1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-26 01:43:29 +04:00
This commit is contained in:
NagiNikaido 2019-04-21 14:32:24 +08:00
parent ae710ca08d
commit 1bfb979d96
52 changed files with 1090 additions and 4731 deletions

3
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "riscv-pk"]
path = riscv-pk
url = https://github.com/rcore-os/riscv-pk.git
[submodule "user"]
path = user
url = https://github.com/rcore-os/rcore-user.git

View File

@ -10,8 +10,6 @@ Supported architectures: x86_64, RISCV32/64, AArch64, MIPS32
Tested boards: QEMU, HiFive Unleashed, x86_64 PC (i5/i7), Raspberry Pi 3B+
[Dev docs](https://rucore.gitbook.io/rust-os-docs/) (in Chinese)
![demo](./docs/2_OSLab/os2atc/demo.png)
## Building
@ -47,18 +45,28 @@ $ make run arch={riscv32,riscv64,x86_64,aarch64,mipsel} mode=release
$ make run arch=x86_64 mode=release pci_passthru=0000:00:00.1 # for ixgbe real nic, find its pci (bus, dev, func) first
```
## Maintainers
| Module | Maintainer |
|--------|-----------------------|
| x86_64 | @wangrunji0408 |
| RISCV | @jiegec |
| ARM (Raspi3) | @equation314 |
| MIPS | @HarryChen @miskcoo |
| Memory, Process, File System | @wangrunji0408 |
| Network with drivers | @jiegec |
| GUI | @equation314 |
## History
This is a project of THU courses:
* Operating System (2018 Spring)
* Comprehensive Experiment of Computer System (2018 Summer)
* Operating System Train (2018 Autumn)
* Operating System (2019 Spring)
* [Operating System (2018 Spring) ](http://os.cs.tsinghua.edu.cn/oscourse/OS2018spring/projects/g11)
* [Comprehensive Experiment of Computer System (2018 Summer)](http://os.cs.tsinghua.edu.cn/oscourse/csproject2018/group05)
* [Operating System Train (2018 Autumn)](http://os.cs.tsinghua.edu.cn/oscourse/OsTrain2018)
* [Operating System (2019 Spring)](http://os.cs.tsinghua.edu.cn/oscourse/OS2019spring/projects)
Project wiki (internal access only): [OS](http://os.cs.tsinghua.edu.cn/oscourse/OS2018spring/projects/g11), [CECS](http://os.cs.tsinghua.edu.cn/oscourse/csproject2018/group05), [OST](http://os.cs.tsinghua.edu.cn/oscourse/OsTrain2018)
Reports (in Chinese): [docs](./docs)
[Reports](./docs) and [Dev docs](https://rucore.gitbook.io/rust-os-docs/) (in Chinese)
It's based on [BlogOS](https://github.com/phil-opp/blog_os) , a demo project in the excellent tutorial [Writing an OS in Rust (First Edition)](https://os.phil-opp.com/first-edition/).

View File

@ -56,7 +56,9 @@ impl MemoryArea {
}
/// Check the array is within the readable memory
fn check_read_array<S>(&self, ptr: *const S, count: usize) -> bool {
ptr as usize >= self.start_addr && unsafe { ptr.add(count) as usize } <= self.end_addr
// page align
ptr as usize >= Page::of_addr(self.start_addr).start_address()
&& unsafe { ptr.add(count) as usize } < Page::of_addr(self.end_addr + PAGE_SIZE - 1).start_address()
}
/// Check the array is within the writable memory
fn check_write_array<S>(&self, ptr: *mut S, count: usize) -> bool {

33
kernel/Cargo.lock generated
View File

@ -85,7 +85,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitvec"
version = "0.11.0"
source = "git+https://github.com/myrrlyn/bitvec.git#f8bd136426fde431f321e647e3207b28623fc569"
source = "git+https://github.com/myrrlyn/bitvec.git#ed2aec38bfb5b1116e3585b1574c50655b9c85ec"
[[package]]
name = "bootloader"
@ -393,21 +393,21 @@ dependencies = [
"riscv 0.5.0 (git+https://github.com/rcore-os/riscv)",
"smoltcp 0.5.0 (git+https://github.com/rcore-os/smoltcp)",
"spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uart_16550 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"x86_64 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"x86_64 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rcore-fs"
version = "0.1.0"
source = "git+https://github.com/rcore-os/rcore-fs#d7a2006cc316c98b7050aec63a2770dd690a4a80"
source = "git+https://github.com/rcore-os/rcore-fs#64d399fe664927f14853c22943a4bdeb34095f99"
[[package]]
name = "rcore-fs-sfs"
version = "0.1.0"
source = "git+https://github.com/rcore-os/rcore-fs#d7a2006cc316c98b7050aec63a2770dd690a4a80"
source = "git+https://github.com/rcore-os/rcore-fs#64d399fe664927f14853c22943a4bdeb34095f99"
dependencies = [
"bitvec 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -555,11 +555,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "uart_16550"
version = "0.1.0"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"x86_64 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"x86_64 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -615,18 +615,6 @@ dependencies = [
"raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "x86_64"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "x86_64"
version = "0.3.6"
@ -642,7 +630,7 @@ dependencies = [
[[package]]
name = "x86_64"
version = "0.5.3"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"array-init 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -734,7 +722,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
"checksum tock-registers 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a385d94f3f62e60445a0adb9ff8d9621faa272234530d4c0f848ec98f88e316"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "269f953d8de3226f7c065c589c7b4a3e83d10a419c7c3b5e2e0f197e6acc966e"
"checksum uart_16550 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b9392f60931fe3bf8f24e0a15ee4f51528770f1d64c48768ab66571334d95b0"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f70329e2cbe45d6c97a5112daad40c34cd9a4e18edb5a2a18fefeb584d8d25e5"
@ -744,8 +732,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum x86 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "841e1ca5a87068718a2a26f2473c6f93cf3b8119f9778fa0ae4b39b664d9e66a"
"checksum x86_64 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd647af1614659e1febec1d681231aea4ebda4818bf55a578aff02f3e4db4b4"
"checksum x86_64 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f9258d7e2dd25008d69e8c9e9ee37865887a5e1e3d06a62f1cb3f6c209e6f177"
"checksum x86_64 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7e92e985f4052118fd69f2b366c67e91288c0f01f4ae52610dce236425dfa0"
"checksum x86_64 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0a8201f52d2c7b373c7243dcdfb27c0dd5012f221ef6a126f507ee82005204"
"checksum xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22678df5df766e8d1e5d609da69f0c3132d794edf6ab5e75e7abcd2270d4cf58"
"checksum zero 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f1bc8a6b2005884962297587045002d8cfb8dcec9db332f4ca216ddc5de82c5"

View File

@ -19,6 +19,7 @@ authors = [
]
[features]
default = ["sv39"]
# Page table sv39 or sv48 (for riscv64)
sv39 = []
board_u540 = ["sv39", "link_user"]
@ -31,6 +32,8 @@ board_malta = ["link_user"]
board_mipssim = ["link_user"]
# for thinpad
board_thinpad = ["link_user"]
# for x86 PC
board_pc = ["link_user"]
# Hard link user program
link_user = []
# Run cmdline instead of user shell, useful for automatic testing
@ -68,7 +71,7 @@ bootloader = { git = "https://github.com/rcore-os/bootloader" }
apic = { git = "https://github.com/rcore-os/apic-rs" }
x86_64 = "0.5"
raw-cpuid = "6.0"
uart_16550 = "0.1"
uart_16550 = "0.2"
pc-keyboard = "0.5"
[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies]

View File

@ -23,6 +23,7 @@
# smp = 1 | 2 | ... SMP core number
# graphic = on | off Enable/disable qemu graphical output
# board = none Running on QEMU
# | pc Only available on x86_64, run on real pc
# | u540 Only available on riscv64, run on HiFive U540, use Sv39
# | raspi3 Only available on aarch64, run on Raspberry Pi 3 Model B/B+
# pci_passthru = 0000:00:00.1 Only available on x86_64, passthrough the specified PCI device
@ -32,8 +33,8 @@
arch ?= riscv64
board ?= none
mode ?= debug
LOG ?= debug
mode ?= release
LOG ?=
graphic ?= off
smp ?= 4
pci_passthru ?=
@ -57,8 +58,14 @@ ifeq ($(arch), $(filter $(arch), aarch64 mipsel))
#link user img, so use original image
export SFSIMG = $(user_dir)/build/$(arch).img
else
# board is pc or qemu?
ifeq ($(board), pc)
#link user img, so use original image
export SFSIMG = $(user_dir)/build/$(arch).img
else
export SFSIMG = $(user_dir)/build/$(arch).qcow2
endif
endif # pc or qemu
endif # aarch64 mipsel
ifeq ($(arch), aarch64)
board := raspi3
@ -89,12 +96,15 @@ qemu_net_opts :=
ifeq ($(arch), x86_64)
qemu_opts += \
-drive format=raw,file=$(bootimage) \
-drive format=qcow2,file=$(SFSIMG),media=disk,cache=writeback,id=sfsimg,if=none \
-device ahci,id=ahci0 \
-device ide-drive,drive=sfsimg,bus=ahci0.0 \
-serial mon:stdio \
-m 4G \
-device isa-debug-exit
ifeq ($(board), none)
qemu_opts += \
-drive format=qcow2,file=$(SFSIMG),media=disk,cache=writeback,id=sfsimg,if=none \
-device ahci,id=ahci0 \
-device ide-drive,drive=sfsimg,bus=ahci0.0
endif
ifeq ($(pci_passthru), )
qemu_net_opts += \
-netdev type=tap,id=net0,script=no,downscript=no \
@ -114,7 +124,8 @@ endif
else ifeq ($(arch), riscv32)
qemu_opts += \
-machine virt \
-kernel $(kernel_img) \
-kernel ../tools/opensbi/virt_rv32.elf \
-device loader,addr=0x80400000,file=$(kernel_img) \
-drive file=$(SFSIMG),format=qcow2,id=sfs \
-device virtio-blk-device,drive=sfs
qemu_net_opts += \
@ -122,11 +133,19 @@ qemu_net_opts += \
-device virtio-net-device,netdev=net0
else ifeq ($(arch), riscv64)
ifeq ($(board), u540)
qemu_opts += \
-machine virt \
-kernel $(kernel_img) \
-kernel ../tools/opensbi/fu540.elf \
-device loader,addr=0x80200000,file=$(kernel_img)
else
qemu_opts += \
-machine virt \
-kernel ../tools/opensbi/virt_rv64.elf \
-device loader,addr=0x80200000,file=$(kernel_img) \
-drive file=$(SFSIMG),format=qcow2,id=sfs \
-device virtio-blk-device,drive=sfs
endif
qemu_net_opts += \
-netdev type=tap,id=net0,script=no,downscript=no \
-device virtio-net-device,netdev=net0
@ -190,14 +209,13 @@ endif
ifneq ($(board), none)
features += board_$(board)
endif
build_args := --target targets/$(target).json --features "$(features)"
ifeq ($(mode), release)
build_args += --release
endif
### prefix ###
ifeq ($(arch), x86_64)
ifeq ($(uname), Darwin)
@ -288,28 +306,8 @@ ifeq ($(need_bootloader), true)
endif
$(kernel_img): kernel $(bootloader)
ifeq ($(arch), riscv32)
@mkdir -p target/$(target)/bbl && \
cd target/$(target)/bbl && \
$(bbl_path)/configure \
$(riscv_pk_args) \
--with-arch=rv32imac \
--disable-fp-emulation \
--host=riscv64-unknown-elf \
--with-payload=$(abspath $(kernel)) && \
make -j && \
cp bbl $(abspath $@)
else ifeq ($(arch), riscv64)
@mkdir -p target/$(target)/bbl && \
cd target/$(target)/bbl && \
$(bbl_path)/configure \
$(riscv_pk_args) \
--with-arch=rv64imac \
--disable-fp-emulation \
--host=riscv64-unknown-elf \
--with-payload=$(abspath $(kernel)) && \
make -j && \
cp bbl $(abspath $@)
ifeq ($(arch), $(filter $(arch), riscv32 riscv64))
@$(objcopy) $(kernel) --strip-all -O binary $@
else ifeq ($(arch), aarch64)
ifneq ($(u_boot), )
@cp $(u_boot) $@
@ -326,13 +324,7 @@ kernel: $(dtb)
ifeq ($(arch), x86_64)
@bootimage build $(build_args)
@mv target/x86_64/bootimage.bin $(bootimage)
else ifeq ($(arch), riscv32)
@-patch -p0 -N -b \
$(shell rustc --print sysroot)/lib/rustlib/src/rust/src/libcore/sync/atomic.rs \
src/arch/riscv32/atomic.patch
@cargo xbuild $(build_args)
else ifeq ($(arch), riscv64)
@cp src/arch/riscv32/board/u540/linker.ld src/arch/riscv32/boot/linker64.ld
else ifeq ($(arch), $(filter $(arch), riscv32 riscv64))
@-patch -p0 -N -b \
$(shell rustc --print sysroot)/lib/rustlib/src/rust/src/libcore/sync/atomic.rs \
src/arch/riscv32/atomic.patch
@ -374,7 +366,8 @@ endif
ifeq ($(board), u540)
.PHONY:
install: $(kernel_img)
@$(objcopy) -S -O binary --change-addresses -0x80000000 $< $(build_path)/bin
@$(objcopy) -S -O binary ../tools/opensbi/fu540.elf $(build_path)/bin
@dd if=$< of=$(build_path)/bin bs=131072 seek=16
@../tools/u540/mkimg.sh $(build_path)/bin $(build_path)/sd.img
endif

View File

@ -1,49 +0,0 @@
/* Copy from bbl-ucore : https://ring00.github.io/bbl-ucore */
/* Simple linker script for the ucore kernel.
See the GNU ld 'info' manual ("info ld") to learn the syntax. */
OUTPUT_ARCH(riscv)
ENTRY(_start)
BASE_ADDRESS = 0xffffffffc0020000;
SECTIONS
{
/* Load the kernel at this address: "." means the current address */
. = BASE_ADDRESS;
start = .;
.text : {
stext = .;
*(.text.entry)
*(.text .text.*)
. = ALIGN(4K);
etext = .;
}
.rodata : {
srodata = .;
*(.rodata .rodata.*)
. = ALIGN(4K);
erodata = .;
}
.data : {
sdata = .;
*(.data .data.*)
edata = .;
}
.stack : {
*(.bss.stack)
}
.bss : {
sbss = .;
*(.bss .bss.*)
ebss = .;
}
PROVIDE(end = .);
}

View File

@ -4,7 +4,7 @@ use super::consts::KERNEL_OFFSET;
pub unsafe fn init_external_interrupt() {
const HART1_S_MODE_INTERRUPT_ENABLES: *mut u64 = (KERNEL_OFFSET + 0x0C00_2100) as *mut u64;
const SERIAL: u64 = 4;
HART1_S_MODE_INTERRUPT_ENABLES.write(1 << SERIAL);
HART1_S_MODE_INTERRUPT_ENABLES.write_volatile(1 << SERIAL);
}
/// Claim and complete external interrupt by reading and writing to
@ -13,7 +13,14 @@ pub unsafe fn handle_external_interrupt() {
const HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE: *mut u32 =
(KERNEL_OFFSET + 0x0C20_2004) as *mut u32;
// claim
let source = HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE.read();
let source = HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE.read_volatile();
// complete
HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE.write(source);
HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE.write_volatile(source);
}
pub unsafe fn enable_serial_interrupt() {
const SERIAL_BASE: *mut u8 = (KERNEL_OFFSET + 0x10010000) as *mut u8;
const UART_REG_IE: usize = 4;
const UART_RXWM: u8 = 0x2;
SERIAL_BASE.add(UART_REG_IE).write_volatile(UART_RXWM);
}

View File

@ -0,0 +1,18 @@
use super::consts::KERNEL_OFFSET;
/// Mask all external interrupt except serial.
pub unsafe fn init_external_interrupt() {
// By default:
// riscv-pk (bbl) enables all S-Mode IRQs (ref: machine/minit.c)
// OpenSBI v0.3 disables all IRQs (ref: platform/common/irqchip/plic.c)
const HART0_S_MODE_INTERRUPT_ENABLES: *mut u32 = (KERNEL_OFFSET + 0x0C00_2080) as *mut u32;
const SERIAL: u32 = 0xa;
HART0_S_MODE_INTERRUPT_ENABLES.write_volatile(1 << SERIAL);
}
pub unsafe fn enable_serial_interrupt() {
const UART16550: *mut u8 = (KERNEL_OFFSET + 0x10000000) as *mut u8;
UART16550.add(4).write_volatile(0x0B);
UART16550.add(1).write_volatile(0x01);
}

View File

@ -1,19 +0,0 @@
.section .text.entry
.globl _start
_start:
add t0, a0, 1
slli t0, t0, 16
lui sp, %hi(bootstack)
addi sp, sp, %lo(bootstack)
add sp, sp, t0
call rust_main
.section .bss.stack
.align 12 #PGSHIFT
.global bootstack
bootstack:
.space 4096 * 16 * 8
.global bootstacktop
bootstacktop:

View File

@ -0,0 +1,55 @@
.section .text.entry
.globl _start
_start:
# a0 == hartid
# pc == 0x80200000
# sp == 0x800xxxxx
# 1. set sp
# sp = bootstack + (hartid + 1) * 0x10000
add t0, a0, 1
slli t0, t0, 16
lui sp, %hi(bootstack)
add sp, sp, t0
# 2. enable paging
# satp = (1 << 31) | PPN(boot_page_table_sv32)
lui t0, %hi(boot_page_table_sv32)
li t1, 0xc0000000 - 0x80000000
sub t0, t0, t1
srli t0, t0, 12
li t1, 1 << 31
or t0, t0, t1
csrw satp, t0
sfence.vma
# 3. jump to rust_main (absolute address)
lui t0, %hi(rust_main)
addi t0, t0, %lo(rust_main)
jr t0
.section .bss.stack
.align 12 # page align
.global bootstack
bootstack:
.space 4096 * 16 * 8
.global bootstacktop
bootstacktop:
.section .data
.align 12 # page align
boot_page_table_sv32:
# NOTE: assume kernel image < 16M
# 0x80000000 -> 0x80000000 (4M * 4)
# 0xc0000000 -> 0x80000000 (4M * 4)
.zero 4 * 512
.word (0x80000 << 10) | 0xcf # VRWXAD
.word (0x80400 << 10) | 0xcf # VRWXAD
.word (0x80800 << 10) | 0xcf # VRWXAD
.word (0x80c00 << 10) | 0xcf # VRWXAD
.zero 4 * 252
.word (0x80000 << 10) | 0xcf # VRWXAD
.word (0x80400 << 10) | 0xcf # VRWXAD
.word (0x80800 << 10) | 0xcf # VRWXAD
.word (0x80c00 << 10) | 0xcf # VRWXAD
.zero 4 * 252

View File

@ -0,0 +1,48 @@
.section .text.entry
.globl _start
_start:
# a0 == hartid
# pc == 0x80200000
# sp == 0x800xxxxx
# 1. set sp
# sp = bootstack + (hartid + 1) * 0x10000
add t0, a0, 1
slli t0, t0, 16
lui sp, %hi(bootstack)
add sp, sp, t0
# 2. enable paging
# satp = (8 << 60) | PPN(boot_page_table_sv39)
lui t0, %hi(boot_page_table_sv39)
li t1, 0xffffffffc0000000 - 0x80000000
sub t0, t0, t1
srli t0, t0, 12
li t1, 8 << 60
or t0, t0, t1
csrw satp, t0
sfence.vma
# 3. jump to rust_main (absolute address)
lui t0, %hi(rust_main)
addi t0, t0, %lo(rust_main)
jr t0
.section .bss.stack
.align 12 # page align
.global bootstack
bootstack:
.space 4096 * 16 * 8
.global bootstacktop
bootstacktop:
.section .data
.align 12 # page align
boot_page_table_sv39:
# 0x00000000_80000000 -> 0x80000000 (1G)
# 0xffffffff_c0000000 -> 0x80000000 (1G)
.quad 0
.quad 0
.quad (0x80000 << 10) | 0xcf # VRWXAD
.zero 8 * 508
.quad (0x80000 << 10) | 0xcf # VRWXAD

View File

@ -6,7 +6,7 @@
OUTPUT_ARCH(riscv)
ENTRY(_start)
BASE_ADDRESS = 0xC0020000;
BASE_ADDRESS = 0xC0400000;
SECTIONS
{

View File

@ -6,7 +6,7 @@
OUTPUT_ARCH(riscv)
ENTRY(_start)
BASE_ADDRESS = 0xffffffffc0020000;
BASE_ADDRESS = 0xffffffffc0200000;
SECTIONS
{

View File

@ -22,17 +22,11 @@ pub const KERNEL_P2_INDEX: usize = (KERNEL_OFFSET >> 12 >> 10) & 0x3ff;
#[cfg(target_arch = "riscv64")]
pub const KERNEL_P4_INDEX: usize = (KERNEL_OFFSET >> 12 >> 9 >> 9 >> 9) & 0o777;
pub const KERNEL_HEAP_SIZE: usize = 0x00a0_0000;
pub const KERNEL_HEAP_SIZE: usize = 0x0080_0000;
#[cfg(target_arch = "riscv32")]
pub const MEMORY_OFFSET: usize = 0x8000_0000;
#[cfg(target_arch = "riscv64")]
pub const MEMORY_OFFSET: usize = 0x8000_0000;
#[cfg(target_arch = "riscv32")]
pub const MEMORY_END: usize = 0x8100_0000;
#[cfg(target_arch = "riscv64")]
pub const MEMORY_END: usize = 0x8100_0000;
// TODO: get memory end from device tree
pub const MEMORY_END: usize = 0x8800_0000;
// FIXME: rv64 `sh` and `ls` will crash if stack top > 0x80000000 ???
pub const USER_STACK_OFFSET: usize = 0x80000000 - USER_STACK_SIZE;

View File

@ -1,8 +1,3 @@
use crate::consts::MAX_CPU_NUM;
use core::ptr::{read_volatile, write_volatile};
static mut STARTED: [bool; MAX_CPU_NUM] = [false; MAX_CPU_NUM];
pub unsafe fn set_cpu_id(cpu_id: usize) {
asm!("mv gp, $0" : : "r"(cpu_id));
}
@ -19,18 +14,6 @@ pub fn send_ipi(cpu_id: usize) {
super::sbi::send_ipi(1 << cpu_id);
}
pub unsafe fn has_started(cpu_id: usize) -> bool {
read_volatile(&STARTED[cpu_id])
}
pub unsafe fn start_others(hart_mask: usize) {
for cpu_id in 0..MAX_CPU_NUM {
if (hart_mask >> cpu_id) & 1 != 0 {
write_volatile(&mut STARTED[cpu_id], true);
}
}
}
pub fn halt() {
unsafe { riscv::asm::wfi() }
}

View File

@ -47,6 +47,3 @@ pub fn getchar_option() -> Option<char> {
pub fn putfmt(fmt: Arguments) {
SerialPort.write_fmt(fmt).unwrap();
}
const TXDATA: *mut u32 = 0x38000000 as *mut u32;
const RXDATA: *mut u32 = 0x38000004 as *mut u32;

View File

@ -8,13 +8,17 @@ use riscv::{addr::*, register::sstatus};
/// Initialize the memory management module
pub fn init(dtb: usize) {
// allow user memory access
unsafe {
sstatus::set_sum();
} // Allow user memory access
// initialize heap and Frame allocator
}
// initialize heap and Frame allocator
init_frame_allocator();
init_heap();
// remap the kernel use 4K page
unsafe {
super::paging::setup_recursive_mapping();
}
remap_the_kernel(dtb);
}
@ -93,7 +97,7 @@ fn remap_the_kernel(dtb: usize) {
Linear::new(offset),
"dts",
);
// map PLIC for HiFiveU
// map PLIC for HiFiveU & VirtIO
let offset = -(KERNEL_OFFSET as isize);
ms.push(
KERNEL_OFFSET + 0x0C00_2000,
@ -109,6 +113,22 @@ fn remap_the_kernel(dtb: usize) {
Linear::new(offset),
"plic1",
);
// map UART for HiFiveU
ms.push(
KERNEL_OFFSET + 0x10010000,
KERNEL_OFFSET + 0x10010000 + PAGE_SIZE,
MemoryAttr::default(),
Linear::new(offset),
"uart",
);
// map UART for VirtIO
ms.push(
KERNEL_OFFSET + 0x10000000,
KERNEL_OFFSET + 0x10000000 + PAGE_SIZE,
MemoryAttr::default(),
Linear::new(offset),
"uart16550",
);
unsafe {
ms.activate();
}

View File

@ -1,6 +1,10 @@
#[cfg(feature = "board_u540")]
#[path = "board/u540/mod.rs"]
mod board;
#[cfg(not(feature = "board_u540"))]
#[path = "board/virt/mod.rs"]
mod board;
pub mod compiler_rt;
pub mod consts;
pub mod cpu;
@ -13,19 +17,24 @@ mod sbi;
pub mod syscall;
pub mod timer;
use self::consts::{KERNEL_OFFSET, MEMORY_OFFSET};
use core::sync::atomic::{AtomicBool, Ordering};
use log::*;
#[no_mangle]
pub extern "C" fn rust_main(hartid: usize, dtb: usize, hart_mask: usize) -> ! {
// An initial recursive page table has been set by BBL (shared by all cores)
pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! {
let device_tree_vaddr = device_tree_paddr - MEMORY_OFFSET + KERNEL_OFFSET;
unsafe {
cpu::set_cpu_id(hartid);
}
if hartid != BOOT_HART_ID {
while unsafe { !cpu::has_started(hartid) } {}
println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb);
while !AP_CAN_INIT.load(Ordering::Relaxed) {}
println!(
"Hello RISCV! in hart {}, device tree @ {:#x}",
hartid, device_tree_vaddr
);
others_main();
//other_main -> !
}
@ -34,24 +43,25 @@ pub extern "C" fn rust_main(hartid: usize, dtb: usize, hart_mask: usize) -> ! {
memory::clear_bss();
}
println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb);
println!(
"Hello RISCV! in hart {}, device tree @ {:#x}",
hartid, device_tree_vaddr
);
crate::logging::init();
interrupt::init();
memory::init(dtb);
memory::init(device_tree_vaddr);
timer::init();
// FIXME: init driver on u540
#[cfg(not(feature = "board_u540"))]
crate::drivers::init(dtb);
#[cfg(feature = "board_u540")]
crate::drivers::init(device_tree_vaddr);
unsafe {
board::enable_serial_interrupt();
board::init_external_interrupt();
}
crate::process::init();
unsafe {
cpu::start_others(hart_mask);
}
AP_CAN_INIT.store(true, Ordering::Relaxed);
crate::kmain();
}
@ -62,6 +72,8 @@ fn others_main() -> ! {
crate::kmain();
}
static AP_CAN_INIT: AtomicBool = AtomicBool::new(false);
#[cfg(not(feature = "board_u540"))]
const BOOT_HART_ID: usize = 0;
#[cfg(feature = "board_u540")]
@ -94,6 +106,8 @@ global_asm!(
.endm
"
);
global_asm!(include_str!("boot/entry.asm"));
#[cfg(target_arch = "riscv32")]
global_asm!(include_str!("boot/entry32.asm"));
#[cfg(target_arch = "riscv64")]
global_asm!(include_str!("boot/entry64.asm"));
global_asm!(include_str!("boot/trap.asm"));

View File

@ -198,7 +198,7 @@ impl InactivePageTable for InactivePageTable0 {
fn start();
fn end();
}
let mut entrys: [PageTableEntry; 16] = unsafe { core::mem::uninitialized() };
let mut entrys: [PageTableEntry; 256] = unsafe { core::mem::uninitialized() };
let entry_start = start as usize >> 22;
let entry_end = (end as usize >> 22) + 1;
let entry_count = entry_end - entry_start;
@ -299,3 +299,13 @@ impl FrameDeallocator for FrameAllocatorForRiscv {
dealloc_frame(frame.start_address().as_usize());
}
}
pub unsafe fn setup_recursive_mapping() {
let frame = satp::read().frame();
let root_page_table = unsafe { &mut *(frame.start_address().as_usize() as *mut RvPageTable) };
root_page_table.set_recursive(RECURSIVE_INDEX, frame);
unsafe {
sfence_vma_all();
}
info!("setup recursive mapping end");
}

View File

@ -1,4 +1,5 @@
//! Port from sbi.h
#![allow(dead_code)]
#[inline(always)]
fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {

View File

@ -55,7 +55,7 @@ pub const USER_GRANT_PML4: usize = (USER_GRANT_OFFSET & PML4_MASK) / PML4_SIZE;
pub const USER_STACK_OFFSET: usize = USER_GRANT_OFFSET + PML4_SIZE;
pub const USER_STACK_PML4: usize = (USER_STACK_OFFSET & PML4_MASK) / PML4_SIZE;
/// Size of user stack
pub const USER_STACK_SIZE: usize = 1024 * 1024; // 1 MB
pub const USER_STACK_SIZE: usize = 8 * 1024 * 1024; // 8 MB, the default config of Linux
/// Offset to user sigstack
pub const USER_SIGSTACK_OFFSET: usize = USER_STACK_OFFSET + PML4_SIZE;

View File

@ -1,5 +1,3 @@
// Copy from Redox
use once::*;
use spin::Mutex;
use uart_16550::SerialPort;
@ -7,8 +5,8 @@ use x86_64::instructions::port::Port;
use crate::arch::interrupt::{consts, enable_irq};
pub static COM1: Mutex<SerialPort> = Mutex::new(SerialPort::new(0x3F8));
pub static COM2: Mutex<SerialPort> = Mutex::new(SerialPort::new(0x2F8));
pub static COM1: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3F8) });
pub static COM2: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x2F8) });
pub fn init() {
assert_has_not_been_called!("serial::init must be called only once");
@ -27,7 +25,6 @@ impl SerialRead for SerialPort {
fn receive(&mut self) -> u8 {
unsafe {
let ports = self as *mut _ as *mut [Port<u8>; 6];
let _line_sts = &(*ports)[5];
let data = &(*ports)[0];
data.read()
}

View File

@ -206,11 +206,11 @@ impl AsciiConsole for VgaWriter {
CSI::CursorMove(dx, dy) => {
let x = (self.pos.row.0 as i8 + dx).max(0) as u8;
let y = (self.pos.col.0 as i8 + dy).max(0) as u8;
self.set_pos(Position::new(Row(x), Col(y)));
self.set_pos(Position::new(Row(x), Col(y))).unwrap();
}
CSI::CursorMoveLine(dx) => {
let x = (self.pos.row.0 as i8 + dx).max(0) as u8;
self.set_pos(Position::new(Row(x), Col(0)));
self.set_pos(Position::new(Row(x), Col(0))).unwrap();
}
_ => {}
}

View File

@ -17,7 +17,19 @@ pub fn init() {
static mut CPUS: [Option<Cpu>; MAX_CPU_NUM] = [
// TODO: More elegant ?
None, None, None, None, None, None, None, None,
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
None,
// None, None, None, None, None, None, None, None,
// None, None, None, None, None, None, None, None,
// None, None, None, None, None, None, None, None,
// None, None, None, None, None, None, None, None,
// None, None, None, None, None, None, None, None,
// None, None, None, None, None, None, None, None,
// None, None, None, None, None, None, None, None,
// None, None, None, None, None, None, None, None,
];
pub struct Cpu {

View File

@ -2,7 +2,7 @@
pub use crate::arch::consts::*;
pub const MAX_CPU_NUM: usize = 8;
pub const MAX_CPU_NUM: usize = 64;
pub const MAX_PROCESS_NUM: usize = 128;
pub const USEC_PER_TICK: usize = 10000;

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -113,7 +113,7 @@ impl FileHandle {
self.inode.poll()
}
pub fn io_control(&self, cmd: u32, arg: u32) -> Result<()> {
pub fn io_control(&self, cmd: u32, arg: usize) -> Result<()> {
self.inode.io_control(cmd, arg)
}
}

View File

@ -31,7 +31,7 @@ impl FileLike {
}
pub fn ioctl(&mut self, request: usize, arg1: usize, arg2: usize, arg3: usize) -> SysResult {
match self {
FileLike::File(file) => file.io_control(request as u32, arg1 as u32)?,
FileLike::File(file) => file.io_control(request as u32, arg1)?,
FileLike::Socket(socket) => {
socket.ioctl(request, arg1, arg2, arg3)?;
}

View File

@ -69,7 +69,7 @@ macro_rules! impl_inode {
fn move_(&self, _old_name: &str, _target: &Arc<INode>, _new_name: &str) -> Result<()> { Err(FsError::NotDir) }
fn find(&self, _name: &str) -> Result<Arc<INode>> { Err(FsError::NotDir) }
fn get_entry(&self, _id: usize) -> Result<String> { Err(FsError::NotDir) }
fn io_control(&self, _cmd: u32, _data: u32) -> Result<()> { Err(FsError::NotSupported) }
fn io_control(&self, _cmd: u32, _data: usize) -> Result<()> { Err(FsError::NotSupported) }
fn fs(&self) -> Arc<FileSystem> { unimplemented!() }
fn as_any_ref(&self) -> &Any { self }
};

View File

@ -20,8 +20,6 @@ impl Stdin {
self.pushed.notify_one();
}
pub fn pop(&self) -> char {
// QEMU v3.0 don't support M-mode external interrupt (bug?)
// So we have to use polling.
loop {
let ret = self.buf.lock().pop_front();
match ret {
@ -43,6 +41,11 @@ lazy_static! {
pub static ref STDOUT: Arc<Stdout> = Arc::new(Stdout::default());
}
const TCGETS: u32 = 0x5401;
const TIOCGPGRP: u32 = 0x540F;
const TIOCSPGRP: u32 = 0x5410;
const TIOCGWINSZ: u32 = 0x5413;
// TODO: better way to provide default impl?
macro_rules! impl_inode {
() => {
@ -57,7 +60,23 @@ macro_rules! impl_inode {
fn move_(&self, _old_name: &str, _target: &Arc<INode>, _new_name: &str) -> Result<()> { Err(FsError::NotDir) }
fn find(&self, _name: &str) -> Result<Arc<INode>> { Err(FsError::NotDir) }
fn get_entry(&self, _id: usize) -> Result<String> { Err(FsError::NotDir) }
fn io_control(&self, _cmd: u32, _data: u32) -> Result<()> { Err(FsError::NotSupported) }
fn io_control(&self, cmd: u32, data: usize) -> Result<()> {
match cmd {
TCGETS | TIOCGWINSZ | TIOCSPGRP => {
// pretend to be tty
Ok(())
},
TIOCGPGRP => {
// pretend to be have a tty process group
// TODO: verify pointer
unsafe {
*(data as *mut u32) = 0
};
Ok(())
}
_ => Err(FsError::NotSupported)
}
}
fn fs(&self) -> Arc<FileSystem> { unimplemented!() }
fn as_any_ref(&self) -> &Any { self }
};

View File

@ -6,6 +6,7 @@
#![feature(optin_builtin_traits)]
#![feature(panic_info_message)]
#![feature(global_asm)]
#![deny(unused_must_use)]
#![no_std]
// just keep it ...

View File

@ -14,13 +14,12 @@ pub fn init() {
static LOGGER: SimpleLogger = SimpleLogger;
log::set_logger(&LOGGER).unwrap();
log::set_max_level(match option_env!("LOG") {
Some("off") => LevelFilter::Off,
Some("error") => LevelFilter::Error,
Some("warn") => LevelFilter::Warn,
Some("info") => LevelFilter::Info,
Some("debug") => LevelFilter::Debug,
Some("trace") => LevelFilter::Trace,
_ => LevelFilter::Warn,
_ => LevelFilter::Off,
});
}

View File

@ -16,9 +16,9 @@ pub type MemorySet = rcore_memory::memory_set::MemorySet<InactivePageTable0>;
#[cfg(target_arch = "x86_64")]
pub type FrameAlloc = bitmap_allocator::BitAlloc16M;
// RISCV has 8M memory
// RISCV has 1G memory
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
pub type FrameAlloc = bitmap_allocator::BitAlloc4K;
pub type FrameAlloc = bitmap_allocator::BitAlloc1M;
// Raspberry Pi 3 has 1G memory
#[cfg(any(target_arch = "aarch64", target_arch = "mips"))]

View File

@ -5,7 +5,7 @@ use core::ptr::null;
pub struct ProcInitInfo {
pub args: Vec<String>,
pub envs: BTreeMap<String, String>,
pub envs: Vec<String>,
pub auxv: BTreeMap<u8, usize>,
}
@ -19,10 +19,8 @@ impl ProcInitInfo {
let envs: Vec<_> = self
.envs
.iter()
.map(|(key, value)| {
writer.push_str(value.as_str());
writer.push_slice(&[b"="]);
writer.push_slice(key.as_bytes());
.map(|arg| {
writer.push_str(arg.as_str());
writer.sp
})
.collect();

View File

@ -26,6 +26,7 @@ pub fn init() {
}
static PROCESSORS: [Processor; MAX_CPU_NUM] = [
// TODO: More elegant ?
Processor::new(),
Processor::new(),
Processor::new(),
@ -34,6 +35,78 @@ static PROCESSORS: [Processor; MAX_CPU_NUM] = [
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
];
/// Get current process

View File

@ -158,10 +158,12 @@ impl Thread {
}
/// Make a new user process from ELF `data`
pub fn new_user<'a, Iter>(data: &[u8], args: Iter) -> Box<Thread>
where
Iter: Iterator<Item = &'a str>,
{
pub fn new_user(
data: &[u8],
exec_path: &str,
mut args: Vec<String>,
envs: Vec<String>,
) -> Box<Thread> {
// Parse ELF
let elf = ElfFile::new(data).expect("failed to read elf");
@ -172,17 +174,31 @@ impl Thread {
_ => panic!("ELF is not executable or shared object"),
}
// Check interpreter
// Check ELF arch
match elf.header.pt2.machine().as_machine() {
#[cfg(target_arch = "x86_64")]
header::Machine::X86_64 => {}
#[cfg(target_arch = "aarch64")]
header::Machine::AArch64 => {}
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
header::Machine::Other(243) => {}
#[cfg(target_arch = "mips")]
header::Machine::Mips => {}
machine @ _ => panic!("invalid elf arch: {:?}", machine),
}
// Check interpreter (for dynamic link)
if let Ok(loader_path) = elf.get_interpreter() {
// assuming absolute path
if let Ok(inode) = crate::fs::ROOT_INODE.lookup_follow(loader_path, FOLLOW_MAX_DEPTH) {
if let Ok(buf) = inode.read_as_vec() {
debug!("using loader {}", &loader_path);
// Elf loader should not have INTERP
// No infinite loop
let mut new_args: Vec<&str> = args.collect();
new_args.insert(0, loader_path);
return Thread::new_user(buf.as_slice(), new_args.into_iter());
args.insert(0, loader_path.into());
args.insert(1, exec_path.into());
args.remove(2);
info!("loader args: {:?}", args);
return Thread::new_user(buf.as_slice(), exec_path, args, envs);
} else {
warn!("loader specified as {} but failed to read", &loader_path);
}
@ -211,8 +227,8 @@ impl Thread {
// Make init info
let init_info = ProcInitInfo {
args: args.map(|s| String::from(s)).collect(),
envs: BTreeMap::new(),
args,
envs,
auxv: {
let mut map = BTreeMap::new();
if let Some(phdr_vaddr) = elf.get_phdr_vaddr() {
@ -418,7 +434,7 @@ impl ElfExt for ElfFile<'_> {
virt_addr + mem_size,
ph.flags().to_attr(),
ByFrame::new(GlobalFrameAlloc),
"",
"elf",
);
unsafe { ::core::slice::from_raw_parts_mut(virt_addr as *mut u8, mem_size) }
};

View File

@ -8,11 +8,14 @@ use alloc::vec::Vec;
#[cfg(not(feature = "run_cmdline"))]
pub fn run_user_shell() {
if let Ok(inode) = ROOT_INODE.lookup("rust/sh") {
if let Ok(inode) = ROOT_INODE.lookup("busybox") {
let data = inode.read_as_vec().unwrap();
processor()
.manager()
.add(Thread::new_user(data.as_slice(), "sh".split(' ')));
processor().manager().add(Thread::new_user(
data.as_slice(),
"busybox",
vec!["busybox".into(), "sh".into()],
Vec::new(),
));
} else {
processor().manager().add(Thread::new_kernel(shell, 0));
}
@ -23,9 +26,11 @@ pub fn run_user_shell() {
let cmdline = CMDLINE.read();
let inode = ROOT_INODE.lookup(&cmdline).unwrap();
let data = inode.read_as_vec().unwrap();
processor()
.manager()
.add(Thread::new_user(data.as_slice(), cmdline.split(' ')));
processor().manager().add(Thread::new_user(
data.as_slice(),
cmdline.split(' ').map(|s| s.into()).collect(),
Vec::new(),
));
}
pub extern "C" fn shell(_arg: usize) -> ! {
@ -42,9 +47,12 @@ pub extern "C" fn shell(_arg: usize) -> ! {
let name = cmd.trim().split(' ').next().unwrap();
if let Ok(file) = ROOT_INODE.lookup(name) {
let data = file.read_as_vec().unwrap();
let _pid = processor()
.manager()
.add(Thread::new_user(data.as_slice(), cmd.split(' ')));
let _pid = processor().manager().add(Thread::new_user(
data.as_slice(),
&cmd,
cmd.split(' ').map(|s| s.into()).collect(),
Vec::new(),
));
// TODO: wait until process exits, or use user land shell completely
//unsafe { thread::JoinHandle::<()>::_of(pid) }.join().unwrap();
} else {

View File

@ -10,7 +10,7 @@ use crate::fs::*;
use crate::memory::MemorySet;
use crate::sync::Condvar;
use bitvec::{BitSlice, BitVec, LittleEndian};
use bitvec::prelude::{BitSlice, BitVec, LittleEndian};
use super::*;
@ -66,12 +66,28 @@ pub fn sys_pwrite(fd: usize, base: *const u8, len: usize, offset: usize) -> SysR
Ok(len)
}
pub fn sys_poll(ufds: *mut PollFd, nfds: usize, timeout_msecs: usize) -> SysResult {
info!(
"poll: ufds: {:?}, nfds: {}, timeout_msecs: {:#x}",
ufds, nfds, timeout_msecs
);
pub fn sys_ppoll(ufds: *mut PollFd, nfds: usize, timeout: *const TimeSpec) -> SysResult {
let proc = process();
let timeout_msecs = if timeout.is_null() {
1 << 31 // infinity
} else {
proc.vm.check_read_ptr(timeout)?;
unsafe { (*timeout).to_msec() }
};
drop(proc);
sys_poll(ufds, nfds, timeout_msecs as usize)
}
pub fn sys_poll(ufds: *mut PollFd, nfds: usize, timeout_msecs: usize) -> SysResult {
let proc = process();
if !proc.pid.is_init() {
// we trust pid 0 process
info!(
"poll: ufds: {:?}, nfds: {}, timeout_msecs: {:#x}",
ufds, nfds, timeout_msecs
);
}
proc.vm.check_write_array(ufds, nfds)?;
let polls = unsafe { slice::from_raw_parts_mut(ufds, nfds) };
@ -209,11 +225,14 @@ pub fn sys_readv(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResul
}
pub fn sys_writev(fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResult {
info!(
"writev: fd: {}, iov: {:?}, count: {}",
fd, iov_ptr, iov_count
);
let mut proc = process();
if !proc.pid.is_init() {
// we trust pid 0 process
info!(
"writev: fd: {}, iov: {:?}, count: {}",
fd, iov_ptr, iov_count
);
}
let iovs = IoVecs::check_and_new(iov_ptr, iov_count, &proc.vm, false)?;
let buf = iovs.read_all_to_vec();
@ -240,7 +259,7 @@ pub fn sys_openat(dir_fd: usize, path: *const u8, flags: usize, mode: usize) ->
let inode = if flags.contains(OpenFlags::CREATE) {
let (dir_path, file_name) = split_path(&path);
// relative to cwd
let dir_inode = proc.lookup_inode_at(dir_fd, dir_path)?;
let dir_inode = proc.lookup_inode_at(dir_fd, dir_path, true)?;
match dir_inode.find(file_name) {
Ok(file_inode) => {
if flags.contains(OpenFlags::EXCLUSIVE) {
@ -254,7 +273,7 @@ pub fn sys_openat(dir_fd: usize, path: *const u8, flags: usize, mode: usize) ->
Err(e) => return Err(SysError::from(e)),
}
} else {
proc.lookup_inode_at(dir_fd, &path)?
proc.lookup_inode_at(dir_fd, &path, true)?
};
let fd = proc.get_free_fd();
@ -284,10 +303,10 @@ pub fn sys_faccessat(dirfd: usize, path: *const u8, mode: usize, flags: usize) -
// we trust pid 0 process
info!(
"faccessat: dirfd: {}, path: {:?}, mode: {:#o}, flags: {:?}",
dirfd, path, mode, flags
dirfd as isize, path, mode, flags
);
}
let inode = proc.lookup_inode_at(dirfd, &path)?;
let inode = proc.lookup_inode_at(dirfd, &path, !flags.contains(AtFlags::SYMLINK_NOFOLLOW))?;
Ok(0)
}
@ -306,8 +325,7 @@ pub fn sys_getcwd(buf: *mut u8, len: usize) -> SysResult {
}
pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult {
warn!("lstat is partial implemented as stat");
sys_stat(path, stat_ptr)
sys_fstatat(AT_FDCWD, path, stat_ptr, AtFlags::SYMLINK_NOFOLLOW.bits())
}
pub fn sys_fstat(fd: usize, stat_ptr: *mut Stat) -> SysResult {
@ -329,10 +347,10 @@ pub fn sys_fstatat(dirfd: usize, path: *const u8, stat_ptr: *mut Stat, flags: us
let flags = AtFlags::from_bits_truncate(flags);
info!(
"fstatat: dirfd: {}, path: {:?}, stat_ptr: {:?}, flags: {:?}",
dirfd, path, stat_ptr, flags
dirfd as isize, path, stat_ptr, flags
);
let inode = proc.lookup_inode_at(dirfd, &path)?;
let inode = proc.lookup_inode_at(dirfd, &path, !flags.contains(AtFlags::SYMLINK_NOFOLLOW))?;
let stat = Stat::from(inode.metadata()?);
unsafe {
stat_ptr.write(stat);
@ -354,7 +372,7 @@ pub fn sys_readlinkat(dirfd: usize, path: *const u8, base: *mut u8, len: usize)
proc.vm.check_write_array(base, len)?;
info!("readlink: path: {:?}, base: {:?}, len: {}", path, base, len);
let inode = proc.lookup_inode_at(dirfd, &path)?;
let inode = proc.lookup_inode_at(dirfd, &path, false)?;
if inode.metadata()?.type_ == FileType::SymLink {
// TODO: recursive link resolution and loop detection
let mut slice = unsafe { slice::from_raw_parts_mut(base, len) };
@ -472,12 +490,9 @@ pub fn sys_chdir(path: *const u8) -> SysResult {
if path.len() > 0 {
let cwd = match path.as_bytes()[0] {
b'/' => String::from("/"),
_ => proc.cwd.clone()
_ => proc.cwd.clone(),
};
let mut cwd_vec:Vec<_> =
cwd.split("/")
.filter(|&x| x != "")
.collect();
let mut cwd_vec: Vec<_> = cwd.split("/").filter(|&x| x != "").collect();
let path_split = path.split("/").filter(|&x| x != "");
for seg in path_split {
if seg == ".." {
@ -515,13 +530,13 @@ pub fn sys_renameat(
let newpath = unsafe { proc.vm.check_and_clone_cstr(newpath)? };
info!(
"renameat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}",
olddirfd, oldpath, newdirfd, newpath
olddirfd as isize, oldpath, newdirfd as isize, newpath
);
let (old_dir_path, old_file_name) = split_path(&oldpath);
let (new_dir_path, new_file_name) = split_path(&newpath);
let old_dir_inode = proc.lookup_inode_at(olddirfd, old_dir_path)?;
let new_dir_inode = proc.lookup_inode_at(newdirfd, new_dir_path)?;
let old_dir_inode = proc.lookup_inode_at(olddirfd, old_dir_path, false)?;
let new_dir_inode = proc.lookup_inode_at(newdirfd, new_dir_path, false)?;
old_dir_inode.move_(old_file_name, &new_dir_inode, new_file_name)?;
Ok(0)
}
@ -536,11 +551,11 @@ pub fn sys_mkdirat(dirfd: usize, path: *const u8, mode: usize) -> SysResult {
// TODO: check pathname
info!(
"mkdirat: dirfd: {}, path: {:?}, mode: {:#o}",
dirfd, path, mode
dirfd as isize, path, mode
);
let (dir_path, file_name) = split_path(&path);
let inode = proc.lookup_inode_at(dirfd, dir_path)?;
let inode = proc.lookup_inode_at(dirfd, dir_path, true)?;
if inode.find(file_name).is_ok() {
return Err(SysError::EEXIST);
}
@ -580,12 +595,12 @@ pub fn sys_linkat(
let flags = AtFlags::from_bits_truncate(flags);
info!(
"linkat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}, flags: {:?}",
olddirfd, oldpath, newdirfd, newpath, flags
olddirfd as isize, oldpath, newdirfd as isize, newpath, flags
);
let (new_dir_path, new_file_name) = split_path(&newpath);
let inode = proc.lookup_inode_at(olddirfd, &oldpath)?;
let new_dir_inode = proc.lookup_inode_at(newdirfd, new_dir_path)?;
let inode = proc.lookup_inode_at(olddirfd, &oldpath, true)?;
let new_dir_inode = proc.lookup_inode_at(newdirfd, new_dir_path, true)?;
new_dir_inode.link(new_file_name, &inode)?;
Ok(0)
}
@ -600,11 +615,11 @@ pub fn sys_unlinkat(dirfd: usize, path: *const u8, flags: usize) -> SysResult {
let flags = AtFlags::from_bits_truncate(flags);
info!(
"unlinkat: dirfd: {}, path: {:?}, flags: {:?}",
dirfd, path, flags
dirfd as isize, path, flags
);
let (dir_path, file_name) = split_path(&path);
let dir_inode = proc.lookup_inode_at(dirfd, dir_path)?;
let dir_inode = proc.lookup_inode_at(dirfd, dir_path, true)?;
let file_inode = dir_inode.find(file_name)?;
if file_inode.metadata()?.type_ == FileType::Dir {
return Err(SysError::EISDIR);
@ -647,8 +662,8 @@ pub fn sys_pipe(fds: *mut u32) -> SysResult {
);
unsafe {
*fds = read_fd as u32;
*(fds.add(1)) = write_fd as u32;
fds.write(read_fd as u32);
fds.add(1).write(write_fd as u32);
}
info!("pipe: created rfd: {} wfd: {}", read_fd, write_fd);
@ -661,69 +676,60 @@ pub fn sys_sync() -> SysResult {
Ok(0)
}
pub fn sys_sendfile(out_fd: usize, in_fd: usize, offset: *mut usize, count: usize) -> SysResult {
pub fn sys_sendfile(
out_fd: usize,
in_fd: usize,
offset_ptr: *mut usize,
count: usize,
) -> SysResult {
info!(
"sendfile: out: {}, in: {}, offset: {:?}, count: {}",
out_fd, in_fd, offset, count
"sendfile: out: {}, in: {}, offset_ptr: {:?}, count: {}",
out_fd, in_fd, offset_ptr, count
);
let proc = process();
// We know it's save, pacify the borrow checker
let proc_cell = UnsafeCell::new(proc);
let proc_in = unsafe { &mut *proc_cell.get() };
let proc_out = unsafe { &mut *proc_cell.get() };
//let in_file: &mut FileHandle = unsafe { &mut *UnsafeCell::new(proc.get_file(in_fd)?).get() };
//let out_file: &mut FileHandle = unsafe { &mut *UnsafeCell::new(proc.get_file(out_fd)?).get() };
let in_file = proc_in.get_file(in_fd)?;
let out_file = proc_out.get_file(out_fd)?;
let in_file = unsafe { (*proc_cell.get()).get_file(in_fd)? };
let out_file = unsafe { (*proc_cell.get()).get_file(out_fd)? };
let mut buffer = [0u8; 1024];
if offset.is_null() {
// read from current file offset
let mut bytes_read = 0;
while bytes_read < count {
let len = min(buffer.len(), count - bytes_read);
let read_len = in_file.read(&mut buffer[..len])?;
if read_len == 0 {
break;
}
bytes_read += read_len;
let mut bytes_written = 0;
while bytes_written < read_len {
let write_len = out_file.write(&buffer[bytes_written..])?;
if write_len == 0 {
return Err(SysError::EBADF);
}
bytes_written += write_len;
}
}
return Ok(bytes_read);
} else {
let proc_mem = unsafe { &mut *proc_cell.get() };
proc_mem.vm.check_read_ptr(offset)?;
let mut read_offset = unsafe { *offset };
// read from specified offset and write new offset back
let mut bytes_read = 0;
while bytes_read < count {
let len = min(buffer.len(), count - bytes_read);
let read_len = in_file.read_at(read_offset, &mut buffer[..len])?;
if read_len == 0 {
break;
}
bytes_read += read_len;
read_offset += read_len;
let mut bytes_written = 0;
while bytes_written < read_len {
let write_len = out_file.write(&buffer[bytes_written..])?;
if write_len == 0 {
return Err(SysError::EBADF);
}
bytes_written += write_len;
}
}
let mut read_offset = if !offset_ptr.is_null() {
unsafe {
*offset = read_offset;
(*proc_cell.get()).vm.check_read_ptr(offset_ptr)?;
offset_ptr.read()
}
} else {
in_file.seek(SeekFrom::Current(0))? as usize
};
// read from specified offset and write new offset back
let mut bytes_read = 0;
while bytes_read < count {
let len = min(buffer.len(), count - bytes_read);
let read_len = in_file.read_at(read_offset, &mut buffer[..len])?;
if read_len == 0 {
break;
}
bytes_read += read_len;
read_offset += read_len;
let mut bytes_written = 0;
while bytes_written < read_len {
let write_len = out_file.write(&buffer[bytes_written..])?;
if write_len == 0 {
return Err(SysError::EBADF);
}
bytes_written += write_len;
}
return Ok(bytes_read);
}
if !offset_ptr.is_null() {
unsafe {
offset_ptr.write(read_offset);
}
} else {
in_file.seek(SeekFrom::Current(bytes_read as i64))?;
}
return Ok(bytes_read);
}
impl Process {
@ -751,12 +757,11 @@ impl Process {
&self,
dirfd: usize,
path: &str,
// follow: bool,
follow: bool,
) -> Result<Arc<INode>, SysError> {
let follow = true;
debug!(
"lookup_inode_at: fd: {:?}, cwd: {:?}, path: {:?}, follow: {:?}",
dirfd, self.cwd, path, follow
"lookup_inode_at: dirfd: {:?}, cwd: {:?}, path: {:?}, follow: {:?}",
dirfd as isize, self.cwd, path, follow
);
let follow_max_depth = if follow { FOLLOW_MAX_DEPTH } else { 0 };
if dirfd == AT_FDCWD {
@ -773,7 +778,7 @@ impl Process {
}
pub fn lookup_inode(&self, path: &str) -> Result<Arc<INode>, SysError> {
self.lookup_inode_at(AT_FDCWD, path)
self.lookup_inode_at(AT_FDCWD, path, true)
}
}
@ -1139,7 +1144,7 @@ pub struct IoVec {
/// Starting address
base: *mut u8,
/// Number of bytes to transfer
len: u64,
len: usize,
}
/// A valid IoVecs request from user
@ -1160,15 +1165,15 @@ impl IoVecs {
if iov.len > 0 {
// skip empty iov
if readv {
vm.check_write_array(iov.base, iov.len as usize)?;
vm.check_write_array(iov.base, iov.len)?;
} else {
vm.check_read_array(iov.base, iov.len as usize)?;
vm.check_read_array(iov.base, iov.len)?;
}
}
}
let slices = iovs
.iter()
.map(|iov| unsafe { slice::from_raw_parts_mut(iov.base, iov.len as usize) })
.map(|iov| unsafe { slice::from_raw_parts_mut(iov.base, iov.len) })
.collect();
Ok(IoVecs(slices))
}

View File

@ -88,7 +88,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
}
SYS_GETPID => sys_getpid(),
// 40
SYS_SENDFILE => sys_sendfile(args[0], args[1], args[3] as *mut usize, args[4]),
SYS_SENDFILE => sys_sendfile(args[0], args[1], args[2] as *mut usize, args[3]),
SYS_SOCKET => sys_socket(args[0], args[1], args[2]),
SYS_CONNECT => sys_connect(args[0], args[1] as *const SockAddr, args[2]),
SYS_ACCEPT => sys_accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32),
@ -194,12 +194,28 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
warn!("sys_getegid is unimplemented");
Ok(0)
}
SYS_SETPGID => {
warn!("sys_setpgid is unimplemented");
Ok(0)
}
// 110
SYS_GETPPID => sys_getppid(),
SYS_SETSID => {
warn!("sys_setsid is unimplemented");
Ok(0)
}
SYS_GETPGID => {
warn!("sys_getpgid is unimplemented");
Ok(0)
}
SYS_GETGROUPS => {
warn!("sys_getgroups is unimplemented");
Ok(0)
}
SYS_SETGROUPS => {
warn!("sys_setgroups is unimplemented");
Ok(0)
}
SYS_SIGALTSTACK => {
warn!("sys_sigaltstack is unimplemented");
Ok(0)
@ -213,6 +229,10 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
Err(SysError::EACCES)
}
SYS_SETPRIORITY => sys_set_priority(args[0]),
SYS_PRCTL => {
warn!("prctl is unimplemented");
Ok(0)
}
// SYS_SETRLIMIT => sys_setrlimit(),
SYS_SYNC => sys_sync(),
SYS_MOUNT => {
@ -254,11 +274,24 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
}
SYS_NEWFSTATAT => sys_fstatat(args[0], args[1] as *const u8, args[2] as *mut Stat, args[3]),
SYS_UNLINKAT => sys_unlinkat(args[0], args[1] as *const u8, args[2]),
SYS_READLINKAT => sys_readlinkat(args[0], args[1] as *const u8, args[2] as *mut u8, args[3]),
SYS_RENAMEAT => sys_renameat(args[0], args[1] as *const u8, args[2], args[3] as *const u8),
SYS_LINKAT => sys_linkat(args[0], args[1] as *const u8, args[2], args[3] as *const u8, args[4]),
SYS_LINKAT => sys_linkat(
args[0],
args[1] as *const u8,
args[2],
args[3] as *const u8,
args[4],
),
SYS_SYMLINKAT => Err(SysError::EACCES),
SYS_READLINKAT => {
sys_readlinkat(args[0], args[1] as *const u8, args[2] as *mut u8, args[3])
}
SYS_FCHMODAT => {
warn!("sys_fchmodat is unimplemented");
Ok(0)
}
SYS_FACCESSAT => sys_faccessat(args[0], args[1] as *const u8, args[2], args[3]),
SYS_PPOLL => sys_ppoll(args[0] as *mut PollFd, args[1], args[2] as *const TimeSpec), // ignore sigmask
// 280
SYS_UTIMENSAT => {
warn!("sys_utimensat is unimplemented");
@ -324,7 +357,10 @@ fn x86_64_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<Sys
args[4] as *const TimeVal,
),
SYS_DUP2 => sys_dup2(args[0], args[1]),
// SYS_PAUSE => sys_pause(),
SYS_ALARM => {
warn!("sys_alarm is unimplemented");
Ok(0)
}
SYS_FORK => sys_fork(tf),
// use fork for vfork
SYS_VFORK => sys_fork(tf),
@ -339,16 +375,12 @@ fn x86_64_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<Sys
warn!("sys_chmod is unimplemented");
Ok(0)
}
SYS_ARCH_PRCTL => sys_arch_prctl(args[0] as i32, args[1], tf),
SYS_TIME => sys_time(args[0] as *mut u64),
SYS_ALARM => {
warn!("sys_alarm is unimplemented");
Ok(0)
}
SYS_CHOWN => {
warn!("sys_chown is unimplemented");
Ok(0)
}
SYS_ARCH_PRCTL => sys_arch_prctl(args[0] as i32, args[1], tf),
SYS_TIME => sys_time(args[0] as *mut u64),
SYS_EPOLL_CREATE => {
warn!("sys_epoll_create is unimplemented");
Err(SysError::ENOSYS)

View File

@ -13,7 +13,7 @@ pub fn sys_fork(tf: &TrapFrame) -> SysResult {
/// Create a new thread in the current process.
/// The new thread's stack pointer will be set to `newsp`,
/// and thread pointer will be set to `newtls`.
/// and thread pointer will be set to `newtls`.
/// The child tid will be stored at both `parent_tid` and `child_tid`.
/// This is partially implemented for musl only.
pub fn sys_clone(
@ -24,17 +24,19 @@ pub fn sys_clone(
newtls: usize,
tf: &TrapFrame,
) -> SysResult {
let clone_flags = CloneFlags::from_bits_truncate(flags);
info!(
"clone: flags: {:#x}, newsp: {:#x}, parent_tid: {:?}, child_tid: {:?}, newtls: {:#x}",
flags, newsp, parent_tid, child_tid, newtls
"clone: flags: {:?} == {:#x}, newsp: {:#x}, parent_tid: {:?}, child_tid: {:?}, newtls: {:#x}",
clone_flags, flags, newsp, parent_tid, child_tid, newtls
);
if flags == 0x4111 {
if flags == 0x4111 || flags == 0x11 {
warn!("sys_clone is calling sys_fork instead, ignoring other args");
return sys_fork(tf);
}
if flags != 0x7d0f00 {
warn!("sys_clone only support musl pthread_create");
return Err(SysError::ENOSYS);
if (flags != 0x7d0f00) && (flags!= 0x5d0f00) { //0x5d0f00 is the args from gcc of alpine linux
//warn!("sys_clone only support musl pthread_create");
panic!("sys_clone only support sys_fork OR musl pthread_create without flags{:x}", flags);
//return Err(SysError::ENOSYS);
}
{
let proc = process();
@ -123,9 +125,9 @@ pub fn sys_exec(
envp: *const *const u8,
tf: &mut TrapFrame,
) -> SysResult {
info!("exec: name: {:?}, argv: {:?} envp: {:?}", name, argv, envp);
info!("exec: name: {:?}, argv: {:?}, envp: {:?}", name, argv, envp);
let proc = process();
let _name = if name.is_null() {
let exec_name = if name.is_null() {
String::from("")
} else {
unsafe { proc.vm.check_and_clone_cstr(name)? }
@ -145,16 +147,37 @@ pub fn sys_exec(
current_argv = current_argv.add(1);
}
}
info!("exec: args {:?}", args);
// Check and copy envs to kernel
let mut envs = Vec::new();
unsafe {
let mut current_env = envp as *const *const u8;
if !current_env.is_null() {
proc.vm.check_read_ptr(current_env)?;
while !(*current_env).is_null() {
let env = proc.vm.check_and_clone_cstr(*current_env)?;
envs.push(env);
current_env = current_env.add(1);
}
}
}
if args.is_empty() {
return Err(SysError::EINVAL);
}
info!(
"exec: name: {:?}, args: {:?}, envp: {:?}",
exec_name, args, envs
);
// Read program file
let path = args[0].as_str();
let inode = proc.lookup_inode(path)?;
//let path = args[0].as_str();
let exec_path = exec_name.as_str();
let inode = proc.lookup_inode(exec_path)?;
let buf = inode.read_as_vec()?;
// Make new Thread
let iter = args.iter().map(|s| s.as_str());
let mut thread = Thread::new_user(buf.as_slice(), iter);
let mut thread = Thread::new_user(buf.as_slice(), exec_path, args, envs);
thread.proc.lock().clone_for_exec(&proc);
// Activate new page table
@ -228,7 +251,11 @@ pub fn sys_gettid() -> SysResult {
/// Get the parent process id
pub fn sys_getppid() -> SysResult {
Ok(process().parent.as_ref().unwrap().lock().pid.get())
if let Some(ref parent) = process().parent.as_ref() {
Ok(parent.lock().pid.get())
} else {
Ok(0)
}
}
/// Exit the current thread
@ -310,3 +337,30 @@ pub fn sys_set_priority(priority: usize) -> SysResult {
processor().manager().set_priority(pid, priority as u8);
Ok(0)
}
bitflags! {
pub struct CloneFlags: usize {
const CSIGNAL = 0x000000ff;
const VM = 0x0000100;
const FS = 0x0000200;
const FILES = 0x0000400;
const SIGHAND = 0x0000800;
const PTRACE = 0x0002000;
const VFORK = 0x0004000;
const PARENT = 0x0008000;
const SYSVSEM = 0x0008000;
const SETTLS = 0x0008000;
const PARENT_SETTID = 0x0010000;
const CHILD_CLEARTID = 0x0020000;
const DETACHED = 0x0040000;
const UNTRACED = 0x0080000;
const CHILD_SETTID = 0x0100000;
const NEWCGROUP = 0x0200000;
const NEWUTS = 0x0400000;
const NEWIPC = 0x0800000;
const NEWUSER = 0x1000000;
const NEWPID = 0x2000000;
const NEWNET = 0x4000000;
const IO = 0x8000000;
}
}

View File

@ -19,6 +19,7 @@ const USEC_PER_SEC: u64 = 1_000_000;
const MSEC_PER_SEC: u64 = 1_000;
const USEC_PER_MSEC: u64 = 1_000;
const NSEC_PER_USEC: u64 = 1_000;
const NSEC_PER_MSEC: u64 = 1_000_000;
/// Get time since epoch in usec
fn get_epoch_usec() -> u64 {
@ -58,6 +59,10 @@ pub struct TimeSpec {
}
impl TimeSpec {
pub fn to_msec(&self) -> u64 {
self.sec * MSEC_PER_SEC + self.nsec / NSEC_PER_MSEC
}
pub fn to_duration(&self) -> Duration {
Duration::new(self.sec, self.nsec as u32)
}

View File

@ -83,4 +83,4 @@ pub fn write<T>(addr: usize, content: T) {
pub fn read<T>(addr: usize) -> T {
let cell = (addr) as *const T;
unsafe { read_volatile(cell) }
}
}

@ -1 +0,0 @@
Subproject commit 405ea59dd7dd2762c5883822f21d9995bea32b0c

View File

@ -10,11 +10,11 @@ arch = sys.argv[2]
mode = sys.argv[3]
print('--------------------------------------')
for line in lines:
match = re.search('(#[0-9]+ )(0x[0-9A-F]+)( fp 0x[0-9A-F]+)', line)
match = re.search('#([0-9]+) PC: (0x[0-9A-F]+) FP: (0x[0-9A-F]+)', line)
if match:
addr = match.group(2)
process = subprocess.run([addrline, '-e', 'target/{0}/{1}/rcore'.format(arch, mode), '-f', '-C', addr], capture_output=True)
res = process.stdout.decode('utf-8')
print('{0}{1}{3} {2}'.format(match.group(1), match.group(2), res.strip(), match.group(3)))
print('#{0} PC: {1} FP: {3} {2}'.format(match.group(1), match.group(2), res.strip(), match.group(3)))
else:
print(line, end='')

9
tools/opensbi/README.md Normal file
View File

@ -0,0 +1,9 @@
# OpenSBI
These are binary release of OpenSBI on this [commit](https://github.com/riscv/opensbi/tree/194dbbe5a13dff2255411c26d249f3ad4ef42c0b) at 2019.04.15.
- fu540.elf: opensbi-0.3-rv64-bin/platform/sifive/fu540/firmware/fw_jump.elf
- virt_rv32.elf: opensbi-0.3-rv32-bin/platform/qemu/virt/firmware/fw_jump.elf
- virt_rv64.elf: opensbi-0.3-rv64-bin/platform/qemu/virt/firmware/fw_jump.elf
NOTE: The [official v0.3 release](https://github.com/riscv/opensbi/releases/tag/v0.3) has bug on serial interrupt.

BIN
tools/opensbi/fu540.elf Executable file

Binary file not shown.

BIN
tools/opensbi/virt_rv32.elf Executable file

Binary file not shown.

BIN
tools/opensbi/virt_rv64.elf Executable file

Binary file not shown.

382
tools/syscall_64.tbl Normal file
View File

@ -0,0 +1,382 @@
#
# 64-bit system call numbers and entry vectors
#
# The format is:
# <number> <abi> <name> <entry point>
#
# The abi is "common", "64" or "x32" for this file.
#
0 common read sys_read
1 common write sys_write
2 common open sys_open
3 common close sys_close
4 common stat sys_newstat
5 common fstat sys_newfstat
6 common lstat sys_newlstat
7 common poll sys_poll
8 common lseek sys_lseek
9 common mmap sys_mmap
10 common mprotect sys_mprotect
11 common munmap sys_munmap
12 common brk sys_brk
13 64 rt_sigaction sys_rt_sigaction
14 common rt_sigprocmask sys_rt_sigprocmask
15 64 rt_sigreturn sys_rt_sigreturn/ptregs
16 64 ioctl sys_ioctl
17 common pread64 sys_pread64
18 common pwrite64 sys_pwrite64
19 64 readv sys_readv
20 64 writev sys_writev
21 common access sys_access
22 common pipe sys_pipe
23 common select sys_select
24 common sched_yield sys_sched_yield
25 common mremap sys_mremap
26 common msync sys_msync
27 common mincore sys_mincore
28 common madvise sys_madvise
29 common shmget sys_shmget
30 common shmat sys_shmat
31 common shmctl sys_shmctl
32 common dup sys_dup
33 common dup2 sys_dup2
34 common pause sys_pause
35 common nanosleep sys_nanosleep
36 common getitimer sys_getitimer
37 common alarm sys_alarm
38 common setitimer sys_setitimer
39 common getpid sys_getpid
40 common sendfile sys_sendfile64
41 common socket sys_socket
42 common connect sys_connect
43 common accept sys_accept
44 common sendto sys_sendto
45 64 recvfrom sys_recvfrom
46 64 sendmsg sys_sendmsg
47 64 recvmsg sys_recvmsg
48 common shutdown sys_shutdown
49 common bind sys_bind
50 common listen sys_listen
51 common getsockname sys_getsockname
52 common getpeername sys_getpeername
53 common socketpair sys_socketpair
54 64 setsockopt sys_setsockopt
55 64 getsockopt sys_getsockopt
56 common clone sys_clone/ptregs
57 common fork sys_fork/ptregs
58 common vfork sys_vfork/ptregs
59 64 execve sys_execve/ptregs
60 common exit sys_exit
61 common wait4 sys_wait4
62 common kill sys_kill
63 common uname sys_newuname
64 common semget sys_semget
65 common semop sys_semop
66 common semctl sys_semctl
67 common shmdt sys_shmdt
68 common msgget sys_msgget
69 common msgsnd sys_msgsnd
70 common msgrcv sys_msgrcv
71 common msgctl sys_msgctl
72 common fcntl sys_fcntl
73 common flock sys_flock
74 common fsync sys_fsync
75 common fdatasync sys_fdatasync
76 common truncate sys_truncate
77 common ftruncate sys_ftruncate
78 common getdents sys_getdents
79 common getcwd sys_getcwd
80 common chdir sys_chdir
81 common fchdir sys_fchdir
82 common rename sys_rename
83 common mkdir sys_mkdir
84 common rmdir sys_rmdir
85 common creat sys_creat
86 common link sys_link
87 common unlink sys_unlink
88 common symlink sys_symlink
89 common readlink sys_readlink
90 common chmod sys_chmod
91 common fchmod sys_fchmod
92 common chown sys_chown
93 common fchown sys_fchown
94 common lchown sys_lchown
95 common umask sys_umask
96 common gettimeofday sys_gettimeofday
97 common getrlimit sys_getrlimit
98 common getrusage sys_getrusage
99 common sysinfo sys_sysinfo
100 common times sys_times
101 64 ptrace sys_ptrace
102 common getuid sys_getuid
103 common syslog sys_syslog
104 common getgid sys_getgid
105 common setuid sys_setuid
106 common setgid sys_setgid
107 common geteuid sys_geteuid
108 common getegid sys_getegid
109 common setpgid sys_setpgid
110 common getppid sys_getppid
111 common getpgrp sys_getpgrp
112 common setsid sys_setsid
113 common setreuid sys_setreuid
114 common setregid sys_setregid
115 common getgroups sys_getgroups
116 common setgroups sys_setgroups
117 common setresuid sys_setresuid
118 common getresuid sys_getresuid
119 common setresgid sys_setresgid
120 common getresgid sys_getresgid
121 common getpgid sys_getpgid
122 common setfsuid sys_setfsuid
123 common setfsgid sys_setfsgid
124 common getsid sys_getsid
125 common capget sys_capget
126 common capset sys_capset
127 64 rt_sigpending sys_rt_sigpending
128 64 rt_sigtimedwait sys_rt_sigtimedwait
129 64 rt_sigqueueinfo sys_rt_sigqueueinfo
130 common rt_sigsuspend sys_rt_sigsuspend
131 64 sigaltstack sys_sigaltstack
132 common utime sys_utime
133 common mknod sys_mknod
134 64 uselib
135 common personality sys_personality
136 common ustat sys_ustat
137 common statfs sys_statfs
138 common fstatfs sys_fstatfs
139 common sysfs sys_sysfs
140 common getpriority sys_getpriority
141 common setpriority sys_setpriority
142 common sched_setparam sys_sched_setparam
143 common sched_getparam sys_sched_getparam
144 common sched_setscheduler sys_sched_setscheduler
145 common sched_getscheduler sys_sched_getscheduler
146 common sched_get_priority_max sys_sched_get_priority_max
147 common sched_get_priority_min sys_sched_get_priority_min
148 common sched_rr_get_interval sys_sched_rr_get_interval
149 common mlock sys_mlock
150 common munlock sys_munlock
151 common mlockall sys_mlockall
152 common munlockall sys_munlockall
153 common vhangup sys_vhangup
154 common modify_ldt sys_modify_ldt
155 common pivot_root sys_pivot_root
156 64 _sysctl sys_sysctl
157 common prctl sys_prctl
158 common arch_prctl sys_arch_prctl
159 common adjtimex sys_adjtimex
160 common setrlimit sys_setrlimit
161 common chroot sys_chroot
162 common sync sys_sync
163 common acct sys_acct
164 common settimeofday sys_settimeofday
165 common mount sys_mount
166 common umount2 sys_umount
167 common swapon sys_swapon
168 common swapoff sys_swapoff
169 common reboot sys_reboot
170 common sethostname sys_sethostname
171 common setdomainname sys_setdomainname
172 common iopl sys_iopl/ptregs
173 common ioperm sys_ioperm
174 64 create_module
175 common init_module sys_init_module
176 common delete_module sys_delete_module
177 64 get_kernel_syms
178 64 query_module
179 common quotactl sys_quotactl
180 64 nfsservctl
181 common getpmsg
182 common putpmsg
183 common afs_syscall
184 common tuxcall
185 common security
186 common gettid sys_gettid
187 common readahead sys_readahead
188 common setxattr sys_setxattr
189 common lsetxattr sys_lsetxattr
190 common fsetxattr sys_fsetxattr
191 common getxattr sys_getxattr
192 common lgetxattr sys_lgetxattr
193 common fgetxattr sys_fgetxattr
194 common listxattr sys_listxattr
195 common llistxattr sys_llistxattr
196 common flistxattr sys_flistxattr
197 common removexattr sys_removexattr
198 common lremovexattr sys_lremovexattr
199 common fremovexattr sys_fremovexattr
200 common tkill sys_tkill
201 common time sys_time
202 common futex sys_futex
203 common sched_setaffinity sys_sched_setaffinity
204 common sched_getaffinity sys_sched_getaffinity
205 64 set_thread_area
206 64 io_setup sys_io_setup
207 common io_destroy sys_io_destroy
208 common io_getevents sys_io_getevents
209 64 io_submit sys_io_submit
210 common io_cancel sys_io_cancel
211 64 get_thread_area
212 common lookup_dcookie sys_lookup_dcookie
213 common epoll_create sys_epoll_create
214 64 epoll_ctl_old
215 64 epoll_wait_old
216 common remap_file_pages sys_remap_file_pages
217 common getdents64 sys_getdents64
218 common set_tid_address sys_set_tid_address
219 common restart_syscall sys_restart_syscall
220 common semtimedop sys_semtimedop
221 common fadvise64 sys_fadvise64
222 64 timer_create sys_timer_create
223 common timer_settime sys_timer_settime
224 common timer_gettime sys_timer_gettime
225 common timer_getoverrun sys_timer_getoverrun
226 common timer_delete sys_timer_delete
227 common clock_settime sys_clock_settime
228 common clock_gettime sys_clock_gettime
229 common clock_getres sys_clock_getres
230 common clock_nanosleep sys_clock_nanosleep
231 common exit_group sys_exit_group
232 common epoll_wait sys_epoll_wait
233 common epoll_ctl sys_epoll_ctl
234 common tgkill sys_tgkill
235 common utimes sys_utimes
236 64 vserver
237 common mbind sys_mbind
238 common set_mempolicy sys_set_mempolicy
239 common get_mempolicy sys_get_mempolicy
240 common mq_open sys_mq_open
241 common mq_unlink sys_mq_unlink
242 common mq_timedsend sys_mq_timedsend
243 common mq_timedreceive sys_mq_timedreceive
244 64 mq_notify sys_mq_notify
245 common mq_getsetattr sys_mq_getsetattr
246 64 kexec_load sys_kexec_load
247 64 waitid sys_waitid
248 common add_key sys_add_key
249 common request_key sys_request_key
250 common keyctl sys_keyctl
251 common ioprio_set sys_ioprio_set
252 common ioprio_get sys_ioprio_get
253 common inotify_init sys_inotify_init
254 common inotify_add_watch sys_inotify_add_watch
255 common inotify_rm_watch sys_inotify_rm_watch
256 common migrate_pages sys_migrate_pages
257 common openat sys_openat
258 common mkdirat sys_mkdirat
259 common mknodat sys_mknodat
260 common fchownat sys_fchownat
261 common futimesat sys_futimesat
262 common newfstatat sys_newfstatat
263 common unlinkat sys_unlinkat
264 common renameat sys_renameat
265 common linkat sys_linkat
266 common symlinkat sys_symlinkat
267 common readlinkat sys_readlinkat
268 common fchmodat sys_fchmodat
269 common faccessat sys_faccessat
270 common pselect6 sys_pselect6
271 common ppoll sys_ppoll
272 common unshare sys_unshare
273 64 set_robust_list sys_set_robust_list
274 64 get_robust_list sys_get_robust_list
275 common splice sys_splice
276 common tee sys_tee
277 common sync_file_range sys_sync_file_range
278 64 vmsplice sys_vmsplice
279 64 move_pages sys_move_pages
280 common utimensat sys_utimensat
281 common epoll_pwait sys_epoll_pwait
282 common signalfd sys_signalfd
283 common timerfd_create sys_timerfd_create
284 common eventfd sys_eventfd
285 common fallocate sys_fallocate
286 common timerfd_settime sys_timerfd_settime
287 common timerfd_gettime sys_timerfd_gettime
288 common accept4 sys_accept4
289 common signalfd4 sys_signalfd4
290 common eventfd2 sys_eventfd2
291 common epoll_create1 sys_epoll_create1
292 common dup3 sys_dup3
293 common pipe2 sys_pipe2
294 common inotify_init1 sys_inotify_init1
295 64 preadv sys_preadv
296 64 pwritev sys_pwritev
297 64 rt_tgsigqueueinfo sys_rt_tgsigqueueinfo
298 common perf_event_open sys_perf_event_open
299 64 recvmmsg sys_recvmmsg
300 common fanotify_init sys_fanotify_init
301 common fanotify_mark sys_fanotify_mark
302 common prlimit64 sys_prlimit64
303 common name_to_handle_at sys_name_to_handle_at
304 common open_by_handle_at sys_open_by_handle_at
305 common clock_adjtime sys_clock_adjtime
306 common syncfs sys_syncfs
307 64 sendmmsg sys_sendmmsg
308 common setns sys_setns
309 common getcpu sys_getcpu
310 64 process_vm_readv sys_process_vm_readv
311 64 process_vm_writev sys_process_vm_writev
312 common kcmp sys_kcmp
313 common finit_module sys_finit_module
314 common sched_setattr sys_sched_setattr
315 common sched_getattr sys_sched_getattr
316 common renameat2 sys_renameat2
317 common seccomp sys_seccomp
318 common getrandom sys_getrandom
319 common memfd_create sys_memfd_create
320 common kexec_file_load sys_kexec_file_load
321 common bpf sys_bpf
322 64 execveat sys_execveat/ptregs
323 common userfaultfd sys_userfaultfd
324 common membarrier sys_membarrier
325 common mlock2 sys_mlock2
326 common copy_file_range sys_copy_file_range
327 64 preadv2 sys_preadv2
328 64 pwritev2 sys_pwritev2
329 common pkey_mprotect sys_pkey_mprotect
330 common pkey_alloc sys_pkey_alloc
331 common pkey_free sys_pkey_free
332 common statx sys_statx
#
# x32-specific system call numbers start at 512 to avoid cache impact
# for native 64-bit operation.
#
512 x32 rt_sigaction compat_sys_rt_sigaction
513 x32 rt_sigreturn sys32_x32_rt_sigreturn
514 x32 ioctl compat_sys_ioctl
515 x32 readv compat_sys_readv
516 x32 writev compat_sys_writev
517 x32 recvfrom compat_sys_recvfrom
518 x32 sendmsg compat_sys_sendmsg
519 x32 recvmsg compat_sys_recvmsg
520 x32 execve compat_sys_execve/ptregs
521 x32 ptrace compat_sys_ptrace
522 x32 rt_sigpending compat_sys_rt_sigpending
523 x32 rt_sigtimedwait compat_sys_rt_sigtimedwait
524 x32 rt_sigqueueinfo compat_sys_rt_sigqueueinfo
525 x32 sigaltstack compat_sys_sigaltstack
526 x32 timer_create compat_sys_timer_create
527 x32 mq_notify compat_sys_mq_notify
528 x32 kexec_load compat_sys_kexec_load
529 x32 waitid compat_sys_waitid
530 x32 set_robust_list compat_sys_set_robust_list
531 x32 get_robust_list compat_sys_get_robust_list
532 x32 vmsplice compat_sys_vmsplice
533 x32 move_pages compat_sys_move_pages
534 x32 preadv compat_sys_preadv64
535 x32 pwritev compat_sys_pwritev64
536 x32 rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo
537 x32 recvmmsg compat_sys_recvmmsg
538 x32 sendmmsg compat_sys_sendmmsg
539 x32 process_vm_readv compat_sys_process_vm_readv
540 x32 process_vm_writev compat_sys_process_vm_writev
541 x32 setsockopt compat_sys_setsockopt
542 x32 getsockopt compat_sys_getsockopt
543 x32 io_setup compat_sys_io_setup
544 x32 io_submit compat_sys_io_submit
545 x32 execveat compat_sys_execveat/ptregs
546 x32 preadv2 compat_sys_preadv64v2
547 x32 pwritev2 compat_sys_pwritev64v2

2
user

@ -1 +1 @@
Subproject commit fdaa1be8635944d88ff128da13bf0464f7ce2eb6
Subproject commit 8dbc0edb935a62d748aaac39258d4a985de0ae17