mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-22 16:16:16 +04:00
Merge branch 'dev'
This commit is contained in:
commit
4c2839d95d
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,6 +1,3 @@
|
|||||||
[submodule "riscv-pk"]
|
|
||||||
path = riscv-pk
|
|
||||||
url = https://github.com/rcore-os/riscv-pk.git
|
|
||||||
[submodule "user"]
|
[submodule "user"]
|
||||||
path = user
|
path = user
|
||||||
url = https://github.com/rcore-os/rcore-user.git
|
url = https://github.com/rcore-os/rcore-user.git
|
||||||
|
@ -56,7 +56,9 @@ impl MemoryArea {
|
|||||||
}
|
}
|
||||||
/// Check the array is within the readable memory
|
/// Check the array is within the readable memory
|
||||||
fn check_read_array<S>(&self, ptr: *const S, count: usize) -> bool {
|
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
|
/// Check the array is within the writable memory
|
||||||
fn check_write_array<S>(&self, ptr: *mut S, count: usize) -> bool {
|
fn check_write_array<S>(&self, ptr: *mut S, count: usize) -> bool {
|
||||||
|
31
kernel/Cargo.lock
generated
31
kernel/Cargo.lock
generated
@ -393,21 +393,21 @@ dependencies = [
|
|||||||
"riscv 0.5.0 (git+https://github.com/rcore-os/riscv)",
|
"riscv 0.5.0 (git+https://github.com/rcore-os/riscv)",
|
||||||
"smoltcp 0.5.0 (git+https://github.com/rcore-os/smoltcp)",
|
"smoltcp 0.5.0 (git+https://github.com/rcore-os/smoltcp)",
|
||||||
"spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rcore-fs"
|
name = "rcore-fs"
|
||||||
version = "0.1.0"
|
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]]
|
[[package]]
|
||||||
name = "rcore-fs-sfs"
|
name = "rcore-fs-sfs"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"bitvec 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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]]
|
[[package]]
|
||||||
name = "uart_16550"
|
name = "uart_16550"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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]]
|
[[package]]
|
||||||
@ -615,18 +615,6 @@ dependencies = [
|
|||||||
"raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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]]
|
[[package]]
|
||||||
name = "x86_64"
|
name = "x86_64"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
@ -642,7 +630,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "x86_64"
|
name = "x86_64"
|
||||||
version = "0.5.3"
|
version = "0.5.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"array-init 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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 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 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 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-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 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"
|
"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-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 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 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.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 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"
|
"checksum zero 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f1bc8a6b2005884962297587045002d8cfb8dcec9db332f4ca216ddc5de82c5"
|
||||||
|
@ -19,6 +19,7 @@ authors = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
default = ["sv39"]
|
||||||
# Page table sv39 or sv48 (for riscv64)
|
# Page table sv39 or sv48 (for riscv64)
|
||||||
sv39 = []
|
sv39 = []
|
||||||
board_u540 = ["sv39", "link_user"]
|
board_u540 = ["sv39", "link_user"]
|
||||||
@ -31,6 +32,8 @@ board_malta = ["link_user"]
|
|||||||
board_mipssim = ["link_user"]
|
board_mipssim = ["link_user"]
|
||||||
# for thinpad
|
# for thinpad
|
||||||
board_thinpad = ["link_user"]
|
board_thinpad = ["link_user"]
|
||||||
|
# for x86 PC
|
||||||
|
board_pc = ["link_user"]
|
||||||
# Hard link user program
|
# Hard link user program
|
||||||
link_user = []
|
link_user = []
|
||||||
# Run cmdline instead of user shell, useful for automatic testing
|
# 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" }
|
apic = { git = "https://github.com/rcore-os/apic-rs" }
|
||||||
x86_64 = "0.5"
|
x86_64 = "0.5"
|
||||||
raw-cpuid = "6.0"
|
raw-cpuid = "6.0"
|
||||||
uart_16550 = "0.1"
|
uart_16550 = "0.2"
|
||||||
pc-keyboard = "0.5"
|
pc-keyboard = "0.5"
|
||||||
|
|
||||||
[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies]
|
[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies]
|
||||||
|
@ -33,8 +33,8 @@
|
|||||||
|
|
||||||
arch ?= riscv64
|
arch ?= riscv64
|
||||||
board ?= none
|
board ?= none
|
||||||
mode ?= debug
|
mode ?= release
|
||||||
LOG ?= debug
|
LOG ?=
|
||||||
graphic ?= off
|
graphic ?= off
|
||||||
smp ?= 4
|
smp ?= 4
|
||||||
pci_passthru ?=
|
pci_passthru ?=
|
||||||
@ -58,16 +58,13 @@ ifeq ($(arch), $(filter $(arch), aarch64 mipsel))
|
|||||||
#link user img, so use original image
|
#link user img, so use original image
|
||||||
export SFSIMG = $(user_dir)/build/$(arch).img
|
export SFSIMG = $(user_dir)/build/$(arch).img
|
||||||
else
|
else
|
||||||
ifeq ($(arch), x86_64)
|
|
||||||
# board is pc or qemu?
|
# board is pc or qemu?
|
||||||
ifeq ($(board), pc)
|
ifeq ($(board), pc)
|
||||||
#link user img, so use original image
|
#link user img, so use original image
|
||||||
export SFSIMG = $(user_dir)/build/$(arch).img
|
export SFSIMG = $(user_dir)/build/$(arch).img
|
||||||
features += link_user
|
|
||||||
else
|
else
|
||||||
export SFSIMG = $(user_dir)/build/$(arch).qcow2
|
export SFSIMG = $(user_dir)/build/$(arch).qcow2
|
||||||
endif # pc or qemu
|
endif # pc or qemu
|
||||||
endif # x86_64
|
|
||||||
endif # aarch64 mipsel
|
endif # aarch64 mipsel
|
||||||
|
|
||||||
ifeq ($(arch), aarch64)
|
ifeq ($(arch), aarch64)
|
||||||
@ -98,17 +95,16 @@ qemu_net_opts :=
|
|||||||
|
|
||||||
ifeq ($(arch), x86_64)
|
ifeq ($(arch), x86_64)
|
||||||
qemu_opts += \
|
qemu_opts += \
|
||||||
-drive format=raw,file=$(bootimage)
|
-drive format=raw,file=$(bootimage) \
|
||||||
|
-serial mon:stdio \
|
||||||
|
-m 4G \
|
||||||
|
-device isa-debug-exit
|
||||||
ifeq ($(board), none)
|
ifeq ($(board), none)
|
||||||
qemu_opts += \
|
qemu_opts += \
|
||||||
-drive format=qcow2,file=$(SFSIMG),media=disk,cache=writeback,id=sfsimg,if=none \
|
-drive format=qcow2,file=$(SFSIMG),media=disk,cache=writeback,id=sfsimg,if=none \
|
||||||
-device ahci,id=ahci0 \
|
-device ahci,id=ahci0 \
|
||||||
-device ide-drive,drive=sfsimg,bus=ahci0.0
|
-device ide-drive,drive=sfsimg,bus=ahci0.0
|
||||||
endif
|
endif
|
||||||
qemu_opts += \
|
|
||||||
-serial mon:stdio \
|
|
||||||
-m 4G \
|
|
||||||
-device isa-debug-exit
|
|
||||||
ifeq ($(pci_passthru), )
|
ifeq ($(pci_passthru), )
|
||||||
qemu_net_opts += \
|
qemu_net_opts += \
|
||||||
-netdev type=tap,id=net0,script=no,downscript=no \
|
-netdev type=tap,id=net0,script=no,downscript=no \
|
||||||
@ -128,7 +124,8 @@ endif
|
|||||||
else ifeq ($(arch), riscv32)
|
else ifeq ($(arch), riscv32)
|
||||||
qemu_opts += \
|
qemu_opts += \
|
||||||
-machine virt \
|
-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 \
|
-drive file=$(SFSIMG),format=qcow2,id=sfs \
|
||||||
-device virtio-blk-device,drive=sfs
|
-device virtio-blk-device,drive=sfs
|
||||||
qemu_net_opts += \
|
qemu_net_opts += \
|
||||||
@ -136,11 +133,19 @@ qemu_net_opts += \
|
|||||||
-device virtio-net-device,netdev=net0
|
-device virtio-net-device,netdev=net0
|
||||||
|
|
||||||
else ifeq ($(arch), riscv64)
|
else ifeq ($(arch), riscv64)
|
||||||
|
ifeq ($(board), u540)
|
||||||
qemu_opts += \
|
qemu_opts += \
|
||||||
-machine virt \
|
-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 \
|
-drive file=$(SFSIMG),format=qcow2,id=sfs \
|
||||||
-device virtio-blk-device,drive=sfs
|
-device virtio-blk-device,drive=sfs
|
||||||
|
endif
|
||||||
qemu_net_opts += \
|
qemu_net_opts += \
|
||||||
-netdev type=tap,id=net0,script=no,downscript=no \
|
-netdev type=tap,id=net0,script=no,downscript=no \
|
||||||
-device virtio-net-device,netdev=net0
|
-device virtio-net-device,netdev=net0
|
||||||
@ -201,11 +206,9 @@ features += sv39
|
|||||||
riscv_pk_args += --enable-sv39
|
riscv_pk_args += --enable-sv39
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(arch), x86_64)
|
|
||||||
ifneq ($(board), none)
|
ifneq ($(board), none)
|
||||||
features += board_$(board)
|
features += board_$(board)
|
||||||
endif
|
endif
|
||||||
endif
|
|
||||||
|
|
||||||
build_args := --target targets/$(target).json --features "$(features)"
|
build_args := --target targets/$(target).json --features "$(features)"
|
||||||
|
|
||||||
@ -303,28 +306,8 @@ ifeq ($(need_bootloader), true)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
$(kernel_img): kernel $(bootloader)
|
$(kernel_img): kernel $(bootloader)
|
||||||
ifeq ($(arch), riscv32)
|
ifeq ($(arch), $(filter $(arch), riscv32 riscv64))
|
||||||
@mkdir -p target/$(target)/bbl && \
|
@$(objcopy) $(kernel) --strip-all -O binary $@
|
||||||
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 $@)
|
|
||||||
else ifeq ($(arch), aarch64)
|
else ifeq ($(arch), aarch64)
|
||||||
ifneq ($(u_boot), )
|
ifneq ($(u_boot), )
|
||||||
@cp $(u_boot) $@
|
@cp $(u_boot) $@
|
||||||
@ -341,13 +324,7 @@ kernel: $(dtb)
|
|||||||
ifeq ($(arch), x86_64)
|
ifeq ($(arch), x86_64)
|
||||||
@bootimage build $(build_args)
|
@bootimage build $(build_args)
|
||||||
@mv target/x86_64/bootimage.bin $(bootimage)
|
@mv target/x86_64/bootimage.bin $(bootimage)
|
||||||
else ifeq ($(arch), riscv32)
|
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
|
|
||||||
@cargo xbuild $(build_args)
|
|
||||||
else ifeq ($(arch), riscv64)
|
|
||||||
@cp src/arch/riscv32/board/u540/linker.ld src/arch/riscv32/boot/linker64.ld
|
|
||||||
@-patch -p0 -N -b \
|
@-patch -p0 -N -b \
|
||||||
$(shell rustc --print sysroot)/lib/rustlib/src/rust/src/libcore/sync/atomic.rs \
|
$(shell rustc --print sysroot)/lib/rustlib/src/rust/src/libcore/sync/atomic.rs \
|
||||||
src/arch/riscv32/atomic.patch
|
src/arch/riscv32/atomic.patch
|
||||||
@ -389,7 +366,8 @@ endif
|
|||||||
ifeq ($(board), u540)
|
ifeq ($(board), u540)
|
||||||
.PHONY:
|
.PHONY:
|
||||||
install: $(kernel_img)
|
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
|
@../tools/u540/mkimg.sh $(build_path)/bin $(build_path)/sd.img
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
virtqueue_pop
|
|
||||||
virtio_blk_req_complete
|
|
||||||
virtio_blk_rw_complete
|
|
||||||
virtio_blk_submit_multireq
|
|
||||||
virtio_blk_handle_write
|
|
||||||
virtio_blk_handle_read
|
|
||||||
e1000e_link_status
|
|
||||||
e1000e_mac_set_sw
|
|
||||||
e1000e_irq_itr_set
|
|
||||||
e1000e_irq_eitr_set
|
|
||||||
e1000e_tx_disabled
|
|
||||||
e1000e_tx_descr
|
|
||||||
e1000e_rx_descr
|
|
||||||
#e1000e_rx_has_buffers
|
|
||||||
e1000e_rx_start_recv
|
|
||||||
#e1000e_rx_can_recv
|
|
||||||
e1000e_rx_can_recv_rings_full
|
|
||||||
e1000_receiver_overrun
|
|
||||||
#e1000e_rx_receive_iov
|
|
||||||
e1000e_core_ctrl_sw_reset
|
|
||||||
e1000e_core_ctrl_phy_reset
|
|
||||||
e1000e_rx_desc_buff_sizes
|
|
||||||
e1000e_rx_set_rctl
|
|
||||||
e1000e_rx_desc_len
|
|
||||||
e1000e_core_ctrl_write
|
|
||||||
e1000e_link_status_changed
|
|
||||||
e1000e_rx_rss_dispatched_to_queue
|
|
||||||
e1000e_rx_desc_buff_write
|
|
||||||
e1000e_rx_null_descriptor
|
|
||||||
e1000e_rx_set_rdt
|
|
||||||
e1000e_msix_use_vector_fail
|
|
||||||
e1000e_msix_init_fail
|
|
||||||
e1000e_msi_init_fail
|
|
||||||
e1000e_cb_pci_uninit
|
|
||||||
e1000e_cfg_support_virtio
|
|
||||||
e1000e_irq_msi_notify_postponed
|
|
||||||
e1000e_irq_msix_notify_postponed_vec
|
|
||||||
e1000e_irq_throttling_no_pending_vec
|
|
||||||
e1000e_irq_msix_notify_vec
|
|
||||||
e1000e_wrn_msix_vec_wrong
|
|
||||||
e1000e_wrn_msix_invalid
|
|
||||||
e1000e_irq_iam_clear_eiame
|
|
||||||
e1000e_irq_icr_clear_eiac
|
|
||||||
e1000e_irq_msi_notify
|
|
||||||
pci_update_mappings_del
|
|
||||||
pci_update_mappings_add
|
|
||||||
e1000e_irq_icr_write
|
|
||||||
e1000e_irq_icr_read_entry
|
|
||||||
e1000e_irq_legacy_notify
|
|
||||||
e1000e_irq_add_msi_other
|
|
||||||
e1000e_irq_pending_interrupts
|
|
||||||
e1000e_irq_icr_write
|
|
||||||
e1000e_irq_msix_notify_vec
|
|
||||||
e1000e_wrn_msix_vec_wrong
|
|
||||||
e1000e_wrn_msix_invalid
|
|
||||||
e1000e_irq_iam_clear_eiame
|
|
||||||
e1000e_irq_icr_clear_eiac
|
|
||||||
e1000e_irq_postponed_by_xitr
|
|
||||||
e1000e_intrmgr_rearm_timer
|
|
||||||
msix_*
|
|
||||||
#ahci_*
|
|
||||||
ide_*
|
|
@ -7,22 +7,23 @@
|
|||||||
.globl switch_context
|
.globl switch_context
|
||||||
.extern _root_page_table_ptr
|
.extern _root_page_table_ptr
|
||||||
.extern _cur_kstack_ptr
|
.extern _cur_kstack_ptr
|
||||||
|
.extern _cur_tls
|
||||||
|
|
||||||
switch_context:
|
switch_context:
|
||||||
// save from's registers
|
// save from's registers
|
||||||
addi sp, sp, (-4*14)
|
addi sp, sp, (-4*14)
|
||||||
sw sp, 0(a0)
|
sw sp, 0(a0)
|
||||||
sw ra, 0(sp)
|
sw ra, 0(sp)
|
||||||
sw s0, 2*4(sp)
|
sw s0, 4*4(sp)
|
||||||
sw s1, 3*4(sp)
|
sw s1, 5*4(sp)
|
||||||
sw s2, 4*4(sp)
|
sw s2, 6*4(sp)
|
||||||
sw s3, 5*4(sp)
|
sw s3, 7*4(sp)
|
||||||
sw s4, 6*4(sp)
|
sw s4, 8*4(sp)
|
||||||
sw s5, 7*4(sp)
|
sw s5, 9*4(sp)
|
||||||
sw s6, 8*4(sp)
|
sw s6, 10*4(sp)
|
||||||
sw s7, 9*4(sp)
|
sw s7, 11*4(sp)
|
||||||
sw s8, 10*4(sp)
|
sw s8, 12*4(sp)
|
||||||
sw gp, 11*4(sp)
|
sw gp, 13*4(sp)
|
||||||
// sw ra, 12*4(sp)
|
// sw ra, 12*4(sp)
|
||||||
// sw sp, 13*4(sp)
|
// sw sp, 13*4(sp)
|
||||||
|
|
||||||
@ -31,27 +32,34 @@ switch_context:
|
|||||||
lw s1, 0(s0)
|
lw s1, 0(s0)
|
||||||
sw s1, 4(sp)
|
sw s1, 4(sp)
|
||||||
|
|
||||||
|
// save TLS
|
||||||
|
la s2, _cur_tls
|
||||||
|
lw s1, 0(s2)
|
||||||
|
sw s1, 2*4(sp)
|
||||||
|
|
||||||
// restore to's registers
|
// restore to's registers
|
||||||
lw sp, 0(a1)
|
lw sp, 0(a1)
|
||||||
|
|
||||||
|
// restore page table address
|
||||||
lw s1, 4(sp)
|
lw s1, 4(sp)
|
||||||
sw s1, 0(s0)
|
sw s1, 0(s0)
|
||||||
|
|
||||||
// restore kstack ptr
|
// restore TLS
|
||||||
// la s0, _cur_kstack_ptr
|
lw s1, 2*4(sp)
|
||||||
// addi s1, sp, 4 * 14
|
sw s1, 0(s2)
|
||||||
// sw s1, 0(s0)
|
mtc0 s1, $4, 2 // cp0.user_local
|
||||||
|
|
||||||
lw ra, 0(sp)
|
lw ra, 0(sp)
|
||||||
lw s0, 2*4(sp)
|
lw s0, 4*4(sp)
|
||||||
lw s1, 3*4(sp)
|
lw s1, 5*4(sp)
|
||||||
lw s2, 4*4(sp)
|
lw s2, 6*4(sp)
|
||||||
lw s3, 5*4(sp)
|
lw s3, 7*4(sp)
|
||||||
lw s4, 6*4(sp)
|
lw s4, 8*4(sp)
|
||||||
lw s5, 7*4(sp)
|
lw s5, 9*4(sp)
|
||||||
lw s6, 8*4(sp)
|
lw s6, 10*4(sp)
|
||||||
lw s7, 9*4(sp)
|
lw s7, 11*4(sp)
|
||||||
lw s8, 10*4(sp)
|
lw s8, 12*4(sp)
|
||||||
lw gp, 11*4(sp)
|
lw gp, 13*4(sp)
|
||||||
addi sp, sp, (4*14)
|
addi sp, sp, (4*14)
|
||||||
|
|
||||||
sw zero, 0(a1)
|
sw zero, 0(a1)
|
||||||
|
@ -177,3 +177,6 @@ _root_page_table_ptr:
|
|||||||
.global _cur_kstack_ptr
|
.global _cur_kstack_ptr
|
||||||
_cur_kstack_ptr:
|
_cur_kstack_ptr:
|
||||||
.space 4 # 4bytes
|
.space 4 # 4bytes
|
||||||
|
.global _cur_tls
|
||||||
|
_cur_tls:
|
||||||
|
.space 4 # 4bytes
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
//! Workaround for missing compiler-builtin symbols
|
|
||||||
//!
|
|
||||||
//! [atomic](http://llvm.org/docs/Atomics.html#libcalls-atomic)
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn abort() {
|
|
||||||
panic!("abort");
|
|
||||||
}
|
|
@ -6,7 +6,8 @@ pub const KERNEL_OFFSET: usize = 0x80100000;
|
|||||||
|
|
||||||
pub const MEMORY_OFFSET: usize = 0x8000_0000;
|
pub const MEMORY_OFFSET: usize = 0x8000_0000;
|
||||||
|
|
||||||
pub const USER_STACK_OFFSET: usize = 0x80000000 - USER_STACK_SIZE;
|
pub const USER_STACK_OFFSET: usize = 0x70000000 - USER_STACK_SIZE;
|
||||||
pub const USER_STACK_SIZE: usize = 0x10000;
|
pub const USER_STACK_SIZE: usize = 0x10000;
|
||||||
|
pub const USER32_STACK_OFFSET: usize = 0x70000000 - USER_STACK_SIZE;
|
||||||
|
|
||||||
pub const MAX_DTB_SIZE: usize = 0x2000;
|
pub const MAX_DTB_SIZE: usize = 0x2000;
|
||||||
|
@ -50,8 +50,8 @@ pub struct TrapFrame {
|
|||||||
pub sp: usize,
|
pub sp: usize,
|
||||||
pub fp: usize,
|
pub fp: usize,
|
||||||
pub ra: usize,
|
pub ra: usize,
|
||||||
/// Reserve space for hartid
|
/// Reserved
|
||||||
pub _hartid: usize,
|
pub reserved: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TrapFrame {
|
impl TrapFrame {
|
||||||
@ -120,6 +120,7 @@ impl InitStack {
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn trap_return();
|
fn trap_return();
|
||||||
|
fn _cur_tls();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Saved registers for kernel context switches.
|
/// Saved registers for kernel context switches.
|
||||||
@ -130,17 +131,21 @@ struct ContextData {
|
|||||||
ra: usize,
|
ra: usize,
|
||||||
/// Page table token
|
/// Page table token
|
||||||
satp: usize,
|
satp: usize,
|
||||||
/// Callee-saved registers
|
/// s[0] = TLS
|
||||||
|
/// s[1] = reserved
|
||||||
|
/// s[2..11] = Callee-saved registers
|
||||||
s: [usize; 12],
|
s: [usize; 12],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContextData {
|
impl ContextData {
|
||||||
fn new(satp: usize) -> Self {
|
fn new(satp: usize, tls: usize) -> Self {
|
||||||
ContextData {
|
let mut context = ContextData {
|
||||||
ra: trap_return as usize,
|
ra: trap_return as usize,
|
||||||
satp,
|
satp: satp,
|
||||||
..ContextData::default()
|
..ContextData::default()
|
||||||
}
|
};
|
||||||
|
context.s[0] = tls;
|
||||||
|
context
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +196,7 @@ impl Context {
|
|||||||
);
|
);
|
||||||
|
|
||||||
InitStack {
|
InitStack {
|
||||||
context: ContextData::new(satp),
|
context: ContextData::new(satp, 0),
|
||||||
tf: TrapFrame::new_kernel_thread(entry, arg, kstack_top),
|
tf: TrapFrame::new_kernel_thread(entry, arg, kstack_top),
|
||||||
}
|
}
|
||||||
.push_at(kstack_top)
|
.push_at(kstack_top)
|
||||||
@ -214,7 +219,7 @@ impl Context {
|
|||||||
);
|
);
|
||||||
|
|
||||||
InitStack {
|
InitStack {
|
||||||
context: ContextData::new(satp),
|
context: ContextData::new(satp, 0),
|
||||||
tf: TrapFrame::new_user_thread(entry_addr, ustack_top),
|
tf: TrapFrame::new_user_thread(entry_addr, ustack_top),
|
||||||
}
|
}
|
||||||
.push_at(kstack_top)
|
.push_at(kstack_top)
|
||||||
@ -226,8 +231,9 @@ impl Context {
|
|||||||
/// The SATP register will be set to `satp`.
|
/// The SATP register will be set to `satp`.
|
||||||
/// All the other registers are same as the original.
|
/// All the other registers are same as the original.
|
||||||
pub unsafe fn new_fork(tf: &TrapFrame, kstack_top: usize, satp: usize) -> Self {
|
pub unsafe fn new_fork(tf: &TrapFrame, kstack_top: usize, satp: usize) -> Self {
|
||||||
|
let tls = unsafe { *(_cur_tls as *const usize) };
|
||||||
InitStack {
|
InitStack {
|
||||||
context: ContextData::new(satp),
|
context: ContextData::new(satp, tls),
|
||||||
tf: {
|
tf: {
|
||||||
let mut tf = tf.clone();
|
let mut tf = tf.clone();
|
||||||
// fork function's ret value, the new process is 0
|
// fork function's ret value, the new process is 0
|
||||||
@ -253,11 +259,10 @@ impl Context {
|
|||||||
tls: usize,
|
tls: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
InitStack {
|
InitStack {
|
||||||
context: ContextData::new(satp),
|
context: ContextData::new(satp, tls),
|
||||||
tf: {
|
tf: {
|
||||||
let mut tf = tf.clone();
|
let mut tf = tf.clone();
|
||||||
tf.sp = ustack_top; // sp
|
tf.sp = ustack_top; // sp
|
||||||
tf.v1 = tls;
|
|
||||||
tf.v0 = 0; // return value
|
tf.v0 = 0; // return value
|
||||||
tf
|
tf
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
use mips::registers::cp0;
|
||||||
|
use mips::instructions;
|
||||||
use crate::consts::MAX_CPU_NUM;
|
use crate::consts::MAX_CPU_NUM;
|
||||||
use core::ptr::{read_volatile, write_volatile};
|
use core::ptr::{read_volatile, write_volatile};
|
||||||
use mips::registers::cp0;
|
|
||||||
|
|
||||||
static mut STARTED: [bool; MAX_CPU_NUM] = [false; MAX_CPU_NUM];
|
static mut STARTED: [bool; MAX_CPU_NUM] = [false; MAX_CPU_NUM];
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ pub unsafe fn start_others(hart_mask: usize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn halt() {
|
pub fn halt() {
|
||||||
/* nothing to do */
|
unsafe { instructions::wait(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn exit_in_qemu(error_code: u8) -> ! {
|
pub unsafe fn exit_in_qemu(error_code: u8) -> ! {
|
||||||
|
@ -70,6 +70,17 @@ pub extern "C" fn rust_trap(tf: &mut TrapFrame) {
|
|||||||
E::TLBModification => page_fault(tf),
|
E::TLBModification => page_fault(tf),
|
||||||
E::TLBLoadMiss => page_fault(tf),
|
E::TLBLoadMiss => page_fault(tf),
|
||||||
E::TLBStoreMiss => page_fault(tf),
|
E::TLBStoreMiss => page_fault(tf),
|
||||||
|
E::ReservedInstruction => {
|
||||||
|
if !reserved_inst(tf) {
|
||||||
|
error!("Unhandled Exception @ CPU{}: {:?} ", 0, tf.cause.cause());
|
||||||
|
crate::trap::error(tf)
|
||||||
|
} else {
|
||||||
|
tf.epc = tf.epc + 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
E::CoprocessorUnusable => {
|
||||||
|
tf.epc = tf.epc + 4;
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
error!("Unhandled Exception @ CPU{}: {:?} ", 0, tf.cause.cause());
|
error!("Unhandled Exception @ CPU{}: {:?} ", 0, tf.cause.cause());
|
||||||
crate::trap::error(tf)
|
crate::trap::error(tf)
|
||||||
@ -149,6 +160,79 @@ fn syscall(tf: &mut TrapFrame) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_trapframe_register(rt: usize, val: usize, tf: &mut TrapFrame) {
|
||||||
|
match rt {
|
||||||
|
1 => tf.at = val,
|
||||||
|
2 => tf.v0 = val,
|
||||||
|
3 => tf.v1 = val,
|
||||||
|
4 => tf.a0 = val,
|
||||||
|
5 => tf.a1 = val,
|
||||||
|
6 => tf.a2 = val,
|
||||||
|
7 => tf.a3 = val,
|
||||||
|
8 => tf.t0 = val,
|
||||||
|
9 => tf.t1 = val,
|
||||||
|
10 => tf.t2 = val,
|
||||||
|
11 => tf.t3 = val,
|
||||||
|
12 => tf.t4 = val,
|
||||||
|
13 => tf.t5 = val,
|
||||||
|
14 => tf.t6 = val,
|
||||||
|
15 => tf.t7 = val,
|
||||||
|
16 => tf.s0 = val,
|
||||||
|
17 => tf.s1 = val,
|
||||||
|
18 => tf.s2 = val,
|
||||||
|
19 => tf.s3 = val,
|
||||||
|
20 => tf.s4 = val,
|
||||||
|
21 => tf.s5 = val,
|
||||||
|
22 => tf.s6 = val,
|
||||||
|
23 => tf.s7 = val,
|
||||||
|
24 => tf.t8 = val,
|
||||||
|
25 => tf.t9 = val,
|
||||||
|
26 => tf.k0 = val,
|
||||||
|
27 => tf.k1 = val,
|
||||||
|
28 => tf.gp = val,
|
||||||
|
29 => tf.sp = val,
|
||||||
|
30 => tf.fp = val,
|
||||||
|
31 => tf.ra = val,
|
||||||
|
_ => {
|
||||||
|
error!("Unknown register {:?} ", rt);
|
||||||
|
crate::trap::error(tf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reserved_inst(tf: &mut TrapFrame) -> bool {
|
||||||
|
let inst = unsafe {
|
||||||
|
*(tf.epc as *const usize)
|
||||||
|
};
|
||||||
|
|
||||||
|
let opcode = inst >> 26;
|
||||||
|
let rt = (inst >> 16) & 0b11111;
|
||||||
|
let rd = (inst >> 11) & 0b11111;
|
||||||
|
let sel = (inst >> 6) & 0b111;
|
||||||
|
let format = inst & 0b111111;
|
||||||
|
|
||||||
|
if opcode == 0b011111 && format == 0b111011 {
|
||||||
|
// RDHWR
|
||||||
|
if rd == 29 && sel == 0 {
|
||||||
|
extern "C" {
|
||||||
|
fn _cur_tls();
|
||||||
|
}
|
||||||
|
|
||||||
|
let tls = unsafe {
|
||||||
|
*(_cur_tls as *const usize)
|
||||||
|
};
|
||||||
|
|
||||||
|
set_trapframe_register(rt, tls, tf);
|
||||||
|
info!("Read TLS by rdhdr {:x} to register {:?}", tls, rt);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn page_fault(tf: &mut TrapFrame) {
|
fn page_fault(tf: &mut TrapFrame) {
|
||||||
// TODO: set access/dirty bit
|
// TODO: set access/dirty bit
|
||||||
let addr = tf.vaddr;
|
let addr = tf.vaddr;
|
||||||
@ -164,6 +248,19 @@ fn page_fault(tf: &mut TrapFrame) {
|
|||||||
tlb_entry.entry_lo0.get_pfn() << 12,
|
tlb_entry.entry_lo0.get_pfn() << 12,
|
||||||
tlb_entry.entry_lo1.get_pfn() << 12
|
tlb_entry.entry_lo1.get_pfn() << 12
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let tlb_valid = if virt_addr.page_number() & 1 == 0 {
|
||||||
|
tlb_entry.entry_lo0.valid()
|
||||||
|
} else {
|
||||||
|
tlb_entry.entry_lo1.valid()
|
||||||
|
};
|
||||||
|
|
||||||
|
if !tlb_valid {
|
||||||
|
if !crate::memory::handle_page_fault(addr) {
|
||||||
|
crate::trap::error(tf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tlb::write_tlb_random(tlb_entry)
|
tlb::write_tlb_random(tlb_entry)
|
||||||
}
|
}
|
||||||
Err(()) => {
|
Err(()) => {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
pub mod compiler_rt;
|
|
||||||
pub mod consts;
|
pub mod consts;
|
||||||
pub mod cpu;
|
pub mod cpu;
|
||||||
pub mod driver;
|
pub mod driver;
|
||||||
|
@ -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 = .);
|
|
||||||
}
|
|
@ -4,7 +4,7 @@ use super::consts::KERNEL_OFFSET;
|
|||||||
pub unsafe fn init_external_interrupt() {
|
pub unsafe fn init_external_interrupt() {
|
||||||
const HART1_S_MODE_INTERRUPT_ENABLES: *mut u64 = (KERNEL_OFFSET + 0x0C00_2100) as *mut u64;
|
const HART1_S_MODE_INTERRUPT_ENABLES: *mut u64 = (KERNEL_OFFSET + 0x0C00_2100) as *mut u64;
|
||||||
const SERIAL: u64 = 4;
|
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
|
/// 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 =
|
const HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE: *mut u32 =
|
||||||
(KERNEL_OFFSET + 0x0C20_2004) as *mut u32;
|
(KERNEL_OFFSET + 0x0C20_2004) as *mut u32;
|
||||||
// claim
|
// claim
|
||||||
let source = HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE.read();
|
let source = HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE.read_volatile();
|
||||||
// complete
|
// 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);
|
||||||
}
|
}
|
||||||
|
18
kernel/src/arch/riscv32/board/virt/mod.rs
Normal file
18
kernel/src/arch/riscv32/board/virt/mod.rs
Normal 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);
|
||||||
|
}
|
@ -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:
|
|
55
kernel/src/arch/riscv32/boot/entry32.asm
Normal file
55
kernel/src/arch/riscv32/boot/entry32.asm
Normal 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
|
48
kernel/src/arch/riscv32/boot/entry64.asm
Normal file
48
kernel/src/arch/riscv32/boot/entry64.asm
Normal 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
|
@ -6,7 +6,7 @@
|
|||||||
OUTPUT_ARCH(riscv)
|
OUTPUT_ARCH(riscv)
|
||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
|
||||||
BASE_ADDRESS = 0xC0020000;
|
BASE_ADDRESS = 0xC0400000;
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
OUTPUT_ARCH(riscv)
|
OUTPUT_ARCH(riscv)
|
||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
|
||||||
BASE_ADDRESS = 0xffffffffc0020000;
|
BASE_ADDRESS = 0xffffffffc0200000;
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
|
@ -22,17 +22,11 @@ pub const KERNEL_P2_INDEX: usize = (KERNEL_OFFSET >> 12 >> 10) & 0x3ff;
|
|||||||
#[cfg(target_arch = "riscv64")]
|
#[cfg(target_arch = "riscv64")]
|
||||||
pub const KERNEL_P4_INDEX: usize = (KERNEL_OFFSET >> 12 >> 9 >> 9 >> 9) & 0o777;
|
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;
|
pub const MEMORY_OFFSET: usize = 0x8000_0000;
|
||||||
#[cfg(target_arch = "riscv64")]
|
// TODO: get memory end from device tree
|
||||||
pub const MEMORY_OFFSET: usize = 0x8000_0000;
|
pub const MEMORY_END: usize = 0x8800_0000;
|
||||||
|
|
||||||
#[cfg(target_arch = "riscv32")]
|
|
||||||
pub const MEMORY_END: usize = 0x8100_0000;
|
|
||||||
#[cfg(target_arch = "riscv64")]
|
|
||||||
pub const MEMORY_END: usize = 0x8100_0000;
|
|
||||||
|
|
||||||
// FIXME: rv64 `sh` and `ls` will crash if stack top > 0x80000000 ???
|
// FIXME: rv64 `sh` and `ls` will crash if stack top > 0x80000000 ???
|
||||||
pub const USER_STACK_OFFSET: usize = 0x80000000 - USER_STACK_SIZE;
|
pub const USER_STACK_OFFSET: usize = 0x80000000 - USER_STACK_SIZE;
|
||||||
|
@ -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) {
|
pub unsafe fn set_cpu_id(cpu_id: usize) {
|
||||||
asm!("mv gp, $0" : : "r"(cpu_id));
|
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);
|
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() {
|
pub fn halt() {
|
||||||
unsafe { riscv::asm::wfi() }
|
unsafe { riscv::asm::wfi() }
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,3 @@ pub fn getchar_option() -> Option<char> {
|
|||||||
pub fn putfmt(fmt: Arguments) {
|
pub fn putfmt(fmt: Arguments) {
|
||||||
SerialPort.write_fmt(fmt).unwrap();
|
SerialPort.write_fmt(fmt).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
const TXDATA: *mut u32 = 0x38000000 as *mut u32;
|
|
||||||
const RXDATA: *mut u32 = 0x38000004 as *mut u32;
|
|
||||||
|
@ -8,13 +8,17 @@ use riscv::{addr::*, register::sstatus};
|
|||||||
|
|
||||||
/// Initialize the memory management module
|
/// Initialize the memory management module
|
||||||
pub fn init(dtb: usize) {
|
pub fn init(dtb: usize) {
|
||||||
|
// allow user memory access
|
||||||
unsafe {
|
unsafe {
|
||||||
sstatus::set_sum();
|
sstatus::set_sum();
|
||||||
} // Allow user memory access
|
}
|
||||||
// initialize heap and Frame allocator
|
// initialize heap and Frame allocator
|
||||||
init_frame_allocator();
|
init_frame_allocator();
|
||||||
init_heap();
|
init_heap();
|
||||||
// remap the kernel use 4K page
|
// remap the kernel use 4K page
|
||||||
|
unsafe {
|
||||||
|
super::paging::setup_recursive_mapping();
|
||||||
|
}
|
||||||
remap_the_kernel(dtb);
|
remap_the_kernel(dtb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +97,7 @@ fn remap_the_kernel(dtb: usize) {
|
|||||||
Linear::new(offset),
|
Linear::new(offset),
|
||||||
"dts",
|
"dts",
|
||||||
);
|
);
|
||||||
// map PLIC for HiFiveU
|
// map PLIC for HiFiveU & VirtIO
|
||||||
let offset = -(KERNEL_OFFSET as isize);
|
let offset = -(KERNEL_OFFSET as isize);
|
||||||
ms.push(
|
ms.push(
|
||||||
KERNEL_OFFSET + 0x0C00_2000,
|
KERNEL_OFFSET + 0x0C00_2000,
|
||||||
@ -109,6 +113,22 @@ fn remap_the_kernel(dtb: usize) {
|
|||||||
Linear::new(offset),
|
Linear::new(offset),
|
||||||
"plic1",
|
"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 {
|
unsafe {
|
||||||
ms.activate();
|
ms.activate();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
#[cfg(feature = "board_u540")]
|
#[cfg(feature = "board_u540")]
|
||||||
#[path = "board/u540/mod.rs"]
|
#[path = "board/u540/mod.rs"]
|
||||||
mod board;
|
mod board;
|
||||||
|
#[cfg(not(feature = "board_u540"))]
|
||||||
|
#[path = "board/virt/mod.rs"]
|
||||||
|
mod board;
|
||||||
|
|
||||||
pub mod compiler_rt;
|
pub mod compiler_rt;
|
||||||
pub mod consts;
|
pub mod consts;
|
||||||
pub mod cpu;
|
pub mod cpu;
|
||||||
@ -13,19 +17,24 @@ mod sbi;
|
|||||||
pub mod syscall;
|
pub mod syscall;
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
|
|
||||||
|
use self::consts::{KERNEL_OFFSET, MEMORY_OFFSET};
|
||||||
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
use log::*;
|
use log::*;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn rust_main(hartid: usize, dtb: usize, hart_mask: usize) -> ! {
|
pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! {
|
||||||
// An initial recursive page table has been set by BBL (shared by all cores)
|
let device_tree_vaddr = device_tree_paddr - MEMORY_OFFSET + KERNEL_OFFSET;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
cpu::set_cpu_id(hartid);
|
cpu::set_cpu_id(hartid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if hartid != BOOT_HART_ID {
|
if hartid != BOOT_HART_ID {
|
||||||
while unsafe { !cpu::has_started(hartid) } {}
|
while !AP_CAN_INIT.load(Ordering::Relaxed) {}
|
||||||
println!("Hello RISCV! in hart {}, dtb @ {:#x}", hartid, dtb);
|
println!(
|
||||||
|
"Hello RISCV! in hart {}, device tree @ {:#x}",
|
||||||
|
hartid, device_tree_vaddr
|
||||||
|
);
|
||||||
others_main();
|
others_main();
|
||||||
//other_main -> !
|
//other_main -> !
|
||||||
}
|
}
|
||||||
@ -34,24 +43,25 @@ pub extern "C" fn rust_main(hartid: usize, dtb: usize, hart_mask: usize) -> ! {
|
|||||||
memory::clear_bss();
|
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();
|
crate::logging::init();
|
||||||
interrupt::init();
|
interrupt::init();
|
||||||
memory::init(dtb);
|
memory::init(device_tree_vaddr);
|
||||||
timer::init();
|
timer::init();
|
||||||
// FIXME: init driver on u540
|
// FIXME: init driver on u540
|
||||||
#[cfg(not(feature = "board_u540"))]
|
#[cfg(not(feature = "board_u540"))]
|
||||||
crate::drivers::init(dtb);
|
crate::drivers::init(device_tree_vaddr);
|
||||||
#[cfg(feature = "board_u540")]
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
board::enable_serial_interrupt();
|
||||||
board::init_external_interrupt();
|
board::init_external_interrupt();
|
||||||
}
|
}
|
||||||
crate::process::init();
|
crate::process::init();
|
||||||
|
|
||||||
unsafe {
|
AP_CAN_INIT.store(true, Ordering::Relaxed);
|
||||||
cpu::start_others(hart_mask);
|
|
||||||
}
|
|
||||||
crate::kmain();
|
crate::kmain();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +72,8 @@ fn others_main() -> ! {
|
|||||||
crate::kmain();
|
crate::kmain();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static AP_CAN_INIT: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
#[cfg(not(feature = "board_u540"))]
|
#[cfg(not(feature = "board_u540"))]
|
||||||
const BOOT_HART_ID: usize = 0;
|
const BOOT_HART_ID: usize = 0;
|
||||||
#[cfg(feature = "board_u540")]
|
#[cfg(feature = "board_u540")]
|
||||||
@ -94,6 +106,8 @@ global_asm!(
|
|||||||
.endm
|
.endm
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
#[cfg(target_arch = "riscv32")]
|
||||||
global_asm!(include_str!("boot/entry.asm"));
|
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"));
|
global_asm!(include_str!("boot/trap.asm"));
|
||||||
|
@ -198,7 +198,7 @@ impl InactivePageTable for InactivePageTable0 {
|
|||||||
fn start();
|
fn start();
|
||||||
fn end();
|
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_start = start as usize >> 22;
|
||||||
let entry_end = (end as usize >> 22) + 1;
|
let entry_end = (end as usize >> 22) + 1;
|
||||||
let entry_count = entry_end - entry_start;
|
let entry_count = entry_end - entry_start;
|
||||||
@ -299,3 +299,13 @@ impl FrameDeallocator for FrameAllocatorForRiscv {
|
|||||||
dealloc_frame(frame.start_address().as_usize());
|
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");
|
||||||
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
//! Port from sbi.h
|
//! Port from sbi.h
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
|
fn sbi_call(which: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
|
||||||
|
@ -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_OFFSET: usize = USER_GRANT_OFFSET + PML4_SIZE;
|
||||||
pub const USER_STACK_PML4: usize = (USER_STACK_OFFSET & PML4_MASK) / PML4_SIZE;
|
pub const USER_STACK_PML4: usize = (USER_STACK_OFFSET & PML4_MASK) / PML4_SIZE;
|
||||||
/// Size of user stack
|
/// 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
|
/// Offset to user sigstack
|
||||||
pub const USER_SIGSTACK_OFFSET: usize = USER_STACK_OFFSET + PML4_SIZE;
|
pub const USER_SIGSTACK_OFFSET: usize = USER_STACK_OFFSET + PML4_SIZE;
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// Copy from Redox
|
|
||||||
|
|
||||||
use once::*;
|
use once::*;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
use uart_16550::SerialPort;
|
use uart_16550::SerialPort;
|
||||||
@ -7,8 +5,8 @@ use x86_64::instructions::port::Port;
|
|||||||
|
|
||||||
use crate::arch::interrupt::{consts, enable_irq};
|
use crate::arch::interrupt::{consts, enable_irq};
|
||||||
|
|
||||||
pub static COM1: Mutex<SerialPort> = Mutex::new(SerialPort::new(0x3F8));
|
pub static COM1: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3F8) });
|
||||||
pub static COM2: Mutex<SerialPort> = Mutex::new(SerialPort::new(0x2F8));
|
pub static COM2: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x2F8) });
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
assert_has_not_been_called!("serial::init must be called only once");
|
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 {
|
fn receive(&mut self) -> u8 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ports = self as *mut _ as *mut [Port<u8>; 6];
|
let ports = self as *mut _ as *mut [Port<u8>; 6];
|
||||||
let _line_sts = &(*ports)[5];
|
|
||||||
let data = &(*ports)[0];
|
let data = &(*ports)[0];
|
||||||
data.read()
|
data.read()
|
||||||
}
|
}
|
||||||
|
@ -206,11 +206,11 @@ impl AsciiConsole for VgaWriter {
|
|||||||
CSI::CursorMove(dx, dy) => {
|
CSI::CursorMove(dx, dy) => {
|
||||||
let x = (self.pos.row.0 as i8 + dx).max(0) as u8;
|
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;
|
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) => {
|
CSI::CursorMoveLine(dx) => {
|
||||||
let x = (self.pos.row.0 as i8 + dx).max(0) as u8;
|
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();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -17,22 +17,19 @@ pub fn init() {
|
|||||||
|
|
||||||
static mut CPUS: [Option<Cpu>; MAX_CPU_NUM] = [
|
static mut CPUS: [Option<Cpu>; MAX_CPU_NUM] = [
|
||||||
// TODO: More elegant ?
|
// 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,
|
||||||
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 {
|
pub struct Cpu {
|
||||||
|
File diff suppressed because it is too large
Load Diff
BIN
kernel/src/drivers/console/fonts/font8x16_1bpp.raw
Normal file
BIN
kernel/src/drivers/console/fonts/font8x16_1bpp.raw
Normal file
Binary file not shown.
@ -113,7 +113,7 @@ impl FileHandle {
|
|||||||
self.inode.poll()
|
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)
|
self.inode.io_control(cmd, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ impl FileLike {
|
|||||||
}
|
}
|
||||||
pub fn ioctl(&mut self, request: usize, arg1: usize, arg2: usize, arg3: usize) -> SysResult {
|
pub fn ioctl(&mut self, request: usize, arg1: usize, arg2: usize, arg3: usize) -> SysResult {
|
||||||
match self {
|
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) => {
|
FileLike::Socket(socket) => {
|
||||||
socket.ioctl(request, arg1, arg2, arg3)?;
|
socket.ioctl(request, arg1, arg2, arg3)?;
|
||||||
}
|
}
|
||||||
|
@ -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 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 find(&self, _name: &str) -> Result<Arc<INode>> { Err(FsError::NotDir) }
|
||||||
fn get_entry(&self, _id: usize) -> Result<String> { 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 fs(&self) -> Arc<FileSystem> { unimplemented!() }
|
||||||
fn as_any_ref(&self) -> &Any { self }
|
fn as_any_ref(&self) -> &Any { self }
|
||||||
};
|
};
|
||||||
|
@ -20,8 +20,6 @@ impl Stdin {
|
|||||||
self.pushed.notify_one();
|
self.pushed.notify_one();
|
||||||
}
|
}
|
||||||
pub fn pop(&self) -> char {
|
pub fn pop(&self) -> char {
|
||||||
// QEMU v3.0 don't support M-mode external interrupt (bug?)
|
|
||||||
// So we have to use polling.
|
|
||||||
loop {
|
loop {
|
||||||
let ret = self.buf.lock().pop_front();
|
let ret = self.buf.lock().pop_front();
|
||||||
match ret {
|
match ret {
|
||||||
@ -43,6 +41,11 @@ lazy_static! {
|
|||||||
pub static ref STDOUT: Arc<Stdout> = Arc::new(Stdout::default());
|
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?
|
// TODO: better way to provide default impl?
|
||||||
macro_rules! impl_inode {
|
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 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 find(&self, _name: &str) -> Result<Arc<INode>> { Err(FsError::NotDir) }
|
||||||
fn get_entry(&self, _id: usize) -> Result<String> { 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 fs(&self) -> Arc<FileSystem> { unimplemented!() }
|
||||||
fn as_any_ref(&self) -> &Any { self }
|
fn as_any_ref(&self) -> &Any { self }
|
||||||
};
|
};
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#![feature(optin_builtin_traits)]
|
#![feature(optin_builtin_traits)]
|
||||||
#![feature(panic_info_message)]
|
#![feature(panic_info_message)]
|
||||||
#![feature(global_asm)]
|
#![feature(global_asm)]
|
||||||
|
#![deny(unused_must_use)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
// just keep it ...
|
// just keep it ...
|
||||||
|
@ -14,13 +14,12 @@ pub fn init() {
|
|||||||
static LOGGER: SimpleLogger = SimpleLogger;
|
static LOGGER: SimpleLogger = SimpleLogger;
|
||||||
log::set_logger(&LOGGER).unwrap();
|
log::set_logger(&LOGGER).unwrap();
|
||||||
log::set_max_level(match option_env!("LOG") {
|
log::set_max_level(match option_env!("LOG") {
|
||||||
Some("off") => LevelFilter::Off,
|
|
||||||
Some("error") => LevelFilter::Error,
|
Some("error") => LevelFilter::Error,
|
||||||
Some("warn") => LevelFilter::Warn,
|
Some("warn") => LevelFilter::Warn,
|
||||||
Some("info") => LevelFilter::Info,
|
Some("info") => LevelFilter::Info,
|
||||||
Some("debug") => LevelFilter::Debug,
|
Some("debug") => LevelFilter::Debug,
|
||||||
Some("trace") => LevelFilter::Trace,
|
Some("trace") => LevelFilter::Trace,
|
||||||
_ => LevelFilter::Warn,
|
_ => LevelFilter::Off,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@ pub type MemorySet = rcore_memory::memory_set::MemorySet<InactivePageTable0>;
|
|||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub type FrameAlloc = bitmap_allocator::BitAlloc16M;
|
pub type FrameAlloc = bitmap_allocator::BitAlloc16M;
|
||||||
|
|
||||||
// RISCV has 8M memory
|
// RISCV has 1G memory
|
||||||
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
#[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
|
// Raspberry Pi 3 has 1G memory
|
||||||
#[cfg(any(target_arch = "aarch64", target_arch = "mips"))]
|
#[cfg(any(target_arch = "aarch64", target_arch = "mips"))]
|
||||||
|
@ -5,7 +5,7 @@ use core::ptr::null;
|
|||||||
|
|
||||||
pub struct ProcInitInfo {
|
pub struct ProcInitInfo {
|
||||||
pub args: Vec<String>,
|
pub args: Vec<String>,
|
||||||
pub envs: BTreeMap<String, String>,
|
pub envs: Vec<String>,
|
||||||
pub auxv: BTreeMap<u8, usize>,
|
pub auxv: BTreeMap<u8, usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,10 +19,8 @@ impl ProcInitInfo {
|
|||||||
let envs: Vec<_> = self
|
let envs: Vec<_> = self
|
||||||
.envs
|
.envs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(key, value)| {
|
.map(|arg| {
|
||||||
writer.push_str(value.as_str());
|
writer.push_str(arg.as_str());
|
||||||
writer.push_slice(&[b"="]);
|
|
||||||
writer.push_slice(key.as_bytes());
|
|
||||||
writer.sp
|
writer.sp
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -27,38 +27,86 @@ pub fn init() {
|
|||||||
|
|
||||||
static PROCESSORS: [Processor; MAX_CPU_NUM] = [
|
static PROCESSORS: [Processor; MAX_CPU_NUM] = [
|
||||||
// TODO: More elegant ?
|
// TODO: More elegant ?
|
||||||
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(), 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(), Processor::new(), Processor::new(),
|
||||||
|
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
|
||||||
|
// Processor::new(), Processor::new(), Processor::new(), Processor::new(),
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Get current process
|
/// Get current process
|
||||||
|
@ -158,10 +158,12 @@ impl Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Make a new user process from ELF `data`
|
/// Make a new user process from ELF `data`
|
||||||
pub fn new_user<'a, Iter>(data: &[u8], args: Iter) -> Box<Thread>
|
pub fn new_user(
|
||||||
where
|
data: &[u8],
|
||||||
Iter: Iterator<Item = &'a str>,
|
exec_path: &str,
|
||||||
{
|
mut args: Vec<String>,
|
||||||
|
envs: Vec<String>,
|
||||||
|
) -> Box<Thread> {
|
||||||
// Parse ELF
|
// Parse ELF
|
||||||
let elf = ElfFile::new(data).expect("failed to read 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"),
|
_ => 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() {
|
if let Ok(loader_path) = elf.get_interpreter() {
|
||||||
// assuming absolute path
|
// assuming absolute path
|
||||||
if let Ok(inode) = crate::fs::ROOT_INODE.lookup_follow(loader_path, FOLLOW_MAX_DEPTH) {
|
if let Ok(inode) = crate::fs::ROOT_INODE.lookup_follow(loader_path, FOLLOW_MAX_DEPTH) {
|
||||||
if let Ok(buf) = inode.read_as_vec() {
|
if let Ok(buf) = inode.read_as_vec() {
|
||||||
debug!("using loader {}", &loader_path);
|
|
||||||
// Elf loader should not have INTERP
|
// Elf loader should not have INTERP
|
||||||
// No infinite loop
|
// No infinite loop
|
||||||
let mut new_args: Vec<&str> = args.collect();
|
args.insert(0, loader_path.into());
|
||||||
new_args.insert(0, loader_path);
|
args.insert(1, exec_path.into());
|
||||||
return Thread::new_user(buf.as_slice(), new_args.into_iter());
|
args.remove(2);
|
||||||
|
info!("loader args: {:?}", args);
|
||||||
|
return Thread::new_user(buf.as_slice(), exec_path, args, envs);
|
||||||
} else {
|
} else {
|
||||||
warn!("loader specified as {} but failed to read", &loader_path);
|
warn!("loader specified as {} but failed to read", &loader_path);
|
||||||
}
|
}
|
||||||
@ -211,8 +227,8 @@ impl Thread {
|
|||||||
|
|
||||||
// Make init info
|
// Make init info
|
||||||
let init_info = ProcInitInfo {
|
let init_info = ProcInitInfo {
|
||||||
args: args.map(|s| String::from(s)).collect(),
|
args,
|
||||||
envs: BTreeMap::new(),
|
envs,
|
||||||
auxv: {
|
auxv: {
|
||||||
let mut map = BTreeMap::new();
|
let mut map = BTreeMap::new();
|
||||||
if let Some(phdr_vaddr) = elf.get_phdr_vaddr() {
|
if let Some(phdr_vaddr) = elf.get_phdr_vaddr() {
|
||||||
@ -418,7 +434,7 @@ impl ElfExt for ElfFile<'_> {
|
|||||||
virt_addr + mem_size,
|
virt_addr + mem_size,
|
||||||
ph.flags().to_attr(),
|
ph.flags().to_attr(),
|
||||||
ByFrame::new(GlobalFrameAlloc),
|
ByFrame::new(GlobalFrameAlloc),
|
||||||
"",
|
"elf",
|
||||||
);
|
);
|
||||||
unsafe { ::core::slice::from_raw_parts_mut(virt_addr as *mut u8, mem_size) }
|
unsafe { ::core::slice::from_raw_parts_mut(virt_addr as *mut u8, mem_size) }
|
||||||
};
|
};
|
||||||
|
@ -8,11 +8,14 @@ use alloc::vec::Vec;
|
|||||||
|
|
||||||
#[cfg(not(feature = "run_cmdline"))]
|
#[cfg(not(feature = "run_cmdline"))]
|
||||||
pub fn run_user_shell() {
|
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();
|
let data = inode.read_as_vec().unwrap();
|
||||||
processor()
|
processor().manager().add(Thread::new_user(
|
||||||
.manager()
|
data.as_slice(),
|
||||||
.add(Thread::new_user(data.as_slice(), "sh".split(' ')));
|
"busybox",
|
||||||
|
vec!["busybox".into(), "sh".into()],
|
||||||
|
Vec::new(),
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
processor().manager().add(Thread::new_kernel(shell, 0));
|
processor().manager().add(Thread::new_kernel(shell, 0));
|
||||||
}
|
}
|
||||||
@ -23,9 +26,11 @@ pub fn run_user_shell() {
|
|||||||
let cmdline = CMDLINE.read();
|
let cmdline = CMDLINE.read();
|
||||||
let inode = ROOT_INODE.lookup(&cmdline).unwrap();
|
let inode = ROOT_INODE.lookup(&cmdline).unwrap();
|
||||||
let data = inode.read_as_vec().unwrap();
|
let data = inode.read_as_vec().unwrap();
|
||||||
processor()
|
processor().manager().add(Thread::new_user(
|
||||||
.manager()
|
data.as_slice(),
|
||||||
.add(Thread::new_user(data.as_slice(), cmdline.split(' ')));
|
cmdline.split(' ').map(|s| s.into()).collect(),
|
||||||
|
Vec::new(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub extern "C" fn shell(_arg: usize) -> ! {
|
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();
|
let name = cmd.trim().split(' ').next().unwrap();
|
||||||
if let Ok(file) = ROOT_INODE.lookup(name) {
|
if let Ok(file) = ROOT_INODE.lookup(name) {
|
||||||
let data = file.read_as_vec().unwrap();
|
let data = file.read_as_vec().unwrap();
|
||||||
let _pid = processor()
|
let _pid = processor().manager().add(Thread::new_user(
|
||||||
.manager()
|
data.as_slice(),
|
||||||
.add(Thread::new_user(data.as_slice(), cmd.split(' ')));
|
&cmd,
|
||||||
|
cmd.split(' ').map(|s| s.into()).collect(),
|
||||||
|
Vec::new(),
|
||||||
|
));
|
||||||
// TODO: wait until process exits, or use user land shell completely
|
// TODO: wait until process exits, or use user land shell completely
|
||||||
//unsafe { thread::JoinHandle::<()>::_of(pid) }.join().unwrap();
|
//unsafe { thread::JoinHandle::<()>::_of(pid) }.join().unwrap();
|
||||||
} else {
|
} else {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
use core::cell::UnsafeCell;
|
use core::cell::UnsafeCell;
|
||||||
use core::cmp::min;
|
use core::cmp::min;
|
||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
||||||
|
#[cfg(not(target_arch = "mips"))]
|
||||||
use rcore_fs::vfs::Timespec;
|
use rcore_fs::vfs::Timespec;
|
||||||
|
|
||||||
use crate::drivers::SOCKET_ACTIVITY;
|
use crate::drivers::SOCKET_ACTIVITY;
|
||||||
@ -66,12 +67,28 @@ pub fn sys_pwrite(fd: usize, base: *const u8, len: usize, offset: usize) -> SysR
|
|||||||
Ok(len)
|
Ok(len)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sys_poll(ufds: *mut PollFd, nfds: usize, timeout_msecs: usize) -> SysResult {
|
pub fn sys_ppoll(ufds: *mut PollFd, nfds: usize, timeout: *const TimeSpec) -> SysResult {
|
||||||
info!(
|
|
||||||
"poll: ufds: {:?}, nfds: {}, timeout_msecs: {:#x}",
|
|
||||||
ufds, nfds, timeout_msecs
|
|
||||||
);
|
|
||||||
let proc = process();
|
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)?;
|
proc.vm.check_write_array(ufds, nfds)?;
|
||||||
|
|
||||||
let polls = unsafe { slice::from_raw_parts_mut(ufds, nfds) };
|
let polls = unsafe { slice::from_raw_parts_mut(ufds, nfds) };
|
||||||
@ -209,11 +226,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 {
|
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();
|
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 iovs = IoVecs::check_and_new(iov_ptr, iov_count, &proc.vm, false)?;
|
||||||
|
|
||||||
let buf = iovs.read_all_to_vec();
|
let buf = iovs.read_all_to_vec();
|
||||||
@ -240,7 +260,7 @@ pub fn sys_openat(dir_fd: usize, path: *const u8, flags: usize, mode: usize) ->
|
|||||||
let inode = if flags.contains(OpenFlags::CREATE) {
|
let inode = if flags.contains(OpenFlags::CREATE) {
|
||||||
let (dir_path, file_name) = split_path(&path);
|
let (dir_path, file_name) = split_path(&path);
|
||||||
// relative to cwd
|
// 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) {
|
match dir_inode.find(file_name) {
|
||||||
Ok(file_inode) => {
|
Ok(file_inode) => {
|
||||||
if flags.contains(OpenFlags::EXCLUSIVE) {
|
if flags.contains(OpenFlags::EXCLUSIVE) {
|
||||||
@ -254,7 +274,7 @@ pub fn sys_openat(dir_fd: usize, path: *const u8, flags: usize, mode: usize) ->
|
|||||||
Err(e) => return Err(SysError::from(e)),
|
Err(e) => return Err(SysError::from(e)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
proc.lookup_inode_at(dir_fd, &path)?
|
proc.lookup_inode_at(dir_fd, &path, true)?
|
||||||
};
|
};
|
||||||
|
|
||||||
let fd = proc.get_free_fd();
|
let fd = proc.get_free_fd();
|
||||||
@ -284,10 +304,10 @@ pub fn sys_faccessat(dirfd: usize, path: *const u8, mode: usize, flags: usize) -
|
|||||||
// we trust pid 0 process
|
// we trust pid 0 process
|
||||||
info!(
|
info!(
|
||||||
"faccessat: dirfd: {}, path: {:?}, mode: {:#o}, flags: {:?}",
|
"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)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,8 +326,7 @@ pub fn sys_getcwd(buf: *mut u8, len: usize) -> SysResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult {
|
pub fn sys_lstat(path: *const u8, stat_ptr: *mut Stat) -> SysResult {
|
||||||
warn!("lstat is partial implemented as stat");
|
sys_fstatat(AT_FDCWD, path, stat_ptr, AtFlags::SYMLINK_NOFOLLOW.bits())
|
||||||
sys_stat(path, stat_ptr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sys_fstat(fd: usize, stat_ptr: *mut Stat) -> SysResult {
|
pub fn sys_fstat(fd: usize, stat_ptr: *mut Stat) -> SysResult {
|
||||||
@ -329,10 +348,10 @@ pub fn sys_fstatat(dirfd: usize, path: *const u8, stat_ptr: *mut Stat, flags: us
|
|||||||
let flags = AtFlags::from_bits_truncate(flags);
|
let flags = AtFlags::from_bits_truncate(flags);
|
||||||
info!(
|
info!(
|
||||||
"fstatat: dirfd: {}, path: {:?}, stat_ptr: {:?}, flags: {:?}",
|
"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()?);
|
let stat = Stat::from(inode.metadata()?);
|
||||||
unsafe {
|
unsafe {
|
||||||
stat_ptr.write(stat);
|
stat_ptr.write(stat);
|
||||||
@ -354,7 +373,7 @@ pub fn sys_readlinkat(dirfd: usize, path: *const u8, base: *mut u8, len: usize)
|
|||||||
proc.vm.check_write_array(base, len)?;
|
proc.vm.check_write_array(base, len)?;
|
||||||
info!("readlink: path: {:?}, base: {:?}, len: {}", path, 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 {
|
if inode.metadata()?.type_ == FileType::SymLink {
|
||||||
// TODO: recursive link resolution and loop detection
|
// TODO: recursive link resolution and loop detection
|
||||||
let mut slice = unsafe { slice::from_raw_parts_mut(base, len) };
|
let mut slice = unsafe { slice::from_raw_parts_mut(base, len) };
|
||||||
@ -472,12 +491,9 @@ pub fn sys_chdir(path: *const u8) -> SysResult {
|
|||||||
if path.len() > 0 {
|
if path.len() > 0 {
|
||||||
let cwd = match path.as_bytes()[0] {
|
let cwd = match path.as_bytes()[0] {
|
||||||
b'/' => String::from("/"),
|
b'/' => String::from("/"),
|
||||||
_ => proc.cwd.clone()
|
_ => proc.cwd.clone(),
|
||||||
};
|
};
|
||||||
let mut cwd_vec:Vec<_> =
|
let mut cwd_vec: Vec<_> = cwd.split("/").filter(|&x| x != "").collect();
|
||||||
cwd.split("/")
|
|
||||||
.filter(|&x| x != "")
|
|
||||||
.collect();
|
|
||||||
let path_split = path.split("/").filter(|&x| x != "");
|
let path_split = path.split("/").filter(|&x| x != "");
|
||||||
for seg in path_split {
|
for seg in path_split {
|
||||||
if seg == ".." {
|
if seg == ".." {
|
||||||
@ -515,13 +531,13 @@ pub fn sys_renameat(
|
|||||||
let newpath = unsafe { proc.vm.check_and_clone_cstr(newpath)? };
|
let newpath = unsafe { proc.vm.check_and_clone_cstr(newpath)? };
|
||||||
info!(
|
info!(
|
||||||
"renameat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}",
|
"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 (old_dir_path, old_file_name) = split_path(&oldpath);
|
||||||
let (new_dir_path, new_file_name) = split_path(&newpath);
|
let (new_dir_path, new_file_name) = split_path(&newpath);
|
||||||
let old_dir_inode = proc.lookup_inode_at(olddirfd, old_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)?;
|
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)?;
|
old_dir_inode.move_(old_file_name, &new_dir_inode, new_file_name)?;
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
@ -536,11 +552,11 @@ pub fn sys_mkdirat(dirfd: usize, path: *const u8, mode: usize) -> SysResult {
|
|||||||
// TODO: check pathname
|
// TODO: check pathname
|
||||||
info!(
|
info!(
|
||||||
"mkdirat: dirfd: {}, path: {:?}, mode: {:#o}",
|
"mkdirat: dirfd: {}, path: {:?}, mode: {:#o}",
|
||||||
dirfd, path, mode
|
dirfd as isize, path, mode
|
||||||
);
|
);
|
||||||
|
|
||||||
let (dir_path, file_name) = split_path(&path);
|
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() {
|
if inode.find(file_name).is_ok() {
|
||||||
return Err(SysError::EEXIST);
|
return Err(SysError::EEXIST);
|
||||||
}
|
}
|
||||||
@ -580,12 +596,12 @@ pub fn sys_linkat(
|
|||||||
let flags = AtFlags::from_bits_truncate(flags);
|
let flags = AtFlags::from_bits_truncate(flags);
|
||||||
info!(
|
info!(
|
||||||
"linkat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}, flags: {:?}",
|
"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 (new_dir_path, new_file_name) = split_path(&newpath);
|
||||||
let inode = proc.lookup_inode_at(olddirfd, &oldpath)?;
|
let inode = proc.lookup_inode_at(olddirfd, &oldpath, true)?;
|
||||||
let new_dir_inode = proc.lookup_inode_at(newdirfd, new_dir_path)?;
|
let new_dir_inode = proc.lookup_inode_at(newdirfd, new_dir_path, true)?;
|
||||||
new_dir_inode.link(new_file_name, &inode)?;
|
new_dir_inode.link(new_file_name, &inode)?;
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
@ -600,11 +616,11 @@ pub fn sys_unlinkat(dirfd: usize, path: *const u8, flags: usize) -> SysResult {
|
|||||||
let flags = AtFlags::from_bits_truncate(flags);
|
let flags = AtFlags::from_bits_truncate(flags);
|
||||||
info!(
|
info!(
|
||||||
"unlinkat: dirfd: {}, path: {:?}, flags: {:?}",
|
"unlinkat: dirfd: {}, path: {:?}, flags: {:?}",
|
||||||
dirfd, path, flags
|
dirfd as isize, path, flags
|
||||||
);
|
);
|
||||||
|
|
||||||
let (dir_path, file_name) = split_path(&path);
|
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)?;
|
let file_inode = dir_inode.find(file_name)?;
|
||||||
if file_inode.metadata()?.type_ == FileType::Dir {
|
if file_inode.metadata()?.type_ == FileType::Dir {
|
||||||
return Err(SysError::EISDIR);
|
return Err(SysError::EISDIR);
|
||||||
@ -647,8 +663,8 @@ pub fn sys_pipe(fds: *mut u32) -> SysResult {
|
|||||||
);
|
);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
*fds = read_fd as u32;
|
fds.write(read_fd as u32);
|
||||||
*(fds.add(1)) = write_fd as u32;
|
fds.add(1).write(write_fd as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("pipe: created rfd: {} wfd: {}", read_fd, write_fd);
|
info!("pipe: created rfd: {} wfd: {}", read_fd, write_fd);
|
||||||
@ -661,69 +677,60 @@ pub fn sys_sync() -> SysResult {
|
|||||||
Ok(0)
|
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!(
|
info!(
|
||||||
"sendfile: out: {}, in: {}, offset: {:?}, count: {}",
|
"sendfile: out: {}, in: {}, offset_ptr: {:?}, count: {}",
|
||||||
out_fd, in_fd, offset, count
|
out_fd, in_fd, offset_ptr, count
|
||||||
);
|
);
|
||||||
let proc = process();
|
let proc = process();
|
||||||
// We know it's save, pacify the borrow checker
|
// We know it's save, pacify the borrow checker
|
||||||
let proc_cell = UnsafeCell::new(proc);
|
let proc_cell = UnsafeCell::new(proc);
|
||||||
let proc_in = unsafe { &mut *proc_cell.get() };
|
let in_file = unsafe { (*proc_cell.get()).get_file(in_fd)? };
|
||||||
let proc_out = unsafe { &mut *proc_cell.get() };
|
let out_file = unsafe { (*proc_cell.get()).get_file(out_fd)? };
|
||||||
//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 mut buffer = [0u8; 1024];
|
let mut buffer = [0u8; 1024];
|
||||||
if offset.is_null() {
|
|
||||||
// read from current file offset
|
let mut read_offset = if !offset_ptr.is_null() {
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unsafe {
|
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 {
|
impl Process {
|
||||||
@ -751,12 +758,11 @@ impl Process {
|
|||||||
&self,
|
&self,
|
||||||
dirfd: usize,
|
dirfd: usize,
|
||||||
path: &str,
|
path: &str,
|
||||||
// follow: bool,
|
follow: bool,
|
||||||
) -> Result<Arc<INode>, SysError> {
|
) -> Result<Arc<INode>, SysError> {
|
||||||
let follow = true;
|
|
||||||
debug!(
|
debug!(
|
||||||
"lookup_inode_at: fd: {:?}, cwd: {:?}, path: {:?}, follow: {:?}",
|
"lookup_inode_at: dirfd: {:?}, cwd: {:?}, path: {:?}, follow: {:?}",
|
||||||
dirfd, self.cwd, path, follow
|
dirfd as isize, self.cwd, path, follow
|
||||||
);
|
);
|
||||||
let follow_max_depth = if follow { FOLLOW_MAX_DEPTH } else { 0 };
|
let follow_max_depth = if follow { FOLLOW_MAX_DEPTH } else { 0 };
|
||||||
if dirfd == AT_FDCWD {
|
if dirfd == AT_FDCWD {
|
||||||
@ -773,7 +779,7 @@ impl Process {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookup_inode(&self, path: &str) -> Result<Arc<INode>, SysError> {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -978,7 +984,55 @@ pub struct Stat {
|
|||||||
ctime: Timespec,
|
ctime: Timespec,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "x86_64"))]
|
#[cfg(target_arch = "mips")]
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||||
|
pub struct Timespec {
|
||||||
|
pub sec: i32,
|
||||||
|
pub nsec: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "mips")]
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Stat {
|
||||||
|
/// ID of device containing file
|
||||||
|
dev: u64,
|
||||||
|
/// padding
|
||||||
|
__pad1: u64,
|
||||||
|
/// inode number
|
||||||
|
ino: u64,
|
||||||
|
/// file type and mode
|
||||||
|
mode: StatMode,
|
||||||
|
/// number of hard links
|
||||||
|
nlink: u32,
|
||||||
|
|
||||||
|
/// user ID of owner
|
||||||
|
uid: u32,
|
||||||
|
/// group ID of owner
|
||||||
|
gid: u32,
|
||||||
|
/// device ID (if special file)
|
||||||
|
rdev: u64,
|
||||||
|
/// padding
|
||||||
|
__pad2: u64,
|
||||||
|
/// total size, in bytes
|
||||||
|
size: u64,
|
||||||
|
|
||||||
|
/// last access time
|
||||||
|
atime: Timespec,
|
||||||
|
/// last modification time
|
||||||
|
mtime: Timespec,
|
||||||
|
/// last status change time
|
||||||
|
ctime: Timespec,
|
||||||
|
|
||||||
|
/// blocksize for filesystem I/O
|
||||||
|
blksize: u32,
|
||||||
|
/// padding
|
||||||
|
__pad3: u32,
|
||||||
|
/// number of 512B blocks allocated
|
||||||
|
blocks: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_arch = "x86_64", target_arch = "mips"))]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Stat {
|
pub struct Stat {
|
||||||
@ -1107,7 +1161,29 @@ impl From<Metadata> for Stat {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "x86_64"))]
|
#[cfg(target_arch = "mips")]
|
||||||
|
fn from(info: Metadata) -> Self {
|
||||||
|
Stat {
|
||||||
|
dev: info.dev as u64,
|
||||||
|
ino: info.inode as u64,
|
||||||
|
mode: StatMode::from_type_mode(info.type_, info.mode as u16),
|
||||||
|
nlink: info.nlinks as u32,
|
||||||
|
uid: info.uid as u32,
|
||||||
|
gid: info.gid as u32,
|
||||||
|
rdev: 0,
|
||||||
|
size: info.size as u64,
|
||||||
|
blksize: info.blk_size as u32,
|
||||||
|
blocks: info.blocks as u64,
|
||||||
|
atime: Timespec { sec: info.atime.sec as i32, nsec: info.atime.nsec },
|
||||||
|
mtime: Timespec { sec: info.mtime.sec as i32, nsec: info.mtime.nsec },
|
||||||
|
ctime: Timespec { sec: info.ctime.sec as i32, nsec: info.ctime.nsec },
|
||||||
|
__pad1: 0,
|
||||||
|
__pad2: 0,
|
||||||
|
__pad3: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_arch = "x86_64", target_arch="mips")))]
|
||||||
fn from(info: Metadata) -> Self {
|
fn from(info: Metadata) -> Self {
|
||||||
Stat {
|
Stat {
|
||||||
dev: info.dev as u64,
|
dev: info.dev as u64,
|
||||||
@ -1139,7 +1215,7 @@ pub struct IoVec {
|
|||||||
/// Starting address
|
/// Starting address
|
||||||
base: *mut u8,
|
base: *mut u8,
|
||||||
/// Number of bytes to transfer
|
/// Number of bytes to transfer
|
||||||
len: u64,
|
len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A valid IoVecs request from user
|
/// A valid IoVecs request from user
|
||||||
@ -1160,15 +1236,15 @@ impl IoVecs {
|
|||||||
if iov.len > 0 {
|
if iov.len > 0 {
|
||||||
// skip empty iov
|
// skip empty iov
|
||||||
if readv {
|
if readv {
|
||||||
vm.check_write_array(iov.base, iov.len as usize)?;
|
vm.check_write_array(iov.base, iov.len)?;
|
||||||
} else {
|
} else {
|
||||||
vm.check_read_array(iov.base, iov.len as usize)?;
|
vm.check_read_array(iov.base, iov.len)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let slices = iovs
|
let slices = iovs
|
||||||
.iter()
|
.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();
|
.collect();
|
||||||
Ok(IoVecs(slices))
|
Ok(IoVecs(slices))
|
||||||
}
|
}
|
||||||
|
@ -123,6 +123,21 @@ bitflags! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "mips")]
|
||||||
|
bitflags! {
|
||||||
|
pub struct MmapFlags: usize {
|
||||||
|
/// Changes are shared.
|
||||||
|
const SHARED = 1 << 0;
|
||||||
|
/// Changes are private.
|
||||||
|
const PRIVATE = 1 << 1;
|
||||||
|
/// Place the mapping at the exact address
|
||||||
|
const FIXED = 1 << 4;
|
||||||
|
/// The mapping is not backed by any file. (non-POSIX)
|
||||||
|
const ANONYMOUS = 0x800;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "mips"))]
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct MmapFlags: usize {
|
pub struct MmapFlags: usize {
|
||||||
/// Changes are shared.
|
/// Changes are shared.
|
||||||
|
@ -88,7 +88,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
|
|||||||
}
|
}
|
||||||
SYS_GETPID => sys_getpid(),
|
SYS_GETPID => sys_getpid(),
|
||||||
// 40
|
// 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_SOCKET => sys_socket(args[0], args[1], args[2]),
|
||||||
SYS_CONNECT => sys_connect(args[0], args[1] as *const SockAddr, 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),
|
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");
|
warn!("sys_getegid is unimplemented");
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
SYS_SETPGID => {
|
||||||
|
warn!("sys_setpgid is unimplemented");
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
// 110
|
// 110
|
||||||
SYS_GETPPID => sys_getppid(),
|
SYS_GETPPID => sys_getppid(),
|
||||||
SYS_SETSID => {
|
SYS_SETSID => {
|
||||||
warn!("sys_setsid is unimplemented");
|
warn!("sys_setsid is unimplemented");
|
||||||
Ok(0)
|
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 => {
|
SYS_SIGALTSTACK => {
|
||||||
warn!("sys_sigaltstack is unimplemented");
|
warn!("sys_sigaltstack is unimplemented");
|
||||||
Ok(0)
|
Ok(0)
|
||||||
@ -213,6 +229,10 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
|
|||||||
Err(SysError::EACCES)
|
Err(SysError::EACCES)
|
||||||
}
|
}
|
||||||
SYS_SETPRIORITY => sys_set_priority(args[0]),
|
SYS_SETPRIORITY => sys_set_priority(args[0]),
|
||||||
|
SYS_PRCTL => {
|
||||||
|
warn!("prctl is unimplemented");
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
// SYS_SETRLIMIT => sys_setrlimit(),
|
// SYS_SETRLIMIT => sys_setrlimit(),
|
||||||
SYS_SYNC => sys_sync(),
|
SYS_SYNC => sys_sync(),
|
||||||
SYS_MOUNT => {
|
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_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_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_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_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_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
|
// 280
|
||||||
SYS_UTIMENSAT => {
|
SYS_UTIMENSAT => {
|
||||||
warn!("sys_utimensat is unimplemented");
|
warn!("sys_utimensat is unimplemented");
|
||||||
@ -286,8 +319,15 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
|
|||||||
let x86_64_ret = x86_64_syscall(id, args, tf);
|
let x86_64_ret = x86_64_syscall(id, args, tf);
|
||||||
#[cfg(not(target_arch = "x86_64"))]
|
#[cfg(not(target_arch = "x86_64"))]
|
||||||
let x86_64_ret = None;
|
let x86_64_ret = None;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "mips")]
|
||||||
|
let mips_ret = mips_syscall(id, args, tf);
|
||||||
|
#[cfg(not(target_arch = "mips"))]
|
||||||
|
let mips_ret = None;
|
||||||
if let Some(ret) = x86_64_ret {
|
if let Some(ret) = x86_64_ret {
|
||||||
ret
|
ret
|
||||||
|
} else if let Some(ret) = mips_ret {
|
||||||
|
ret
|
||||||
} else {
|
} else {
|
||||||
error!("unknown syscall id: {}, args: {:x?}", id, args);
|
error!("unknown syscall id: {}, args: {:x?}", id, args);
|
||||||
crate::trap::error(tf);
|
crate::trap::error(tf);
|
||||||
@ -307,6 +347,60 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "mips")]
|
||||||
|
fn mips_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<SysResult> {
|
||||||
|
let ret = match id {
|
||||||
|
SYS_FORK => sys_fork(tf),
|
||||||
|
SYS_OPEN => sys_open(args[0] as *const u8, args[1], args[2]),
|
||||||
|
SYS_DUP2 => sys_dup2(args[0], args[1]),
|
||||||
|
SYS_MMAP2 => sys_mmap(args[0], args[1], args[2], args[3], args[4], args[5] * 4096),
|
||||||
|
SYS_FSTAT64 => sys_fstat(args[0], args[1] as *mut Stat),
|
||||||
|
SYS_LSTAT64 => sys_lstat(args[0] as *const u8, args[1] as *mut Stat),
|
||||||
|
SYS_STAT64 => sys_stat(args[0] as *const u8, args[1] as *mut Stat),
|
||||||
|
SYS_PIPE => {
|
||||||
|
let fd_ptr = args[0] as *mut u32;
|
||||||
|
match sys_pipe(fd_ptr) {
|
||||||
|
Ok(code) => {
|
||||||
|
unsafe {
|
||||||
|
tf.v0 = *fd_ptr as usize;
|
||||||
|
tf.v1 = *(fd_ptr.add(1)) as usize;
|
||||||
|
}
|
||||||
|
Ok(tf.v0)
|
||||||
|
},
|
||||||
|
Err(err) => Err(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
SYS_GETPGID => {
|
||||||
|
warn!("sys_getpgid is unimplemented");
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
SYS_SETPGID => {
|
||||||
|
warn!("sys_setpgid is unimplemented");
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
SYS_FCNTL64 => {
|
||||||
|
warn!("sys_fcntl64 is unimplemented");
|
||||||
|
Ok(0)
|
||||||
|
},
|
||||||
|
SYS_SET_THREAD_AREA => {
|
||||||
|
info!("set_thread_area: tls: 0x{:x}", args[0]);
|
||||||
|
extern "C" {
|
||||||
|
fn _cur_tls();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
asm!("mtc0 $0, $$4, 2": :"r"(args[0]));
|
||||||
|
*(_cur_tls as *mut usize) = args[0];
|
||||||
|
}
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some(ret)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
fn x86_64_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<SysResult> {
|
fn x86_64_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<SysResult> {
|
||||||
let ret = match id {
|
let ret = match id {
|
||||||
@ -324,7 +418,10 @@ fn x86_64_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<Sys
|
|||||||
args[4] as *const TimeVal,
|
args[4] as *const TimeVal,
|
||||||
),
|
),
|
||||||
SYS_DUP2 => sys_dup2(args[0], args[1]),
|
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),
|
SYS_FORK => sys_fork(tf),
|
||||||
// use fork for vfork
|
// use fork for vfork
|
||||||
SYS_VFORK => sys_fork(tf),
|
SYS_VFORK => sys_fork(tf),
|
||||||
@ -339,16 +436,12 @@ fn x86_64_syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> Option<Sys
|
|||||||
warn!("sys_chmod is unimplemented");
|
warn!("sys_chmod is unimplemented");
|
||||||
Ok(0)
|
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 => {
|
SYS_CHOWN => {
|
||||||
warn!("sys_chown is unimplemented");
|
warn!("sys_chown is unimplemented");
|
||||||
Ok(0)
|
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 => {
|
SYS_EPOLL_CREATE => {
|
||||||
warn!("sys_epoll_create is unimplemented");
|
warn!("sys_epoll_create is unimplemented");
|
||||||
Err(SysError::ENOSYS)
|
Err(SysError::ENOSYS)
|
||||||
|
@ -13,7 +13,7 @@ pub fn sys_fork(tf: &TrapFrame) -> SysResult {
|
|||||||
|
|
||||||
/// Create a new thread in the current process.
|
/// Create a new thread in the current process.
|
||||||
/// The new thread's stack pointer will be set to `newsp`,
|
/// 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`.
|
/// The child tid will be stored at both `parent_tid` and `child_tid`.
|
||||||
/// This is partially implemented for musl only.
|
/// This is partially implemented for musl only.
|
||||||
pub fn sys_clone(
|
pub fn sys_clone(
|
||||||
@ -24,17 +24,19 @@ pub fn sys_clone(
|
|||||||
newtls: usize,
|
newtls: usize,
|
||||||
tf: &TrapFrame,
|
tf: &TrapFrame,
|
||||||
) -> SysResult {
|
) -> SysResult {
|
||||||
|
let clone_flags = CloneFlags::from_bits_truncate(flags);
|
||||||
info!(
|
info!(
|
||||||
"clone: flags: {:#x}, newsp: {:#x}, parent_tid: {:?}, child_tid: {:?}, newtls: {:#x}",
|
"clone: flags: {:?} == {:#x}, newsp: {:#x}, parent_tid: {:?}, child_tid: {:?}, newtls: {:#x}",
|
||||||
flags, newsp, parent_tid, child_tid, newtls
|
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");
|
warn!("sys_clone is calling sys_fork instead, ignoring other args");
|
||||||
return sys_fork(tf);
|
return sys_fork(tf);
|
||||||
}
|
}
|
||||||
if flags != 0x7d0f00 {
|
if (flags != 0x7d0f00) && (flags!= 0x5d0f00) { //0x5d0f00 is the args from gcc of alpine linux
|
||||||
warn!("sys_clone only support musl pthread_create");
|
//warn!("sys_clone only support musl pthread_create");
|
||||||
return Err(SysError::ENOSYS);
|
panic!("sys_clone only support sys_fork OR musl pthread_create without flags{:x}", flags);
|
||||||
|
//return Err(SysError::ENOSYS);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let proc = process();
|
let proc = process();
|
||||||
@ -123,9 +125,9 @@ pub fn sys_exec(
|
|||||||
envp: *const *const u8,
|
envp: *const *const u8,
|
||||||
tf: &mut TrapFrame,
|
tf: &mut TrapFrame,
|
||||||
) -> SysResult {
|
) -> SysResult {
|
||||||
info!("exec: name: {:?}, argv: {:?} envp: {:?}", name, argv, envp);
|
info!("exec: name: {:?}, argv: {:?}, envp: {:?}", name, argv, envp);
|
||||||
let proc = process();
|
let proc = process();
|
||||||
let _name = if name.is_null() {
|
let exec_name = if name.is_null() {
|
||||||
String::from("")
|
String::from("")
|
||||||
} else {
|
} else {
|
||||||
unsafe { proc.vm.check_and_clone_cstr(name)? }
|
unsafe { proc.vm.check_and_clone_cstr(name)? }
|
||||||
@ -145,19 +147,37 @@ pub fn sys_exec(
|
|||||||
current_argv = current_argv.add(1);
|
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() {
|
if args.is_empty() {
|
||||||
return Err(SysError::EINVAL);
|
return Err(SysError::EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"exec: name: {:?}, args: {:?}, envp: {:?}",
|
||||||
|
exec_name, args, envs
|
||||||
|
);
|
||||||
|
|
||||||
// Read program file
|
// Read program file
|
||||||
let path = args[0].as_str();
|
//let path = args[0].as_str();
|
||||||
let inode = proc.lookup_inode(path)?;
|
let exec_path = exec_name.as_str();
|
||||||
|
let inode = proc.lookup_inode(exec_path)?;
|
||||||
let buf = inode.read_as_vec()?;
|
let buf = inode.read_as_vec()?;
|
||||||
|
|
||||||
// Make new Thread
|
// Make new Thread
|
||||||
let iter = args.iter().map(|s| s.as_str());
|
let mut thread = Thread::new_user(buf.as_slice(), exec_path, args, envs);
|
||||||
let mut thread = Thread::new_user(buf.as_slice(), iter);
|
|
||||||
thread.proc.lock().clone_for_exec(&proc);
|
thread.proc.lock().clone_for_exec(&proc);
|
||||||
|
|
||||||
// Activate new page table
|
// Activate new page table
|
||||||
@ -231,7 +251,11 @@ pub fn sys_gettid() -> SysResult {
|
|||||||
|
|
||||||
/// Get the parent process id
|
/// Get the parent process id
|
||||||
pub fn sys_getppid() -> SysResult {
|
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
|
/// Exit the current thread
|
||||||
@ -313,3 +337,30 @@ pub fn sys_set_priority(priority: usize) -> SysResult {
|
|||||||
processor().manager().set_priority(pid, priority as u8);
|
processor().manager().set_priority(pid, priority as u8);
|
||||||
Ok(0)
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -19,6 +19,7 @@ const USEC_PER_SEC: u64 = 1_000_000;
|
|||||||
const MSEC_PER_SEC: u64 = 1_000;
|
const MSEC_PER_SEC: u64 = 1_000;
|
||||||
const USEC_PER_MSEC: u64 = 1_000;
|
const USEC_PER_MSEC: u64 = 1_000;
|
||||||
const NSEC_PER_USEC: u64 = 1_000;
|
const NSEC_PER_USEC: u64 = 1_000;
|
||||||
|
const NSEC_PER_MSEC: u64 = 1_000_000;
|
||||||
|
|
||||||
/// Get time since epoch in usec
|
/// Get time since epoch in usec
|
||||||
fn get_epoch_usec() -> u64 {
|
fn get_epoch_usec() -> u64 {
|
||||||
@ -32,20 +33,20 @@ fn get_epoch_usec() -> u64 {
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct TimeVal {
|
pub struct TimeVal {
|
||||||
sec: u64,
|
sec: usize,
|
||||||
usec: u64,
|
usec: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TimeVal {
|
impl TimeVal {
|
||||||
pub fn to_msec(&self) -> u64 {
|
pub fn to_msec(&self) -> u64 {
|
||||||
self.sec * MSEC_PER_SEC + self.usec / USEC_PER_MSEC
|
(self.sec as u64) * MSEC_PER_SEC + (self.usec as u64) / USEC_PER_MSEC
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_epoch() -> Self {
|
pub fn get_epoch() -> Self {
|
||||||
let usec = get_epoch_usec();
|
let usec = get_epoch_usec();
|
||||||
TimeVal {
|
TimeVal {
|
||||||
sec: usec / USEC_PER_SEC,
|
sec: (usec / USEC_PER_SEC) as usize,
|
||||||
usec: usec % USEC_PER_SEC,
|
usec: (usec % USEC_PER_SEC) as usize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,20 +54,24 @@ impl TimeVal {
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct TimeSpec {
|
pub struct TimeSpec {
|
||||||
sec: u64,
|
sec: usize,
|
||||||
nsec: u64,
|
nsec: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TimeSpec {
|
impl TimeSpec {
|
||||||
|
pub fn to_msec(&self) -> u64 {
|
||||||
|
(self.sec as u64) * MSEC_PER_SEC + (self.nsec as u64) / NSEC_PER_MSEC
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_duration(&self) -> Duration {
|
pub fn to_duration(&self) -> Duration {
|
||||||
Duration::new(self.sec, self.nsec as u32)
|
Duration::new(self.sec as u64, self.nsec as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_epoch() -> Self {
|
pub fn get_epoch() -> Self {
|
||||||
let usec = get_epoch_usec();
|
let usec = get_epoch_usec();
|
||||||
TimeSpec {
|
TimeSpec {
|
||||||
sec: usec / USEC_PER_SEC,
|
sec: (usec / USEC_PER_SEC) as usize,
|
||||||
nsec: usec % USEC_PER_SEC * NSEC_PER_USEC,
|
nsec: (usec % USEC_PER_SEC * NSEC_PER_USEC) as usize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,12 +135,12 @@ pub fn sys_getrusage(who: usize, rusage: *mut RUsage) -> SysResult {
|
|||||||
let usec = (tick - tick_base) * USEC_PER_TICK as u64;
|
let usec = (tick - tick_base) * USEC_PER_TICK as u64;
|
||||||
let new_rusage = RUsage {
|
let new_rusage = RUsage {
|
||||||
utime: TimeVal {
|
utime: TimeVal {
|
||||||
sec: usec / USEC_PER_SEC,
|
sec: (usec / USEC_PER_SEC) as usize,
|
||||||
usec: usec % USEC_PER_SEC,
|
usec: (usec % USEC_PER_SEC) as usize,
|
||||||
},
|
},
|
||||||
stime: TimeVal {
|
stime: TimeVal {
|
||||||
sec: usec / USEC_PER_SEC,
|
sec: (usec / USEC_PER_SEC) as usize,
|
||||||
usec: usec % USEC_PER_SEC,
|
usec: (usec % USEC_PER_SEC) as usize,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
unsafe { *rusage = new_rusage };
|
unsafe { *rusage = new_rusage };
|
||||||
|
@ -83,4 +83,4 @@ pub fn write<T>(addr: usize, content: T) {
|
|||||||
pub fn read<T>(addr: usize) -> T {
|
pub fn read<T>(addr: usize) -> T {
|
||||||
let cell = (addr) as *const T;
|
let cell = (addr) as *const T;
|
||||||
unsafe { read_volatile(cell) }
|
unsafe { read_volatile(cell) }
|
||||||
}
|
}
|
||||||
|
1
riscv-pk
1
riscv-pk
@ -1 +0,0 @@
|
|||||||
Subproject commit 405ea59dd7dd2762c5883822f21d9995bea32b0c
|
|
@ -10,11 +10,11 @@ arch = sys.argv[2]
|
|||||||
mode = sys.argv[3]
|
mode = sys.argv[3]
|
||||||
print('--------------------------------------')
|
print('--------------------------------------')
|
||||||
for line in lines:
|
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:
|
if match:
|
||||||
addr = match.group(2)
|
addr = match.group(2)
|
||||||
process = subprocess.run([addrline, '-e', 'target/{0}/{1}/rcore'.format(arch, mode), '-f', '-C', addr], capture_output=True)
|
process = subprocess.run([addrline, '-e', 'target/{0}/{1}/rcore'.format(arch, mode), '-f', '-C', addr], capture_output=True)
|
||||||
res = process.stdout.decode('utf-8')
|
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:
|
else:
|
||||||
print(line, end='')
|
print(line, end='')
|
||||||
|
9
tools/opensbi/README.md
Normal file
9
tools/opensbi/README.md
Normal 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
BIN
tools/opensbi/fu540.elf
Executable file
Binary file not shown.
BIN
tools/opensbi/virt_rv32.elf
Executable file
BIN
tools/opensbi/virt_rv32.elf
Executable file
Binary file not shown.
BIN
tools/opensbi/virt_rv64.elf
Executable file
BIN
tools/opensbi/virt_rv64.elf
Executable file
Binary file not shown.
2
user
2
user
@ -1 +1 @@
|
|||||||
Subproject commit fdaa1be8635944d88ff128da13bf0464f7ce2eb6
|
Subproject commit 8dbc0edb935a62d748aaac39258d4a985de0ae17
|
Loading…
Reference in New Issue
Block a user