task2 finished

This commit is contained in:
2025-05-27 15:59:57 +08:00
parent 5292fdc6ac
commit bd21012f73
6 changed files with 70 additions and 4 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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