From 4b17055f30ca9db49943c5f8db0fb751cf4aa57e Mon Sep 17 00:00:00 2001 From: dzy Date: Wed, 26 Dec 2018 20:29:22 +0800 Subject: [PATCH] running user program. --- kernel/run-qemu-script-custom-llc | 12 +++-- kernel/src/process/mod.rs | 3 +- kernel/src/syscall.rs | 28 +++++----- user/hand/.gitignore | 2 + user/hand/build_img | 14 +++++ user/hand/riscv32.ld | 43 +++++++++++++++ user/hand/riscv64.ld | 43 +++++++++++++++ user/hand/test.c | 87 +++++++++++++++++++++++++++++++ user/riscv64-ucore.json | 35 +++++++++++++ user/ucore-ulib/src/syscall.rs | 4 ++ 10 files changed, 252 insertions(+), 19 deletions(-) create mode 100644 user/hand/.gitignore create mode 100755 user/hand/build_img create mode 100644 user/hand/riscv32.ld create mode 100644 user/hand/riscv64.ld create mode 100644 user/hand/test.c create mode 100644 user/riscv64-ucore.json diff --git a/kernel/run-qemu-script-custom-llc b/kernel/run-qemu-script-custom-llc index ddc017a..36b0760 100755 --- a/kernel/run-qemu-script-custom-llc +++ b/kernel/run-qemu-script-custom-llc @@ -22,15 +22,14 @@ if [[ ${RV32} = 1 ]]; then COMPILER_RT_CFLAGS="-march=rv32ia -mabi=ilp32 -O3" SFSIMG_CFLAGS="-march=rv32ia -mabi=ilp32" RISCV_PK_CONFIGURE_FLAGS="--with-arch=rv32imac --disable-fp-emulation --host=riscv32-unknown-elf" - UCORE_USER_IMAGE="../user/img/ucore-rv32.img" else TARGET_ARCH=riscv64 - export LOG=warn COMPILER_RT_CFLAGS="-march=rv64ia -mabi=lp64 -O3" SFSIMG_CFLAGS="-march=rv64ia -mabi=lp64" RISCV_PK_CONFIGURE_FLAGS="--with-arch=rv64imac --disable-fp-emulation --host=riscv64-unknown-elf" - UCORE_USER_IMAGE="../user/img/ucore-riscv64.img" fi +UCORE_USER_IMAGE="../user/hand/user-${TARGET_ARCH}.img" +# UCORE_USER_IMAGE="../user/build/user-${TARGET_ARCH}.img" LLC=llc RUST_SRC_PATH=$(rustc --print sysroot)/lib/rustlib/src/rust/src CARGO_PATH=~/.cargo @@ -490,7 +489,11 @@ _user_img_start: .incbin "${UCORE_USER_IMAGE}" _user_img_end: EOF -${CC} outdir/sfsimg.S ${SFSIMG_CFLAGS} -c -o outdir/sfsimg.o +if ! ${CC} outdir/sfsimg.S ${SFSIMG_CFLAGS} -c -o outdir/sfsimg.o +then + echo "You should manually create sfs image!" + exit 1 +fi ${AR} r outdir/libsfsimg.a outdir/sfsimg.o fi @@ -540,6 +543,7 @@ gen_full_rlib if [[ ${K210} = 1 ]]; then export LINK_K210='-L native=kendryte' fi +echo "rustc crate-type bin to ${TARGET_JSON}" rustc --edition=2018 --crate-name ucore src/main.rs \ --color always --crate-type bin --emit=link \ -C opt-level=1 \ diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index a9a3f39..9b3a386 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -24,7 +24,8 @@ pub fn init() { extern fn idle(_arg: usize) -> ! { loop { cpu::halt(); } } - for i in 0..4 { + // TODO: make #idle_thr equal to #cpu + for i in 0..1 { manager.add(ContextImpl::new_kernel(idle, i), 0); } crate::shell::run_user_shell(); diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index 4935c29..ad0be20 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -12,7 +12,7 @@ use crate::thread; use crate::util; /// System call dispatcher -pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> i32 { +pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize { let ret = match id { // file 100 => sys_open(args[0] as *const u8, args[1]), @@ -28,9 +28,9 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> i32 { 130 => sys_dup(args[0], args[1]), // process - 001 => sys_exit(args[0] as i32), + 001 => sys_exit(args[0] as isize), 002 => sys_fork(tf), - 003 => sys_wait(args[0], args[1] as *mut i32), + 003 => sys_wait(args[0], args[1] as *mut isize), 004 => sys_exec(args[0] as *const u8, args[1] as usize, args[2] as *const *const u8, tf), // 005 => sys_clone(), 010 => sys_yield(), @@ -62,7 +62,7 @@ fn sys_read(fd: usize, base: *mut u8, len: usize) -> SysResult { info!("read: fd: {}, base: {:?}, len: {:#x}", fd, base, len); let slice = unsafe { slice::from_raw_parts_mut(base, len) }; let len = get_file(fd)?.lock().read(slice)?; - Ok(len as i32) + Ok(len as isize) } fn sys_write(fd: usize, base: *const u8, len: usize) -> SysResult { @@ -70,7 +70,7 @@ fn sys_write(fd: usize, base: *const u8, len: usize) -> SysResult { info!("write: fd: {}, base: {:?}, len: {:#x}", fd, base, len); let slice = unsafe { slice::from_raw_parts(base, len) }; let len = get_file(fd)?.lock().write(slice)?; - Ok(len as i32) + Ok(len as isize) } fn sys_open(path: *const u8, flags: usize) -> SysResult { @@ -89,7 +89,7 @@ fn sys_open(path: *const u8, flags: usize) -> SysResult { }; let file = File::new(inode, flags.contains(VfsFlags::READABLE), flags.contains(VfsFlags::WRITABLE)); process().files.insert(fd, Arc::new(Mutex::new(file))); - Ok(fd as i32) + Ok(fd as isize) } fn sys_close(fd: usize) -> SysResult { @@ -146,12 +146,12 @@ fn sys_fork(tf: &TrapFrame) -> SysResult { let pid = processor().manager().add(context, thread::current().id()); //memory_set_map_swappable(processor.get_context_mut(pid).get_memory_set_mut()); info!("fork: {} -> {}", thread::current().id(), pid); - Ok(pid as i32) + Ok(pid as isize) } /// Wait the process exit. /// Return the PID. Store exit code to `code` if it's not null. -fn sys_wait(pid: usize, code: *mut i32) -> SysResult { +fn sys_wait(pid: usize, code: *mut isize) -> SysResult { // TODO: check ptr loop { use alloc::vec; @@ -166,7 +166,7 @@ fn sys_wait(pid: usize, code: *mut i32) -> SysResult { match processor().manager().get_status(pid) { Some(Status::Exited(exit_code)) => { if !code.is_null() { - unsafe { code.write(exit_code as i32); } + unsafe { code.write(exit_code as isize); } } processor().manager().remove(pid); info!("wait: {} -> {}", thread::current().id(), pid); @@ -240,11 +240,11 @@ fn sys_kill(pid: usize) -> SysResult { /// Get the current process id fn sys_getpid() -> SysResult { - Ok(thread::current().id() as i32) + Ok(thread::current().id() as isize) } /// Exit the current process -fn sys_exit(exit_code: i32) -> SysResult { +fn sys_exit(exit_code: isize) -> SysResult { let pid = thread::current().id(); info!("exit: {}, code: {}", pid, exit_code); processor().manager().exit(pid, exit_code as usize); @@ -263,7 +263,7 @@ fn sys_sleep(time: usize) -> SysResult { } fn sys_get_time() -> SysResult { - unsafe { Ok(crate::trap::TICK as i32) } + unsafe { Ok(crate::trap::TICK as isize) } } fn sys_lab6_set_priority(priority: usize) -> SysResult { @@ -281,9 +281,9 @@ fn get_file(fd: usize) -> Result<&'static Arc>, SysError> { process().files.get(&fd).ok_or(SysError::InvalidFile) } -pub type SysResult = Result; +pub type SysResult = Result; -#[repr(i32)] +#[repr(isize)] #[derive(Debug)] pub enum SysError { VfsError, diff --git a/user/hand/.gitignore b/user/hand/.gitignore new file mode 100644 index 0000000..a979526 --- /dev/null +++ b/user/hand/.gitignore @@ -0,0 +1,2 @@ +output/ +*.img diff --git a/user/hand/build_img b/user/hand/build_img new file mode 100755 index 0000000..7a1574d --- /dev/null +++ b/user/hand/build_img @@ -0,0 +1,14 @@ +#!/bin/bash +ARCH=riscv64 + +CC=${ARCH}-unknown-elf-gcc +CFLAGS="-nostartfiles -nostdlib -nodefaultlibs -o output/a.out -T ${ARCH}.ld -fno-builtin" +if ! [[ -d output ]] +then + mkdir output +fi + +#CFLAGS="${CFLAGS} -DRISCV_QEMU" + +${CC} ${CFLAGS} test.c +mksfs zip output ./user-${ARCH}.img diff --git a/user/hand/riscv32.ld b/user/hand/riscv32.ld new file mode 100644 index 0000000..e4052bc --- /dev/null +++ b/user/hand/riscv32.ld @@ -0,0 +1,43 @@ +OUTPUT_ARCH(riscv) +ENTRY(_start) + +SECTIONS { + /* Load programs at this address: "." means the current address */ + . = 0x00800020; + + .text : { + *(.text .stub .text.* .gnu.linkonce.t.*) + } + + PROVIDE(etext = .); /* Define the 'etext' symbol to this value */ + + .rodata : { + *(.rodata .rodata.* .gnu.linkonce.r.*) + } + + /* Adjust the address for the data segment to the next page */ + . = ALIGN(0x1000); + + /* The data segment */ + .data : { + *(.data) + *(.data.*) + } + + .sdata : { + *(.sdata) + *(.sdata.*) + } + + PROVIDE(edata = .); + + .bss : { + *(.bss) + } + + PROVIDE(end = .); + + /DISCARD/ : { + *(.eh_frame .note.GNU-stack .comment) + } +} diff --git a/user/hand/riscv64.ld b/user/hand/riscv64.ld new file mode 100644 index 0000000..d901f84 --- /dev/null +++ b/user/hand/riscv64.ld @@ -0,0 +1,43 @@ +OUTPUT_ARCH(riscv) +ENTRY(_start) + +SECTIONS { + /* Load programs at this address: "." means the current address */ + . = 0x800020; + + .text : { + *(.text .stub .text.* .gnu.linkonce.t.*) + } + + PROVIDE(etext = .); /* Define the 'etext' symbol to this value */ + + .rodata : { + *(.rodata .rodata.* .gnu.linkonce.r.*) + } + + /* Adjust the address for the data segment to the next page */ + . = ALIGN(0x1000); + + /* The data segment */ + .data : { + *(.data) + *(.data.*) + } + + .sdata : { + *(.sdata) + *(.sdata.*) + } + + PROVIDE(edata = .); + + .bss : { + *(.bss) + } + + PROVIDE(end = .); + + /DISCARD/ : { + *(.eh_frame .note.GNU-stack .comment) + } +} diff --git a/user/hand/test.c b/user/hand/test.c new file mode 100644 index 0000000..98db558 --- /dev/null +++ b/user/hand/test.c @@ -0,0 +1,87 @@ +#ifdef RISCV_QEMU +# define SYS_write 64 +# define SYS_exit 93 +long syscall(long a0, long a1, long a2, long a3, long a4, long a5, long a6) { + register long _0 __asm__("a7") = a0; + register long _1 __asm__("a0") = a1; + register long _2 __asm__("a1") = a2; + register long _3 __asm__("a2") = a3; + register long _4 __asm__("a3") = a4; + register long _5 __asm__("a4") = a5; + register long _6 __asm__("a5") = a6; + __asm__ __volatile__("ecall":::); + return _1; +} + +#else +# define SYS_write 103 +# define SYS_exit 1 +# define SYS_fork 2 +# define SYS_putc 30 +# define SYS_getpid 18 +# define SYS_sleep 11 + +long syscall(long a0, long a1, long a2, long a3, long a4, long a5, long a6) { + register long _0 __asm__("x10") = a0; + register long _1 __asm__("x11") = a1; + register long _2 __asm__("x12") = a2; + register long _3 __asm__("x13") = a3; + register long _4 __asm__("x14") = a4; + register long _5 __asm__("x15") = a5; + register long _6 __asm__("x16") = a6; + __asm__ __volatile__("ecall":::); + return _0; +} +#endif + +const char* welcome_msg = "hello world!\n"; +const char* hexch = "0123456789ABCDEF"; + +void putc(char c) { + syscall(SYS_putc, c, 0, 0, 0, 0, 0); +} + +void putstr(const char* s) { + for (; *s; s++) + syscall(SYS_putc, *s, 0, 0, 0, 0, 0); +} + +void putint_hex(long v) { + char ch[18]; + ch[16] = 'H'; + ch[17] = 0; + for (int i = 15; i >= 0; i--) { + ch[i] = hexch[v & 15]; + v >>= 4; + } + putstr(ch); +} + +void _start() { + putstr(welcome_msg); + putc('\n'); + + putstr("my pid is "); + long v = syscall(SYS_getpid, 0, 0, 0, 0, 0, 0); + putint_hex(v); + putc('\n'); + + long v1 = syscall(SYS_fork, 0, 0, 0, 0, 0, 0); + putstr("fork returned: "); + putint_hex(v1); + putc('\n'); + if (v1 != 0) { + putstr("parent sleeping"); + putc('\n'); + syscall(SYS_sleep, 200, 0, 0, 0, 0, 0); + } + putstr("my pid is "); + v = syscall(SYS_getpid, 0, 0, 0, 0, 0, 0); + putint_hex(v); + putc('\n'); + + putint_hex(v); + putstr(" is exiting"); + putc('\n'); + syscall(SYS_exit, 0, 0, 0, 0, 0, 0); +} diff --git a/user/riscv64-ucore.json b/user/riscv64-ucore.json new file mode 100644 index 0000000..4742c08 --- /dev/null +++ b/user/riscv64-ucore.json @@ -0,0 +1,35 @@ +{ + "llvm-target": "riscv64", + "data-layout": "e-m:e-p:64:64-i64:64-n64-S128", + "target-endian": "little", + "target-pointer-width": "64", + "target-c-int-width": "32", + "os": "none", + "arch": "riscv64", + "cpu": "generic-rv64", + "features": "", + "max-atomic-width": "32", + "linker": "rust-lld", + "linker-flavor": "ld.lld", + "pre-link-args": { + "ld.lld": [ + "-Tsrc/arch/riscv32/boot/linker64.ld" + ] + }, + "executables": true, + "panic-strategy": "abort", + "relocation-model": "static", + "abi-blacklist": [ + "cdecl", + "stdcall", + "fastcall", + "vectorcall", + "thiscall", + "aapcs", + "win64", + "sysv64", + "ptx-kernel", + "msp430-interrupt", + "x86-interrupt" + ] +} diff --git a/user/ucore-ulib/src/syscall.rs b/user/ucore-ulib/src/syscall.rs index 1a75785..2c86438 100644 --- a/user/ucore-ulib/src/syscall.rs +++ b/user/ucore-ulib/src/syscall.rs @@ -45,7 +45,11 @@ impl fmt::Write for SysPutc { #[inline(always)] fn sys_call(id: usize, arg0: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) -> i32 { + #[cfg(target_arch = "riscv64")] + let ret: i32 = 0; + #[cfg(target_arch = "riscv32")] let ret: i32; + unsafe { #[cfg(target_arch = "riscv32")] asm!("ecall"