Skip to content

Commit 86abde4

Browse files
wyfcyxwangrunji0408
authored andcommitted
chk-ch8-part4
1 parent 99fa0b5 commit 86abde4

17 files changed

+293
-17
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
os/target
22
usr/rust/target
3+
os/src/link_user.S
34
Cargo.lock

Diff for: os/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ edition = "2018"
1010
riscv = { git = "https://github.com/rcore-os/riscv", features = ["inline-asm"] }
1111
spin = "0.5.2"
1212
buddy_system_allocator = "0.3"
13-
13+
xmas-elf = "0.6"

Diff for: os/Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ env:
1313
rustup component add llvm-tools-preview rustfmt
1414
rustup target add $(target)
1515

16+
export USER_IMG = ../usr/rust/target/$(target)/debug/hello_world
17+
1618
kernel:
1719
cargo build
1820

Diff for: os/build.rs

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use std::fs::File;
2+
use std::io::{Result, Write};
3+
4+
fn main() {
5+
println!("cargo:rerun-if-env-changed=USER_IMG");
6+
if let Ok(user_img) = std::env::var("USER_IMG") {
7+
println!("cargo:rerun-if-changed={}", user_img);
8+
}
9+
gen_link_user_asm().unwrap();
10+
}
11+
12+
/// Generate assembly file for linking user image
13+
fn gen_link_user_asm() -> Result<()> {
14+
let mut f = File::create("src/link_user.S").unwrap();
15+
let user_img = std::env::var("USER_IMG").unwrap();
16+
17+
writeln!(f, "# generated by build.rs - do not edit")?;
18+
writeln!(f, r#"
19+
.section .data
20+
.global _user_img_start
21+
.global _user_img_end
22+
_user_img_start:
23+
.incbin "{}"
24+
_user_img_end:
25+
"#, user_img)?;
26+
Ok(())
27+
}

Diff for: os/src/consts.rs

+3
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ pub const PHYSICAL_MEMORY_OFFSET: usize = 0xffffffff40000000;
1313
pub const PAGE_SIZE: usize = 4096;
1414

1515
pub const KERNEL_STACK_SIZE: usize = 0x80000;
16+
17+
pub const USER_STACK_SIZE: usize = 0x80000;
18+
pub const USER_STACK_OFFSET: usize = 0xffffffff00000000;

Diff for: os/src/context.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,15 @@ impl Context {
4646
contextContent.tf.x[11] = args[1];
4747
contextContent.tf.x[12] = args[2];
4848
}
49-
49+
50+
pub unsafe fn new_user_thread(
51+
entry: usize,
52+
ustack_top: usize,
53+
kstack_top: usize,
54+
satp: usize
55+
) -> Self {
56+
ContextContent::new_user_thread(entry, ustack_top, satp).push_at(kstack_top)
57+
}
5058
}
5159

5260
#[repr(C)]
@@ -86,6 +94,28 @@ impl ContextContent {
8694
content
8795
}
8896

97+
fn new_user_thread(
98+
entry: usize,
99+
ustack_top: usize,
100+
satp: usize
101+
) -> Self {
102+
ContextContent {
103+
ra: __trapret as usize,
104+
satp,
105+
s: [0; 12],
106+
tf: {
107+
let mut tf: TrapFrame = unsafe { zeroed() };
108+
tf.x[2] = ustack_top;
109+
tf.sepc = entry;
110+
tf.sstatus = sstatus::read();
111+
tf.sstatus.set_spie(true);
112+
tf.sstatus.set_sie(false);
113+
tf.sstatus.set_spp(sstatus::SPP::User);
114+
tf
115+
}
116+
}
117+
}
118+
89119
unsafe fn push_at(self, stack_top: usize) -> Context {
90120
let ptr = (stack_top as *mut ContextContent).sub(1);
91121
*ptr = self;

Diff for: os/src/init.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
global_asm!(include_str!("boot/entry64.asm"));
2+
global_asm!(include_str!("link_user.S"));
23

34
use crate::consts::*;
45
use crate::memory::{

Diff for: os/src/interrupt.rs

+11
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ pub fn rust_trap(tf: &mut TrapFrame) {
4040
Trap::Exception(Exception::InstructionPageFault) => page_fault(tf),
4141
Trap::Exception(Exception::LoadPageFault) => page_fault(tf),
4242
Trap::Exception(Exception::StorePageFault) => page_fault(tf),
43+
Trap::Exception(Exception::UserEnvCall) => syscall(tf),
4344
_ => panic!("undefined trap!")
4445
}
4546
}
@@ -58,6 +59,16 @@ fn page_fault(tf: &mut TrapFrame) {
5859
panic!("page fault!");
5960
}
6061

62+
fn syscall(tf: &mut TrapFrame) {
63+
tf.sepc += 4;
64+
let ret = crate::syscall::syscall(
65+
tf.x[17],
66+
[tf.x[10], tf.x[11], tf.x[12]],
67+
tf
68+
);
69+
tf.x[10] = ret as usize;
70+
}
71+
6172
#[inline(always)]
6273
pub fn disable_and_store() -> usize {
6374
let sstatus: usize;

Diff for: os/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ mod timer;
1818
mod consts;
1919
mod memory;
2020
mod process;
21+
mod syscall;

Diff for: os/src/memory/memory_set/area.rs

+15
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,19 @@ impl MemoryArea {
3939
attr : attr,
4040
}
4141
}
42+
43+
pub fn page_copy(&self, pt: &mut PageTableImpl, src: usize, length: usize) {
44+
let mut l = length;
45+
let mut s = src;
46+
for page in PageRange::new(self.start, self.end) {
47+
self.handler.page_copy(
48+
pt,
49+
page,
50+
s,
51+
if l < PAGE_SIZE { l } else { PAGE_SIZE },
52+
);
53+
s += PAGE_SIZE;
54+
if l >= PAGE_SIZE { l -= PAGE_SIZE; }
55+
}
56+
}
4257
}

Diff for: os/src/memory/memory_set/handler.rs

+47-1
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ use super::attr::MemoryAttr;
33
use crate::memory::alloc_frame;
44
use core::fmt::Debug;
55
use alloc::boxed::Box;
6-
6+
use crate::memory::access_pa_via_va;
7+
use crate::consts::PAGE_SIZE;
78

89
pub trait MemoryHandler: Debug + 'static {
910
fn box_clone(&self) -> Box<dyn MemoryHandler>;
1011
fn map(&self, pt: &mut PageTableImpl, va: usize, attr: &MemoryAttr);
1112
fn unmap(&self, pt: &mut PageTableImpl, va: usize);
13+
fn page_copy(&self, pt: &mut PageTableImpl, va: usize, src: usize, length: usize);
1214
}
1315

1416
impl Clone for Box<dyn MemoryHandler> {
@@ -32,6 +34,29 @@ impl MemoryHandler for Linear {
3234
fn unmap(&self, pt: &mut PageTableImpl, va: usize) {
3335
pt.unmap(va);
3436
}
37+
fn page_copy(&self, pt: &mut PageTableImpl, va: usize, src: usize, length: usize) {
38+
let pa = pt.get_entry(va)
39+
.expect("get pa error!")
40+
.0
41+
.addr()
42+
.as_usize();
43+
assert!(va == access_pa_via_va(pa));
44+
assert!(va == pa + self.offset);
45+
unsafe {
46+
let dst = core::slice::from_raw_parts_mut(
47+
va as *mut u8,
48+
PAGE_SIZE,
49+
);
50+
if length > 0 {
51+
let src = core::slice::from_raw_parts(
52+
src as *const u8,
53+
PAGE_SIZE,
54+
);
55+
for i in 0..length { dst[i] = src[i]; }
56+
}
57+
for i in length..PAGE_SIZE { dst[i] = 0; }
58+
}
59+
}
3560
}
3661

3762
#[derive(Debug, Clone)]
@@ -55,4 +80,25 @@ impl MemoryHandler for ByFrame {
5580
fn unmap(&self, pt: &mut PageTableImpl, va: usize) {
5681
pt.unmap(va);
5782
}
83+
fn page_copy(&self, pt: &mut PageTableImpl, va: usize, src: usize, length: usize) {
84+
let pa = pt.get_entry(va)
85+
.expect("get pa error!")
86+
.0
87+
.addr()
88+
.as_usize();
89+
unsafe {
90+
let dst = core::slice::from_raw_parts_mut(
91+
access_pa_via_va(pa) as *mut u8,
92+
PAGE_SIZE,
93+
);
94+
if length > 0 {
95+
let src = core::slice::from_raw_parts(
96+
src as *const u8,
97+
PAGE_SIZE,
98+
);
99+
for i in 0..length { dst[i] = src[i]; }
100+
}
101+
for i in length..PAGE_SIZE { dst[i] = 0; }
102+
}
103+
}
58104
}

Diff for: os/src/memory/memory_set/mod.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,17 @@ pub struct MemorySet {
2222
}
2323

2424
impl MemorySet {
25-
pub fn push(&mut self, start: usize, end: usize, attr: MemoryAttr, handler: impl MemoryHandler) {
25+
pub fn push(&mut self, start: usize, end: usize, attr: MemoryAttr, handler: impl MemoryHandler, data: Option<(usize, usize)>) {
2626
assert!(start <= end, "invalid memory area!");
2727
assert!(self.test_free_area(start, end), "memory area overlap!");
2828
let area = MemoryArea::new(start, end, Box::new(handler), attr);
2929
area.map(&mut self.page_table);
30+
if let Some((src, length)) = data {
31+
area.page_copy(&mut self.page_table, src, length);
32+
}
3033
self.areas.push(area);
31-
}
34+
35+
}
3236
fn test_free_area(&self, start: usize, end: usize) -> bool {
3337
self.areas
3438
.iter()
@@ -66,34 +70,42 @@ impl MemorySet {
6670
etext as usize,
6771
MemoryAttr::new().set_readonly().set_execute(),
6872
Linear::new(offset),
73+
None,
6974
);
7075
// .rodata R
7176
self.push(
7277
srodata as usize,
7378
erodata as usize,
7479
MemoryAttr::new().set_readonly(),
7580
Linear::new(offset),
81+
None,
7682
);
7783
// .data R|W
7884
self.push(
7985
sdata as usize,
8086
edata as usize,
8187
MemoryAttr::new(),
82-
Linear::new(offset)
88+
Linear::new(offset),
89+
None,
8390
);
8491
// .bss R|W
8592
self.push(
8693
sbss as usize,
8794
ebss as usize,
8895
MemoryAttr::new(),
89-
Linear::new(offset)
96+
Linear::new(offset),
97+
None,
9098
);
9199
// 物理内存 R|W
92100
self.push(
93101
(end as usize / PAGE_SIZE + 1) * PAGE_SIZE,
94102
access_pa_via_va(PHYSICAL_MEMORY_END),
95103
MemoryAttr::new(),
96104
Linear::new(offset),
105+
None,
97106
);
98107
}
108+
pub fn token(&self) -> usize {
109+
self.page_table.token()
110+
}
99111
}

Diff for: os/src/memory/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ pub fn kernel_remap() {
5757
bootstacktop as usize,
5858
MemoryAttr::new(),
5959
Linear::new(PHYSICAL_MEMORY_OFFSET),
60+
None,
6061
);
6162

6263
unsafe {

Diff for: os/src/memory/paging.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::memory::{
2121
access_pa_via_va
2222
};
2323

24-
pub struct PageEntry(&'static mut PageTableEntry, Page);
24+
pub struct PageEntry(pub &'static mut PageTableEntry, Page);
2525

2626
impl PageEntry {
2727
pub fn update(&mut self) {
@@ -115,7 +115,7 @@ impl PageTableImpl {
115115
flush.flush();
116116
}
117117

118-
fn get_entry(&mut self, va: usize) -> Option<&mut PageEntry> {
118+
pub fn get_entry(&mut self, va: usize) -> Option<&mut PageEntry> {
119119
let page = Page::of_addr(VirtAddr::new(va));
120120
if let Ok(e) = self.page_table.ref_entry(page.clone()) {
121121
let e = unsafe { &mut *(e as *mut PageTableEntry) };

Diff for: os/src/process/mod.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,15 @@ use scheduler::RRScheduler;
99
use thread_pool::ThreadPool;
1010
use alloc::boxed::Box;
1111

12+
1213
pub type Tid = usize;
1314
pub type ExitCode = usize;
1415

1516

1617
static CPU: Processor = Processor::new();
1718

18-
19-
#[no_mangle]
20-
pub extern "C" fn temp_thread(from_thread: &mut Thread, current_thread: &mut Thread) {
21-
println!("I'm leaving soon, but I still want to say: Hello world!");
22-
current_thread.switch_to(from_thread);
23-
}
24-
2519
pub fn init() {
26-
let scheduler = RRScheduler::new(1);
20+
let scheduler = RRScheduler::new(2);
2721
let thread_pool = ThreadPool::new(100, Box::new(scheduler));
2822
let idle = Thread::new_kernel(Processor::idle_main as usize);
2923
idle.append_initial_arguments([&CPU as *const Processor as usize, 0, 0]);
@@ -36,6 +30,20 @@ pub fn init() {
3630
thread
3731
});
3832
}
33+
34+
extern "C" {
35+
fn _user_img_start();
36+
fn _user_img_end();
37+
}
38+
let data = unsafe {
39+
core::slice::from_raw_parts(
40+
_user_img_start as *const u8,
41+
_user_img_end as usize - _user_img_start as usize,
42+
)
43+
};
44+
let user_thread = unsafe { Thread::new_user(data) };
45+
CPU.add_thread(user_thread);
46+
3947
println!("++++ setup process! ++++");
4048
}
4149

@@ -50,6 +58,7 @@ pub extern "C" fn hello_thread(arg: usize) -> ! {
5058
loop {}
5159
}
5260

61+
5362
pub fn tick() {
5463
CPU.tick();
5564
}

0 commit comments

Comments
 (0)