task2 finished
This commit is contained in:
@ -123,14 +123,20 @@ allocproc(void)
|
||||
|
||||
found:
|
||||
p->pid = allocpid();
|
||||
p->state = USED;
|
||||
|
||||
// Allocate a trapframe page.
|
||||
if((p->trapframe = (struct trapframe *)kalloc()) == 0){
|
||||
release(&p->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Allocate a usyscall page.
|
||||
if((p->usyscall = (struct usyscall *)kalloc()) == 0){
|
||||
freeproc(p);
|
||||
release(&p->lock);
|
||||
return 0;
|
||||
}
|
||||
p->usyscall->pid = p->pid ;
|
||||
|
||||
// An empty user page table.
|
||||
p->pagetable = proc_pagetable(p);
|
||||
@ -155,6 +161,9 @@ found:
|
||||
static void
|
||||
freeproc(struct proc *p)
|
||||
{
|
||||
if (p->usyscall) {
|
||||
kfree((void*)p->usyscall);
|
||||
}
|
||||
if(p->trapframe)
|
||||
kfree((void*)p->trapframe);
|
||||
p->trapframe = 0;
|
||||
@ -202,6 +211,16 @@ proc_pagetable(struct proc *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// map the usyscall just below TRAMPOFRAME, for trampoline.S.
|
||||
// 这个页需要设置PTE_U为,使得用户态可以访问
|
||||
if(mappages(pagetable, USYSCALL, PGSIZE,
|
||||
(uint64)(p->usyscall), PTE_R | PTE_U) < 0){
|
||||
uvmunmap(pagetable, TRAPFRAME, 1, 0);
|
||||
uvmunmap(pagetable, TRAMPOLINE, 1, 0);
|
||||
uvmfree(pagetable, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pagetable;
|
||||
}
|
||||
|
||||
@ -210,6 +229,7 @@ proc_pagetable(struct proc *p)
|
||||
void
|
||||
proc_freepagetable(pagetable_t pagetable, uint64 sz)
|
||||
{
|
||||
uvmunmap(pagetable, USYSCALL, 1, 0);
|
||||
uvmunmap(pagetable, TRAMPOLINE, 1, 0);
|
||||
uvmunmap(pagetable, TRAPFRAME, 1, 0);
|
||||
uvmfree(pagetable, sz);
|
||||
|
||||
@ -94,11 +94,12 @@ struct proc {
|
||||
|
||||
// wait_lock must be held when using this:
|
||||
struct proc *parent; // Parent process
|
||||
|
||||
// these are private to the process, so p->lock need not be held.
|
||||
// these are private to the process, so p->lock need not be held.
|
||||
uint64 kstack; // Virtual address of kernel stack
|
||||
uint64 sz; // Size of process memory (bytes)
|
||||
pagetable_t pagetable; // User page table
|
||||
// 进程的结构体中需要加上usyscall字段
|
||||
struct usyscall *usyscall; // data page for usyscall
|
||||
struct trapframe *trapframe; // data page for trampoline.S
|
||||
struct context context; // swtch() here to run process
|
||||
struct file *ofile[NOFILE]; // Open files
|
||||
|
||||
@ -375,7 +375,9 @@ typedef uint64 *pagetable_t; // 512 PTEs
|
||||
#define PTE_W (1L << 2)
|
||||
#define PTE_X (1L << 3)
|
||||
#define PTE_U (1L << 4) // user can access
|
||||
|
||||
#define PTE_A (1L << 6) // Accessed bit
|
||||
#define PTE_D (1L << 7) // Dirty bit
|
||||
#define PTE_PS (1L << 7) // Page Size bit in PTE (for 2MB superpages)
|
||||
|
||||
|
||||
#if defined(LAB_MMAP) || defined(LAB_PGTBL)
|
||||
|
||||
@ -111,6 +111,7 @@ extern uint64 sys_recv(void);
|
||||
#ifdef LAB_PGTBL
|
||||
extern uint64 sys_pgpte(void);
|
||||
extern uint64 sys_kpgtbl(void);
|
||||
extern uint64 sys_pgaccess(void);
|
||||
#endif
|
||||
|
||||
// An array mapping syscall numbers from syscall.h
|
||||
@ -146,6 +147,7 @@ static uint64 (*syscalls[])(void) = {
|
||||
#ifdef LAB_PGTBL
|
||||
[SYS_pgpte] sys_pgpte,
|
||||
[SYS_kpgtbl] sys_kpgtbl,
|
||||
[SYS_pgaccess] sys_pgaccess,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -123,3 +123,41 @@ sys_uptime(void)
|
||||
release(&tickslock);
|
||||
return xticks;
|
||||
}
|
||||
|
||||
uint64
|
||||
sys_pgaccess(void)
|
||||
{
|
||||
uint64 va;
|
||||
int n;
|
||||
uint64 user_mask_addr;
|
||||
argaddr(0, &va);
|
||||
argint(1, &n);
|
||||
argaddr(2, &user_mask_addr);
|
||||
if (va < 0 || n < 0 || user_mask_addr < 0)
|
||||
return -1;
|
||||
|
||||
if (n < 0 || n > 32)
|
||||
return -1;
|
||||
|
||||
struct proc *p = myproc();
|
||||
uint64 mask = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
uint64 v = va + i * PGSIZE;
|
||||
pte_t *pte = walk(p->pagetable, v, 0);
|
||||
|
||||
if (!pte || (*pte & PTE_PS))
|
||||
continue;
|
||||
|
||||
if ((*pte & PTE_V) && (*pte & PTE_A)) {
|
||||
mask |= (1 << i); // Set bit i in mask
|
||||
*pte &= ~PTE_A; // Clear the Accessed bit
|
||||
}
|
||||
}
|
||||
|
||||
if (copyout(p->pagetable, user_mask_addr, (char*)&mask, sizeof(mask)) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -101,6 +101,9 @@ walk(pagetable_t pagetable, uint64 va, int alloc)
|
||||
for(int level = 2; level > 0; level--) {
|
||||
pte_t *pte = &pagetable[PX(level, va)];
|
||||
if(*pte & PTE_V) {
|
||||
if (*pte & PTE_PS) { // 如果是 Superpage
|
||||
return pte;
|
||||
}
|
||||
pagetable = (pagetable_t)PTE2PA(*pte);
|
||||
#ifdef LAB_PGTBL
|
||||
if(PTE_LEAF(*pte)) {
|
||||
|
||||
Reference in New Issue
Block a user