Compare commits

...

5 Commits

Author SHA1 Message Date
刘丰源 8566a6993a flush tlb 2021-04-14 16:22:19 +08:00
Runji Wang 1576b2c5eb fix bug in riscv crate
remove rcore-memory crate
move kernel virtual address to 0xFFFF_FFFF_8000_0000
2021-04-02 22:22:31 +08:00
刘丰源 97ea51da9f fork fail 2021-04-01 15:47:11 +08:00
刘丰源 dfc42fb879 handle keyboard interrupt 2021-03-31 15:37:40 +08:00
刘丰源 17e612659a fix riscv64 2021-03-29 15:39:15 +08:00
55 changed files with 944 additions and 4988 deletions

6
.gitignore vendored
View File

@ -5,4 +5,8 @@ Cargo.lock
/rootfs
/prebuilt/linux/alpine*
.idea
scripts/linux/test-result.txt
scripts/linux/test-result.txt
*.img
.vscode
.DS_Store
link_user.S

View File

@ -57,6 +57,6 @@ ifeq ($(wildcard prebuilt/linux/riscv64/busybox),)
@mkdir -p prebuilt/linux/riscv64
@wget https://github.com/rcore-os/busybox-prebuilts/raw/master/busybox-1.30.1-riscv64/busybox -O prebuilt/linux/riscv64/busybox
endif
@cp prebuilt/linux/riscv64/busybox rootfs/bin/
@@rcore-fs-fuse riscv64.img rootfs zip
@cp prebuilt/linux/riscv64/* rootfs/bin/
@@rcore-fs-fuse --fs sfs riscv64.img rootfs zip
@qemu-img resize riscv64.img +50M

View File

@ -1,9 +0,0 @@
[package]
name = "rcore-memory"
version = "0.1.0"
authors = ["WangRunji <wangrunji0408@163.com>"]
edition = "2018"
[dependencies]
log = "0.4"
spin = "0.5"

View File

@ -1,772 +0,0 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
Alloc /home/os/dl/os-porting/rCore/crate/memory/src/no_mmu.rs /^ type Alloc: GlobalAlloc + 'static;$/;" T
BadFill /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^ struct BadFill;$/;" s
ByFrame /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/byframe.rs /^pub struct ByFrame<T: FrameAllocator> {$/;" s
COMPLETE /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^const COMPLETE: usize = 0x2;$/;" c
CastStream /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ struct CastStream<'v>(Cast<'v>);$/;" s
CastVisitor /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ struct CastVisitor<'v>(Cast<'v>);$/;" s
Count /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ struct Count(usize);$/;" s
CowExt /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^pub struct CowExt<T: PageTable> {$/;" s
DebugVisitor /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ struct DebugVisitor<'a, 'b: 'a>(&'a mut fmt::Formatter<'b>);$/;" s
Delay /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/delay.rs /^pub struct Delay<T: FrameAllocator> {$/;" s
DisplayVisitor /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ struct DisplayVisitor<'a, 'b: 'a>(&'a mut fmt::Formatter<'b>);$/;" s
EnhancedClockSwapManager /home/os/dl/os-porting/rCore/crate/memory/src/swap/enhanced_clock.rs /^pub struct EnhancedClockSwapManager {$/;" s
Entry /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^pub trait Entry {$/;" t
Err /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ type Err = ParseLevelError;$/;" T
Error /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/error.rs /^pub struct Error {$/;" s
FifoSwapManager /home/os/dl/os-porting/rCore/crate/memory/src/swap/fifo.rs /^pub struct FifoSwapManager {$/;" s
File /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/file.rs /^pub struct File<F, T> {$/;" s
Fill /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^pub trait Fill {$/;" t
Finish /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^struct Finish<'a> {$/;" s
Foo /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ struct Foo(Arc<AtomicUsize>);$/;" s
Foo /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ struct Foo(Arc<AtomicUsize>);$/;" s
Frame /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^type Frame = usize;$/;" T
FrameAlloc /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ struct FrameAlloc(usize);$/;" s
FrameAlloc /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ struct FrameAlloc(usize);$/;" s
FrameAllocator /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/mod.rs /^pub trait FrameAllocator: Debug + Clone + Send + Sync + 'static {$/;" t
FrameRcMap /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^struct FrameRcMap(Option<BTreeMap<Frame, (u16, u16)>>);$/;" s
Get /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ struct Get<'k, 'v> {$/;" s
INCOMPLETE /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^const INCOMPLETE: usize = 0x0;$/;" c
INIT /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ static INIT: Once<()> = Once::new();$/;" c
INIT /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ static INIT: Once<usize> = Once::new();$/;" c
INIT /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ pub const INIT: Self = Once {$/;" c
INITIALIZED /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^const INITIALIZED: usize = 2;$/;" c
INITIALIZING /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^const INITIALIZING: usize = 1;$/;" c
Inner /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/error.rs /^enum Inner {$/;" g
Item /home/os/dl/os-porting/rCore/crate/memory/src/addr.rs /^ type Item = Page;$/;" T
J /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ const J: u32 = 1000;$/;" c
K /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ const K: u32 = 3;$/;" c
Key /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^pub struct Key<'k> {$/;" s
KeyValues /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^struct KeyValues<'a>(&'a dyn kv::Source);$/;" s
LEVEL_PARSE_ERROR /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^static LEVEL_PARSE_ERROR: &str =$/;" c
LOG_LEVEL_NAMES /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^static LOG_LEVEL_NAMES: [&str; 6] = ["OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"];$/;" c
Level /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub enum Level {$/;" g
LevelEnum /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ struct LevelEnum;$/;" s
LevelFilter /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub enum LevelFilter {$/;" g
LevelFilterEnum /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ struct LevelFilterEnum;$/;" s
LevelFilterIdentifier /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ struct LevelFilterIdentifier;$/;" s
LevelIdentifier /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ struct LevelIdentifier;$/;" s
Linear /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/linear.rs /^pub struct Linear {$/;" s
Log /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub trait Log: Sync + Send {$/;" t
M /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ static M: Mutex<()> = Mutex::new(());$/;" c
MAX_LEVEL_INNER /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Debug;$/;" c
MAX_LEVEL_INNER /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Error;$/;" c
MAX_LEVEL_INNER /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Info;$/;" c
MAX_LEVEL_INNER /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Off;$/;" c
MAX_LEVEL_INNER /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Trace;$/;" c
MAX_LEVEL_INNER /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Warn;$/;" c
MAX_LOG_LEVEL_FILTER /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^static MAX_LOG_LEVEL_FILTER: AtomicUsize = AtomicUsize::new(0);$/;" c
MaybeStaticStr /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^enum MaybeStaticStr<'a> {$/;" g
MemOp /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ pub enum MemOp {$/;" g
MemoryArea /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^pub struct MemoryArea {$/;" s
MemoryArea /home/os/dl/os-porting/rCore/crate/memory/src/no_mmu.rs /^struct MemoryArea<S: NoMMUSupport> {$/;" s
MemoryAttr /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^pub struct MemoryAttr {$/;" s
MemoryHandler /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/mod.rs /^pub trait MemoryHandler: Debug + Send + Sync + 'static {$/;" t
MemorySet /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^pub struct MemorySet<T: PageTableExt> {$/;" s
MemorySet /home/os/dl/os-porting/rCore/crate/memory/src/no_mmu.rs /^pub struct MemorySet<S: NoMMUSupport> {$/;" s
Metadata /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub struct Metadata<'a> {$/;" s
MetadataBuilder /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub struct MetadataBuilder<'a> {$/;" s
MockEntry /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^pub struct MockEntry {$/;" s
MockPageTable /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^pub struct MockPageTable {$/;" s
MockSwapper /home/os/dl/os-porting/rCore/crate/memory/src/swap/mock_swapper.rs /^pub struct MockSwapper {$/;" s
Mutex /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^pub struct Mutex<T: ?Sized>$/;" s
MutexGuard /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^pub struct MutexGuard<'a, T: ?Sized + 'a>$/;" s
NOP /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ static NOP: NopLogger = NopLogger;$/;" c
NoMMUSupport /home/os/dl/os-porting/rCore/crate/memory/src/no_mmu.rs /^pub trait NoMMUSupport {$/;" t
NonCopy /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ struct NonCopy(i32);$/;" s
NonCopy /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ struct NonCopy(i32);$/;" s
NopLogger /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^struct NopLogger;$/;" s
O /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ static O: Once<()> = Once::INIT;$/;" c
O /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ static O: Once<()> = Once::new();$/;" c
O /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ static O: Once<usize> = Once::new();$/;" c
Once /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^pub struct Once<T> {$/;" s
OnePair /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ struct OnePair {$/;" s
Output /home/os/dl/os-porting/rCore/crate/memory/src/addr.rs /^ type Output = Self;$/;" T
PAGE_COUNT /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^const PAGE_COUNT: usize = 16;$/;" c
PAGE_SIZE /home/os/dl/os-porting/rCore/crate/memory/src/addr.rs /^pub const PAGE_SIZE: usize = 1 << 12;$/;" c
PAGE_SIZE /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^const PAGE_SIZE: usize = 4096;$/;" c
PAGE_SIZE /home/os/dl/os-porting/rCore/crate/memory/src/swap/mock_swapper.rs /^const PAGE_SIZE: usize = 4096;$/;" c
PANICKED /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^const PANICKED: usize = 0x3;$/;" c
Page /home/os/dl/os-porting/rCore/crate/memory/src/addr.rs /^pub struct Page {$/;" s
PageFaultHandler /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^type PageFaultHandler = Box<dyn FnMut(&mut MockPageTable, VirtAddr)>;$/;" T
PageRange /home/os/dl/os-porting/rCore/crate/memory/src/addr.rs /^pub struct PageRange {$/;" s
PageTable /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^pub trait PageTable {$/;" t
PageTableExt /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^pub trait PageTableExt: PageTable + Sized {$/;" t
ParseLevelError /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub struct ParseLevelError(());$/;" s
PhysAddr /home/os/dl/os-porting/rCore/crate/memory/src/addr.rs /^pub type PhysAddr = usize;$/;" T
READER /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^const READER: usize = 1 << 2;$/;" c
RUNNING /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^const RUNNING: usize = 0x1;$/;" c
Read /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/file.rs /^pub trait Read: Clone + Send + Sync + 'static {$/;" t
Record /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub struct Record<'a> {$/;" s
RecordBuilder /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub struct RecordBuilder<'a> {$/;" s
RwLock /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^pub struct RwLock<T: ?Sized> {$/;" s
RwLockReadGuard /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^pub struct RwLockReadGuard<'a, T: 'a + ?Sized> {$/;" s
RwLockUpgradeableGuard /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^pub struct RwLockUpgradeableGuard<'a, T: 'a + ?Sized> {$/;" s
RwLockWriteGuard /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^pub struct RwLockWriteGuard<'a, T: 'a + ?Sized> {$/;" s
SET_LOGGER_ERROR /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^static SET_LOGGER_ERROR: &str = "attempted to set a logger after the logging system \\$/;" c
STATE /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^static STATE: AtomicUsize = AtomicUsize::new(0);$/;" c
STATIC_MAX_LEVEL /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub const STATIC_MAX_LEVEL: LevelFilter = MAX_LEVEL_INNER;$/;" c
SetLoggerError /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub struct SetLoggerError(());$/;" s
Shared /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/shared.rs /^pub struct Shared<T: FrameAllocator> {$/;" s
SharedGuard /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/shared.rs /^pub struct SharedGuard<T: FrameAllocator> {$/;" s
Slot /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^pub struct Slot<'s, 'f> {$/;" s
Source /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^pub trait Source {$/;" t
SvalVisitor /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ struct SvalVisitor<'a, 'b: 'a>(&'a mut sval::value::Stream<'b>);$/;" s
SwapError /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^pub enum SwapError {$/;" g
SwapExt /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^pub struct SwapExt<T: PageTable, M: SwapManager, S: Swapper> {$/;" s
SwapManager /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^pub trait SwapManager {$/;" t
Swapper /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^pub trait Swapper {$/;" t
Target /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ type Target = T;$/;" T
Target /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ type Target = T;$/;" T
Target /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ type Target = T;$/;" T
Target /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ type Target = T;$/;" T
TestFill /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^ struct TestFill;$/;" s
TestSval /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ struct TestSval;$/;" s
TestVisitor /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/test.rs /^ struct TestVisitor(Option<Token>);$/;" s
TestVisitor /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ struct TestVisitor {$/;" s
ToKey /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^pub trait ToKey {$/;" t
ToValue /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/mod.rs /^pub trait ToValue {$/;" t
TypeIds /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ struct TypeIds;$/;" s
UNINITIALIZED /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^const UNINITIALIZED: usize = 0;$/;" c
UPGRADED /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^const UPGRADED: usize = 1 << 1;$/;" c
Unwinder /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ struct Unwinder {$/;" s
Unwinder /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ struct Unwinder {$/;" s
VMError /home/os/dl/os-porting/rCore/crate/memory/src/lib.rs /^pub enum VMError {$/;" g
VMResult /home/os/dl/os-porting/rCore/crate/memory/src/lib.rs /^pub type VMResult<T> = Result<T, VMError>;$/;" T
Value /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/mod.rs /^pub struct Value<'v> {$/;" s
Value /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ type Value = Level;$/;" T
Value /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ type Value = LevelFilter;$/;" T
VirtAddr /home/os/dl/os-porting/rCore/crate/memory/src/addr.rs /^pub type VirtAddr = usize;$/;" T
Visitor /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^pub trait Visitor<'kvs> {$/;" t
WRITER /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^const WRITER: usize = 1;$/;" c
__log_file /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/macros.rs /^macro_rules! __log_file {$/;" d
__log_format_args /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/macros.rs /^macro_rules! __log_format_args {$/;" d
__log_line /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/macros.rs /^macro_rules! __log_line {$/;" d
__log_module_path /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/macros.rs /^macro_rules! __log_module_path {$/;" d
__private_api_enabled /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub fn __private_api_enabled(level: Level, target: &str) -> bool {$/;" f
__private_api_log /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub fn __private_api_log($/;" f
__private_api_log_lit /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub fn __private_api_log_lit($/;" f
_check /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn _check(_: &dyn Source) {}$/;" f
_check /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn _check(_: &dyn Visitor) {}$/;" f
_read /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn _read(&mut self, addr: VirtAddr) {$/;" f
_write /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn _write(&mut self, addr: VirtAddr) {$/;" f
accessed /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn accessed(&self) -> bool {$/;" f
accessed /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn accessed(&self) -> bool;$/;" f
activate /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub unsafe fn activate(&self) {$/;" f
activate /home/os/dl/os-porting/rCore/crate/memory/src/no_mmu.rs /^ pub unsafe fn activate(&self) {}$/;" f
activate /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ unsafe fn activate(&self) {$/;" f
active_token /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn active_token() -> usize;$/;" f
add /home/os/dl/os-porting/rCore/crate/memory/src/addr.rs /^ fn add(self, rhs: usize) -> Self::Output {$/;" f
add_assign /home/os/dl/os-porting/rCore/crate/memory/src/addr.rs /^ fn add_assign(&mut self, rhs: usize) {$/;" f
alloc /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ fn alloc(&mut self) -> PhysAddr {$/;" f
alloc /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/mod.rs /^ fn alloc(&self) -> Option<PhysAddr>;$/;" f
alloc /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/shared.rs /^ pub fn alloc(&mut self, virt_addr: usize) -> Option<usize> {$/;" f
alloc /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ fn alloc(&mut self) -> Option<PhysAddr> {$/;" f
alloc_contiguous /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/mod.rs /^ fn alloc_contiguous(&self, size: usize, align_log2: usize) -> Option<PhysAddr>;$/;" f
alloc_id /home/os/dl/os-porting/rCore/crate/memory/src/swap/mock_swapper.rs /^ fn alloc_id(&self) -> usize {$/;" f
allocator /home/os/dl/os-porting/rCore/crate/memory/src/no_mmu.rs /^ fn allocator() -> &'static Self::Alloc;$/;" f
apply /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn apply(&self, entry: &mut dyn Entry) {$/;" f
args /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn args(&mut self, args: fmt::Arguments<'a>) -> &mut RecordBuilder<'a> {$/;" f
args /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn args(&self) -> &fmt::Arguments<'a> {$/;" f
as_buf /home/os/dl/os-porting/rCore/crate/memory/src/no_mmu.rs /^ unsafe fn as_buf(&self) -> &'static mut [u8] {$/;" f
as_ref /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^ fn as_ref(&self) -> &str {$/;" f
as_str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^ pub fn as_str(&self) -> &str {$/;" f
assert_data_eq /home/os/dl/os-porting/rCore/crate/memory/src/swap/mock_swapper.rs /^ fn assert_data_eq(data1: &[u8; 4096], data2: &[u8; 4096]) {$/;" f
bool /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn bool(&mut self, v: bool) -> Result<(), Error> {$/;" f
bool /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ fn bool(&mut self, v: bool) -> Result<(), Error> {$/;" f
bool /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn bool(&mut self, v: bool) -> Result<(), Error>;$/;" f
bool /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn bool(&mut self, v: bool) -> Result<(), Error> {$/;" f
bool /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn bool(&mut self, v: bool) -> sval::stream::Result {$/;" f
bool /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/test.rs /^ fn bool(&mut self, v: bool) -> Result<(), Error> {$/;" f
borrow /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^ fn borrow(&self) -> &str {$/;" f
borrowed_str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn borrowed_str(&mut self, v: &'v str) -> Result<(), Error> {$/;" f
borrowed_str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn borrowed_str(&mut self, v: &'v str) -> Result<(), Error> {$/;" f
box_clone /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/byframe.rs /^ fn box_clone(&self) -> Box<dyn MemoryHandler> {$/;" f
box_clone /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/delay.rs /^ fn box_clone(&self) -> Box<dyn MemoryHandler> {$/;" f
box_clone /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/file.rs /^ fn box_clone(&self) -> Box<dyn MemoryHandler> {$/;" f
box_clone /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/linear.rs /^ fn box_clone(&self) -> Box<dyn MemoryHandler> {$/;" f
box_clone /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/mod.rs /^ fn box_clone(&self) -> Box<dyn MemoryHandler>;$/;" f
box_clone /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/shared.rs /^ fn box_clone(&self) -> Box<dyn MemoryHandler> {$/;" f
boxed /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/error.rs /^ pub fn boxed<E>(err: E) -> Self$/;" f
btree_map /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn btree_map() {$/;" f
build /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn build(&self) -> Metadata<'a> {$/;" f
build /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn build(&self) -> Record<'a> {$/;" f
builder /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn builder() -> MetadataBuilder<'a> {$/;" f
builder /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn builder() -> RecordBuilder<'a> {$/;" f
call_once /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ pub fn call_once<'a, F>(&'a self, builder: F) -> &'a T$/;" f
cast /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn cast(self) -> Cast<'v> {$/;" f
char /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn char(&mut self, v: char) -> Result<(), Error> {$/;" f
char /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ fn char(&mut self, v: char) -> Result<(), Error> {$/;" f
char /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn char(&mut self, v: char) -> Result<(), Error>;$/;" f
char /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn char(&mut self, v: char) -> Result<(), Error> {$/;" f
char /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn char(&mut self, v: char) -> sval::stream::Result {$/;" f
char /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/test.rs /^ fn char(&mut self, v: char) -> Result<(), Error> {$/;" f
check_read_array /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ fn check_read_array<S>(&self, ptr: *const S, count: usize) -> usize {$/;" f
check_read_array /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub unsafe fn check_read_array<S>($/;" f
check_read_ptr /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub unsafe fn check_read_ptr<S>(&self, ptr: *const S) -> VMResult<&'static S> {$/;" f
check_write_array /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ fn check_write_array<S>(&self, ptr: *mut S, count: usize) -> usize {$/;" f
check_write_array /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub unsafe fn check_write_array<S>($/;" f
check_write_ptr /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub unsafe fn check_write_ptr<S>(&self, ptr: *mut S) -> VMResult<&'static mut S> {$/;" f
clear /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn clear(&mut self) {$/;" f
clear_accessed /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn clear_accessed(&mut self) {$/;" f
clear_accessed /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn clear_accessed(&mut self);$/;" f
clear_dirty /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn clear_dirty(&mut self) {$/;" f
clear_dirty /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn clear_dirty(&mut self);$/;" f
clear_shared /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn clear_shared(&mut self) {$/;" f
clear_shared /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn clear_shared(&mut self);$/;" f
clone /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn clone(&self) -> Self {$/;" f
clone /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn clone(&self) -> Level {$/;" f
clone /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn clone(&self) -> LevelFilter {$/;" f
clone /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/mod.rs /^ fn clone(&self) -> Box<dyn MemoryHandler> {$/;" f
clone /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn clone(&mut self) -> Self {$/;" f
clone /home/os/dl/os-porting/rCore/crate/memory/src/no_mmu.rs /^ fn clone(&self) -> Self {$/;" f
clone /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ unsafe fn clone<'a, 'b, T>(x: &'a mut T) -> &'b mut T {$/;" f
clone_map /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/byframe.rs /^ fn clone_map($/;" f
clone_map /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/delay.rs /^ fn clone_map($/;" f
clone_map /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/file.rs /^ fn clone_map($/;" f
clone_map /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/linear.rs /^ fn clone_map($/;" f
clone_map /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/mod.rs /^ fn clone_map($/;" f
clone_map /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/shared.rs /^ fn clone_map($/;" f
cmp /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^ fn cmp(&self, other: &Self) -> cmp::Ordering {$/;" f
cmp /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn cmp(&self, other: &Level) -> cmp::Ordering {$/;" f
cmp /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn cmp(&self, other: &LevelFilter) -> cmp::Ordering {$/;" f
compare_exchange /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^fn compare_exchange($/;" f
contains /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn contains(&self, addr: VirtAddr) -> bool {$/;" f
count /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn count(&self) -> usize {$/;" f
count /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn count() {$/;" f
count /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn count(&self) -> usize {$/;" f
count /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn count() {$/;" f
dealloc /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/mod.rs /^ fn dealloc(&self, target: PhysAddr);$/;" f
dealloc /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/shared.rs /^ pub fn dealloc(&mut self, virt_addr: usize) {$/;" f
debug /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn debug(&mut self, _: &dyn fmt::Debug) -> Result<(), Error> {$/;" f
debug /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ fn debug(&mut self, v: &dyn fmt::Debug) -> Result<(), Error> {$/;" f
debug /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn debug(&mut self, v: &dyn fmt::Debug) -> Result<(), Error>;$/;" f
debug /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn debug(&mut self, v: &dyn fmt::Debug) -> Result<(), Error> {$/;" f
debug /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/test.rs /^ fn debug(&mut self, v: &dyn fmt::Debug) -> Result<(), Error> {$/;" f
debug /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/macros.rs /^macro_rules! debug {$/;" d
default /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn default() -> Mutex<T> {$/;" f
default /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn default() -> RwLock<T> {$/;" f
deref /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn deref<'b>(&'b self) -> &'b T { &*self.data }$/;" f
deref /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn deref(&self) -> &T {$/;" f
deref /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ fn deref(&self) -> &<Self as Deref>::Target {$/;" f
deref /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ fn deref(&self) -> &<Self as Deref>::Target {$/;" f
deref_mut /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn deref_mut<'b>(&'b mut self) -> &'b mut T { &mut *self.data }$/;" f
deref_mut /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn deref_mut(&mut self) -> &mut T {$/;" f
deref_mut /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {$/;" f
deref_mut /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {$/;" f
deserialize /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>$/;" f
deserialize /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>$/;" f
dirty /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn dirty(&self) -> bool {$/;" f
dirty /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn dirty(&self) -> bool;$/;" f
display /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ fn display(&mut self, v: &dyn fmt::Display) -> Result<(), Error> {$/;" f
display /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn display(&mut self, v: &dyn fmt::Display) -> Result<(), Error> {$/;" f
downcast_primitive /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn downcast_primitive<'v, T: ?Sized>(&self, value: Erased<'v, T>) -> Option<Primitive<'v>> {$/;" f
downcast_primitive /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn downcast_primitive(self) -> Option<Primitive<'v>> {$/;" f
downgrade /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ pub fn downgrade(self) -> RwLockReadGuard<'rwlock, T> {$/;" f
drop /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn drop(&mut self) {$/;" f
drop /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn drop(&mut self) {$/;" f
drop /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn drop(&mut self)$/;" f
drop /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ fn drop(&mut self) {$/;" f
drop /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn drop(&mut self) {$/;" f
drop /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn drop(&mut self) {$/;" f
drop /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn drop(&mut self) {$/;" f
drop /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/shared.rs /^ fn drop(&mut self) {$/;" f
drop /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ fn drop(&mut self) {$/;" f
drop /home/os/dl/os-porting/rCore/crate/memory/src/no_mmu.rs /^ fn drop(&mut self) {$/;" f
enabled /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn enabled(&self, _: &Metadata) -> bool {$/;" f
enabled /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn enabled(&self, metadata: &Metadata) -> bool;$/;" f
entry /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn entry() {$/;" f
eq /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^ fn eq(&self, other: &Key<'ko>) -> bool {$/;" f
eq /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn eq(&self, other: &Level) -> bool {$/;" f
eq /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn eq(&self, other: &LevelFilter) -> bool {$/;" f
eq_ignore_ascii_case /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^fn eq_ignore_ascii_case(a: &str, b: &str) -> bool {$/;" f
error /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/macros.rs /^macro_rules! error {$/;" d
execute /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn execute(mut self) -> Self {$/;" f
execute /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn execute(&self) -> bool {$/;" f
execute /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn execute(&self) -> bool;$/;" f
expecting /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {$/;" f
f64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn f64(&mut self, v: f64) -> Result<(), Error> {$/;" f
f64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ fn f64(&mut self, v: f64) -> Result<(), Error> {$/;" f
f64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn f64(&mut self, v: f64) -> Result<(), Error>;$/;" f
f64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn f64(&mut self, v: f64) -> Result<(), Error> {$/;" f
f64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn f64(&mut self, v: f64) -> sval::stream::Result {$/;" f
f64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/test.rs /^ fn f64(&mut self, v: f64) -> Result<(), Error> {$/;" f
file /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn file(&mut self, file: Option<&'a str>) -> &mut RecordBuilder<'a> {$/;" f
file /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn file(&self) -> Option<&'a str> {$/;" f
file_static /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn file_static(&mut self, file: Option<&'static str>) -> &mut RecordBuilder<'a> {$/;" f
file_static /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn file_static(&self) -> Option<&'static str> {$/;" f
fill /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^ fn fill(&self, slot: &mut Slot) -> Result<(), Error> {$/;" f
fill /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^ fn fill(&self, slot: &mut Slot) -> Result<(), Error> {$/;" f
fill /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^ fn fill(&self, slot: &mut Slot) -> Result<(), Error>;$/;" f
fill_any /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^ pub fn fill_any<T>(&mut self, value: T) -> Result<(), Error>$/;" f
fill_cast /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^ fn fill_cast() {$/;" f
fill_data /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/file.rs /^ fn fill_data(&self, pt: &mut dyn PageTable, addr: VirtAddr) -> usize {$/;" f
fill_debug /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^ fn fill_debug() {$/;" f
fill_debug /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ pub fn fill_debug<T>(&mut self, value: T) -> Result<(), Error>$/;" f
fill_display /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ pub fn fill_display<T>(&mut self, value: T) -> Result<(), Error>$/;" f
fill_multiple_times_panics /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^ fn fill_multiple_times_panics() {$/;" f
fill_sval /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ pub fn fill_sval<T>(&mut self, value: T) -> Result<(), Error>$/;" f
fill_value_borrowed /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^ fn fill_value_borrowed() {$/;" f
fill_value_owned /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^ fn fill_value_owned() {$/;" f
find_free_area /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn find_free_area(&self, addr_hint: usize, len: usize) -> VirtAddr {$/;" f
flush /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn flush(&self) {}$/;" f
flush /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn flush(&self);$/;" f
flush_cache_copy_user /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn flush_cache_copy_user(&mut self, start: VirtAddr, end: VirtAddr, execute: bool);$/;" f
flush_tlb /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn flush_tlb();$/;" f
fmt /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/error.rs /^ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {$/;" f
fmt /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {$/;" f
fmt /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {$/;" f
fmt /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {$/;" f
fmt /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {$/;" f
fmt /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {$/;" f
fmt /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result$/;" f
fmt /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {$/;" f
fmt /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {$/;" f
fmt /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/file.rs /^ fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {$/;" f
fmt /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {$/;" f
fmt_cast /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ fn fmt_cast() {$/;" f
fmt_debug /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ fn fmt_debug() {$/;" f
fmt_display /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ fn fmt_display() {$/;" f
fn /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ pub const fn new(user_data: T) -> Mutex<T>$/;" c
fn /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ pub const fn new() -> Once<T> {$/;" c
fn /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ pub const fn new(user_data: T) -> RwLock<T> {$/;" c
force_get /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ fn force_get<'a>(&'a self) -> &'a T {$/;" f
force_read_decrement /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ pub unsafe fn force_read_decrement(&self) {$/;" f
force_unlock /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ pub unsafe fn force_unlock(&self) {$/;" f
force_write_unlock /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ pub unsafe fn force_write_unlock(&self) {$/;" f
from /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/error.rs /^ fn from(err: io::Error) -> Self {$/;" f
from /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/error.rs /^ fn from(_: fmt::Error) -> Self {$/;" f
from /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^ fn from(s: &'k str) -> Self {$/;" f
from /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/impls.rs /^ fn from(value: $into_ty) -> Self {$/;" f
from /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/impls.rs /^ fn from(value: &'v str) -> Self {$/;" f
from /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/impls.rs /^ fn from(value: fmt::Arguments<'v>) -> Self {$/;" f
from /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn from(v: &'v str) -> Self {$/;" f
from /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn from(v: bool) -> Self {$/;" f
from /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn from(v: char) -> Self {$/;" f
from /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn from(v: f64) -> Self {$/;" f
from /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn from(v: fmt::Arguments<'v>) -> Self {$/;" f
from /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn from(v: i64) -> Self {$/;" f
from /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn from(v: u64) -> Self {$/;" f
from_debug /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ pub fn from_debug<T>(value: &'v T) -> Self$/;" f
from_display /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ pub fn from_display<T>(value: &'v T) -> Self$/;" f
from_fill /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^ pub fn from_fill<T>(value: &'v T) -> Self$/;" f
from_primitive /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/mod.rs /^ fn from_primitive<T>(value: T) -> Self$/;" f
from_str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^ pub fn from_str(key: &'k str) -> Self {$/;" f
from_str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn from_str(level: &str) -> Result<Level, Self::Err> {$/;" f
from_str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn from_str(level: &str) -> Result<LevelFilter, Self::Err> {$/;" f
from_sval /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn from_sval(_: sval::value::Error) -> Self {$/;" f
from_sval /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ pub fn from_sval<T>(value: &'v T) -> Self$/;" f
from_usize /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn from_usize(u: usize) -> Option<Level> {$/;" f
from_usize /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn from_usize(u: usize) -> Option<LevelFilter> {$/;" f
ge /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn ge(&self, other: &Level) -> bool {$/;" f
ge /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn ge(&self, other: &LevelFilter) -> bool {$/;" f
get /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn get() {$/;" f
get /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn get<'v>(&'v self, key: Key) -> Option<Value<'v>> {$/;" f
get /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn get() {$/;" f
get /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn get<'v>(&'v self, key: Key) -> Option<Value<'v>> {$/;" f
get /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn get(&self) -> &'a str {$/;" f
get /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/shared.rs /^ pub fn get(&self, addr: usize) -> Option<usize> {$/;" f
get_entry /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn get_entry(&mut self, addr: VirtAddr) -> Option<&mut dyn Entry> {$/;" f
get_entry /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn get_entry(&mut self, addr: VirtAddr) -> Option<&mut dyn Entry>;$/;" f
get_page_slice_mut /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn get_page_slice_mut<'a, 'b>(&'a mut self, addr: VirtAddr) -> &'b mut [u8] {$/;" f
get_page_slice_mut /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn get_page_slice_mut<'a>(&mut self, addr: VirtAddr) -> &'a mut [u8];$/;" f
get_page_table_mut /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn get_page_table_mut(&mut self) -> &mut T {$/;" f
gt /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn gt(&self, other: &Level) -> bool {$/;" f
gt /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn gt(&self, other: &LevelFilter) -> bool {$/;" f
handle_page_fault /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/byframe.rs /^ fn handle_page_fault(&self, _pt: &mut dyn PageTable, _addr: VirtAddr) -> bool {$/;" f
handle_page_fault /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/delay.rs /^ fn handle_page_fault(&self, pt: &mut dyn PageTable, addr: VirtAddr) -> bool {$/;" f
handle_page_fault /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/file.rs /^ fn handle_page_fault(&self, pt: &mut dyn PageTable, addr: usize) -> bool {$/;" f
handle_page_fault /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/linear.rs /^ fn handle_page_fault(&self, _pt: &mut dyn PageTable, _addr: VirtAddr) -> bool {$/;" f
handle_page_fault /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/mod.rs /^ fn handle_page_fault(&self, pt: &mut dyn PageTable, addr: VirtAddr) -> bool;$/;" f
handle_page_fault /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/shared.rs /^ fn handle_page_fault(&self, pt: &mut dyn PageTable, addr: VirtAddr) -> bool {$/;" f
handle_page_fault /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn handle_page_fault(&mut self, addr: VirtAddr) -> bool {$/;" f
hash /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^ fn hash<H>(&self, state: &mut H)$/;" f
hash_map /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn hash_map() {$/;" f
i64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn i64(&mut self, v: i64) -> Result<(), Error> {$/;" f
i64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ fn i64(&mut self, v: i64) -> Result<(), Error> {$/;" f
i64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn i64(&mut self, v: i64) -> Result<(), Error>;$/;" f
i64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn i64(&mut self, v: i64) -> Result<(), Error> {$/;" f
i64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn i64(&mut self, v: i64) -> sval::stream::Result {$/;" f
i64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/test.rs /^ fn i64(&mut self, v: i64) -> Result<(), Error> {$/;" f
impl_into_owned /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/impls.rs /^macro_rules! impl_into_owned {$/;" d
inc /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn inc() {$/;" f
info /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/macros.rs /^macro_rules! info {$/;" d
init_constant /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ fn init_constant() {$/;" f
into_bool /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn into_bool(self) -> Option<bool> {$/;" f
into_borrowed_str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn into_borrowed_str(self) -> Option<&'v str> {$/;" f
into_char /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn into_char(self) -> Option<char> {$/;" f
into_f64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn into_f64(self) -> Option<f64> {$/;" f
into_i64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn into_i64(self) -> Option<i64> {$/;" f
into_inner /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ pub fn into_inner(self) -> T {$/;" f
into_inner /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ pub fn into_inner(self) -> T {$/;" f
into_primitive /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn into_primitive(self) -> Primitive<'v> {$/;" f
into_sval /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn into_sval(self) -> sval::value::Error {$/;" f
into_u64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn into_u64(self) -> Option<u64> {$/;" f
invalid_token /home/os/dl/os-porting/rCore/crate/memory/src/swap/mock_swapper.rs /^ fn invalid_token() {$/;" f
is_overlap_with /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn is_overlap_with(&self, start_addr: VirtAddr, end_addr: VirtAddr) -> bool {$/;" f
iter /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn iter(&self) -> impl Iterator<Item = &MemoryArea> {$/;" f
key_from_string /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^ fn key_from_string() {$/;" f
key_values /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn key_values(&mut self, kvs: &'a dyn kv::Source) -> &mut RecordBuilder<'a> {$/;" f
key_values /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn key_values(&self) -> &dyn kv::Source {$/;" f
le /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn le(&self, other: &Level) -> bool {$/;" f
le /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn le(&self, other: &LevelFilter) -> bool {$/;" f
level /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn level(&mut self, arg: Level) -> &mut MetadataBuilder<'a> {$/;" f
level /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn level(&mut self, level: Level) -> &mut RecordBuilder<'a> {$/;" f
level /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn level(&self) -> Level {$/;" f
level_bytes_tokens /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn level_bytes_tokens(variant: &'static [u8]) -> [Token; 3] {$/;" f
level_filter_bytes_tokens /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn level_filter_bytes_tokens(variant: &'static [u8]) -> [Token; 3] {$/;" f
level_filter_token /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn level_filter_token(variant: &'static str) -> Token {$/;" f
level_token /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn level_token(variant: &'static str) -> Token {$/;" f
line /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn line(&mut self, line: Option<u32>) -> &mut RecordBuilder<'a> {$/;" f
line /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn line(&self) -> Option<u32> {$/;" f
lock /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ pub fn lock(&self) -> MutexGuard<T>$/;" f
log /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn log(&self, _: &Record) {}$/;" f
log /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn log(&self, record: &Record);$/;" f
log /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/macros.rs /^macro_rules! log {$/;" d
log_enabled /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/macros.rs /^macro_rules! log_enabled {$/;" d
logger /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub fn logger() -> &'static dyn Log {$/;" f
lots_and_lots /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn lots_and_lots() {$/;" f
lt /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn lt(&self, other: &Level) -> bool {$/;" f
lt /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn lt(&self, other: &LevelFilter) -> bool {$/;" f
map /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ fn map(&mut self) -> &mut BTreeMap<Frame, (u16, u16)> {$/;" f
map /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/byframe.rs /^ fn map(&self, pt: &mut dyn PageTable, addr: VirtAddr, attr: &MemoryAttr) {$/;" f
map /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/delay.rs /^ fn map(&self, pt: &mut dyn PageTable, addr: VirtAddr, attr: &MemoryAttr) {$/;" f
map /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/file.rs /^ fn map(&self, pt: &mut dyn PageTable, addr: usize, attr: &MemoryAttr) {$/;" f
map /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/linear.rs /^ fn map(&self, pt: &mut dyn PageTable, addr: VirtAddr, attr: &MemoryAttr) {$/;" f
map /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/mod.rs /^ fn map(&self, pt: &mut dyn PageTable, addr: VirtAddr, attr: &MemoryAttr);$/;" f
map /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/shared.rs /^ fn map(&self, pt: &mut dyn PageTable, addr: VirtAddr, attr: &MemoryAttr) {$/;" f
map /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ fn map(&self, pt: &mut dyn PageTable) {$/;" f
map /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn map(&mut self, addr: VirtAddr, target: PhysAddr) -> &mut dyn Entry {$/;" f
map /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn map(&mut self, addr: VirtAddr, target: PhysAddr) -> &mut dyn Entry;$/;" f
map_kernel /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn map_kernel(&mut self);$/;" f
map_to_shared /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ pub fn map_to_shared(&mut self, addr: VirtAddr, target: PhysAddr, writable: bool) {$/;" f
map_to_swappable /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ pub fn map_to_swappable(&mut self, addr: VirtAddr, target: PhysAddr) -> &mut T::Entry {$/;" f
max /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn max() -> Level {$/;" f
max /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn max() -> LevelFilter {$/;" f
max_level /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub fn max_level() -> LevelFilter {$/;" f
metadata /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn metadata(&mut self, metadata: Metadata<'a>) -> &mut RecordBuilder<'a> {$/;" f
metadata /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn metadata(&self) -> &Metadata<'a> {$/;" f
mmio /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn mmio(mut self, value: u8) -> Self {$/;" f
mmio /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn mmio(&self) -> u8 {$/;" f
mmio /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn mmio(&self) -> u8;$/;" f
module_path /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn module_path(&mut self, path: Option<&'a str>) -> &mut RecordBuilder<'a> {$/;" f
module_path /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn module_path(&self) -> Option<&'a str> {$/;" f
module_path_static /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn module_path_static(&mut self, path: Option<&'static str>) -> &mut RecordBuilder<'a> {$/;" f
module_path_static /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn module_path_static(&self) -> Option<&'static str> {$/;" f
move_next /home/os/dl/os-porting/rCore/crate/memory/src/swap/enhanced_clock.rs /^ fn move_next(&mut self) {$/;" f
msg /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/error.rs /^ pub fn msg(msg: &'static str) -> Self {$/;" f
mut /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^static mut LOGGER: &dyn Log = &NopLogger;$/;" c
mut /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ static mut CNT: u32 = 0;$/;" c
mut /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ static mut RUN: bool = false;$/;" c
new /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn new() -> MetadataBuilder<'a> {$/;" f
new /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn new() -> RecordBuilder<'a> {$/;" f
new /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ pub fn new(page_table: T) -> Self {$/;" f
new /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/byframe.rs /^ pub fn new(allocator: T) -> Self {$/;" f
new /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/delay.rs /^ pub fn new(allocator: T) -> Self {$/;" f
new /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/linear.rs /^ pub fn new(offset: isize) -> Self {$/;" f
new /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/shared.rs /^ pub fn new(allocator: T) -> Self {$/;" f
new /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn new() -> Self {$/;" f
new /home/os/dl/os-porting/rCore/crate/memory/src/no_mmu.rs /^ fn new(size: usize) -> Self {$/;" f
new /home/os/dl/os-porting/rCore/crate/memory/src/no_mmu.rs /^ pub fn new() -> Self {$/;" f
new /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ pub fn new() -> Self {$/;" f
new /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn new() -> Self {$/;" f
new /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ pub fn new(page_table: T, swap_manager: M, swapper: S) -> Self {$/;" f
new_bare /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn new_bare() -> Self {$/;" f
new_bare /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn new_bare() -> Self;$/;" f
new_with_guard /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/shared.rs /^ pub fn new_with_guard(allocator: T, guard: Arc<Mutex<SharedGuard<T>>>) -> Self {$/;" f
new_with_size /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/shared.rs /^ pub fn new_with_size(allocator: T, size: usize) -> Self {$/;" f
next /home/os/dl/os-porting/rCore/crate/memory/src/addr.rs /^ fn next(&mut self) -> Option<Self::Item> {$/;" f
none /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn none(&mut self) -> Result<(), Error> {$/;" f
none /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ fn none(&mut self) -> Result<(), Error> {$/;" f
none /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn none(&mut self) -> Result<(), Error>;$/;" f
none /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn none(&mut self) -> Result<(), Error> {$/;" f
none /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/test.rs /^ fn none(&mut self) -> Result<(), Error> {$/;" f
obtain_lock /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn obtain_lock(&self)$/;" f
of_addr /home/os/dl/os-porting/rCore/crate/memory/src/addr.rs /^ pub fn of_addr(addr: VirtAddr) -> Self {$/;" f
ok_or /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^fn ok_or<T, E>(t: Option<T>, e: E) -> Result<T, E> {$/;" f
page_fault /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn page_fault() {$/;" f
page_fault_handler /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ pub fn page_fault_handler($/;" f
page_fault_handler /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ pub fn page_fault_handler<T2: InactivePageTable>($/;" f
panic /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ fn panic() {$/;" f
partial_cmp /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^ fn partial_cmp(&self, other: &Key<'ko>) -> Option<cmp::Ordering> {$/;" f
partial_cmp /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn partial_cmp(&self, other: &Level) -> Option<cmp::Ordering> {$/;" f
partial_cmp /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn partial_cmp(&self, other: &LevelFilter) -> Option<cmp::Ordering> {$/;" f
pop /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn pop(&mut self, start_addr: VirtAddr, end_addr: VirtAddr) {$/;" f
pop /home/os/dl/os-porting/rCore/crate/memory/src/swap/enhanced_clock.rs /^ fn pop<T, S>(&mut self, page_table: &mut T, _swapper: &mut S) -> Option<VirtAddr>$/;" f
pop /home/os/dl/os-porting/rCore/crate/memory/src/swap/fifo.rs /^ fn pop<T, S>(&mut self, _: &mut T, _: &mut S) -> Option<Frame>$/;" f
pop /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ fn pop<T, S>(&mut self, page_table: &mut T, swapper: &mut S) -> Option<Frame>$/;" f
pop_with_split /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn pop_with_split(&mut self, start_addr: VirtAddr, end_addr: VirtAddr) {$/;" f
present /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn present(&self) -> bool {$/;" f
present /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn present(&self) -> bool;$/;" f
primitive_cast /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn primitive_cast() {$/;" f
primitive_cast /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn primitive_cast() {$/;" f
push /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn push($/;" f
push /home/os/dl/os-porting/rCore/crate/memory/src/no_mmu.rs /^ pub fn push(&mut self, size: usize) -> &'static mut [u8] {$/;" f
push /home/os/dl/os-porting/rCore/crate/memory/src/swap/enhanced_clock.rs /^ fn push(&mut self, addr: usize) {$/;" f
push /home/os/dl/os-porting/rCore/crate/memory/src/swap/fifo.rs /^ fn push(&mut self, frame: Frame) {$/;" f
push /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ fn push(&mut self, frame: Frame);$/;" f
range_of /home/os/dl/os-porting/rCore/crate/memory/src/addr.rs /^ pub fn range_of(begin: VirtAddr, end: VirtAddr) -> PageRange {$/;" f
read /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ pub fn read(&self) -> RwLockReadGuard<T> {$/;" f
read /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn read(&mut self, addr: usize) -> u8 {$/;" f
read /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn read(&mut self, _addr: VirtAddr) -> u8 {$/;" f
read_at /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/file.rs /^ fn read_at(&self, offset: usize, buf: &mut [u8]) -> usize;$/;" f
read_count /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ fn read_count(&mut self, frame: &Frame) -> u16 {$/;" f
read_decrease /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ fn read_decrease(&mut self, frame: &Frame) {$/;" f
read_increase /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ fn read_increase(&mut self, frame: &Frame) {$/;" f
read_write /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn read_write() {$/;" f
readonly /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn readonly(mut self) -> Self {$/;" f
readonly_shared /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn readonly_shared(&self) -> bool {$/;" f
readonly_shared /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn readonly_shared(&self) -> bool;$/;" f
remove /home/os/dl/os-porting/rCore/crate/memory/src/swap/enhanced_clock.rs /^ fn remove(&mut self, addr: usize) {$/;" f
remove /home/os/dl/os-porting/rCore/crate/memory/src/swap/fifo.rs /^ fn remove(&mut self, token: usize, addr: VirtAddr) {$/;" f
remove /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ fn remove(&mut self, token: usize, addr: VirtAddr);$/;" f
remove_current /home/os/dl/os-porting/rCore/crate/memory/src/swap/enhanced_clock.rs /^ fn remove_current(&mut self) -> Option<VirtAddr> {$/;" f
remove_from_swappable /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ pub unsafe fn remove_from_swappable<T2: InactivePageTable>($/;" f
serialize /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>$/;" f
set_boxed_logger /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub fn set_boxed_logger(logger: Box<dyn Log>) -> Result<(), SetLoggerError> {$/;" f
set_execute /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn set_execute(&mut self, _value: bool) {$/;" f
set_execute /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn set_execute(&mut self, value: bool);$/;" f
set_handler /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ pub fn set_handler(&mut self, page_fault_handler: PageFaultHandler) {$/;" f
set_logger /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub fn set_logger(logger: &'static dyn Log) -> Result<(), SetLoggerError> {$/;" f
set_logger_inner /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^fn set_logger_inner<F>(make_logger: F) -> Result<(), SetLoggerError>$/;" f
set_logger_racy /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub unsafe fn set_logger_racy(logger: &'static dyn Log) -> Result<(), SetLoggerError> {$/;" f
set_max_level /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^pub fn set_max_level(level: LevelFilter) {$/;" f
set_mmio /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn set_mmio(&mut self, _value: u8) {$/;" f
set_mmio /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn set_mmio(&mut self, value: u8);$/;" f
set_present /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn set_present(&mut self, value: bool) {$/;" f
set_present /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn set_present(&mut self, value: bool);$/;" f
set_shared /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn set_shared(&mut self, writable: bool) {$/;" f
set_shared /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn set_shared(&mut self, writable: bool);$/;" f
set_swappable /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ pub unsafe fn set_swappable<T2: InactivePageTable>(&mut self, pt: *mut T2, addr: VirtAddr) {$/;" f
set_swapped /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn set_swapped(&mut self, value: bool) {$/;" f
set_swapped /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn set_swapped(&mut self, value: bool);$/;" f
set_target /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn set_target(&mut self, target: usize) {$/;" f
set_target /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn set_target(&mut self, target: PhysAddr);$/;" f
set_token /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ unsafe fn set_token(token: usize);$/;" f
set_user /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn set_user(&mut self, _value: bool) {$/;" f
set_user /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn set_user(&mut self, value: bool);$/;" f
set_writable /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn set_writable(&mut self, value: bool) {$/;" f
set_writable /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn set_writable(&mut self, value: bool);$/;" f
smoke /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn smoke() {$/;" f
smoke /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn smoke() {$/;" f
smoke_once /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ fn smoke_once() {$/;" f
smoke_once_value /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ fn smoke_once_value() {$/;" f
source_is_object_safe /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn source_is_object_safe() {$/;" f
stampede_once /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ fn stampede_once() {$/;" f
start_address /home/os/dl/os-porting/rCore/crate/memory/src/addr.rs /^ pub fn start_address(&self) -> VirtAddr {$/;" f
std_support /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/error.rs /^mod std_support {$/;" m
std_support /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^mod std_support {$/;" m
std_support /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^mod std_support {$/;" m
std_support /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/impls.rs /^mod std_support {$/;" m
std_support /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^mod std_support {$/;" m
str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn str(&mut self, _: &str) -> Result<(), Error> {$/;" f
str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn str(&mut self, v: &str) -> Result<(), Error> {$/;" f
str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ fn str(&mut self, v: &str) -> Result<(), Error> {$/;" f
str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn str(&mut self, v: &str) -> Result<(), Error>;$/;" f
str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn str(&mut self, v: &str) -> Result<(), Error> {$/;" f
str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn str(&mut self, s: &str) -> sval::stream::Result {$/;" f
str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/test.rs /^ fn str(&mut self, v: &str) -> Result<(), Error> {$/;" f
stream /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn stream(&self, stream: &mut sval::value::Stream) -> sval::value::Result {$/;" f
stream /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn stream(&self, s: &mut sval::value::Stream) -> sval::value::Result {$/;" f
sval /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn sval(&mut self, v: &dyn super::sval::Value) -> Result<(), Error> {$/;" f
sval /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ fn sval(&mut self, v: &dyn super::sval::Value) -> Result<(), Error> {$/;" f
sval /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn sval(&mut self, v: &dyn sval::Value) -> Result<(), Error>;$/;" f
sval /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn sval(&mut self, v: &dyn sval::Value) -> Result<(), Error> {$/;" f
sval /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/test.rs /^ fn sval(&mut self, _: &dyn internal::sval::Value) -> Result<(), Error> {$/;" f
sval_cast /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn sval_cast() {$/;" f
sval_debug /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn sval_debug() {$/;" f
swap_in /home/os/dl/os-porting/rCore/crate/memory/src/swap/mock_swapper.rs /^ fn swap_in(&mut self, token: usize, data: &mut [u8]) -> Result<(), ()> {$/;" f
swap_in /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ fn swap_in(&mut self, token: usize, data: &mut [u8]) -> Result<(), ()>;$/;" f
swap_in /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ fn swap_in<T2: InactivePageTable>($/;" f
swap_out /home/os/dl/os-porting/rCore/crate/memory/src/swap/mock_swapper.rs /^ fn swap_out(&mut self, data: &[u8]) -> Result<usize, ()> {$/;" f
swap_out /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ fn swap_out(&mut self, data: &[u8]) -> Result<usize, ()>;$/;" f
swap_out /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ fn swap_out<T2: InactivePageTable>(&mut self, frame: &Frame) -> Result<PhysAddr, SwapError> {$/;" f
swap_out_any /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ pub fn swap_out_any<T2: InactivePageTable>(&mut self) -> Result<PhysAddr, SwapError> {$/;" f
swap_out_in /home/os/dl/os-porting/rCore/crate/memory/src/swap/mock_swapper.rs /^ fn swap_out_in() {$/;" f
swap_update /home/os/dl/os-porting/rCore/crate/memory/src/swap/mock_swapper.rs /^ fn swap_update(&mut self, token: usize, data: &[u8]) -> Result<(), ()> {$/;" f
swap_update /home/os/dl/os-porting/rCore/crate/memory/src/swap/mock_swapper.rs /^ fn swap_update() {$/;" f
swap_update /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ fn swap_update(&mut self, token: usize, data: &[u8]) -> Result<(), ()>;$/;" f
swapped /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn swapped(&self) -> bool {$/;" f
swapped /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn swapped(&self) -> bool;$/;" f
target /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn target(&mut self, target: &'a str) -> &mut MetadataBuilder<'a> {$/;" f
target /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn target(&mut self, target: &'a str) -> &mut RecordBuilder<'a> {$/;" f
target /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn target(&self) -> &'a str {$/;" f
target /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn target(&self) -> usize {$/;" f
target /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn target(&self) -> PhysAddr;$/;" f
test /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ fn test() {$/;" f
test /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^pub mod test {$/;" m
test /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^mod test {$/;" m
test /home/os/dl/os-porting/rCore/crate/memory/src/swap/enhanced_clock.rs /^ fn test() {$/;" f
test /home/os/dl/os-porting/rCore/crate/memory/src/swap/enhanced_clock.rs /^mod test {$/;" m
test /home/os/dl/os-porting/rCore/crate/memory/src/swap/fifo.rs /^ fn test() {$/;" f
test /home/os/dl/os-porting/rCore/crate/memory/src/swap/fifo.rs /^mod test {$/;" m
test /home/os/dl/os-porting/rCore/crate/memory/src/swap/mock_swapper.rs /^mod test {$/;" m
test /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^mod test {$/;" m
test_cross_cmp /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_cross_cmp() {$/;" f
test_cross_eq /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_cross_eq() {$/;" f
test_error_trait /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_error_trait() {$/;" f
test_force_read_decrement /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn test_force_read_decrement() {$/;" f
test_force_write_unlock /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn test_force_write_unlock() {$/;" f
test_free_area /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ fn test_free_area(&self, start_addr: usize, end_addr: usize) -> bool {$/;" f
test_from_sval /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn test_from_sval() {$/;" f
test_into_inner /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn test_into_inner() {$/;" f
test_into_inner /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn test_into_inner() {$/;" f
test_into_inner_drop /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn test_into_inner_drop() {$/;" f
test_into_inner_drop /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn test_into_inner_drop() {$/;" f
test_level_case_insensitive /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn test_level_case_insensitive() {$/;" f
test_level_de_bytes /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn test_level_de_bytes() {$/;" f
test_level_de_error /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn test_level_de_error() {$/;" f
test_level_filter_case_insensitive /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn test_level_filter_case_insensitive() {$/;" f
test_level_filter_de_bytes /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn test_level_filter_de_bytes() {$/;" f
test_level_filter_de_error /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn test_level_filter_de_error() {$/;" f
test_level_filter_ser_de /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn test_level_filter_ser_de() {$/;" f
test_level_from_str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_level_from_str() {$/;" f
test_level_ser_de /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn test_level_ser_de() {$/;" f
test_level_show /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_level_show() {$/;" f
test_levelfilter_from_str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_levelfilter_from_str() {$/;" f
test_levelfilter_show /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_levelfilter_show() {$/;" f
test_manager /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ pub fn test_manager(swap_manager: impl 'static + SwapManager, ops: &[MemOp], pgfault_count: &[u8]) {$/;" f
test_metadata_builder /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_metadata_builder() {$/;" f
test_metadata_convenience_builder /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_metadata_convenience_builder() {$/;" f
test_mutex_arc_access_in_unwind /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn test_mutex_arc_access_in_unwind() {$/;" f
test_mutex_arc_nested /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn test_mutex_arc_nested() {$/;" f
test_mutex_force_lock /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn test_mutex_force_lock() {$/;" f
test_mutex_unsized /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn test_mutex_unsized() {$/;" f
test_record_builder /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_record_builder() {$/;" f
test_record_complete_builder /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_record_complete_builder() {$/;" f
test_record_convenience_builder /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_record_convenience_builder() {$/;" f
test_record_key_values_builder /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_record_key_values_builder() {$/;" f
test_record_key_values_get_coerce /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_record_key_values_get_coerce() {$/;" f
test_rw_access_in_unwind /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn test_rw_access_in_unwind() {$/;" f
test_rw_arc /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn test_rw_arc() {$/;" f
test_rw_try_read /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn test_rw_try_read() {$/;" f
test_rwlock_try_write /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn test_rwlock_try_write() {$/;" f
test_rwlock_unsized /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn test_rwlock_unsized() {$/;" f
test_sval_structured /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn test_sval_structured() {$/;" f
test_to_level /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_to_level() {$/;" f
test_to_level_filter /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn test_to_level_filter() {$/;" f
test_to_value_display /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/impls.rs /^ fn test_to_value_display() {$/;" f
test_to_value_structured /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/impls.rs /^ fn test_to_value_structured() {$/;" f
test_upgrade_downgrade /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn test_upgrade_downgrade() {$/;" f
test_with /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ pub fn test_with(pt: &mut CowExt<impl PageTable>) {$/;" f
tests /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^mod tests {$/;" m
tests /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ mod tests {$/;" m
tests /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^mod tests {$/;" m
tests /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/fill.rs /^mod tests {$/;" m
tests /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/impls.rs /^mod tests {$/;" m
tests /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ mod tests {$/;" m
tests /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^mod tests {$/;" m
tests /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^mod tests {$/;" m
tests /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^mod tests {$/;" m
tests /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^mod tests {$/;" m
tests /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^mod tests {$/;" m
tests /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^mod tests {$/;" m
tests /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^mod tests {$/;" m
tests /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^mod tests {$/;" m
tick /home/os/dl/os-porting/rCore/crate/memory/src/swap/enhanced_clock.rs /^ fn tick(&mut self) {$/;" f
tick /home/os/dl/os-porting/rCore/crate/memory/src/swap/fifo.rs /^ fn tick(&mut self) {}$/;" f
tick /home/os/dl/os-porting/rCore/crate/memory/src/swap/mod.rs /^ fn tick(&mut self);$/;" f
to_ascii_uppercase /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn to_ascii_uppercase(c: u8) -> u8 {$/;" f
to_bool /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_bool(&self) -> Option<bool> {$/;" f
to_borrowed_str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_borrowed_str(&self) -> Option<&str> {$/;" f
to_builder /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn to_builder(&self) -> RecordBuilder {$/;" f
to_char /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_char(&self) -> Option<char> {$/;" f
to_f32 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_f32(&self) -> Option<f32> {$/;" f
to_f64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_f64(&self) -> Option<f64> {$/;" f
to_i16 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_i16(&self) -> Option<i16> {$/;" f
to_i32 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_i32(&self) -> Option<i32> {$/;" f
to_i64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_i64(&self) -> Option<i64> {$/;" f
to_i8 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_i8(&self) -> Option<i8> {$/;" f
to_isize /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_isize(&self) -> Option<isize> {$/;" f
to_key /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^ fn to_key(&self) -> Key {$/;" f
to_key /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^ fn to_key(&self) -> Key {$/;" f
to_key /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/key.rs /^ fn to_key(&self) -> Key;$/;" f
to_level /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn to_level(&self) -> Option<Level> {$/;" f
to_level_filter /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ pub fn to_level_filter(&self) -> LevelFilter {$/;" f
to_str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_str(&self) -> Option<Cow<str>> {$/;" f
to_u16 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_u16(&self) -> Option<u16> {$/;" f
to_u32 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_u32(&self) -> Option<u32> {$/;" f
to_u64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_u64(&self) -> Option<u64> {$/;" f
to_u8 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_u8(&self) -> Option<u8> {$/;" f
to_usize /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ pub fn to_usize(&self) -> Option<usize> {$/;" f
to_value /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/impls.rs /^ fn to_value(&self) -> Value {$/;" f
to_value /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/impls.rs /^ fn to_value(&self) -> Value {$/;" f
to_value /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/impls.rs /^ fn to_value(&self) -> Value {$/;" f
to_value /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/mod.rs /^ fn to_value(&self) -> Value {$/;" f
to_value /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/mod.rs /^ fn to_value(&self) -> Value;$/;" f
token /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn token(&self) -> usize {$/;" f
token /home/os/dl/os-porting/rCore/crate/memory/src/no_mmu.rs /^ pub fn token(&self) -> usize {$/;" f
token /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn token(&self) -> usize;$/;" f
trace /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/macros.rs /^macro_rules! trace {$/;" d
translate /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn translate(&mut self, addr: VirtAddr) -> Option<PhysAddr> {$/;" f
translate /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn translate(&self, addr: VirtAddr) -> PhysAddr {$/;" f
trigger_page_fault /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn trigger_page_fault(&mut self, addr: VirtAddr) {$/;" f
try /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ fn try() {$/;" f
try /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ pub fn try<'a>(&'a self) -> Option<&'a T> {$/;" f
try_lock /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ fn try_lock() {$/;" f
try_lock /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/mutex.rs /^ pub fn try_lock(&self) -> Option<MutexGuard<T>>$/;" f
try_no_wait /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ fn try_no_wait() {$/;" f
try_read /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ pub fn try_read(&self) -> Option<RwLockReadGuard<T>> {$/;" f
try_upgrade /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ pub fn try_upgrade(self) -> Result<RwLockWriteGuard<'rwlock, T>, Self> {$/;" f
try_upgrade_internal /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn try_upgrade_internal(self, strong: bool) -> Result<RwLockWriteGuard<'rwlock, T>, Self> {$/;" f
try_upgradeable_read /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ pub fn try_upgradeable_read(&self) -> Option<RwLockUpgradeableGuard<T>> {$/;" f
try_write /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ pub fn try_write(&self) -> Option<RwLockWriteGuard<T>> {$/;" f
try_write_internal /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ fn try_write_internal(&self, strong: bool) -> Option<RwLockWriteGuard<T>> {$/;" f
type_ids /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ macro_rules! type_ids {$/;" d
u64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/cast.rs /^ fn u64(&mut self, v: u64) -> Result<(), Error> {$/;" f
u64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/fmt.rs /^ fn u64(&mut self, v: u64) -> Result<(), Error> {$/;" f
u64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn u64(&mut self, v: u64) -> Result<(), Error>;$/;" f
u64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn u64(&mut self, v: u64) -> Result<(), Error> {$/;" f
u64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/sval.rs /^ fn u64(&mut self, v: u64) -> sval::stream::Result {$/;" f
u64 /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/test.rs /^ fn u64(&mut self, v: u64) -> Result<(), Error> {$/;" f
unmap /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/byframe.rs /^ fn unmap(&self, pt: &mut dyn PageTable, addr: VirtAddr) {$/;" f
unmap /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/delay.rs /^ fn unmap(&self, pt: &mut dyn PageTable, addr: VirtAddr) {$/;" f
unmap /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/file.rs /^ fn unmap(&self, pt: &mut dyn PageTable, addr: usize) {$/;" f
unmap /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/linear.rs /^ fn unmap(&self, pt: &mut dyn PageTable, addr: VirtAddr) {$/;" f
unmap /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/mod.rs /^ fn unmap(&self, pt: &mut dyn PageTable, addr: VirtAddr);$/;" f
unmap /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/handler/shared.rs /^ fn unmap(&self, pt: &mut dyn PageTable, addr: VirtAddr) {$/;" f
unmap /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ fn unmap(&self, pt: &mut dyn PageTable) {$/;" f
unmap /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn unmap(&mut self, addr: VirtAddr) {$/;" f
unmap /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn unmap(&mut self, addr: VirtAddr);$/;" f
unmap_shared /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ pub fn unmap_shared(&mut self, addr: VirtAddr) {$/;" f
update /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn update(&mut self) {}$/;" f
update /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn update(&mut self);$/;" f
upgrade /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ pub fn upgrade(mut self) -> RwLockWriteGuard<'rwlock, T> {$/;" f
upgradeable_read /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ pub fn upgradeable_read(&self) -> RwLockUpgradeableGuard<T> {$/;" f
user /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn user(mut self) -> Self {$/;" f
user /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn user(&self) -> bool {$/;" f
user /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn user(&self) -> bool;$/;" f
visit /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> {$/;" f
visit /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> {$/;" f
visit /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> {$/;" f
visit /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error>;$/;" f
visit /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/internal/mod.rs /^ fn visit(self, visitor: &mut dyn Visitor<'v>) -> Result<(), Error> {$/;" f
visit /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/value/mod.rs /^ fn visit<'a>(&'a self, visitor: &mut dyn Visitor<'a>) -> Result<(), Error> {$/;" f
visit_bytes /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>$/;" f
visit_enum /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn visit_enum<A>(self, value: A) -> Result<Self::Value, A::Error>$/;" f
visit_pair /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn visit_pair(&mut self, _: Key<'kvs>, _: Value<'kvs>) -> Result<(), Error> {$/;" f
visit_pair /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {$/;" f
visit_pair /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {$/;" f
visit_pair /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {$/;" f
visit_pair /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error>;$/;" f
visit_pair /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/lib.rs /^ fn visit_pair($/;" f
visit_str /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/serde.rs /^ fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>$/;" f
visitor_is_object_safe /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/kv/source.rs /^ fn visitor_is_object_safe() {$/;" f
wait /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ fn wait() {$/;" f
wait /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/once.rs /^ pub fn wait<'a>(&'a self) -> Option<&'a T> {$/;" f
warn /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/log-0.4.11/src/macros.rs /^macro_rules! warn {$/;" d
with /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub unsafe fn with(&self, f: impl FnOnce()) {$/;" f
with /home/os/dl/os-porting/rCore/crate/memory/src/no_mmu.rs /^ pub fn with<T>(&self, f: impl FnOnce() -> T) -> T {$/;" f
with /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ unsafe fn with<T>(&self, f: impl FnOnce() -> T) -> T {$/;" f
writable /home/os/dl/os-porting/rCore/crate/memory/src/memory_set/mod.rs /^ pub fn writable(mut self) -> Self {$/;" f
writable /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn writable(&self) -> bool {$/;" f
writable /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn writable(&self) -> bool;$/;" f
writable_shared /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn writable_shared(&self) -> bool {$/;" f
writable_shared /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn writable_shared(&self) -> bool;$/;" f
write /home/os/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/spin-0.5.2/src/rw_lock.rs /^ pub fn write(&self) -> RwLockWriteGuard<T> {$/;" f
write /home/os/dl/os-porting/rCore/crate/memory/src/paging/mock_page_table.rs /^ fn write(&mut self, addr: usize, data: u8) {$/;" f
write /home/os/dl/os-porting/rCore/crate/memory/src/paging/mod.rs /^ fn write(&mut self, _addr: VirtAddr, _data: u8) {$/;" f
write_count /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ fn write_count(&mut self, frame: &Frame) -> u16 {$/;" f
write_decrease /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ fn write_decrease(&mut self, frame: &Frame) {$/;" f
write_increase /home/os/dl/os-porting/rCore/crate/memory/src/cow.rs /^ fn write_increase(&mut self, frame: &Frame) {$/;" f

View File

@ -1,70 +0,0 @@
use core::ops::{Add, AddAssign};
pub type VirtAddr = usize;
pub type PhysAddr = usize;
pub const PAGE_SIZE: usize = 1 << 12;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Page {
number: usize,
}
impl Page {
/// Returns the start address of the page.
pub fn start_address(&self) -> VirtAddr {
self.number * PAGE_SIZE
}
/// Returns the page that contains the given virtual address.
pub fn of_addr(addr: VirtAddr) -> Self {
Page {
number: addr / PAGE_SIZE,
}
}
/// Returns a range of pages between address [begin, end)
pub fn range_of(begin: VirtAddr, end: VirtAddr) -> PageRange {
PageRange {
start: Page::of_addr(begin),
end: Page::of_addr(end - 1),
}
}
}
impl Add<usize> for Page {
type Output = Self;
fn add(self, rhs: usize) -> Self::Output {
Page {
number: self.number + rhs,
}
}
}
impl AddAssign<usize> for Page {
fn add_assign(&mut self, rhs: usize) {
*self = self.clone() + rhs;
}
}
/// A range of pages with exclusive upper bound.
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub struct PageRange {
start: Page,
end: Page,
}
impl Iterator for PageRange {
type Item = Page;
fn next(&mut self) -> Option<Self::Item> {
if self.start <= self.end {
let page = self.start.clone();
self.start += 1;
Some(page)
} else {
None
}
}
}

View File

@ -1,279 +0,0 @@
//! Shared memory & Copy-on-write extension for page table
//!
//! To use the CowExt, make a wrapper over the original apge table
//! Like: CowExt::new(origin_page_table)
//! Invoke page_fault_handler() on the CowExt to run the COW process
//! If the method above returns true, the COW process is executed, else do your own things.
//!
//! To implement the CowExt, we added a "shared state" to the page table entry
//! We use 2bits in the entry for "readonly and shared" and "writable and shared"
//! For CPU, the page of the entry is present and readonly,
//! and it's possible to read the page through different page tables
//! but when the page is writen, the page fault will be triggered.
//! When page fault is triggered, the page_fault_handler() on the CowExt should be invoked.
//! In the page_fault_handler() method, we return false if the page is accurately readonly.
//! Elsewise we copy the data in the page into a newly allocated frame,
//! and modify the page table entry to map the page to the frame, and set the present and writable bit.
//!
//! A frame can have write and read reference at the same time,
//! so we need to maintain the count of write and read reference.
//! When page fault occurs, if the read reference count is 0 and the write reference count is 1
//! The copy process should be skipped and the entry is mark as writable directly.
use super::paging::*;
use super::*;
use alloc::collections::BTreeMap;
use core::ops::{Deref, DerefMut};
/// Wrapper for page table, supporting shared map & copy-on-write
pub struct CowExt<T: PageTable> {
page_table: T,
rc_map: FrameRcMap,
}
impl<T: PageTable> CowExt<T> {
/*
** @brief create a COW extension
** @param page_table: T the inner page table
** @retval CowExt the COW extension created
*/
pub fn new(page_table: T) -> Self {
CowExt {
page_table,
rc_map: FrameRcMap::default(),
}
}
/*
** @brief map the virtual address to a target physics address as shared
** @param addr: VirtAddr the virual address to map
** @param target: VirtAddr the target physics address
** @param writable: bool if it is true, set the page as writable and shared
** else set the page as readonly and shared
** @retval none
*/
pub fn map_to_shared(&mut self, addr: VirtAddr, target: PhysAddr, writable: bool) {
let entry = self.page_table.map(addr, target);
entry.set_writable(false);
entry.set_shared(writable);
entry.update();
let frame = target / PAGE_SIZE;
match writable {
true => self.rc_map.write_increase(&frame),
false => self.rc_map.read_increase(&frame),
}
}
/*
** @brief unmap a virual address from physics address
** with apecial additional process for shared page
** @param addr: VirtAddr the virual address to unmap
** @retval none
*/
pub fn unmap_shared(&mut self, addr: VirtAddr) {
let entry = self.page_table.get_entry(addr).expect("entry not exist");
let frame = entry.target() / PAGE_SIZE;
if entry.readonly_shared() {
self.rc_map.read_decrease(&frame);
} else if entry.writable_shared() {
self.rc_map.write_decrease(&frame);
}
self.page_table.unmap(addr);
}
/*
** @brief execute the COW process for page fault
** This function must be called whenever PageFault happens.
** @param addr: VirtAddr the virual address of the page fault
** @param alloc_frame: impl FnOnce() -> PhysAddr
** the page allocation function
** that allocate a page and returns physics address
** of beginning of the page
** @retval bool whether copy-on-write happens.
*/
pub fn page_fault_handler(
&mut self,
addr: VirtAddr,
alloc_frame: impl FnOnce() -> PhysAddr,
) -> bool {
let entry = self.page_table.get_entry(addr);
if entry.is_none() {
return false;
}
let entry = entry.unwrap();
if !entry.readonly_shared() && !entry.writable_shared() {
return false;
}
let frame = entry.target() / PAGE_SIZE;
if self.rc_map.read_count(&frame) == 0 && self.rc_map.write_count(&frame) == 1 {
entry.clear_shared();
entry.set_writable(true);
entry.update();
self.rc_map.write_decrease(&frame);
return true;
}
use core::mem::MaybeUninit;
let mut temp_data: [u8; PAGE_SIZE] = unsafe { MaybeUninit::zeroed().assume_init() };
temp_data[..].copy_from_slice(self.get_page_slice_mut(addr));
self.unmap_shared(addr);
self.map(addr, alloc_frame());
self.get_page_slice_mut(addr)
.copy_from_slice(&temp_data[..]);
true
}
}
impl<T: PageTable> Deref for CowExt<T> {
type Target = T;
fn deref(&self) -> &<Self as Deref>::Target {
&self.page_table
}
}
impl<T: PageTable> DerefMut for CowExt<T> {
fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
&mut self.page_table
}
}
/// A map contains reference count for shared frame
///
/// It will lazily construct the `BTreeMap`, to avoid heap alloc when heap is unavailable.
#[derive(Default)]
struct FrameRcMap(Option<BTreeMap<Frame, (u16, u16)>>);
type Frame = usize;
impl FrameRcMap {
/*
** @brief get the read reference count of the frame
** @param frame: &Frame the frame to get the read reference count
** @retval u16 the read reference count
*/
fn read_count(&mut self, frame: &Frame) -> u16 {
self.map().get(frame).unwrap_or(&(0, 0)).0
}
/*
** @brief get the write reference count of the frame
** @param frame: &Frame the frame to get the write reference count
** @retval u16 the write reference count
*/
fn write_count(&mut self, frame: &Frame) -> u16 {
self.map().get(frame).unwrap_or(&(0, 0)).1
}
/*
** @brief increase the read reference count of the frame
** @param frame: &Frame the frame to increase the read reference count
** @retval none
*/
fn read_increase(&mut self, frame: &Frame) {
let (r, w) = self.map().get(&frame).unwrap_or(&(0, 0)).clone();
self.map().insert(frame.clone(), (r + 1, w));
}
/*
** @brief decrease the read reference count of the frame
** @param frame: &Frame the frame to decrease the read reference count
** @retval none
*/
fn read_decrease(&mut self, frame: &Frame) {
self.map().get_mut(frame).unwrap().0 -= 1;
}
/*
** @brief increase the write reference count of the frame
** @param frame: &Frame the frame to increase the write reference count
** @retval none
*/
fn write_increase(&mut self, frame: &Frame) {
let (r, w) = self.map().get(&frame).unwrap_or(&(0, 0)).clone();
self.map().insert(frame.clone(), (r, w + 1));
}
/*
** @brief decrease the write reference count of the frame
** @param frame: &Frame the frame to decrease the write reference count
** @retval none
*/
fn write_decrease(&mut self, frame: &Frame) {
self.map().get_mut(frame).unwrap().1 -= 1;
}
/*
** @brief get the internal btree map, lazily initialize the btree map if it is not present
** @retval &mut BTreeMap<Frame, (u16, u16)>
** the internal btree map
*/
fn map(&mut self) -> &mut BTreeMap<Frame, (u16, u16)> {
if self.0.is_none() {
self.0 = Some(BTreeMap::new());
}
self.0.as_mut().unwrap()
}
}
pub mod test {
use super::*;
#[test]
fn test() {
let mut pt = CowExt::new(MockPageTable::new());
let pt0 = unsafe { &mut *(&mut pt as *mut CowExt<MockPageTable>) };
struct FrameAlloc(usize);
impl FrameAlloc {
fn alloc(&mut self) -> PhysAddr {
let pa = self.0 * PAGE_SIZE;
self.0 += 1;
pa
}
}
let mut alloc = FrameAlloc(4);
pt.page_table
.set_handler(Box::new(move |_, addr: VirtAddr| {
pt0.page_fault_handler(addr, || alloc.alloc());
}));
test_with(&mut pt);
}
pub fn test_with(pt: &mut CowExt<impl PageTable>) {
let target = 0x0;
let frame = 0x0;
pt.map(0x1000, target);
pt.write(0x1000, 1);
assert_eq!(pt.read(0x1000), 1);
pt.unmap(0x1000);
pt.map_to_shared(0x1000, target, true);
pt.map_to_shared(0x2000, target, true);
pt.map_to_shared(0x3000, target, false);
assert_eq!(pt.rc_map.read_count(&frame), 1);
assert_eq!(pt.rc_map.write_count(&frame), 2);
assert_eq!(pt.read(0x1000), 1);
assert_eq!(pt.read(0x2000), 1);
assert_eq!(pt.read(0x3000), 1);
pt.write(0x1000, 2);
assert_eq!(pt.rc_map.read_count(&frame), 1);
assert_eq!(pt.rc_map.write_count(&frame), 1);
assert_ne!(pt.get_entry(0x1000).unwrap().target(), target);
assert_eq!(pt.read(0x1000), 2);
assert_eq!(pt.read(0x2000), 1);
assert_eq!(pt.read(0x3000), 1);
pt.unmap_shared(0x3000);
assert_eq!(pt.rc_map.read_count(&frame), 0);
assert_eq!(pt.rc_map.write_count(&frame), 1);
// assert!(!pt.get_entry(0x3000).present());
pt.write(0x2000, 3);
assert_eq!(pt.rc_map.read_count(&frame), 0);
assert_eq!(pt.rc_map.write_count(&frame), 0);
assert_eq!(
pt.get_entry(0x2000).unwrap().target(),
target,
"The last write reference should not allocate new frame."
);
assert_eq!(pt.read(0x1000), 2);
assert_eq!(pt.read(0x2000), 3);
}
}

View File

@ -1,22 +0,0 @@
#![cfg_attr(not(test), no_std)]
#![feature(nll)]
#![deny(non_snake_case)]
// import macros from log
use log::*;
extern crate alloc;
mod addr;
pub mod cow;
pub mod memory_set;
pub mod no_mmu;
pub mod paging;
//pub mod swap;
pub use crate::addr::*;
pub enum VMError {
InvalidPtr,
}
pub type VMResult<T> = Result<T, VMError>;

View File

@ -1,46 +0,0 @@
use super::*;
#[derive(Debug, Clone)]
pub struct ByFrame<T: FrameAllocator> {
allocator: T,
}
impl<T: FrameAllocator> MemoryHandler for ByFrame<T> {
fn box_clone(&self) -> Box<dyn MemoryHandler> {
Box::new(self.clone())
}
fn map(&self, pt: &mut dyn PageTable, addr: VirtAddr, attr: &MemoryAttr) {
let target = self.allocator.alloc().expect("failed to allocate frame");
let entry = pt.map(addr, target);
attr.apply(entry);
}
fn unmap(&self, pt: &mut dyn PageTable, addr: VirtAddr) {
let target = pt.get_entry(addr).expect("fail to get entry").target();
self.allocator.dealloc(target);
pt.unmap(addr);
}
fn clone_map(
&self,
pt: &mut dyn PageTable,
src_pt: &mut dyn PageTable,
addr: VirtAddr,
attr: &MemoryAttr,
) {
self.map(pt, addr, attr);
let data = src_pt.get_page_slice_mut(addr);
pt.get_page_slice_mut(addr).copy_from_slice(data);
}
fn handle_page_fault(&self, _pt: &mut dyn PageTable, _addr: VirtAddr) -> bool {
false
}
}
impl<T: FrameAllocator> ByFrame<T> {
pub fn new(allocator: T) -> Self {
ByFrame { allocator }
}
}

View File

@ -1,77 +0,0 @@
use super::*;
#[derive(Debug, Clone)]
pub struct Delay<T: FrameAllocator> {
allocator: T,
}
impl<T: FrameAllocator> MemoryHandler for Delay<T> {
fn box_clone(&self) -> Box<dyn MemoryHandler> {
Box::new(self.clone())
}
fn map(&self, pt: &mut dyn PageTable, addr: VirtAddr, attr: &MemoryAttr) {
let entry = pt.map(addr, 0);
entry.set_present(false);
attr.apply(entry);
}
fn unmap(&self, pt: &mut dyn PageTable, addr: VirtAddr) {
let entry = pt.get_entry(addr).expect("failed to get entry");
if entry.present() {
self.allocator.dealloc(entry.target());
}
// PageTable::unmap requires page to be present
entry.set_present(true);
pt.unmap(addr);
}
fn clone_map(
&self,
pt: &mut dyn PageTable,
src_pt: &mut dyn PageTable,
addr: VirtAddr,
attr: &MemoryAttr,
) {
let entry = src_pt.get_entry(addr).expect("failed to get entry");
if entry.present() {
// eager map and copy data
let data = src_pt.get_page_slice_mut(addr);
let target = self.allocator.alloc().expect("failed to alloc frame");
let entry = pt.map(addr, target);
attr.apply(entry);
pt.get_page_slice_mut(addr).copy_from_slice(data);
pt.flush_cache_copy_user(addr, addr + data.len(), attr.execute);
} else {
// delay map
self.map(pt, addr, attr);
}
}
fn handle_page_fault(&self, pt: &mut dyn PageTable, addr: VirtAddr) -> bool {
let entry = pt.get_entry(addr).expect("failed to get entry");
if entry.present() {
// not a delay case
return false;
}
let frame = self.allocator.alloc().expect("failed to alloc frame");
entry.set_target(frame);
entry.set_present(true);
entry.update();
//init with zero for delay mmap mode
let data = pt.get_page_slice_mut(addr);
let len = data.len();
for x in data {
*x = 0;
}
pt.flush_cache_copy_user(addr, addr + len, false);
true
}
}
impl<T: FrameAllocator> Delay<T> {
pub fn new(allocator: T) -> Self {
Delay { allocator }
}
}

View File

@ -1,102 +0,0 @@
use super::*;
/// Delay mapping a page to an area of a file.
#[derive(Clone)]
pub struct File<F, T> {
pub file: F,
pub mem_start: usize,
pub file_start: usize,
pub file_end: usize,
pub allocator: T,
}
pub trait Read: Clone + Send + Sync + 'static {
fn read_at(&self, offset: usize, buf: &mut [u8]) -> usize;
}
impl<F: Read, T: FrameAllocator> MemoryHandler for File<F, T> {
fn box_clone(&self) -> Box<dyn MemoryHandler> {
Box::new(self.clone())
}
fn map(&self, pt: &mut dyn PageTable, addr: usize, attr: &MemoryAttr) {
let entry = pt.map(addr, 0);
entry.set_present(false);
attr.apply(entry);
}
fn unmap(&self, pt: &mut dyn PageTable, addr: usize) {
let entry = pt.get_entry(addr).expect("failed to get entry");
if entry.present() {
self.allocator.dealloc(entry.target());
}
// PageTable::unmap requires page to be present
entry.set_present(true);
pt.unmap(addr);
}
fn clone_map(
&self,
pt: &mut dyn PageTable,
src_pt: &mut dyn PageTable,
addr: usize,
attr: &MemoryAttr,
) {
let entry = src_pt.get_entry(addr).expect("failed to get entry");
if entry.present() && !attr.readonly {
// eager map and copy data
let data = src_pt.get_page_slice_mut(addr);
let target = self.allocator.alloc().expect("failed to alloc frame");
let entry = pt.map(addr, target);
attr.apply(entry);
pt.get_page_slice_mut(addr).copy_from_slice(data);
pt.flush_cache_copy_user(addr, addr + data.len(), attr.execute);
} else {
// delay map
self.map(pt, addr, attr);
}
}
fn handle_page_fault(&self, pt: &mut dyn PageTable, addr: usize) -> bool {
let addr = addr & !(PAGE_SIZE - 1);
let entry = pt.get_entry(addr).expect("failed to get entry");
if entry.present() {
return false;
}
let execute = entry.execute();
let frame = self.allocator.alloc().expect("failed to alloc frame");
entry.set_target(frame);
entry.set_present(true);
entry.update();
let read_size = self.fill_data(pt, addr);
pt.flush_cache_copy_user(addr, addr + read_size, execute);
true
}
}
impl<F: Read, T: FrameAllocator> File<F, T> {
fn fill_data(&self, pt: &mut dyn PageTable, addr: VirtAddr) -> usize {
let data = pt.get_page_slice_mut(addr);
let file_offset = addr + self.file_start - self.mem_start;
let read_size = (self.file_end as isize - file_offset as isize)
.min(PAGE_SIZE as isize)
.max(0) as usize;
let read_size = self.file.read_at(file_offset, &mut data[..read_size]);
if read_size != PAGE_SIZE {
data[read_size..].iter_mut().for_each(|x| *x = 0);
}
read_size
}
}
impl<F, T> Debug for File<F, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
f.debug_struct("FileHandler")
.field("mem_start", &self.mem_start)
.field("file_start", &self.file_start)
.field("file_end", &self.file_end)
.finish()
}
}

View File

@ -1,42 +0,0 @@
use super::*;
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Linear {
offset: isize,
}
impl MemoryHandler for Linear {
fn box_clone(&self) -> Box<dyn MemoryHandler> {
Box::new(self.clone())
}
fn map(&self, pt: &mut dyn PageTable, addr: VirtAddr, attr: &MemoryAttr) {
let target = (addr as isize + self.offset) as PhysAddr;
let entry = pt.map(addr, target);
attr.apply(entry);
}
fn unmap(&self, pt: &mut dyn PageTable, addr: VirtAddr) {
pt.unmap(addr);
}
fn clone_map(
&self,
pt: &mut dyn PageTable,
_src_pt: &mut dyn PageTable,
addr: VirtAddr,
attr: &MemoryAttr,
) {
self.map(pt, addr, attr);
}
fn handle_page_fault(&self, _pt: &mut dyn PageTable, _addr: VirtAddr) -> bool {
false
}
}
impl Linear {
pub fn new(offset: isize) -> Self {
Linear { offset }
}
}

View File

@ -1,51 +0,0 @@
use super::*;
// here may be a interesting part for lab
pub trait MemoryHandler: Debug + Send + Sync + 'static {
fn box_clone(&self) -> Box<dyn MemoryHandler>;
/// Map `addr` in the page table
/// Should set page flags here instead of in `page_fault_handler`
fn map(&self, pt: &mut dyn PageTable, addr: VirtAddr, attr: &MemoryAttr);
/// Unmap `addr` in the page table
fn unmap(&self, pt: &mut dyn PageTable, addr: VirtAddr);
/// Clone map `addr` from page table `src_pt` to `pt`.
fn clone_map(
&self,
pt: &mut dyn PageTable,
src_pt: &mut dyn PageTable,
addr: VirtAddr,
attr: &MemoryAttr,
);
/// Handle page fault on `addr`
/// Return true if success, false if error
fn handle_page_fault(&self, pt: &mut dyn PageTable, addr: VirtAddr) -> bool;
}
impl Clone for Box<dyn MemoryHandler> {
fn clone(&self) -> Box<dyn MemoryHandler> {
self.box_clone()
}
}
pub trait FrameAllocator: Debug + Clone + Send + Sync + 'static {
fn alloc(&self) -> Option<PhysAddr>;
fn alloc_contiguous(&self, size: usize, align_log2: usize) -> Option<PhysAddr>;
fn dealloc(&self, target: PhysAddr);
}
mod byframe;
mod delay;
mod file;
mod linear;
mod shared;
//mod swap;
pub use self::byframe::ByFrame;
pub use self::delay::Delay;
pub use self::file::{File, Read};
pub use self::linear::Linear;
pub use self::shared::{Shared, SharedGuard};

View File

@ -1,171 +0,0 @@
use super::*;
use alloc::collections::BTreeMap;
use alloc::sync::Arc;
use spin::Mutex;
// represent physical memory area
#[derive(Debug)]
pub struct SharedGuard<T: FrameAllocator> {
allocator: T,
pub size: usize,
// indirect mapping now. target: page_offset -> physAddr
target: BTreeMap<usize, usize>,
}
impl<T: FrameAllocator> SharedGuard<T> {
pub fn new(allocator: T) -> Self {
SharedGuard {
allocator: allocator,
// size meaningful only for sys_shm
size: 0,
target: BTreeMap::new(),
}
}
pub fn new_with_size(allocator: T, size: usize) -> Self {
SharedGuard {
allocator: allocator,
size: size,
target: BTreeMap::new(),
}
}
pub fn alloc(&mut self, virt_addr: usize) -> Option<usize> {
let phys_addr = self.allocator.alloc().expect("failed to allocate frame");
self.target.insert(virt_addr, phys_addr);
Some(phys_addr)
}
pub fn dealloc(&mut self, virt_addr: usize) {
let phys_addr = self.target.get(&virt_addr).unwrap().clone();
self.allocator.dealloc(phys_addr);
self.target.remove(&virt_addr);
}
pub fn get(&self, addr: usize) -> Option<usize> {
match self.target.get(&addr) {
Some(phys_addr) => Some(phys_addr.clone()),
None => None,
}
}
}
impl<T: FrameAllocator> Drop for SharedGuard<T> {
fn drop(&mut self) {
let mut free_list = Vec::new();
for (virt_addr, _phys_addr) in self.target.iter() {
free_list.push(virt_addr.clone());
}
for virt_addr in free_list.iter() {
self.dealloc(virt_addr.clone());
}
}
}
#[derive(Debug, Clone)]
pub struct Shared<T: FrameAllocator> {
allocator: T,
// used as an indirection layer to hack rust "mut" protection
start_virt_addr: Arc<Mutex<Option<usize>>>,
guard: Arc<Mutex<SharedGuard<T>>>,
}
impl<T: FrameAllocator> MemoryHandler for Shared<T> {
fn box_clone(&self) -> Box<dyn MemoryHandler> {
Box::new(self.clone())
}
fn map(&self, pt: &mut dyn PageTable, addr: VirtAddr, attr: &MemoryAttr) {
//assert!(self.guard.is_some(), "remapping memory area")
// you have to make sure that this function is called in a sequential order
// I assume that the first call of this function pass the startVirtualAddr of the MemoryArea
// TODO: Remove this potential bug
// Remember that pages can be randomly delayed allocated by all sharing threads
// Take care when to use "addrOffset" instead of "addr"
// Hack
if self.start_virt_addr.lock().is_none() {
let mut init_start_virt_addr = self.start_virt_addr.lock();
*init_start_virt_addr = Some(addr);
}
let addr_offset = addr - self.start_virt_addr.lock().unwrap();
let phys_addr_opt = self.guard.lock().get(addr_offset);
if phys_addr_opt.is_none() {
// not mapped yet
let entry = pt.map(addr, 0);
entry.set_present(false);
attr.apply(entry);
} else {
// physical memory already allocated by other process
let phys_addr = phys_addr_opt.unwrap().clone();
let entry = pt.map(addr, phys_addr);
attr.apply(entry)
}
}
fn unmap(&self, pt: &mut dyn PageTable, addr: VirtAddr) {
// free physical memory done when guard destroyed
pt.unmap(addr);
}
fn clone_map(
&self,
pt: &mut dyn PageTable,
_src_pt: &mut dyn PageTable,
addr: VirtAddr,
attr: &MemoryAttr,
) {
// actual map done when handling page fault, since guard are copied.
let entry = pt.map(addr, 0);
entry.set_present(false);
attr.apply(entry);
}
fn handle_page_fault(&self, pt: &mut dyn PageTable, addr: VirtAddr) -> bool {
let entry = pt.get_entry(addr).expect("failed to get entry");
let addr_offset = addr - self.start_virt_addr.lock().unwrap();
let phys_addr_opt = self.guard.lock().get(addr_offset);
if entry.present() {
// not a delay case
return false;
} else if phys_addr_opt.is_none() {
// physical memory not alloced.
let frame = self.guard.lock().alloc(addr_offset).unwrap();
entry.set_target(frame);
entry.set_present(true);
entry.update();
// init with zero for delay mmap mode
let data = pt.get_page_slice_mut(addr);
let len = data.len();
for x in data {
*x = 0;
}
pt.flush_cache_copy_user(addr, addr + len, false);
} else {
// physical memory alloced. update page table
let frame = phys_addr_opt.unwrap().clone();
entry.set_target(frame);
entry.set_present(true);
entry.update();
}
true
}
}
impl<T: FrameAllocator> Shared<T> {
pub fn new(allocator: T) -> Self {
Shared {
allocator: allocator.clone(),
start_virt_addr: Arc::new(Mutex::new(None)),
guard: Arc::new(Mutex::new(SharedGuard::new(allocator))),
}
}
pub fn new_with_guard(allocator: T, guard: Arc<Mutex<SharedGuard<T>>>) -> Self {
Shared {
allocator: allocator.clone(),
start_virt_addr: Arc::new(Mutex::new(None)),
guard: guard.clone(),
}
}
}

View File

@ -1,421 +0,0 @@
//! Memory management structures
use alloc::{boxed::Box, vec::Vec};
use core::fmt::{Debug, Error, Formatter};
use core::mem::size_of;
use crate::paging::*;
use super::*;
use self::handler::MemoryHandler;
pub mod handler;
/// A continuous memory space when the same attribute
#[derive(Debug, Clone)]
pub struct MemoryArea {
start_addr: VirtAddr,
end_addr: VirtAddr,
attr: MemoryAttr,
handler: Box<dyn MemoryHandler>,
name: &'static str,
}
impl MemoryArea {
/// Test whether a virtual address is in the memory area
pub fn contains(&self, addr: VirtAddr) -> bool {
addr >= self.start_addr && addr < self.end_addr
}
/// Check the array is within the readable memory.
/// Return the size of space covered in the area.
fn check_read_array<S>(&self, ptr: *const S, count: usize) -> usize {
// page align
let min_bound = (ptr as usize).max(Page::of_addr(self.start_addr).start_address());
let max_bound = unsafe { ptr.add(count) as usize }
.min(Page::of_addr(self.end_addr + PAGE_SIZE - 1).start_address());
if max_bound >= min_bound {
max_bound - min_bound
} else {
0
}
}
/// Check the array is within the writable memory.
/// Return the size of space covered in the area.
fn check_write_array<S>(&self, ptr: *mut S, count: usize) -> usize {
if self.attr.readonly {
0
} else {
self.check_read_array(ptr, count)
}
}
/// Test whether this area is (page) overlap with area [`start_addr`, `end_addr`)
pub fn is_overlap_with(&self, start_addr: VirtAddr, end_addr: VirtAddr) -> bool {
let p0 = Page::of_addr(self.start_addr);
let p1 = Page::of_addr(self.end_addr - 1) + 1;
let p2 = Page::of_addr(start_addr);
let p3 = Page::of_addr(end_addr - 1) + 1;
!(p1 <= p2 || p0 >= p3)
}
/// Map all pages in the area to page table `pt`
fn map(&self, pt: &mut dyn PageTable) {
for page in Page::range_of(self.start_addr, self.end_addr) {
self.handler.map(pt, page.start_address(), &self.attr);
}
}
/// Unmap all pages in the area from page table `pt`
fn unmap(&self, pt: &mut dyn PageTable) {
for page in Page::range_of(self.start_addr, self.end_addr) {
self.handler.unmap(pt, page.start_address());
}
}
}
/// The attributes of the memory
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
pub struct MemoryAttr {
user: bool,
readonly: bool,
execute: bool,
mmio: u8,
}
impl MemoryAttr {
pub fn user(mut self) -> Self {
self.user = true;
self
}
pub fn readonly(mut self) -> Self {
self.readonly = true;
self
}
pub fn writable(mut self) -> Self {
self.readonly = false;
self
}
pub fn execute(mut self) -> Self {
self.execute = true;
self
}
pub fn mmio(mut self, value: u8) -> Self {
self.mmio = value;
self
}
/// Apply the attributes to page table entry, then update it.
/// NOTE: You may need to set present manually.
pub fn apply(&self, entry: &mut dyn Entry) {
entry.set_user(self.user);
entry.set_writable(!self.readonly);
entry.set_execute(self.execute);
entry.set_mmio(self.mmio);
entry.update();
}
}
/// A set of memory space with multiple memory areas with associated page table
/// NOTE: Don't remove align(64), or you will fail to run MIPS.
/// Temporary solution for rv64
#[cfg_attr(not(target_arch = "riscv64"), repr(align(64)))]
pub struct MemorySet<T: PageTableExt> {
areas: Vec<MemoryArea>,
page_table: T,
}
impl<T: PageTableExt> MemorySet<T> {
/// Create a new `MemorySet`
pub fn new() -> Self {
MemorySet {
areas: Vec::new(),
page_table: T::new(),
}
}
/// Create a new `MemorySet` for kernel remap
pub fn new_bare() -> Self {
MemorySet {
areas: Vec::new(),
page_table: T::new_bare(),
}
}
/// Check the pointer is within the readable memory
pub unsafe fn check_read_ptr<S>(&self, ptr: *const S) -> VMResult<&'static S> {
self.check_read_array(ptr, 1).map(|s| &s[0])
}
/// Check the pointer is within the writable memory
pub unsafe fn check_write_ptr<S>(&self, ptr: *mut S) -> VMResult<&'static mut S> {
self.check_write_array(ptr, 1).map(|s| &mut s[0])
}
/// Check the array is within the readable memory
pub unsafe fn check_read_array<S>(
&self,
ptr: *const S,
count: usize,
) -> VMResult<&'static [S]> {
let mut valid_size = 0;
for area in self.areas.iter() {
valid_size += area.check_read_array(ptr, count);
if valid_size == size_of::<S>() * count {
return Ok(core::slice::from_raw_parts(ptr, count));
}
}
Err(VMError::InvalidPtr)
}
/// Check the array is within the writable memory
pub unsafe fn check_write_array<S>(
&self,
ptr: *mut S,
count: usize,
) -> VMResult<&'static mut [S]> {
let mut valid_size = 0;
for area in self.areas.iter() {
valid_size += area.check_write_array(ptr, count);
if valid_size == size_of::<S>() * count {
return Ok(core::slice::from_raw_parts_mut(ptr, count));
}
}
Err(VMError::InvalidPtr)
}
/// Find a free area with hint address `addr_hint` and length `len`.
/// Return the start address of found free area.
/// Used for mmap.
pub fn find_free_area(&self, addr_hint: usize, len: usize) -> VirtAddr {
// brute force:
// try each area's end address as the start
core::iter::once(addr_hint)
.chain(self.areas.iter().map(|area| area.end_addr))
.map(|addr| (addr + PAGE_SIZE - 1) & !(PAGE_SIZE - 1)) // round up a page
.find(|&addr| self.test_free_area(addr, addr + len))
.expect("failed to find free area ???")
}
/// Test if [`start_addr`, `end_addr`) is a free area
fn test_free_area(&self, start_addr: usize, end_addr: usize) -> bool {
self.areas
.iter()
.find(|area| area.is_overlap_with(start_addr, end_addr))
.is_none()
}
/// Add an area to this set
pub fn push(
&mut self,
mut start_addr: VirtAddr,
mut end_addr: VirtAddr,
attr: MemoryAttr,
handler: impl MemoryHandler,
name: &'static str,
) {
start_addr = start_addr & !(PAGE_SIZE - 1);
end_addr = (end_addr + PAGE_SIZE - 1) & !(PAGE_SIZE - 1);
assert!(start_addr < end_addr, "invalid memory area");
assert!(
self.test_free_area(start_addr, end_addr),
"memory area overlap"
);
let area = MemoryArea {
start_addr,
end_addr,
attr,
handler: Box::new(handler),
name,
};
area.map(&mut self.page_table);
// keep order by start address
let idx = self
.areas
.iter()
.enumerate()
.find(|(_, other)| start_addr < other.start_addr)
.map(|(i, _)| i)
.unwrap_or(self.areas.len());
self.areas.insert(idx, area);
}
/// Remove the area `[start_addr, end_addr)` from `MemorySet`
pub fn pop(&mut self, start_addr: VirtAddr, end_addr: VirtAddr) {
assert!(start_addr <= end_addr, "invalid memory area");
for i in 0..self.areas.len() {
if self.areas[i].start_addr == start_addr && self.areas[i].end_addr == end_addr {
let area = self.areas.remove(i);
area.unmap(&mut self.page_table);
return;
}
}
panic!("no memory area found");
}
/// Remove the area `[start_addr, end_addr)` from `MemorySet`
/// and split existed ones when necessary.
pub fn pop_with_split(&mut self, start_addr: VirtAddr, end_addr: VirtAddr) {
assert!(start_addr <= end_addr, "invalid memory area");
let mut i = 0;
while i < self.areas.len() {
if self.areas[i].is_overlap_with(start_addr, end_addr) {
if self.areas[i].start_addr >= start_addr && self.areas[i].end_addr <= end_addr {
// subset
let area = self.areas.remove(i);
area.unmap(&mut self.page_table);
i = i.wrapping_sub(1);
} else if self.areas[i].start_addr >= start_addr
&& self.areas[i].start_addr < end_addr
{
// prefix
let area = self.areas.remove(i);
let dead_area = MemoryArea {
start_addr: area.start_addr,
end_addr,
attr: area.attr,
handler: area.handler.box_clone(),
name: area.name,
};
dead_area.unmap(&mut self.page_table);
let new_area = MemoryArea {
start_addr: end_addr,
end_addr: area.end_addr,
attr: area.attr,
handler: area.handler,
name: area.name,
};
self.areas.insert(i, new_area);
} else if self.areas[i].end_addr <= end_addr && self.areas[i].end_addr > start_addr
{
// postfix
let area = self.areas.remove(i);
let dead_area = MemoryArea {
start_addr,
end_addr: area.end_addr,
attr: area.attr,
handler: area.handler.box_clone(),
name: area.name,
};
dead_area.unmap(&mut self.page_table);
let new_area = MemoryArea {
start_addr: area.start_addr,
end_addr: start_addr,
attr: area.attr,
handler: area.handler,
name: area.name,
};
self.areas.insert(i, new_area);
} else {
// superset
let area = self.areas.remove(i);
let dead_area = MemoryArea {
start_addr,
end_addr,
attr: area.attr,
handler: area.handler.box_clone(),
name: area.name,
};
dead_area.unmap(&mut self.page_table);
let new_area_left = MemoryArea {
start_addr: area.start_addr,
end_addr: start_addr,
attr: area.attr,
handler: area.handler.box_clone(),
name: area.name,
};
self.areas.insert(i, new_area_left);
let new_area_right = MemoryArea {
start_addr: end_addr,
end_addr: area.end_addr,
attr: area.attr,
handler: area.handler,
name: area.name,
};
self.areas.insert(i + 1, new_area_right);
i += 1;
}
}
i = i.wrapping_add(1);
}
}
/// Get iterator of areas
pub fn iter(&self) -> impl Iterator<Item = &MemoryArea> {
self.areas.iter()
}
/// Execute function `f` with the associated page table
pub unsafe fn with(&self, f: impl FnOnce()) {
self.page_table.with(f);
}
/// Activate the associated page table
pub unsafe fn activate(&self) {
self.page_table.activate();
}
/// Get the token of the associated page table
pub fn token(&self) -> usize {
self.page_table.token()
}
/// Clear and unmap all areas
pub fn clear(&mut self) {
let Self {
ref mut page_table,
ref mut areas,
..
} = self;
for area in areas.iter() {
area.unmap(page_table);
}
areas.clear();
}
/// Get physical address of the page of given virtual `addr`
pub fn translate(&mut self, addr: VirtAddr) -> Option<PhysAddr> {
self.page_table.get_entry(addr).and_then(|entry| {
if entry.user() {
Some(entry.target())
} else {
None
}
})
}
/// Get the reference of inner page table
pub fn get_page_table_mut(&mut self) -> &mut T {
&mut self.page_table
}
pub fn handle_page_fault(&mut self, addr: VirtAddr) -> bool {
let area = self.areas.iter().find(|area| area.contains(addr));
match area {
Some(area) => area.handler.handle_page_fault(&mut self.page_table, addr),
None => false,
}
}
pub fn clone(&mut self) -> Self {
let mut new_page_table = T::new();
let Self {
ref mut page_table,
ref areas,
..
} = self;
for area in areas.iter() {
for page in Page::range_of(area.start_addr, area.end_addr) {
area.handler.clone_map(
&mut new_page_table,
page_table,
page.start_address(),
&area.attr,
);
}
}
MemorySet {
areas: areas.clone(),
page_table: new_page_table,
}
}
}
impl<T: PageTableExt> Drop for MemorySet<T> {
fn drop(&mut self) {
self.clear();
}
}
impl<T: PageTableExt> Debug for MemorySet<T> {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
f.debug_list().entries(self.areas.iter()).finish()
}
}

View File

@ -1,74 +0,0 @@
use alloc::alloc::{GlobalAlloc, Layout};
use alloc::vec::Vec;
use core::marker::PhantomData;
pub trait NoMMUSupport {
type Alloc: GlobalAlloc + 'static;
fn allocator() -> &'static Self::Alloc;
}
#[derive(Clone, Debug)]
pub struct MemorySet<S: NoMMUSupport> {
areas: Vec<MemoryArea<S>>,
support: PhantomData<S>,
}
impl<S: NoMMUSupport> MemorySet<S> {
pub fn new() -> Self {
Self {
areas: Vec::new(),
support: PhantomData,
}
}
/// Allocate `size` bytes space. Return the slice.
pub fn push(&mut self, size: usize) -> &'static mut [u8] {
let area = MemoryArea::new(size);
let slice = unsafe { area.as_buf() };
self.areas.push(area);
slice
}
// empty impls
pub fn with<T>(&self, f: impl FnOnce() -> T) -> T {
f()
}
pub fn token(&self) -> usize {
0
}
pub unsafe fn activate(&self) {}
}
#[derive(Debug)]
struct MemoryArea<S: NoMMUSupport> {
ptr: usize,
layout: Layout,
support: PhantomData<S>,
}
impl<S: NoMMUSupport> MemoryArea<S> {
fn new(size: usize) -> Self {
let layout = Layout::from_size_align(size, 1).unwrap();
let ptr = unsafe { S::allocator().alloc(layout) } as usize;
MemoryArea {
ptr,
layout,
support: PhantomData,
}
}
unsafe fn as_buf(&self) -> &'static mut [u8] {
core::slice::from_raw_parts_mut(self.ptr as *mut u8, self.layout.size())
}
}
impl<S: NoMMUSupport> Clone for MemoryArea<S> {
fn clone(&self) -> Self {
let new_area = MemoryArea::new(self.layout.size());
unsafe { new_area.as_buf().copy_from_slice(self.as_buf()) }
new_area
}
}
impl<S: NoMMUSupport> Drop for MemoryArea<S> {
fn drop(&mut self) {
unsafe { S::allocator().dealloc(self.ptr as *mut u8, self.layout) }
}
}

View File

@ -1,298 +0,0 @@
//! Mock Page Table
//!
//! An mock implementation for the PageTable.
//! Used to test page table operation.
use super::*;
use alloc::boxed::Box;
const PAGE_COUNT: usize = 16;
const PAGE_SIZE: usize = 4096;
// a mock page table for test purpose
pub struct MockPageTable {
entries: [MockEntry; PAGE_COUNT],
data: [u8; PAGE_SIZE * PAGE_COUNT],
page_fault_handler: Option<PageFaultHandler>,
}
// the entry of the mock page table
#[derive(Default, Copy, Clone)]
pub struct MockEntry {
target: PhysAddr,
present: bool,
writable: bool,
accessed: bool,
dirty: bool,
writable_shared: bool,
readonly_shared: bool,
swapped: bool,
}
impl Entry for MockEntry {
fn update(&mut self) {}
fn accessed(&self) -> bool {
self.accessed
}
fn dirty(&self) -> bool {
self.dirty
}
fn writable(&self) -> bool {
self.writable
}
fn present(&self) -> bool {
self.present
}
fn clear_accessed(&mut self) {
self.accessed = false;
}
fn clear_dirty(&mut self) {
self.dirty = false;
}
fn set_writable(&mut self, value: bool) {
self.writable = value;
}
fn set_present(&mut self, value: bool) {
self.present = value;
}
fn target(&self) -> usize {
self.target
}
fn set_target(&mut self, target: usize) {
self.target = target;
}
fn writable_shared(&self) -> bool {
self.writable_shared
}
fn readonly_shared(&self) -> bool {
self.readonly_shared
}
fn set_shared(&mut self, writable: bool) {
self.writable_shared = writable;
self.readonly_shared = !writable;
}
fn clear_shared(&mut self) {
self.writable_shared = false;
self.readonly_shared = false;
}
fn swapped(&self) -> bool {
self.swapped
}
fn set_swapped(&mut self, value: bool) {
self.swapped = value;
}
fn user(&self) -> bool {
unimplemented!()
}
fn set_user(&mut self, _value: bool) {
unimplemented!()
}
fn execute(&self) -> bool {
unimplemented!()
}
fn set_execute(&mut self, _value: bool) {
unimplemented!()
}
fn mmio(&self) -> u8 {
unimplemented!()
}
fn set_mmio(&mut self, _value: u8) {
unimplemented!()
}
}
type PageFaultHandler = Box<dyn FnMut(&mut MockPageTable, VirtAddr)>;
impl PageTable for MockPageTable {
// type Entry = MockEntry;
fn map(&mut self, addr: VirtAddr, target: PhysAddr) -> &mut dyn Entry {
let entry = &mut self.entries[addr / PAGE_SIZE];
assert!(!entry.present);
entry.present = true;
entry.writable = true;
entry.target = target & !(PAGE_SIZE - 1);
entry
}
fn unmap(&mut self, addr: VirtAddr) {
let entry = &mut self.entries[addr / PAGE_SIZE];
assert!(entry.present);
entry.present = false;
}
fn get_entry(&mut self, addr: VirtAddr) -> Option<&mut dyn Entry> {
Some(&mut self.entries[addr / PAGE_SIZE])
}
fn get_page_slice_mut<'a, 'b>(&'a mut self, addr: VirtAddr) -> &'b mut [u8] {
self._read(addr);
let pa = self.translate(addr) & !(PAGE_SIZE - 1);
let data = unsafe { &mut *(&mut self.data as *mut [u8; PAGE_SIZE * PAGE_COUNT]) };
&mut data[pa..pa + PAGE_SIZE]
}
fn read(&mut self, addr: usize) -> u8 {
self._read(addr);
self.data[self.translate(addr)]
}
fn write(&mut self, addr: usize, data: u8) {
self._write(addr);
self.data[self.translate(addr)] = data;
}
}
impl MockPageTable {
/*
** @brief create a new MockPageTable
** @retval MockPageTable the mock page table created
*/
pub fn new() -> Self {
use core::mem::MaybeUninit;
MockPageTable {
entries: [MockEntry::default(); PAGE_COUNT],
data: unsafe { MaybeUninit::zeroed().assume_init() },
page_fault_handler: None,
}
}
/*
** @brief set the page fault handler
** used for mock the page fault feature
** @param page_fault_handler: PageFaultHandler
** the page fault handler
** @retval none
*/
pub fn set_handler(&mut self, page_fault_handler: PageFaultHandler) {
self.page_fault_handler = Some(page_fault_handler);
}
/*
** @brief trigger page fault
** used for mock the page fault feature
** @param addr: VirtAddr the virtual address used to trigger the page fault
** @retval none
*/
fn trigger_page_fault(&mut self, addr: VirtAddr) {
// In order to call the handler with &mut self as an argument
// We have to first take the handler out of self, finally put it back
let mut handler = self.page_fault_handler.take().unwrap();
handler(self, addr);
self.page_fault_handler = Some(handler);
}
/*
** @brief translate virtual address to physics address
** used for mock address translation feature
** @param addr: VirtAddr the virtual address to translation
** @retval PhysAddr the translation result
*/
fn translate(&self, addr: VirtAddr) -> PhysAddr {
let entry = &self.entries[addr / PAGE_SIZE];
assert!(entry.present);
let pa = (entry.target & !(PAGE_SIZE - 1)) | (addr & (PAGE_SIZE - 1));
assert!(pa < self.data.len(), "Physical memory access out of range");
pa
}
/*
** @brief attempt to read the virtual address
** trigger page fault when failed
** @param addr: VirtAddr the virual address of data to read
** @retval none
*/
fn _read(&mut self, addr: VirtAddr) {
while !self.entries[addr / PAGE_SIZE].present {
self.trigger_page_fault(addr);
}
self.entries[addr / PAGE_SIZE].accessed = true;
}
/*
** @brief attempt to write the virtual address
** trigger page fault when failed
** @param addr: VirtAddr the virual address of data to write
** @retval none
*/
fn _write(&mut self, addr: VirtAddr) {
while !(self.entries[addr / PAGE_SIZE].present && self.entries[addr / PAGE_SIZE].writable) {
self.trigger_page_fault(addr);
}
self.entries[addr / PAGE_SIZE].accessed = true;
self.entries[addr / PAGE_SIZE].dirty = true;
}
}
#[cfg(test)]
mod test {
use super::*;
use alloc::sync::Arc;
use core::cell::RefCell;
#[test]
fn read_write() {
let mut pt = MockPageTable::new();
pt.map(0x0, 0x0);
pt.map(0x1000, 0x1000);
pt.map(0x2000, 0x1000);
pt.write(0x0, 1);
pt.write(0x1, 2);
pt.write(0x1000, 3);
assert_eq!(pt.read(0x0), 1);
assert_eq!(pt.read(0x1), 2);
assert_eq!(pt.read(0x1000), 3);
assert_eq!(pt.read(0x2000), 3);
}
#[test]
fn entry() {
let mut pt = MockPageTable::new();
pt.map(0x0, 0x1000);
let entry = pt.get_entry(0).unwrap();
assert!(entry.present());
assert!(entry.writable());
assert!(!entry.accessed());
assert!(!entry.dirty());
assert_eq!(entry.target(), 0x1000);
pt.read(0x0);
let entry = pt.get_entry(0).unwrap();
assert!(entry.accessed());
assert!(!entry.dirty());
entry.clear_accessed();
assert!(!entry.accessed());
pt.write(0x1, 1);
let entry = pt.get_entry(0).unwrap();
assert!(entry.accessed());
assert!(entry.dirty());
entry.clear_dirty();
assert!(!entry.dirty());
entry.set_writable(false);
assert!(!entry.writable());
entry.set_present(false);
assert!(!entry.present());
}
#[test]
fn page_fault() {
let page_fault_count = Arc::new(RefCell::new(0usize));
let mut pt = MockPageTable::new();
pt.set_handler(Box::new({
let page_fault_count1 = page_fault_count.clone();
move |pt: &mut MockPageTable, addr: VirtAddr| {
*page_fault_count1.borrow_mut() += 1;
pt.map(addr, addr);
}
}));
pt.map(0, 0);
pt.read(0);
assert_eq!(*page_fault_count.borrow(), 0);
pt.write(0x1000, 0xff);
assert_eq!(*page_fault_count.borrow(), 1);
pt.unmap(0);
pt.read(0);
assert_eq!(*page_fault_count.borrow(), 2);
}
}

View File

@ -1,139 +0,0 @@
//! Generic page table interface
//!
//! Implemented for every architecture, used by OS.
#[cfg(test)]
pub use self::mock_page_table::MockPageTable;
use super::*;
#[cfg(test)]
mod mock_page_table;
pub trait PageTable {
// type Entry: Entry;
/// Map a page of virual address `addr` to the frame of physics address `target`
/// Return the page table entry of the mapped virual address
fn map(&mut self, addr: VirtAddr, target: PhysAddr) -> &mut dyn Entry;
/// Unmap a page of virual address `addr`
fn unmap(&mut self, addr: VirtAddr);
/// Get the page table entry of a page of virual address `addr`
/// If its page do not exist, return `None`
fn get_entry(&mut self, addr: VirtAddr) -> Option<&mut dyn Entry>;
/// Get a mutable reference of the content of a page of virtual address `addr`
fn get_page_slice_mut<'a>(&mut self, addr: VirtAddr) -> &'a mut [u8];
/// When copied user data (in page fault handler)maybe need to flush I/D cache.
fn flush_cache_copy_user(&mut self, start: VirtAddr, end: VirtAddr, execute: bool);
/// Read data from virtual address `addr`
/// Used for testing with mock
fn read(&mut self, _addr: VirtAddr) -> u8 {
unimplemented!()
}
/// Write data to virtual address `addr`
/// Used for testing with mock
fn write(&mut self, _addr: VirtAddr, _data: u8) {
unimplemented!()
}
}
/// Page Table Entry
pub trait Entry {
/// Make all changes take effect.
///
/// IMPORTANT!
/// This must be called after any change to ensure it become effective.
/// Usually it will cause a TLB/MMU flush.
fn update(&mut self);
/// A bit set by hardware when the page is accessed
fn accessed(&self) -> bool;
/// A bit set by hardware when the page is written
fn dirty(&self) -> bool;
/// Will PageFault when try to write page where writable=0
fn writable(&self) -> bool;
/// Will PageFault when try to access page where present=0
fn present(&self) -> bool;
fn clear_accessed(&mut self);
fn clear_dirty(&mut self);
fn set_writable(&mut self, value: bool);
fn set_present(&mut self, value: bool);
/// The target physics address in the entry
/// Can be used for other purpose if present=0
fn target(&self) -> PhysAddr;
fn set_target(&mut self, target: PhysAddr);
// For Copy-on-write
fn writable_shared(&self) -> bool;
fn readonly_shared(&self) -> bool;
fn set_shared(&mut self, writable: bool);
fn clear_shared(&mut self);
// For Swap
fn swapped(&self) -> bool;
fn set_swapped(&mut self, value: bool);
fn user(&self) -> bool;
fn set_user(&mut self, value: bool);
fn execute(&self) -> bool;
fn set_execute(&mut self, value: bool);
fn mmio(&self) -> u8;
fn set_mmio(&mut self, value: u8);
}
/// Extra methods of `PageTable` for non-trait-object usage
pub trait PageTableExt: PageTable + Sized {
/// Create a new page table with kernel memory mapped
fn new() -> Self {
let mut pt = Self::new_bare();
pt.map_kernel();
pt
}
/// Create a new page table without kernel memory mapped
fn new_bare() -> Self;
/// Map kernel segments
fn map_kernel(&mut self);
/// CR3 on x86, SATP on RISCV, TTBR on AArch64
fn token(&self) -> usize;
unsafe fn set_token(token: usize);
fn active_token() -> usize;
fn flush_tlb();
/// Activate this page table
unsafe fn activate(&self) {
let old_token = Self::active_token();
let new_token = self.token();
debug!("switch table {:x?} -> {:x?}", old_token, new_token);
if old_token != new_token {
Self::set_token(new_token);
Self::flush_tlb();
}
}
/// Execute function `f` with this page table activated
unsafe fn with<T>(&self, f: impl FnOnce() -> T) -> T {
let old_token = Self::active_token();
let new_token = self.token();
debug!("switch table {:x?} -> {:x?}", old_token, new_token);
if old_token != new_token {
Self::set_token(new_token);
Self::flush_tlb();
}
let ret = f();
debug!("switch table {:x?} -> {:x?}", new_token, old_token);
if old_token != new_token {
Self::set_token(old_token);
Self::flush_tlb();
}
ret
}
}

View File

@ -1,100 +0,0 @@
//! Implememnt the swap manager with the enhanced clock page replacement algorithm
use alloc::collections::VecDeque;
use super::*;
use crate::paging::Entry;
#[derive(Default)]
pub struct EnhancedClockSwapManager {
clock_ptr: usize,
deque: VecDeque<VirtAddr>,
}
// FIXME: It's unusable. But can pass a simple test.
impl SwapManager for EnhancedClockSwapManager {
fn tick(&mut self) {
}
fn push(&mut self, addr: usize) {
let pos = if self.clock_ptr == 0 {self.deque.len()} else {self.clock_ptr};
self.deque.insert(pos, addr);
}
fn remove(&mut self, addr: usize) {
let id = self.deque.iter()
.position(|&x| x == addr)
.expect("address not found");
if id < self.clock_ptr {
self.clock_ptr -= 1;
}
self.deque.remove(id);
}
fn pop<T, S>(&mut self, page_table: &mut T, _swapper: &mut S) -> Option<VirtAddr>
where T: PageTable, S: Swapper
{
loop {
let addr = self.deque[self.clock_ptr];
// FIXME: Once define `slice`, all modifies of `entry` below will fail.
// Then the loop will never stop.
// The reason may be `get_page_slice_mut()` contains unsafe operation,
// which lead the compiler to do a wrong optimization.
// let slice = page_table.get_page_slice_mut(addr);
let entry = page_table.get_entry(addr).unwrap();
// println!("{:#x} , {}, {}", addr, entry.accessed(), entry.dirty());
match (entry.accessed(), entry.dirty()) {
(true, _) => {
entry.clear_accessed();
},
(false, true) => {
// FIXME:
// if let Ok(token) = swapper.swap_out(slice) {
// entry.clear_dirty();
// }
},
_ => {
return self.remove_current();
}
}
self.move_next();
}
}
}
impl EnhancedClockSwapManager {
fn remove_current(&mut self) -> Option<VirtAddr> {
let addr = self.deque.remove(self.clock_ptr);
if self.clock_ptr == self.deque.len() {
self.clock_ptr = 0;
}
return addr;
}
fn move_next(&mut self) {
self.clock_ptr += 1;
if self.clock_ptr == self.deque.len() {
self.clock_ptr = 0;
}
}
}
#[cfg(test)]
mod test {
use super::*;
use swap::test::*;
#[test]
fn test() {
use self::MemOp::{R, W};
let ops = [
R(0x1000), R(0x2000), R(0x3000), R(0x4000),
R(0x3000), W(0x1000), R(0x4000), W(0x2000), R(0x5000),
R(0x2000), W(0x1000), R(0x2000), R(0x3000), R(0x4000)];
let pgfault_count = [
1, 2, 3, 4,
4, 4, 4, 4, 5,
5, 5, 5, 6, 7];
test_manager(EnhancedClockSwapManager::default(), &ops, &pgfault_count);
}
}

View File

@ -1,65 +0,0 @@
//! Implememnt the swap manager with the FIFO page replacement algorithm
use super::*;
use alloc::collections::VecDeque;
#[derive(Default)]
pub struct FifoSwapManager {
deque: VecDeque<Frame>,
}
impl SwapManager for FifoSwapManager {
fn tick(&mut self) {}
fn push(&mut self, frame: Frame) {
info!(
"SwapManager push token: {:x?} vaddr: {:x?}",
frame.get_token(),
frame.get_virtaddr()
);
self.deque.push_back(frame);
}
fn remove(&mut self, token: usize, addr: VirtAddr) {
info!("SwapManager remove token: {:x?} vaddr: {:x?}", token, addr);
let id = self
.deque
.iter()
.position(|ref x| x.get_virtaddr() == addr && x.get_token() == token)
.expect("address not found");
self.deque.remove(id);
//info!("SwapManager remove token finished: {:x?} vaddr: {:x?}", token, addr);
}
fn pop<T, S>(&mut self, _: &mut T, _: &mut S) -> Option<Frame>
where
T: PageTable,
S: Swapper,
{
self.deque.pop_front()
}
}
/*
#[cfg(test)]
mod test {
use super::*;
use swap::test::*;
#[test]
fn test() {
use self::MemOp::{R, W};
let ops = [
R(0x1000), R(0x2000), R(0x3000), R(0x4000),
W(0x3000), W(0x1000), W(0x4000), W(0x2000), W(0x5000),
W(0x2000), W(0x1000), W(0x2000), W(0x3000), W(0x4000),
W(0x5000), R(0x1000), W(0x1000)];
let pgfault_count = [
1, 2, 3, 4,
4, 4, 4, 4, 5,
5, 6, 7, 8, 9,
10, 11, 11];
test_manager(FifoSwapManager::default(), &ops, &pgfault_count);
}
}
*/

View File

@ -1,92 +0,0 @@
//! Mock Swapper
//!
//! An mock implement of the swapper
//! Used to test page table operation
use super::Swapper;
use alloc::collections::BTreeMap;
use core::mem::MaybeUninit;
const PAGE_SIZE: usize = 4096;
#[derive(Default)]
pub struct MockSwapper {
map: BTreeMap<usize, [u8; PAGE_SIZE]>,
}
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 { MaybeUninit::zeroed().assume_init() };
slice.copy_from_slice(data);
self.map.insert(id, slice);
Ok(id)
}
fn swap_update(&mut self, token: usize, data: &[u8]) -> Result<(), ()> {
if !self.map.contains_key(&token) {
return Err(());
}
let mut slice: [u8; PAGE_SIZE] = unsafe { MaybeUninit::zeroed().assume_init() };
slice.copy_from_slice(data);
self.map.insert(token, slice);
Ok(())
}
fn swap_in(&mut self, token: usize, data: &mut [u8]) -> Result<(), ()> {
match self.map.remove(&token) {
Some(d) => data.copy_from_slice(d.as_ref()),
None => return Err(()),
}
Ok(())
}
}
impl MockSwapper {
/*
** @brief allocate an unused id for location on the mock device
** @retval usize the allocated location id
*/
fn alloc_id(&self) -> usize {
(0..100usize).find(|i| !self.map.contains_key(i)).unwrap()
}
}
#[cfg(test)]
mod test {
use super::*;
fn assert_data_eq(data1: &[u8; 4096], data2: &[u8; 4096]) {
for (&a, &b) in data2.iter().zip(data1.iter()) {
assert_eq!(a, b);
}
}
#[test]
fn swap_out_in() {
let mut swapper = MockSwapper::default();
let mut data: [u8; 4096] = unsafe { MaybeUninit::zeroed().assume_init() };
let data1: [u8; 4096] = unsafe { MaybeUninit::zeroed().assume_init() };
let token = swapper.swap_out(&data1).unwrap();
swapper.swap_in(token, &mut data).unwrap();
assert_data_eq(&data, &data1);
}
#[test]
fn swap_update() {
let mut swapper = MockSwapper::default();
let mut data: [u8; 4096] = unsafe { MaybeUninit::zeroed().assume_init() };
let data1: [u8; 4096] = unsafe { MaybeUninit::zeroed().assume_init() };
let data2: [u8; 4096] = unsafe { MaybeUninit::zeroed().assume_init() };
let token = swapper.swap_out(&data1).unwrap();
swapper.swap_update(token, &data2).unwrap();
swapper.swap_in(token, &mut data).unwrap();
assert_data_eq(&data, &data2);
}
#[test]
fn invalid_token() {
let mut swapper = MockSwapper::default();
let mut data: [u8; 4096] = unsafe { MaybeUninit::zeroed().assume_init() };
assert_eq!(swapper.swap_in(0, &mut data), Err(()));
}
}

View File

@ -1,465 +0,0 @@
//! Swap extension for page table
//! and generic interface for swap manager and swapper
//!
//! To use the SwapExt, make a wrapper over the original apge table using swap manager and swapper
//! Like: SwapExt::new(origin_page_table,swap_manager,swapper)
//! Invoke page_fault_handler() on the SwapExt to run the swap process
//! If the method above returns true, a page is swapped in, else do your own things.
use super::addr::Frame;
use super::paging::*;
use super::*;
use core::ops::{Deref, DerefMut};
//pub use self::fifo::FifoSwapManager;
//pub use self::enhanced_clock::EnhancedClockSwapManager;
pub mod fifo;
//mod enhanced_clock;
pub mod mock_swapper;
//#[cfg(test)]
//mod mock_swapper;
/// Manage all swappable pages, decide which to swap out
pub trait SwapManager {
//type Inactive: InactivePageTable;
/*
** @brief update intarnal state pre tick
** Called when tick interrupt occured
** @retval none
*/
fn tick(&mut self);
/*
** @brief update intarnal state when page is pushed into memory
** Called when map a swappable page into the memory
** @param frame: Frame the Frame recording the swappable frame info
** @retval none
*/
fn push(&mut self, frame: Frame);
/*
** @brief update intarnal state when page is removed from memory
** Called to delete the addr entry from the swap manager
** @param token: usize the inactive page table token for the virtual address
** @param addr: VirtAddr the virual address of the page removed from memory
** @retval none
*/
fn remove(&mut self, token: usize, addr: VirtAddr);
/*
** @brief select swap out victim when there is need to swap out a page
** (The params is only used by `EnhancedClockSwapManager` currently)
** @param page_table: &mut T the current page table
** @param swapper: &mut S the swapper used
** @retval Option<Frame> the Frame of the victim page, if present
*/
fn pop<T, S>(&mut self, page_table: &mut T, swapper: &mut S) -> Option<Frame>
where
T: PageTable,
S: Swapper;
}
/// Implement swap in & out execution
pub trait Swapper {
/*
** @brief Allocate space on device and write data to it
** @param data: &[u8] the data to write to the device
** @retval Result<usize, ()> the execute result, and a token indicating the location on the device if success
*/
fn swap_out(&mut self, data: &[u8]) -> Result<usize, ()>;
/*
** @brief Update data on device.
** @param token: usize the token indicating the location on the device
** @param data: &[u8] the data to overwrite on the device
** @retval Result<(), ()> the execute result
*/
fn swap_update(&mut self, token: usize, data: &[u8]) -> Result<(), ()>;
/*
** @brief Recover data from device and deallocate the space.
** @param token: usize the token indicating the location on the device
** @param data: &mut [u8] the reference to data in the space in memory
** @retval Result<(), ()> the execute result
*/
fn swap_in(&mut self, token: usize, data: &mut [u8]) -> Result<(), ()>;
}
/// Wrapper for page table, supporting swap functions
pub struct SwapExt<T: PageTable, M: SwapManager, S: Swapper> {
page_table: T,
swap_manager: M,
swapper: S,
}
impl<T: PageTable, M: SwapManager, S: Swapper> SwapExt<T, M, S> {
/*
** @brief create a swap extension
** @param page_table: T the inner page table
** @param swap_manager: M the SwapManager used
** @param swapper: S the Swapper used
** @retval SwapExt the swap extension created
*/
pub fn new(page_table: T, swap_manager: M, swapper: S) -> Self {
SwapExt {
page_table,
swap_manager,
swapper,
}
}
/*
** @brief set a page swappable
** @param pt: *mut T2 the raw pointer for the target page's inactive page table
** @param addr: VirtAddr the target page's virtual address
*/
pub unsafe fn set_swappable<T2: InactivePageTable>(&mut self, pt: *mut T2, addr: VirtAddr) {
let Self {
ref mut page_table,
ref mut swap_manager,
..
} = self;
let targetpt = &mut *(pt);
let pttoken = {
info!(
"SET_SWAPPABLE: the target page table token is {:x?}, addr is {:x?}",
targetpt.token(),
addr
);
targetpt.token()
};
targetpt.with(|| {
let entry = page_table
.get_entry(addr)
.expect("failed to get page entry when set swappable");
if entry.present() {
let frame = Frame::new(pt as usize, addr, pttoken);
swap_manager.push(frame);
}
});
/*
let token = unsafe{
(*pt).token()
};
let frame = Frame::new(pt as usize, addr, token);
self.swap_manager.push(frame);
*/
}
/*
** @brief remove a page (given virtual address) from swappable pages, if the page is swapped, swap in at first
** @param pt: *mut T2 the raw pointer for the target page's inactive page table
** @param addr: VirtAddr the target page's virtual address
** @param alloc_frame: the function to alloc a free physical frame for once
*/
pub unsafe fn remove_from_swappable<T2: InactivePageTable>(
&mut self,
pt: *mut T2,
addr: VirtAddr,
alloc_frame: impl FnOnce() -> PhysAddr,
) {
//info!("come into remove_from swappable");
let Self {
ref mut page_table,
ref mut swap_manager,
ref mut swapper,
} = self;
let targetpt = &mut *(pt);
let pttoken = {
info!(
"SET_UNSWAPPABLE: the target page table token is {:x?}, addr is {:x?}",
targetpt.token(),
addr
);
targetpt.token()
};
//info!("try to change pagetable");
targetpt.with(|| {
let token = {
let entry = page_table.get_entry(addr).unwrap();
if !entry.swapped() {
if entry.present() {
// if the addr isn't indicating a swapped page, panic occured here
swap_manager.remove(pttoken, addr);
}
return;
}
let token = entry.target() / PAGE_SIZE;
let frame = alloc_frame();
entry.set_target(frame);
entry.set_swapped(false);
entry.set_present(true);
entry.update();
token
};
info!("swap in vaddr {:x?} at remove from swappable.", addr);
let data = page_table.get_page_slice_mut(addr);
swapper.swap_in(token, data).unwrap();
});
trace!("come out of femove_from swappable");
}
/*
** @brief map the virtual address to a target physics address as swappable
** @param addr: VirtAddr the virual address to map
** @param target: VirtAddr the target physics address
** @retval none
*/
/*
pub fn map_to_swappable(&mut self, addr: VirtAddr, target: PhysAddr) -> &mut T::Entry {
self.swap_manager.push(addr);
self.map(addr, target)
}*/
/*
** @brief Swap out any one of the swapped pages
** @retval Result<PhysAddr, SwapError>
** the physics address of released frame if success,
** the error if failed
*/
pub fn swap_out_any<T2: InactivePageTable>(&mut self) -> Result<PhysAddr, SwapError> {
info!("COME in to swap_out_any");
let victim: Option<Frame> = {
let Self {
ref mut page_table,
ref mut swap_manager,
ref mut swapper,
} = self;
swap_manager.pop(page_table, swapper)
};
info!("swap out page {}", victim.unwrap().get_virtaddr());
match victim {
None => Err(SwapError::NoSwapped),
Some(frame) => self.swap_out::<T2>(&frame),
}
}
/*
** @brief Swap out page
** @param frame: Frame the Frame of page recording the page info
** @retval Result<PhysAddr, SwapError>
** the physics address of the original map target frame if success,
** the error if failed
*/
fn swap_out<T2: InactivePageTable>(&mut self, frame: &Frame) -> Result<PhysAddr, SwapError> {
let Self {
ref mut page_table,
ref mut swapper,
..
} = self;
let ret = unsafe {
let pt = &mut *(frame.get_page_table() as *mut T2);
pt.with(|| {
//use core::slice;
//let data = unsafe { slice::from_raw_parts_mut((frame.virtaddr & !(PAGE_SIZE - 1)) as *mut u8, PAGE_SIZE) };
let data = page_table.get_page_slice_mut(frame.get_virtaddr());
let entry = page_table
.get_entry(frame.get_virtaddr())
.ok_or(SwapError::NotMapped)?;
if entry.swapped() {
return Err(SwapError::AlreadySwapped);
}
//assert!(!entry.swapped(), "Page already swapped!");
let token = swapper.swap_out(data).map_err(|_| SwapError::IOError)?;
//let token = swapper.swap_out(data).unwrap();
let target = entry.target();
entry.set_target(token * PAGE_SIZE);
entry.set_swapped(true);
entry.set_present(false);
entry.update();
Ok(target)
})
};
ret
}
/*
** @brief map the virtual address to a target physics address and then swap in page data, noted that the page should be in the current page table
** @param pt: *mut T2 the raw pointer for the swapping page's inactive page table
** @param addr: VirtAddr the virual address of beginning of page
** @param target: PhysAddr the target physics address
** @retval Result<()), SwapError>
** the execute result, and the error if failed
*/
fn swap_in<T2: InactivePageTable>(
&mut self,
pt: *mut T2,
addr: VirtAddr,
target: PhysAddr,
) -> Result<(), SwapError> {
info!("come in to swap in");
let entry = self
.page_table
.get_entry(addr)
.ok_or(SwapError::NotMapped)?;
if !entry.swapped() {
return Err(SwapError::NotSwapped);
}
let token = entry.target() / PAGE_SIZE;
entry.set_target(target);
entry.set_swapped(false);
entry.set_present(true);
entry.update();
let data = self.page_table.get_page_slice_mut(addr);
self.swapper
.swap_in(token, data)
.map_err(|_| SwapError::IOError)?;
let pttoken = unsafe { (*pt).token() };
let frame = Frame::new(pt as usize, addr, pttoken);
;
self.swap_manager.push(frame);
Ok(())
}
/*
** @brief execute the frame delayed allocate and swap process for page fault
** This function must be called whenever PageFault happens.
** @param pt: *mut T2 the raw pointer for the target page's inactive page table (exactly the current page table)
** @param addr: VirtAddr the virual address of the page fault
** @param swapin: bool whether to set the page swappable if delayed allocate a frame for a page
** @param alloc_frame: impl FnOnce() -> PhysAddr
** the page allocation function
** that allocate a page and returns physics address
** of beginning of the page
** @retval bool whether swap in happens.
*/
pub fn page_fault_handler<T2: InactivePageTable>(
&mut self,
pt: *mut T2,
addr: VirtAddr,
swapin: bool,
alloc_frame: impl FnOnce() -> PhysAddr,
) -> bool {
// handle page delayed allocating
{
info!("try handling delayed frame allocator");
let need_alloc = {
let entry = self.page_table.get_entry(addr).expect("fail to get entry");
//info!("got entry!");
!entry.present() && !entry.swapped()
};
info!("need_alloc got");
if need_alloc {
info!("need_alloc!");
let frame = alloc_frame();
{
let entry = self.page_table.get_entry(addr).unwrap();
entry.set_target(frame);
//let new_entry = self.page_table.map(addr, frame);
entry.set_present(true);
entry.update();
}
if swapin {
unsafe {
self.set_swappable(pt, addr & 0xfffff000);
}
}
//area.get_flags().apply(new_entry); this instruction may be used when hide attr is used
info!("allocated successfully");
return true;
}
info!("not need alloc!");
}
// now we didn't attach the cow so the present will be false when swapped(), to enable the cow some changes will be needed
match self.page_table.get_entry(addr) {
// infact the get_entry(addr) should not be None here
None => return false,
Some(entry) => {
if !entry.swapped() {
return false;
}
}
}
// Allocate a frame, if failed, swap out a page
let frame = alloc_frame();
self.swap_in(pt, addr, frame).ok().unwrap();
true
}
}
pub enum SwapError {
/// attempt to swap out a page that is already swapped out
AlreadySwapped,
///
NotMapped,
/// attempt to swap in a page that is already in the memory
NotSwapped,
/// there are no page to be swapped out
NoSwapped,
/// swap failed due to IO error while interact with device
IOError,
}
impl<T: PageTable, M: SwapManager, S: Swapper> Deref for SwapExt<T, M, S> {
type Target = T;
fn deref(&self) -> &<Self as Deref>::Target {
&self.page_table
}
}
impl<T: PageTable, M: SwapManager, S: Swapper> DerefMut for SwapExt<T, M, S> {
fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
&mut self.page_table
}
}
/*
#[cfg(test)]
mod test {
use super::*;
use super::mock_swapper::MockSwapper;
use alloc::{sync::Arc, boxed::Box};
use core::cell::RefCell;
use paging::MockPageTable;
#[derive(Debug)]
pub enum MemOp {
R(usize),
W(usize),
}
struct FrameAlloc(usize);
impl FrameAlloc {
fn alloc(&mut self) -> Option<PhysAddr> {
if self.0 == 0 {
return None;
}
self.0 -= 1;
Some((self.0 + 1) * PAGE_SIZE)
}
}
unsafe fn clone<'a, 'b, T>(x: &'a mut T) -> &'b mut T {
&mut *(x as *mut T)
}
/// Test framework with different SwapManagers.
/// See `fifo::test` mod for example.
pub fn test_manager(swap_manager: impl 'static + SwapManager, ops: &[MemOp], pgfault_count: &[u8]) {
use self::MemOp::{R, W};
let page_fault_count = Arc::new(RefCell::new(0u8));
let mut pt = SwapExt::new(MockPageTable::new(), swap_manager, MockSwapper::default());
// Move to closure
let pt0 = unsafe{ clone(&mut pt) };
let page_fault_count1 = page_fault_count.clone();
let mut alloc = FrameAlloc(4);
pt.set_handler(Box::new(move |_, addr: VirtAddr| {
*page_fault_count1.borrow_mut() += 1;
if pt0.page_fault_handler(addr, || alloc.alloc()) {
return;
}
// The page is not mapped, map it to a new frame, if no more frame, swap out.
let target = alloc.alloc().or_else(|| pt0.swap_out_any().ok())
.expect("no more frame in both allocator and swap_manager");
pt0.map_to_swappable(addr, target);
}));
for (op, &count) in ops.iter().zip(pgfault_count.iter()) {
match op {
R(addr) => { pt.read(*addr); }
W(addr) => pt.write(*addr, 0),
}
assert_eq!(*(*page_fault_count).borrow(), count);
}
}
}
*/

View File

@ -30,8 +30,5 @@ rcore-console = { git = "https://github.com/rcore-os/rcore-console", default-fea
acpi = "1.1"
[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies]
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"], rev = "21e32ee1" }
rcore-memory = { path = "../crate/memory" }
rcore-fs = { git = "https://github.com/rcore-os/rcore-fs" }
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"], rev = "0074cbc" }
device_tree = { git = "https://github.com/rcore-os/device_tree-rs" }

View File

@ -8,11 +8,13 @@ use riscv::register::{
},
sie,
sepc,
stval,
stvec,
sscratch,
sstatus,
sstatus::Sstatus,
};
use trapframe::TrapFrame;
/*
use crate::timer::{
@ -30,25 +32,14 @@ use super::uart;
use crate::{putfmt, phys_to_virt};
use super::clock_set_next_event;
global_asm!(include_str!("trap.asm"));
#[repr(C)]
pub struct TrapFrame{
pub x: [usize; 32], //General registers
pub sstatus: Sstatus,
pub sepc: usize,
pub stval: usize,
pub scause: Scause,
}
pub fn init(){
unsafe{
extern "C" {
fn __alltraps();
fn trap_entry();
}
sscratch::write(0);
stvec::write(__alltraps as usize, stvec::TrapMode::Direct);
stvec::write(trap_entry as usize, stvec::TrapMode::Direct);
sstatus::set_sie();
@ -63,13 +54,14 @@ pub fn init(){
}
#[no_mangle]
pub fn rust_trap(tf: &mut TrapFrame){
pub fn trap_handler(tf: &mut TrapFrame){
let sepc = tf.sepc;
let stval = tf.stval;
let is_int = tf.scause.bits() >> 63;
let code = tf.scause.bits() & !(1 << 63);
match tf.scause.cause() {
let scause = scause::read();
let stval = stval::read();
let is_int = scause.bits() >> 63;
let code = scause.bits() & !(1 << 63);
trace!("{:?}", scause.cause());
match scause.cause() {
Trap::Exception(Exception::Breakpoint) => breakpoint(&mut tf.sepc),
Trap::Exception(Exception::IllegalInstruction) => panic!("IllegalInstruction: {:#x}->{:#x}", sepc, stval),
Trap::Exception(Exception::LoadFault) => panic!("Load access fault: {:#x}->{:#x}", sepc, stval),
@ -79,11 +71,22 @@ pub fn rust_trap(tf: &mut TrapFrame){
Trap::Exception(Exception::InstructionPageFault) => page_fault(stval, tf),
Trap::Interrupt(Interrupt::SupervisorTimer) => super_timer(),
Trap::Interrupt(Interrupt::SupervisorSoft) => super_soft(),
Trap::Interrupt(Interrupt::SupervisorExternal) => plic::handle_interrupt(),
Trap::Interrupt(Interrupt::SupervisorExternal) => external(),
_ => panic!("Undefined Trap: {:#x} {:#x}", is_int, code)
}
}
fn external() {
// assume only keyboard interrupt
let mut c = sbi::console_getchar();
if c <= 255 {
if c == '\r' as usize {
c = '\n' as usize;
}
super::serial_put(c as u8);
}
}
fn breakpoint(sepc: &mut usize){
bare_println!("A breakpoint set @0x{:x} ", sepc);
@ -93,14 +96,23 @@ fn breakpoint(sepc: &mut usize){
}
fn page_fault(stval: usize, tf: &mut TrapFrame){
panic!("EXCEPTION: Page Fault @ {:#x}->{:#x}", tf.sepc, stval);
/* debug info
use super::PageTableImpl;
use kernel_hal::PhysAddr;
use kernel_hal::PageTableTrait;
let mut page_table = PageTableImpl {
root_paddr: riscv::register::satp::read().bits() as usize
};
info!("{:#x?}", page_table.query(tf.sepc));
*/
panic!("{:#?} @ {:#x}->{:#x}", scause::read().cause(), tf.sepc, stval);
}
fn super_timer(){
clock_set_next_event();
//bare_println!("Tick");
bare_print!(".");
// bare_print!(".");
//发生外界中断时epc的指令还没有执行故无需修改epc到下一条
}

View File

@ -2,7 +2,7 @@ use super::super::*;
use kernel_hal::{PageTableTrait, PhysAddr, VirtAddr};
use riscv::addr::Page;
use riscv::paging::{PageTableFlags as PTF, *};
use riscv::register::{time, satp, sie};
use riscv::register::{time, satp, sie, stval};
//use crate::sbi;
use core::mem;
use core::fmt::{ self, Write };
@ -10,27 +10,6 @@ use alloc::{collections::VecDeque, vec::Vec};
mod sbi;
mod paging;
use paging::PageTableImpl as rCorePageTableImpl;
pub type MemorySet = rcore_memory::memory_set::MemorySet<rCorePageTableImpl>;
pub fn remap_the_kernel(_dtb: usize) {
let ms = MemorySet::new();
unsafe {
ms.activate();
}
unsafe {
SATP = ms.token();
}
mem::forget(ms);
info!("remap kernel end");
}
// First core stores its SATP here.
static mut SATP: usize = 0;
/// Page Table
#[repr(C)]
pub struct PageTableImpl {
@ -41,7 +20,7 @@ impl PageTableImpl {
/// Create a new `PageTable`.
#[allow(clippy::new_without_default)]
#[export_name = "hal_pt_new"]
pub fn new() -> Self {
pub extern "C" fn new() -> Self {
let root_frame = Frame::alloc().expect("failed to alloc frame");
let root_vaddr = phys_to_virt(root_frame.paddr);
let root = unsafe { &mut *(root_vaddr as *mut PageTable) };
@ -130,6 +109,7 @@ pub unsafe fn set_page_table(vmtoken: usize) {
#[cfg(target_arch = "riscv64")]
let mode = satp::Mode::Sv39;
satp::set(mode, 0, vmtoken >> 12);
riscv::asm::sfence_vma_all();
}
trait FlagsExt {
@ -274,6 +254,7 @@ fn get_cycle() -> u64 {
*/
}
#[export_name = "hal_timer_now"]
pub fn timer_now() -> Duration {
const FREQUENCY: u64 = 10_000_000; // ???
let time = get_cycle();
@ -281,12 +262,17 @@ pub fn timer_now() -> Duration {
Duration::from_nanos(time * 1_000_000_000 / FREQUENCY as u64)
}
fn clock_set_next_event() {
pub fn clock_set_next_event() {
//let TIMEBASE: u64 = 100000;
let TIMEBASE: u64 = 10_000_000;
sbi::set_timer(get_cycle() + TIMEBASE);
}
pub const Timer: usize = usize::MAX / 2 + 1 + 5;
pub fn is_timer_intr(trap: usize) -> bool {
trap == Timer
}
fn timer_init() {
unsafe {
sie::set_stimer();
@ -359,5 +345,19 @@ mod interrupt;
mod plic;
mod uart;
mod virtio;
pub const Syscall: usize = 8;
pub const InstructionPageFault: usize = 12;
pub const LoadPageFault: usize = 13;
pub const StorePageFault: usize = 15;
pub fn is_page_fault(trap: usize) -> bool {
trap == InstructionPageFault || trap == LoadPageFault || trap == StorePageFault
}
pub fn get_page_fault_addr() -> usize {
stval::read()
}
pub fn is_syscall(trap: usize) -> bool {
trap == Syscall
}

View File

@ -1,267 +0,0 @@
use core::mem::ManuallyDrop;
use log::*;
use rcore_memory::paging::*;
use riscv::addr::{Page, PhysAddr, VirtAddr};
use riscv::asm::{sfence_vma, sfence_vma_all};
use riscv::paging::{FrameAllocator, FrameDeallocator};
use riscv::paging::{Mapper, PageTable as RvPageTable, PageTableEntry, PageTableFlags as EF};
use riscv::register::satp;
use crate::{phys_to_virt, Frame};
use super::FrameAllocatorImpl;
#[cfg(target_arch = "riscv32")]
type TopLevelPageTable<'a> = riscv::paging::Rv32PageTable<'a>;
#[cfg(target_arch = "riscv64")]
type TopLevelPageTable<'a> = riscv::paging::Rv39PageTable<'a>;
static PHYSICAL_MEMORY_OFFSET: usize = 0xFFFF_FFFF_4000_0000;
pub struct PageTableImpl {
page_table: TopLevelPageTable<'static>,
root_frame: riscv::addr::Frame,
entry: Option<PageEntry>,
}
/// PageTableEntry: the contents of this entry.
/// Page: this entry is the pte of page `Page`.
pub struct PageEntry(&'static mut PageTableEntry, Page);
impl PageTable for PageTableImpl {
fn map(&mut self, addr: usize, target: usize) -> &mut dyn Entry {
// map the 4K `page` to the 4K `frame` with `flags`
let flags = EF::VALID | EF::READABLE | EF::WRITABLE;
let page = Page::of_addr(VirtAddr::new(addr));
let frame = riscv::addr::Frame::of_addr(PhysAddr::new(target));
// we may need frame allocator to alloc frame for new page table(first/second)
self.page_table
.map_to(page, frame, flags, &mut FrameAllocatorImpl)
.unwrap()
.flush();
self.get_entry(addr).expect("fail to get entry")
}
fn unmap(&mut self, addr: usize) {
let page = Page::of_addr(VirtAddr::new(addr));
let (_, flush) = self.page_table.unmap(page).unwrap();
flush.flush();
}
fn get_entry(&mut self, vaddr: usize) -> Option<&mut dyn Entry> {
let page = Page::of_addr(VirtAddr::new(vaddr));
if let Ok(e) = self.page_table.ref_entry(page.clone()) {
let e = unsafe { &mut *(e as *mut PageTableEntry) };
self.entry = Some(PageEntry(e, page));
Some(self.entry.as_mut().unwrap())
} else {
None
}
}
fn get_page_slice_mut<'a>(&mut self, addr: usize) -> &'a mut [u8] {
let frame = self
.page_table
.translate_page(Page::of_addr(VirtAddr::new(addr)))
.unwrap();
let vaddr = frame.start_address().as_usize() + PHYSICAL_MEMORY_OFFSET;
unsafe { core::slice::from_raw_parts_mut(vaddr as *mut u8, 0x1000) }
}
fn flush_cache_copy_user(&mut self, _start: usize, _end: usize, _execute: bool) {}
}
/// implementation for the Entry trait in /crate/memory/src/paging/mod.rs
impl Entry for PageEntry {
fn update(&mut self) {
unsafe {
sfence_vma(0, self.1.start_address().as_usize());
}
}
fn accessed(&self) -> bool {
self.0.flags().contains(EF::ACCESSED)
}
fn dirty(&self) -> bool {
self.0.flags().contains(EF::DIRTY)
}
fn writable(&self) -> bool {
self.0.flags().contains(EF::WRITABLE)
}
fn present(&self) -> bool {
self.0.flags().contains(EF::VALID | EF::READABLE)
}
fn clear_accessed(&mut self) {
self.0.flags_mut().remove(EF::ACCESSED);
}
fn clear_dirty(&mut self) {
self.0.flags_mut().remove(EF::DIRTY);
}
fn set_writable(&mut self, value: bool) {
self.0.flags_mut().set(EF::WRITABLE, value);
}
fn set_present(&mut self, value: bool) {
self.0.flags_mut().set(EF::VALID | EF::READABLE, value);
}
fn target(&self) -> usize {
self.0.addr().as_usize()
}
fn set_target(&mut self, target: usize) {
let flags = self.0.flags();
let frame = riscv::addr::Frame::of_addr(PhysAddr::new(target));
self.0.set(frame, flags);
}
fn writable_shared(&self) -> bool {
self.0.flags().contains(EF::RESERVED1)
}
fn readonly_shared(&self) -> bool {
self.0.flags().contains(EF::RESERVED2)
}
fn set_shared(&mut self, writable: bool) {
let flags = self.0.flags_mut();
flags.set(EF::RESERVED1, writable);
flags.set(EF::RESERVED2, !writable);
}
fn clear_shared(&mut self) {
self.0.flags_mut().remove(EF::RESERVED1 | EF::RESERVED2);
}
fn swapped(&self) -> bool {
self.0.flags().contains(EF::RESERVED1)
}
fn set_swapped(&mut self, value: bool) {
self.0.flags_mut().set(EF::RESERVED1, value);
}
fn user(&self) -> bool {
self.0.flags().contains(EF::USER)
}
fn set_user(&mut self, value: bool) {
self.0.flags_mut().set(EF::USER, value);
}
fn execute(&self) -> bool {
self.0.flags().contains(EF::EXECUTABLE)
}
fn set_execute(&mut self, value: bool) {
self.0.flags_mut().set(EF::EXECUTABLE, value);
}
fn mmio(&self) -> u8 {
0
}
fn set_mmio(&mut self, _value: u8) {}
}
impl PageTableImpl {
/// Unsafely get the current active page table.
/// Using ManuallyDrop to wrap the page table: this is how `core::mem::forget` is implemented now.
pub unsafe fn active() -> ManuallyDrop<Self> {
#[cfg(target_arch = "riscv32")]
let mask = 0x7fffffff;
#[cfg(target_arch = "riscv64")]
let mask = 0x0fffffff_ffffffff;
let frame = riscv::addr::Frame::of_ppn(PageTableImpl::active_token() & mask);
let table = frame.as_kernel_mut(PHYSICAL_MEMORY_OFFSET);
ManuallyDrop::new(PageTableImpl {
page_table: TopLevelPageTable::new(table, PHYSICAL_MEMORY_OFFSET),
root_frame: frame,
entry: None,
})
}
/// The method for getting the kernel page table.
/// In riscv kernel page table and user page table are the same table. However you have to do the initialization.
pub unsafe fn kernel_table() -> ManuallyDrop<Self> {
Self::active()
}
}
impl PageTableExt for PageTableImpl {
fn new_bare() -> Self {
let RFrame = Frame::alloc().expect("failed to alloc frame");
let target = RFrame.paddr;
//let target = alloc_frame().expect("failed to allocate frame");
let frame = riscv::addr::Frame::of_addr(PhysAddr::new(target));
let table = unsafe { &mut *(phys_to_virt(target) as *mut RvPageTable) };
table.zero();
debug!("new_bare(), {:#x?}, {:p}", frame, table);
PageTableImpl {
page_table: TopLevelPageTable::new(table, PHYSICAL_MEMORY_OFFSET),
root_frame: frame,
entry: None,
}
}
fn map_kernel(&mut self) {
info!("mapping kernel linear mapping");
let table = unsafe {
&mut *(phys_to_virt(self.root_frame.start_address().as_usize()) as *mut RvPageTable)
};
#[cfg(target_arch = "riscv32")]
for i in 256..1024 {
let flags =
EF::VALID | EF::READABLE | EF::WRITABLE | EF::EXECUTABLE | EF::ACCESSED | EF::DIRTY;
let frame = riscv::addr::Frame::of_addr(PhysAddr::new((i << 22) - PHYSICAL_MEMORY_OFFSET));
table[i].set(frame, flags);
}
#[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;
// 地址4K对齐
let frame = riscv::addr::Frame::of_addr(PhysAddr::new(
// ? i * 1G
(0xFFFFFF80_00000000 + (i << 30)) - PHYSICAL_MEMORY_OFFSET,
));
debug!("table[{:?}] frame: {:#x?}", i, frame);
table[i].set(frame, flags);
}
}
fn token(&self) -> usize {
#[cfg(target_arch = "riscv32")]
return self.root_frame.number() | (1 << 31);
#[cfg(target_arch = "riscv64")]
return self.root_frame.number() | (8 << 60);
}
//设置satp
unsafe fn set_token(token: usize) {
satp::write(token);
}
fn active_token() -> usize {
satp::read().bits()
}
fn flush_tlb() {
unsafe {
sfence_vma_all();
}
}
}
impl Drop for PageTableImpl {
fn drop(&mut self) {
Frame {
paddr: self.root_frame.start_address().as_usize(),
}
.dealloc()
}
}
/*
struct FrameAllocatorForRiscv;
impl FrameAllocator for FrameAllocatorForRiscv {
fn alloc(&mut self) -> Option<Frame> {
alloc_frame().map(|addr| Frame::of_addr(PhysAddr::new(addr)))
}
}
impl FrameDeallocator for FrameAllocatorForRiscv {
fn dealloc(&mut self, frame: Frame) {
dealloc_frame(frame.start_address().as_usize());
}
}
*/

View File

@ -1,130 +0,0 @@
.equ XLENB, 8
# sp + 8*a2 -> a1
.macro LOAD a1, a2
ld \a1, \a2*XLENB(sp)
.endm
.macro STORE a1, a2
sd \a1, \a2*XLENB(sp)
.endm
# int in U: sscratch = kernel_addr; int in S: sscratch = 0;
.macro SAVE_ALL
csrrw sp, sscratch, sp
bnez sp, trap_from_user
trap_from_kernel:
csrr sp, sscratch
trap_from_user:
addi sp, sp, -36*XLENB
# x0 = 0, x2 = sp
STORE x1, 1
STORE x3, 3
STORE x4, 4
STORE x5, 5
STORE x6, 6
STORE x7, 7
STORE x8, 8
STORE x9, 9
STORE x10, 10
STORE x11, 11
STORE x12, 12
STORE x13, 13
STORE x14, 14
STORE x15, 15
STORE x16, 16
STORE x17, 17
STORE x18, 18
STORE x19, 19
STORE x20, 20
STORE x21, 21
STORE x22, 22
STORE x23, 23
STORE x24, 24
STORE x25, 25
STORE x26, 26
STORE x27, 27
STORE x28, 28
STORE x29, 29
STORE x30, 30
STORE x31, 31
csrrw s0, sscratch, x0
csrr s1, sstatus
csrr s2, sepc
csrr s3, stval
csrr s4, scause
STORE s0, 2
STORE s1, 32
STORE s2, 33
STORE s3, 34
STORE s4, 35
.endm
.macro RESTORE_ALL
# s1 = sstatus, s2 = sepc
LOAD s1, 32
LOAD s2, 33
# int in Kernel, sstatus SPP = 1; int in User, sstatus SPP 0
andi s0, s1, 1 << 8
bnez s0, _to_kernel
_to_user:
addi s0, sp, 36 * XLENB
csrw sscratch, s0
_to_kernel:
csrw sstatus, s1
csrw sepc, s2
LOAD x1, 1
LOAD x3, 3
LOAD x4, 4
LOAD x5, 5
LOAD x6, 6
LOAD x7, 7
LOAD x8, 8
LOAD x9, 9
LOAD x10, 10
LOAD x11, 11
LOAD x12, 12
LOAD x13, 13
LOAD x14, 14
LOAD x15, 15
LOAD x16, 16
LOAD x17, 17
LOAD x18, 18
LOAD x19, 19
LOAD x20, 20
LOAD x21, 21
LOAD x22, 22
LOAD x23, 23
LOAD x24, 24
LOAD x25, 25
LOAD x26, 26
LOAD x27, 27
LOAD x28, 28
LOAD x29, 29
LOAD x30, 30
LOAD x31, 31
# sp
LOAD x2, 2
.endm
.section .text
.globl __alltraps
.align 4
__alltraps:
SAVE_ALL
mv a0, sp
jal rust_trap
.globl __trapret
__trapret:
RESTORE_ALL
sret

View File

@ -1,45 +0,0 @@
use alloc::string::String;
use core::slice;
use device_tree::{DeviceTree, Node};
use super::virtio_mmio::virtio_probe;
use super::CMDLINE;
const DEVICE_TREE_MAGIC: u32 = 0xd00dfeed;
fn walk_dt_node(dt: &Node) {
if let Ok(compatible) = dt.prop_str("compatible") {
// TODO: query this from table
if compatible == "virtio,mmio" {
virtio_probe(dt);
}
// TODO: initial other devices (16650, etc.)
}
if let Ok(bootargs) = dt.prop_str("bootargs") {
if bootargs.len() > 0 {
info!("Kernel cmdline: {}", bootargs);
*CMDLINE.write() = String::from(bootargs);
}
}
for child in dt.children.iter() {
walk_dt_node(child);
}
}
struct DtbHeader {
magic: u32,
size: u32,
}
pub fn init(dtb: usize) {
let header = unsafe { &*(dtb as *const DtbHeader) };
let magic = u32::from_be(header.magic);
if magic == DEVICE_TREE_MAGIC {
let size = u32::from_be(header.size);
let dtb_data = unsafe { slice::from_raw_parts(dtb as *const u8, size as usize) };
if let Ok(dt) = DeviceTree::load(dtb_data) {
walk_dt_node(&dt.root);
}
}
}

View File

@ -1,127 +0,0 @@
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use lazy_static::lazy_static;
//use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
use spin::RwLock;
//use crate::sync::Condvar;
use rcore_fs::dev::{BlockDevice, DevError};
#[allow(dead_code)]
pub mod virtio_mmio;
pub mod virtio_blk;
mod device_tree;
#[derive(Debug, Eq, PartialEq)]
pub enum DeviceType {
Net,
Gpu,
Input,
Block,
}
pub trait Driver: Send + Sync {
// if interrupt belongs to this driver, handle it and return true
// return false otherwise
// irq number is provided when available
// driver should skip handling when irq number is mismatched
fn try_handle_interrupt(&self, irq: Option<u32>) -> bool;
// return the correspondent device type, see DeviceType
fn device_type(&self) -> DeviceType;
// get unique identifier for this device
// should be different for each instance
fn get_id(&self) -> String;
/*
// Rust trait is still too restricted...
// network related drivers should implement these
// get mac address for this device
fn get_mac(&self) -> EthernetAddress {
unimplemented!("not a net driver")
}
// get interface name for this device
fn get_ifname(&self) -> String {
unimplemented!("not a net driver")
}
// get ip addresses
fn get_ip_addresses(&self) -> Vec<IpCidr> {
unimplemented!("not a net driver")
}
// get ipv4 address
fn ipv4_address(&self) -> Option<Ipv4Address> {
unimplemented!("not a net driver")
}
// manually trigger a poll, use it after sending packets
fn poll(&self) {
unimplemented!("not a net driver")
}
// send an ethernet frame, only use it when necessary
fn send(&self, data: &[u8]) -> Option<usize> {
unimplemented!("not a net driver")
}
// get mac address from ip address in arp table
fn get_arp(&self, ip: IpAddress) -> Option<EthernetAddress> {
unimplemented!("not a net driver")
}
*/
// block related drivers should implement these
fn read_block(&self, block_id: usize, buf: &mut [u8]) -> Result<(), DevError> {
unimplemented!("not a block driver")
}
fn write_block(&self, block_id: usize, buf: &[u8]) -> Result<(), DevError> {
unimplemented!("not a block driver")
}
}
lazy_static! {
// NOTE: RwLock only write when initializing drivers
pub static ref DRIVERS: RwLock<Vec<Arc<Driver>>> = RwLock::new(Vec::new());
pub static ref NET_DRIVERS: RwLock<Vec<Arc<Driver>>> = RwLock::new(Vec::new());
pub static ref BLK_DRIVERS: RwLock<Vec<Arc<BlockDriver>>> = RwLock::new(Vec::new());
}
pub struct BlockDriver(Arc<Driver>);
impl BlockDevice for BlockDriver {
const BLOCK_SIZE_LOG2: u8 = 9; // 512
fn read_at(&self, block_id: usize, buf: &mut [u8]) -> Result<(), DevError> {
self.0.read_block(block_id, buf)
}
fn write_at(&self, block_id: usize, buf: &[u8]) -> Result<(), DevError> {
self.0.write_block(block_id, buf)
}
fn sync(&self) -> Result<(), DevError> {
Ok(())
}
}
/*
lazy_static! {
pub static ref SOCKET_ACTIVITY: Condvar = Condvar::new();
}
*/
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "mips"))]
pub fn init(dtb: usize) {
device_tree::init(dtb);
}
lazy_static! {
// Write only once at boot
pub static ref CMDLINE: RwLock<String> = RwLock::new(String::new());
}

View File

@ -1,232 +0,0 @@
use alloc::string::String;
use alloc::sync::Arc;
use core::cmp::min;
use core::mem::{size_of, zeroed};
use core::slice;
use alloc::format;
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;
use rcore_fs::dev::{BlockDevice, DevError};
use super::BlockDriver;
use crate::memory::active_table;
//use crate::sync::SpinNoIrqLock as Mutex;
use spin::Mutex;
use super::virtio_mmio::*;
use super::{DeviceType, Driver, BLK_DRIVERS, DRIVERS};
pub struct VirtIOBlk {
interrupt_parent: u32,
interrupt: u32,
header: usize,
queue: VirtIOVirtqueue,
capacity: usize,
}
pub struct VirtIOBlkDriver(Mutex<VirtIOBlk>);
#[repr(C)]
#[derive(Debug)]
struct VirtIOBlkConfig {
capacity: Volatile<u64>, // number of 512 sectors
}
#[repr(C)]
#[derive(Debug, Default)]
struct VirtIOBlkReadReq {
req_type: u32,
reserved: u32,
sector: u64,
}
#[repr(C)]
struct VirtIOBlkWriteReq {
req_type: u32,
reserved: u32,
sector: u64,
data: [u8; VIRTIO_BLK_BLK_SIZE],
}
#[repr(C)]
struct VirtIOBlkReadResp {
data: [u8; VIRTIO_BLK_BLK_SIZE],
status: u8,
}
#[repr(C)]
#[derive(Debug, Default)]
struct VirtIOBlkWriteResp {
status: u8,
}
const VIRTIO_BLK_T_IN: u32 = 0;
const VIRTIO_BLK_T_OUT: u32 = 1;
const VIRTIO_BLK_S_OK: u8 = 0;
const VIRTIO_BLK_S_IOERR: u8 = 1;
const VIRTIO_BLK_S_UNSUPP: u8 = 2;
const VIRTIO_BLK_BLK_SIZE: usize = 512;
bitflags! {
struct VirtIOBlkFeature : u64 {
const BARRIER = 1 << 0;
const SIZE_MAX = 1 << 1;
const SEG_MAX = 1 << 2;
const GEOMETRY = 1 << 4;
const RO = 1 << 5;
const BLK_SIZE = 1 << 6;
const SCSI = 1 << 7;
const FLUSH = 1 << 9;
const TOPOLOGY = 1 << 10;
const CONFIG_WCE = 1 << 11;
const DISCARD = 1 << 13;
const WRITE_ZEROES = 1 << 14;
// device independent
const NOTIFY_ON_EMPTY = 1 << 24; // legacy
const ANY_LAYOUT = 1 << 27; // legacy
const RING_INDIRECT_DESC = 1 << 28;
const RING_EVENT_IDX = 1 << 29;
const UNUSED = 1 << 30; // legacy
const VERSION_1 = 1 << 32; // detect legacy
const ACCESS_PLATFORM = 1 << 33; // since virtio v1.1
const RING_PACKED = 1 << 34; // since virtio v1.1
const IN_ORDER = 1 << 35; // since virtio v1.1
const ORDER_PLATFORM = 1 << 36; // since virtio v1.1
const SR_IOV = 1 << 37; // since virtio v1.1
const NOTIFICATION_DATA = 1 << 38; // since virtio v1.1
}
}
impl Driver for VirtIOBlkDriver {
fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
let driver = self.0.lock();
// ensure header page is mapped
active_table().map_if_not_exists(driver.header as usize, driver.header as usize);
let header = unsafe { &mut *(driver.header as *mut VirtIOHeader) };
let interrupt = header.interrupt_status.read();
if interrupt != 0 {
header.interrupt_ack.write(interrupt);
return true;
}
return false;
}
fn device_type(&self) -> DeviceType {
DeviceType::Block
}
fn get_id(&self) -> String {
format!("virtio_block")
}
fn read_block(&self, block_id: usize, buf: &mut [u8]) -> Result<(), DevError> {
let mut driver = self.0.lock();
// ensure header page is mapped
active_table().map_if_not_exists(driver.header as usize, driver.header as usize);
let mut req = VirtIOBlkReadReq::default();
req.req_type = VIRTIO_BLK_T_IN;
req.reserved = 0;
req.sector = block_id as u64;
let input = [0; size_of::<VirtIOBlkReadResp>()];
let output = unsafe {
slice::from_raw_parts(
&req as *const VirtIOBlkReadReq as *const u8,
size_of::<VirtIOBlkReadReq>(),
)
};
driver.queue.add_and_notify(&[&input], &[output], 0);
driver.queue.get_block();
let resp = unsafe { &*(&input as *const u8 as *const VirtIOBlkReadResp) };
if resp.status == VIRTIO_BLK_S_OK {
let len = min(buf.len(), VIRTIO_BLK_BLK_SIZE);
buf[..len].clone_from_slice(&resp.data[..len]);
//true
Ok(())
} else {
//false
Err(DevError)
}
}
fn write_block(&self, block_id: usize, buf: &[u8]) -> Result<(), DevError> {
let mut driver = self.0.lock();
// ensure header page is mapped
active_table().map_if_not_exists(driver.header as usize, driver.header as usize);
let mut req: VirtIOBlkWriteReq = unsafe { zeroed() };
req.req_type = VIRTIO_BLK_T_OUT;
req.reserved = 0;
req.sector = block_id as u64;
let len = min(buf.len(), VIRTIO_BLK_BLK_SIZE);
req.data[..len].clone_from_slice(&buf[..len]);
let input = [0; size_of::<VirtIOBlkWriteResp>()];
let output = unsafe {
slice::from_raw_parts(
&req as *const VirtIOBlkWriteReq as *const u8,
size_of::<VirtIOBlkWriteReq>(),
)
};
driver.queue.add_and_notify(&[&input], &[output], 0);
driver.queue.get_block();
let resp = unsafe { &*(&input as *const u8 as *const VirtIOBlkWriteResp) };
if resp.status == VIRTIO_BLK_S_OK {
Ok(())
} else {
Err(DevError)
}
}
}
pub fn virtio_blk_init(node: &Node) {
let reg = node.prop_raw("reg").unwrap();
let from = reg.as_slice().read_be_u64(0).unwrap();
let header = unsafe { &mut *(from as *mut VirtIOHeader) };
header.status.write(VirtIODeviceStatus::DRIVER.bits());
let device_features_bits = header.read_device_features();
let device_features = VirtIOBlkFeature::from_bits_truncate(device_features_bits);
info!("Device features {:?}", device_features);
// negotiate these flags only
let supported_features = VirtIOBlkFeature::empty();
let driver_features = (device_features & supported_features).bits();
header.write_driver_features(driver_features);
// read configuration space
let config = unsafe { &mut *((from + VIRTIO_CONFIG_SPACE_OFFSET) as *mut VirtIOBlkConfig) };
info!("Config: {:?}", config);
info!(
"Found a block device of size {}KB",
config.capacity.read() / 2
);
// virtio 4.2.4 Legacy interface
// configure two virtqueues: ingress and egress
header.guest_page_size.write(PAGE_SIZE as u32); // one page
let driver = VirtIOBlkDriver(Mutex::new(VirtIOBlk {
interrupt: node.prop_u32("interrupts").unwrap(),
interrupt_parent: node.prop_u32("interrupt-parent").unwrap(),
header: from as usize,
queue: VirtIOVirtqueue::new(header, 0, 16),
capacity: config.capacity.read() as usize,
}));
header.status.write(VirtIODeviceStatus::DRIVER_OK.bits());
let driver = Arc::new(driver);
DRIVERS.write().push(driver.clone());
BLK_DRIVERS.write().push(Arc::new(BlockDriver(driver)));
}

View File

@ -1,406 +0,0 @@
use alloc::alloc::{GlobalAlloc, Layout};
use alloc::{vec, vec::Vec};
use core::mem::size_of;
use core::slice;
use core::sync::atomic::{fence, Ordering};
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::{ReadOnly, Volatile, WriteOnly};
//use crate::arch::consts::{KERNEL_OFFSET, MEMORY_OFFSET};
use crate::memory::active_table;
use crate::HEAP_ALLOCATOR;
use super::virtio_blk;
/*
use super::super::block::virtio_blk;
use super::super::gpu::virtio_gpu;
use super::super::input::virtio_input;
use super::super::net::virtio_net;
*/
pub const KERNEL_OFFSET: usize = 0xFFFF_FFFF_C000_0000;
pub const MEMORY_OFFSET: usize = 0x8000_0000;
// virtio 4.2.4 Legacy interface
#[repr(C)]
#[derive(Debug)]
pub struct VirtIOHeader {
magic: ReadOnly<u32>, // 0x000
version: ReadOnly<u32>, // 0x004
device_id: ReadOnly<u32>, // 0x008
vendor_id: ReadOnly<u32>, // 0x00c
pub device_features: ReadOnly<u32>, // 0x010
pub device_features_sel: WriteOnly<u32>, // 0x014
__r1: [ReadOnly<u32>; 2],
pub driver_features: WriteOnly<u32>, // 0x020
pub driver_features_sel: WriteOnly<u32>, // 0x024
pub guest_page_size: WriteOnly<u32>, // 0x028
__r2: ReadOnly<u32>,
pub queue_sel: WriteOnly<u32>, // 0x030
pub queue_num_max: ReadOnly<u32>, // 0x034
pub queue_num: WriteOnly<u32>, // 0x038
pub queue_align: WriteOnly<u32>, // 0x03c
pub queue_pfn: Volatile<u32>, // 0x040
queue_ready: Volatile<u32>, // new interface only
__r3: [ReadOnly<u32>; 2],
pub queue_notify: WriteOnly<u32>, // 0x050
__r4: [ReadOnly<u32>; 3],
pub interrupt_status: ReadOnly<u32>, // 0x060
pub interrupt_ack: WriteOnly<u32>, // 0x064
__r5: [ReadOnly<u32>; 2],
pub status: Volatile<u32>, // 0x070
__r6: [ReadOnly<u32>; 3],
queue_desc_low: WriteOnly<u32>, // new interface only since here
queue_desc_high: WriteOnly<u32>,
__r7: [ReadOnly<u32>; 2],
queue_avail_low: WriteOnly<u32>,
queue_avail_high: WriteOnly<u32>,
__r8: [ReadOnly<u32>; 2],
queue_used_low: WriteOnly<u32>,
queue_used_high: WriteOnly<u32>,
__r9: [ReadOnly<u32>; 21],
config_generation: ReadOnly<u32>,
}
#[repr(C)]
pub struct VirtIOVirtqueue {
header: usize,
queue_address: usize,
queue_num: usize,
queue: usize,
desc: usize, // *mut VirtIOVirtqueueDesc,
avail: usize, // *mut VirtIOVirtqueueAvailableRing,
used: usize, // *mut VirtIOVirtqueueUsedRing,
desc_state: Vec<usize>,
num_used: usize,
free_head: usize,
avail_idx: u16,
last_used_idx: u16,
}
impl VirtIOVirtqueue {
// Initialize a virtqueue
pub fn new(header: &mut VirtIOHeader, queue: usize, queue_num: usize) -> VirtIOVirtqueue {
header.queue_sel.write(queue as u32);
assert_eq!(header.queue_pfn.read(), 0); // not in use
let queue_num_max = header.queue_num_max.read();
assert!(queue_num_max >= queue_num as u32); // queue available
assert!(queue_num & (queue_num - 1) == 0); // power of two
let align = PAGE_SIZE;
let size = virtqueue_size(queue_num, align);
assert!(size % align == 0);
// alloc continuous pages
let address =
unsafe { HEAP_ALLOCATOR.alloc_zeroed(Layout::from_size_align(size, align).unwrap()) }
as usize;
header.queue_num.write(queue_num as u32);
header.queue_align.write(align as u32);
header
.queue_pfn
.write(((address - KERNEL_OFFSET + MEMORY_OFFSET) as u32) >> 12);
// link desc together
let desc =
unsafe { slice::from_raw_parts_mut(address as *mut VirtIOVirtqueueDesc, queue_num) };
for i in 0..(queue_num - 1) {
desc[i].next.write((i + 1) as u16);
}
VirtIOVirtqueue {
header: header as *mut VirtIOHeader as usize,
queue_address: address,
queue_num,
queue,
desc: address,
avail: address + size_of::<VirtIOVirtqueueDesc>() * queue_num,
used: address + virtqueue_used_elem_offset(queue_num, align),
desc_state: vec![0; queue_num],
num_used: 0,
free_head: 0,
avail_idx: 0,
last_used_idx: 0,
}
}
pub fn can_add(&self, input_len: usize, output_len: usize) -> bool {
return input_len + output_len + self.num_used <= self.queue_num;
}
// Add buffers to the virtqueue
// Return true on success, false otherwise
// ref. linux virtio_ring.c virtqueue_add
pub fn add(&mut self, input: &[&[u8]], output: &[&[u8]], user_data: usize) -> bool {
assert!(input.len() + output.len() > 0);
if !self.can_add(input.len(), output.len()) {
return false;
}
let desc = unsafe {
slice::from_raw_parts_mut(self.desc as *mut VirtIOVirtqueueDesc, self.queue_num)
};
let head = self.free_head;
let mut prev = 0;
let mut cur = self.free_head;
for i in 0..output.len() {
desc[cur].flags.write(VirtIOVirtqueueFlag::NEXT.bits());
desc[cur]
.addr
.write(output[i].as_ptr() as u64 - KERNEL_OFFSET as u64 + MEMORY_OFFSET as u64);
desc[cur].len.write(output[i].len() as u32);
prev = cur;
cur = desc[cur].next.read() as usize;
}
for i in 0..input.len() {
desc[cur]
.flags
.write((VirtIOVirtqueueFlag::NEXT | VirtIOVirtqueueFlag::WRITE).bits());
desc[cur]
.addr
.write(input[i].as_ptr() as u64 - KERNEL_OFFSET as u64 + MEMORY_OFFSET as u64);
desc[cur].len.write(input[i].len() as u32);
prev = cur;
cur = desc[cur].next.read() as usize;
}
desc[prev]
.flags
.write(desc[prev].flags.read() & !(VirtIOVirtqueueFlag::NEXT.bits()));
self.num_used += input.len() + output.len();
self.free_head = cur;
let avail = unsafe { &mut *(self.avail as *mut VirtIOVirtqueueAvailableRing) };
let avail_slot = self.avail_idx as usize & (self.queue_num - 1);
avail.ring[avail_slot].write(head as u16);
// write barrier
fence(Ordering::SeqCst);
self.avail_idx = self.avail_idx.wrapping_add(1);
avail.idx.write(self.avail_idx);
self.desc_state[head] = user_data;
return true;
}
// Add buffers to the virtqueue and notify device about it
pub fn add_and_notify(&mut self, input: &[&[u8]], output: &[&[u8]], user_data: usize) -> bool {
let res = self.add(input, output, user_data);
if res {
self.notify();
}
return res;
}
pub fn can_get(&self) -> bool {
let used = unsafe { &mut *(self.used as *mut VirtIOVirtqueueUsedRing) };
return self.last_used_idx != used.idx.read();
}
// Get device used buffers (input, output, length, user_data)
// ref. linux virtio_ring.c virtqueue_get_buf_ctx
pub fn get(&mut self) -> Option<(Vec<&'static [u8]>, Vec<&'static [u8]>, usize, usize)> {
let used = unsafe { &mut *(self.used as *mut VirtIOVirtqueueUsedRing) };
if self.last_used_idx == used.idx.read() {
return None;
}
// read barrier
fence(Ordering::SeqCst);
let last_used_slot = self.last_used_idx as usize & (self.queue_num - 1);
let index = used.ring[last_used_slot].id.read() as usize;
let len = used.ring[last_used_slot].len.read();
let user_data = self.desc_state[last_used_slot];
self.desc_state[last_used_slot] = 0;
let mut cur = index;
let desc = unsafe {
slice::from_raw_parts_mut(self.desc as *mut VirtIOVirtqueueDesc, self.queue_num)
};
let mut input = Vec::new();
let mut output = Vec::new();
loop {
let flags = VirtIOVirtqueueFlag::from_bits_truncate(desc[cur].flags.read());
let addr = desc[cur].addr.read() as u64 - MEMORY_OFFSET as u64 + KERNEL_OFFSET as u64;
let buffer =
unsafe { slice::from_raw_parts(addr as *const u8, desc[cur].len.read() as usize) };
if flags.contains(VirtIOVirtqueueFlag::WRITE) {
input.push(buffer);
} else {
output.push(buffer);
}
if flags.contains(VirtIOVirtqueueFlag::NEXT) {
cur = desc[cur].next.read() as usize;
self.num_used -= 1;
} else {
desc[cur].next.write(self.free_head as u16);
self.num_used -= 1;
break;
}
}
self.free_head = index;
self.last_used_idx = self.last_used_idx.wrapping_add(1);
Some((input, output, len as usize, user_data))
}
// Get device used buffers until succeed
// See get() above
pub fn get_block(&mut self) -> (Vec<&'static [u8]>, Vec<&'static [u8]>, usize, usize) {
loop {
let res = self.get();
if res.is_some() {
return res.unwrap();
}
}
}
// Notify device about new buffers
pub fn notify(&mut self) {
let header = unsafe { &mut *(self.header as *mut VirtIOHeader) };
header.queue_notify.write(self.queue as u32);
}
}
pub const VIRTIO_CONFIG_SPACE_OFFSET: u64 = 0x100;
impl VirtIOHeader {
pub fn read_device_features(&mut self) -> u64 {
let mut device_features_bits: u64;
self.device_features_sel.write(0); // device features [0, 32)
device_features_bits = self.device_features.read().into();
self.device_features_sel.write(1); // device features [32, 64)
device_features_bits = device_features_bits + ((self.device_features.read() as u64) << 32);
device_features_bits
}
pub fn write_driver_features(&mut self, driver_features: u64) {
self.driver_features_sel.write(0); // driver features [0, 32)
self.driver_features
.write((driver_features & 0xFFFFFFFF) as u32);
self.driver_features_sel.write(1); // driver features [32, 64)
self.driver_features
.write(((driver_features & 0xFFFFFFFF00000000) >> 32) as u32);
}
}
bitflags! {
pub struct VirtIODeviceStatus : u32 {
const ACKNOWLEDGE = 1;
const DRIVER = 2;
const FAILED = 128;
const FEATURES_OK = 8;
const DRIVER_OK = 4;
const DEVICE_NEEDS_RESET = 64;
}
}
#[repr(C)]
#[derive(Debug)]
pub struct VirtIOVirtqueueDesc {
pub addr: Volatile<u64>,
pub len: Volatile<u32>,
pub flags: Volatile<u16>,
pub next: Volatile<u16>,
}
bitflags! {
pub struct VirtIOVirtqueueFlag : u16 {
const NEXT = 1;
const WRITE = 2;
const INDIRECT = 4;
}
}
#[repr(C)]
#[derive(Debug)]
pub struct VirtIOVirtqueueAvailableRing {
pub flags: Volatile<u16>,
pub idx: Volatile<u16>,
pub ring: [Volatile<u16>; 32], // actual size: queue_size
used_event: Volatile<u16>, // unused
}
#[repr(C)]
#[derive(Debug)]
pub struct VirtIOVirtqueueUsedElem {
id: Volatile<u32>,
len: Volatile<u32>,
}
#[repr(C)]
#[derive(Debug)]
pub struct VirtIOVirtqueueUsedRing {
pub flags: Volatile<u16>,
pub idx: Volatile<u16>,
pub ring: [VirtIOVirtqueueUsedElem; 32], // actual size: queue_size
avail_event: Volatile<u16>, // unused
}
// virtio 2.4.2 Legacy Interfaces: A Note on Virtqueue Layout
pub fn virtqueue_size(num: usize, align: usize) -> usize {
(((size_of::<VirtIOVirtqueueDesc>() * num + size_of::<u16>() * (3 + num)) + align)
& !(align - 1))
+ (((size_of::<u16>() * 3 + size_of::<VirtIOVirtqueueUsedElem>() * num) + align)
& !(align - 1))
}
pub fn virtqueue_used_elem_offset(num: usize, align: usize) -> usize {
((size_of::<VirtIOVirtqueueDesc>() * num + size_of::<u16>() * (3 + num)) + align) & !(align - 1)
}
pub fn virtio_probe(node: &Node) {
if let Some(reg) = node.prop_raw("reg") {
let from = reg.as_slice().read_be_u64(0).unwrap();
let size = reg.as_slice().read_be_u64(8).unwrap();
// assuming one page
assert_eq!(size as usize, PAGE_SIZE);
active_table().map(from as usize, from as usize);
let header = unsafe { &mut *(from as *mut VirtIOHeader) };
let magic = header.magic.read();
let version = header.version.read();
let device_id = header.device_id.read();
// only support legacy device
if magic == 0x74726976 && version == 1 && device_id != 0 {
// "virt" magic
info!(
"Detected virtio device with vendor id {:#X}",
header.vendor_id.read()
);
info!("Device tree node {:?}", node);
// virtio 3.1.1 Device Initialization
header.status.write(0);
header.status.write(VirtIODeviceStatus::ACKNOWLEDGE.bits());
if device_id == 1 {
// net device
//virtio_net::virtio_net_init(node);
warn!("virtio net device {}", device_id);
} else if device_id == 2 {
debug!("virtio blk device {}", device_id);
// blk device
virtio_blk::virtio_blk_init(node);
} else if device_id == 16 {
// gpu device
//virtio_gpu::virtio_gpu_init(node);
warn!("virtio gpu device {}", device_id);
} else if device_id == 18 {
// input device
//virtio_input::virtio_input_init(node);
warn!("virtio input device {}", device_id);
} else {
warn!("Unrecognized virtio device {}", device_id);
}
} else {
active_table().unmap(from as usize);
}
}
}

View File

@ -48,7 +48,7 @@ pub use self::arch::*;
#[allow(improper_ctypes)]
extern "C" {
fn hal_pt_map_kernel(pt: *mut u8, current: *const u8);
fn hal_frame_alloc() -> Option<PhysAddr>;
fn hal_frame_alloc() -> PhysAddr;
fn hal_frame_dealloc(paddr: &PhysAddr);
#[link_name = "hal_pmem_base"]
static PMEM_BASE: usize;
@ -72,10 +72,20 @@ impl Thread {
impl Future for PageTableSwitchWrapper {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
/* debug info
use kernel_hal::PhysAddr;
use kernel_hal::PageTableTrait;
let mut page_table = PageTableImpl {
root_paddr: self.vmtoken
};
error!("asd1: {:#x?}, {:x}", page_table.query(0xc44b6), self.vmtoken);
*/
unsafe {
arch::set_page_table(self.vmtoken);
}
self.inner.lock().as_mut().poll(cx)
// error!("asd2: {:#x?}, {:x}", page_table.query(0xc44b6), self.vmtoken);
let x = self.inner.lock().as_mut().poll(cx);
x
}
}
@ -117,7 +127,7 @@ pub struct Frame {
impl Frame {
pub fn alloc() -> Option<Self> {
unsafe { hal_frame_alloc().map(|paddr| Frame { paddr }) }
unsafe { Some(Self { paddr: hal_frame_alloc() }) }
}
pub fn dealloc(&mut self) {
@ -211,7 +221,7 @@ mod tests {
}
#[no_mangle]
extern "C" fn hal_frame_alloc() -> Option<PhysAddr> {
extern "C" fn hal_frame_alloc() -> PhysAddr {
unimplemented!()
}

View File

@ -171,7 +171,7 @@ pub struct PhysFrame {
impl PhysFrame {
#[linkage = "weak"]
#[export_name = "hal_frame_alloc"]
pub fn alloc() -> Option<Self> {
pub fn alloc() -> Self {
unimplemented!()
}
@ -438,3 +438,8 @@ pub fn fill_random(buf: &mut [u8]) {
pub fn fill_random(_buf: &mut [u8]) {
// TODO
}
#[cfg(target_arch = "riscv64")]
pub fn fill_random(_buf: &mut [u8]) {
// TODO
}

View File

@ -17,8 +17,12 @@ kernel-hal = { path = "../kernel-hal" }
rcore-fs-hostfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2", optional = true }
env_logger = { version = "0.7", optional = true }
kernel-hal-unix = { path = "../kernel-hal-unix", optional = true }
kernel-hal-bare = { path = "../kernel-hal-bare" }
async-std = { version = "1.6", features = ["attributes"], optional = true }
[features]
default = ["std"]
std = ["env_logger", "async-std", "kernel-hal-unix", "rcore-fs-hostfs", "zircon-object/aspace-separate"]
[target.'cfg(target_arch = "riscv64")'.dependencies]
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"], rev = "0074cbc" }

View File

@ -3,7 +3,7 @@
#![no_std]
#![feature(asm)]
#![feature(global_asm)]
#![deny(warnings, unused_must_use, missing_docs)]
// #![deny(warnings, unused_must_use, missing_docs)]
extern crate alloc;
#[macro_use]
@ -12,7 +12,7 @@ extern crate log;
use {
alloc::{boxed::Box, string::String, sync::Arc, vec::Vec},
core::{future::Future, pin::Pin},
kernel_hal::{GeneralRegs, MMUFlags},
kernel_hal::{MMUFlags, UserContext},
linux_object::{
fs::{vfs::FileSystem, INodeExt},
loader::LinuxElfLoader,
@ -67,6 +67,7 @@ async fn new_thread(thread: CurrentThread) {
kernel_hal::context_run(&mut cx);
trace!("back from user: {:#x?}", cx);
// handle trap/interrupt/syscall
#[cfg(target_arch = "x86_64")]
match cx.trap_num {
0x100 => handle_syscall(&thread, &mut cx.general).await,
0x20..=0x3f => {
@ -93,6 +94,46 @@ async fn new_thread(thread: CurrentThread) {
}
_ => panic!("not supported interrupt from user mode. {:#x?}", cx),
}
#[cfg(target_arch = "riscv64")]
let trap_num = riscv::register::scause::read().bits();
#[cfg(target_arch = "riscv64")]
match trap_num {
// page fault
_ if kernel_hal_bare::arch::is_page_fault(trap_num) => {
let addr = kernel_hal_bare::arch::get_page_fault_addr();
info!("page fault from user @ {:#x}", addr);
let flags = if trap_num == 15 {
MMUFlags::WRITE
} else {
MMUFlags::READ
};
let vmar = thread.proc().vmar();
match vmar.handle_page_fault(addr, flags) {
Ok(()) => {}
Err(err) => {
panic!("Page Fault from user mode {:#x?}, tf = {:#x?}", err, cx);
}
}
}
_ if kernel_hal_bare::arch::is_timer_intr(trap_num) => {
kernel_hal_bare::arch::clock_set_next_event();
kernel_hal::timer_tick();
}
_ if kernel_hal_bare::arch::is_syscall(trap_num) => handle_syscall(&thread, &mut cx).await,
_ => {
/* debug info
use kernel_hal_bare::PageTableImpl;
use kernel_hal::PhysAddr;
use kernel_hal::PageTableTrait;
let mut page_table = PageTableImpl {
root_paddr: riscv::register::satp::read().bits() as usize
};
info!("{:x}", riscv::register::satp::read().bits());
info!("{:#x?}", page_table.query(riscv::register::sepc::read()));
*/
panic!("unhandled trap {:?}", riscv::register::scause::read().cause());
}
}
thread.end_running(cx);
}
}
@ -102,10 +143,15 @@ fn thread_fn(thread: CurrentThread) -> Pin<Box<dyn Future<Output = ()> + Send +
}
/// syscall handler entry
async fn handle_syscall(thread: &CurrentThread, regs: &mut GeneralRegs) {
trace!("syscall: {:#x?}", regs);
let num = regs.rax as u32;
let args = [regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9];
async fn handle_syscall(thread: &CurrentThread, context: &mut UserContext) {
trace!("syscall: {:#x?}", context);
let num = context.get_syscall_num();
let args = context.get_syscall_args();
// let regs = &mut context.general;
#[cfg(target_arch = "riscv64")]
{
context.sepc = context.sepc + 4;
}
let mut syscall = Syscall {
thread,
#[cfg(feature = "std")]
@ -113,7 +159,8 @@ async fn handle_syscall(thread: &CurrentThread, regs: &mut GeneralRegs) {
#[cfg(not(feature = "std"))]
syscall_entry: 0,
thread_fn,
regs,
context,
};
regs.rax = syscall.syscall(num, args).await as usize;
let ret = syscall.syscall(num as u32, args).await;
context.set_syscall_ret(ret as usize);
}

View File

@ -184,6 +184,7 @@ impl From<ZxError> for LxError {
ZxError::SHOULD_WAIT => LxError::EAGAIN,
ZxError::PEER_CLOSED => LxError::EPIPE,
ZxError::BAD_HANDLE => LxError::EBADF,
ZxError::NO_MEMORY => LxError::ENOMEM,
_ => unimplemented!("unknown error type: {:?}", e),
}
}

View File

@ -6,7 +6,7 @@ use {
crate::fs::INodeExt,
alloc::{collections::BTreeMap, string::String, sync::Arc, vec::Vec},
rcore_fs::vfs::INode,
xmas_elf::ElfFile,
xmas_elf::{ElfFile, program::Type},
zircon_object::{util::elf_loader::*, vm::*, ZxError},
};
@ -54,7 +54,10 @@ impl LinuxElfLoader {
vmo.write(offset as usize, &self.syscall_entry.to_ne_bytes())?;
}
elf.relocate(base).map_err(|_| ZxError::INVALID_ARGS)?;
match elf.relocate(base).map_err(|_| ZxError::INVALID_ARGS) {
Ok(_) => {},
_ => warn!(".rela.dyn not found"),
}
let stack_vmo = VmObject::new_paged(self.stack_pages);
let flags = MMUFlags::READ | MMUFlags::WRITE | MMUFlags::USER;
@ -67,7 +70,9 @@ impl LinuxElfLoader {
auxv: {
let mut map = BTreeMap::new();
map.insert(abi::AT_BASE, base);
map.insert(abi::AT_PHDR, base + elf.header.pt2.ph_offset() as usize);
if let Some(phdr_vaddr) = get_phdr_vaddr(&elf) {
map.insert(abi::AT_PHDR, phdr_vaddr as usize);
}
map.insert(abi::AT_ENTRY, entry);
map.insert(abi::AT_PHENT, elf.header.pt2.ph_entry_size() as usize);
map.insert(abi::AT_PHNUM, elf.header.pt2.ph_count() as usize);
@ -82,3 +87,22 @@ impl LinuxElfLoader {
Ok((entry, sp))
}
}
fn get_phdr_vaddr(elf: &ElfFile) -> Option<u64> {
if let Some(phdr) = elf
.program_iter()
.find(|ph| ph.get_type() == Ok(Type::Phdr))
{
// if phdr exists in program header, use it
Some(phdr.virtual_addr())
} else if let Some(elf_addr) = elf
.program_iter()
.find(|ph| ph.get_type() == Ok(Type::Load) && ph.offset() == 0)
{
// otherwise, check if elf is loaded from the beginning, then phdr can be inferred.
Some(elf_addr.virtual_addr() + elf.header.pt2.ph_offset())
} else {
warn!("elf: no phdr found, tls might not work");
None
}
}

View File

@ -1,8 +1,12 @@
use std::io::Write;
fn main() {
println!("cargo:rerun-if-changed=src/syscall.h.in");
let arch = std::env::var("ARCH").unwrap();
if arch == "riscv64" {
println!("cargo:rerun-if-changed=src/syscall_riscv64.h.in");
} else {
println!("cargo:rerun-if-changed=src/syscall.h.in");
}
let mut fout = std::fs::File::create("src/consts.rs").unwrap();
writeln!(fout, "// Generated by build.rs. DO NOT EDIT.").unwrap();
writeln!(fout, "use numeric_enum_macro::numeric_enum;\n").unwrap();
@ -11,8 +15,13 @@ fn main() {
writeln!(fout, "#[derive(Debug, Eq, PartialEq)]").unwrap();
writeln!(fout, "#[allow(non_camel_case_types)]").unwrap();
writeln!(fout, "pub enum SyscallType {{").unwrap();
let data = std::fs::read_to_string("src/syscall.h.in").unwrap();
let mut name: String = String::default();
if arch == "riscv64" {
name = "src/syscall_riscv64.h.in".to_string()
} else if arch == "x86_64" {
name = "src/syscall.h.in".to_string()
}
let data = std::fs::read_to_string(name).unwrap();
for line in data.lines() {
if !line.starts_with("#define") {
continue;

View File

@ -6,352 +6,283 @@ numeric_enum! {
#[derive(Debug, Eq, PartialEq)]
#[allow(non_camel_case_types)]
pub enum SyscallType {
READ = 0,
WRITE = 1,
OPEN = 2,
CLOSE = 3,
STAT = 4,
FSTAT = 5,
LSTAT = 6,
POLL = 7,
LSEEK = 8,
MMAP = 9,
MPROTECT = 10,
MUNMAP = 11,
BRK = 12,
RT_SIGACTION = 13,
RT_SIGPROCMASK = 14,
RT_SIGRETURN = 15,
IOCTL = 16,
PREAD64 = 17,
PWRITE64 = 18,
READV = 19,
WRITEV = 20,
ACCESS = 21,
PIPE = 22,
SELECT = 23,
SCHED_YIELD = 24,
MREMAP = 25,
MSYNC = 26,
MINCORE = 27,
MADVISE = 28,
SHMGET = 29,
SHMAT = 30,
SHMCTL = 31,
DUP = 32,
DUP2 = 33,
PAUSE = 34,
NANOSLEEP = 35,
GETITIMER = 36,
ALARM = 37,
SETITIMER = 38,
GETPID = 39,
SENDFILE = 40,
SOCKET = 41,
CONNECT = 42,
ACCEPT = 43,
SENDTO = 44,
RECVFROM = 45,
SENDMSG = 46,
RECVMSG = 47,
SHUTDOWN = 48,
BIND = 49,
LISTEN = 50,
GETSOCKNAME = 51,
GETPEERNAME = 52,
SOCKETPAIR = 53,
SETSOCKOPT = 54,
GETSOCKOPT = 55,
CLONE = 56,
FORK = 57,
VFORK = 58,
EXECVE = 59,
EXIT = 60,
WAIT4 = 61,
KILL = 62,
UNAME = 63,
SEMGET = 64,
SEMOP = 65,
SEMCTL = 66,
SHMDT = 67,
MSGGET = 68,
MSGSND = 69,
MSGRCV = 70,
MSGCTL = 71,
FCNTL = 72,
FLOCK = 73,
FSYNC = 74,
FDATASYNC = 75,
TRUNCATE = 76,
FTRUNCATE = 77,
GETDENTS = 78,
GETCWD = 79,
CHDIR = 80,
FCHDIR = 81,
RENAME = 82,
MKDIR = 83,
RMDIR = 84,
CREAT = 85,
LINK = 86,
UNLINK = 87,
SYMLINK = 88,
READLINK = 89,
CHMOD = 90,
FCHMOD = 91,
CHOWN = 92,
FCHOWN = 93,
LCHOWN = 94,
UMASK = 95,
GETTIMEOFDAY = 96,
GETRLIMIT = 97,
GETRUSAGE = 98,
SYSINFO = 99,
TIMES = 100,
PTRACE = 101,
GETUID = 102,
SYSLOG = 103,
GETGID = 104,
SETUID = 105,
SETGID = 106,
GETEUID = 107,
GETEGID = 108,
SETPGID = 109,
GETPPID = 110,
GETPGRP = 111,
SETSID = 112,
SETREUID = 113,
SETREGID = 114,
GETGROUPS = 115,
SETGROUPS = 116,
SETRESUID = 117,
GETRESUID = 118,
SETRESGID = 119,
GETRESGID = 120,
GETPGID = 121,
SETFSUID = 122,
SETFSGID = 123,
GETSID = 124,
CAPGET = 125,
CAPSET = 126,
RT_SIGPENDING = 127,
RT_SIGTIMEDWAIT = 128,
RT_SIGQUEUEINFO = 129,
RT_SIGSUSPEND = 130,
SIGALTSTACK = 131,
UTIME = 132,
MKNOD = 133,
USELIB = 134,
PERSONALITY = 135,
USTAT = 136,
STATFS = 137,
FSTATFS = 138,
SYSFS = 139,
GETPRIORITY = 140,
SETPRIORITY = 141,
SCHED_SETPARAM = 142,
SCHED_GETPARAM = 143,
SCHED_SETSCHEDULER = 144,
SCHED_GETSCHEDULER = 145,
SCHED_GET_PRIORITY_MAX = 146,
SCHED_GET_PRIORITY_MIN = 147,
SCHED_RR_GET_INTERVAL = 148,
MLOCK = 149,
MUNLOCK = 150,
MLOCKALL = 151,
MUNLOCKALL = 152,
VHANGUP = 153,
MODIFY_LDT = 154,
PIVOT_ROOT = 155,
_SYSCTL = 156,
PRCTL = 157,
ARCH_PRCTL = 158,
ADJTIMEX = 159,
SETRLIMIT = 160,
CHROOT = 161,
SYNC = 162,
ACCT = 163,
SETTIMEOFDAY = 164,
MOUNT = 165,
UMOUNT2 = 166,
SWAPON = 167,
SWAPOFF = 168,
REBOOT = 169,
SETHOSTNAME = 170,
SETDOMAINNAME = 171,
IOPL = 172,
IOPERM = 173,
CREATE_MODULE = 174,
INIT_MODULE = 175,
DELETE_MODULE = 176,
GET_KERNEL_SYMS = 177,
QUERY_MODULE = 178,
QUOTACTL = 179,
NFSSERVCTL = 180,
GETPMSG = 181,
PUTPMSG = 182,
AFS_SYSCALL = 183,
TUXCALL = 184,
SECURITY = 185,
GETTID = 186,
READAHEAD = 187,
SETXATTR = 188,
LSETXATTR = 189,
FSETXATTR = 190,
GETXATTR = 191,
LGETXATTR = 192,
FGETXATTR = 193,
LISTXATTR = 194,
LLISTXATTR = 195,
FLISTXATTR = 196,
REMOVEXATTR = 197,
LREMOVEXATTR = 198,
FREMOVEXATTR = 199,
TKILL = 200,
TIME = 201,
FUTEX = 202,
SCHED_SETAFFINITY = 203,
SCHED_GETAFFINITY = 204,
SET_THREAD_AREA = 205,
IO_SETUP = 206,
IO_DESTROY = 207,
IO_GETEVENTS = 208,
IO_SUBMIT = 209,
IO_CANCEL = 210,
GET_THREAD_AREA = 211,
LOOKUP_DCOOKIE = 212,
EPOLL_CREATE = 213,
EPOLL_CTL_OLD = 214,
EPOLL_WAIT_OLD = 215,
REMAP_FILE_PAGES = 216,
GETDENTS64 = 217,
SET_TID_ADDRESS = 218,
RESTART_SYSCALL = 219,
SEMTIMEDOP = 220,
FADVISE64 = 221,
TIMER_CREATE = 222,
TIMER_SETTIME = 223,
TIMER_GETTIME = 224,
TIMER_GETOVERRUN = 225,
TIMER_DELETE = 226,
CLOCK_SETTIME = 227,
CLOCK_GETTIME = 228,
CLOCK_GETRES = 229,
CLOCK_NANOSLEEP = 230,
EXIT_GROUP = 231,
EPOLL_WAIT = 232,
EPOLL_CTL = 233,
TGKILL = 234,
UTIMES = 235,
VSERVER = 236,
MBIND = 237,
SET_MEMPOLICY = 238,
GET_MEMPOLICY = 239,
MQ_OPEN = 240,
MQ_UNLINK = 241,
MQ_TIMEDSEND = 242,
MQ_TIMEDRECEIVE = 243,
MQ_NOTIFY = 244,
MQ_GETSETATTR = 245,
KEXEC_LOAD = 246,
WAITID = 247,
ADD_KEY = 248,
REQUEST_KEY = 249,
KEYCTL = 250,
IOPRIO_SET = 251,
IOPRIO_GET = 252,
INOTIFY_INIT = 253,
INOTIFY_ADD_WATCH = 254,
INOTIFY_RM_WATCH = 255,
MIGRATE_PAGES = 256,
OPENAT = 257,
MKDIRAT = 258,
MKNODAT = 259,
FCHOWNAT = 260,
FUTIMESAT = 261,
NEWFSTATAT = 262,
UNLINKAT = 263,
RENAMEAT = 264,
LINKAT = 265,
SYMLINKAT = 266,
READLINKAT = 267,
FCHMODAT = 268,
FACCESSAT = 269,
PSELECT6 = 270,
PPOLL = 271,
UNSHARE = 272,
SET_ROBUST_LIST = 273,
GET_ROBUST_LIST = 274,
SPLICE = 275,
TEE = 276,
SYNC_FILE_RANGE = 277,
VMSPLICE = 278,
MOVE_PAGES = 279,
UTIMENSAT = 280,
EPOLL_PWAIT = 281,
SIGNALFD = 282,
TIMERFD_CREATE = 283,
EVENTFD = 284,
FALLOCATE = 285,
TIMERFD_SETTIME = 286,
TIMERFD_GETTIME = 287,
ACCEPT4 = 288,
SIGNALFD4 = 289,
EVENTFD2 = 290,
EPOLL_CREATE1 = 291,
DUP3 = 292,
PIPE2 = 293,
INOTIFY_INIT1 = 294,
PREADV = 295,
PWRITEV = 296,
RT_TGSIGQUEUEINFO = 297,
PERF_EVENT_OPEN = 298,
RECVMMSG = 299,
FANOTIFY_INIT = 300,
FANOTIFY_MARK = 301,
PRLIMIT64 = 302,
NAME_TO_HANDLE_AT = 303,
OPEN_BY_HANDLE_AT = 304,
CLOCK_ADJTIME = 305,
SYNCFS = 306,
SENDMMSG = 307,
SETNS = 308,
GETCPU = 309,
PROCESS_VM_READV = 310,
PROCESS_VM_WRITEV = 311,
KCMP = 312,
FINIT_MODULE = 313,
SCHED_SETATTR = 314,
SCHED_GETATTR = 315,
RENAMEAT2 = 316,
SECCOMP = 317,
GETRANDOM = 318,
MEMFD_CREATE = 319,
KEXEC_FILE_LOAD = 320,
BPF = 321,
EXECVEAT = 322,
USERFAULTFD = 323,
MEMBARRIER = 324,
MLOCK2 = 325,
COPY_FILE_RANGE = 326,
PREADV2 = 327,
PWRITEV2 = 328,
PKEY_MPROTECT = 329,
PKEY_ALLOC = 330,
PKEY_FREE = 331,
STATX = 332,
IO_PGETEVENTS = 333,
RSEQ = 334,
PIDFD_SEND_SIGNAL = 424,
IO_URING_SETUP = 425,
IO_URING_ENTER = 426,
IO_URING_REGISTER = 427,
OPEN_TREE = 428,
MOVE_MOUNT = 429,
FSOPEN = 430,
FSCONFIG = 431,
FSMOUNT = 432,
FSPICK = 433,
PIDFD_OPEN = 434,
CLONE3 = 435,
IO_SETUP = 0,
IO_DESTROY = 1,
IO_SUBMIT = 2,
IO_CANCEL = 3,
IO_GETEVENTS = 4,
SETXATTR = 5,
LSETXATTR = 6,
FSETXATTR = 7,
GETXATTR = 8,
LGETXATTR = 9,
FGETXATTR = 10,
LISTXATTR = 11,
LLISTXATTR = 12,
FLISTXATTR = 13,
REMOVEXATTR = 14,
LREMOVEXATTR = 15,
FREMOVEXATTR = 16,
GETCWD = 17,
LOOKUP_DCOOKIE = 18,
EVENTFD2 = 19,
EPOLL_CREATE1 = 20,
EPOLL_CTL = 21,
EPOLL_PWAIT = 22,
DUP = 23,
DUP3 = 24,
FCNTL = 25,
INOTIFY_INIT1 = 26,
INOTIFY_ADD_WATCH = 27,
INOTIFY_RM_WATCH = 28,
IOCTL = 29,
IOPRIO_SET = 30,
IOPRIO_GET = 31,
FLOCK = 32,
MKNODAT = 33,
MKDIRAT = 34,
UNLINKAT = 35,
SYMLINKAT = 36,
LINKAT = 37,
RENAMEAT = 38,
UMOUNT2 = 39,
MOUNT = 40,
PIVOT_ROOT = 41,
NFSSERVCTL = 42,
STATFS = 43,
FSTATFS = 44,
TRUNCATE = 45,
FTRUNCATE = 46,
FALLOCATE = 47,
FACCESSAT = 48,
CHDIR = 49,
FCHDIR = 50,
CHROOT = 51,
FCHMOD = 52,
FCHMODAT = 53,
FCHOWNAT = 54,
FCHOWN = 55,
OPENAT = 56,
CLOSE = 57,
VHANGUP = 58,
PIPE2 = 59,
QUOTACTL = 60,
GETDENTS64 = 61,
LSEEK = 62,
READ = 63,
WRITE = 64,
READV = 65,
WRITEV = 66,
PREAD64 = 67,
PWRITE64 = 68,
PREADV = 69,
PWRITEV = 70,
SENDFILE = 71,
PSELECT6 = 72,
PPOLL = 73,
SIGNALFD4 = 74,
VMSPLICE = 75,
SPLICE = 76,
TEE = 77,
READLINKAT = 78,
NEWFSTATAT = 79,
FSTAT = 80,
SYNC = 81,
FSYNC = 82,
FDATASYNC = 83,
SYNC_FILE_RANGE = 84,
TIMERFD_CREATE = 85,
TIMERFD_SETTIME = 86,
TIMERFD_GETTIME = 87,
UTIMENSAT = 88,
ACCT = 89,
CAPGET = 90,
CAPSET = 91,
PERSONALITY = 92,
EXIT = 93,
EXIT_GROUP = 94,
WAITID = 95,
SET_TID_ADDRESS = 96,
UNSHARE = 97,
FUTEX = 98,
SET_ROBUST_LIST = 99,
GET_ROBUST_LIST = 100,
NANOSLEEP = 101,
GETITIMER = 102,
SETITIMER = 103,
KEXEC_LOAD = 104,
INIT_MODULE = 105,
DELETE_MODULE = 106,
TIMER_CREATE = 107,
TIMER_GETTIME = 108,
TIMER_GETOVERRUN = 109,
TIMER_SETTIME = 110,
TIMER_DELETE = 111,
CLOCK_SETTIME = 112,
CLOCK_GETTIME = 113,
CLOCK_GETRES = 114,
CLOCK_NANOSLEEP = 115,
SYSLOG = 116,
PTRACE = 117,
SCHED_SETPARAM = 118,
SCHED_SETSCHEDULER = 119,
SCHED_GETSCHEDULER = 120,
SCHED_GETPARAM = 121,
SCHED_SETAFFINITY = 122,
SCHED_GETAFFINITY = 123,
SCHED_YIELD = 124,
SCHED_GET_PRIORITY_MAX = 125,
SCHED_GET_PRIORITY_MIN = 126,
SCHED_RR_GET_INTERVAL = 127,
RESTART_SYSCALL = 128,
KILL = 129,
TKILL = 130,
TGKILL = 131,
SIGALTSTACK = 132,
RT_SIGSUSPEND = 133,
RT_SIGACTION = 134,
RT_SIGPROCMASK = 135,
RT_SIGPENDING = 136,
RT_SIGTIMEDWAIT = 137,
RT_SIGQUEUEINFO = 138,
RT_SIGRETURN = 139,
SETPRIORITY = 140,
GETPRIORITY = 141,
REBOOT = 142,
SETREGID = 143,
SETGID = 144,
SETREUID = 145,
SETUID = 146,
SETRESUID = 147,
GETRESUID = 148,
SETRESGID = 149,
GETRESGID = 150,
SETFSUID = 151,
SETFSGID = 152,
TIMES = 153,
SETPGID = 154,
GETPGID = 155,
GETSID = 156,
SETSID = 157,
GETGROUPS = 158,
SETGROUPS = 159,
UNAME = 160,
SETHOSTNAME = 161,
SETDOMAINNAME = 162,
GETRLIMIT = 163,
SETRLIMIT = 164,
GETRUSAGE = 165,
UMASK = 166,
PRCTL = 167,
GETCPU = 168,
GETTIMEOFDAY = 169,
SETTIMEOFDAY = 170,
ADJTIMEX = 171,
GETPID = 172,
GETPPID = 173,
GETUID = 174,
GETEUID = 175,
GETGID = 176,
GETEGID = 177,
GETTID = 178,
SYSINFO = 179,
MQ_OPEN = 180,
MQ_UNLINK = 181,
MQ_TIMEDSEND = 182,
MQ_TIMEDRECEIVE = 183,
MQ_NOTIFY = 184,
MQ_GETSETATTR = 185,
MSGGET = 186,
MSGCTL = 187,
MSGRCV = 188,
MSGSND = 189,
SEMGET = 190,
SEMCTL = 191,
SEMTIMEDOP = 192,
SEMOP = 193,
SHMGET = 194,
SHMCTL = 195,
SHMAT = 196,
SHMDT = 197,
SOCKET = 198,
SOCKETPAIR = 199,
BIND = 200,
LISTEN = 201,
ACCEPT = 202,
CONNECT = 203,
GETSOCKNAME = 204,
GETPEERNAME = 205,
SENDTO = 206,
RECVFROM = 207,
SETSOCKOPT = 208,
GETSOCKOPT = 209,
SHUTDOWN = 210,
SENDMSG = 211,
RECVMSG = 212,
READAHEAD = 213,
BRK = 214,
MUNMAP = 215,
MREMAP = 216,
ADD_KEY = 217,
REQUEST_KEY = 218,
KEYCTL = 219,
CLONE = 220,
EXECVE = 221,
MMAP = 222,
FADVISE64 = 223,
SWAPON = 224,
SWAPOFF = 225,
MPROTECT = 226,
MSYNC = 227,
MLOCK = 228,
MUNLOCK = 229,
MLOCKALL = 230,
MUNLOCKALL = 231,
MINCORE = 232,
MADVISE = 233,
REMAP_FILE_PAGES = 234,
MBIND = 235,
GET_MEMPOLICY = 236,
SET_MEMPOLICY = 237,
MIGRATE_PAGES = 238,
MOVE_PAGES = 239,
RT_TGSIGQUEUEINFO = 240,
PERF_EVENT_OPEN = 241,
ACCEPT4 = 242,
RECVMMSG = 243,
ARCH_SPECIFIC_SYSCALL = 244,
WAIT4 = 260,
PRLIMIT64 = 261,
FANOTIFY_INIT = 262,
FANOTIFY_MARK = 263,
NAME_TO_HANDLE_AT = 264,
OPEN_BY_HANDLE_AT = 265,
CLOCK_ADJTIME = 266,
SYNCFS = 267,
SETNS = 268,
SENDMMSG = 269,
PROCESS_VM_READV = 270,
PROCESS_VM_WRITEV = 271,
KCMP = 272,
FINIT_MODULE = 273,
SCHED_SETATTR = 274,
SCHED_GETATTR = 275,
RENAMEAT2 = 276,
SECCOMP = 277,
GETRANDOM = 278,
MEMFD_CREATE = 279,
BPF = 280,
EXECVEAT = 281,
USERFAULTFD = 282,
MEMBARRIER = 283,
MLOCK2 = 284,
COPY_FILE_RANGE = 285,
PREADV2 = 286,
PWRITEV2 = 287,
PKEY_MPROTECT = 288,
PKEY_ALLOC = 289,
PKEY_FREE = 290,
MAP_PCI_DEVICE = 999,
GET_PADDR = 998,
}
}

View File

@ -19,7 +19,7 @@ impl Syscall<'_> {
/// - base pointer to the buffer to fill with read contents
/// - len number of bytes to read
pub async fn sys_read(&self, fd: FileDesc, mut base: UserOutPtr<u8>, len: usize) -> SysResult {
info!("read: fd={:?}, base={:?}, len={:#x}", fd, base, len);
trace!("read: fd={:?}, base={:?}, len={:#x}", fd, base, len);
let proc = self.linux_process();
let file_like = proc.get_file_like(fd)?;
let mut buf = vec![0u8; len];

View File

@ -32,7 +32,7 @@ use {
self::consts::SyscallType as Sys,
alloc::sync::Arc,
core::convert::TryFrom,
kernel_hal::{user::*, GeneralRegs},
kernel_hal::{user::*, UserContext},
linux_object::{error::*, fs::FileDesc, process::*},
zircon_object::{object::*, task::*, vm::VirtAddr},
};
@ -53,7 +53,7 @@ pub struct Syscall<'a> {
/// the entry of current syscall
pub syscall_entry: VirtAddr,
/// store the regs statues
pub regs: &'a mut GeneralRegs,
pub context: &'a mut UserContext,
/// new thread function
pub thread_fn: ThreadFn,
}
@ -61,14 +61,14 @@ pub struct Syscall<'a> {
impl Syscall<'_> {
/// syscall entry function
pub async fn syscall(&mut self, num: u32, args: [usize; 6]) -> isize {
debug!("syscall: num={}, args={:x?}", num, args);
let sys_type = match Sys::try_from(num) {
Ok(t) => t,
Err(_) => {
error!("invalid syscall number: {}", num);
return LxError::EINVAL as _;
}
};
};
debug!("syscall: {:?}, args={:x?}", sys_type, args);
let [a0, a1, a2, a3, a4, a5] = args;
let ret = match sys_type {
Sys::READ => self.sys_read(a0.into(), a1.into(), a2).await,
@ -236,8 +236,9 @@ impl Syscall<'_> {
// Sys::DELETE_MODULE => self.sys_delete_module(a0.into(), a1 as u32),
#[cfg(target_arch = "x86_64")]
_ => self.x86_64_syscall(sys_type, args).await,
#[cfg(target_arch = "riscv64")]
_ => self.riscv64_syscall(sys_type, args).await,
};
info!("<= {:x?}", ret);
match ret {
Ok(value) => value as isize,
Err(err) => -(err as isize),
@ -279,6 +280,16 @@ impl Syscall<'_> {
}
}
#[cfg(target_arch = "riscv64")]
/// syscall specified for riscv64
async fn riscv64_syscall(&mut self, sys_type: Sys, _args: [usize; 6]) -> SysResult {
// let [a0, a1, a2, a3, a4, _a5] = args;
info!("{:?}", sys_type);
match sys_type {
_ => self.unknown_syscall(sys_type),
}
}
/// unkown syscalls, currently is similar to unimplemented syscalls but emit an error
fn unknown_syscall(&mut self, sys_type: Sys) -> SysResult {
error!("unknown syscall: {:?}. exit...", sys_type);

View File

@ -0,0 +1,283 @@
//! RISCV32 syscall ids
//! Reference: https://github.com/riscv/riscv-musl/blob/staging/arch/riscv32/bits/syscall.h.in
#define __NR_IO_SETUP 0
#define __NR_IO_DESTROY 1
#define __NR_IO_SUBMIT 2
#define __NR_IO_CANCEL 3
#define __NR_IO_GETEVENTS 4
#define __NR_SETXATTR 5
#define __NR_LSETXATTR 6
#define __NR_FSETXATTR 7
#define __NR_GETXATTR 8
#define __NR_LGETXATTR 9
#define __NR_FGETXATTR 10
#define __NR_LISTXATTR 11
#define __NR_LLISTXATTR 12
#define __NR_FLISTXATTR 13
#define __NR_REMOVEXATTR 14
#define __NR_LREMOVEXATTR 15
#define __NR_FREMOVEXATTR 16
#define __NR_GETCWD 17
#define __NR_LOOKUP_DCOOKIE 18
#define __NR_EVENTFD2 19
#define __NR_EPOLL_CREATE1 20
#define __NR_EPOLL_CTL 21
#define __NR_EPOLL_PWAIT 22
#define __NR_DUP 23
#define __NR_DUP3 24
#define __NR_FCNTL 25
#define __NR_INOTIFY_INIT1 26
#define __NR_INOTIFY_ADD_WATCH 27
#define __NR_INOTIFY_RM_WATCH 28
#define __NR_IOCTL 29
#define __NR_IOPRIO_SET 30
#define __NR_IOPRIO_GET 31
#define __NR_FLOCK 32
#define __NR_MKNODAT 33
#define __NR_MKDIRAT 34
#define __NR_UNLINKAT 35
#define __NR_SYMLINKAT 36
#define __NR_LINKAT 37
#define __NR_RENAMEAT 38
#define __NR_UMOUNT2 39
#define __NR_MOUNT 40
#define __NR_PIVOT_ROOT 41
#define __NR_NFSSERVCTL 42
#define __NR_STATFS 43
#define __NR_FSTATFS 44
#define __NR_TRUNCATE 45
#define __NR_FTRUNCATE 46
#define __NR_FALLOCATE 47
#define __NR_FACCESSAT 48
#define __NR_CHDIR 49
#define __NR_FCHDIR 50
#define __NR_CHROOT 51
#define __NR_FCHMOD 52
#define __NR_FCHMODAT 53
#define __NR_FCHOWNAT 54
#define __NR_FCHOWN 55
#define __NR_OPENAT 56
#define __NR_CLOSE 57
#define __NR_VHANGUP 58
#define __NR_PIPE2 59
#define __NR_QUOTACTL 60
#define __NR_GETDENTS64 61
#define __NR_LSEEK 62
#define __NR_READ 63
#define __NR_WRITE 64
#define __NR_READV 65
#define __NR_WRITEV 66
#define __NR_PREAD64 67
#define __NR_PWRITE64 68
#define __NR_PREADV 69
#define __NR_PWRITEV 70
#define __NR_SENDFILE 71
#define __NR_PSELECT6 72
#define __NR_PPOLL 73
#define __NR_SIGNALFD4 74
#define __NR_VMSPLICE 75
#define __NR_SPLICE 76
#define __NR_TEE 77
#define __NR_READLINKAT 78
#define __NR_NEWFSTATAT 79
#define __NR_FSTAT 80
#define __NR_SYNC 81
#define __NR_FSYNC 82
#define __NR_FDATASYNC 83
#define __NR_SYNC_FILE_RANGE 84
#define __NR_TIMERFD_CREATE 85
#define __NR_TIMERFD_SETTIME 86
#define __NR_TIMERFD_GETTIME 87
#define __NR_UTIMENSAT 88
#define __NR_ACCT 89
#define __NR_CAPGET 90
#define __NR_CAPSET 91
#define __NR_PERSONALITY 92
#define __NR_EXIT 93
#define __NR_EXIT_GROUP 94
#define __NR_WAITID 95
#define __NR_SET_TID_ADDRESS 96
#define __NR_UNSHARE 97
#define __NR_FUTEX 98
#define __NR_SET_ROBUST_LIST 99
#define __NR_GET_ROBUST_LIST 100
#define __NR_NANOSLEEP 101
#define __NR_GETITIMER 102
#define __NR_SETITIMER 103
#define __NR_KEXEC_LOAD 104
#define __NR_INIT_MODULE 105
#define __NR_DELETE_MODULE 106
#define __NR_TIMER_CREATE 107
#define __NR_TIMER_GETTIME 108
#define __NR_TIMER_GETOVERRUN 109
#define __NR_TIMER_SETTIME 110
#define __NR_TIMER_DELETE 111
#define __NR_CLOCK_SETTIME 112
#define __NR_CLOCK_GETTIME 113
#define __NR_CLOCK_GETRES 114
#define __NR_CLOCK_NANOSLEEP 115
#define __NR_SYSLOG 116
#define __NR_PTRACE 117
#define __NR_SCHED_SETPARAM 118
#define __NR_SCHED_SETSCHEDULER 119
#define __NR_SCHED_GETSCHEDULER 120
#define __NR_SCHED_GETPARAM 121
#define __NR_SCHED_SETAFFINITY 122
#define __NR_SCHED_GETAFFINITY 123
#define __NR_SCHED_YIELD 124
#define __NR_SCHED_GET_PRIORITY_MAX 125
#define __NR_SCHED_GET_PRIORITY_MIN 126
#define __NR_SCHED_RR_GET_INTERVAL 127
#define __NR_RESTART_SYSCALL 128
#define __NR_KILL 129
#define __NR_TKILL 130
#define __NR_TGKILL 131
#define __NR_SIGALTSTACK 132
#define __NR_RT_SIGSUSPEND 133
#define __NR_RT_SIGACTION 134
#define __NR_RT_SIGPROCMASK 135
#define __NR_RT_SIGPENDING 136
#define __NR_RT_SIGTIMEDWAIT 137
#define __NR_RT_SIGQUEUEINFO 138
#define __NR_RT_SIGRETURN 139
#define __NR_SETPRIORITY 140
#define __NR_GETPRIORITY 141
#define __NR_REBOOT 142
#define __NR_SETREGID 143
#define __NR_SETGID 144
#define __NR_SETREUID 145
#define __NR_SETUID 146
#define __NR_SETRESUID 147
#define __NR_GETRESUID 148
#define __NR_SETRESGID 149
#define __NR_GETRESGID 150
#define __NR_SETFSUID 151
#define __NR_SETFSGID 152
#define __NR_TIMES 153
#define __NR_SETPGID 154
#define __NR_GETPGID 155
#define __NR_GETSID 156
#define __NR_SETSID 157
#define __NR_GETGROUPS 158
#define __NR_SETGROUPS 159
#define __NR_UNAME 160
#define __NR_SETHOSTNAME 161
#define __NR_SETDOMAINNAME 162
#define __NR_GETRLIMIT 163
#define __NR_SETRLIMIT 164
#define __NR_GETRUSAGE 165
#define __NR_UMASK 166
#define __NR_PRCTL 167
#define __NR_GETCPU 168
#define __NR_GETTIMEOFDAY 169
#define __NR_SETTIMEOFDAY 170
#define __NR_ADJTIMEX 171
#define __NR_GETPID 172
#define __NR_GETPPID 173
#define __NR_GETUID 174
#define __NR_GETEUID 175
#define __NR_GETGID 176
#define __NR_GETEGID 177
#define __NR_GETTID 178
#define __NR_SYSINFO 179
#define __NR_MQ_OPEN 180
#define __NR_MQ_UNLINK 181
#define __NR_MQ_TIMEDSEND 182
#define __NR_MQ_TIMEDRECEIVE 183
#define __NR_MQ_NOTIFY 184
#define __NR_MQ_GETSETATTR 185
#define __NR_MSGGET 186
#define __NR_MSGCTL 187
#define __NR_MSGRCV 188
#define __NR_MSGSND 189
#define __NR_SEMGET 190
#define __NR_SEMCTL 191
#define __NR_SEMTIMEDOP 192
#define __NR_SEMOP 193
#define __NR_SHMGET 194
#define __NR_SHMCTL 195
#define __NR_SHMAT 196
#define __NR_SHMDT 197
#define __NR_SOCKET 198
#define __NR_SOCKETPAIR 199
#define __NR_BIND 200
#define __NR_LISTEN 201
#define __NR_ACCEPT 202
#define __NR_CONNECT 203
#define __NR_GETSOCKNAME 204
#define __NR_GETPEERNAME 205
#define __NR_SENDTO 206
#define __NR_RECVFROM 207
#define __NR_SETSOCKOPT 208
#define __NR_GETSOCKOPT 209
#define __NR_SHUTDOWN 210
#define __NR_SENDMSG 211
#define __NR_RECVMSG 212
#define __NR_READAHEAD 213
#define __NR_BRK 214
#define __NR_MUNMAP 215
#define __NR_MREMAP 216
#define __NR_ADD_KEY 217
#define __NR_REQUEST_KEY 218
#define __NR_KEYCTL 219
#define __NR_CLONE 220
#define __NR_EXECVE 221
#define __NR_MMAP 222
#define __NR_FADVISE64 223
#define __NR_SWAPON 224
#define __NR_SWAPOFF 225
#define __NR_MPROTECT 226
#define __NR_MSYNC 227
#define __NR_MLOCK 228
#define __NR_MUNLOCK 229
#define __NR_MLOCKALL 230
#define __NR_MUNLOCKALL 231
#define __NR_MINCORE 232
#define __NR_MADVISE 233
#define __NR_REMAP_FILE_PAGES 234
#define __NR_MBIND 235
#define __NR_GET_MEMPOLICY 236
#define __NR_SET_MEMPOLICY 237
#define __NR_MIGRATE_PAGES 238
#define __NR_MOVE_PAGES 239
#define __NR_RT_TGSIGQUEUEINFO 240
#define __NR_PERF_EVENT_OPEN 241
#define __NR_ACCEPT4 242
#define __NR_RECVMMSG 243
#define __NR_ARCH_SPECIFIC_SYSCALL 244
#define __NR_WAIT4 260
#define __NR_PRLIMIT64 261
#define __NR_FANOTIFY_INIT 262
#define __NR_FANOTIFY_MARK 263
#define __NR_NAME_TO_HANDLE_AT 264
#define __NR_OPEN_BY_HANDLE_AT 265
#define __NR_CLOCK_ADJTIME 266
#define __NR_SYNCFS 267
#define __NR_SETNS 268
#define __NR_SENDMMSG 269
#define __NR_PROCESS_VM_READV 270
#define __NR_PROCESS_VM_WRITEV 271
#define __NR_KCMP 272
#define __NR_FINIT_MODULE 273
#define __NR_SCHED_SETATTR 274
#define __NR_SCHED_GETATTR 275
#define __NR_RENAMEAT2 276
#define __NR_SECCOMP 277
#define __NR_GETRANDOM 278
#define __NR_MEMFD_CREATE 279
#define __NR_BPF 280
#define __NR_EXECVEAT 281
#define __NR_USERFAULTFD 282
#define __NR_MEMBARRIER 283
#define __NR_MLOCK2 284
#define __NR_COPY_FILE_RANGE 285
#define __NR_PREADV2 286
#define __NR_PWRITEV2 287
#define __NR_PKEY_MPROTECT 288
#define __NR_PKEY_ALLOC 289
#define __NR_PKEY_FREE 290
// custom temporary syscall
#define __NR_MAP_PCI_DEVICE 999
#define __NR_GET_PADDR 998

View File

@ -20,10 +20,9 @@ use linux_object::time::*;
impl Syscall<'_> {
/// Fork the current process. Return the child's PID.
pub fn sys_fork(&self) -> SysResult {
info!("fork:");
let new_proc = Process::fork_from(self.zircon_process(), false)?;
let new_thread = Thread::create_linux(&new_proc)?;
new_thread.start_with_regs(GeneralRegs::new_fork(self.regs), self.thread_fn)?;
new_thread.start_with_context(UserContext::new_fork(self.context), self.thread_fn)?;
info!("fork: {} -> {}", self.zircon_process().id(), new_proc.id());
Ok(new_proc.id() as usize)
@ -34,7 +33,7 @@ impl Syscall<'_> {
info!("vfork:");
let new_proc = Process::fork_from(self.zircon_process(), true)?;
let new_thread = Thread::create_linux(&new_proc)?;
new_thread.start_with_regs(GeneralRegs::new_fork(self.regs), self.thread_fn)?;
new_thread.start_with_context(UserContext::new_fork(self.context), self.thread_fn)?;
let new_proc: Arc<dyn KernelObject> = new_proc;
info!("vfork: {} -> {}", self.zircon_process().id(), new_proc.id());
@ -62,8 +61,7 @@ impl Syscall<'_> {
);
if flags == 0x4111 || flags == 0x11 {
warn!("sys_clone is calling sys_fork instead, ignoring other args");
unimplemented!()
// return self.sys_fork();
return self.sys_fork();
}
if flags != 0x7d_0f00 && flags != 0x5d_0f00 {
// 0x5d0f00: gcc of alpine linux
@ -72,8 +70,8 @@ impl Syscall<'_> {
panic!("unsupported sys_clone flags: {:#x}", flags);
}
let new_thread = Thread::create_linux(self.zircon_process())?;
let regs = GeneralRegs::new_clone(self.regs, newsp, newtls);
new_thread.start_with_regs(regs, self.thread_fn)?;
let regs = UserContext::new_clone(self.context, newsp, newtls);
new_thread.start_with_context(regs, self.thread_fn)?;
let tid = new_thread.id();
info!("clone: {} -> {}", self.thread.id(), tid);
@ -182,8 +180,8 @@ impl Syscall<'_> {
// TODO: use right signal
self.zircon_process().signal_set(Signal::SIGNALED);
*self.regs = GeneralRegs::new_fn(entry, sp, 0, 0);
*self.context = UserContext::new_fn(entry, sp, 0, 0);
self.context.sstatus = 1 << 18 | 1 << 14 | 1 << 13 | 1 << 5;
Ok(0)
}
//
@ -362,3 +360,27 @@ impl RegExt for GeneralRegs {
GeneralRegs { rax: 0, ..*regs }
}
}
#[cfg(target_arch = "riscv64")]
impl RegExt for UserContext {
fn new_fn(entry: usize, sp: usize, arg1: usize, arg2: usize) -> Self {
let mut ctx = UserContext::default();
ctx.set_ip(entry);
ctx.set_sp(sp);
ctx.general.a0 = arg1;
ctx.general.a1 = arg2;
ctx
}
fn new_clone(_regs: &Self, _newsp: usize, _newtls: usize) -> Self {
unimplemented!();
}
fn new_fork(origin_ctx: &Self) -> Self {
let mut ctx = UserContext {
..*origin_ctx
};
ctx.set_syscall_ret(0);
ctx
}
}

View File

@ -29,9 +29,9 @@ executor = { git = "https://github.com/rcore-os/executor.git", rev = "a2d02ee9"
zircon-loader = { path = "../zircon-loader", default-features = false, optional = true }
zircon-syscall = { path = "../zircon-syscall", optional = true }
zircon-object = { path = "../zircon-object", optional = true }
linux-loader = { path = "../linux-loader", default-features = false, optional = true }
linux-object = { path = "../linux-object", default-features = false, optional = true }
rcore-fs-sfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2", optional = true }
linux-loader = { path = "../linux-loader", default-features = false }
linux-object = { path = "../linux-object", default-features = false }
rcore-fs-sfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "6df6cd2" }
[target.'cfg(target_arch = "x86_64")'.dependencies]
x86_64 = "0.12"
@ -40,6 +40,4 @@ rboot = { path = "../rboot", default-features = false }
rvm = { git = "https://github.com/rcore-os/RVM", rev = "e91d625", optional = true }
[target.'cfg(target_arch = "riscv64")'.dependencies]
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"], rev = "21e32ee1" }
rcore-memory = { path = "../crate/memory" }
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"], rev = "0074cbc" }

View File

@ -9,6 +9,8 @@ hypervisor ?=
smp ?= 1
test_filter ?= *.*
export ARCH=$(arch)
build_args := -Z build-std=core,alloc --target $(arch).json
build_path := target/$(arch)/$(mode)
kernel := $(build_path)/zcore
@ -17,7 +19,7 @@ kernel_bin := $(build_path)/zcore.bin
ESP := $(build_path)/esp
OVMF := ../rboot/OVMF.fd
qemu := qemu-system-$(arch)
OBJDUMP := rust-objdump -print-imm-hex -x86-asm-syntax=intel
OBJDUMP := rust-objdump --print-imm-hex --x86-asm-syntax=intel
OBJCOPY := rust-objcopy --binary-architecture=$(arch)
VMDISK := $(build_path)/boot.vdi
QEMU_DISK := $(build_path)/disk.qcow2
@ -50,13 +52,16 @@ qemu_opts += \
-device isa-debug-exit,iobase=0xf4,iosize=0x04
else ifeq ($(arch), riscv64)
export USER_IMG = ../riscv64.img
qemu_opts += \
-machine virt \
-no-reboot \
-no-shutdown \
-nographic \
-drive file=$(QEMU_DISK),format=qcow2,id=sfs \
-device virtio-blk-device,drive=sfs \
-drive file=$(QEMU_DISK),format=raw,id=x0 \
-device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 \
-kernel $(kernel_bin)
endif
@ -90,8 +95,8 @@ debug: build debugrun
TERMINAL := terminal
debugrun: $(QEMU_DISK)
$(TERMINAL) -e "gdb -tui -x gdbinit"
$(qemu) $(qemu_opts) -s -S
$(qemu) $(qemu_opts) -s -S &
riscv64-unknown-elf-gdb -x gdbinit $(kernel)
justrun: $(QEMU_DISK)
$(qemu) $(qemu_opts)

31
zCore/build.rs Normal file
View File

@ -0,0 +1,31 @@
use std::fs::File;
use std::io::{Result, Write};
fn main() {
println!("cargo:rerun-if-env-changed=USER_IMG");
if let Ok(user_img) = std::env::var("USER_IMG") {
println!("cargo:rerun-if-changed={}", user_img);
}
gen_link_user_asm().unwrap();
}
/// Generate assembly file for linking user image
fn gen_link_user_asm() -> Result<()> {
let mut f = File::create("src/link_user.S").unwrap();
let user_img = std::env::var("USER_IMG").unwrap();
writeln!(f, "# generated by build.rs - do not edit")?;
writeln!(
f,
r#"
.section .data
.global _user_img_start
.global _user_img_end
_user_img_start:
.incbin "{}"
_user_img_end:
"#,
user_img
)?;
Ok(())
}

View File

@ -9,7 +9,7 @@ _start:
#12
lui t0, %hi(boot_page_table_sv39)
li t1, 0xffffffffc0000000 - 0x80000000 #
li t1, 0xffffffff00000000 #
#
sub t0, t0, t1
@ -45,8 +45,12 @@ bootstacktop:
.section .data
.align 12 #12
boot_page_table_sv39:
#1G的一个大页: 0xffffffff_c0000000 --> 0x80000000
#5110
.zero 8 * 511
#PPN=0x80000(12), VRWXAD置1
.quad (0x80000 << 10) | 0xcf
# 0xffffffff_00000000 --> 0x00000000
# 0xffffffff_40000000 --> 0x40000000
# 0xffffffff_80000000 --> 0x80000000
# 0xffffffff_C0000000 --> 0xC0000000
.zero 8 * 508
.quad (0x00000 << 10) | 0xef
.quad (0x40000 << 10) | 0xef
.quad (0x80000 << 10) | 0xef
.quad (0xc0000 << 10) | 0xef

View File

@ -8,7 +8,7 @@ BASE_ADDRESS = 0x80200000;
*/
/* opensbi仍旧把kernel放在0x80200000物理内存中 */
BASE_ADDRESS = 0xffffffffc0200000;
BASE_ADDRESS = 0xffffffff80200000;
SECTIONS
{

View File

@ -3,12 +3,12 @@
#[cfg(target_arch = "riscv32")]
pub const PHYSICAL_MEMORY_OFFSET: usize = 0x4000_0000;
#[cfg(target_arch = "riscv64")]
pub const PHYSICAL_MEMORY_OFFSET: usize = 0xFFFF_FFFF_4000_0000;
pub const PHYSICAL_MEMORY_OFFSET: usize = 0xFFFF_FFFF_0000_0000;
#[cfg(target_arch = "riscv32")]
pub const KERNEL_OFFSET: usize = 0xC000_0000;
#[cfg(target_arch = "riscv64")]
pub const KERNEL_OFFSET: usize = 0xFFFF_FFFF_C000_0000;
pub const KERNEL_OFFSET: usize = 0xFFFF_FFFF_8000_0000;
pub const KERNEL_HEAP_SIZE: usize = 0x0080_0000;

View File

@ -29,7 +29,7 @@ mod memory;
use rboot::BootInfo;
#[cfg(target_arch = "riscv64")]
use kernel_hal_bare::{BootInfo, GraphicInfo, remap_the_kernel};
use kernel_hal_bare::{BootInfo, GraphicInfo};
use alloc::vec::Vec;
pub use memory::{hal_frame_alloc, hal_frame_dealloc, hal_pt_map_kernel, phys_to_virt, write_readonly_test, execute_unexecutable_test, read_invalid_test};
@ -83,31 +83,36 @@ fn main(ramfs_data: &[u8], cmdline: &str) {
run();
}
#[cfg(target_arch = "riscv64")]
global_asm!(include_str!("link_user.S"));
#[cfg(target_arch = "riscv64")]
#[no_mangle]
pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! {
let device_tree_vaddr = phys_to_virt(device_tree_paddr);
extern "C" {
fn _user_img_start();
fn _user_img_end();
};
let boot_info = BootInfo {
memory_map: Vec::new(),
physical_memory_offset: 0,
graphic_info: GraphicInfo{mode: 0, fb_addr: 0, fb_size: 0},
acpi2_rsdp_addr: 0,
smbios_addr: 0,
initramfs_addr: 0,
initramfs_size: 0,
cmdline: "LOG=trace:TERM=xterm-256color:console.shell=true:virtcon.disable=true",
initramfs_addr: _user_img_start as u64,
initramfs_size: _user_img_end as u64 - _user_img_start as u64,
cmdline: "LOG=info:TERM=xterm-256color:console.shell=true:virtcon.disable=true",
};
unsafe {
memory::clear_bss();
}
logging::init(get_log_level(boot_info.cmdline));
logging::init("info");
warn!("rust_main(), After logging init\n\n");
memory::init_heap();
memory::init_frame_allocator(&boot_info);
remap_the_kernel(device_tree_vaddr);
#[cfg(feature = "graphic")]
init_framebuffer(boot_info);
@ -126,9 +131,6 @@ pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! {
*/
loop {} //remove me
// 挂载virtio-blk-device rootfs
//
let ramfs_data = unsafe {
@ -149,19 +151,15 @@ fn main(ramfs_data: &'static mut [u8], _cmdline: &str) {
use alloc::vec;
use alloc::string::String;
/*
use linux_object::fs::MemBuf;
use linux_object::fs::STDIN;
*/
kernel_hal_bare::serial_set_callback(Box::new({
move || {
let mut buffer = [0; 255];
let len = kernel_hal_bare::serial_read(&mut buffer);
for c in &buffer[..len] {
/*
STDIN.push((*c).into());
*/
kernel_hal_bare::serial_write(alloc::format!("{}", *c as char).as_str());
}
false
@ -170,13 +168,11 @@ fn main(ramfs_data: &'static mut [u8], _cmdline: &str) {
let args: Vec<String> = vec!["/bin/busybox".into(), "sh".into()];
let envs: Vec<String> = vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/x86_64-alpine-linux-musl/bin".into()];
/*
let device = Arc::new(MemBuf::new(ramfs_data));
let rootfs = rcore_fs_sfs::SimpleFileSystem::open(device).unwrap();
let _proc = linux_loader::run(args, envs, rootfs);
run();
*/
}
#[cfg(target_arch = "x86_64")]
@ -188,6 +184,27 @@ fn run() -> ! {
}
}
#[cfg(target_arch = "riscv64")]
pub fn wait_for_interrupt() {
unsafe {
// enable interrupt and disable
let sie = riscv::register::sstatus::read().sie();
riscv::register::sstatus::set_sie();
riscv::asm::wfi();
if !sie {
riscv::register::sstatus::clear_sie();
}
}
}
#[cfg(target_arch = "riscv64")]
fn run() -> ! {
loop {
executor::run_until_idle();
wait_for_interrupt();
}
}
fn get_log_level(cmdline: &str) -> &str {
for opt in cmdline.split(':') {
// parse 'key=value'

View File

@ -99,14 +99,15 @@ pub fn init_heap() {
#[no_mangle]
#[allow(improper_ctypes_definitions)]
pub extern "C" fn hal_frame_alloc() -> Option<usize> {
pub extern "C" fn hal_frame_alloc() -> usize {
// get the real address of the alloc frame
let ret = FRAME_ALLOCATOR
.lock()
.alloc()
.map(|id| id * PAGE_SIZE + MEMORY_OFFSET);
trace!("Allocate frame: {:x?}", ret);
ret
assert!(ret.unwrap() != 0, "No Mem");
ret.unwrap()
}
#[no_mangle]
@ -141,9 +142,13 @@ pub extern "C" fn hal_pt_map_kernel(pt: &mut PageTable, current: &PageTable) {
pt[PHYSICAL_MEMORY_PM4].set_addr(ephysical.addr(), ephysical.flags() | EF::GLOBAL);
}
#[no_mangle]
#[cfg(target_arch = "riscv64")]
pub extern "C" fn hal_pt_map_kernel(pt: &mut PageTable, current: &PageTable) {
info!("hal_pt_map_kernel(), NULL! ");
use riscv::addr::Frame;
for i in 508..512 {
pt[i] = current[i].clone();
}
}
pub unsafe fn clear_bss() {

View File

@ -90,6 +90,12 @@ pub struct PacketGuestMem {
pub _reserved: u64,
}
#[cfg(target_arch = "riscv64")]
#[repr(C)]
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
pub struct PacketGuestMem {
}
#[repr(C)]
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
pub struct PacketGuestIo {

View File

@ -142,6 +142,15 @@ struct ExceptionContext {
padding2: u64,
}
/// Data associated with an exception (siginfo in linux parlance)
/// Things available from regsets (e.g., pc) are not included here.
/// For an example list of things one might add, see linux siginfo.
#[cfg(target_arch = "riscv64")]
#[repr(C)]
#[derive(Debug, Default, Clone)]
pub struct ExceptionContext {
}
impl ExceptionContext {
#[cfg(target_arch = "x86_64")]
fn from_user_context(cx: &UserContext) -> Self {
@ -155,6 +164,10 @@ impl ExceptionContext {
fn from_user_context(_cx: &UserContext) -> Self {
unimplemented!()
}
#[cfg(target_arch = "riscv64")]
fn from_user_context(_cx: &UserContext) -> Self {
unimplemented!()
}
}
/// Data reported to an exception handler for most exceptions.

View File

@ -14,7 +14,7 @@ use {
time::Duration,
},
futures::{channel::oneshot::*, future::FutureExt, pin_mut, select_biased},
kernel_hal::{sleep_until, GeneralRegs, UserContext},
kernel_hal::{sleep_until, UserContext},
spin::Mutex,
};
@ -244,21 +244,25 @@ impl Thread {
{
let mut inner = self.inner.lock();
let context = inner.context.as_mut().ok_or(ZxError::BAD_STATE)?;
context.set_ip(entry);
context.set_sp(stack);
#[cfg(target_arch = "x86_64")]
{
context.general.rip = entry;
context.general.rsp = stack;
context.general.rdi = arg1;
context.general.rsi = arg2;
context.general.rflags |= 0x3202;
}
#[cfg(target_arch = "aarch64")]
{
context.elr = entry;
context.sp = stack;
context.general.x0 = arg1;
context.general.x1 = arg2;
}
#[cfg(target_arch = "riscv64")]
{
context.general.a0 = arg1;
context.general.a1 = arg2;
context.sstatus = 1 << 18 | 1 << 14 | 1 << 13 | 1 << 5;
}
inner.change_state(ThreadState::Running, &self.base);
}
let vmtoken = self.proc().vmar().table_phys();
@ -266,16 +270,25 @@ impl Thread {
Ok(())
}
/// Start execution with given registers.
pub fn start_with_regs(self: &Arc<Self>, regs: GeneralRegs, thread_fn: ThreadFn) -> ZxResult {
/// Start execution with given context.
pub fn start_with_context(self: &Arc<Self>, ctx: UserContext, thread_fn: ThreadFn) -> ZxResult {
{
let mut inner = self.inner.lock();
let context = inner.context.as_mut().ok_or(ZxError::BAD_STATE)?;
context.general = regs;
context.general = ctx.general;
#[cfg(target_arch = "x86_64")]
{
context.general.rflags |= 0x3202;
}
#[cfg(target_arch = "riscv64")]
{
context.sepc = ctx.sepc;
context.sstatus = ctx.sstatus;
}
/* debug info
info!("a0: {:x}", ctx.general.a0);
info!("sepc: {:x}", ctx.sepc);
*/
inner.change_state(ThreadState::Running, &self.base);
}
let vmtoken = self.proc().vmar().table_phys();

View File

@ -640,6 +640,9 @@ impl VmarInner {
mapping.map()?;
self.mappings.push(mapping);
}
/* debug info
error!("hhhhh: {:#x?}", page_table.lock().query(0xc44b6));
*/
Ok(())
}
}
@ -958,6 +961,9 @@ pub const KERNEL_ASPACE_BASE: u64 = 0xffff_ff02_0000_0000;
/// The size of kernel address space
pub const KERNEL_ASPACE_SIZE: u64 = 0x0000_0080_0000_0000;
/// The base of user address space
#[cfg(target_arch = "riscv64")]
pub const USER_ASPACE_BASE: u64 = 0x0000_0000_0000_0000;
#[cfg(target_arch = "x86_64")]
pub const USER_ASPACE_BASE: u64 = 0x0000_0000_0100_0000;
/// The size of user address space
pub const USER_ASPACE_SIZE: u64 = (1u64 << 47) - 4096 - USER_ASPACE_BASE;

View File

@ -549,7 +549,7 @@ impl VMObjectPagedInner {
return Ok(CommitResult::Ref(PhysFrame::zero_frame_addr()));
}
// lazy allocate zero frame
let target_frame = PhysFrame::alloc().ok_or(ZxError::NO_MEMORY)?;
let target_frame = PhysFrame::alloc();
kernel_hal::frame_zero_in_range(target_frame.addr(), 0, PAGE_SIZE);
if out_of_range {
// can never be a hidden vmo
@ -628,7 +628,7 @@ impl VMObjectPagedInner {
return Ok(CommitResult::CopyOnWrite(target_frame, need_unmap));
} else if flags.contains(MMUFlags::WRITE) && child_tag.is_split() {
// copy-on-write
let target_frame = PhysFrame::alloc().ok_or(ZxError::NO_MEMORY)?;
let target_frame = PhysFrame::alloc();
kernel_hal::frame_copy(frame.frame.addr(), target_frame.addr());
frame.tag = child_tag;
return Ok(CommitResult::CopyOnWrite(target_frame, true));