Skip to content

Commit e0fb22f

Browse files
committed
Init the ch5
1 parent 9d0e7c2 commit e0fb22f

File tree

22 files changed

+910
-292
lines changed

22 files changed

+910
-292
lines changed

os/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ BASE ?= 1
3030
# Disassembly
3131
DISASM ?= -x
3232

33+
# Run usertests or usershell
34+
TEST ?=
35+
3336
build: env $(KERNEL_BIN)
3437

3538
env:

os/build.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ _num_app:
4141
}
4242
writeln!(f, r#" .quad app_{}_end"#, apps.len() - 1)?;
4343

44+
writeln!(
45+
f,
46+
r#"
47+
.global _app_names
48+
_app_names:"#
49+
)?;
50+
for app in apps.iter() {
51+
writeln!(f, r#" .string "{}""#, app)?;
52+
}
53+
4454
for (idx, app) in apps.iter().enumerate() {
4555
println!("app_{}: {}", idx, app);
4656
writeln!(

os/src/config.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ pub const KERNEL_HEAP_SIZE: usize = 0x200_0000;
1313
pub const PAGE_SIZE: usize = 0x1000;
1414
/// page size bits: 12
1515
pub const PAGE_SIZE_BITS: usize = 0xc;
16-
/// the max number of syscall
17-
pub const MAX_SYSCALL_NUM: usize = 500;
1816
/// the virtual addr of trapoline
1917
pub const TRAMPOLINE: usize = usize::MAX - PAGE_SIZE + 1;
2018
/// the virtual addr of trap context

os/src/loader.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
//! Loading user applications into memory
22
33
/// Get the total number of applications.
4+
use alloc::vec::Vec;
5+
use lazy_static::*;
6+
///get app number
47
pub fn get_num_app() -> usize {
58
extern "C" {
69
fn _num_app();
710
}
811
unsafe { (_num_app as usize as *const usize).read_volatile() }
912
}
10-
1113
/// get applications data
1214
pub fn get_app_data(app_id: usize) -> &'static [u8] {
1315
extern "C" {
@@ -24,3 +26,45 @@ pub fn get_app_data(app_id: usize) -> &'static [u8] {
2426
)
2527
}
2628
}
29+
30+
lazy_static! {
31+
///All of app's name
32+
static ref APP_NAMES: Vec<&'static str> = {
33+
let num_app = get_num_app();
34+
extern "C" {
35+
fn _app_names();
36+
}
37+
let mut start = _app_names as usize as *const u8;
38+
let mut v = Vec::new();
39+
unsafe {
40+
for _ in 0..num_app {
41+
let mut end = start;
42+
while end.read_volatile() != b'\0' {
43+
end = end.add(1);
44+
}
45+
let slice = core::slice::from_raw_parts(start, end as usize - start as usize);
46+
let str = core::str::from_utf8(slice).unwrap();
47+
v.push(str);
48+
start = end.add(1);
49+
}
50+
}
51+
v
52+
};
53+
}
54+
55+
#[allow(unused)]
56+
///get app data from name
57+
pub fn get_app_data_by_name(name: &str) -> Option<&'static [u8]> {
58+
let num_app = get_num_app();
59+
(0..num_app)
60+
.find(|&i| APP_NAMES[i] == name)
61+
.map(get_app_data)
62+
}
63+
///list all apps
64+
pub fn list_apps() {
65+
println!("/**** APPS ****");
66+
for app in APP_NAMES.iter() {
67+
println!("{}", app);
68+
}
69+
println!("**************/");
70+
}

os/src/main.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
//! - [`trap`]: Handles all cases of switching from userspace to the kernel
77
//! - [`task`]: Task management
88
//! - [`syscall`]: System call handling and implementation
9+
//! - [`mm`]: Address map using SV39
10+
//! - [`sync`]:Wrap a static data structure inside it so that we are able to access it without any `unsafe`.
911
//!
1012
//! The operating system also starts in this module. Kernel code starts
1113
//! executing from `entry.asm`, after which [`rust_main()`] is called to
1214
//! initialize various pieces of functionality. (See its source code for
1315
//! details.)
1416
//!
15-
//! We then call [`task::run_first_task()`] and for the first time go to
17+
//! We then call [`task::run_tasks()`] and for the first time go to
1618
//! userspace.
1719
1820
#![deny(missing_docs)]
@@ -43,9 +45,10 @@ pub mod task;
4345
pub mod timer;
4446
pub mod trap;
4547

46-
core::arch::global_asm!(include_str!("entry.asm"));
47-
core::arch::global_asm!(include_str!("link_app.S"));
48+
use core::arch::global_asm;
4849

50+
global_asm!(include_str!("entry.asm"));
51+
global_asm!(include_str!("link_app.S"));
4952
/// clear BSS segment
5053
fn clear_bss() {
5154
extern "C" {
@@ -100,11 +103,13 @@ pub fn rust_main() -> ! {
100103
clear_bss();
101104
kernel_log_info();
102105
mm::init();
103-
println!("[kernel] back to world!");
104106
mm::remap_test();
107+
task::add_initproc();
108+
println!("after initproc!");
105109
trap::init();
106110
trap::enable_timer_interrupt();
107111
timer::set_next_trigger();
108-
task::run_first_task();
112+
loader::list_apps();
113+
task::run_tasks();
109114
panic!("Unreachable in rust_main!");
110115
}

os/src/mm/frame_allocator.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//! Implementation of [`FrameAllocator`] which
22
//! controls all the frames in the operating system.
3-
43
use super::{PhysAddr, PhysPageNum};
54
use crate::config::MEMORY_END;
65
use crate::sync::UPSafeCell;

os/src/mm/memory_set.rs

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
//! Implementation of [`MapArea`] and [`MemorySet`].
2-
32
use super::{frame_alloc, FrameTracker};
43
use super::{PTEFlags, PageTable, PageTableEntry};
54
use super::{PhysAddr, PhysPageNum, VirtAddr, VirtPageNum};
65
use super::{StepByOne, VPNRange};
7-
use crate::config::{
8-
KERNEL_STACK_SIZE, MEMORY_END, PAGE_SIZE, TRAMPOLINE, TRAP_CONTEXT_BASE, USER_STACK_SIZE,
9-
};
6+
use crate::config::{MEMORY_END, PAGE_SIZE, TRAMPOLINE, TRAP_CONTEXT_BASE, USER_STACK_SIZE};
107
use crate::sync::UPSafeCell;
118
use alloc::collections::BTreeMap;
129
use alloc::sync::Arc;
@@ -63,6 +60,21 @@ impl MemorySet {
6360
None,
6461
);
6562
}
63+
/// remove a area
64+
pub fn remove_area_with_start_vpn(&mut self, start_vpn: VirtPageNum) {
65+
if let Some((idx, area)) = self
66+
.areas
67+
.iter_mut()
68+
.enumerate()
69+
.find(|(_, area)| area.vpn_range.get_start() == start_vpn)
70+
{
71+
area.unmap(&mut self.page_table);
72+
self.areas.remove(idx);
73+
}
74+
}
75+
/// Add a new MapArea into this MemorySet.
76+
/// Assuming that there are no conflicts in the virtual address
77+
/// space.
6678
fn push(&mut self, mut map_area: MapArea, data: Option<&[u8]>) {
6779
map_area.map(&mut self.page_table);
6880
if let Some(data) = data {
@@ -221,6 +233,26 @@ impl MemorySet {
221233
elf.header.pt2.entry_point() as usize,
222234
)
223235
}
236+
/// Create a new address space by copy code&data from a exited process's address space.
237+
pub fn from_existed_user(user_space: &Self) -> Self {
238+
let mut memory_set = Self::new_bare();
239+
// map trampoline
240+
memory_set.map_trampoline();
241+
// copy data sections/trap_context/user_stack
242+
for area in user_space.areas.iter() {
243+
let new_area = MapArea::from_another(area);
244+
memory_set.push(new_area, None);
245+
// copy data from another space
246+
for vpn in area.vpn_range {
247+
let src_ppn = user_space.translate(vpn).unwrap().ppn();
248+
let dst_ppn = memory_set.translate(vpn).unwrap().ppn();
249+
dst_ppn
250+
.get_bytes_array()
251+
.copy_from_slice(src_ppn.get_bytes_array());
252+
}
253+
}
254+
memory_set
255+
}
224256
/// Change page table by writing satp CSR Register.
225257
pub fn activate(&self) {
226258
let satp = self.page_table.token();
@@ -233,6 +265,12 @@ impl MemorySet {
233265
pub fn translate(&self, vpn: VirtPageNum) -> Option<PageTableEntry> {
234266
self.page_table.translate(vpn)
235267
}
268+
269+
///Remove all `MapArea`
270+
pub fn recycle_data_pages(&mut self) {
271+
self.areas.clear();
272+
}
273+
236274
/// shrink the area to new_end
237275
#[allow(unused)]
238276
pub fn shrink_to(&mut self, start: VirtAddr, new_end: VirtAddr) -> bool {
@@ -287,6 +325,14 @@ impl MapArea {
287325
map_perm,
288326
}
289327
}
328+
pub fn from_another(another: &Self) -> Self {
329+
Self {
330+
vpn_range: VPNRange::new(another.vpn_range.get_start(), another.vpn_range.get_end()),
331+
data_frames: BTreeMap::new(),
332+
map_type: another.map_type,
333+
map_perm: another.map_perm,
334+
}
335+
}
290336
pub fn map_one(&mut self, page_table: &mut PageTable, vpn: VirtPageNum) {
291337
let ppn: PhysPageNum;
292338
match self.map_type {
@@ -302,7 +348,6 @@ impl MapArea {
302348
let pte_flags = PTEFlags::from_bits(self.map_perm.bits).unwrap();
303349
page_table.map(vpn, ppn, pte_flags);
304350
}
305-
#[allow(unused)]
306351
pub fn unmap_one(&mut self, page_table: &mut PageTable, vpn: VirtPageNum) {
307352
if self.map_type == MapType::Framed {
308353
self.data_frames.remove(&vpn);
@@ -314,7 +359,6 @@ impl MapArea {
314359
self.map_one(page_table, vpn);
315360
}
316361
}
317-
#[allow(unused)]
318362
pub fn unmap(&mut self, page_table: &mut PageTable) {
319363
for vpn in self.vpn_range {
320364
self.unmap_one(page_table, vpn);
@@ -379,13 +423,6 @@ bitflags! {
379423
}
380424
}
381425

382-
/// Return (bottom, top) of a kernel stack in kernel space.
383-
pub fn kernel_stack_position(app_id: usize) -> (usize, usize) {
384-
let top = TRAMPOLINE - app_id * (KERNEL_STACK_SIZE + PAGE_SIZE);
385-
let bottom = top - KERNEL_STACK_SIZE;
386-
(bottom, top)
387-
}
388-
389426
/// remap test in kernel space
390427
#[allow(unused)]
391428
pub fn remap_test() {

os/src/mm/mod.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
//! map area and memory set, is implemented here.
66
//!
77
//! Every task or process has a memory_set to control its virtual memory.
8-
98
mod address;
109
mod frame_allocator;
1110
mod heap_allocator;
@@ -16,10 +15,9 @@ pub use address::{PhysAddr, PhysPageNum, VirtAddr, VirtPageNum};
1615
use address::{StepByOne, VPNRange};
1716
pub use frame_allocator::{frame_alloc, FrameTracker};
1817
pub use memory_set::remap_test;
19-
pub use memory_set::{kernel_stack_position, MapPermission, MemorySet, KERNEL_SPACE};
20-
pub use page_table::{translated_byte_buffer, PageTableEntry};
21-
pub use page_table::{PTEFlags, PageTable};
22-
18+
pub use memory_set::{MapPermission, MemorySet, KERNEL_SPACE};
19+
pub use page_table::{translated_byte_buffer, translated_refmut, translated_str, PageTableEntry};
20+
use page_table::{PTEFlags, PageTable};
2321
/// initiate heap allocator, frame allocator and kernel space
2422
pub fn init() {
2523
heap_allocator::init_heap();

os/src/mm/page_table.rs

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,20 @@
11
//! Implementation of [`PageTableEntry`] and [`PageTable`].
2-
3-
use super::{frame_alloc, FrameTracker, PhysPageNum, StepByOne, VirtAddr, VirtPageNum};
2+
use super::{frame_alloc, FrameTracker, PhysAddr, PhysPageNum, StepByOne, VirtAddr, VirtPageNum};
3+
use alloc::string::String;
44
use alloc::vec;
55
use alloc::vec::Vec;
66
use bitflags::*;
77

88
bitflags! {
99
/// page table entry flags
1010
pub struct PTEFlags: u8 {
11-
/// Valid
1211
const V = 1 << 0;
13-
/// Readable
1412
const R = 1 << 1;
15-
/// Writable
1613
const W = 1 << 2;
17-
/// eXecutable
1814
const X = 1 << 3;
19-
/// User
2015
const U = 1 << 4;
21-
/// Global
2216
const G = 1 << 5;
23-
/// Accessed
2417
const A = 1 << 6;
25-
/// Dirty
2618
const D = 1 << 7;
2719
}
2820
}
@@ -151,6 +143,17 @@ impl PageTable {
151143
pub fn translate(&self, vpn: VirtPageNum) -> Option<PageTableEntry> {
152144
self.find_pte(vpn).map(|pte| *pte)
153145
}
146+
/// get the physical address from the virtual address
147+
pub fn translate_va(&self, va: VirtAddr) -> Option<PhysAddr> {
148+
self.find_pte(va.clone().floor()).map(|pte| {
149+
//println!("translate_va:va = {:?}", va);
150+
let aligned_pa: PhysAddr = pte.ppn().into();
151+
//println!("translate_va:pa_align = {:?}", aligned_pa);
152+
let offset = va.page_offset();
153+
let aligned_pa_usize: usize = aligned_pa.into();
154+
(aligned_pa_usize + offset).into()
155+
})
156+
}
154157
/// get the token from the page table
155158
pub fn token(&self) -> usize {
156159
8usize << 60 | self.root_ppn.0
@@ -179,3 +182,34 @@ pub fn translated_byte_buffer(token: usize, ptr: *const u8, len: usize) -> Vec<&
179182
}
180183
v
181184
}
185+
186+
/// Translate&Copy a ptr[u8] array end with `\0` to a `String` Vec through page table
187+
pub fn translated_str(token: usize, ptr: *const u8) -> String {
188+
let page_table = PageTable::from_token(token);
189+
let mut string = String::new();
190+
let mut va = ptr as usize;
191+
loop {
192+
let ch: u8 = *(page_table
193+
.translate_va(VirtAddr::from(va))
194+
.unwrap()
195+
.get_mut());
196+
if ch == 0 {
197+
break;
198+
} else {
199+
string.push(ch as char);
200+
va += 1;
201+
}
202+
}
203+
string
204+
}
205+
/// Translate a ptr[u8] array through page table and return a mutable reference of T
206+
pub fn translated_refmut<T>(token: usize, ptr: *mut T) -> &'static mut T {
207+
//trace!("into translated_refmut!");
208+
let page_table = PageTable::from_token(token);
209+
let va = ptr as usize;
210+
//trace!("translated_refmut: before translate_va");
211+
page_table
212+
.translate_va(VirtAddr::from(va))
213+
.unwrap()
214+
.get_mut()
215+
}

0 commit comments

Comments
 (0)