diff options
author | Keir Fraser <keir@xen.org> | 2010-11-09 11:49:49 +0000 |
---|---|---|
committer | Keir Fraser <keir@xen.org> | 2010-11-09 11:49:49 +0000 |
commit | 5a771800114c437fb857b44b3ed74f60e87979c2 (patch) | |
tree | a9a1089b753cdfb65757b08c6406d1721d989ad3 /xen/arch/x86/domain_build.c | |
parent | e04aea7477c379e904e7520bdfa2f42284427a97 (diff) | |
download | xen-5a771800114c437fb857b44b3ed74f60e87979c2.tar.gz xen-5a771800114c437fb857b44b3ed74f60e87979c2.tar.bz2 xen-5a771800114c437fb857b44b3ed74f60e87979c2.zip |
x86: do away with the boot time low-memory 1:1 mapping
By doing so, we're no longer restricted to be able to place all boot
loader modules into the low 1Gb/4Gb (32-/64-bit) of memory, nor is
there a dependency anymore on where the boot loader places the
modules.
We're also no longer restricted to copy the modules into a place below
4Gb, nor to put them all together into a single piece of memory.
Further it allows even the 32-bit Dom0 kernel to be loaded anywhere in
physical memory (except if it doesn't support PAE-above-4G).
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Diffstat (limited to 'xen/arch/x86/domain_build.c')
-rw-r--r-- | xen/arch/x86/domain_build.c | 106 |
1 files changed, 71 insertions, 35 deletions
diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index 75479ea4ec..903be9a40e 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -31,6 +31,7 @@ #include <asm/p2m.h> #include <asm/e820.h> #include <asm/acpi.h> +#include <asm/setup.h> #include <asm/bzimage.h> /* for bzimage_parse */ #include <asm/io_apic.h> @@ -284,9 +285,9 @@ static void __init process_dom0_ioports_disable(void) int __init construct_dom0( struct domain *d, - unsigned long _image_base, - unsigned long _image_start, unsigned long image_len, - unsigned long _initrd_start, unsigned long initrd_len, + const module_t *image, unsigned long image_headroom, + const module_t *initrd, + void *(*bootstrap_map)(const module_t *), char *cmdline) { int i, cpu, rc, compatible, compat32, order, machine; @@ -301,16 +302,14 @@ int __init construct_dom0( start_info_t *si; struct vcpu *v = d->vcpu[0]; unsigned long long value; -#if defined(__i386__) - char *image_base = (char *)_image_base; /* use lowmem mappings */ - char *image_start = (char *)_image_start; /* use lowmem mappings */ - char *initrd_start = (char *)_initrd_start; /* use lowmem mappings */ -#elif defined(__x86_64__) - char *image_base = __va(_image_base); - char *image_start = __va(_image_start); - char *initrd_start = __va(_initrd_start); -#endif -#if CONFIG_PAGING_LEVELS >= 4 + char *image_base = bootstrap_map(image); + unsigned long image_len = image->mod_end; + char *image_start = image_base + image_headroom; + unsigned long initrd_len = initrd ? initrd->mod_end : 0; +#if CONFIG_PAGING_LEVELS < 4 + module_t mpt; + void *mpt_ptr; +#else l4_pgentry_t *l4tab = NULL, *l4start = NULL; #endif l3_pgentry_t *l3tab = NULL, *l3start = NULL; @@ -340,7 +339,7 @@ int __init construct_dom0( unsigned long v_end; /* Machine address of next candidate page-table page. */ - unsigned long mpt_alloc; + paddr_t mpt_alloc; /* Sanity! */ BUG_ON(d->domain_id != 0); @@ -495,17 +494,17 @@ int __init construct_dom0( if ( (1UL << order) > nr_pages ) panic("Domain 0 allocation is too small for kernel image.\n"); -#ifdef __i386__ - /* Ensure that our low-memory 1:1 mapping covers the allocation. */ - page = alloc_domheap_pages(d, order, MEMF_bits(30)); -#else if ( parms.p2m_base != UNSET_ADDR ) { vphysmap_start = parms.p2m_base; vphysmap_end = vphysmap_start + nr_pages * sizeof(unsigned long); } - page = alloc_domheap_pages(d, order, 0); +#ifdef __i386__ + if ( !test_bit(XENFEAT_pae_pgdir_above_4gb, parms.f_supported) ) + page = alloc_domheap_pages(d, order, MEMF_bits(32)); + else #endif + page = alloc_domheap_pages(d, order, 0); if ( page == NULL ) panic("Not enough RAM for domain 0 allocation.\n"); alloc_spfn = page_to_mfn(page); @@ -534,8 +533,7 @@ int __init construct_dom0( _p(v_start), _p(v_end)); printk(" ENTRY ADDRESS: %p\n", _p(parms.virt_entry)); - mpt_alloc = (vpt_start - v_start) + - (unsigned long)pfn_to_paddr(alloc_spfn); + mpt_alloc = (vpt_start - v_start) + pfn_to_paddr(alloc_spfn); #if defined(__i386__) /* @@ -548,17 +546,25 @@ int __init construct_dom0( return -EINVAL; } + mpt.mod_start = mpt_alloc >> PAGE_SHIFT; + mpt.mod_end = vpt_end - vpt_start; + mpt_ptr = bootstrap_map(&mpt); +#define MPT_ALLOC(n) (mpt_ptr += (n)*PAGE_SIZE, mpt_alloc += (n)*PAGE_SIZE) + /* WARNING: The new domain must have its 'processor' field filled in! */ - l3start = l3tab = (l3_pgentry_t *)mpt_alloc; mpt_alloc += PAGE_SIZE; - l2start = l2tab = (l2_pgentry_t *)mpt_alloc; mpt_alloc += 4*PAGE_SIZE; + l3start = l3tab = mpt_ptr; MPT_ALLOC(1); + l2start = l2tab = mpt_ptr; MPT_ALLOC(4); for (i = 0; i < L3_PAGETABLE_ENTRIES; i++) { - copy_page(l2tab + i * L2_PAGETABLE_ENTRIES, - idle_pg_table_l2 + i * L2_PAGETABLE_ENTRIES); - l3tab[i] = l3e_from_paddr((u32)l2tab + i*PAGE_SIZE, L3_PROT); + if ( i < 3 ) + clear_page(l2tab + i * L2_PAGETABLE_ENTRIES); + else + copy_page(l2tab + i * L2_PAGETABLE_ENTRIES, + idle_pg_table_l2 + i * L2_PAGETABLE_ENTRIES); + l3tab[i] = l3e_from_pfn(mpt.mod_start + 1 + i, L3_PROT); l2tab[(LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT)+i] = - l2e_from_paddr((u32)l2tab + i*PAGE_SIZE, __PAGE_HYPERVISOR); + l2e_from_pfn(mpt.mod_start + 1 + i, __PAGE_HYPERVISOR); } - v->arch.guest_table = pagetable_from_paddr((unsigned long)l3start); + v->arch.guest_table = pagetable_from_pfn(mpt.mod_start); for ( i = 0; i < PDPT_L2_ENTRIES; i++ ) l2tab[l2_linear_offset(PERDOMAIN_VIRT_START) + i] = @@ -570,9 +576,9 @@ int __init construct_dom0( { if ( !((unsigned long)l1tab & (PAGE_SIZE-1)) ) { - l1start = l1tab = (l1_pgentry_t *)mpt_alloc; - mpt_alloc += PAGE_SIZE; - *l2tab = l2e_from_paddr((unsigned long)l1start, L2_PROT); + l1tab = mpt_ptr; + *l2tab = l2e_from_paddr(mpt_alloc, L2_PROT); + MPT_ALLOC(1); l2tab++; clear_page(l1tab); if ( count == 0 ) @@ -587,11 +593,14 @@ int __init construct_dom0( mfn++; } +#undef MPT_ALLOC /* Pages that are part of page tables must be read only. */ + mpt_alloc = (paddr_t)mpt.mod_start << PAGE_SHIFT; + mpt_ptr = l3start; l2tab = l2start + l2_linear_offset(vpt_start); - l1start = l1tab = (l1_pgentry_t *)(u32)l2e_get_paddr(*l2tab); - l1tab += l1_table_offset(vpt_start); + l1start = mpt_ptr + (l2e_get_paddr(*l2tab) - mpt_alloc); + l1tab = l1start + l1_table_offset(vpt_start); for ( count = 0; count < nr_pt_pages; count++ ) { page = mfn_to_page(l1e_get_pfn(*l1tab)); @@ -627,9 +636,15 @@ int __init construct_dom0( break; } if ( !((unsigned long)++l1tab & (PAGE_SIZE - 1)) ) - l1start = l1tab = (l1_pgentry_t *)(u32)l2e_get_paddr(*++l2tab); + l1tab = mpt_ptr + (l2e_get_paddr(*++l2tab) - mpt_alloc); } + /* + * Put Xen's first L3 entry into Dom0's page tables so that updates + * through bootstrap_map() will affect the page tables we will run on. + */ + l3start[0] = l3e_from_paddr(__pa(idle_pg_table_l2), L3_PROT); + #elif defined(__x86_64__) /* Overlap with Xen protected area? */ @@ -807,6 +822,7 @@ int __init construct_dom0( /* Copy the OS image and free temporary buffer. */ elf.dest = (void*)vkern_start; elf_load_binary(&elf); + bootstrap_map(NULL); if ( UNSET_ADDR != parms.virt_hypercall ) { @@ -823,7 +839,12 @@ int __init construct_dom0( /* Copy the initial ramdisk. */ if ( initrd_len != 0 ) + { + char *initrd_start = bootstrap_map(initrd); + memcpy((void *)vinitrd_start, initrd_start, initrd_len); + bootstrap_map(NULL); + } /* Free temporary buffers. */ discard_initial_images(); @@ -1033,7 +1054,22 @@ int __init construct_dom0( write_ptbase(current); #if defined(__i386__) - /* Destroy low mappings - they were only for our convenience. */ + /* Restore Dom0's first L3 entry. */ + mpt.mod_end = 5 * PAGE_SIZE; + l3start = mpt_ptr = bootstrap_map(&mpt); + l2start = mpt_ptr + PAGE_SIZE; + l3start[0] = l3e_from_pfn(mpt.mod_start + 1, L3_PROT); + + /* Re-setup CR3 */ + if ( paging_mode_enabled(d) ) + paging_update_paging_modes(v); + else + update_cr3(v); + + /* + * Destroy low mappings - they were only for our convenience. Note + * that zap_low_mappings() exceeds what bootstrap_map(NULL) would do. + */ zap_low_mappings(l2start); #endif |