mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-21 23:56:18 +04:00
Merge pull request #80 from rcore-riscv-hypervisor-dev/rvm
RISC-V 64 Hypervisor: rCore on rCore
This commit is contained in:
commit
13ad2d1905
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -3,4 +3,4 @@
|
|||||||
url = https://github.com/rcore-os/rcore-user.git
|
url = https://github.com/rcore-os/rcore-user.git
|
||||||
[submodule "rboot"]
|
[submodule "rboot"]
|
||||||
path = rboot
|
path = rboot
|
||||||
url = https://github.com/rcore-os/rboot.git
|
url = https://github.com/rcore-os/rboot.git
|
@ -49,10 +49,20 @@ impl<T: FrameAllocator> MemoryHandler for Delay<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_page_fault(&self, pt: &mut dyn PageTable, addr: VirtAddr) -> bool {
|
fn handle_page_fault_ext(
|
||||||
|
&self,
|
||||||
|
pt: &mut dyn PageTable,
|
||||||
|
addr: VirtAddr,
|
||||||
|
access: super::AccessType,
|
||||||
|
) -> bool {
|
||||||
let entry = pt.get_entry(addr).expect("failed to get entry");
|
let entry = pt.get_entry(addr).expect("failed to get entry");
|
||||||
if entry.present() {
|
if entry.present() {
|
||||||
// not a delay case
|
// permission check.
|
||||||
|
if access.check_access(entry) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// permisison check failed.
|
||||||
|
error!("Permission check failed at 0x{:x}.", addr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let frame = self.allocator.alloc().expect("failed to alloc frame");
|
let frame = self.allocator.alloc().expect("failed to alloc frame");
|
||||||
|
@ -58,10 +58,24 @@ impl<F: Read, T: FrameAllocator> MemoryHandler for File<F, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_page_fault(&self, pt: &mut dyn PageTable, addr: usize) -> bool {
|
fn handle_page_fault_ext(
|
||||||
|
&self,
|
||||||
|
pt: &mut dyn PageTable,
|
||||||
|
addr: usize,
|
||||||
|
access: super::AccessType,
|
||||||
|
) -> bool {
|
||||||
let addr = addr & !(PAGE_SIZE - 1);
|
let addr = addr & !(PAGE_SIZE - 1);
|
||||||
let entry = pt.get_entry(addr).expect("failed to get entry");
|
let entry = pt.get_entry(addr).expect("failed to get entry");
|
||||||
if entry.present() {
|
if entry.present() {
|
||||||
|
// permission check.
|
||||||
|
if access.check_access(entry) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// permisison check failed.
|
||||||
|
error!(
|
||||||
|
"Permission check failed at 0x{:x}, access = {:?}.",
|
||||||
|
addr, access
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let execute = entry.execute();
|
let execute = entry.execute();
|
||||||
|
@ -1,5 +1,45 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct AccessType {
|
||||||
|
pub write: bool,
|
||||||
|
pub execute: bool,
|
||||||
|
pub user: bool,
|
||||||
|
}
|
||||||
|
impl AccessType {
|
||||||
|
pub fn unknown() -> Self {
|
||||||
|
AccessType {
|
||||||
|
write: true,
|
||||||
|
execute: true,
|
||||||
|
user: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn read(user: bool) -> Self {
|
||||||
|
AccessType {
|
||||||
|
write: false,
|
||||||
|
execute: false,
|
||||||
|
user,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn write(user: bool) -> Self {
|
||||||
|
AccessType {
|
||||||
|
write: true,
|
||||||
|
execute: false,
|
||||||
|
user,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn execute(user: bool) -> Self {
|
||||||
|
AccessType {
|
||||||
|
write: false,
|
||||||
|
execute: true,
|
||||||
|
user,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn check_access(self, entry: &dyn paging::Entry) -> bool {
|
||||||
|
((!self.write) || entry.writable())
|
||||||
|
&& ((!self.execute) || entry.execute())
|
||||||
|
&& ((!self.user) || entry.user())
|
||||||
|
}
|
||||||
|
}
|
||||||
// here may be a interesting part for lab
|
// here may be a interesting part for lab
|
||||||
pub trait MemoryHandler: Debug + Send + Sync + 'static {
|
pub trait MemoryHandler: Debug + Send + Sync + 'static {
|
||||||
fn box_clone(&self) -> Box<dyn MemoryHandler>;
|
fn box_clone(&self) -> Box<dyn MemoryHandler>;
|
||||||
@ -22,7 +62,20 @@ pub trait MemoryHandler: Debug + Send + Sync + 'static {
|
|||||||
|
|
||||||
/// Handle page fault on `addr`
|
/// Handle page fault on `addr`
|
||||||
/// Return true if success, false if error
|
/// Return true if success, false if error
|
||||||
fn handle_page_fault(&self, pt: &mut dyn PageTable, addr: VirtAddr) -> bool;
|
fn handle_page_fault(&self, pt: &mut dyn PageTable, addr: VirtAddr) -> bool {
|
||||||
|
self.handle_page_fault_ext(pt, addr, AccessType::unknown())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handle page fault on `addr` and access type `access`
|
||||||
|
/// Return true if success (or should-retry), false if error
|
||||||
|
fn handle_page_fault_ext(
|
||||||
|
&self,
|
||||||
|
pt: &mut dyn PageTable,
|
||||||
|
addr: VirtAddr,
|
||||||
|
_access: AccessType,
|
||||||
|
) -> bool {
|
||||||
|
self.handle_page_fault(pt, addr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for Box<dyn MemoryHandler> {
|
impl Clone for Box<dyn MemoryHandler> {
|
||||||
|
@ -35,7 +35,7 @@ impl<T: FrameAllocator> SharedGuard<T> {
|
|||||||
self.target.insert(virt_addr, phys_addr);
|
self.target.insert(virt_addr, phys_addr);
|
||||||
Some(phys_addr)
|
Some(phys_addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dealloc(&mut self, virt_addr: usize) {
|
pub fn dealloc(&mut self, virt_addr: usize) {
|
||||||
let phys_addr = self.target.get(&virt_addr).unwrap().clone();
|
let phys_addr = self.target.get(&virt_addr).unwrap().clone();
|
||||||
self.allocator.dealloc(phys_addr);
|
self.allocator.dealloc(phys_addr);
|
||||||
|
@ -376,6 +376,15 @@ impl<T: PageTableExt> MemorySet<T> {
|
|||||||
&mut self.page_table
|
&mut self.page_table
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_page_fault_ext(&mut self, addr: VirtAddr, access: handler::AccessType) -> bool {
|
||||||
|
let area = self.areas.iter().find(|area| area.contains(addr));
|
||||||
|
match area {
|
||||||
|
Some(area) => area
|
||||||
|
.handler
|
||||||
|
.handle_page_fault_ext(&mut self.page_table, addr, access),
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn handle_page_fault(&mut self, addr: VirtAddr) -> bool {
|
pub fn handle_page_fault(&mut self, addr: VirtAddr) -> bool {
|
||||||
let area = self.areas.iter().find(|area| area.contains(addr));
|
let area = self.areas.iter().find(|area| area.contains(addr));
|
||||||
match area {
|
match area {
|
||||||
|
57
kernel/Cargo.lock
generated
57
kernel/Cargo.lock
generated
@ -50,7 +50,7 @@ source = "git+https://github.com/rcore-os/apic-rs?rev=fb86bd7#fb86bd7c798608a18c
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bit_field 0.10.1",
|
"bit_field 0.10.1",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"x86",
|
"x86 0.33.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -89,9 +89,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit-vec"
|
name = "bit-vec"
|
||||||
version = "0.6.2"
|
version = "0.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3"
|
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit_field"
|
name = "bit_field"
|
||||||
@ -114,7 +114,7 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "bitmap-allocator"
|
name = "bitmap-allocator"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rcore-os/bitmap-allocator#03bd9909d0dc85e99f5559b97a163ab81073df83"
|
source = "git+https://github.com/rcore-os/bitmap-allocator?rev=03bd990#03bd9909d0dc85e99f5559b97a163ab81073df83"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit_field 0.9.0",
|
"bit_field 0.9.0",
|
||||||
]
|
]
|
||||||
@ -164,9 +164,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.60"
|
version = "1.0.67"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c"
|
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@ -456,6 +456,15 @@ dependencies = [
|
|||||||
"rustc_version",
|
"rustc_version",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "raw-cpuid"
|
||||||
|
version = "9.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c27cb5785b85bd05d4eb171556c9a1a514552e26123aeae6bb7d811353148026"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rboot"
|
name = "rboot"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
@ -495,7 +504,7 @@ dependencies = [
|
|||||||
"paste",
|
"paste",
|
||||||
"pc-keyboard",
|
"pc-keyboard",
|
||||||
"pci",
|
"pci",
|
||||||
"raw-cpuid",
|
"raw-cpuid 8.0.0",
|
||||||
"rboot",
|
"rboot",
|
||||||
"rcore-console",
|
"rcore-console",
|
||||||
"rcore-fs",
|
"rcore-fs",
|
||||||
@ -623,8 +632,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "riscv"
|
name = "riscv"
|
||||||
version = "0.5.6"
|
version = "0.6.0"
|
||||||
source = "git+https://github.com/rcore-os/riscv?rev=38f3786#38f3786966ba15cc76977375162e3f3622a30f4b"
|
source = "git+https://github.com/rcore-riscv-hypervisor-dev/riscv.git?rev=3f5efb1#3f5efb1b8d4ceb12e291ef3d7b27120ea038eb83"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bare-metal",
|
"bare-metal",
|
||||||
"bit_field 0.10.1",
|
"bit_field 0.10.1",
|
||||||
@ -671,27 +680,28 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rvm"
|
name = "rvm"
|
||||||
version = "1.0.1"
|
version = "1.2.0"
|
||||||
source = "git+https://github.com/rcore-os/RVM?rev=939eb0a#939eb0aafd100e9944e4f2fe90eebfa8149d2b85"
|
source = "git+https://github.com/rcore-riscv-hypervisor-dev/RVM?rev=2867e78#2867e782463fe81e572d7c3cd68abaf79252f50c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit-set",
|
"bit-set",
|
||||||
"bit_field 0.10.1",
|
"bit_field 0.10.1",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"bitmap-allocator 0.1.0 (git+https://github.com/rcore-os/bitmap-allocator)",
|
"bitmap-allocator 0.1.0 (git+https://github.com/rcore-os/bitmap-allocator?rev=03bd990)",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"numeric-enum-macro",
|
"numeric-enum-macro",
|
||||||
"raw-cpuid",
|
"raw-cpuid 9.0.0",
|
||||||
|
"riscv",
|
||||||
"rvm_macros",
|
"rvm_macros",
|
||||||
"spin",
|
"spin",
|
||||||
"x86",
|
"x86 0.36.0",
|
||||||
"x86_64",
|
"x86_64",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rvm_macros"
|
name = "rvm_macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rcore-os/RVM?rev=939eb0a#939eb0aafd100e9944e4f2fe90eebfa8149d2b85"
|
source = "git+https://github.com/rcore-riscv-hypervisor-dev/RVM?rev=2867e78#2867e782463fe81e572d7c3cd68abaf79252f50c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
@ -766,7 +776,7 @@ name = "trapframe"
|
|||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
source = "git+https://github.com/rcore-os/trapframe-rs?rev=bdfe5aa#bdfe5aaebcdd64636c8831c2b8c17e4fede40c0b"
|
source = "git+https://github.com/rcore-os/trapframe-rs?rev=bdfe5aa#bdfe5aaebcdd64636c8831c2b8c17e4fede40c0b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"raw-cpuid",
|
"raw-cpuid 8.0.0",
|
||||||
"x86_64",
|
"x86_64",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -845,7 +855,7 @@ checksum = "88dfeb711b61ce620c0cb6fd9f8e3e678622f0c971da2a63c4b3e25e88ed012f"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "virtio-drivers"
|
name = "virtio-drivers"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/rcore-os/virtio-drivers?rev=dfa70e14#dfa70e1425c9eac1b30e671be61b557a3ce56e7e"
|
source = "git+https://github.com/rcore-riscv-hypervisor-dev/virtio-drivers?rev=1201a0b#1201a0b40c016301c8135e564439e40a769facc8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"log",
|
"log",
|
||||||
@ -903,7 +913,18 @@ checksum = "2786ac694ed572ab5d2bbcd9e188805dba26b3501973dd69718914fb3d4a5a69"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bit_field 0.10.1",
|
"bit_field 0.10.1",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"raw-cpuid",
|
"raw-cpuid 8.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "x86"
|
||||||
|
version = "0.36.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "268696f47813d5744c80c868e014485e27b30d40eaeeff2f7685b10b70215e5c"
|
||||||
|
dependencies = [
|
||||||
|
"bit_field 0.10.1",
|
||||||
|
"bitflags",
|
||||||
|
"raw-cpuid 9.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -22,6 +22,7 @@ authors = [
|
|||||||
default = []
|
default = []
|
||||||
board_qemu = []
|
board_qemu = []
|
||||||
board_u540 = ["link_user"]
|
board_u540 = ["link_user"]
|
||||||
|
board_rcore_vmm_guest = ["link_user"]
|
||||||
# (for aarch64 RaspberryPi3)
|
# (for aarch64 RaspberryPi3)
|
||||||
nographic = []
|
nographic = []
|
||||||
consolegraphic = []
|
consolegraphic = []
|
||||||
@ -72,11 +73,11 @@ rlibc = "1.0"
|
|||||||
smoltcp = { git = "https://github.com/rcore-os/smoltcp", rev = "5bd87c7c", default-features = false, features = ["alloc", "log", "ethernet", "proto-ipv4", "proto-igmp", "socket-icmp", "socket-udp", "socket-tcp", "socket-raw"] }
|
smoltcp = { git = "https://github.com/rcore-os/smoltcp", rev = "5bd87c7c", default-features = false, features = ["alloc", "log", "ethernet", "proto-ipv4", "proto-igmp", "socket-icmp", "socket-udp", "socket-tcp", "socket-raw"] }
|
||||||
spin = "0.5"
|
spin = "0.5"
|
||||||
trapframe = { git = "https://github.com/rcore-os/trapframe-rs", rev = "bdfe5aa" }
|
trapframe = { git = "https://github.com/rcore-os/trapframe-rs", rev = "bdfe5aa" }
|
||||||
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "dfa70e14" }
|
virtio-drivers = { git = "https://github.com/rcore-riscv-hypervisor-dev/virtio-drivers", rev = "1201a0b" }
|
||||||
volatile = "0.2"
|
volatile = "0.2"
|
||||||
woke = "0.0.2"
|
woke = "0.0.2"
|
||||||
xmas-elf = "0.7"
|
xmas-elf = "0.7"
|
||||||
rvm = { git = "https://github.com/rcore-os/RVM", rev = "939eb0a", optional = true }
|
rvm = { git = "https://github.com/rcore-riscv-hypervisor-dev/RVM", rev = "2867e78", optional = true }
|
||||||
|
|
||||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||||
apic = { git = "https://github.com/rcore-os/apic-rs", rev = "fb86bd7" }
|
apic = { git = "https://github.com/rcore-os/apic-rs", rev = "fb86bd7" }
|
||||||
@ -88,7 +89,7 @@ uart_16550 = "0.2.7"
|
|||||||
x86_64 = "0.11"
|
x86_64 = "0.11"
|
||||||
|
|
||||||
[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies]
|
[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies]
|
||||||
riscv = { git = "https://github.com/rcore-os/riscv", rev = "38f3786", features = ["inline-asm"] }
|
riscv = { git = "https://github.com/rcore-riscv-hypervisor-dev/riscv" , rev = "3f5efb1", features = ["inline-asm", "hypervisor"] }
|
||||||
|
|
||||||
[target.'cfg(target_arch = "aarch64")'.dependencies]
|
[target.'cfg(target_arch = "aarch64")'.dependencies]
|
||||||
aarch64 = { git = "https://github.com/rcore-os/aarch64", version = "3.0.1" }
|
aarch64 = { git = "https://github.com/rcore-os/aarch64", version = "3.0.1" }
|
||||||
|
@ -22,12 +22,15 @@
|
|||||||
# | pc [ x86_64 only] Run on real pc
|
# | pc [ x86_64 only] Run on real pc
|
||||||
# | u540 [riscv64 only] Run on HiFive U540, use Sv39
|
# | u540 [riscv64 only] Run on HiFive U540, use Sv39
|
||||||
# | raspi3 [aarch64 only] Run on Raspberry Pi 3 Model B/B+
|
# | raspi3 [aarch64 only] Run on Raspberry Pi 3 Model B/B+
|
||||||
|
# | rcore_vmm_guest [riscv64 only] Run on rust-rvm-vmm/RVM. Requires variable GUEST_USER_IMG to be specified.
|
||||||
# NET = on | off [ x86_64 only] Enable NIC
|
# NET = on | off [ x86_64 only] Enable NIC
|
||||||
# PCI_PASSTHRU = 0000:00:00.1 [ x86_64 only] Passthrough the specified PCI device
|
# PCI_PASSTHRU = 0000:00:00.1 [ x86_64 only] Passthrough the specified PCI device
|
||||||
# INIT = /bin/ls [riscv64 only] Run specified program instead of user shell
|
# INIT = /bin/ls [riscv64 only] Run specified program instead of user shell
|
||||||
# EXTRA_NIC = on | off [ x86_64 only] Add an additional e1000 nic
|
# EXTRA_NIC = on | off [ x86_64 only] Add an additional e1000 nic
|
||||||
# ACCEL = on | off [ x86_64 only] Enable/disable kvm/hvf acceleration
|
# ACCEL = on | off [ x86_64 only] Enable/disable kvm/hvf acceleration
|
||||||
# HYPERVISOR = on | off [ x86_64 only] Enable/disable the RVM hypervisor, and set ACCEL to on
|
# HYPERVISOR = on | off [ x86_64 and riscv64 only] Enable/disable the RVM hypervisor, and set ACCEL to on under x86_64
|
||||||
|
# UART2 = on | off [riscv64 only] Add an extra virtio-driven UART port on unix domain socket /tmp/rcore_uart2
|
||||||
|
# GUEST_USER_IMG = <sfsimg> Image path of user programs. Specially taken out to allow out-of-tree user image.
|
||||||
# FEATURES = profile | ... Add additional features
|
# FEATURES = profile | ... Add additional features
|
||||||
|
|
||||||
ARCH ?= riscv64
|
ARCH ?= riscv64
|
||||||
@ -40,6 +43,7 @@ INIT ?=
|
|||||||
EXTRA_NIC ?= off
|
EXTRA_NIC ?= off
|
||||||
ACCEL ?= off
|
ACCEL ?= off
|
||||||
HYPERVISOR ?= off
|
HYPERVISOR ?= off
|
||||||
|
UART2 ?= off
|
||||||
|
|
||||||
qemu := qemu-system-$(ARCH)
|
qemu := qemu-system-$(ARCH)
|
||||||
target := $(ARCH)
|
target := $(ARCH)
|
||||||
@ -53,7 +57,14 @@ user_dir := ../user
|
|||||||
|
|
||||||
### export environments ###
|
### export environments ###
|
||||||
|
|
||||||
|
ifeq ($(BOARD), rcore_vmm_guest)
|
||||||
|
ifeq ($(GUEST_USER_IMG), )
|
||||||
|
$(error For building guest rCore image you have to specify the variable GUEST_USER_IMG .)
|
||||||
|
endif
|
||||||
|
export USER_IMG = $(GUEST_USER_IMG)
|
||||||
|
else
|
||||||
export USER_IMG = $(user_dir)/build/$(ARCH).img
|
export USER_IMG = $(user_dir)/build/$(ARCH).img
|
||||||
|
endif
|
||||||
export USER_QCOW2 = $(user_dir)/build/$(ARCH).qcow2
|
export USER_QCOW2 = $(user_dir)/build/$(ARCH).qcow2
|
||||||
|
|
||||||
ifeq ($(ARCH), aarch64)
|
ifeq ($(ARCH), aarch64)
|
||||||
@ -124,10 +135,27 @@ qemu_opts += \
|
|||||||
-serial mon:stdio \
|
-serial mon:stdio \
|
||||||
-bios ../tools/opensbi/fu540.elf \
|
-bios ../tools/opensbi/fu540.elf \
|
||||||
-device loader,addr=0x80200000,file=$(kernel_img)
|
-device loader,addr=0x80200000,file=$(kernel_img)
|
||||||
|
else ifeq ($(BOARD), rcore_vmm_guest)
|
||||||
|
qemu_opts += \
|
||||||
|
-machine virt \
|
||||||
|
-cpu rv64,x-h=true \
|
||||||
|
-serial mon:stdio \
|
||||||
|
-bios ../tools/opensbi/fw_jump.elf \
|
||||||
|
-m 1G\
|
||||||
|
-kernel $(kernel_img)
|
||||||
else
|
else
|
||||||
qemu_opts += \
|
qemu_opts += \
|
||||||
-machine virt \
|
-machine virt \
|
||||||
-serial mon:stdio \
|
-cpu rv64,x-h=true \
|
||||||
|
-m 2G \
|
||||||
|
-serial mon:stdio
|
||||||
|
ifeq ($(UART2), on)
|
||||||
|
qemu_opts += \
|
||||||
|
-chardev socket,path=/tmp/rcore_uart2,server=on,wait=off,id=uart2 \
|
||||||
|
-device virtio-serial-device,id=uart2-bus \
|
||||||
|
-device virtconsole,chardev=uart2
|
||||||
|
endif
|
||||||
|
qemu_opts += \
|
||||||
-bios ../tools/opensbi/fw_jump.elf \
|
-bios ../tools/opensbi/fw_jump.elf \
|
||||||
-device loader,addr=0x80200000,file=$(kernel_img) \
|
-device loader,addr=0x80200000,file=$(kernel_img) \
|
||||||
-drive file=$(USER_QCOW2),format=qcow2,id=sfs \
|
-drive file=$(USER_QCOW2),format=qcow2,id=sfs \
|
||||||
@ -173,8 +201,10 @@ endif
|
|||||||
|
|
||||||
ifeq ($(HYPERVISOR), on)
|
ifeq ($(HYPERVISOR), on)
|
||||||
FEATURES += hypervisor
|
FEATURES += hypervisor
|
||||||
|
ifeq ($(ARCH), x86_64)
|
||||||
ACCEL = on
|
ACCEL = on
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(ACCEL), on)
|
ifeq ($(ACCEL), on)
|
||||||
ifeq ($(shell uname), Darwin)
|
ifeq ($(shell uname), Darwin)
|
||||||
@ -257,6 +287,8 @@ debug: $(kernel) $(kernel_img)
|
|||||||
@sleep 1
|
@sleep 1
|
||||||
@$(gdb) $(kernel) -x ../tools/gdbinit
|
@$(gdb) $(kernel) -x ../tools/gdbinit
|
||||||
|
|
||||||
|
justdebug:
|
||||||
|
@$(qemu) $(qemu_opts) -s -S
|
||||||
build: $(kernel_img)
|
build: $(kernel_img)
|
||||||
|
|
||||||
asm:
|
asm:
|
||||||
@ -347,4 +379,4 @@ endif
|
|||||||
|
|
||||||
.PHONY:
|
.PHONY:
|
||||||
addr2line:
|
addr2line:
|
||||||
@python3.7 ../tools/addr2line.py $(prefix)addr2line $(ARCH) $(MODE)
|
@python3 ../tools/addr2line.py $(prefix)addr2line $(ARCH) $(MODE)
|
||||||
|
14
kernel/src/arch/riscv/board/rcore_vmm_guest/mod.rs
Normal file
14
kernel/src/arch/riscv/board/rcore_vmm_guest/mod.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::drivers::*;
|
||||||
|
use crate::memory::phys_to_virt;
|
||||||
|
use riscv::register::sie;
|
||||||
|
|
||||||
|
/// Enable external interrupt
|
||||||
|
pub unsafe fn init_external_interrupt() {
|
||||||
|
sie::set_sext();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(dtb: usize) {
|
||||||
|
serial::uart16550::driver_init();
|
||||||
|
irq::plic::driver_init();
|
||||||
|
device_tree::init(dtb);
|
||||||
|
}
|
@ -14,6 +14,15 @@ pub fn is_page_fault(trap: usize) -> bool {
|
|||||||
trap == InstructionPageFault || trap == LoadPageFault || trap == StorePageFault
|
trap == InstructionPageFault || trap == LoadPageFault || trap == StorePageFault
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_execute_page_fault(trap: usize) -> bool {
|
||||||
|
trap == InstructionPageFault
|
||||||
|
}
|
||||||
|
pub fn is_read_page_fault(trap: usize) -> bool {
|
||||||
|
trap == LoadPageFault
|
||||||
|
}
|
||||||
|
pub fn is_write_page_fault(trap: usize) -> bool {
|
||||||
|
trap == StorePageFault
|
||||||
|
}
|
||||||
pub fn is_syscall(trap: usize) -> bool {
|
pub fn is_syscall(trap: usize) -> bool {
|
||||||
trap == Syscall
|
trap == Syscall
|
||||||
}
|
}
|
||||||
|
@ -36,18 +36,30 @@ pub unsafe fn restore(flags: usize) {
|
|||||||
/// This function is called from `trap.asm`.
|
/// This function is called from `trap.asm`.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn trap_handler(tf: &mut TrapFrame) {
|
pub extern "C" fn trap_handler(tf: &mut TrapFrame) {
|
||||||
|
trap_handler_no_frame(&mut tf.sepc);
|
||||||
|
}
|
||||||
|
|
||||||
|
use crate::memory::AccessType;
|
||||||
|
#[inline]
|
||||||
|
pub fn trap_handler_no_frame(sepc: &mut usize) {
|
||||||
use self::scause::{Exception as E, Interrupt as I, Trap};
|
use self::scause::{Exception as E, Interrupt as I, Trap};
|
||||||
let scause = scause::read();
|
let scause = scause::read();
|
||||||
let stval = stval::read();
|
let stval = stval::read();
|
||||||
|
let is_user = false;
|
||||||
trace!("Interrupt @ CPU{}: {:?} ", super::cpu::id(), scause.cause());
|
trace!("Interrupt @ CPU{}: {:?} ", super::cpu::id(), scause.cause());
|
||||||
match scause.cause() {
|
match scause.cause() {
|
||||||
Trap::Interrupt(I::SupervisorExternal) => external(),
|
Trap::Interrupt(I::SupervisorExternal) => external(),
|
||||||
Trap::Interrupt(I::SupervisorSoft) => ipi(),
|
Trap::Interrupt(I::SupervisorSoft) => ipi(),
|
||||||
Trap::Interrupt(I::SupervisorTimer) => timer(),
|
Trap::Interrupt(I::SupervisorTimer) => timer(),
|
||||||
Trap::Exception(E::LoadPageFault) => page_fault(stval, tf),
|
Trap::Exception(E::LoadPageFault) => page_fault(stval, sepc, AccessType::read(is_user)),
|
||||||
Trap::Exception(E::StorePageFault) => page_fault(stval, tf),
|
Trap::Exception(E::StorePageFault) => page_fault(stval, sepc, AccessType::write(is_user)),
|
||||||
Trap::Exception(E::InstructionPageFault) => page_fault(stval, tf),
|
Trap::Exception(E::InstructionPageFault) => {
|
||||||
_ => panic!("unhandled trap {:?}", scause.cause()),
|
page_fault(stval, sepc, AccessType::execute(is_user))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let bits = scause.bits();
|
||||||
|
panic!("unhandled trap {:?} ({})", scause.cause(), bits);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
trace!("Interrupt end");
|
trace!("Interrupt end");
|
||||||
}
|
}
|
||||||
@ -57,7 +69,6 @@ fn external() {
|
|||||||
unsafe {
|
unsafe {
|
||||||
super::board::handle_external_interrupt();
|
super::board::handle_external_interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
IRQ_MANAGER
|
IRQ_MANAGER
|
||||||
.read()
|
.read()
|
||||||
.try_handle_interrupt(Some(SupervisorExternal));
|
.try_handle_interrupt(Some(SupervisorExternal));
|
||||||
@ -73,22 +84,23 @@ pub fn timer() {
|
|||||||
crate::trap::timer();
|
crate::trap::timer();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn page_fault(stval: usize, tf: &mut TrapFrame) {
|
fn page_fault(stval: usize, sepc: &mut usize, access: AccessType) {
|
||||||
let addr = stval;
|
let addr = stval;
|
||||||
trace!("\nEXCEPTION: Page Fault @ {:#x}", addr);
|
info!("\nEXCEPTION: Page Fault @ {:#x}", addr);
|
||||||
|
|
||||||
if crate::memory::handle_page_fault(addr) {
|
if crate::memory::handle_page_fault_ext(addr, access) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn _copy_user_start();
|
fn _copy_user_start();
|
||||||
fn _copy_user_end();
|
fn _copy_user_end();
|
||||||
}
|
}
|
||||||
if tf.sepc >= _copy_user_start as usize && tf.sepc < _copy_user_end as usize {
|
if *sepc >= _copy_user_start as usize && *sepc < _copy_user_end as usize {
|
||||||
debug!("fixup for addr {:x?}", addr);
|
info!("fixup for addr {:x?}", addr);
|
||||||
tf.sepc = crate::memory::read_user_fixup as usize;
|
*sepc = crate::memory::read_user_fixup as usize;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
error!("unhandled page fault {:#x} from {:#x}", addr, sepc);
|
||||||
panic!("unhandled page fault");
|
panic!("unhandled page fault");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,8 +128,8 @@ pub fn wait_for_interrupt() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_user_page_fault(thread: &Arc<Thread>, addr: usize) -> bool {
|
pub fn handle_user_page_fault_ext(thread: &Arc<Thread>, addr: usize, access: AccessType) -> bool {
|
||||||
thread.vm.lock().handle_page_fault(addr)
|
thread.vm.lock().handle_page_fault_ext(addr, access)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_reserved_inst(tf: &mut UserContext) -> bool {
|
pub fn handle_reserved_inst(tf: &mut UserContext) -> bool {
|
||||||
|
@ -1,11 +1,33 @@
|
|||||||
|
use crate::drivers::SerialDriver;
|
||||||
use crate::drivers::SERIAL_DRIVERS;
|
use crate::drivers::SERIAL_DRIVERS;
|
||||||
|
use alloc::sync::Arc;
|
||||||
use core::fmt::{Arguments, Write};
|
use core::fmt::{Arguments, Write};
|
||||||
|
pub struct HeaplessWrite<T: AsRef<dyn SerialDriver>>(T);
|
||||||
|
impl<T: AsRef<dyn SerialDriver>> core::fmt::Write for HeaplessWrite<T> {
|
||||||
|
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||||
|
self.0.as_ref().write(s.as_bytes());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HeaplessSBIWrite;
|
||||||
|
impl core::fmt::Write for HeaplessSBIWrite {
|
||||||
|
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||||
|
for ch in s.as_bytes() {
|
||||||
|
super::sbi::console_putchar(*ch as usize);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn putfmt(fmt: Arguments) {
|
pub fn putfmt(fmt: Arguments) {
|
||||||
// output to serial
|
// output to serial
|
||||||
let mut drivers = SERIAL_DRIVERS.write();
|
let mut drivers = SERIAL_DRIVERS.write();
|
||||||
if let Some(serial) = drivers.first_mut() {
|
if let Some(serial) = drivers.first_mut() {
|
||||||
serial.write(format!("{}", fmt).as_bytes());
|
HeaplessWrite(&serial).write_fmt(fmt).unwrap();
|
||||||
|
} else {
|
||||||
|
// might miss some early messages.
|
||||||
|
// no no no i don't accept it.
|
||||||
|
// note that we can't use heap here.
|
||||||
|
HeaplessSBIWrite.write_fmt(fmt).unwrap();
|
||||||
}
|
}
|
||||||
// might miss some early messages, but it's okay
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,10 @@ use trapframe;
|
|||||||
#[cfg(feature = "board_u540")]
|
#[cfg(feature = "board_u540")]
|
||||||
#[path = "board/u540/mod.rs"]
|
#[path = "board/u540/mod.rs"]
|
||||||
pub mod board;
|
pub mod board;
|
||||||
#[cfg(not(feature = "board_u540"))]
|
#[cfg(feature = "board_rcore_vmm_guest")]
|
||||||
|
#[path = "board/rcore_vmm_guest/mod.rs"]
|
||||||
|
pub mod board;
|
||||||
|
#[cfg(not(any(feature = "board_u540", feature = "board_rcore_vmm_guest")))]
|
||||||
#[path = "board/virt/mod.rs"]
|
#[path = "board/virt/mod.rs"]
|
||||||
pub mod board;
|
pub mod board;
|
||||||
|
|
||||||
@ -16,7 +19,7 @@ pub mod io;
|
|||||||
pub mod memory;
|
pub mod memory;
|
||||||
pub mod paging;
|
pub mod paging;
|
||||||
pub mod rand;
|
pub mod rand;
|
||||||
mod sbi;
|
pub mod sbi;
|
||||||
pub mod signal;
|
pub mod signal;
|
||||||
pub mod syscall;
|
pub mod syscall;
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
@ -36,8 +39,6 @@ fn start_all_harts() {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! {
|
pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! {
|
||||||
let device_tree_vaddr = phys_to_virt(device_tree_paddr);
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
cpu::set_cpu_id(hartid);
|
cpu::set_cpu_id(hartid);
|
||||||
}
|
}
|
||||||
@ -46,15 +47,15 @@ pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! {
|
|||||||
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
|
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
{
|
{
|
||||||
LOTTERY_HART_ID.store(hartid, Ordering::SeqCst);
|
DEVICE_TREE_PADDR.store(device_tree_paddr, Ordering::SeqCst);
|
||||||
start_all_harts();
|
start_all_harts();
|
||||||
}
|
}
|
||||||
let main_hart = LOTTERY_HART_ID.load(Ordering::SeqCst);
|
|
||||||
if hartid != main_hart {
|
if hartid != BOOT_HART_ID {
|
||||||
while !AP_CAN_INIT.load(Ordering::Relaxed) {}
|
while !AP_CAN_INIT.load(Ordering::Relaxed) {}
|
||||||
others_main(hartid);
|
others_main(hartid);
|
||||||
}
|
}
|
||||||
|
let device_tree_vaddr = phys_to_virt(DEVICE_TREE_PADDR.load(Ordering::SeqCst));
|
||||||
unsafe {
|
unsafe {
|
||||||
memory::clear_bss();
|
memory::clear_bss();
|
||||||
}
|
}
|
||||||
@ -93,7 +94,7 @@ fn others_main(hartid: usize) -> ! {
|
|||||||
|
|
||||||
static AP_CAN_INIT: AtomicBool = AtomicBool::new(false);
|
static AP_CAN_INIT: AtomicBool = AtomicBool::new(false);
|
||||||
static FIRST_HART: AtomicBool = AtomicBool::new(false);
|
static FIRST_HART: AtomicBool = AtomicBool::new(false);
|
||||||
static LOTTERY_HART_ID: AtomicUsize = AtomicUsize::new(0);
|
static DEVICE_TREE_PADDR: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
#[cfg(not(feature = "board_u540"))]
|
#[cfg(not(feature = "board_u540"))]
|
||||||
const BOOT_HART_ID: usize = 0;
|
const BOOT_HART_ID: usize = 0;
|
||||||
|
@ -5,7 +5,9 @@ use log::*;
|
|||||||
use rcore_memory::paging::*;
|
use rcore_memory::paging::*;
|
||||||
use riscv::addr::*;
|
use riscv::addr::*;
|
||||||
use riscv::asm::{sfence_vma, sfence_vma_all};
|
use riscv::asm::{sfence_vma, sfence_vma_all};
|
||||||
use riscv::paging::{FrameAllocator, FrameDeallocator};
|
use riscv::paging::MapperFlushable;
|
||||||
|
use riscv::paging::PTE;
|
||||||
|
use riscv::paging::{FrameAllocatorFor, FrameDeallocatorFor};
|
||||||
use riscv::paging::{Mapper, PageTable as RvPageTable, PageTableEntry, PageTableFlags as EF};
|
use riscv::paging::{Mapper, PageTable as RvPageTable, PageTableEntry, PageTableFlags as EF};
|
||||||
use riscv::register::satp;
|
use riscv::register::satp;
|
||||||
|
|
||||||
@ -14,6 +16,13 @@ type TopLevelPageTable<'a> = riscv::paging::Rv32PageTable<'a>;
|
|||||||
#[cfg(target_arch = "riscv64")]
|
#[cfg(target_arch = "riscv64")]
|
||||||
type TopLevelPageTable<'a> = riscv::paging::Rv39PageTable<'a>;
|
type TopLevelPageTable<'a> = riscv::paging::Rv39PageTable<'a>;
|
||||||
|
|
||||||
|
use riscv::use_sv32;
|
||||||
|
use riscv::use_sv39;
|
||||||
|
#[cfg(target_arch = "riscv32")]
|
||||||
|
use_sv32!();
|
||||||
|
#[cfg(target_arch = "riscv64")]
|
||||||
|
use_sv39!();
|
||||||
|
|
||||||
pub struct PageTableImpl {
|
pub struct PageTableImpl {
|
||||||
page_table: TopLevelPageTable<'static>,
|
page_table: TopLevelPageTable<'static>,
|
||||||
root_frame: Frame,
|
root_frame: Frame,
|
||||||
@ -29,7 +38,7 @@ impl PageTable for PageTableImpl {
|
|||||||
// map the 4K `page` to the 4K `frame` with `flags`
|
// map the 4K `page` to the 4K `frame` with `flags`
|
||||||
let flags = EF::VALID | EF::READABLE | EF::WRITABLE;
|
let flags = EF::VALID | EF::READABLE | EF::WRITABLE;
|
||||||
let page = Page::of_addr(VirtAddr::new(addr));
|
let page = Page::of_addr(VirtAddr::new(addr));
|
||||||
let frame = Frame::of_addr(PhysAddr::new(target));
|
let frame = Frame::of_addr(PhysAddr::new_u64(target as u64));
|
||||||
// we may need frame allocator to alloc frame for new page table(first/second)
|
// we may need frame allocator to alloc frame for new page table(first/second)
|
||||||
self.page_table
|
self.page_table
|
||||||
.map_to(page, frame, flags, &mut FrameAllocatorForRiscv)
|
.map_to(page, frame, flags, &mut FrameAllocatorForRiscv)
|
||||||
@ -99,11 +108,11 @@ impl Entry for PageEntry {
|
|||||||
self.0.flags_mut().set(EF::VALID | EF::READABLE, value);
|
self.0.flags_mut().set(EF::VALID | EF::READABLE, value);
|
||||||
}
|
}
|
||||||
fn target(&self) -> usize {
|
fn target(&self) -> usize {
|
||||||
self.0.addr().as_usize()
|
self.0.addr::<PhysAddr>().as_usize()
|
||||||
}
|
}
|
||||||
fn set_target(&mut self, target: usize) {
|
fn set_target(&mut self, target: usize) {
|
||||||
let flags = self.0.flags();
|
let flags = self.0.flags();
|
||||||
let frame = Frame::of_addr(PhysAddr::new(target));
|
let frame = Frame::of_addr(PhysAddr::new_u64(target as u64));
|
||||||
self.0.set(frame, flags);
|
self.0.set(frame, flags);
|
||||||
}
|
}
|
||||||
fn writable_shared(&self) -> bool {
|
fn writable_shared(&self) -> bool {
|
||||||
@ -153,7 +162,7 @@ impl PageTableImpl {
|
|||||||
#[cfg(target_arch = "riscv64")]
|
#[cfg(target_arch = "riscv64")]
|
||||||
let mask = 0x0fffffff_ffffffff;
|
let mask = 0x0fffffff_ffffffff;
|
||||||
let frame = Frame::of_ppn(PageTableImpl::active_token() & mask);
|
let frame = Frame::of_ppn(PageTableImpl::active_token() & mask);
|
||||||
let table = frame.as_kernel_mut(PHYSICAL_MEMORY_OFFSET);
|
let table = frame.as_kernel_mut(PHYSICAL_MEMORY_OFFSET as u64);
|
||||||
ManuallyDrop::new(PageTableImpl {
|
ManuallyDrop::new(PageTableImpl {
|
||||||
page_table: TopLevelPageTable::new(table, PHYSICAL_MEMORY_OFFSET),
|
page_table: TopLevelPageTable::new(table, PHYSICAL_MEMORY_OFFSET),
|
||||||
root_frame: frame,
|
root_frame: frame,
|
||||||
@ -170,7 +179,7 @@ impl PageTableImpl {
|
|||||||
impl PageTableExt for PageTableImpl {
|
impl PageTableExt for PageTableImpl {
|
||||||
fn new_bare() -> Self {
|
fn new_bare() -> Self {
|
||||||
let target = alloc_frame().expect("failed to allocate frame");
|
let target = alloc_frame().expect("failed to allocate frame");
|
||||||
let frame = Frame::of_addr(PhysAddr::new(target));
|
let frame = Frame::of_addr(PhysAddr::new_u64(target as u64));
|
||||||
|
|
||||||
let table = unsafe { &mut *(phys_to_virt(target) as *mut RvPageTable) };
|
let table = unsafe { &mut *(phys_to_virt(target) as *mut RvPageTable) };
|
||||||
table.zero();
|
table.zero();
|
||||||
@ -202,8 +211,8 @@ impl PageTableExt for PageTableImpl {
|
|||||||
}
|
}
|
||||||
let flags =
|
let flags =
|
||||||
EF::VALID | EF::READABLE | EF::WRITABLE | EF::EXECUTABLE | EF::ACCESSED | EF::DIRTY;
|
EF::VALID | EF::READABLE | EF::WRITABLE | EF::EXECUTABLE | EF::ACCESSED | EF::DIRTY;
|
||||||
let frame = Frame::of_addr(PhysAddr::new(
|
let frame = Frame::of_addr(PhysAddr::new_u64(
|
||||||
(0xFFFFFF80_00000000 + (i << 30)) - PHYSICAL_MEMORY_OFFSET,
|
((0xFFFFFF80_00000000 + (i << 30)) - PHYSICAL_MEMORY_OFFSET) as u64,
|
||||||
));
|
));
|
||||||
table[i].set(frame, flags);
|
table[i].set(frame, flags);
|
||||||
}
|
}
|
||||||
@ -239,13 +248,13 @@ impl Drop for PageTableImpl {
|
|||||||
|
|
||||||
struct FrameAllocatorForRiscv;
|
struct FrameAllocatorForRiscv;
|
||||||
|
|
||||||
impl FrameAllocator for FrameAllocatorForRiscv {
|
impl FrameAllocatorFor<PhysAddr> for FrameAllocatorForRiscv {
|
||||||
fn alloc(&mut self) -> Option<Frame> {
|
fn alloc(&mut self) -> Option<Frame> {
|
||||||
alloc_frame().map(|addr| Frame::of_addr(PhysAddr::new(addr)))
|
alloc_frame().map(|addr| Frame::of_addr(PhysAddr::new_u64(addr as u64)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FrameDeallocator for FrameAllocatorForRiscv {
|
impl FrameDeallocatorFor<PhysAddr> for FrameAllocatorForRiscv {
|
||||||
fn dealloc(&mut self, frame: Frame) {
|
fn dealloc(&mut self, frame: Frame) {
|
||||||
dealloc_frame(frame.start_address().as_usize());
|
dealloc_frame(frame.start_address().as_usize());
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,30 @@ pub fn sbi_hart_get_status(hartid: usize) -> SBIRet {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sbi_set_timer(stime_value: u64) -> SBIRet {
|
||||||
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
let ret = sbi_call(
|
||||||
|
SBICall {
|
||||||
|
eid: SBI_EID_TIME,
|
||||||
|
fid: SBI_FID_TIME_SET,
|
||||||
|
},
|
||||||
|
stime_value as usize,
|
||||||
|
(stime_value >> 32) as usize,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
let ret = sbi_call(
|
||||||
|
SBICall {
|
||||||
|
eid: SBI_EID_TIME,
|
||||||
|
fid: SBI_FID_TIME_SET,
|
||||||
|
},
|
||||||
|
stime_value as usize,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
const SBI_SUCCESS: isize = 0;
|
const SBI_SUCCESS: isize = 0;
|
||||||
const SBI_ERR_FAILED: isize = -1;
|
const SBI_ERR_FAILED: isize = -1;
|
||||||
const SBI_ERR_NOT_SUPPORTED: isize = -2;
|
const SBI_ERR_NOT_SUPPORTED: isize = -2;
|
||||||
@ -75,6 +99,8 @@ const SBI_EID_HSM: usize = 0x48534D;
|
|||||||
const SBI_FID_HSM_START: usize = 0;
|
const SBI_FID_HSM_START: usize = 0;
|
||||||
const SBI_FID_HSM_STOP: usize = 1;
|
const SBI_FID_HSM_STOP: usize = 1;
|
||||||
const SBI_FID_HSM_STATUS: usize = 2;
|
const SBI_FID_HSM_STATUS: usize = 2;
|
||||||
|
const SBI_EID_TIME: usize = 0x54494D45;
|
||||||
|
const SBI_FID_TIME_SET: usize = 0;
|
||||||
|
|
||||||
/// Legacy calls.
|
/// Legacy calls.
|
||||||
|
|
||||||
|
@ -33,13 +33,11 @@ pub fn init() {
|
|||||||
/// Set the next timer interrupt
|
/// Set the next timer interrupt
|
||||||
pub fn set_next() {
|
pub fn set_next() {
|
||||||
// 100Hz @ QEMU
|
// 100Hz @ QEMU
|
||||||
let timebase = 250000;
|
let timebase = 100000;
|
||||||
sbi::set_timer(get_cycle() + timebase);
|
sbi::sbi_set_timer(get_cycle() + timebase);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn timer_now() -> Duration {
|
pub fn timer_now() -> Duration {
|
||||||
// TODO: get actual freq
|
|
||||||
const FREQUENCY: u16 = 2600;
|
|
||||||
let time = get_cycle();
|
let time = get_cycle();
|
||||||
Duration::from_nanos(time * 1000 / FREQUENCY as u64)
|
Duration::from_nanos(time * 100)
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ use super::super::block::virtio_blk;
|
|||||||
use super::super::gpu::virtio_gpu;
|
use super::super::gpu::virtio_gpu;
|
||||||
use super::super::input::virtio_input;
|
use super::super::input::virtio_input;
|
||||||
use super::super::net::virtio_net;
|
use super::super::net::virtio_net;
|
||||||
|
use super::super::serial::virtio_console;
|
||||||
use crate::drivers::device_tree::DEVICE_TREE_REGISTRY;
|
use crate::drivers::device_tree::DEVICE_TREE_REGISTRY;
|
||||||
use crate::memory::phys_to_virt;
|
use crate::memory::phys_to_virt;
|
||||||
use device_tree::util::SliceRead;
|
use device_tree::util::SliceRead;
|
||||||
@ -35,6 +36,7 @@ pub fn virtio_probe(node: &Node) {
|
|||||||
DeviceType::Block => virtio_blk::init(header),
|
DeviceType::Block => virtio_blk::init(header),
|
||||||
DeviceType::GPU => virtio_gpu::init(header),
|
DeviceType::GPU => virtio_gpu::init(header),
|
||||||
DeviceType::Input => virtio_input::init(header),
|
DeviceType::Input => virtio_input::init(header),
|
||||||
|
DeviceType::Console => virtio_console::init(node, header),
|
||||||
t => warn!("Unrecognized virtio device: {:?}", t),
|
t => warn!("Unrecognized virtio device: {:?}", t),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,10 @@ impl IntcDriver for Plic {
|
|||||||
/// Register interrupt controller local irq
|
/// Register interrupt controller local irq
|
||||||
fn register_local_irq(&self, irq: usize, driver: Arc<dyn Driver>) {
|
fn register_local_irq(&self, irq: usize, driver: Arc<dyn Driver>) {
|
||||||
// enable irq for context 1
|
// enable irq for context 1
|
||||||
write(self.base + 0x2080, 1 << irq);
|
write(
|
||||||
|
self.base + 0x2080,
|
||||||
|
read::<u32>(self.base + 0x2080) | (1 << irq),
|
||||||
|
);
|
||||||
// set priority to 7
|
// set priority to 7
|
||||||
write(self.base + irq * 4, 7);
|
write(self.base + irq * 4, 7);
|
||||||
let mut manager = self.manager.lock();
|
let mut manager = self.manager.lock();
|
||||||
@ -58,7 +61,7 @@ pub const SupervisorExternal: usize = usize::MAX / 2 + 1 + 8;
|
|||||||
fn init_dt(dt: &Node) {
|
fn init_dt(dt: &Node) {
|
||||||
let addr = dt.prop_u64("reg").unwrap() as usize;
|
let addr = dt.prop_u64("reg").unwrap() as usize;
|
||||||
let phandle = dt.prop_u32("phandle").unwrap();
|
let phandle = dt.prop_u32("phandle").unwrap();
|
||||||
info!("Found riscv plic at {:#x}", addr);
|
info!("Found riscv plic at {:#x}, {:?}", addr, dt);
|
||||||
let base = phys_to_virt(addr);
|
let base = phys_to_virt(addr);
|
||||||
let plic = Arc::new(Plic {
|
let plic = Arc::new(Plic {
|
||||||
base,
|
base,
|
||||||
|
@ -43,10 +43,11 @@ impl RtcDriver for RtcGoldfish {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn init_dt(dt: &Node) {
|
fn init_dt(dt: &Node) {
|
||||||
|
use crate::memory::phys_to_virt;
|
||||||
let addr = dt.prop_u64("reg").unwrap() as usize;
|
let addr = dt.prop_u64("reg").unwrap() as usize;
|
||||||
RTC_DRIVERS
|
RTC_DRIVERS.write().push(Arc::new(RtcGoldfish {
|
||||||
.write()
|
base: phys_to_virt(addr),
|
||||||
.push(Arc::new(RtcGoldfish { base: addr }));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn driver_init() {
|
pub fn driver_init() {
|
||||||
|
@ -11,10 +11,21 @@ pub mod com;
|
|||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
pub mod uart16550;
|
pub mod uart16550;
|
||||||
|
|
||||||
|
pub mod virtio_console;
|
||||||
|
|
||||||
pub trait SerialDriver: Driver {
|
pub trait SerialDriver: Driver {
|
||||||
// read one byte from tty
|
// read one byte from tty
|
||||||
fn read(&self) -> u8;
|
fn read(&self) -> u8;
|
||||||
|
|
||||||
// write bytes to tty
|
// write bytes to tty
|
||||||
fn write(&self, data: &[u8]);
|
fn write(&self, data: &[u8]);
|
||||||
|
|
||||||
|
// get if it is ready. as a hint.
|
||||||
|
fn try_read(&self) -> Option<u8> {
|
||||||
|
Some(self.read())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
use crate::sync::Condvar;
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref SERIAL_ACTIVITY: Condvar = Condvar::new();
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ impl Driver for SerialPort {
|
|||||||
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
|
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
|
||||||
if let Some(c) = self.getchar_option() {
|
if let Some(c) = self.getchar_option() {
|
||||||
crate::trap::serial(c);
|
crate::trap::serial(c);
|
||||||
|
super::SERIAL_ACTIVITY.notify_all();
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@ -72,7 +73,8 @@ impl SerialPort {
|
|||||||
/// non-blocking version of putchar()
|
/// non-blocking version of putchar()
|
||||||
pub fn putchar(&self, c: u8) {
|
pub fn putchar(&self, c: u8) {
|
||||||
for _ in 0..100 {
|
for _ in 0..100 {
|
||||||
if (read::<u8>(self.base + COM_LSR * self.multiplier) & COM_LSR_TXRDY) == 0 {
|
if (read::<u8>(self.base + COM_LSR * self.multiplier) & COM_LSR_TXRDY) == COM_LSR_TXRDY
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,6 +114,9 @@ impl SerialDriver for SerialPort {
|
|||||||
self.putchar(*byte);
|
self.putchar(*byte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn try_read(&self) -> Option<u8> {
|
||||||
|
self.getchar_option()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const COM_RX: usize = 0; // In: Receive buffer (DLAB=0)
|
const COM_RX: usize = 0; // In: Receive buffer (DLAB=0)
|
||||||
@ -149,6 +154,7 @@ pub fn init_dt(dt: &Node) {
|
|||||||
if let Some(manager) = DEVICE_TREE_INTC.write().get_mut(&intc) {
|
if let Some(manager) = DEVICE_TREE_INTC.write().get_mut(&intc) {
|
||||||
manager.register_local_irq(irq, com.clone());
|
manager.register_local_irq(irq, com.clone());
|
||||||
info!("registered uart16550 to intc");
|
info!("registered uart16550 to intc");
|
||||||
|
info!("Init uart16550 at {:#x}, {:?}", base, dt);
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
80
kernel/src/drivers/serial/virtio_console.rs
Normal file
80
kernel/src/drivers/serial/virtio_console.rs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
use alloc::boxed::Box;
|
||||||
|
use alloc::string::String;
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
|
||||||
|
use super::super::{DeviceType, Driver, DRIVERS, IRQ_MANAGER, SERIAL_DRIVERS};
|
||||||
|
use crate::drivers::device_tree::{DEVICE_TREE_INTC, DEVICE_TREE_REGISTRY};
|
||||||
|
use crate::{
|
||||||
|
drivers::{BlockDriver, NetDriver},
|
||||||
|
sync::SpinNoIrqLock as Mutex,
|
||||||
|
};
|
||||||
|
use device_tree::Node;
|
||||||
|
use log::*;
|
||||||
|
use virtio_drivers::VirtIOConsole;
|
||||||
|
use virtio_drivers::{VirtIOHeader, VirtIOInput};
|
||||||
|
|
||||||
|
struct VirtIOConsoleDriver(Mutex<VirtIOConsole<'static>>);
|
||||||
|
pub fn init(dt: &Node, header: &'static mut VirtIOHeader) {
|
||||||
|
let mut console = VirtIOConsole::new(header).expect("failed to create virtio console");
|
||||||
|
let driver = Arc::new(VirtIOConsoleDriver(Mutex::new(console)));
|
||||||
|
let irq_opt = dt.prop_u32("interrupts").ok().map(|irq| irq as usize);
|
||||||
|
let mut found = false;
|
||||||
|
if let Ok(intc) = dt.prop_u32("interrupt-parent") {
|
||||||
|
if let Some(irq) = irq_opt {
|
||||||
|
if let Some(manager) = DEVICE_TREE_INTC.write().get_mut(&intc) {
|
||||||
|
manager.register_local_irq(irq, driver.clone());
|
||||||
|
info!("registered virtio_console to intc");
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
info!("registered virtio_console to root");
|
||||||
|
IRQ_MANAGER.write().register_opt(irq_opt, driver.clone());
|
||||||
|
}
|
||||||
|
SERIAL_DRIVERS.write().push(driver);
|
||||||
|
}
|
||||||
|
impl Driver for VirtIOConsoleDriver {
|
||||||
|
fn try_handle_interrupt(&self, _irq: Option<usize>) -> bool {
|
||||||
|
let mut console = self.0.lock();
|
||||||
|
let ack = console.ack_interrupt().expect("failed to ack interrupt");
|
||||||
|
if ack {
|
||||||
|
super::SERIAL_ACTIVITY.notify_all();
|
||||||
|
}
|
||||||
|
ack
|
||||||
|
}
|
||||||
|
|
||||||
|
fn device_type(&self) -> DeviceType {
|
||||||
|
DeviceType::Serial
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_id(&self) -> String {
|
||||||
|
String::from("virtio_console")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_net(&self) -> Option<&dyn NetDriver> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_block(&self) -> Option<&dyn BlockDriver> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::drivers::serial::SerialDriver for VirtIOConsoleDriver {
|
||||||
|
fn read(&self) -> u8 {
|
||||||
|
let mut console = self.0.lock();
|
||||||
|
console.recv(true).unwrap().unwrap_or(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, data: &[u8]) {
|
||||||
|
let mut console = self.0.lock();
|
||||||
|
for byte in data {
|
||||||
|
console.send(*byte).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn try_read(&self) -> Option<u8> {
|
||||||
|
let mut console = self.0.lock();
|
||||||
|
console.recv(true).unwrap()
|
||||||
|
}
|
||||||
|
}
|
@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
mod fbdev;
|
mod fbdev;
|
||||||
mod random;
|
mod random;
|
||||||
|
mod serial;
|
||||||
mod shm;
|
mod shm;
|
||||||
mod tty;
|
mod tty;
|
||||||
|
|
||||||
pub use fbdev::*;
|
pub use fbdev::*;
|
||||||
pub use random::*;
|
pub use random::*;
|
||||||
|
pub use serial::*;
|
||||||
pub use shm::*;
|
pub use shm::*;
|
||||||
pub use tty::*;
|
pub use tty::*;
|
||||||
|
78
kernel/src/fs/devfs/serial.rs
Normal file
78
kernel/src/fs/devfs/serial.rs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
use crate::drivers::serial::SERIAL_ACTIVITY;
|
||||||
|
use crate::drivers::SerialDriver;
|
||||||
|
use crate::drivers::SERIAL_DRIVERS;
|
||||||
|
use crate::syscall::spin_and_wait;
|
||||||
|
use alloc::sync::Arc;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
use core::any::Any;
|
||||||
|
use rcore_fs::vfs::*;
|
||||||
|
pub struct Serial {
|
||||||
|
id: usize,
|
||||||
|
driver: Arc<dyn SerialDriver>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serial {
|
||||||
|
pub fn new(id: usize, driver: Arc<dyn SerialDriver>) -> Self {
|
||||||
|
Serial { id, driver }
|
||||||
|
}
|
||||||
|
pub fn wrap_all_serial_devices() -> Vec<Self> {
|
||||||
|
let drivers = SERIAL_DRIVERS.read();
|
||||||
|
drivers
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, x)| Serial::new(i, x))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl INode for Serial {
|
||||||
|
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize> {
|
||||||
|
let mut n = 0;
|
||||||
|
for r in buf.iter_mut() {
|
||||||
|
if let Some(x) = self.driver.try_read() {
|
||||||
|
*r = x;
|
||||||
|
n += 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> {
|
||||||
|
self.driver.write(buf);
|
||||||
|
Ok(buf.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll(&self) -> Result<PollStatus> {
|
||||||
|
Ok(PollStatus {
|
||||||
|
read: true,
|
||||||
|
write: true,
|
||||||
|
error: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn metadata(&self) -> Result<Metadata> {
|
||||||
|
Ok(Metadata {
|
||||||
|
dev: 1,
|
||||||
|
inode: 1,
|
||||||
|
size: 0,
|
||||||
|
blk_size: 0,
|
||||||
|
blocks: 0,
|
||||||
|
atime: Timespec { sec: 0, nsec: 0 },
|
||||||
|
mtime: Timespec { sec: 0, nsec: 0 },
|
||||||
|
ctime: Timespec { sec: 0, nsec: 0 },
|
||||||
|
type_: FileType::CharDevice,
|
||||||
|
mode: 0o666,
|
||||||
|
nlinks: 1,
|
||||||
|
uid: 0,
|
||||||
|
gid: 0,
|
||||||
|
rdev: make_rdev(4, self.id),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any_ref(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,7 @@ use rcore_fs_sfs::{INodeImpl, SimpleFileSystem};
|
|||||||
|
|
||||||
use self::devfs::{Fbdev, RandomINode};
|
use self::devfs::{Fbdev, RandomINode};
|
||||||
|
|
||||||
pub use self::devfs::{ShmINode, TTY};
|
pub use self::devfs::{Serial, ShmINode, TTY};
|
||||||
pub use self::file::*;
|
pub use self::file::*;
|
||||||
pub use self::file_like::*;
|
pub use self::file_like::*;
|
||||||
pub use self::pipe::Pipe;
|
pub use self::pipe::Pipe;
|
||||||
@ -82,6 +82,10 @@ lazy_static! {
|
|||||||
devfs.add("tty", TTY.clone()).expect("failed to mknod /dev/tty");
|
devfs.add("tty", TTY.clone()).expect("failed to mknod /dev/tty");
|
||||||
devfs.add("fb0", Arc::new(Fbdev::default())).expect("failed to mknod /dev/fb0");
|
devfs.add("fb0", Arc::new(Fbdev::default())).expect("failed to mknod /dev/fb0");
|
||||||
devfs.add("shm", Arc::new(ShmINode::default())).expect("failed to mkdir shm");
|
devfs.add("shm", Arc::new(ShmINode::default())).expect("failed to mkdir shm");
|
||||||
|
for (i, serial) in Serial::wrap_all_serial_devices().into_iter().enumerate(){
|
||||||
|
devfs.add(&format!("ttyS{}", i), Arc::new(serial)).expect("failed to add a serial");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(feature = "hypervisor")]
|
#[cfg(feature = "hypervisor")]
|
||||||
devfs.add("rvm", Arc::new(crate::rvm::RvmINode::new())).expect("failed to mknod /dev/rvm");
|
devfs.add("rvm", Arc::new(crate::rvm::RvmINode::new())).expect("failed to mknod /dev/rvm");
|
||||||
|
@ -139,6 +139,19 @@ pub fn handle_page_fault(addr: usize) -> bool {
|
|||||||
lock.handle_page_fault(addr)
|
lock.handle_page_fault(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handle page fault at `addr` with access type `access`.
|
||||||
|
/// Return true to continue, false to halt.
|
||||||
|
pub fn handle_page_fault_ext(addr: usize, access: crate::memory::AccessType) -> bool {
|
||||||
|
debug!(
|
||||||
|
"page fault from kernel @ {:#x} with access type {:?}",
|
||||||
|
addr, access
|
||||||
|
);
|
||||||
|
|
||||||
|
let thread = current_thread().unwrap();
|
||||||
|
let mut lock = thread.vm.lock();
|
||||||
|
lock.handle_page_fault_ext(addr, access)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init_heap() {
|
pub fn init_heap() {
|
||||||
use crate::consts::KERNEL_HEAP_SIZE;
|
use crate::consts::KERNEL_HEAP_SIZE;
|
||||||
const MACHINE_ALIGN: usize = mem::size_of::<usize>();
|
const MACHINE_ALIGN: usize = mem::size_of::<usize>();
|
||||||
@ -190,7 +203,6 @@ pub unsafe extern "C" fn read_user_fixup() -> usize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_from_user<T>(addr: *const T) -> Option<T> {
|
pub fn copy_from_user<T>(addr: *const T) -> Option<T> {
|
||||||
#[naked]
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
#[link_section = ".text.copy_user"]
|
#[link_section = ".text.copy_user"]
|
||||||
unsafe extern "C" fn read_user<T>(dst: *mut T, src: *const T) -> usize {
|
unsafe extern "C" fn read_user<T>(dst: *mut T, src: *const T) -> usize {
|
||||||
@ -208,7 +220,6 @@ pub fn copy_from_user<T>(addr: *const T) -> Option<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_to_user<T>(addr: *mut T, src: *const T) -> bool {
|
pub fn copy_to_user<T>(addr: *mut T, src: *const T) -> bool {
|
||||||
#[naked]
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
#[link_section = ".text.copy_user"]
|
#[link_section = ".text.copy_user"]
|
||||||
unsafe extern "C" fn write_user<T>(dst: *mut T, src: *const T) -> usize {
|
unsafe extern "C" fn write_user<T>(dst: *mut T, src: *const T) -> usize {
|
||||||
|
@ -5,7 +5,7 @@ use super::{
|
|||||||
use crate::arch::interrupt::consts::{
|
use crate::arch::interrupt::consts::{
|
||||||
is_intr, is_page_fault, is_reserved_inst, is_syscall, is_timer_intr,
|
is_intr, is_page_fault, is_reserved_inst, is_syscall, is_timer_intr,
|
||||||
};
|
};
|
||||||
use crate::arch::interrupt::{get_trap_num, handle_reserved_inst, handle_user_page_fault};
|
use crate::arch::interrupt::{get_trap_num, handle_reserved_inst};
|
||||||
use crate::arch::{
|
use crate::arch::{
|
||||||
cpu,
|
cpu,
|
||||||
fp::FpState,
|
fp::FpState,
|
||||||
@ -505,10 +505,8 @@ pub fn spawn(thread: Arc<Thread>) {
|
|||||||
thread_context.fp.restore();
|
thread_context.fp.restore();
|
||||||
cx.run();
|
cx.run();
|
||||||
thread_context.fp.save();
|
thread_context.fp.save();
|
||||||
|
|
||||||
let trap_num = get_trap_num(&cx);
|
let trap_num = get_trap_num(&cx);
|
||||||
trace!("back from user: {:#x?} trap_num {:#x}", cx, trap_num);
|
trace!("back from user: {:#x?} trap_num {:#x}", cx, trap_num);
|
||||||
|
|
||||||
let mut exit = false;
|
let mut exit = false;
|
||||||
let mut do_yield = false;
|
let mut do_yield = false;
|
||||||
match trap_num {
|
match trap_num {
|
||||||
@ -517,10 +515,36 @@ pub fn spawn(thread: Arc<Thread>) {
|
|||||||
// page fault
|
// page fault
|
||||||
let addr = get_page_fault_addr();
|
let addr = get_page_fault_addr();
|
||||||
info!("page fault from user @ {:#x}", addr);
|
info!("page fault from user @ {:#x}", addr);
|
||||||
|
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||||
if !handle_user_page_fault(&thread, addr) {
|
{
|
||||||
// TODO: SIGSEGV
|
use crate::arch::interrupt::consts::{
|
||||||
panic!("page fault handle failed");
|
is_execute_page_fault, is_read_page_fault, is_write_page_fault,
|
||||||
|
};
|
||||||
|
use crate::arch::interrupt::handle_user_page_fault_ext;
|
||||||
|
let access_type = match trap_num {
|
||||||
|
_ if is_execute_page_fault(trap_num) => {
|
||||||
|
crate::memory::AccessType::execute(true)
|
||||||
|
}
|
||||||
|
_ if is_read_page_fault(trap_num) => {
|
||||||
|
crate::memory::AccessType::read(true)
|
||||||
|
}
|
||||||
|
_ if is_write_page_fault(trap_num) => {
|
||||||
|
crate::memory::AccessType::write(true)
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
if !handle_user_page_fault_ext(&thread, addr, access_type) {
|
||||||
|
// TODO: SIGSEGV
|
||||||
|
panic!("page fault handle failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
|
||||||
|
{
|
||||||
|
use crate::arch::interrupt::handle_user_page_fault;
|
||||||
|
if !handle_user_page_fault(&thread, addr) {
|
||||||
|
// TODO: SIGSEGV
|
||||||
|
panic!("page fault handle failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ if is_syscall(trap_num) => exit = handle_syscall(&thread, cx).await,
|
_ if is_syscall(trap_num) => exit = handle_syscall(&thread, cx).await,
|
||||||
|
@ -26,6 +26,16 @@ const RVM_VCPU_READ_STATE: u32 = RVM_IO + 0x13;
|
|||||||
const RVM_VCPU_WRITE_STATE: u32 = RVM_IO + 0x14;
|
const RVM_VCPU_WRITE_STATE: u32 = RVM_IO + 0x14;
|
||||||
const RVM_VCPU_INTERRUPT: u32 = RVM_IO + 0x15;
|
const RVM_VCPU_INTERRUPT: u32 = RVM_IO + 0x15;
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))]
|
||||||
|
mod riscv_intr_constants {
|
||||||
|
pub const RVM_RISCV_SET_SSIP: u32 = 0;
|
||||||
|
pub const RVM_RISCV_CLEAR_SSIP: u32 = 1;
|
||||||
|
pub const RVM_RISCV_SET_SEIP: u32 = 2;
|
||||||
|
pub const RVM_RISCV_CLEAR_SEIP: u32 = 3;
|
||||||
|
}
|
||||||
|
#[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))]
|
||||||
|
use riscv_intr_constants::*;
|
||||||
|
|
||||||
pub struct RvmINode {
|
pub struct RvmINode {
|
||||||
guests: RwLock<BTreeMap<usize, Guest>>,
|
guests: RwLock<BTreeMap<usize, Guest>>,
|
||||||
vcpus: RwLock<BTreeMap<usize, Vcpu>>,
|
vcpus: RwLock<BTreeMap<usize, Vcpu>>,
|
||||||
@ -44,6 +54,7 @@ struct RvmGuestAddMemoryRegionArgs {
|
|||||||
vmid: u16,
|
vmid: u16,
|
||||||
guest_start_paddr: u64,
|
guest_start_paddr: u64,
|
||||||
memory_size: u64,
|
memory_size: u64,
|
||||||
|
userspace_addr: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -118,16 +129,19 @@ impl INode for RvmINode {
|
|||||||
self.guest_create().map_err(into_fs_error)
|
self.guest_create().map_err(into_fs_error)
|
||||||
}
|
}
|
||||||
RVM_GUEST_ADD_MEMORY_REGION => {
|
RVM_GUEST_ADD_MEMORY_REGION => {
|
||||||
let args = UserInPtr::<RvmGuestAddMemoryRegionArgs>::from(data)
|
let mut ptr = UserInOutPtr::<RvmGuestAddMemoryRegionArgs>::from(data);
|
||||||
.read()
|
let mut args = ptr.read().or(Err(FsError::InvalidParam))?;
|
||||||
.or(Err(FsError::InvalidParam))?;
|
|
||||||
info!("[RVM] ioctl RVM_GUEST_ADD_MEMORY_REGION {:x?}", args);
|
info!("[RVM] ioctl RVM_GUEST_ADD_MEMORY_REGION {:x?}", args);
|
||||||
self.guest_add_memory_region(
|
let userspace_addr = self
|
||||||
args.vmid as usize,
|
.guest_add_memory_region(
|
||||||
args.guest_start_paddr as usize,
|
args.vmid as usize,
|
||||||
args.memory_size as usize,
|
args.guest_start_paddr as usize,
|
||||||
)
|
args.memory_size as usize,
|
||||||
.map_err(into_fs_error)
|
)
|
||||||
|
.map_err(into_fs_error)?;
|
||||||
|
args.userspace_addr = userspace_addr as u64;
|
||||||
|
ptr.write(args).or(Err(FsError::DeviceError))?;
|
||||||
|
Ok(0)
|
||||||
}
|
}
|
||||||
RVM_GUEST_SET_TRAP => {
|
RVM_GUEST_SET_TRAP => {
|
||||||
let args = UserInPtr::<RvmGuestSetTrapArgs>::from(data)
|
let args = UserInPtr::<RvmGuestSetTrapArgs>::from(data)
|
||||||
@ -354,7 +368,7 @@ impl RvmINode {
|
|||||||
Err(RvmError::InvalidParam)
|
Err(RvmError::InvalidParam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(any(target_arch = "x86_64"))]
|
||||||
fn vcpu_interrupt(&self, vcpu_id: usize, vector: u32) -> RvmResult<()> {
|
fn vcpu_interrupt(&self, vcpu_id: usize, vector: u32) -> RvmResult<()> {
|
||||||
if let Some(vcpu) = self.vcpus.write().get_mut(&vcpu_id) {
|
if let Some(vcpu) = self.vcpus.write().get_mut(&vcpu_id) {
|
||||||
vcpu.inner.lock().virtual_interrupt(vector)
|
vcpu.inner.lock().virtual_interrupt(vector)
|
||||||
@ -362,6 +376,25 @@ impl RvmINode {
|
|||||||
Err(RvmError::InvalidParam)
|
Err(RvmError::InvalidParam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||||
|
fn vcpu_interrupt(&self, vcpu_id: usize, arg: u32) -> RvmResult<()> {
|
||||||
|
if let Some(vcpu) = self.vcpus.write().get_mut(&vcpu_id) {
|
||||||
|
//vcpu.inner.lock().virtual_interrupt(vector)
|
||||||
|
let irq = &vcpu.irq;
|
||||||
|
match arg {
|
||||||
|
self::RVM_RISCV_SET_SSIP => irq.set_software_interrupt(true),
|
||||||
|
self::RVM_RISCV_CLEAR_SSIP => irq.set_software_interrupt(false),
|
||||||
|
self::RVM_RISCV_SET_SEIP => irq.set_external_interrupt(true),
|
||||||
|
self::RVM_RISCV_CLEAR_SEIP => irq.set_external_interrupt(false),
|
||||||
|
_ => {
|
||||||
|
return Err(RvmError::InvalidParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(RvmError::InvalidParam)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: remove guest & vcpu
|
// TODO: remove guest & vcpu
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,7 @@ impl<T: FrameAllocator> MemoryHandler for RvmPageTableHandlerDelay<T> {
|
|||||||
if target == 0 {
|
if target == 0 {
|
||||||
target = self.allocator.alloc().expect("failed to alloc frame");
|
target = self.allocator.alloc().expect("failed to alloc frame");
|
||||||
}
|
}
|
||||||
|
info!("guest_paddr={}, target={}", guest_paddr, target);
|
||||||
rvm_pt
|
rvm_pt
|
||||||
.map(guest_paddr, target, GuestMemoryAttr::default())
|
.map(guest_paddr, target, GuestMemoryAttr::default())
|
||||||
.expect("failed to create GPA -> HPA mapping");
|
.expect("failed to create GPA -> HPA mapping");
|
||||||
|
@ -28,15 +28,20 @@ fn into_fs_error(e: RvmError) -> FsError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod rvm_extern_fn {
|
mod rvm_extern_fn {
|
||||||
use crate::memory::{alloc_frame, dealloc_frame, phys_to_virt};
|
use crate::memory::{alloc_frame_contiguous, dealloc_frame, phys_to_virt};
|
||||||
#[rvm::extern_fn(alloc_frame)]
|
use rvm::PAGE_SIZE;
|
||||||
fn rvm_alloc_frame() -> Option<usize> {
|
#[rvm::extern_fn(alloc_frames)]
|
||||||
alloc_frame()
|
fn rvm_alloc_frames(n: usize, align_log2: usize) -> Option<usize> {
|
||||||
|
alloc_frame_contiguous(n, align_log2)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rvm::extern_fn(dealloc_frame)]
|
#[rvm::extern_fn(dealloc_frames)]
|
||||||
fn rvm_dealloc_frame(paddr: usize) {
|
fn rvm_dealloc_frames(paddr: usize, n: usize, _align_log2: usize) {
|
||||||
dealloc_frame(paddr)
|
for i in 0..n {
|
||||||
|
dealloc_frame(paddr + i * PAGE_SIZE)
|
||||||
|
}
|
||||||
|
//use crate::memory::dealloc_frame_contiguous;
|
||||||
|
//dealloc_frame_contiguous(paddr, n, align_log2)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rvm::extern_fn(phys_to_virt)]
|
#[rvm::extern_fn(phys_to_virt)]
|
||||||
@ -45,11 +50,31 @@ mod rvm_extern_fn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
#[rvm::extern_fn(x86_all_traps_handler_addr)]
|
#[rvm::extern_fn(is_host_timer_interrupt)]
|
||||||
unsafe fn rvm_x86_all_traps_handler_addr() -> usize {
|
fn rvm_x86_is_host_timer_interrupt(_vec: u8) -> bool {
|
||||||
extern "C" {
|
// TODO: fill in the blanks.
|
||||||
fn __alltraps();
|
false
|
||||||
|
}
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
#[rvm::extern_fn(is_host_serial_interrupt)]
|
||||||
|
fn rvm_x86_is_host_serial_interrupt(_vec: u8) -> bool {
|
||||||
|
// TODO: fill in the blanks.
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))]
|
||||||
|
#[rvm::extern_fn(riscv_trap_handler_no_frame)]
|
||||||
|
fn rvm_riscv_trap_handler_no_frame(sepc: &mut usize) {
|
||||||
|
crate::arch::interrupt::trap_handler_no_frame(sepc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))]
|
||||||
|
#[rvm::extern_fn(riscv_check_hypervisor_extension)]
|
||||||
|
fn rvm_riscv_check_hypervisor_extension() -> bool {
|
||||||
|
if cfg!(feature = "hypervisor") {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
__alltraps as usize
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,10 @@ pub(super) struct Guest {
|
|||||||
|
|
||||||
pub(super) struct Vcpu {
|
pub(super) struct Vcpu {
|
||||||
pub(super) inner: Mutex<VcpuInner>,
|
pub(super) inner: Mutex<VcpuInner>,
|
||||||
|
//#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||||
|
//inner_id: usize,
|
||||||
|
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||||
|
pub(super) irq: Arc<rvm::InterruptState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Guest {
|
impl Guest {
|
||||||
@ -47,8 +51,22 @@ impl Guest {
|
|||||||
|
|
||||||
impl Vcpu {
|
impl Vcpu {
|
||||||
pub fn new(entry: u64, guest: Arc<GuestInner>) -> RvmResult<Self> {
|
pub fn new(entry: u64, guest: Arc<GuestInner>) -> RvmResult<Self> {
|
||||||
Ok(Self {
|
#[cfg(any(target_arch = "x86_64"))]
|
||||||
inner: Mutex::new(VcpuInner::new(entry, guest)?),
|
{
|
||||||
})
|
Ok(Self {
|
||||||
|
inner: Mutex::new(VcpuInner::new(entry, guest)?),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||||
|
{
|
||||||
|
let inner = VcpuInner::new(entry, Arc::clone(&guest))?;
|
||||||
|
let inner_id = inner.get_id();
|
||||||
|
let irq = guest.get_irq_by_id(inner_id);
|
||||||
|
return Ok(Self {
|
||||||
|
inner: Mutex::new(inner),
|
||||||
|
//inner_id,
|
||||||
|
irq,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,7 @@ impl Syscall<'_> {
|
|||||||
for elm in slice {
|
for elm in slice {
|
||||||
unsafe {
|
unsafe {
|
||||||
// to prevent overflow
|
// to prevent overflow
|
||||||
*elm = (i + crate::trap::TICK as u8 as u16) as u8;
|
*elm = (i + crate::trap::wall_tick() as u8 as u16) as u8;
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ impl Syscall<'_> {
|
|||||||
let rusage = unsafe { self.vm().check_write_ptr(rusage)? };
|
let rusage = unsafe { self.vm().check_write_ptr(rusage)? };
|
||||||
|
|
||||||
let tick_base = *TICK_BASE;
|
let tick_base = *TICK_BASE;
|
||||||
let tick = unsafe { crate::trap::TICK as u64 };
|
let tick = unsafe { crate::trap::wall_tick() as u64 };
|
||||||
|
|
||||||
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 {
|
||||||
@ -68,7 +68,7 @@ impl Syscall<'_> {
|
|||||||
let buf = unsafe { self.vm().check_write_ptr(buf)? };
|
let buf = unsafe { self.vm().check_write_ptr(buf)? };
|
||||||
|
|
||||||
let _tick_base = *TICK_BASE;
|
let _tick_base = *TICK_BASE;
|
||||||
let tick = unsafe { crate::trap::TICK as u64 };
|
let tick = unsafe { crate::trap::wall_tick() as u64 };
|
||||||
|
|
||||||
let new_buf = Tms {
|
let new_buf = Tms {
|
||||||
tms_utime: 0,
|
tms_utime: 0,
|
||||||
@ -85,7 +85,7 @@ impl Syscall<'_> {
|
|||||||
// should be initialized together
|
// should be initialized together
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref EPOCH_BASE: u64 = crate::drivers::rtc::read_epoch();
|
pub static ref EPOCH_BASE: u64 = crate::drivers::rtc::read_epoch();
|
||||||
pub static ref TICK_BASE: u64 = unsafe { crate::trap::TICK as u64 };
|
pub static ref TICK_BASE: u64 = unsafe { crate::trap::wall_tick() as u64 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1ms msec
|
// 1ms msec
|
||||||
@ -102,7 +102,7 @@ const NSEC_PER_MSEC: u64 = 1_000_000;
|
|||||||
fn get_epoch_usec() -> u64 {
|
fn get_epoch_usec() -> u64 {
|
||||||
let tick_base = *TICK_BASE;
|
let tick_base = *TICK_BASE;
|
||||||
let epoch_base = *EPOCH_BASE;
|
let epoch_base = *EPOCH_BASE;
|
||||||
let tick = unsafe { crate::trap::TICK as u64 };
|
let tick = unsafe { crate::trap::wall_tick() as u64 };
|
||||||
|
|
||||||
(tick - tick_base) * USEC_PER_TICK as u64 + epoch_base * USEC_PER_SEC
|
(tick - tick_base) * USEC_PER_TICK as u64 + epoch_base * USEC_PER_SEC
|
||||||
}
|
}
|
||||||
|
@ -3,19 +3,32 @@ use crate::consts::INFORM_PER_MSEC;
|
|||||||
use crate::process::*;
|
use crate::process::*;
|
||||||
use crate::sync::SpinNoIrqLock as Mutex;
|
use crate::sync::SpinNoIrqLock as Mutex;
|
||||||
use crate::{signal::SignalUserContext, sync::Condvar};
|
use crate::{signal::SignalUserContext, sync::Condvar};
|
||||||
|
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use naive_timer::Timer;
|
use naive_timer::Timer;
|
||||||
use trapframe::TrapFrame;
|
use trapframe::TrapFrame;
|
||||||
use trapframe::UserContext;
|
use trapframe::UserContext;
|
||||||
|
pub static TICK: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
pub static TICK_ALL_PROCESSORS: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
pub static mut TICK: usize = 0;
|
pub unsafe fn wall_tick() -> usize {
|
||||||
|
return TICK.load(Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
pub fn cpu_tick() -> usize {
|
||||||
|
return TICK_ALL_PROCESSORS.load(Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
pub fn do_tick() {
|
||||||
|
if crate::arch::cpu::id() == 0 {
|
||||||
|
let ret = TICK.fetch_add(1, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
TICK_ALL_PROCESSORS.fetch_add(1, Ordering::Relaxed);
|
||||||
|
}
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref TICK_ACTIVITY: Condvar = Condvar::new();
|
pub static ref TICK_ACTIVITY: Condvar = Condvar::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uptime_msec() -> usize {
|
pub fn uptime_msec() -> usize {
|
||||||
unsafe { crate::trap::TICK * crate::consts::USEC_PER_TICK / 1000 }
|
unsafe { crate::trap::wall_tick() * crate::consts::USEC_PER_TICK / 1000 }
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
@ -23,6 +36,9 @@ lazy_static! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn timer() {
|
pub fn timer() {
|
||||||
|
do_tick();
|
||||||
|
//let ret=unsafe{wall_tick()};
|
||||||
|
|
||||||
let now = crate::arch::timer::timer_now();
|
let now = crate::arch::timer::timer_now();
|
||||||
NAIVE_TIMER.lock().expire(now);
|
NAIVE_TIMER.lock().expire(now);
|
||||||
}
|
}
|
||||||
|
2
tools/gdbinit-sbi
Normal file
2
tools/gdbinit-sbi
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
file ../tools/sbi/fw_jump.elf
|
||||||
|
target remote 127.0.0.1:1234
|
2
user
2
user
@ -1 +1 @@
|
|||||||
Subproject commit 94620bd696ac61b40129d845671cde83001fdf61
|
Subproject commit 1c5e883fcfb0dc18895dce7b1931d7cf3a4261b1
|
Loading…
Reference in New Issue
Block a user