Merge pull request #52 from oscourse-tsinghua/dev

Dev
master
PanQL 6 years ago committed by GitHub
commit 3b9e7e0216
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

1
.gitignore vendored

@ -1,6 +1,7 @@
build
target
/kernel/src/arch/x86_64/interrupt/vector.asm
/kernel/src/arch/mipsel/boot/linker.ld
*.gen.s
*.dtb

@ -109,8 +109,8 @@ impl<T: PageTable> CowExt<T> {
self.rc_map.write_decrease(&frame);
return true;
}
use core::mem::uninitialized;
let mut temp_data: [u8; PAGE_SIZE] = unsafe { uninitialized() };
use core::mem::MaybeUninit;
let mut temp_data: [u8; PAGE_SIZE] = unsafe { MaybeUninit::uninitialized().into_initialized() };
temp_data[..].copy_from_slice(self.get_page_slice_mut(addr));
self.unmap_shared(addr);

@ -1,6 +1,7 @@
#![cfg_attr(not(test), no_std)]
#![feature(alloc)]
#![feature(nll)]
#![feature(maybe_uninit)]
// import macros from log
use log::*;

@ -144,10 +144,10 @@ impl MockPageTable {
** @retval MockPageTable the mock page table created
*/
pub fn new() -> Self {
use core::mem::uninitialized;
use core::mem::MaybeUninit;
MockPageTable {
entries: [MockEntry::default(); PAGE_COUNT],
data: unsafe { uninitialized() },
data: unsafe { MaybeUninit::uninitialized().into_initialized() },
page_fault_handler: None,
}
}

@ -5,7 +5,7 @@
use super::Swapper;
use alloc::collections::BTreeMap;
use core::mem::uninitialized;
use core::mem::MaybeUninit;
const PAGE_SIZE: usize = 4096;
@ -17,7 +17,7 @@ pub struct MockSwapper {
impl Swapper for MockSwapper {
fn swap_out(&mut self, data: &[u8]) -> Result<usize, ()> {
let id = self.alloc_id();
let mut slice: [u8; PAGE_SIZE] = unsafe { uninitialized() };
let mut slice: [u8; PAGE_SIZE] = unsafe { MaybeUninit::uninitialized().into_initialized() };
slice.copy_from_slice(data);
self.map.insert(id, slice);
Ok(id)
@ -27,7 +27,7 @@ impl Swapper for MockSwapper {
if !self.map.contains_key(&token) {
return Err(());
}
let mut slice: [u8; PAGE_SIZE] = unsafe { uninitialized() };
let mut slice: [u8; PAGE_SIZE] = unsafe { MaybeUninit::uninitialized().into_initialized() };
slice.copy_from_slice(data);
self.map.insert(token, slice);
Ok(())
@ -64,8 +64,8 @@ mod test {
#[test]
fn swap_out_in() {
let mut swapper = MockSwapper::default();
let mut data: [u8; 4096] = unsafe { uninitialized() };
let data1: [u8; 4096] = unsafe { uninitialized() };
let mut data: [u8; 4096] = unsafe { MaybeUninit::uninitialized().into_initialized() };
let data1: [u8; 4096] = unsafe { MaybeUninit::uninitialized().into_initialized() };
let token = swapper.swap_out(&data1).unwrap();
swapper.swap_in(token, &mut data).unwrap();
assert_data_eq(&data, &data1);
@ -74,9 +74,9 @@ mod test {
#[test]
fn swap_update() {
let mut swapper = MockSwapper::default();
let mut data: [u8; 4096] = unsafe { uninitialized() };
let data1: [u8; 4096] = unsafe { uninitialized() };
let data2: [u8; 4096] = unsafe { uninitialized() };
let mut data: [u8; 4096] = unsafe { MaybeUninit::uninitialized().into_initialized() };
let data1: [u8; 4096] = unsafe { MaybeUninit::uninitialized().into_initialized() };
let data2: [u8; 4096] = unsafe { MaybeUninit::uninitialized().into_initialized() };
let token = swapper.swap_out(&data1).unwrap();
swapper.swap_update(token, &data2).unwrap();
swapper.swap_in(token, &mut data).unwrap();
@ -86,7 +86,7 @@ mod test {
#[test]
fn invalid_token() {
let mut swapper = MockSwapper::default();
let mut data: [u8; 4096] = unsafe { uninitialized() };
let mut data: [u8; 4096] = unsafe { MaybeUninit::uninitialized().into_initialized() };
assert_eq!(swapper.swap_in(0, &mut data), Err(()));
}
}

10
kernel/Cargo.lock generated

@ -82,8 +82,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitvec"
version = "0.11.0"
source = "git+https://github.com/myrrlyn/bitvec.git#8ab20a3e33fe068fc3a4a05eda1211d5fcc1237b"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bootloader"
@ -377,7 +377,7 @@ 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)",
"bitmap-allocator 0.1.0 (git+https://github.com/rcore-os/bitmap-allocator)",
"bitvec 0.11.0 (git+https://github.com/myrrlyn/bitvec.git)",
"bitvec 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bootloader 0.4.0 (git+https://github.com/rcore-os/bootloader?branch=vga)",
"buddy_system_allocator 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)",
@ -435,7 +435,7 @@ dependencies = [
[[package]]
name = "rcore-thread"
version = "0.1.0"
source = "git+https://github.com/rcore-os/rcore-thread#77e8e0778154734ee59525e043caab6339e14d75"
source = "git+https://github.com/rcore-os/rcore-thread#56021ab440fab8c7b819fed6a42649fb8bbaec07"
dependencies = [
"deque 0.3.2 (git+https://github.com/rcore-os/deque.git?branch=no_std)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -691,7 +691,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum bitmap-allocator 0.1.0 (git+https://github.com/rcore-os/bitmap-allocator)" = "<none>"
"checksum bitvec 0.11.0 (git+https://github.com/myrrlyn/bitvec.git)" = "<none>"
"checksum bitvec 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c28d4291b516ccfbb897d45de3c468c135e6af7c4f1f1aacfaae0a5bc2e6ea2c"
"checksum bitvec 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cfadef5c4e2c2e64067b9ecc061179f12ac7ec65ba613b1f60f3972bbada1f5b"
"checksum bootloader 0.4.0 (git+https://github.com/rcore-os/bootloader?branch=vga)" = "<none>"
"checksum buddy_system_allocator 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "59da15ef556589ee78370281d75b67f2d69ed26465ec0e0f3961e2021502426f"

@ -53,7 +53,7 @@ bitflags = "1.0"
bit_field = "0.9"
volatile = "0.2"
heapless = "0.4"
bitvec = { git = "https://github.com/myrrlyn/bitvec.git", default-features = false, features = ["alloc"] }
bitvec = { version = "0.11", default-features = false, features = ["alloc"] }
console-traits = "0.3"
buddy_system_allocator = "0.3"
pci = { git = "https://github.com/rcore-os/pci-rs" }

@ -98,6 +98,7 @@ export DTB = $(dtb)
qemu_opts := \
-smp cores=$(smp)
qemu_net_opts :=
qemu_ui_opts :=
ifeq ($(arch), x86_64)
qemu_opts += \
@ -120,6 +121,8 @@ qemu_opts += \
-machine accel=kvm
qemu_net_opts += \
-device vfio-pci,host=$(pci_passthru)
qemu_ui_opts += \
-vga std
endif
ifeq ($(extra_nic), on)
qemu_net_opts += \
@ -138,6 +141,9 @@ qemu_opts += \
qemu_net_opts += \
-netdev type=tap,id=net0,script=no,downscript=no \
-device virtio-net-device,netdev=net0
qemu_ui_opts += \
-device virtio-gpu-device \
-device virtio-mouse-device
else ifeq ($(arch), riscv64)
ifeq ($(board), u540)
@ -158,6 +164,9 @@ endif
qemu_net_opts += \
-netdev type=tap,id=net0,script=no,downscript=no \
-device virtio-net-device,netdev=net0
qemu_ui_opts += \
-device virtio-gpu-device \
-device virtio-mouse-device
else ifeq ($(arch), aarch64)
qemu_opts += \
@ -271,9 +280,7 @@ justrunnet: build
@sudo qemu-system-$(arch) $(qemu_opts) $(qemu_net_opts)
justrunui: build
@qemu-system-$(arch) $(qemu_opts) \
-device virtio-gpu-device \
-device virtio-mouse-device
@qemu-system-$(arch) $(qemu_opts) $(qemu_ui_opts)
justruntest: build
@qemu-system-$(arch) $(filter-out -serial mon:stdio, $(qemu_opts)) --append $(init) -serial file:../tests/stdout -monitor null
@ -346,8 +353,9 @@ else ifeq ($(arch), aarch64)
@cargo xbuild $(build_args)
else ifeq ($(arch), mipsel)
@for file in context entry trap ; do \
$(hostcc) -E src/arch/$(arch)/boot/$${file}.S -o src/arch/$(arch)/boot/$${file}.gen.s ; \
$(hostcc) -Dboard_$(board) -E src/arch/$(arch)/boot/$${file}.S -o src/arch/$(arch)/boot/$${file}.gen.s ; \
done
$(hostcc) -Dboard_$(board) -E src/arch/$(arch)/boot/linker.ld.S -o src/arch/$(arch)/boot/linker.ld
@cargo xbuild $(build_args)
endif

@ -212,7 +212,7 @@ impl PageTableImpl {
PageTableImpl {
page_table: MappedPageTable::new(table, frame_to_page_table),
root_frame: frame,
entry: core::mem::uninitialized(),
entry: core::mem::MaybeUninit::uninitialized().into_initialized(),
}
}
}
@ -227,7 +227,7 @@ impl PageTableExt for PageTableImpl {
PageTableImpl {
page_table: MappedPageTable::new(table, frame_to_page_table),
root_frame: frame,
entry: core::mem::uninitialized(),
entry: core::mem::MaybeUninit::uninitialized().into_initialized(),
}
}
}

@ -1,3 +1,3 @@
/// board specific constants
pub const MEMORY_END: usize = 0x8800_0000;
pub const KERNEL_HEAP_SIZE: usize = 0x0044_0000;
pub const MEMORY_END: usize = 0x8090_0000;
pub const KERNEL_HEAP_SIZE: usize = 0x003b_0000;

@ -9,7 +9,7 @@
chosen {
stdio = &uart2;
bootargs = "rust/sh";
bootargs = "sh";
};
aliases { };

@ -1,3 +1,3 @@
/// board specific constants
pub const MEMORY_END: usize = 0x8080_0000;
pub const KERNEL_HEAP_SIZE: usize = 0x0044_0000;
pub const KERNEL_HEAP_SIZE: usize = 0x0038_0000;

@ -9,7 +9,7 @@
chosen {
stdio = &uart;
bootargs = "";
bootargs = "sh";
};
aliases { };

@ -4,7 +4,11 @@
OUTPUT_ARCH(riscv)
ENTRY(_start)
#ifdef board_thinpad
BASE_ADDRESS = 0x80000000;
#else
BASE_ADDRESS = 0x80100000;
#endif
SECTIONS
{

@ -32,6 +32,12 @@ trap_from_kernel:
* k1 = old stack pointer
* sp = kernel stack */
#ifdef board_thinpad
#define TRAPFRAME_SIZE 304
#else
#define TRAPFRAME_SIZE 176
#endif
# align stack pointer
andi k0, sp, 0xf
beqz k0, sp_aligned
@ -39,12 +45,13 @@ trap_from_kernel:
la k0, 0xfffffff0
and k0, sp, k0
sw sp, -176(k0)
sw sp, -TRAPFRAME_SIZE(k0)
move sp, k0
sp_aligned:
# allocate 38 words for trapframe + 6 extra words
addiu sp, sp, -176
# allocate 38 / 70 words for trapframe + 6 extra words
addiu sp, sp, -TRAPFRAME_SIZE
# save general registers
sw ra, 160(sp)
@ -80,6 +87,42 @@ sp_aligned:
sw AT, 40(sp)
nop
#ifdef board_thinpad
# save floating point registers
swc1 $f0, 164(sp)
swc1 $f1, 168(sp)
swc1 $f2, 172(sp)
swc1 $f3, 176(sp)
swc1 $f4, 180(sp)
swc1 $f5, 184(sp)
swc1 $f6, 188(sp)
swc1 $f7, 192(sp)
swc1 $f8, 196(sp)
swc1 $f9, 200(sp)
swc1 $f10, 204(sp)
swc1 $f11, 208(sp)
swc1 $f12, 212(sp)
swc1 $f13, 216(sp)
swc1 $f14, 220(sp)
swc1 $f15, 224(sp)
swc1 $f16, 228(sp)
swc1 $f17, 232(sp)
swc1 $f18, 236(sp)
swc1 $f19, 240(sp)
swc1 $f20, 244(sp)
swc1 $f21, 248(sp)
swc1 $f22, 252(sp)
swc1 $f23, 256(sp)
swc1 $f24, 260(sp)
swc1 $f25, 264(sp)
swc1 $f26, 268(sp)
swc1 $f27, 272(sp)
swc1 $f28, 276(sp)
swc1 $f29, 280(sp)
swc1 $f30, 284(sp)
swc1 $f31, 288(sp)
#endif
# save hi/lo
mflo t1
sw t1, 36(sp)
@ -158,9 +201,45 @@ trap_return:
lw fp, 156(sp)
lw ra, 160(sp)
#ifdef board_thinpad
# restore floating point registers
lwc1 $f0, 164(sp)
lwc1 $f1, 168(sp)
lwc1 $f2, 172(sp)
lwc1 $f3, 176(sp)
lwc1 $f4, 180(sp)
lwc1 $f5, 184(sp)
lwc1 $f6, 188(sp)
lwc1 $f7, 192(sp)
lwc1 $f8, 196(sp)
lwc1 $f9, 200(sp)
lwc1 $f10, 204(sp)
lwc1 $f11, 208(sp)
lwc1 $f12, 212(sp)
lwc1 $f13, 216(sp)
lwc1 $f14, 220(sp)
lwc1 $f15, 224(sp)
lwc1 $f16, 228(sp)
lwc1 $f17, 232(sp)
lwc1 $f18, 236(sp)
lwc1 $f19, 240(sp)
lwc1 $f20, 244(sp)
lwc1 $f21, 248(sp)
lwc1 $f22, 252(sp)
lwc1 $f23, 256(sp)
lwc1 $f24, 260(sp)
lwc1 $f25, 264(sp)
lwc1 $f26, 268(sp)
lwc1 $f27, 272(sp)
lwc1 $f28, 276(sp)
lwc1 $f29, 280(sp)
lwc1 $f30, 284(sp)
lwc1 $f31, 288(sp)
#endif
# save kernel stack
lw k0, 0(sp)
addiu k1, sp, 176
addiu k1, sp, TRAPFRAME_SIZE
movn k1, k0, k0
la k0, _cur_kstack_ptr

@ -2,11 +2,16 @@
///
pub use super::board::consts::*;
pub const MEMORY_OFFSET: usize = 0x80000000;
pub const KERNEL_OFFSET: usize = 0x80100000;
pub const PHYSICAL_MEMORY_OFFSET: usize = 0x80000000;
pub const MEMORY_OFFSET: usize = 0x8000_0000;
pub const USER_STACK_OFFSET: usize = 0x70000000 - USER_STACK_SIZE;
#[cfg(feature = "board_thinpad")]
pub const KERNEL_OFFSET: usize = 0x8000_0000;
#[cfg(feature = "board_malta")]
pub const KERNEL_OFFSET: usize = 0x8010_0000;
pub const PHYSICAL_MEMORY_OFFSET: usize = 0x8000_0000;
pub const USER_STACK_OFFSET: usize = 0x7000_0000 - USER_STACK_SIZE;
pub const USER_STACK_SIZE: usize = 0x10000;
pub const MAX_DTB_SIZE: usize = 0x2000;

@ -52,6 +52,39 @@ pub struct TrapFrame {
pub sp: usize,
pub fp: usize,
pub ra: usize,
/// Floating-point registers (contains garbage if no FP support present)
pub f0: usize,
pub f1: usize,
pub f2: usize,
pub f3: usize,
pub f4: usize,
pub f5: usize,
pub f6: usize,
pub f7: usize,
pub f8: usize,
pub f9: usize,
pub f10: usize,
pub f11: usize,
pub f12: usize,
pub f13: usize,
pub f14: usize,
pub f15: usize,
pub f16: usize,
pub f17: usize,
pub f18: usize,
pub f19: usize,
pub f20: usize,
pub f21: usize,
pub f22: usize,
pub f23: usize,
pub f24: usize,
pub f25: usize,
pub f26: usize,
pub f27: usize,
pub f28: usize,
pub f29: usize,
pub f30: usize,
pub f31: usize,
/// Reserved
pub reserved: usize,
pub __padding: [usize; 2],

@ -155,7 +155,7 @@ impl PageTableImpl {
PageTableImpl {
page_table: TwoLevelPageTable::new(table),
root_frame: frame,
entry: unsafe { core::mem::uninitialized() },
entry: unsafe { core::mem::MaybeUninit::uninitialized().into_initialized() },
}
}
}
@ -171,7 +171,7 @@ impl PageTableExt for PageTableImpl {
PageTableImpl {
page_table: TwoLevelPageTable::new(table),
root_frame: frame,
entry: unsafe { core::mem::uninitialized() },
entry: unsafe { core::mem::MaybeUninit::uninitialized().into_initialized() },
}
}

@ -1,3 +1,6 @@
#[path = "../../../../drivers/gpu/fb.rs"]
pub mod fb;
use crate::memory::phys_to_virt;
/// Mask all external interrupt except serial.
@ -16,3 +19,7 @@ pub unsafe fn enable_serial_interrupt() {
UART16550.add(4).write_volatile(0x0B);
UART16550.add(1).write_volatile(0x01);
}
pub fn probe_fb_info(_width: u32, _height: u32, _depth: u32) -> fb::FramebufferResult {
unimplemented!()
}

@ -1,4 +1,4 @@
use crate::consts::{KERNEL_OFFSET, MEMORY_END, MEMORY_OFFSET};
use crate::consts::{KERNEL_OFFSET, MEMORY_END, MEMORY_OFFSET, PHYSICAL_MEMORY_OFFSET};
use crate::memory::{init_heap, Linear, MemoryAttr, MemorySet, FRAME_ALLOCATOR};
use core::mem;
use log::*;

@ -1,12 +1,12 @@
#[cfg(feature = "board_u540")]
#[path = "board/u540/mod.rs"]
mod board;
pub mod board;
#[cfg(feature = "board_rocket_chip")]
#[path = "board/rocket_chip/mod.rs"]
mod board;
pub mod board;
#[cfg(not(any(feature = "board_u540", feature = "board_rocket_chip")))]
#[path = "board/virt/mod.rs"]
mod board;
pub mod board;
pub mod compiler_rt;
pub mod consts;

@ -157,7 +157,7 @@ impl PageTableImpl {
PageTableImpl {
page_table: TopLevelPageTable::new(table, PHYSICAL_MEMORY_OFFSET),
root_frame: frame,
entry: unsafe { core::mem::uninitialized() },
entry: unsafe { core::mem::MaybeUninit::uninitialized().into_initialized() },
}
}
}
@ -173,7 +173,7 @@ impl PageTableExt for PageTableImpl {
PageTableImpl {
page_table: TopLevelPageTable::new(table, PHYSICAL_MEMORY_OFFSET),
root_frame: frame,
entry: unsafe { core::mem::uninitialized() },
entry: unsafe { core::mem::MaybeUninit::uninitialized().into_initialized() },
}
}
@ -191,6 +191,10 @@ impl PageTableExt for PageTableImpl {
}
#[cfg(target_arch = "riscv64")]
for i in 509..512 {
if (i == 510) {
// MMIO range 0x60000000 - 0x7FFFFFFF does not work as a large page, dunno why
continue;
}
let flags =
EF::VALID | EF::READABLE | EF::WRITABLE | EF::EXECUTABLE | EF::ACCESSED | EF::DIRTY;
let frame = Frame::of_addr(PhysAddr::new(
@ -198,6 +202,42 @@ impl PageTableExt for PageTableImpl {
));
table[i].set(frame, flags);
}
// MMIO range 0x60000000 - 0x7FFFFFFF does not work as a large page, dunno why
let flags = EF::VALID | EF::READABLE | EF::WRITABLE;
// map Uartlite for Rocket Chip
#[cfg(feature = "board_rocket_chip")]
self.page_table
.map_to(
Page::of_addr(VirtAddr::new(PHYSICAL_MEMORY_OFFSET + 0x6000_0000)),
Frame::of_addr(PhysAddr::new(0x6000_0000)),
flags,
&mut FrameAllocatorForRiscv,
)
.unwrap()
.flush();
// map AXI INTC for Rocket Chip
#[cfg(feature = "board_rocket_chip")]
self.page_table
.map_to(
Page::of_addr(VirtAddr::new(PHYSICAL_MEMORY_OFFSET + 0x6120_0000)),
Frame::of_addr(PhysAddr::new(0x6120_0000)),
flags,
&mut FrameAllocatorForRiscv,
)
.unwrap()
.flush();
// map AXI4-Stream Data FIFO for Rocket Chip
#[cfg(feature = "board_rocket_chip")]
self.page_table
.map_to(
Page::of_addr(VirtAddr::new(PHYSICAL_MEMORY_OFFSET + 0x64A0_0000)),
Frame::of_addr(PhysAddr::new(0x64A0_0000)),
flags,
&mut FrameAllocatorForRiscv,
)
.unwrap()
.flush();
}
fn token(&self) -> usize {

@ -1,15 +1,16 @@
#[path = "../../../drivers/gpu/fb.rs"]
pub mod fb;
use fb::{ColorConfig, FramebufferInfo, FramebufferResult, FRAME_BUFFER};
use crate::consts::KERNEL_OFFSET;
use crate::memory::phys_to_virt;
use fb::{ColorConfig, FramebufferInfo, FramebufferResult, FRAME_BUFFER};
pub fn init_driver() {
#[cfg(not(feature = "nographic"))]
fb::init();
}
pub fn probe_fb_info(width : u32, height : u32, depth : u32) -> FramebufferResult {
pub fn probe_fb_info(width: u32, height: u32, depth: u32) -> FramebufferResult {
let fb_info = FramebufferInfo {
xres: 1024,
yres: 768,
@ -22,5 +23,9 @@ pub fn probe_fb_info(width : u32, height : u32, depth : u32) -> FramebufferResul
bus_addr: 0xfd00_0000,
screen_size: 1024 * 768 * 3,
};
Ok((fb_info, fb::ColorConfig::BGRA8888, KERNEL_OFFSET + 0xf000_0000))
Ok((
fb_info,
fb::ColorConfig::BGRA8888,
phys_to_virt(0xfd00_0000),
))
}

@ -1,5 +1,4 @@
use super::ipi::IPIEventItem;
use alloc::boxed::Box;
use alloc::vec::*;
use core::sync::atomic::{AtomicBool, Ordering};
use x86_64::registers::model_specific::Msr;
@ -8,7 +7,7 @@ use x86_64::structures::tss::TaskStateSegment;
use x86_64::{PrivilegeLevel, VirtAddr};
use crate::consts::MAX_CPU_NUM;
use crate::sync::{Semaphore, SpinLock as Mutex};
use crate::sync::SpinLock as Mutex;
/// Init TSS & GDT.
pub fn init() {
@ -36,6 +35,10 @@ pub struct Cpu {
}
impl Cpu {
pub fn current() -> &'static mut Self {
unsafe { CPUS[super::cpu::id()].as_mut().unwrap() }
}
fn new() -> Self {
Cpu {
gdt: GlobalDescriptorTable::new(),
@ -57,9 +60,6 @@ impl Cpu {
let mut queue = self.ipi_handler_queue.lock();
queue.push(item);
}
pub fn current() -> &'static mut Cpu {
unsafe { CPUS[super::cpu::id()].as_mut().unwrap() }
}
pub fn handle_ipi(&self) {
let mut queue = self.ipi_handler_queue.lock();
let handlers = core::mem::replace(queue.as_mut(), vec![]);
@ -78,7 +78,7 @@ impl Cpu {
self.preemption_disabled.load(Ordering::Relaxed)
}
unsafe fn init(&'static mut self) {
use x86_64::instructions::segmentation::{load_fs, set_cs};
use x86_64::instructions::segmentation::set_cs;
use x86_64::instructions::tables::load_tss;
// Set the stack when DoubleFault occurs
@ -98,9 +98,18 @@ impl Cpu {
set_cs(KCODE_SELECTOR);
// load TSS
load_tss(TSS_SELECTOR);
// store address of TSS to GSBase
let mut gsbase = Msr::new(0xC0000101);
gsbase.write(&self.tss as *const _ as u64);
// for fast syscall:
// store address of TSS to kernel_gsbase
let mut kernel_gsbase = Msr::new(0xC0000102);
kernel_gsbase.write(&self.tss as *const _ as u64);
}
/// 设置从Ring3跳到Ring0时自动切换栈的地址
///
/// 每次进入用户态前,都要调用此函数,才能保证正确返回内核态
pub fn set_ring0_rsp(&mut self, rsp: usize) {
trace!("gdt.set_ring0_rsp: {:#x}", rsp);
self.tss.privilege_stack_table[0] = VirtAddr::new(rsp as u64);
}
}

@ -1,5 +1,4 @@
use super::super::gdt;
use super::TrapFrame;
use core::mem::transmute;
/// `syscall` instruction
use x86_64::registers::model_specific::*;

@ -229,3 +229,9 @@ fn invalid_opcode(tf: &mut TrapFrame) {
fn error(tf: &TrapFrame) {
crate::trap::error(tf);
}
#[no_mangle]
pub unsafe extern "C" fn set_return_rsp(tf: *const TrapFrame) {
use crate::arch::gdt::Cpu;
Cpu::current().set_ring0_rsp(tf.add(1) as usize);
}

@ -49,10 +49,8 @@ __alltraps:
.global trap_ret
trap_ret:
# store kernel rsp -> TSS.sp0
mov rdi, rsp
add rdi, 720
mov gs:[4], rdi
call set_return_rsp
# pop fp state offset
pop rcx
@ -106,6 +104,8 @@ syscall_entry:
# - store rip -> rcx
# - load rip
# swap in kernel gs
swapgs
# store user rsp -> scratch at TSS.sp1
mov gs:[12], rsp
# load kernel rsp <- TSS.sp0
@ -119,8 +119,11 @@ syscall_entry:
push 0 # error_code (dummy)
push 0 # trap_num (dummy)
# swap out kernel gs
swapgs
# enable interrupt
sti
# sti
push rax
push rcx
@ -170,10 +173,8 @@ syscall_return:
# disable interrupt
cli
# store kernel rsp -> TSS.sp0
mov rdi, rsp
add rdi, 720
mov gs:[4], rdi
call set_return_rsp
# pop fp state offset
pop rcx

@ -1,7 +1,6 @@
use super::driver::console::CONSOLE;
use super::driver::serial::*;
use super::driver::vga::VGA_WRITER;
use core::fmt::{Arguments, Write};
use super::driver::console::CONSOLE;
pub fn getchar() -> char {
unsafe {
@ -20,13 +19,14 @@ pub fn putfmt(fmt: Arguments) {
}
#[cfg(not(feature = "nographic"))]
{
use super::driver::vga::VGA_WRITER;
unsafe {
COM1.force_unlock();
}
COM1.lock().write_fmt(fmt).unwrap();
//unsafe { CONSOLE.force_unlock() }
//if let Some(console) = CONSOLE.lock().as_mut() {
//console.write_fmt(fmt).unwrap();
//console.write_fmt(fmt).unwrap();
//}
}
}

@ -9,7 +9,7 @@ use core::sync::atomic::{spin_loop_hint, AtomicU8, Ordering};
pub type IPIEventItem = Box<FnBox()>;
unsafe fn get_apic() -> XApic {
let mut lapic = unsafe { XApic::new(phys_to_virt(LAPIC_ADDR)) };
let mut lapic = XApic::new(phys_to_virt(LAPIC_ADDR));
lapic
}

@ -2,6 +2,7 @@ use bootloader::bootinfo::{BootInfo, MemoryRegionType};
use core::sync::atomic::*;
use log::*;
pub mod board;
pub mod consts;
pub mod cpu;
pub mod driver;
@ -15,7 +16,6 @@ pub mod paging;
pub mod rand;
pub mod syscall;
pub mod timer;
pub mod board;
static AP_CAN_INIT: AtomicBool = AtomicBool::new(false);

@ -21,7 +21,7 @@ pub trait PageExt {
impl PageExt for Page {
fn of_addr(address: usize) -> Self {
use x86_64;
Page::containing_address(x86_64::VirtAddr::new(address as u64))
Page::containing_address(VirtAddr::new(address as u64))
}
fn range_of(begin: usize, end: usize) -> PageRange {
Page::range(Page::of_addr(begin), Page::of_addr(end - 1) + 1)
@ -101,7 +101,7 @@ fn frame_to_page_table(frame: Frame) -> *mut x86PageTable {
impl Entry for PageEntry {
fn update(&mut self) {
use x86_64::{instructions::tlb::flush, VirtAddr};
use x86_64::instructions::tlb::flush;
let addr = self.1.start_address();
flush(addr);
flush_tlb_all(addr.as_u64() as usize);
@ -199,10 +199,10 @@ impl PageTableImpl {
/// WARN: You MUST call `core::mem::forget` for it after use!
pub unsafe fn active() -> Self {
let frame = Cr3::read().0;
let table = unsafe { &mut *frame_to_page_table(frame) };
let table = &mut *frame_to_page_table(frame);
PageTableImpl(
MappedPageTable::new(table, frame_to_page_table),
core::mem::uninitialized(),
core::mem::MaybeUninit::uninitialized().into_initialized(),
frame,
)
}
@ -217,7 +217,7 @@ impl PageTableExt for PageTableImpl {
unsafe {
PageTableImpl(
MappedPageTable::new(table, frame_to_page_table),
core::mem::uninitialized(),
core::mem::MaybeUninit::uninitialized().into_initialized(),
frame,
)
}

@ -8,7 +8,6 @@ use alloc::sync::Arc;
use isomorphic_drivers::block::ahci::{AHCI, BLOCK_SIZE};
use crate::drivers::provider::Provider;
use crate::drivers::BlockDriver;
use crate::sync::SpinNoIrqLock as Mutex;
use super::super::{DeviceType, Driver, BLK_DRIVERS, DRIVERS};

@ -11,8 +11,6 @@ use log::*;
use rcore_memory::PAGE_SIZE;
use volatile::Volatile;
use crate::arch::consts::PHYSICAL_MEMORY_OFFSET;
use crate::drivers::BlockDriver;
use crate::sync::SpinNoIrqLock as Mutex;
use super::super::bus::virtio_mmio::*;

@ -157,8 +157,9 @@ pub fn init_driver(dev: &PCIDevice) {
);
}
}
(0x8086, 0x2922) => {
(0x8086, 0x2922) | (0x8086, 0x8d02) => {
// 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode]
// C610/X99 series chipset 6-Port SATA Controller [AHCI mode]
if let Some(BAR::Memory(addr, len, _, _)) = dev.bars[5] {
let irq = unsafe { enable(dev.loc) };
assert!(len as usize <= PAGE_SIZE);

@ -154,7 +154,7 @@ impl Framebuffer {
8 => ColorDepth8,
16 => ColorDepth16,
32 => ColorDepth32,
24=> ColorDepth24,
24 => ColorDepth24,
_ => Err(format!("unsupported color depth {}", info.depth))?,
};
Ok(Framebuffer {

@ -11,7 +11,6 @@ use bitflags::*;
use device_tree::util::SliceRead;
use device_tree::Node;
use log::*;
use rcore_memory::paging::PageTable;
use rcore_memory::PAGE_SIZE;
use volatile::Volatile;

@ -5,35 +5,53 @@ use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use bitflags::*;
use smoltcp::iface::*;
use smoltcp::phy::{self, DeviceCapabilities};
use smoltcp::time::Instant;
use smoltcp::wire::*;
use smoltcp::Result;
use rcore_memory::PAGE_SIZE;
use crate::drivers::provider::Provider;
use crate::net::SOCKETS;
use crate::sync::SpinNoIrqLock as Mutex;
use super::super::{DeviceType, Driver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY};
use crate::memory::phys_to_virt;
const AXI_STREAM_FIFO_ISR: *mut u32 = phys_to_virt(0x1820_0000) as *mut u32;
const AXI_STREAM_FIFO_IER: *mut u32 = phys_to_virt(0x1820_0004) as *mut u32;
const AXI_STREAM_FIFO_TDFR: *mut u32 = phys_to_virt(0x1820_0008) as *mut u32;
const AXI_STREAM_FIFO_TDFD: *mut u32 = phys_to_virt(0x1820_0010) as *mut u32;
const AXI_STREAM_FIFO_TLR: *mut u32 = phys_to_virt(0x1820_0014) as *mut u32;
const AXI_STREAM_FIFO_RDFR: *mut u32 = phys_to_virt(0x1820_0018) as *mut u32;
const AXI_STREAM_FIFO_RDFO: *mut u32 = phys_to_virt(0x1820_001C) as *mut u32;
const AXI_STREAM_FIFO_RDFD: *mut u32 = phys_to_virt(0x1820_0020) as *mut u32;
const AXI_STREAM_FIFO_RLR: *mut u32 = phys_to_virt(0x1820_0024) as *mut u32;
const AXI_STREAM_FIFO_TDR: *mut u32 = phys_to_virt(0x1820_002C) as *mut u32;
const AXI_STREAM_FIFO_RDR: *mut u32 = phys_to_virt(0x1820_0030) as *mut u32;
const AXI_STREAM_FIFO_ISR: *mut u32 = phys_to_virt(0x64A0_0000) as *mut u32;
const AXI_STREAM_FIFO_IER: *mut u32 = phys_to_virt(0x64A0_0004) as *mut u32;
const AXI_STREAM_FIFO_TDFR: *mut u32 = phys_to_virt(0x64A0_0008) as *mut u32;
const AXI_STREAM_FIFO_TDFD: *mut u32 = phys_to_virt(0x64A0_0010) as *mut u32;
const AXI_STREAM_FIFO_TLR: *mut u32 = phys_to_virt(0x64A0_0014) as *mut u32;
const AXI_STREAM_FIFO_RDFR: *mut u32 = phys_to_virt(0x64A0_0018) as *mut u32;
const AXI_STREAM_FIFO_RDFO: *mut u32 = phys_to_virt(0x64A0_001C) as *mut u32;
const AXI_STREAM_FIFO_RDFD: *mut u32 = phys_to_virt(0x64A0_0020) as *mut u32;
const AXI_STREAM_FIFO_RLR: *mut u32 = phys_to_virt(0x64A0_0024) as *mut u32;
const AXI_STREAM_FIFO_TDR: *mut u32 = phys_to_virt(0x64A0_002C) as *mut u32;
const AXI_STREAM_FIFO_RDR: *mut u32 = phys_to_virt(0x64A0_0030) as *mut u32;
const ENABLED_PORTS: u8 = 2;
bitflags! {
struct AXIStreamFifoInterrupt : u32 {
const RECV_EMPTY = 1 << 19;
const RECV_FULL = 1 << 20;
const TRAN_EMPTY = 1 << 21;
const TRAN_FULL = 1 << 22;
const RECV_RESET = 1 << 23;
const TRAN_RESET = 1 << 24;
const TRAN_SIZE_ERR = 1 << 25;
const RECV_COMPLETE = 1 << 26;
const TRAN_COMPLETE = 1 << 27;
const TRAN_PACKET_OVERRUN_ERR = 1 << 28;
const RECV_PACKET_UNDERRUN_ERR = 1 << 29;
const RECV_PACKET_OVERRUN_READ_ERR = 1 << 30;
const RECV_PACKET_UNDERRUN_READ_ERR = 1 << 31;
}
}
pub struct Router {
buffer: Vec<Vec<u8>>,
buffer: [Vec<Vec<u8>>; ENABLED_PORTS as usize],
}
impl Router {
@ -41,13 +59,13 @@ impl Router {
true
}
fn receive_available(&self) -> bool {
self.buffer.len() > 0
fn receive_available(&self, port: u8) -> bool {
self.buffer[port as usize].len() > 0
}
}
#[derive(Clone)]
pub struct RouterDriver(Arc<Mutex<Router>>);
pub struct RouterDriver(Arc<Mutex<Router>>, u8);
pub struct RouterRxToken(RouterDriver);
pub struct RouterTxToken(RouterDriver);
@ -58,7 +76,7 @@ impl<'a> phy::Device<'a> for RouterDriver {
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
let driver = self.0.lock();
if driver.transmit_available() && driver.receive_available() {
if driver.transmit_available() && driver.receive_available(self.1) {
// potential racing
Some((RouterRxToken(self.clone()), RouterTxToken(self.clone())))
} else {
@ -89,7 +107,7 @@ impl phy::RxToken for RouterRxToken {
F: FnOnce(&[u8]) -> Result<R>,
{
let mut router = (self.0).0.lock();
let buffer = router.buffer.pop().unwrap();
let buffer = router.buffer[(self.0).1 as usize].pop().unwrap();
f(&buffer)
}
}
@ -101,14 +119,20 @@ impl phy::TxToken for RouterTxToken {
{
let mut buffer = vec![0; len];
let res = f(&mut buffer);
debug!("out buf {}", len);
debug!(
"out buf {} data {:x?} port {}",
len,
&buffer[..20],
(self.0).1
);
unsafe {
AXI_STREAM_FIFO_TDR.write_volatile(2);
AXI_STREAM_FIFO_TDFD.write_volatile((self.0).1 as u32);
for byte in buffer {
AXI_STREAM_FIFO_TDFD.write_volatile(byte as u32);
}
AXI_STREAM_FIFO_TLR.write((len * 4) as u32);
AXI_STREAM_FIFO_TLR.write(((len + 1) * 4) as u32);
}
res
}
@ -126,7 +150,10 @@ impl Driver for RouterInterface {
let isr = unsafe { AXI_STREAM_FIFO_ISR.read_volatile() };
if isr > 0 {
debug!("handle router interrupt {:b}", isr);
debug!(
"handle router interrupt {:?}",
AXIStreamFifoInterrupt::from_bits_truncate(isr)
);
unsafe {
AXI_STREAM_FIFO_ISR.write(isr);
let rdfo = AXI_STREAM_FIFO_RDFO.read_volatile();
@ -134,11 +161,17 @@ impl Driver for RouterInterface {
let mut buffer = Vec::new();
let rlr = AXI_STREAM_FIFO_RLR.read_volatile();
let rdr = AXI_STREAM_FIFO_RDR.read_volatile();
for i in 0..rdfo {
let port = AXI_STREAM_FIFO_RDFD.read_volatile();
for i in 1..rdfo {
buffer.push(AXI_STREAM_FIFO_RDFD.read_volatile() as u8);
}
debug!("got packet of length {}", rdfo);
driver.buffer.push(buffer);
debug!(
"got packet of length {} port {} data {:x?}",
rdfo,
port,
&buffer[..20]
);
driver.buffer[port as usize].push(buffer);
}
drop(driver);
@ -183,7 +216,7 @@ impl Driver for RouterInterface {
}
}
pub fn router_init() -> Arc<RouterInterface> {
pub fn router_init() {
unsafe {
// reset tx fifo
AXI_STREAM_FIFO_TDFR.write_volatile(0xA5);
@ -191,38 +224,40 @@ pub fn router_init() -> Arc<RouterInterface> {
AXI_STREAM_FIFO_RDFR.write_volatile(0xA5);
}
let ethernet_addr = EthernetAddress::from_bytes(&[2, 2, 3, 3, 0, 0]);
let net_driver = RouterDriver(Arc::new(Mutex::new(Router { buffer: Vec::new() })));
let ip_addrs = [
IpCidr::new(IpAddress::v4(10, 0, 0, 1), 24),
IpCidr::new(IpAddress::v4(10, 0, 1, 1), 24),
];
let neighbor_cache = NeighborCache::new(BTreeMap::new());
let routes = Routes::new(BTreeMap::new());
let iface = EthernetInterfaceBuilder::new(net_driver.clone())
.ethernet_addr(ethernet_addr)
.ip_addrs(ip_addrs)
.neighbor_cache(neighbor_cache)
.routes(routes)
.finalize();
info!("router interface up");
let router_iface = RouterInterface {
iface: Mutex::new(iface),
driver: net_driver,
};
let driver = Arc::new(router_iface);
DRIVERS.write().push(driver.clone());
NET_DRIVERS.write().push(driver.clone());
for i in 0..ENABLED_PORTS {
let ethernet_addr = EthernetAddress::from_bytes(&[2, 2, 3, 3, 0, i]);
let net_driver = RouterDriver(
Arc::new(Mutex::new(Router {
buffer: [Vec::new(), Vec::new()],
})),
i,
);
let ip_addrs = [IpCidr::new(IpAddress::v4(10, 0, i, 1), 24)];
let neighbor_cache = NeighborCache::new(BTreeMap::new());
let routes = Routes::new(BTreeMap::new());
let iface = EthernetInterfaceBuilder::new(net_driver.clone())
.ethernet_addr(ethernet_addr)
.ip_addrs(ip_addrs)
.neighbor_cache(neighbor_cache)
.routes(routes)
.finalize();
info!("router interface up #{}", i);
let router_iface = RouterInterface {
iface: Mutex::new(iface),
driver: net_driver,
};
let driver = Arc::new(router_iface);
DRIVERS.write().push(driver.clone());
NET_DRIVERS.write().push(driver.clone());
}
// Enable Receive Complete Interrupt
unsafe {
AXI_STREAM_FIFO_IER.write_volatile(1 << 26);
}
driver
}

@ -1,10 +1,6 @@
use alloc::alloc::{alloc_zeroed, dealloc, Layout};
pub use crate::arch::paging::PageTableImpl;
use crate::consts::PHYSICAL_MEMORY_OFFSET;
use crate::memory::{alloc_frame, dealloc_frame, phys_to_virt, virt_to_phys};
use isomorphic_drivers::provider;
use rcore_memory::paging::PageTable;
use rcore_memory::PAGE_SIZE;
pub struct Provider;

@ -68,12 +68,19 @@ impl SerialPort {
impl Write for SerialPort {
fn write_str(&mut self, s: &str) -> Result {
for c in s.bytes() {
if c == 127 {
self.putchar(8);
self.putchar(b' ');
self.putchar(8);
} else {
self.putchar(c);
match c {
127 => {
self.putchar(8);
self.putchar(b' ');
self.putchar(8);
}
b'\n' => {
self.putchar(b'\r');
self.putchar(b'\n');
}
c => {
self.putchar(c);
}
}
}
Ok(())

@ -59,12 +59,19 @@ impl SerialPort {
impl Write for SerialPort {
fn write_str(&mut self, s: &str) -> Result {
for c in s.bytes() {
if c == 127 {
self.putchar(8);
self.putchar(b' ');
self.putchar(8);
} else {
self.putchar(c);
match c {
127 => {
self.putchar(8);
self.putchar(b' ');
self.putchar(8);
}
b'\n' => {
self.putchar(b'\r');
self.putchar(b'\n');
}
c => {
self.putchar(c);
}
}
}
Ok(())

@ -68,12 +68,19 @@ impl SerialPort {
impl Write for SerialPort {
fn write_str(&mut self, s: &str) -> Result {
for c in s.bytes() {
if c == 127 {
self.putchar(8);
self.putchar(b' ');
self.putchar(8);
} else {
self.putchar(c);
match c {
127 => {
self.putchar(8);
self.putchar(b' ');
self.putchar(8);
}
b'\n' => {
self.putchar(b'\r');
self.putchar(b'\n');
}
c => {
self.putchar(c);
}
}
}
Ok(())

@ -49,15 +49,16 @@ impl FileHandle {
if !self.options.read {
return Err(FsError::InvalidParam); // FIXME: => EBADF
}
let mut len : usize = 0;
if !self.options.nonblock { // block
let mut len: usize = 0;
if !self.options.nonblock {
// block
loop {
len = self.inode.read_at(offset, buf)?;
if len > 0 {
break;
}
}
}else{
} else {
len = self.inode.read_at(offset, buf)?;
}
Ok(len)

@ -94,7 +94,7 @@ impl INode for Stdin {
if self.can_read() {
buf[0] = self.pop() as u8;
Ok(1)
}else{
} else {
Ok(0)
}
}

@ -1,8 +1,9 @@
use rcore_fs::vfs::*;
use crate::arch::board::fb::FRAME_BUFFER;
use crate::memory::phys_to_virt;
use alloc::{string::String, sync::Arc, vec::Vec};
use core::any::Any;
use crate::arch::board::fb::FRAME_BUFFER;
#[derive(Default)]
pub struct Vga;
@ -30,15 +31,19 @@ impl INode for Vga {
}
fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize> {
info!("the _offset is {} {}", _offset, _buf[0]);
use crate::consts::KERNEL_OFFSET;
use core::slice;
let frame_buffer_data =
unsafe { slice::from_raw_parts_mut((KERNEL_OFFSET + 0xf000_0000) as *mut u8, ( 1024 * 768 * 3) as usize) };
let frame_buffer_data = unsafe {
slice::from_raw_parts_mut(
phys_to_virt(0xfd00_0000) as *mut u8,
(1024 * 768 * 3) as usize,
)
};
frame_buffer_data.copy_from_slice(&_buf);
return Ok(1024 * 768 * 3);
}
fn poll(&self) -> Result<PollStatus> {
Ok(PollStatus { // TOKNOW and TODO
Ok(PollStatus {
// TOKNOW and TODO
read: true,
write: false,
error: false,

@ -7,6 +7,7 @@
#![feature(panic_info_message)]
#![feature(global_asm)]
#![feature(fnbox)]
#![feature(maybe_uninit)]
#![deny(unused_must_use)]
#![no_std]

@ -14,10 +14,9 @@
use super::HEAP_ALLOCATOR;
pub use crate::arch::paging::*;
use crate::consts::{KERNEL_OFFSET, MEMORY_OFFSET, PHYSICAL_MEMORY_OFFSET};
use crate::consts::{MEMORY_OFFSET, PHYSICAL_MEMORY_OFFSET};
use crate::process::current_thread;
use crate::sync::{MutexGuard, SpinNoIrq, SpinNoIrqLock};
use alloc::boxed::Box;
use crate::sync::SpinNoIrqLock;
use bitmap_allocator::BitAlloc;
use buddy_system_allocator::Heap;
use core::mem;
@ -30,9 +29,9 @@ use rcore_memory::*;
pub type MemorySet = rcore_memory::memory_set::MemorySet<PageTableImpl>;
// x86_64 support up to 64G memory
// x86_64 support up to 1T memory
#[cfg(target_arch = "x86_64")]
pub type FrameAlloc = bitmap_allocator::BitAlloc16M;
pub type FrameAlloc = bitmap_allocator::BitAlloc256M;
// RISCV, ARM, MIPS has 1G memory
#[cfg(all(
@ -132,13 +131,13 @@ pub fn handle_page_fault(addr: usize) -> bool {
pub fn init_heap() {
use crate::consts::KERNEL_HEAP_SIZE;
const machine_align: usize = mem::size_of::<usize>();
const heap_block: usize = KERNEL_HEAP_SIZE / machine_align;
static mut HEAP: [usize; heap_block] = [0; heap_block];
const MACHINE_ALIGN: usize = mem::size_of::<usize>();
const HEAP_BLOCK: usize = KERNEL_HEAP_SIZE / MACHINE_ALIGN;
static mut HEAP: [usize; HEAP_BLOCK] = [0; HEAP_BLOCK];
unsafe {
HEAP_ALLOCATOR
.lock()
.init(HEAP.as_ptr() as usize, heap_block * machine_align);
.init(HEAP.as_ptr() as usize, HEAP_BLOCK * MACHINE_ALIGN);
}
info!("heap init end");
}
@ -171,8 +170,9 @@ pub fn enlarge_heap(heap: &mut Heap) {
}
}
pub fn access_ok(from: usize, len: usize) -> bool {
from < PHYSICAL_MEMORY_OFFSET && (from + len) < PHYSICAL_MEMORY_OFFSET
/// Check whether the address range [addr, addr + len) is not in kernel space
pub fn access_ok(addr: usize, len: usize) -> bool {
addr < PHYSICAL_MEMORY_OFFSET && (addr + len) < PHYSICAL_MEMORY_OFFSET
}
#[naked]
@ -180,39 +180,19 @@ pub unsafe extern "C" fn read_user_fixup() -> usize {
return 1;
}
#[no_mangle]
pub fn copy_from_user_u8(addr: *const u8) -> Option<u8> {
pub fn copy_from_user<T>(addr: *const T) -> Option<T> {
#[naked]
#[inline(never)]
#[link_section = ".text.copy_user"]
unsafe extern "C" fn read_user_u8(dst: *mut u8, src: *const u8) -> usize {
unsafe extern "C" fn read_user<T>(dst: *mut T, src: *const T) -> usize {
dst.copy_from_nonoverlapping(src, 1);
0
}
if !access_ok(addr as usize, size_of::<u8>()) {
if !access_ok(addr as usize, size_of::<T>()) {
return None;
}
let mut dst: u8 = 0;
match unsafe { read_user_u8((&mut dst) as *mut u8, addr) } {
0 => Some(dst),
_ => None,
}
}
#[no_mangle]
pub fn copy_from_user_usize(addr: *const usize) -> Option<usize> {
#[naked]
#[inline(never)]
#[link_section = ".text.copy_user"]
unsafe extern "C" fn read_user_usize(dst: *mut usize, src: *const usize) -> usize {
dst.copy_from_nonoverlapping(src, 1);
0
}
if !access_ok(addr as usize, size_of::<usize>()) {
return None;
}
let mut dst: usize = 0;
match unsafe { read_user_usize((&mut dst) as *mut usize, addr) } {
let mut dst: T = unsafe { core::mem::uninitialized() };
match unsafe { read_user(&mut dst, addr) } {
0 => Some(dst),
_ => None,
}

@ -1,7 +1,6 @@
pub use self::structs::*;
use crate::arch::cpu;
use crate::consts::{MAX_CPU_NUM, MAX_PROCESS_NUM};
use crate::sync::{MutexGuard, SpinNoIrq};
use alloc::{boxed::Box, sync::Arc};
use log::*;
pub use rcore_thread::*;

@ -21,7 +21,7 @@ use crate::sync::{Condvar, SpinNoIrqLock as Mutex};
use super::abi::{self, ProcInitInfo};
use crate::processor;
use core::mem::uninitialized;
use core::mem::MaybeUninit;
use rcore_fs::vfs::INode;
pub struct Thread {
@ -103,7 +103,7 @@ impl Thread {
Box::new(Thread {
context: Context::null(),
// safety: other fields will never be used
..core::mem::uninitialized()
..core::mem::MaybeUninit::uninitialized().into_initialized()
})
}
@ -146,7 +146,7 @@ impl Thread {
) -> Result<(MemorySet, usize, usize), &'static str> {
// Read ELF header
// 0x3c0: magic number from ld-musl.so
let mut data: [u8; 0x3c0] = unsafe { uninitialized() };
let mut data: [u8; 0x3c0] = unsafe { MaybeUninit::uninitialized().into_initialized() };
inode
.read_at(0, &mut data)
.map_err(|_| "failed to read from INode")?;

@ -1,6 +1,5 @@
//! Kernel shell
use crate::arch::io;
use crate::fs::ROOT_INODE;
use crate::process::*;
use alloc::string::String;

@ -1,4 +1,5 @@
use super::*;
use crate::process::processor;
use crate::thread;
use alloc::collections::VecDeque;
use alloc::sync::Arc;
@ -26,26 +27,46 @@ impl Condvar {
});
}
#[deprecated(note = "this may leads to lost wakeup problem. please use `wait` instead.")]
pub fn wait_any(condvars: &[&Condvar]) {
let token = Arc::new(thread::current());
// Avoid racing in the same way as the function above
let mut locks = Vec::new();
locks.reserve(condvars.len());
fn add_to_wait_queue(&self) -> MutexGuard<VecDeque<Arc<thread::Thread>>, SpinNoIrq> {
let mut lock = self.wait_queue.lock();
lock.push_back(Arc::new(thread::current()));
return lock;
}
/// Wait for condvar until condition() returns Some
pub fn wait_event<T>(condvar: &Condvar, mut condition: impl FnMut() -> Option<T>) -> T {
Self::wait_events(&[condvar], condition)
}
/// Wait for condvars until condition() returns Some
pub fn wait_events<T>(condvars: &[&Condvar], mut condition: impl FnMut() -> Option<T>) -> T {
let thread = thread::current();
let tid = thread.id();
let token = Arc::new(thread);
for condvar in condvars {
let mut lock = condvar.wait_queue.lock();
lock.push_back(token.clone());
locks.push(lock);
}
thread::park_action(move || {
drop(locks);
});
}
let mut locks = Vec::with_capacity(condvars.len());
loop {
for condvar in condvars {
let mut lock = condvar.wait_queue.lock();
locks.push(lock);
}
processor().manager().sleep(tid, 0);
locks.clear();
fn add_to_wait_queue(&self) -> MutexGuard<VecDeque<Arc<thread::Thread>>, SpinNoIrq> {
let mut lock = self.wait_queue.lock();
lock.push_back(Arc::new(thread::current()));
return lock;
if let Some(res) = condition() {
let _ = FlagsGuard::no_irq_region();
processor().manager().cancel_sleeping(tid);
for condvar in condvars {
let mut lock = condvar.wait_queue.lock();
lock.retain(|t| !Arc::ptr_eq(t, &token));
}
return res;
}
processor().yield_now();
}
}
/// Park current thread and wait for this condvar to be notified.
@ -54,21 +75,28 @@ impl Condvar {
S: MutexSupport,
{
let mutex = guard.mutex;
let lock = self.add_to_wait_queue();
let token = Arc::new(thread::current());
let mut lock = self.wait_queue.lock();
lock.push_back(token.clone());
thread::park_action(move || {
drop(lock);
drop(guard);
});
mutex.lock()
let ret = mutex.lock();
let mut lock = self.wait_queue.lock();
lock.retain(|t| !Arc::ptr_eq(&t, &token));
ret
}
pub fn notify_one(&self) {
if let Some(t) = self.wait_queue.lock().pop_front() {
if let Some(t) = self.wait_queue.lock().front() {
t.unpark();
}
}
pub fn notify_all(&self) {
while let Some(t) = self.wait_queue.lock().pop_front() {
let queue = self.wait_queue.lock();
for t in queue.iter() {
t.unpark();
}
}
@ -76,14 +104,15 @@ impl Condvar {
/// Return the number of waiters that were woken up.
pub fn notify_n(&self, n: usize) -> usize {
let mut count = 0;
while count < n {
if let Some(t) = self.wait_queue.lock().pop_front() {
t.unpark();
count += 1;
} else {
let queue = self.wait_queue.lock();
for t in queue.iter() {
if count >= n {
break;
}
t.unpark();
count += 1;
}
count
}
}

@ -105,14 +105,17 @@ impl Syscall<'_> {
drop(proc);
let begin_time_ms = crate::trap::uptime_msec();
loop {
Condvar::wait_events(&[&STDIN.pushed, &(*SOCKET_ACTIVITY)], move || {
use PollEvents as PE;
let proc = self.process();
let mut events = 0;
for poll in polls.iter_mut() {
poll.revents = PE::empty();
if let Some(file_like) = proc.files.get(&(poll.fd as usize)) {
let status = file_like.poll()?;
let status = match file_like.poll() {
Ok(ret) => ret,
Err(err) => return Some(Err(err)),
};
if status.error {
poll.revents |= PE::HUP;
events += 1;
@ -133,19 +136,15 @@ impl Syscall<'_> {
drop(proc);
if events > 0 {
return Ok(events);
return Some(Ok(events));
}
let current_time_ms = crate::trap::uptime_msec();
if timeout_msecs < (1 << 31) && current_time_ms - begin_time_ms > timeout_msecs {
return Ok(0);
return Some(Ok(0));
}
// NOTE: To run rustc, uncomment yield_now and comment Condvar.
// Waking up from pipe is unimplemented now.
// thread::yield_now();
Condvar::wait_any(&[&STDIN.pushed, &(*SOCKET_ACTIVITY)]);
}
return None;
})
}
pub fn sys_select(
@ -180,7 +179,7 @@ impl Syscall<'_> {
drop(proc);
let begin_time_ms = crate::trap::uptime_msec();
loop {
Condvar::wait_events(&[&STDIN.pushed, &(*SOCKET_ACTIVITY)], move || {
let proc = self.process();
let mut events = 0;
for (&fd, file_like) in proc.files.iter() {
@ -190,7 +189,10 @@ impl Syscall<'_> {
if !err_fds.contains(fd) && !read_fds.contains(fd) && !write_fds.contains(fd) {
continue;
}
let status = file_like.poll()?;
let status = match file_like.poll() {
Ok(ret) => ret,
Err(err) => return Some(Err(err)),
};
if status.error && err_fds.contains(fd) {
err_fds.set(fd);
events += 1;
@ -207,23 +209,23 @@ impl Syscall<'_> {
drop(proc);
if events > 0 {
return Ok(events);
return Some(Ok(events));
}
if timeout_msecs == 0 {
// no timeout, return now;
return Ok(0);
return Some(Ok(0));
}
let current_time_ms = crate::trap::uptime_msec();
// infinity check
if timeout_msecs < (1 << 31) && current_time_ms - begin_time_ms > timeout_msecs as usize
{
return Ok(0);
return Some(Ok(0));
}
Condvar::wait_any(&[&STDIN.pushed, &(*SOCKET_ACTIVITY)]);
}
return None;
})
}
pub fn sys_readv(&mut self, fd: usize, iov_ptr: *const IoVec, iov_count: usize) -> SysResult {
@ -386,7 +388,7 @@ impl Syscall<'_> {
flags: usize,
) -> SysResult {
let proc = self.process();
let path = unsafe { check_and_clone_cstr(path)? };
let path = check_and_clone_cstr(path)?;
let stat_ref = unsafe { self.vm().check_write_ptr(stat_ptr)? };
let flags = AtFlags::from_bits_truncate(flags);
info!(
@ -537,7 +539,7 @@ impl Syscall<'_> {
pub fn sys_chdir(&mut self, path: *const u8) -> SysResult {
let mut proc = self.process();
let path = unsafe { check_and_clone_cstr(path)? };
let path = check_and_clone_cstr(path)?;
if !proc.pid.is_init() {
// we trust pid 0 process
info!("chdir: path: {:?}", path);
@ -590,8 +592,8 @@ impl Syscall<'_> {
newpath: *const u8,
) -> SysResult {
let proc = self.process();
let oldpath = unsafe { check_and_clone_cstr(oldpath)? };
let newpath = unsafe { check_and_clone_cstr(newpath)? };
let oldpath = check_and_clone_cstr(oldpath)?;
let newpath = check_and_clone_cstr(newpath)?;
info!(
"renameat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}",
olddirfd as isize, oldpath, newdirfd as isize, newpath
@ -611,7 +613,7 @@ impl Syscall<'_> {
pub fn sys_mkdirat(&mut self, dirfd: usize, path: *const u8, mode: usize) -> SysResult {
let proc = self.process();
let path = unsafe { check_and_clone_cstr(path)? };
let path = check_and_clone_cstr(path)?;
// TODO: check pathname
info!(
"mkdirat: dirfd: {}, path: {:?}, mode: {:#o}",
@ -629,7 +631,7 @@ impl Syscall<'_> {
pub fn sys_rmdir(&mut self, path: *const u8) -> SysResult {
let proc = self.process();
let path = unsafe { check_and_clone_cstr(path)? };
let path = check_and_clone_cstr(path)?;
info!("rmdir: path: {:?}", path);
let (dir_path, file_name) = split_path(&path);
@ -655,8 +657,8 @@ impl Syscall<'_> {
flags: usize,
) -> SysResult {
let proc = self.process();
let oldpath = unsafe { check_and_clone_cstr(oldpath)? };
let newpath = unsafe { check_and_clone_cstr(newpath)? };
let oldpath = check_and_clone_cstr(oldpath)?;
let newpath = check_and_clone_cstr(newpath)?;
let flags = AtFlags::from_bits_truncate(flags);
info!(
"linkat: olddirfd: {}, oldpath: {:?}, newdirfd: {}, newpath: {:?}, flags: {:?}",
@ -834,11 +836,8 @@ impl Syscall<'_> {
return Ok(total_written);
}
pub fn sys_fcntl(&mut self, fd : usize, cmd : usize, arg : usize) -> SysResult{
info!(
"fcntl: fd: {}, cmd: {:x}, arg: {}",
fd, cmd, arg
);
pub fn sys_fcntl(&mut self, fd: usize, cmd: usize, arg: usize) -> SysResult {
info!("fcntl: fd: {}, cmd: {:x}, arg: {}", fd, cmd, arg);
let mut proc = self.process();
let file_like = proc.get_file_like(fd)?;
file_like.fcntl(cmd, arg)
@ -886,11 +885,11 @@ impl Process {
match path {
"/proc/self/exe" => {
return Ok(Arc::new(Pseudo::new(&self.exec_path, FileType::SymLink)));
},
}
"/dev/fb0" => {
info!("/dev/fb0 will be opened");
return Ok(Arc::new(Vga::default()));
},
}
_ => {}
}
let (fd_dir_path, fd_name) = split_path(&path);

@ -1,7 +1,5 @@
use rcore_memory::memory_set::handler::{Delay, File, Linear};
use rcore_memory::memory_set::MemoryAttr;
use rcore_memory::paging::PageTable;
use rcore_memory::Page;
use rcore_memory::PAGE_SIZE;
use crate::memory::GlobalFrameAlloc;
@ -53,7 +51,6 @@ impl Syscall<'_> {
);
return Ok(addr);
} else {
let file = proc.get_file(fd)?;
info!("mmap path is {} ", &*file.path);
match &*file.path {
@ -64,15 +61,15 @@ impl Syscall<'_> {
addr,
addr + len,
prot.to_attr(),
Linear::new(
( fb.bus_addr() - addr ) as isize,
),
Linear::new((fb.bus_addr() - addr) as isize),
"mmap_file",
);
info!("mmap for /dev/fb0");
return Ok(addr);
} else {
return Err(SysError::ENOENT);
}
return Ok(addr);
},
}
_ => {
let inode = file.inode();
self.vm().push(
@ -89,7 +86,7 @@ impl Syscall<'_> {
"mmap_file",
);
return Ok(addr);
},
}
};
}
}

@ -10,19 +10,19 @@ use rcore_memory::VMError;
use crate::arch::cpu;
use crate::arch::interrupt::TrapFrame;
use crate::arch::syscall::*;
use crate::memory::{copy_from_user_u8, copy_from_user_usize, MemorySet};
use crate::memory::{copy_from_user, MemorySet};
use crate::process::*;
use crate::sync::{Condvar, MutexGuard, SpinNoIrq};
use crate::thread;
use crate::util;
use self::custom::*;
use self::fs::*;
use self::mem::*;
use self::misc::*;
pub use self::custom::*;
pub use self::fs::*;
pub use self::mem::*;
pub use self::misc::*;
pub use self::net::*;
use self::proc::*;
use self::time::*;
pub use self::proc::*;
pub use self::time::*;
mod custom;
mod fs;
@ -32,7 +32,9 @@ mod net;
mod proc;
mod time;
#[cfg(feature = "profile")]
use alloc::collections::BTreeMap;
#[cfg(feature = "profile")]
use spin::Mutex;
#[cfg(feature = "profile")]
@ -100,9 +102,12 @@ impl Syscall<'_> {
SYS_WRITEV => self.sys_writev(args[0], args[1] as *const IoVec, args[2]),
SYS_SENDFILE => self.sys_sendfile(args[0], args[1], args[2] as *mut usize, args[3]),
SYS_FCNTL => {
info!("SYS_FCNTL : {} {} {} {}", args[0], args[1], args[2], args[3]);
info!(
"SYS_FCNTL : {} {} {} {}",
args[0], args[1], args[2], args[3]
);
self.sys_fcntl(args[0], args[1], args[2])
},
}
SYS_FLOCK => self.unimplemented("flock", Ok(0)),
SYS_FSYNC => self.sys_fsync(args[0]),
SYS_FDATASYNC => self.sys_fdatasync(args[0]),
@ -291,6 +296,7 @@ impl Syscall<'_> {
SYS_GETRANDOM => {
self.sys_getrandom(args[0] as *mut u8, args[1] as usize, args[2] as u32)
}
SYS_RT_SIGQUEUEINFO => self.unimplemented("rt_sigqueueinfo", Ok(0)),
// custom
SYS_MAP_PCI_DEVICE => self.sys_map_pci_device(args[0], args[1]),
@ -552,45 +558,32 @@ pub fn spin_and_wait<T>(condvars: &[&Condvar], mut action: impl FnMut() -> Optio
return result;
}
}
loop {
if let Some(result) = action() {
return result;
}
Condvar::wait_any(&condvars);
}
Condvar::wait_events(&condvars, action)
}
pub fn check_and_clone_cstr(user: *const u8) -> Result<String, SysError> {
let mut buffer = Vec::new();
for i in 0.. {
let addr = unsafe { user.add(i) };
if let Some(data) = copy_from_user_u8(addr) {
if data > 0 {
buffer.push(data);
} else {
break;
}
} else {
return Err(SysError::EFAULT);
let data = copy_from_user(addr).ok_or(SysError::EFAULT)?;
if data == 0 {
break;
}
buffer.push(data);
}
return String::from_utf8(buffer).map_err(|_| SysError::EFAULT);
String::from_utf8(buffer).map_err(|_| SysError::EFAULT)
}
pub fn check_and_clone_cstr_array(user: *const *const u8) -> Result<Vec<String>, SysError> {
let mut buffer = Vec::new();
for i in 0.. {
let addr = unsafe { user.add(i) };
if let Some(str_addr) = copy_from_user_usize(addr as *const usize) {
if str_addr > 0 {
let string = check_and_clone_cstr(str_addr as *const u8)?;
buffer.push(string);
} else {
break;
}
} else {
return Err(SysError::EFAULT);
let str_ptr = copy_from_user(addr).ok_or(SysError::EFAULT)?;
if str_ptr.is_null() {
break;
}
let string = check_and_clone_cstr(str_ptr)?;
buffer.push(string);
}
return Ok(buffer);
Ok(buffer)
}

@ -6,7 +6,7 @@ use crate::fs::FileLike;
use crate::memory::MemorySet;
use crate::net::{
Endpoint, LinkLevelEndpoint, NetlinkEndpoint, NetlinkSocketState, PacketSocketState,
RawSocketState, Socket, TcpSocketState, UdpSocketState, SOCKETS,
RawSocketState, Socket, TcpSocketState, UdpSocketState,
};
use alloc::boxed::Box;
use core::cmp::min;
@ -462,13 +462,13 @@ impl SockAddr {
return Ok(0);
}
let addr_len = unsafe { vm.check_write_ptr(addr_len)? };
let addr_len = vm.check_write_ptr(addr_len)?;
let max_addr_len = *addr_len as usize;
let full_len = self.len()?;
let written_len = min(max_addr_len, full_len);
if written_len > 0 {
let target = unsafe { vm.check_write_array(addr as *mut u8, written_len)? };
let target = vm.check_write_array(addr as *mut u8, written_len)?;
let source = slice::from_raw_parts(&self as *const SockAddr as *const u8, written_len);
target.copy_from_slice(source);
}

@ -1,7 +1,6 @@
//! Syscalls for process
use super::*;
use crate::fs::INodeExt;
impl Syscall<'_> {
/// Fork the current process. Return the child's PID.
@ -153,9 +152,9 @@ impl Syscall<'_> {
path, argv, envp
);
let mut proc = self.process();
let path = unsafe { check_and_clone_cstr(path)? };
let args = unsafe { check_and_clone_cstr_array(argv)? };
let envs = unsafe { check_and_clone_cstr_array(envp)? };
let path = check_and_clone_cstr(path)?;
let args = check_and_clone_cstr_array(argv)?;
let envs = check_and_clone_cstr_array(envp)?;
if args.is_empty() {
error!("exec: args is null");

@ -7,7 +7,7 @@
"target-pointer-width": "32",
"target-c-int-width": "32",
"os": "none",
"features": "+mips32r2,+soft-float",
"features": "+mips32r2,+single-float",
"max-atomic-width": "32",
"linker": "rust-lld",
"linker-flavor": "ld.lld",

Loading…
Cancel
Save