fix user stack
This commit is contained in:
parent
ab3f4232d7
commit
fd60e5934a
|
@ -36,7 +36,7 @@ pub extern "C" fn rust_main(hart_id: usize) -> ! {
|
|||
fn _swap_frame();
|
||||
fn _user_to_supervisor();
|
||||
fn _supervisor_to_user();
|
||||
fn _user_stack_bottom();
|
||||
fn _user_data();
|
||||
}
|
||||
|
||||
unsafe {
|
||||
|
@ -91,7 +91,7 @@ pub extern "C" fn rust_main(hart_id: usize) -> ! {
|
|||
println!("_swap_frame: {:#x}", _swap_frame as usize);
|
||||
println!("_user_to_supervisor: {:#x}", _user_to_supervisor as usize);
|
||||
println!("_supervisor_to_user: {:#x}", _supervisor_to_user as usize);
|
||||
println!("_user_stack_bottom: {:#x}", _user_stack_bottom as usize);
|
||||
println!("_user_data: {:#x}", _user_data as usize);
|
||||
|
||||
// let executor = task::Executor::default();
|
||||
|
||||
|
@ -111,10 +111,9 @@ pub extern "C" fn rust_main(hart_id: usize) -> ! {
|
|||
let kernel_memory = memory::MemorySet::new_kernel().expect("create kernel memory set");
|
||||
kernel_memory.activate();
|
||||
let process = task::Process::new(kernel_memory).expect("create process 1");
|
||||
let _stack_handle = process.alloc_stack().expect("alloc initial stack");
|
||||
let stack_handle = process.alloc_stack().expect("alloc initial stack");
|
||||
// 尝试进入用户态
|
||||
user::try_enter_user()
|
||||
|
||||
user::try_enter_user(stack_handle.end.0 - 4)
|
||||
// let task_1 = task::KernelTask::new(task_1(), process.clone());
|
||||
// let task_2 = task::KernelTask::new(task_2(), process.clone());
|
||||
// let task_3 = task::KernelTask::new(FibonacciFuture::new(5), process);
|
||||
|
|
|
@ -58,6 +58,10 @@ impl PhysicalPageNumber {
|
|||
pub const fn ceil(address: PhysicalAddress) -> Self {
|
||||
Self(address.0 / PAGE_SIZE + (address.0 % PAGE_SIZE != 0) as usize)
|
||||
}
|
||||
/// 从 satp 寄存器中取出根页表物理页号
|
||||
pub fn from_satp(satp: usize) -> Self {
|
||||
Self(satp.get_bits(0..44))
|
||||
}
|
||||
/// 得到物理页的起始地址
|
||||
pub fn start_address(&self) -> PhysicalAddress {
|
||||
PhysicalAddress(self.0 << 12)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::memory::{AddressSpaceId, PhysicalPageNumber, PhysicalAddress, VirtualAddress, VirtualPageNumber, config::PAGE_SIZE, frame::FrameTracker, frame_alloc};
|
||||
use super::{Flags, MapType, Segment, page_table::{PageTable, PageTableTracker}, page_table_entry::PageTableEntry};
|
||||
use alloc::{collections::VecDeque, vec::Vec};
|
||||
use bit_field::BitField;
|
||||
use core::ops::Range;
|
||||
use core::ptr::slice_from_raw_parts_mut;
|
||||
|
||||
|
@ -51,6 +52,7 @@ impl Mapping {
|
|||
// 解引用结束,entry位于最后一级页表
|
||||
Some(entry)
|
||||
}
|
||||
|
||||
/// 找到虚拟页号对应的页表项,如果不存在则返回 None
|
||||
pub fn find_pte(&self, vpn: VirtualPageNumber) -> Option<&mut PageTableEntry> {
|
||||
let root_table_pa = self.root_ppn.start_address();
|
||||
|
|
|
@ -154,14 +154,16 @@ impl MemorySet {
|
|||
// 映射 .user_text 段
|
||||
let user_text_len = _euser_text as usize - _suser_text as usize;
|
||||
let va_range = VirtualAddress(0)..VirtualAddress(user_text_len);
|
||||
let pa_range = PhysicalAddress((_suser_text as usize).wrapping_sub(KERNEL_MAP_OFFSET))..PhysicalAddress((_euser_text as usize).wrapping_sub(KERNEL_MAP_OFFSET));
|
||||
let pa_range = VirtualAddress(_suser_text as usize).physical_address_linear()..VirtualAddress(_euser_text as usize).physical_address_linear();
|
||||
// let pa_range = PhysicalAddress((_suser_text as usize).wrapping_sub(KERNEL_MAP_OFFSET))..PhysicalAddress((_euser_text as usize).wrapping_sub(KERNEL_MAP_OFFSET));
|
||||
mapping.map_defined(&va_range, &pa_range, Flags::EXECUTABLE | Flags::READABLE | Flags::WRITABLE | Flags::USER);
|
||||
|
||||
// 映射 .user_data 段,目前这里作为用户态的栈使用
|
||||
// 映射 .user_data 段
|
||||
let user_stack_len = _euser_data as usize - _suser_data as usize;
|
||||
assert_eq!(user_stack_len, PAGE_SIZE);
|
||||
let va_range = VirtualAddress(USER_STACK_BOTTOM_VA)..VirtualAddress(USER_STACK_BOTTOM_VA + user_stack_len);
|
||||
let pa_range = PhysicalAddress((_suser_data as usize).wrapping_sub(KERNEL_MAP_OFFSET))..PhysicalAddress((_euser_data as usize).wrapping_sub(KERNEL_MAP_OFFSET));
|
||||
let pa_range = VirtualAddress(_suser_data as usize).physical_address_linear()..VirtualAddress(_euser_data as usize).physical_address_linear();
|
||||
// let pa_range = PhysicalAddress((_suser_data as usize).wrapping_sub(KERNEL_MAP_OFFSET))..PhysicalAddress((_euser_data as usize).wrapping_sub(KERNEL_MAP_OFFSET));
|
||||
mapping.map_defined(&va_range, &pa_range, Flags::READABLE | Flags::WRITABLE | Flags::USER);
|
||||
|
||||
// 映射 _swap_frame
|
||||
|
|
|
@ -41,6 +41,23 @@ impl Process {
|
|||
};
|
||||
Some(process)
|
||||
}
|
||||
/// 创建一个用户进程
|
||||
///
|
||||
/// 暂时和创建内核进程无太大区别,后续会思考这部分设计
|
||||
pub fn new_user(memory_set: MemorySet) -> Option<Arc<Self>> {
|
||||
let process = Arc::new(Process {
|
||||
id: next_process_id(),
|
||||
is_user: true,
|
||||
inner: Mutex::new(ProcessInner {
|
||||
memory_set
|
||||
})
|
||||
});
|
||||
unsafe {
|
||||
KernelHartInfo::load_address_space_id(process.address_space_id());
|
||||
KernelHartInfo::load_process(process.clone());
|
||||
};
|
||||
Some(process)
|
||||
}
|
||||
// /// 得到进程编号
|
||||
// pub fn process_id(&self) -> ProcessId {
|
||||
// self.id
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use core::borrow::BorrowMut;
|
||||
|
||||
/// 临时的用户态程序和数据
|
||||
|
||||
use crate::memory::{self, PAGE_SIZE};
|
||||
use crate::memory::{self, PAGE_SIZE, MemorySet};
|
||||
use crate::trap;
|
||||
use crate::task;
|
||||
|
||||
// 尝试进入用户态
|
||||
pub fn try_enter_user() -> ! {
|
||||
pub fn try_enter_user(kernel_stack_top: usize) -> ! {
|
||||
extern {
|
||||
// 用户陷入内核时候的中断处理函数
|
||||
fn _test_user_trap();
|
||||
|
@ -16,6 +18,7 @@ pub fn try_enter_user() -> ! {
|
|||
|
||||
// 创建一个用户态映射
|
||||
let user_memory = memory::MemorySet::new_user().unwrap();
|
||||
|
||||
// 存放用户特权级切换上下文的虚拟地址
|
||||
let swap_cx_va = memory::VirtualAddress(memory::SWAP_CONTEXT_VA);
|
||||
// 存放用户特权级切换上下文的虚拟页号
|
||||
|
@ -37,21 +40,21 @@ pub fn try_enter_user() -> ! {
|
|||
.unwrap()
|
||||
.page_number();
|
||||
println!("user_entry_ppn: {:x?}", user_entry_ppn);
|
||||
// let read_user_va: &mut [u16; 2] = unsafe {user_entry_ppn.start_address().deref_linear_static() };
|
||||
// println!("code in user text:");
|
||||
// for code in read_user_va {
|
||||
// println!("{:#x}", &code);
|
||||
// }
|
||||
// 获取用户的satp寄存器
|
||||
let user_satp = user_memory.mapping.get_satp(user_memory.address_space_id);
|
||||
let process = task::Process::new(user_memory).unwrap();
|
||||
let process = task::Process::new_user(user_memory).unwrap();
|
||||
// 用户态栈
|
||||
let user_stack_handle = process.alloc_stack().expect("alloc user stack");
|
||||
// 这里减 4 是因为映射的时候虚拟地址的右半边是不包含的
|
||||
let user_stack_top = user_stack_handle.end.0 - 4;
|
||||
println!("kernel stack top: {:#x}, user stack top: {:#x}", kernel_stack_top, user_stack_top);
|
||||
// 获取内核的satp寄存器
|
||||
let kernel_satp = riscv::register::satp::read().bits();
|
||||
|
||||
// 往 SwapContext 写东西
|
||||
// _test_user_entry 由虚拟地址 0 映射到真实物理地址
|
||||
*swap_cx = trap::SwapContext::new_to_user(
|
||||
kernel_satp, 0, 0, 0, memory::USER_STACK_BOTTOM_VA + PAGE_SIZE - 4, _test_user_trap as usize);
|
||||
kernel_satp, 0, 0, kernel_stack_top, user_stack_top, _test_user_trap as usize);
|
||||
// println!("swap_cx.epc: {:#x}", swap_cx.epc);
|
||||
// println!("swap_cx.trap_handler: {:#x}", swap_cx.user_trap_handler);
|
||||
trap::switch_to_user(swap_cx, user_satp)
|
||||
|
@ -71,7 +74,7 @@ pub extern "C" fn test_user_entry() {
|
|||
loop {}
|
||||
}
|
||||
|
||||
// 用户态栈
|
||||
#[export_name = "_user_stack_bottom"]
|
||||
// 用户态数据,这里是为了占位
|
||||
#[export_name = "_user_data"]
|
||||
#[link_section = ".user_data"]
|
||||
static _USER_STACK: [usize; PAGE_SIZE / 8] = [1; PAGE_SIZE / 8];
|
Loading…
Reference in New Issue