fix user stack

This commit is contained in:
SKTT1Ryze 2021-04-03 20:39:16 +08:00
parent ab3f4232d7
commit fd60e5934a
6 changed files with 46 additions and 19 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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];