Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
rcore-os
RCore Tutorial V3
提交
064f1cb5
R
RCore Tutorial V3
项目概览
rcore-os
/
RCore Tutorial V3
上一次同步 1 年多
通知
15
Star
793
Fork
260
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
4
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
RCore Tutorial V3
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
4
Issue
4
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
064f1cb5
编写于
12月 06, 2020
作者:
Y
Yifan Wu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fetching buffer arguments from user space.
上级
3625b757
变更
20
隐藏空白更改
内联
并排
Showing
20 changed file
with
405 addition
and
82 deletion
+405
-82
os/build.rs
os/build.rs
+1
-1
os/src/config.rs
os/src/config.rs
+9
-0
os/src/linker.ld
os/src/linker.ld
+4
-0
os/src/loader.rs
os/src/loader.rs
+23
-2
os/src/main.rs
os/src/main.rs
+4
-5
os/src/mm/address.rs
os/src/mm/address.rs
+4
-0
os/src/mm/memory_set.rs
os/src/mm/memory_set.rs
+144
-22
os/src/mm/mod.rs
os/src/mm/mod.rs
+2
-2
os/src/mm/page_table.rs
os/src/mm/page_table.rs
+29
-8
os/src/syscall/mod.rs
os/src/syscall/mod.rs
+1
-0
os/src/task/context.rs
os/src/task/context.rs
+4
-3
os/src/task/mod.rs
os/src/task/mod.rs
+36
-9
os/src/task/task.rs
os/src/task/task.rs
+60
-0
os/src/trap/context.rs
os/src/trap/context.rs
+18
-1
os/src/trap/mod.rs
os/src/trap/mod.rs
+29
-5
os/src/trap/trap.S
os/src/trap/trap.S
+26
-18
user/src/bin/00power_3.rs
user/src/bin/00power_3.rs
+3
-2
user/src/bin/01power_5.rs
user/src/bin/01power_5.rs
+3
-2
user/src/bin/02power_7.rs
user/src/bin/02power_7.rs
+3
-2
user/src/linker.ld
user/src/linker.ld
+2
-0
未找到文件。
os/build.rs
浏览文件 @
064f1cb5
...
...
@@ -2,7 +2,7 @@ use std::io::{Result, Write};
use
std
::
fs
::{
File
,
read_dir
};
fn
main
()
{
println!
(
"cargo:rerun-if-changed=../user/src/
bin/
"
);
println!
(
"cargo:rerun-if-changed=../user/src/"
);
insert_app_data
()
.unwrap
();
}
...
...
os/src/config.rs
浏览文件 @
064f1cb5
...
...
@@ -8,6 +8,15 @@ pub const MEMORY_END: usize = 0x80800000;
pub
const
PAGE_SIZE
:
usize
=
0x1000
;
pub
const
PAGE_SIZE_BITS
:
usize
=
0xc
;
pub
const
TRAMPOLINE
:
usize
=
usize
::
MAX
-
PAGE_SIZE
+
1
;
pub
const
TRAP_CONTEXT
:
usize
=
TRAMPOLINE
-
PAGE_SIZE
;
/// Return (bottom, top) of a kernel stack in kernel space.
pub
fn
kernel_stack_position
(
app_id
:
usize
)
->
(
usize
,
usize
)
{
let
top
=
TRAMPOLINE
-
app_id
*
(
KERNEL_STACK_SIZE
+
PAGE_SIZE
);
let
bottom
=
top
-
KERNEL_STACK_SIZE
;
(
bottom
,
top
)
}
#[cfg(feature
=
"board_k210"
)]
pub
const
CPU_FREQ
:
usize
=
10000000
;
...
...
os/src/linker.ld
浏览文件 @
064f1cb5
...
...
@@ -10,6 +10,10 @@ SECTIONS
stext = .;
.text : {
*(.text.entry)
. = ALIGN(4K);
strampoline = .;
*(.text.trampoline);
. = ALIGN(4K);
*(.text .text.*)
}
...
...
os/src/loader.rs
浏览文件 @
064f1cb5
...
...
@@ -3,6 +3,7 @@ use crate::task::TaskContext;
use
crate
::
config
::
*
;
use
xmas_elf
::
ElfFile
;
/*
#[repr(align(4096))]
struct KernelStack {
data: [u8; KERNEL_STACK_SIZE],
...
...
@@ -43,7 +44,7 @@ impl UserStack {
self.data.as_ptr() as usize + USER_STACK_SIZE
}
}
*/
fn
get_base_i
(
app_id
:
usize
)
->
usize
{
APP_BASE_ADDRESS
+
app_id
*
APP_SIZE_LIMIT
}
...
...
@@ -53,6 +54,23 @@ pub fn get_num_app() -> usize {
unsafe
{
(
_
num_app
as
usize
as
*
const
usize
)
.read_volatile
()
}
}
pub
fn
get_app_data
(
app_id
:
usize
)
->
&
'static
[
u8
]
{
extern
"C"
{
fn
_
num_app
();
}
let
num_app_ptr
=
_
num_app
as
usize
as
*
const
usize
;
let
num_app
=
get_num_app
();
let
app_start
=
unsafe
{
core
::
slice
::
from_raw_parts
(
num_app_ptr
.add
(
1
),
num_app
+
1
)
};
assert
!
(
app_id
<
num_app
);
unsafe
{
core
::
slice
::
from_raw_parts
(
app_start
[
app_id
]
as
*
const
u8
,
app_start
[
app_id
+
1
]
-
app_start
[
app_id
]
)
}
}
/*
fn debug_elf(start_addr: usize, end_addr: usize) {
let data_array = unsafe {
core::slice::from_raw_parts(start_addr as *const u8, end_addr - start_addr)
...
...
@@ -67,14 +85,16 @@ fn debug_elf(start_addr: usize, end_addr: usize) {
let ph = elf.program_header(i).unwrap();
if ph.get_type().unwrap() == xmas_elf::program::Type::Load {
println!(
"offset={:#x},va={:#x},pa={:#x},filesz={:#x},memsz={:#x},align={:#x}"
,
"offset={:#x},va={:#x},pa={:#x},filesz={:#x},memsz={:#x},align={:#x}
,flag={:?}
",
ph.offset(),
ph.virtual_addr(),
ph.physical_addr(),
ph.file_size(),
ph.mem_size(),
ph.align(),
ph.flags(),
);
//println!("len={:?}", ph.get_data(&elf).unwrap());
}
}
}
...
...
@@ -124,3 +144,4 @@ pub fn init_app_cx(app_id: usize) -> &'static TaskContext {
TaskContext::goto_restore(),
)
}
*/
\ No newline at end of file
os/src/main.rs
浏览文件 @
064f1cb5
...
...
@@ -44,11 +44,10 @@ pub fn rust_main() -> ! {
println!
(
"[kernel] back to world!"
);
mm
::
remap_test
();
trap
::
init
();
loader
::
load_apps
();
loop
{}
trap
::
enable_interrupt
();
trap
::
enable_timer_interrupt
();
timer
::
set_next_trigger
();
//loader::load_apps();
//trap::enable_interrupt();
//trap::enable_timer_interrupt();
//timer::set_next_trigger();
task
::
run_first_task
();
panic!
(
"Unreachable in rust_main!"
);
}
\ No newline at end of file
os/src/mm/address.rs
浏览文件 @
064f1cb5
...
...
@@ -71,6 +71,7 @@ impl VirtAddr {
pub
fn
floor
(
&
self
)
->
VirtPageNum
{
VirtPageNum
(
self
.0
/
PAGE_SIZE
)
}
pub
fn
ceil
(
&
self
)
->
VirtPageNum
{
VirtPageNum
((
self
.0
+
PAGE_SIZE
-
1
)
/
PAGE_SIZE
)
}
pub
fn
page_offset
(
&
self
)
->
usize
{
self
.0
&
(
PAGE_SIZE
-
1
)
}
pub
fn
aligned
(
&
self
)
->
bool
{
self
.page_offset
()
==
0
}
}
impl
From
<
VirtAddr
>
for
VirtPageNum
{
fn
from
(
v
:
VirtAddr
)
->
Self
{
...
...
@@ -85,6 +86,7 @@ impl PhysAddr {
pub
fn
floor
(
&
self
)
->
PhysPageNum
{
PhysPageNum
(
self
.0
/
PAGE_SIZE
)
}
pub
fn
ceil
(
&
self
)
->
PhysPageNum
{
PhysPageNum
((
self
.0
+
PAGE_SIZE
-
1
)
/
PAGE_SIZE
)
}
pub
fn
page_offset
(
&
self
)
->
usize
{
self
.0
&
(
PAGE_SIZE
-
1
)
}
pub
fn
aligned
(
&
self
)
->
bool
{
self
.page_offset
()
==
0
}
}
impl
From
<
PhysAddr
>
for
PhysPageNum
{
fn
from
(
v
:
PhysAddr
)
->
Self
{
...
...
@@ -150,6 +152,8 @@ impl<T> SimpleRange<T> where
assert
!
(
start
<=
end
,
"start {:?} > end {:?}!"
,
start
,
end
);
Self
{
l
:
start
,
r
:
end
}
}
pub
fn
get_start
(
&
self
)
->
T
{
self
.l
}
pub
fn
get_end
(
&
self
)
->
T
{
self
.r
}
}
impl
<
T
>
IntoIterator
for
SimpleRange
<
T
>
where
T
:
StepByOne
+
Copy
+
PartialEq
+
PartialOrd
+
Debug
,
{
...
...
os/src/mm/memory_set.rs
浏览文件 @
064f1cb5
use
super
::{
PageTable
,
PTEFlags
,
VirtAddr
,
VirtPageNum
,
PhysAddr
,
PhysPageNum
,
FrameTracker
,
VPNRange
,
frame_alloc
,
};
use
super
::{
PageTable
,
PageTableEntry
,
PTEFlags
};
use
super
::{
VirtPageNum
,
VirtAddr
,
PhysPageNum
,
PhysAddr
};
use
super
::{
FrameTracker
,
frame_alloc
};
use
super
::{
VPNRange
,
StepByOne
};
use
core
::
ops
::
Range
;
use
alloc
::
collections
::
BTreeMap
;
use
alloc
::
vec
::
Vec
;
...
...
@@ -16,7 +9,14 @@ use riscv::register::satp;
use
alloc
::
sync
::
Arc
;
use
lazy_static
::
*
;
use
spin
::
Mutex
;
use
crate
::
config
::
MEMORY_END
;
use
crate
::
config
::{
MEMORY_END
,
PAGE_SIZE
,
TRAMPOLINE
,
TRAP_CONTEXT
,
USER_STACK_SIZE
};
use
xmas_elf
::
ElfFile
;
extern
"C"
{
fn
stext
();
...
...
@@ -28,6 +28,7 @@ extern "C" {
fn
sbss_with_stack
();
fn
ebss
();
fn
ekernel
();
fn
strampoline
();
}
lazy_static!
{
...
...
@@ -48,12 +49,39 @@ impl MemorySet {
areas
:
Vec
::
new
(),
}
}
fn
push
(
&
mut
self
,
mut
map_area
:
MapArea
)
{
pub
fn
token
(
&
self
)
->
usize
{
self
.page_table
.token
()
}
/// Assume that no conflicts.
pub
fn
insert_framed_area
(
&
mut
self
,
start_va
:
VirtAddr
,
end_va
:
VirtAddr
,
permission
:
MapPermission
)
{
self
.push
(
MapArea
::
new
(
start_va
,
end_va
,
MapType
::
Framed
,
permission
,
),
None
);
}
fn
push
(
&
mut
self
,
mut
map_area
:
MapArea
,
data
:
Option
<&
[
u8
]
>
)
{
map_area
.map
(
&
mut
self
.page_table
);
if
let
Some
(
data
)
=
data
{
map_area
.copy_data
(
&
mut
self
.page_table
,
data
);
}
self
.areas
.push
(
map_area
);
}
/// Mention that trampoline is not collected by areas.
fn
map_trampoline
(
&
mut
self
)
{
self
.page_table
.map
(
VirtAddr
::
from
(
TRAMPOLINE
)
.into
(),
PhysAddr
::
from
(
strampoline
as
usize
)
.into
(),
PTEFlags
::
R
|
PTEFlags
::
X
,
);
}
/// Without kernel stacks.
pub
fn
new_kernel
()
->
Self
{
let
mut
memory_set
=
Self
::
new_bare
();
// map trampoline
memory_set
.map_trampoline
();
// map kernel sections
println!
(
".text [{:#x}, {:#x})"
,
stext
as
usize
,
etext
as
usize
);
println!
(
".rodata [{:#x}, {:#x})"
,
srodata
as
usize
,
erodata
as
usize
);
println!
(
".data [{:#x}, {:#x})"
,
sdata
as
usize
,
edata
as
usize
);
...
...
@@ -64,37 +92,105 @@ impl MemorySet {
(
etext
as
usize
)
.into
(),
MapType
::
Identical
,
MapPermission
::
R
|
MapPermission
::
X
,
));
)
,
None
);
println!
(
"mapping .rodata section"
);
memory_set
.push
(
MapArea
::
new
(
(
srodata
as
usize
)
.into
(),
(
erodata
as
usize
)
.into
(),
MapType
::
Identical
,
MapPermission
::
R
,
));
)
,
None
);
println!
(
"mapping .data section"
);
memory_set
.push
(
MapArea
::
new
(
(
sdata
as
usize
)
.into
(),
(
edata
as
usize
)
.into
(),
MapType
::
Identical
,
MapPermission
::
R
|
MapPermission
::
W
,
));
)
,
None
);
println!
(
"mapping .bss section"
);
memory_set
.push
(
MapArea
::
new
(
(
sbss_with_stack
as
usize
)
.into
(),
(
ebss
as
usize
)
.into
(),
MapType
::
Identical
,
MapPermission
::
R
|
MapPermission
::
W
,
));
)
,
None
);
println!
(
"mapping physical memory"
);
memory_set
.push
(
MapArea
::
new
(
(
ekernel
as
usize
)
.into
(),
MEMORY_END
.into
(),
MapType
::
Identical
,
MapPermission
::
R
|
MapPermission
::
W
,
));
)
,
None
);
memory_set
}
/// Include sections in elf and trampoline and TrapContext and user stack,
/// also returns user_sp and entry point.
pub
fn
from_elf
(
elf_data
:
&
[
u8
])
->
(
Self
,
usize
,
usize
)
{
//println!("into from_elf!");
let
mut
memory_set
=
Self
::
new_bare
();
// map trampoline
//println!("mapping trampoline!");
memory_set
.map_trampoline
();
// map program headers of elf, with U flag
//println!("mapping elf!");
let
elf
=
xmas_elf
::
ElfFile
::
new
(
elf_data
)
.unwrap
();
let
elf_header
=
elf
.header
;
let
magic
=
elf_header
.pt1.magic
;
assert_eq!
(
magic
,
[
0x7f
,
0x45
,
0x4c
,
0x46
],
"invalid elf!"
);
let
ph_count
=
elf_header
.pt2
.ph_count
();
//println!("ph_count = {}", ph_count);
let
mut
max_end_vpn
=
VirtPageNum
(
0
);
for
i
in
0
..
ph_count
{
let
ph
=
elf
.program_header
(
i
)
.unwrap
();
if
ph
.get_type
()
.unwrap
()
==
xmas_elf
::
program
::
Type
::
Load
{
//println!("ph#{},va={},memsz={}", i, ph.virtual_addr(), ph.mem_size());
let
start_va
:
VirtAddr
=
(
ph
.virtual_addr
()
as
usize
)
.into
();
let
end_va
:
VirtAddr
=
((
ph
.virtual_addr
()
+
ph
.mem_size
())
as
usize
)
.into
();
let
mut
map_perm
=
MapPermission
::
U
;
let
ph_flags
=
ph
.flags
();
if
ph_flags
.is_read
()
{
map_perm
|
=
MapPermission
::
R
;
}
if
ph_flags
.is_write
()
{
map_perm
|
=
MapPermission
::
W
;
}
if
ph_flags
.is_execute
()
{
map_perm
|
=
MapPermission
::
X
;
}
//println!("creating MapArea!");
let
map_area
=
MapArea
::
new
(
start_va
,
end_va
,
MapType
::
Framed
,
map_perm
,
);
//println!("end_vpn = {:?}", map_area.vpn_range.get_end());
max_end_vpn
=
map_area
.vpn_range
.get_end
();
//println!("pushing MapArea!");
memory_set
.push
(
map_area
,
Some
(
&
elf
.input
[
ph
.offset
()
as
usize
..
(
ph
.offset
()
+
ph
.file_size
())
as
usize
])
);
}
}
// map user stack with U flags
//println!("mapping user stack!");
let
mut
max_end_va
:
VirtAddr
=
max_end_vpn
.into
();
let
mut
user_stack_bottom
:
usize
=
max_end_va
.into
();
// guard page
user_stack_bottom
+=
PAGE_SIZE
;
let
user_stack_top
=
user_stack_bottom
+
USER_STACK_SIZE
;
//println!("user stack={:#x},{:#x}", user_stack_bottom, user_stack_top);
memory_set
.push
(
MapArea
::
new
(
user_stack_bottom
.into
(),
user_stack_top
.into
(),
MapType
::
Framed
,
MapPermission
::
R
|
MapPermission
::
W
|
MapPermission
::
U
,
),
None
);
// map TrapContext
//println!("mapping TrapContext {:#x},{:#x}", TRAP_CONTEXT, TRAMPOLINE);
memory_set
.push
(
MapArea
::
new
(
TRAP_CONTEXT
.into
(),
TRAMPOLINE
.into
(),
MapType
::
Framed
,
MapPermission
::
R
|
MapPermission
::
W
,
),
None
);
(
memory_set
,
user_stack_top
,
elf
.header.pt2
.entry_point
()
as
usize
)
}
pub
fn
activate
(
&
self
)
{
let
satp
=
self
.page_table
.token
();
unsafe
{
...
...
@@ -102,6 +198,9 @@ impl MemorySet {
llvm_asm!
(
"sfence.vma"
::::
"volatile"
);
}
}
pub
fn
translate
(
&
self
,
vpn
:
VirtPageNum
)
->
Option
<
PageTableEntry
>
{
self
.page_table
.translate
(
vpn
)
}
}
pub
struct
MapArea
{
...
...
@@ -118,9 +217,8 @@ impl MapArea {
map_type
:
MapType
,
map_perm
:
MapPermission
)
->
Self
{
// alignment assertion, limit to kernel remapping
let
start_vpn
:
VirtPageNum
=
start_va
.into
();
let
end_vpn
:
VirtPageNum
=
end_va
.into
();
let
start_vpn
:
VirtPageNum
=
start_va
.floor
();
let
end_vpn
:
VirtPageNum
=
end_va
.ceil
();
Self
{
vpn_range
:
VPNRange
::
new
(
start_vpn
,
end_vpn
),
data_frames
:
BTreeMap
::
new
(),
...
...
@@ -129,7 +227,7 @@ impl MapArea {
}
}
pub
fn
map_one
(
&
mut
self
,
page_table
:
&
mut
PageTable
,
vpn
:
VirtPageNum
)
{
let
pte_flags
=
PTEFlags
::
from_bits
(
self
.map_perm.bits
)
.unwrap
();
let
mut
pte_flags
=
PTEFlags
::
from_bits
(
self
.map_perm.bits
)
.unwrap
();
let
mut
ppn
=
PhysPageNum
(
0
);
match
self
.map_type
{
MapType
::
Identical
=>
{
...
...
@@ -162,8 +260,31 @@ impl MapArea {
self
.unmap_one
(
page_table
,
vpn
);
}
}
/// data: start-aligned but maybe with shorted length
/// assume that all frames were cleared before
pub
fn
copy_data
(
&
mut
self
,
page_table
:
&
mut
PageTable
,
data
:
&
[
u8
])
{
assert_eq!
(
self
.map_type
,
MapType
::
Framed
);
let
mut
start
:
usize
=
0
;
let
mut
current_vpn
=
self
.vpn_range
.get_start
();
let
len
=
data
.len
();
loop
{
let
src
=
&
data
[
start
..
len
.min
(
start
+
PAGE_SIZE
)];
let
dst
=
&
mut
page_table
.translate
(
current_vpn
)
.unwrap
()
.ppn
()
.get_bytes_array
()[
..
src
.len
()];
dst
.copy_from_slice
(
src
);
start
+=
PAGE_SIZE
;
if
start
>=
len
{
break
;
}
current_vpn
.step
();
}
}
}
#[derive(Copy,
Clone,
PartialEq,
Debug)]
pub
enum
MapType
{
Identical
,
Framed
,
...
...
@@ -174,6 +295,7 @@ bitflags! {
const
R
=
1
<<
1
;
const
W
=
1
<<
2
;
const
X
=
1
<<
3
;
const
U
=
1
<<
4
;
}
}
...
...
os/src/mm/mod.rs
浏览文件 @
064f1cb5
...
...
@@ -5,11 +5,11 @@ mod page_table;
mod
memory_set
;
use
page_table
::{
PageTable
,
PTEFlags
};
use
address
::
VPNRange
;
use
address
::
{
VPNRange
,
StepByOne
}
;
pub
use
address
::{
PhysAddr
,
VirtAddr
,
PhysPageNum
,
VirtPageNum
};
pub
use
frame_allocator
::{
FrameTracker
,
frame_alloc
};
pub
use
page_table
::{
PageTableEntry
};
pub
use
memory_set
::{
MemorySet
,
KERNEL_SPACE
};
pub
use
memory_set
::{
MemorySet
,
KERNEL_SPACE
,
MapPermission
};
pub
use
memory_set
::
remap_test
;
pub
fn
init
()
{
...
...
os/src/mm/page_table.rs
浏览文件 @
064f1cb5
...
...
@@ -68,7 +68,14 @@ impl PageTable {
frames
:
vec!
[
frame
],
}
}
fn
find_pte
(
&
mut
self
,
vpn
:
VirtPageNum
,
create
:
bool
)
->
Option
<&
mut
PageTableEntry
>
{
/// Temporarily used to get arguments from user space.
pub
fn
from_root_ppn
(
root_ppn
:
PhysPageNum
)
->
Self
{
Self
{
root_ppn
,
frames
:
Vec
::
new
(),
}
}
fn
find_pte_create
(
&
mut
self
,
vpn
:
VirtPageNum
)
->
Option
<&
mut
PageTableEntry
>
{
let
idxs
=
vpn
.indexes
();
let
mut
ppn
=
self
.root_ppn
;
let
mut
result
:
Option
<&
mut
PageTableEntry
>
=
None
;
...
...
@@ -79,9 +86,6 @@ impl PageTable {
break
;
}
if
!
pte
.is_valid
()
{
if
!
create
{
return
None
;
}
let
frame
=
frame_alloc
()
.unwrap
();
*
pte
=
PageTableEntry
::
new
(
frame
.ppn
,
PTEFlags
::
V
);
self
.frames
.push
(
frame
);
...
...
@@ -90,19 +94,36 @@ impl PageTable {
}
result
}
fn
find_pte
(
&
self
,
vpn
:
VirtPageNum
)
->
Option
<&
PageTableEntry
>
{
let
idxs
=
vpn
.indexes
();
let
mut
ppn
=
self
.root_ppn
;
let
mut
result
:
Option
<&
PageTableEntry
>
=
None
;
for
i
in
0
..
3
{
let
pte
=
&
ppn
.get_pte_array
()[
idxs
[
i
]];
if
i
==
2
{
result
=
Some
(
pte
);
break
;
}
if
!
pte
.is_valid
()
{
return
None
;
}
ppn
=
pte
.ppn
();
}
result
}
pub
fn
map
(
&
mut
self
,
vpn
:
VirtPageNum
,
ppn
:
PhysPageNum
,
flags
:
PTEFlags
)
{
//println!("mapping {:?} {:?}", vpn, ppn);
let
pte
=
self
.find_pte
(
vpn
,
true
)
.unwrap
();
let
pte
=
self
.find_pte
_create
(
vpn
)
.unwrap
();
assert
!
(
!
pte
.is_valid
(),
"vpn {:?} is mapped before mapping"
,
vpn
);
*
pte
=
PageTableEntry
::
new
(
ppn
,
flags
|
PTEFlags
::
V
);
}
pub
fn
unmap
(
&
mut
self
,
vpn
:
VirtPageNum
)
{
let
pte
=
self
.find_pte
(
vpn
,
false
)
.unwrap
();
let
pte
=
self
.find_pte
_create
(
vpn
)
.unwrap
();
assert
!
(
pte
.is_valid
(),
"vpn {:?} is invalid before unmapping"
,
vpn
);
*
pte
=
PageTableEntry
::
empty
();
}
pub
fn
translate
(
&
mut
self
,
vpn
:
VirtPageNum
)
->
Option
<
PageTableEntry
>
{
self
.find_pte
(
vpn
,
false
)
pub
fn
translate
(
&
self
,
vpn
:
VirtPageNum
)
->
Option
<
PageTableEntry
>
{
self
.find_pte
(
vpn
)
.map
(|
pte
|
{
pte
.clone
()})
}
pub
fn
token
(
&
self
)
->
usize
{
...
...
os/src/syscall/mod.rs
浏览文件 @
064f1cb5
...
...
@@ -10,6 +10,7 @@ use fs::*;
use
process
::
*
;
pub
fn
syscall
(
syscall_id
:
usize
,
args
:
[
usize
;
3
])
->
isize
{
println!
(
"into syscall!"
);
match
syscall_id
{
SYSCALL_WRITE
=>
sys_write
(
args
[
0
],
args
[
1
]
as
*
const
u8
,
args
[
2
]),
SYSCALL_EXIT
=>
sys_exit
(
args
[
0
]
as
i32
),
...
...
os/src/task/context.rs
浏览文件 @
064f1cb5
use
crate
::
trap
::
trap_return
;
#[repr(C)]
pub
struct
TaskContext
{
ra
:
usize
,
...
...
@@ -5,10 +7,9 @@ pub struct TaskContext {
}
impl
TaskContext
{
pub
fn
goto_restore
()
->
Self
{
extern
"C"
{
fn
__
restore
();
}
pub
fn
goto_trap_return
()
->
Self
{
Self
{
ra
:
__
restore
as
usize
,
ra
:
trap_return
as
usize
,
s
:
[
0
;
12
],
}
}
...
...
os/src/task/mod.rs
浏览文件 @
064f1cb5
...
...
@@ -3,11 +3,13 @@ mod switch;
mod
task
;
use
crate
::
config
::
MAX_APP_NUM
;
use
crate
::
loader
::{
get_num_app
,
init_app_cx
};
use
crate
::
loader
::{
get_num_app
,
get_app_data
};
use
crate
::
trap
::
TrapContext
;
use
core
::
cell
::
RefCell
;
use
lazy_static
::
*
;
use
switch
::
__
switch
;
use
task
::{
TaskControlBlock
,
TaskStatus
};
use
alloc
::
vec
::
Vec
;
pub
use
context
::
TaskContext
;
...
...
@@ -17,7 +19,7 @@ pub struct TaskManager {
}
struct
TaskManagerInner
{
tasks
:
[
TaskControlBlock
;
MAX_APP_NUM
]
,
tasks
:
Vec
<
TaskControlBlock
>
,
current_task
:
usize
,
}
...
...
@@ -25,14 +27,16 @@ unsafe impl Sync for TaskManager {}
lazy_static!
{
pub
static
ref
TASK_MANAGER
:
TaskManager
=
{
println!
(
"init TASK_MANAGER"
);
let
num_app
=
get_num_app
();
let
mut
tasks
=
[
TaskControlBlock
{
task_cx_ptr
:
0
,
task_status
:
TaskStatus
::
UnInit
};
MAX_APP_NUM
];
println!
(
"num_app = {}"
,
num_app
);
let
mut
tasks
:
Vec
<
TaskControlBlock
>
=
Vec
::
new
();
for
i
in
0
..
num_app
{
tasks
[
i
]
.task_cx_ptr
=
init_app_cx
(
i
)
as
*
const
_
as
usize
;
tasks
[
i
]
.task_status
=
TaskStatus
::
Ready
;
println!
(
"creating TCB #{}"
,
i
);
tasks
.push
(
TaskControlBlock
::
new
(
get_app_data
(
i
),
i
,
));
}
TaskManager
{
num_app
,
...
...
@@ -46,11 +50,14 @@ lazy_static! {
impl
TaskManager
{
fn
run_first_task
(
&
self
)
{
println!
(
"into TaskManager::run_first_task"
);
self
.inner
.borrow_mut
()
.tasks
[
0
]
.task_status
=
TaskStatus
::
Running
;
let
next_task_cx
=
self
.inner
.borrow
()
.tasks
[
0
]
.get_task_cx_ptr2
();
println!
(
"next_task_cx={:p} {:#x}"
,
next_task_cx
,
unsafe
{
next_task_cx
.read_volatile
()
});
let
_u
nused
:
usize
=
0
;
unsafe
{
__
switch
(
&
0u
size
as
*
const
_
,
&
_u
nused
as
*
const
_
,
next_task_cx
,
);
}
...
...
@@ -78,6 +85,18 @@ impl TaskManager {
})
}
fn
get_current_token
(
&
self
)
->
usize
{
let
inner
=
self
.inner
.borrow
();
let
current
=
inner
.current_task
;
inner
.tasks
[
current
]
.get_user_token
()
}
fn
get_current_trap_cx
(
&
self
)
->
&
mut
TrapContext
{
let
inner
=
self
.inner
.borrow
();
let
current
=
inner
.current_task
;
inner
.tasks
[
current
]
.get_trap_cx
()
}
fn
run_next_task
(
&
self
)
{
if
let
Some
(
next
)
=
self
.find_next_task
()
{
let
mut
inner
=
self
.inner
.borrow_mut
();
...
...
@@ -123,4 +142,12 @@ pub fn suspend_current_and_run_next() {
pub
fn
exit_current_and_run_next
()
{
mark_current_exited
();
run_next_task
();
}
pub
fn
current_user_token
()
->
usize
{
TASK_MANAGER
.get_current_token
()
}
pub
fn
current_trap_cx
()
->
&
'static
mut
TrapContext
{
TASK_MANAGER
.get_current_trap_cx
()
}
\ No newline at end of file
os/src/task/task.rs
浏览文件 @
064f1cb5
use
crate
::
mm
::{
MemorySet
,
MapPermission
,
PhysPageNum
,
KERNEL_SPACE
,
VirtAddr
};
use
crate
::
trap
::{
TrapContext
,
trap_handler
};
use
crate
::
config
::{
TRAP_CONTEXT
,
kernel_stack_position
};
use
super
::
TaskContext
;
pub
struct
TaskControlBlock
{
pub
task_cx_ptr
:
usize
,
pub
task_status
:
TaskStatus
,
pub
memory_set
:
MemorySet
,
pub
trap_cx_ppn
:
PhysPageNum
,
pub
base_size
:
usize
,
}
impl
TaskControlBlock
{
pub
fn
get_task_cx_ptr2
(
&
self
)
->
*
const
usize
{
&
self
.task_cx_ptr
as
*
const
usize
}
pub
fn
get_trap_cx
(
&
self
)
->
&
'static
mut
TrapContext
{
self
.trap_cx_ppn
.get_mut
()
}
pub
fn
get_user_token
(
&
self
)
->
usize
{
self
.memory_set
.token
()
}
pub
fn
new
(
elf_data
:
&
[
u8
],
app_id
:
usize
)
->
Self
{
//println!("into TCB::new");
// memory_set with elf program headers/trampoline/trap context/user stack
let
(
memory_set
,
user_sp
,
entry_point
)
=
MemorySet
::
from_elf
(
elf_data
);
//println!("user_sp={:#x},entry_point={:#}", user_sp, entry_point);
let
trap_cx_ppn
=
memory_set
.translate
(
VirtAddr
::
from
(
TRAP_CONTEXT
)
.into
())
.unwrap
()
.ppn
();
//println!("trap_cx_ppn={:?}", trap_cx_ppn);
let
task_status
=
TaskStatus
::
Ready
;
// map a kernel-stack in kernel space
//println!("mapping kernel-stack!");
let
(
kernel_stack_bottom
,
kernel_stack_top
)
=
kernel_stack_position
(
app_id
);
//println!("kernel_stack={:#x},{:#x}", kernel_stack_bottom, kernel_stack_top);
KERNEL_SPACE
.lock
()
.insert_framed_area
(
kernel_stack_bottom
.into
(),
kernel_stack_top
.into
(),
MapPermission
::
R
|
MapPermission
::
W
,
);
let
task_cx_ptr
=
(
kernel_stack_top
-
core
::
mem
::
size_of
::
<
TaskContext
>
())
as
*
mut
TaskContext
;
//println!("task_cx size={}", core::mem::size_of::<TaskContext>());
//println!("init task_cx, ptr={:p}", task_cx_ptr);
unsafe
{
*
task_cx_ptr
=
TaskContext
::
goto_trap_return
();
}
//println!("after init task_cx");
let
task_control_block
=
Self
{
task_cx_ptr
:
task_cx_ptr
as
usize
,
task_status
,
memory_set
,
trap_cx_ppn
,
base_size
:
user_sp
,
};
// prepare TrapContext in user space
//println!("preparing trap_cx");
let
trap_cx
=
task_control_block
.get_trap_cx
();
*
trap_cx
=
TrapContext
::
app_init_context
(
entry_point
,
user_sp
,
KERNEL_SPACE
.lock
()
.token
(),
kernel_stack_top
,
trap_handler
as
usize
,
);
task_control_block
}
}
#[derive(Copy,
Clone,
PartialEq)]
...
...
os/src/trap/context.rs
浏览文件 @
064f1cb5
...
...
@@ -5,17 +5,34 @@ pub struct TrapContext {
pub
x
:
[
usize
;
32
],
pub
sstatus
:
Sstatus
,
pub
sepc
:
usize
,
pub
kernel_satp
:
usize
,
pub
kernel_sp
:
usize
,
pub
trap_handler
:
usize
,
}
impl
TrapContext
{
pub
fn
set_sp
(
&
mut
self
,
sp
:
usize
)
{
self
.x
[
2
]
=
sp
;
}
pub
fn
app_init_context
(
entry
:
usize
,
sp
:
usize
)
->
Self
{
pub
fn
app_init_context
(
entry
:
usize
,
sp
:
usize
,
kernel_satp
:
usize
,
kernel_sp
:
usize
,
trap_handler
:
usize
,
)
->
Self
{
let
mut
sstatus
=
sstatus
::
read
();
sstatus
.set_spp
(
SPP
::
User
);
let
mut
temp_sstatus
:
usize
;
unsafe
{
llvm_asm!
(
"csrr $0, sstatus"
:
"=r"
(
temp_sstatus
)
:::
"volatile"
);
}
println!
(
"sstatus={:#x}"
,
temp_sstatus
);
let
mut
cx
=
Self
{
x
:
[
0
;
32
],
sstatus
,
sepc
:
entry
,
kernel_satp
,
kernel_sp
,
trap_handler
,
};
cx
.set_sp
(
sp
);
cx
...
...
os/src/trap/mod.rs
浏览文件 @
064f1cb5
...
...
@@ -17,15 +17,17 @@ use crate::syscall::syscall;
use
crate
::
task
::{
exit_current_and_run_next
,
suspend_current_and_run_next
,
current_user_token
,
current_trap_cx
,
};
use
crate
::
timer
::
set_next_trigger
;
use
crate
::
config
::{
TRAP_CONTEXT
,
TRAMPOLINE
};
global_asm!
(
include_str!
(
"trap.S"
));
pub
fn
init
()
{
extern
"C"
{
fn
__
alltraps
();
}
unsafe
{
stvec
::
write
(
__
alltraps
as
usize
,
TrapMode
::
Direct
);
stvec
::
write
(
TRAMPOLINE
,
TrapMode
::
Direct
);
}
}
...
...
@@ -38,11 +40,14 @@ pub fn enable_timer_interrupt() {
}
#[no_mangle]
pub
fn
trap_handler
(
cx
:
&
mut
TrapContext
)
->
&
mut
TrapContext
{
pub
fn
trap_handler
()
->
!
{
println!
(
"into trap_handler!"
);
let
cx
=
current_trap_cx
();
let
scause
=
scause
::
read
();
let
stval
=
stval
::
read
();
match
scause
.cause
()
{
Trap
::
Exception
(
Exception
::
UserEnvCall
)
=>
{
println!
(
"found UserEnvCall!"
);
cx
.sepc
+=
4
;
cx
.x
[
10
]
=
syscall
(
cx
.x
[
17
],
[
cx
.x
[
10
],
cx
.x
[
11
],
cx
.x
[
12
]])
as
usize
;
}
...
...
@@ -63,7 +68,26 @@ pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext {
panic!
(
"Unsupported trap {:?}, stval = {:#x}!"
,
scause
.cause
(),
stval
);
}
}
cx
trap_return
();
}
pub
use
context
::
TrapContext
;
\ No newline at end of file
#[no_mangle]
pub
fn
trap_return
()
->
!
{
println!
(
"into trap_return"
);
let
trap_cx_ptr
=
TRAP_CONTEXT
;
let
user_satp
=
current_user_token
();
println!
(
"trap_cx_ptr={:#x}, user_satp={:#x}"
,
trap_cx_ptr
,
user_satp
);
extern
"C"
{
fn
__
alltraps
();
fn
__
restore
();
}
let
restore_va
=
__
restore
as
usize
-
__
alltraps
as
usize
+
TRAMPOLINE
;
println!
(
"__alltraps={:#x},__restore={:#x}"
,
__
alltraps
as
usize
,
__
restore
as
usize
);
println!
(
"restore_va={:#x}"
,
restore_va
);
unsafe
{
llvm_asm!
(
"jr $0"
::
"r"
(
restore_va
),
"{a0}"
(
trap_cx_ptr
),
"{a1}"
(
user_satp
)
::
"volatile"
);
}
panic!
(
"Unreachable in back_to_user!"
);
}
pub
use
context
::{
TrapContext
};
os/src/trap/trap.S
浏览文件 @
064f1cb5
...
...
@@ -5,16 +5,14 @@
.
macro
LOAD_GP
n
ld
x
\
n
,
\
n
*
8
(
sp
)
.
endm
.
section
.
text
.
section
.
text
.
trampoline
.
globl
__alltraps
.
globl
__restore
.
align
2
__alltraps
:
csrrw
sp
,
sscratch
,
sp
#
now
sp
->
kernel
stack
,
sscratch
->
user
stack
#
allocate
a
TrapContext
on
kernel
stack
addi
sp
,
sp
,
-
34
*
8
#
save
general
-
purpose
registers
#
now
sp
->*
TrapContext
in
user
space
,
sscratch
->
user
stack
#
save
other
general
purpose
registers
sd
x1
,
1
*
8
(
sp
)
#
skip
sp
(
x2
),
we
will
save
it
later
sd
x3
,
3
*
8
(
sp
)
...
...
@@ -25,28 +23,40 @@ __alltraps:
SAVE_GP
%
n
.
set
n
,
n
+
1
.
endr
#
we
can
use
t0
/
t1
/
t2
freely
,
because
they
were
saved
on
kernel
stack
#
we
can
use
t0
/
t1
/
t2
freely
,
because
they
have
been
saved
in
TrapContext
csrr
t0
,
sstatus
csrr
t1
,
sepc
sd
t0
,
32
*
8
(
sp
)
sd
t1
,
33
*
8
(
sp
)
#
read
user
stack
from
sscratch
and
save
it
on
the
kernel
stack
#
read
user
stack
from
sscratch
and
save
it
in
TrapContext
csrr
t2
,
sscratch
sd
t2
,
2
*
8
(
sp
)
#
set
input
argument
of
trap_handler
(
cx
:
&
mut
TrapContext
)
mv
a0
,
sp
call
trap_handler
#
load
kernel_satp
into
t0
ld
t0
,
34
*
8
(
sp
)
#
load
trap_handler
into
t1
ld
t1
,
36
*
8
(
sp
)
#
move
to
kernel_sp
ld
sp
,
35
*
8
(
sp
)
#
switch
to
kernel
space
csrw
satp
,
t0
sfence.vma
#
jump
to
trap_handler
jr
t1
__restore
:
#
now
sp
->
kernel
stack
(
after
allocated
),
sscratch
->
user
stack
#
a0
:
*
TrapContext
in
user
space
(
Constant
)
; a1: user space token
#
switch
to
user
space
csrw
satp
,
a1
sfence.vma
csrw
sscratch
,
a0
mv
sp
,
a0
#
now
sp
points
to
TrapContext
in
user
space
,
start
restoring
based
on
it
#
restore
sstatus
/
sepc
ld
t0
,
32
*
8
(
sp
)
ld
t1
,
33
*
8
(
sp
)
ld
t2
,
2
*
8
(
sp
)
csrw
sstatus
,
t0
csrw
sepc
,
t1
csrw
sscratch
,
t2
#
restore
general
-
purpuse
registers
except
sp
/
tp
#
restore
general
purpose
registers
except
x0
/
sp
/
tp
ld
x1
,
1
*
8
(
sp
)
ld
x3
,
3
*
8
(
sp
)
.
set
n
,
5
...
...
@@ -54,8 +64,6 @@ __restore:
LOAD_GP
%
n
.
set
n
,
n
+
1
.
endr
#
release
TrapContext
on
kernel
stack
addi
sp
,
sp
,
34
*
8
#
now
sp
->
kernel
stack
,
sscratch
->
user
stack
csrrw
sp
,
sscratch
,
sp
#
back
to
user
stack
ld
sp
,
2
*
8
(
sp
)
sret
user/src/bin/00power_3.rs
浏览文件 @
064f1cb5
...
...
@@ -6,12 +6,13 @@ extern crate user_lib;
const
LEN
:
usize
=
100
;
static
mut
s
:
[
u64
;
LEN
]
=
[
0u64
;
LEN
];
#[no_mangle]
fn
main
()
->
i32
{
unsafe
fn
main
()
->
i32
{
let
p
=
3u64
;
let
m
=
998244353u64
;
let
iter
:
usize
=
100000
;
let
mut
s
=
[
0u64
;
LEN
];
let
mut
cur
=
0u
size
;
s
[
cur
]
=
1
;
for
i
in
1
..=
iter
{
...
...
user/src/bin/01power_5.rs
浏览文件 @
064f1cb5
...
...
@@ -6,12 +6,13 @@ extern crate user_lib;
const
LEN
:
usize
=
100
;
static
mut
s
:
[
u64
;
LEN
]
=
[
0u64
;
LEN
];
#[no_mangle]
fn
main
()
->
i32
{
unsafe
fn
main
()
->
i32
{
let
p
=
5u64
;
let
m
=
998244353u64
;
let
iter
:
usize
=
70000
;
let
mut
s
=
[
0u64
;
LEN
];
let
mut
cur
=
0u
size
;
s
[
cur
]
=
1
;
for
i
in
1
..=
iter
{
...
...
user/src/bin/02power_7.rs
浏览文件 @
064f1cb5
...
...
@@ -6,12 +6,13 @@ extern crate user_lib;
const
LEN
:
usize
=
100
;
static
mut
s
:
[
u64
;
LEN
]
=
[
0u64
;
LEN
];
#[no_mangle]
fn
main
()
->
i32
{
unsafe
fn
main
()
->
i32
{
let
p
=
7u64
;
let
m
=
998244353u64
;
let
iter
:
usize
=
80000
;
let
mut
s
=
[
0u64
;
LEN
];
let
mut
cur
=
0u
size
;
s
[
cur
]
=
1
;
for
i
in
1
..=
iter
{
...
...
user/src/linker.ld
浏览文件 @
064f1cb5
...
...
@@ -11,9 +11,11 @@ SECTIONS
*(.text.entry)
*(.text .text.*)
}
. = ALIGN(4K);
.rodata : {
*(.rodata .rodata.*)
}
. = ALIGN(4K);
.data : {
*(.data .data.*)
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录