forked from rcore-os/zCore
Compare commits
5 Commits
master
...
riscv64-ol
Author | SHA1 | Date |
---|---|---|
![]() |
8566a6993a | |
|
1576b2c5eb | |
![]() |
97ea51da9f | |
![]() |
dfc42fb879 | |
![]() |
17e612659a |
|
@ -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
|
||||
|
|
4
Makefile
4
Makefile
|
@ -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
|
||||
|
|
|
@ -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"
|
|
@ -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
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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>;
|
|
@ -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 }
|
||||
}
|
||||
}
|
|
@ -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 }
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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 }
|
||||
}
|
||||
}
|
|
@ -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};
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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) }
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -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(()));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -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" }
|
||||
|
||||
|
|
|
@ -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到下一条
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
|
@ -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)));
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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!()
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(())
|
||||
}
|
|
@ -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
|
||||
#前511项置0
|
||||
.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
|
||||
|
|
|
@ -8,7 +8,7 @@ BASE_ADDRESS = 0x80200000;
|
|||
*/
|
||||
|
||||
/* opensbi仍旧把kernel放在0x80200000物理内存中 */
|
||||
BASE_ADDRESS = 0xffffffffc0200000;
|
||||
BASE_ADDRESS = 0xffffffff80200000;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue