本文整理汇总了C++中pgdir_walk函数的典型用法代码示例。如果您正苦于以下问题:C++ pgdir_walk函数的具体用法?C++ pgdir_walk怎么用?C++ pgdir_walk使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了pgdir_walk函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: page_insert
int
page_insert(Pde *pgdir, struct Page *pp, u_long va, u_int perm)
{
// Fill this function in
u_int PERM;
Pte *pgtable_entry;
PERM = perm | PTE_V;
pgdir_walk(pgdir, va, 0, &pgtable_entry);
if (pgtable_entry != 0 && (*pgtable_entry & PTE_V) != 0) {
if (pa2page(*pgtable_entry) != pp) {
page_remove(pgdir, va);
} else {
tlb_invalidate(pgdir, va);
*pgtable_entry = (page2pa(pp) | PERM);
return 0;
}
}
tlb_invalidate(pgdir, va);
if (pgdir_walk(pgdir, va, 1, &pgtable_entry) != 0) {
return -E_NO_MEM; // panic("page insert wrong.\n");
}
*pgtable_entry = (page2pa(pp) | PERM);
//printf("page_insert:PTE:\tcon:%x\[email protected]:%x\n",(int)*pgtable_entry,(int)pgtable_entry);
pp->pp_ref++;
return 0;
}
示例2: get_page
/* Given a page table entry, return the page.
* We pass in the page directory index and page table index
* so we can re-create the virtual address if we need to.
*
* If the page was swapped out on disk, swap it in before returning. */
struct page *
get_page(int pdi, int pti, struct page_table* pt)
{
//bool lock_p = false;
int swapped = PTE_TO_LOCATION(pt->table[pti]);
// Wait for page to finish moving to disk, or moving to memory.
while(swapped == PTE_SWAPPING)
{
// Let other stuff run so that this can complete
/*
if(spinlock_do_i_hold(&stealmem_lock)){
spinlock_release(&stealmem_lock);
//lock_p = true;
}
*/
thread_yield();
swapped = PTE_TO_LOCATION(pt->table[pti]);
/*
// Get the lock back if we had released it above.
if(!spinlock_do_i_hold(&stealmem_lock)){
spinlock_acquire(&stealmem_lock);
}
*/
//DEBUG(DB_SWAP,"status: %d", swapped);
}
//if(swapped == PTE_SWAPPING)
//{
// panic("BOB SAGGOT");
//}
int* pte = &(pt->table[pti]);
if(swapped == PTE_SWAP)
{
//bool lock = get_coremap_lock();
//Get the address space, virtual address, and permissions from PTE.
struct addrspace *as = curthread->t_addrspace;
vaddr_t va = PD_INDEX_TO_VA(pdi) | PT_INDEX_TO_VA(pti);
int permissions = PTE_TO_PERMISSIONS(*pte);
//KASSERT(coremap_lock_do_i_hold());
//Allocate a page
struct page *page = page_alloc(as,va,permissions);
struct page_table *pt = pgdir_walk(as,va,false);
KASSERT(page->state == LOCKED);
/* Page now has a home in RAM. But set the swap bit to 1 so we can swap the page in*/
pt->table[pti] |= PTE_SWAP;
//Swap the page in
swapin_page(as,va,page);
/* Page was swapped back in. Re-translate */
pt = pgdir_walk(as,va,false);
*pte = pt->table[pti];
// DEBUG(DB_SWAP,"I%p\n", page);
//release_coremap_lock(lock);
}
int page_num = PTE_TO_PFN(*pte) / PAGE_SIZE;
return &core_map[page_num];
}
示例3: page_insert
//
// Map the physical page 'pp' at virtual address 'va'.
// The permissions (the low 12 bits) of the page table entry
// should be set to 'perm|PTE_P'.
//
// Requirements
// - If there is already a page mapped at 'va', it should be page_remove()d.
// - If necessary, on demand, a page table should be allocated and inserted
// into 'pgdir'.
// - pp->pp_ref should be incremented if the insertion succeeds.
// - The TLB must be invalidated if a page was formerly present at 'va'.
//
// Corner-case hint: Make sure to consider what happens when the same
// pp is re-inserted at the same virtual address in the same pgdir.
// However, try not to distinguish this case in your code, as this
// frequently leads to subtle bugs; there's an elegant way to handle
// everything in one code path.
//
// RETURNS:
// 0 on success
// -E_NO_MEM, if page table couldn't be allocated
//
// Hint: The TA solution is implemented using pgdir_walk, page_remove,
// and page2pa.
//
int
page_insert(pde_t *pgdir, struct PageInfo *pp, void *va, int perm)
{/* // Fill this function in
pte_t *pte;
physaddr_t pa=page2pa(pp);
pte=pgdir_walk(pgdir,va,1);
if (pte==NULL){
cprintf("return error\n");
return -E_NO_MEM;}
//Check If there is already a page mapped at 'va',
if(*pte & PTE_P){
// check if same page is reinserted at the same virtual addr in same pgdir
if(PTE_ADDR(*pte)==pa){
*pte=pa|perm|PTE_P;
return 0;
}
//page should be page_remove()d and tlb invalidated.
page_remove(pgdir,va);
tlb_invalidate(pgdir,va);
}
//set permission of page_table_entry and increment pp->ref count
*pte=pa |perm| PTE_P ;
pp->pp_ref++;
return 0;
*/
pte_t *pte = pgdir_walk(pgdir, va, 0);
physaddr_t ppa = page2pa(pp);
if (pte != NULL) {
// for page alreay mapped
if (*pte & PTE_P){
if(PTE_ADDR(*pte)==ppa){
*pte=ppa|perm|PTE_P;
return 0;
}
page_remove(pgdir, va); // also invalidates tlb
}
if (page_free_list == pp)
page_free_list = page_free_list->pp_link;
} else {
pte = pgdir_walk(pgdir, va, 1);
if (!pte)
return -E_NO_MEM;
}
*pte = page2pa(pp) | perm | PTE_P;
pp->pp_ref++;
//cprintf("ref variable count: %d \n",pp->pp_ref);
tlb_invalidate(pgdir, va);
return 0;
}
示例4: user_mem_check
//
// Check that an environment is allowed to access the range of memory
// [va, va+len) with permissions 'perm | PTE_P'.
// Normally 'perm' will contain PTE_U at least, but this is not required.
// 'va' and 'len' need not be page-aligned; you must test every page that
// contains any of that range. You will test either 'len/PGSIZE',
// 'len/PGSIZE + 1', or 'len/PGSIZE + 2' pages.
//
// A user program can access a virtual address if (1) the address is below
// ULIM, and (2) the page table gives it permission. These are exactly
// the tests you should implement here.
//
// If there is an error, set the 'user_mem_check_addr' variable to the first
// erroneous virtual address.
//
// Returns 0 if the user program can access this range of addresses,
// and -E_FAULT otherwise.
//
int
user_mem_check(struct Env *env, const void *va, size_t len, int perm)
{
// LAB 3: Your code here.
// 这个地方和grade有点关:
// 必须找到第一个错误的地址,而不仅仅是判断是否权限允许访问。
// 所以ia = ROUNDDOWN(va, PGSIZE),va所在页无权限的话,就会出错。
// PGSIZE为步长的增加有点麻烦. 要考虑到第一次ROUNDDOWN()的话
// 出错,但user_mem_check_addr要赋值为va.
uint32_t ia = (uint32_t)va;
perm |= PTE_P;
for ( ; ia < (uint32_t)va + len; ia++){
if (ia > ULIM){
user_mem_check_addr = ia;
return -E_FAULT;
}
pte_t *ptep = pgdir_walk(env->env_pgdir, (void *)ia, 0);
if (!ptep){
user_mem_check_addr = ia;
return -E_FAULT;
}
if ((*ptep & perm) != perm){
user_mem_check_addr = ia;
return -E_FAULT;
}
}
return 0;
}
示例5: page_lookup
//
// Return the page mapped at virtual address 'va'.
// If pte_store is not zero, then we store in it the address
// of the pte for this page. This is used by page_remove and
// can be used to verify page permissions for syscall arguments,
// but should not be used by most callers.
//
// Return NULL if there is no page mapped at va.
//
// Hint: the TA solution uses pgdir_walk and pa2page.
//
struct PageInfo *
page_lookup(pde_t *pgdir, void *va, pte_t **pte_store)
{ // Fill this function in
pte_t *pte_entry;
pte_entry = pgdir_walk(pgdir, va, 0);
if (pte_entry == NULL)
return NULL;
if (*pte_entry == 0)
return NULL;
if (pte_store != NULL)
*pte_store = pte_entry;
return pa2page(PTE_ADDR(*pte_entry));
/* pte_t *pgtab=pgdir_walk(pgdir,va,0);
if( !(pgtab) );
return NULL;
if(pte_store)
*pte_store=pgtab;
return pa2page(PTE_ADDR(*pgtab));
*/
}
示例6: allocate_nonfixed_page
/* Allocate a page in a user address space */
static
void
allocate_nonfixed_page(size_t page_num, struct addrspace *as, vaddr_t va, int permissions)
{
// KASSERT(spinlock_do_i_hold(&stealmem_lock));
KASSERT(core_map[page_num].state == FREE);
//Allocate a page
core_map[page_num].state = LOCKED;
paddr_t pa = page_num * PAGE_SIZE;
core_map[page_num].pa = pa;
core_map[page_num].va = va;
core_map[page_num].as = as;
//Get the page table for the virtual address.
struct page_table *pt = pgdir_walk(as,va,true);
KASSERT(pt != NULL);
KASSERT(pt != 0x0);
//Update the page table entry to point to the page we made.
size_t pt_index = VA_TO_PT_INDEX(va);
vaddr_t page_location = PADDR_TO_KVADDR(core_map[page_num].pa);
pt->table[pt_index] = PAGEVA_TO_PTE(page_location);
// DEBUG(DB_VM, "VA:%p\n", (void*) va);
// DEBUG(DB_VM, "PTE:%p\n", (void*) pt->table[pt_index]);
// DEBUG(DB_VM, "PFN:%p\n", (void*) PTE_TO_PFN(pt->table[pt_index]));
//Add in permissions
pt->table[pt_index] |= permissions;
zero_page(page_num);
free_pages--;
// DEBUG(DB_VM, "A:%d\n",free_pages);
}
示例7: page_insert
//
// Map the physical page 'pp' at virtual address 'va'.
// The permissions (the low 12 bits) of the page table entry
// should be set to 'perm|PTE_P'.
//
// Requirements
// - If there is already a page mapped at 'va', it should be page_remove()d.
// - If necessary, on demand, a page table should be allocated and inserted
// into 'pgdir'.
// - pp->pp_ref should be incremented if the insertion succeeds.
// - The TLB must be invalidated if a page was formerly present at 'va'.
//
// Corner-case hint: Make sure to consider what happens when the same
// pp is re-inserted at the same virtual address in the same pgdir.
// However, try not to distinguish this case in your code, as this
// frequently leads to subtle bugs; there's an elegant way to handle
// everything in one code path.
//
// RETURNS:
// 0 on success
// -E_NO_MEM, if page table couldn't be allocated
//
// Hint: The TA solution is implemented using pgdir_walk, page_remove,
// and page2pa.
//
int
page_insert(pde_t *pgdir, struct PageInfo *pp, void *va, int perm)
{
// Fill this function in
pte_t* ptep = pgdir_walk(pgdir, va, true);
if(!ptep) {
return -E_NO_MEM;
}
if( pa2page(*ptep) != pp ){
page_remove(pgdir, va);
assert( *ptep == 0 );
assert(pp->pp_ref >= 0);
pp->pp_ref++;
}
else {
tlb_invalidate(pgdir, va);
}
*ptep = page2pa(pp) | perm | PTE_P;
/* we should also change pde's perm*/
pde_t *pde = pgdir + PDX(va);
*pde = *pde | perm;
return 0;
}
示例8: user_mem_check
//
// Check that an environment is allowed to access the range of memory
// [va, va+len) with permissions 'perm | PTE_P'.
// Normally 'perm' will contain PTE_U at least, but this is not required.
// 'va' and 'len' need not be page-aligned; you must test every page that
// contains any of that range. You will test either 'len/PGSIZE',
// 'len/PGSIZE + 1', or 'len/PGSIZE + 2' pages.
//
// A user program can access a virtual address if (1) the address is below
// ULIM, and (2) the page table gives it permission. These are exactly
// the tests you should implement here.
//
// If there is an error, set the 'user_mem_check_addr' variable to the first
// erroneous virtual address.
//
// Returns 0 if the user program can access this range of addresses,
// and -E_FAULT otherwise.
//
int
user_mem_check(struct Env *env, const void *va, size_t len, int perm)
{
// LAB 3: Your code here.
uint32_t start=(uint32_t)va;
uint32_t end=(uint32_t)(va+len);
perm=perm|PTE_U|PTE_P;
uint32_t i=0;
pte_t* pte;
for(i=start;i<end;i++)
{
if(i>=(uint32_t)ULIM)
{
user_mem_check_addr=i;
return -E_FAULT;
}
pte = pgdir_walk (env->env_pgdir,(void*)i, 0);
if(pte==NULL||((*pte&perm)!=perm))
{
user_mem_check_addr=i;
return -E_FAULT;
}
}
return 0;
}
示例9: page_insert
//
// Map the physical page 'pp' at virtual address 'va'.
// The permissions (the low 12 bits) of the page table entry
// should be set to 'perm|PTE_P'.
//
// Requirements
// - If there is already a page mapped at 'va', it should be page_remove()d.
// - If necessary, on demand, a page table should be allocated and inserted
// into 'pgdir'.
// - pp->pp_ref should be incremented if the insertion succeeds.
// - The TLB must be invalidated if a page was formerly present at 'va'.
//
// Corner-case hint: Make sure to consider what happens when the same
// pp is re-inserted at the same virtual address in the same pgdir.
//
// RETURNS:
// 0 on success
// -E_NO_MEM, if page table couldn't be allocated
//
// Hint: Check out pgdir_walk, page_remove, page2pa, and similar functions.
//
int
page_insert(pde_t *pgdir, struct Page *pp, uintptr_t va, pte_t perm)
{
// Make sure the page table exists. If it doesn't, try and create one.
// If that fails, exit with status -E_NO_MEM.
pte_t *pte = pgdir_walk(pgdir, va, true);
if (pte == NULL) return -E_NO_MEM;
physaddr_t pa = page2pa(pp);
Page *virtpage = page_lookup(pgdir, va, &pte);
// See if there was an existing entry for va
if (virtpage && (*pte & PTE_P)) {
// Is it the same as the one we're entering?
if (PTE_ADDR(*pte) == pa) {
// Then just change the permissions and return
*pte = PTE_ADDR(*pte) | perm | PTE_P;
// Don't forget to invalidate the tlb!
tlb_invalidate(pgdir, va);
// cprintf("Found existing entry... changing permissions.\n");
return 0;
}
// Remove the old entry
// cprintf("Found an existing entry... removing\n");
page_remove(pgdir, va);
}
// Either there was no entry for va, or there was an old entry and we removed it
// cprintf("Adding entry...\n");
*pte = pa | perm | PTE_P;
pp->pp_ref++;
assert(page_lookup(pgdir, va, &pte));
assert(PTE_ADDR(*pte) == pa);
return 0;
}
示例10: user_mem_check
//
// Check that an environment is allowed to access the range of memory
// [va, va+len) with permissions 'perm | PTE_P'.
// Normally 'perm' will contain PTE_U at least, but this is not required.
// 'va' and 'len' need not be page-aligned; you must test every page that
// contains any of that range. You will test either 'len/PGSIZE',
// 'len/PGSIZE + 1', or 'len/PGSIZE + 2' pages.
//
// A user program can access a virtual address if (1) the address is below
// ULIM, and (2) the page table gives it permission. These are exactly
// the tests you should implement here.
//
// If there is an error, set the 'user_mem_check_addr' variable to the first
// erroneous virtual address.
//
// Returns 0 if the user program can access this range of addresses,
// and -E_FAULT otherwise.
//
int
user_mem_check(struct Env *env, const void *va, size_t len, int perm)
{
// LAB 3: Your code here.
/*stone's solution for lab3-B*/
uintptr_t start = (uintptr_t)va;
uintptr_t end = (uintptr_t)va + len;
perm |= PTE_P;
int r = 0;
while (start < end){
if (start > ULIM){
user_mem_check_addr = start;
r = -E_FAULT;
break;
}
pte_t* pte = pgdir_walk(env->env_pgdir, (void*)start, 0);
if (pte == NULL || (*pte & perm) != perm){
user_mem_check_addr = start;
r = -E_FAULT;
break;
}
start = ROUNDDOWN(start+PGSIZE, PGSIZE);
}
return r;
}
示例11: boot_map_region
//
// Map [va, va+size) of virtual address space to physical [pa, pa+size)
// in the page table rooted at pgdir. Size is a multiple of PGSIZE.
// Use permission bits perm|PTE_P for the entries.
//
// This function is only intended to set up the ``static'' mappings
// above UTOP. As such, it should *not* change the pp_ref field on the
// mapped pages.
//
// Hint: the TA solution uses pgdir_walk
void
boot_map_region(pde_t *pgdir, uintptr_t va, size_t size, physaddr_t pa, int perm)
{
// Fill this function in
pte_t * pte;
uintptr_t vtop ;
uintptr_t initva=va;
if( (va%PGSIZE) || (size%PGSIZE) || (pa%PGSIZE) ){
cprintf("va=%x \n ",va);
cprintf("va%PGSIZE=%x \n ",va%PGSIZE);
cprintf("size%PGSIZE=%x \n ",size%PGSIZE);
cprintf("pa%PGSIZE=%x \n ",pa%PGSIZE);
panic("in boot_map_region ,va or size or pa is not aligned \n ");
}
vtop=va +(size-PGSIZE);
// cprintf("va=%x\n",va);
//cprintf("vtop=%x\n",vtop);
while(va<=vtop && va>=initva){
if((pte = pgdir_walk(pgdir, (void *)va, 1))==0)
panic("get pte fail !");
*pte=(pa& (~0xfff) ) | perm | PTE_P;
// cprintf("va %x map to phys %x\n ",va,pa);
va+=PGSIZE;
pa+=PGSIZE;
}
}
示例12: mon_modpageperms
int
mon_modpageperms(int argc, char **argv, struct Trapframe *tf)
{
uintptr_t va_arg;
int perms;
pde_t *pgdir;
pte_t *pte;
if (argc != 3) {
cprintf("usage: modpageperms va perms\n");
return 0;
}
va_arg = (uintptr_t) strtol(argv[1], NULL, 0);
perms = (uintptr_t) strtol(argv[2], NULL, 0);
if (PTE_ADDR(perms)) {
cprintf("perms 0x%03x is invalid\n", perms);
return 0;
}
pgdir = (pde_t *) KADDR(rcr3());
pte = pgdir_walk(pgdir, (void *) va_arg, 0);
if (!pte) {
cprintf("va 0x%x is not mapped\n", va_arg);
return 0;
}
cprintf("va 0x%x existing pte ");
pte_show(*pte);
*pte = PTE_ADDR(*pte) | perms;
cprintf("va 0x%x changed pte ");
pte_show(*pte);
return 0;
}
示例13: page_lookup
struct Page *
page_lookup(Pde *pgdir, u_long va, Pte **ppte)
{
struct Page *ppage;
Pte *pte;
pgdir_walk(pgdir, va, 0, &pte);
//printf("page_lookup:come 1\n");
if (pte == 0) {
return 0;
}
if ((*pte & PTE_V) == 0) {
return 0; //the page is not in memory.
}
//printf("page_lookup:come 2\n");
ppage = pa2page(*pte);
if (ppte) {
*ppte = pte;
}
return ppage;
}
示例14: mon_showvm
int
mon_showvm(int argc, char **argv, struct Trapframe *tf)
{
uintptr_t begin_va, end_va, va, next_va;
pde_t *pgdir;
pte_t *pte;
int i, j;
if (argc != 3) {
cprintf("usage: dumpvm begin_va end_va\n");
return 0;
}
begin_va = (uintptr_t) strtol(argv[1], NULL, 0);
end_va = (uintptr_t) strtol(argv[2], NULL, 0);
if (begin_va > end_va) {
cprintf("begin va (0x%x) is greater than end va (0x%x)\n", begin_va, end_va);
return 0;
}
pgdir = (pde_t *) KADDR(rcr3());
for (i = j = 0, va = begin_va; va <= end_va; va += PGSIZE) {
pte = pgdir_walk(pgdir, (void *) va, 0);
next_va = MIN(ROUNDDOWN(va + PGSIZE, PGSIZE) - 1, end_va);
show_page(pgdir, va, next_va, *pte && (*pte & PTE_P), &i, &j);
}
if (i)
cprintf("\n");
return 0;
}
示例15: segment_alloc
//
// Allocate len bytes of physical memory for environment env,
// and map it at virtual address va in the environment's address space.
// Does not zero or otherwise initialize the mapped pages in any way.
// Pages should be writable by user and kernel.
// Panic if any allocation attempt fails.
//
static void
segment_alloc(struct Env *e, void *va, size_t len)
{
int i;
pde_t * pgdir = e->env_pgdir;
// LAB 3: Your code here.
// (But only if you need it for load_icode.)
//
// Hint: It is easier to use segment_alloc if the caller can pass
// 'va' and 'len' values that are not page-aligned.
// You should round va down, and round (va + len) up.
if (pgdir != NULL) {
uint32_t saddr = (uint32_t)ROUNDDOWN(va, PGSIZE);
uint32_t eaddr = (uint32_t)ROUNDUP(va + len, PGSIZE);
int i,j;
for (i = 0; i < (eaddr - saddr); i += PGSIZE) {
pte_t *pte = pgdir_walk(pgdir, (void *)(saddr + i), 1);
if (!(*pte & PTE_P)) {
struct Page *p;
if (page_alloc(&p)) {
panic("Out of memory");
}
memset(p, 0, sizeof(struct Page));
p->pp_ref += 1;
*pte = page2pa(p)|PTE_P|PTE_W|PTE_U;
}
*pte = *pte|PTE_P|PTE_W|PTE_U;
pgdir [PDX(saddr+i)] = pgdir [PDX(saddr+i)]|PTE_P|PTE_W|PTE_U;
}
}
}