ia64/xen-unstable

changeset 2436:8ae0831442b8

bitkeeper revision 1.1159.69.18 (413baa1bXGfcJkRulx6s9wKLDL1Kkg)

Clean up pagetable bootstrap in Linux 2.6. Write-protecting the two
pagetables is now clearer, and we properly deallocate the old pagetables
when we are done with them.
author kaf24@freefall.cl.cam.ac.uk
date Mon Sep 06 00:06:51 2004 +0000 (2004-09-06)
parents 791d6dc54a24
children 07ee497a8090
files linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/cpu/common.c linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h xen/common/domain.c
line diff
     1.1 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/cpu/common.c	Sun Sep 05 18:28:08 2004 +0000
     1.2 +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/cpu/common.c	Mon Sep 06 00:06:51 2004 +0000
     1.3 @@ -504,7 +504,7 @@ void __init cpu_gdt_init(struct Xgt_desc
     1.4  	     va < gdt_descr->address + gdt_descr->size;
     1.5  	     va += PAGE_SIZE, f++) {
     1.6  		frames[f] = virt_to_machine(va) >> PAGE_SHIFT;
     1.7 -		wrprotect_bootpt(swapper_pg_dir, (void *)va, 1);
     1.8 +		protect_page(swapper_pg_dir, (void *)va, PROT_ON);
     1.9  	}
    1.10  	flush_page_update_queue();
    1.11  	if (HYPERVISOR_set_gdt(frames, gdt_descr->size / 8))
     2.1 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c	Sun Sep 05 18:28:08 2004 +0000
     2.2 +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c	Mon Sep 06 00:06:51 2004 +0000
     2.3 @@ -76,11 +76,9 @@ static pte_t * __init one_page_table_ini
     2.4  	if (pmd_none(*pmd)) {
     2.5  		pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
     2.6  		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
     2.7 -		flush_page_update_queue();
     2.8  		if (page_table != pte_offset_kernel(pmd, 0))
     2.9  			BUG();	
    2.10  
    2.11 -		wrprotect_bootpt((pgd_t *)start_info.pt_base, page_table, 1);
    2.12  		return page_table;
    2.13  	}
    2.14  	
    2.15 @@ -125,8 +123,7 @@ static void __init page_table_range_init
    2.16  	}
    2.17  }
    2.18  
    2.19 -/* NOTE: caller must call flush_page_update_queue() */
    2.20 -void __init wrprotect_bootpt(pgd_t *pgd, void *page, int set)
    2.21 +void __init protect_page(pgd_t *pgd, void *page, int mode)
    2.22  {
    2.23  	pmd_t *pmd;
    2.24  	pte_t *pte;
    2.25 @@ -138,31 +135,25 @@ void __init wrprotect_bootpt(pgd_t *pgd,
    2.26  	pte = pte_offset_kernel(pmd, addr);
    2.27  	if (!pte_present(*pte))
    2.28  		return;
    2.29 -	queue_l1_entry_update(pte, set ? pte_val_ma(*pte) & ~_PAGE_RW :
    2.30 -	    pte_val_ma(*pte) | _PAGE_RW);
    2.31 +	queue_l1_entry_update(pte, mode ? pte_val_ma(*pte) & ~_PAGE_RW :
    2.32 +					pte_val_ma(*pte) | _PAGE_RW);
    2.33  }
    2.34  
    2.35 -/* NOTE: caller must call flush_page_update_queue() */
    2.36 -static void __init protect_bootpt_entries(pgd_t *spgd, pgd_t *dpgd, int set,
    2.37 -    int pmdupdate, int pmdset)
    2.38 +void __init protect_pagetable(pgd_t *dpgd, pgd_t *spgd, int mode)
    2.39  {
    2.40  	pmd_t *pmd;
    2.41  	pte_t *pte;
    2.42  	int pgd_idx, pmd_idx;
    2.43  
    2.44 +	protect_page(dpgd, spgd, mode);
    2.45 +
    2.46  	for (pgd_idx = 0; pgd_idx < PTRS_PER_PGD_NO_HV; spgd++, pgd_idx++) {
    2.47  		pmd = pmd_offset(spgd, 0);
    2.48  		if (pmd_none(*pmd))
    2.49  			continue;
    2.50 -		if (pmdupdate)
    2.51 -			wrprotect_bootpt(dpgd, pmd, pmdset);
    2.52  		for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD; pmd++, pmd_idx++) {
    2.53 -			if (cpu_has_pse) {
    2.54 -				/* XXX */
    2.55 -			} else {
    2.56 -				pte = pte_offset_kernel(pmd, 0);
    2.57 -				wrprotect_bootpt(dpgd, pte, set);
    2.58 -			}
    2.59 +			pte = pte_offset_kernel(pmd, 0);
    2.60 +			protect_page(dpgd, pte, mode);
    2.61  		}
    2.62  	}
    2.63  }
    2.64 @@ -537,18 +528,6 @@ out:
    2.65  #endif
    2.66  
    2.67  /*
    2.68 - * - write protect new L1 pages in old pgd
    2.69 - * - write protect new pgd page in old pgd
    2.70 - * - write protect new pgd page in new pgd
    2.71 - * - write protect new L1 pages in new pgd
    2.72 - * - write protect old L1 pages in new pgd and write protect old pgd in
    2.73 - *   new pgd
    2.74 - * - pin new pgd
    2.75 - * - switch to new pgd
    2.76 - * - unpin old pgd
    2.77 - * - make old L1 pages and old pgd page writeable in new pgd
    2.78 - */
    2.79 -/*
    2.80   * paging_init() sets up the page tables - note that the first 8MB are
    2.81   * already mapped by head.S.
    2.82   *
    2.83 @@ -557,6 +536,8 @@ out:
    2.84   */
    2.85  void __init paging_init(void)
    2.86  {
    2.87 +	pgd_t *old_pgd = (pgd_t *)start_info.pt_base;
    2.88 +	pgd_t *new_pgd = swapper_pg_dir;
    2.89  #ifdef CONFIG_XEN_PHYSDEV_ACCESS
    2.90  	int i;
    2.91  #endif
    2.92 @@ -569,20 +550,24 @@ void __init paging_init(void)
    2.93  
    2.94  	pagetable_init();
    2.95  
    2.96 -	wrprotect_bootpt((pgd_t *)start_info.pt_base, swapper_pg_dir, 1);
    2.97 -	wrprotect_bootpt(swapper_pg_dir, swapper_pg_dir, 1);
    2.98 +	/*
    2.99 +	 * Write-protect both page tables within both page tables.
   2.100 +	 * That's three ops, as the old p.t. is already protected
   2.101 +	 * within the old p.t. Then pin the new table, switch tables,
   2.102 +	 * and unprotect the old table.
   2.103 +	 */
   2.104 +	protect_pagetable(new_pgd, old_pgd, PROT_ON);
   2.105 +	protect_pagetable(new_pgd, new_pgd, PROT_ON);
   2.106 +	protect_pagetable(old_pgd, new_pgd, PROT_ON);
   2.107 +	queue_pgd_pin(__pa(new_pgd));
   2.108 +	load_cr3(new_pgd);
   2.109 +	queue_pgd_unpin(__pa(old_pgd));
   2.110 +	__flush_tlb_all(); /* implicit flush */
   2.111 +	protect_pagetable(new_pgd, old_pgd, PROT_OFF);
   2.112  	flush_page_update_queue();
   2.113 -	protect_bootpt_entries(swapper_pg_dir, swapper_pg_dir, 1, 0, 0);
   2.114 -	protect_bootpt_entries((pgd_t *)start_info.pt_base, swapper_pg_dir,
   2.115 -	    1, 1, 1);
   2.116 -	queue_pgd_pin(__pa(swapper_pg_dir));
   2.117 -	load_cr3(swapper_pg_dir);
   2.118 -	__flush_tlb_all(); /* implicit flush */
   2.119 -	queue_pgd_unpin(__pa(start_info.pt_base));
   2.120 -	protect_bootpt_entries((pgd_t *)start_info.pt_base, swapper_pg_dir,
   2.121 -	    0, 1, 0);
   2.122 -	wrprotect_bootpt((pgd_t *)start_info.pt_base, swapper_pg_dir, 0);
   2.123 -	flush_page_update_queue();
   2.124 +
   2.125 +	/* Completely detached from old tables, so free them. */
   2.126 +	free_bootmem(__pa(old_pgd), start_info.nr_pt_frames << PAGE_SHIFT);
   2.127  
   2.128  #ifdef CONFIG_X86_PAE
   2.129  	/*
     3.1 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h	Sun Sep 05 18:28:08 2004 +0000
     3.2 +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h	Mon Sep 06 00:06:51 2004 +0000
     3.3 @@ -34,7 +34,11 @@ void xen_cpu_idle (void);
     3.4  void do_hypervisor_callback(struct pt_regs *regs);
     3.5  
     3.6  /* arch/xen/i386/mm/init.c */
     3.7 -void wrprotect_bootpt(pgd_t *, void *, int);
     3.8 +/* NOTE: caller must call flush_page_update_queue() */
     3.9 +#define PROT_ON  1
    3.10 +#define PROT_OFF 0
    3.11 +void /* __init */ protect_page(pgd_t *dpgd, void *page, int mode);
    3.12 +void /* __init */ protect_pagetable(pgd_t *dpgd, pgd_t *spgd, int mode);
    3.13  
    3.14  /* arch/xen/i386/kernel/head.S */
    3.15  void lgdt_finish(void);
     4.1 --- a/xen/common/domain.c	Sun Sep 05 18:28:08 2004 +0000
     4.2 +++ b/xen/common/domain.c	Mon Sep 06 00:06:51 2004 +0000
     4.3 @@ -65,7 +65,7 @@ struct domain *do_createdomain(domid_t d
     4.4          strncpy(d->name, buf, MAX_DOMAIN_NAME);
     4.5          d->name[MAX_DOMAIN_NAME-1] = '\0';
     4.6  
     4.7 -	arch_do_createdomain(d);
     4.8 +        arch_do_createdomain(d);
     4.9  
    4.10          sched_add_domain(d);
    4.11  
    4.12 @@ -152,8 +152,8 @@ void domain_crash(void)
    4.13  {
    4.14      struct domain *d;
    4.15  
    4.16 -    if (current->domain == 0)
    4.17 -	BUG();
    4.18 +    if ( current->domain == 0 )
    4.19 +        BUG();
    4.20  
    4.21      set_bit(DF_CRASHED, &current->flags);
    4.22