/*H:430 * (iv) Switching page tables * * Now we've seen all the page table setting and manipulation, let's see * what happens when the Guest changes page tables (ie. changes the top-level * pgdir). This occurs on almost every context switch. */ void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable) { int newpgdir, repin = 0; /* * The very first time they call this, we're actually running without * any page tables; we've been making it up. Throw them away now. */ if (unlikely(cpu->linear_pages)) { release_all_pagetables(cpu->lg); cpu->linear_pages = false; /* Force allocation of a new pgdir. */ newpgdir = ARRAY_SIZE(cpu->lg->pgdirs); } else { /* Look to see if we have this one already. */ newpgdir = find_pgdir(cpu->lg, pgtable); } /* * If not, we allocate or mug an existing one: if it's a fresh one, * repin gets set to 1. */ if (newpgdir == ARRAY_SIZE(cpu->lg->pgdirs)) newpgdir = new_pgdir(cpu, pgtable, &repin); /* Change the current pgd index to the new one. */ cpu->cpu_pgd = newpgdir; /* If it was completely blank, we map in the Guest kernel stack */ if (repin) pin_stack_pages(cpu); }
/*H:500 * (vii) Setting up the page tables initially. * * When a Guest is first created, set initialize a shadow page table which * we will populate on future faults. The Guest doesn't have any actual * pagetables yet, so we set linear_pages to tell demand_page() to fake it * for the moment. */ int init_guest_pagetable(struct lguest *lg) { struct lg_cpu *cpu = &lg->cpus[0]; int allocated = 0; /* lg (and lg->cpus[]) starts zeroed: this allocates a new pgdir */ cpu->cpu_pgd = new_pgdir(cpu, 0, &allocated); if (!allocated) return -ENOMEM; /* We start with a linear mapping until the initialize. */ cpu->linear_pages = true; return 0; }
/*H:500 * (vii) Setting up the page tables initially. * * When a Guest is first created, set initialize a shadow page table which * we will populate on future faults. The Guest doesn't have any actual * pagetables yet, so we set linear_pages to tell demand_page() to fake it * for the moment. * * We do need the Switcher to be mapped at all times, so we allocate that * part of the Guest page table here. */ int init_guest_pagetable(struct lguest *lg) { struct lg_cpu *cpu = &lg->cpus[0]; int allocated = 0; /* lg (and lg->cpus[]) starts zeroed: this allocates a new pgdir */ cpu->cpu_pgd = new_pgdir(cpu, 0, &allocated); if (!allocated) return -ENOMEM; /* We start with a linear mapping until the initialize. */ cpu->linear_pages = true; /* Allocate the page tables for the Switcher. */ if (!allocate_switcher_mapping(cpu)) { release_all_pagetables(lg); return -ENOMEM; } return 0; }