diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 8431f062af..a8bf2c9bb0 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -497,6 +497,17 @@ static void __init kexec_reserve_area(struct e820map *e820) #endif } +static inline bool_t using_2M_mapping(void) +{ + return !l1_table_offset((unsigned long)__2M_text_end) && + !l1_table_offset((unsigned long)__2M_rodata_start) && + !l1_table_offset((unsigned long)__2M_rodata_end) && + !l1_table_offset((unsigned long)__2M_init_start) && + !l1_table_offset((unsigned long)__2M_init_end) && + !l1_table_offset((unsigned long)__2M_rwdata_start) && + !l1_table_offset((unsigned long)__2M_rwdata_end); +} + static void noinline init_done(void) { void *va; @@ -510,9 +521,18 @@ static void noinline init_done(void) clear_page(va); /* Destroy Xen's mappings, and reuse the pages. */ - destroy_xen_mappings((unsigned long)&__2M_init_start, - (unsigned long)&__2M_init_end); - init_xenheap_pages(__pa(__2M_init_start), __pa(__2M_init_end)); + if ( using_2M_mapping() ) + { + destroy_xen_mappings((unsigned long)&__2M_init_start, + (unsigned long)&__2M_init_end); + init_xenheap_pages(__pa(__2M_init_start), __pa(__2M_init_end)); + } + else + { + destroy_xen_mappings((unsigned long)&__init_begin, + (unsigned long)&__init_end); + init_xenheap_pages(__pa(__init_begin), __pa(__init_end)); + } printk("Freed %ldkB init memory.\n", (long)(__init_end-__init_begin)>>10); @@ -922,6 +942,8 @@ void __init noreturn __start_xen(unsigned long mbi_p) * Undo the temporary-hooking of the l1_identmap. __2M_text_start * is contained in this PTE. */ + BUG_ON(l2_table_offset((unsigned long)_erodata) == + l2_table_offset((unsigned long)_stext)); *pl2e++ = l2e_from_pfn(xen_phys_start >> PAGE_SHIFT, PAGE_HYPERVISOR_RX | _PAGE_PSE); for ( i = 1; i < L2_PAGETABLE_ENTRIES; i++, pl2e++ ) @@ -931,6 +953,13 @@ void __init noreturn __start_xen(unsigned long mbi_p) if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) ) continue; + if ( !using_2M_mapping() ) + { + *pl2e = l2e_from_intpte(l2e_get_intpte(*pl2e) + + xen_phys_start); + continue; + } + if ( i < l2_table_offset((unsigned long)&__2M_text_end) ) { flags = PAGE_HYPERVISOR_RX | _PAGE_PSE; diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S index 29221652f6..5cb9741636 100644 --- a/xen/arch/x86/xen.lds.S +++ b/xen/arch/x86/xen.lds.S @@ -53,11 +53,14 @@ SECTIONS _etext = .; /* End of text section */ } :text = 0x9090 +#ifdef EFI . = ALIGN(MB(2)); +#endif __2M_text_end = .; __2M_rodata_start = .; /* Start of 2M superpages, mapped RO. */ .rodata : { + _srodata = .; /* Bug frames table */ . = ALIGN(4); __start_bug_frames = .; @@ -79,9 +82,12 @@ SECTIONS *(.lockprofile.data) __lock_profile_end = .; #endif + _erodata = .; } :text +#ifdef EFI . = ALIGN(MB(2)); +#endif __2M_rodata_end = .; __2M_init_start = .; /* Start of 2M superpages, mapped RWX (boot only). */ @@ -148,7 +154,9 @@ SECTIONS . = ALIGN(PAGE_SIZE); __init_end = .; +#ifdef EFI . = ALIGN(MB(2)); +#endif __2M_init_end = .; __2M_rwdata_start = .; /* Start of 2M superpages, mapped RW. */ @@ -200,7 +208,9 @@ SECTIONS } :text _end = . ; +#ifdef EFI . = ALIGN(MB(2)); +#endif __2M_rwdata_end = .; #ifdef EFI @@ -250,6 +260,7 @@ ASSERT(kexec_reloc_size - kexec_reloc <= PAGE_SIZE, "kexec_reloc is too large") #endif ASSERT(IS_ALIGNED(__2M_text_start, MB(2)), "__2M_text_start misaligned") +#ifdef EFI ASSERT(IS_ALIGNED(__2M_text_end, MB(2)), "__2M_text_end misaligned") ASSERT(IS_ALIGNED(__2M_rodata_start, MB(2)), "__2M_rodata_start misaligned") ASSERT(IS_ALIGNED(__2M_rodata_end, MB(2)), "__2M_rodata_end misaligned") @@ -257,6 +268,7 @@ ASSERT(IS_ALIGNED(__2M_init_start, MB(2)), "__2M_init_start misaligned") ASSERT(IS_ALIGNED(__2M_init_end, MB(2)), "__2M_init_end misaligned") ASSERT(IS_ALIGNED(__2M_rwdata_start, MB(2)), "__2M_rwdata_start misaligned") ASSERT(IS_ALIGNED(__2M_rwdata_end, MB(2)), "__2M_rwdata_end misaligned") +#endif ASSERT(IS_ALIGNED(cpu0_stack, STACK_SIZE), "cpu0_stack misaligned")