proc_pagetable and proc_freepagetable
This commit is contained in:
parent
1c3e73ba3f
commit
6342f66cd3
@ -60,47 +60,11 @@ struct proc *allocproc(void);
|
||||
|
||||
// Create a user page table for a given process, with no user memory,
|
||||
// but with trampoline and trapframe pages.
|
||||
pagetable_t
|
||||
proc_pagetable(struct proc *p)
|
||||
{
|
||||
pagetable_t pagetable;
|
||||
|
||||
// An empty page table.
|
||||
pagetable = uvmcreate();
|
||||
if(pagetable == 0)
|
||||
return 0;
|
||||
|
||||
// map the trampoline code (for system call return)
|
||||
// at the highest user virtual address.
|
||||
// only the supervisor uses it, on the way
|
||||
// to/from user space, so not PTE_U.
|
||||
if(mappages(pagetable, TRAMPOLINE, PGSIZE,
|
||||
(uint64)trampoline, PTE_R | PTE_X) < 0){
|
||||
uvmfree(pagetable, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// map the trapframe page just below the trampoline page, for
|
||||
// trampoline.S.
|
||||
if(mappages(pagetable, TRAPFRAME, PGSIZE,
|
||||
(uint64)(p->trapframe), PTE_R | PTE_W) < 0){
|
||||
uvmunmap(pagetable, TRAMPOLINE, 1, 0);
|
||||
uvmfree(pagetable, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pagetable;
|
||||
}
|
||||
pagetable_t proc_pagetable(struct proc *p);
|
||||
|
||||
// Free a process's page table, and free the
|
||||
// physical memory it refers to.
|
||||
void
|
||||
proc_freepagetable(pagetable_t pagetable, uint64 sz)
|
||||
{
|
||||
uvmunmap(pagetable, TRAMPOLINE, 1, 0);
|
||||
uvmunmap(pagetable, TRAPFRAME, 1, 0);
|
||||
uvmfree(pagetable, sz);
|
||||
}
|
||||
void proc_freepagetable(pagetable_t pagetable, uint64 sz);
|
||||
|
||||
// a user program that calls exec("/init")
|
||||
// assembled from ../user/initcode.S
|
||||
|
@ -2,14 +2,18 @@
|
||||
|
||||
use super::{context::Context, cpu::Cpu, scheduler::wakeup, trapframe::Trapframe};
|
||||
use crate::{
|
||||
arch::riscv::{Pagetable, PTE_W, PGSIZE},
|
||||
arch::riscv::{Pagetable, PTE_W, PTE_R, PTE_X, PGSIZE, memlayout::{TRAMPOLINE, TRAPFRAME}},
|
||||
fs::file::{File, Inode},
|
||||
mem::{kalloc::{kfree, kalloc}, memset},
|
||||
mem::{
|
||||
kalloc::{kfree, kalloc},
|
||||
memset,
|
||||
virtual_memory::{uvmcreate, uvmfree, uvmunmap, mappages},
|
||||
},
|
||||
sync::spinlock::Spinlock,
|
||||
};
|
||||
use core::{
|
||||
ffi::{c_char, c_void},
|
||||
ptr::{addr_of_mut, null_mut},
|
||||
ptr::{addr_of, addr_of_mut, null_mut},
|
||||
sync::atomic::{AtomicI32, Ordering},
|
||||
};
|
||||
|
||||
@ -34,8 +38,8 @@ extern "C" {
|
||||
pub fn wait(addr: u64) -> i32;
|
||||
pub fn procdump();
|
||||
pub fn proc_mapstacks(kpgtbl: Pagetable);
|
||||
pub fn proc_pagetable(p: *mut Process) -> Pagetable;
|
||||
pub fn proc_freepagetable(pagetable: Pagetable, sz: u64);
|
||||
// pub fn proc_pagetable(p: *mut Process) -> Pagetable;
|
||||
// pub fn proc_freepagetable(pagetable: Pagetable, sz: u64);
|
||||
// pub fn allocproc() -> *mut Process;
|
||||
pub fn uvmalloc(pagetable: Pagetable, oldsz: u64, newsz: u64, xperm: i32) -> u64;
|
||||
pub fn uvmdealloc(pagetable: Pagetable, oldsz: u64, newsz: u64) -> u64;
|
||||
@ -220,6 +224,40 @@ impl Process {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Create a user page table for a given process,
|
||||
/// with no user memory, but with trampoline and trapframe pages.
|
||||
pub unsafe fn alloc_pagetable(&mut self) -> Result<Pagetable, ProcessError> {
|
||||
// Create an empty page table.
|
||||
let pagetable: Pagetable = uvmcreate();
|
||||
if pagetable.is_null() {
|
||||
return Err(ProcessError::Allocation);
|
||||
}
|
||||
|
||||
// Map the trampoline code (for syscall return)
|
||||
// at the highest user virtual address.
|
||||
// Only the supervisor uses it on the way
|
||||
// to and from user space, so not PTE_U.
|
||||
if mappages(pagetable, TRAMPOLINE, PGSIZE, addr_of!(trampoline) as usize as u64, PTE_R | PTE_X) < 0 {
|
||||
uvmfree(pagetable, 0);
|
||||
return Err(ProcessError::Allocation);
|
||||
}
|
||||
|
||||
// Map the trapframe page just below the trampoline page for trampoline.S.
|
||||
if mappages(pagetable, TRAPFRAME, PGSIZE, self.trapframe as usize as u64, PTE_R | PTE_W) < 0 {
|
||||
uvmunmap(pagetable, TRAMPOLINE, 1, 0);
|
||||
uvmfree(pagetable, 0);
|
||||
return Err(ProcessError::Allocation);
|
||||
}
|
||||
|
||||
Ok(pagetable)
|
||||
}
|
||||
/// Free a process's pagetable and free the physical memory it refers to.
|
||||
pub unsafe fn free_pagetable(pagetable: Pagetable, size: usize) {
|
||||
uvmunmap(pagetable, TRAMPOLINE, 1, 0);
|
||||
uvmunmap(pagetable, TRAPFRAME, 1, 0);
|
||||
uvmfree(pagetable, size as u64)
|
||||
}
|
||||
|
||||
/// Kill the process with the given pid.
|
||||
/// Returns true if the process was killed.
|
||||
/// The victim won't exit until it tries to return
|
||||
@ -287,6 +325,16 @@ pub unsafe extern "C" fn freeproc(p: *mut Process) {
|
||||
(*p).free();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn proc_pagetable(p: *mut Process) -> Pagetable {
|
||||
(*p).alloc_pagetable().unwrap_or(null_mut())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn proc_freepagetable(pagetable: Pagetable, size: u64) {
|
||||
Process::free_pagetable(pagetable, size as usize)
|
||||
}
|
||||
|
||||
/// Pass p's abandoned children to init.
|
||||
/// Caller must hold wait_lock.
|
||||
#[no_mangle]
|
||||
|
Loading…
x
Reference in New Issue
Block a user