diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/xen/enlighten.c | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index e532eb50e8d7..511f92d79e4a 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -1002,19 +1002,24 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) | |||
1002 | * If the MFN is not in the m2p (provided to us by the hypervisor) this | 1002 | * If the MFN is not in the m2p (provided to us by the hypervisor) this |
1003 | * function won't do anything. In practice this means that the XenBus | 1003 | * function won't do anything. In practice this means that the XenBus |
1004 | * MFN won't be available for the initial domain. */ | 1004 | * MFN won't be available for the initial domain. */ |
1005 | static void __init xen_reserve_mfn(unsigned long mfn) | 1005 | static unsigned long __init xen_reserve_mfn(unsigned long mfn) |
1006 | { | 1006 | { |
1007 | unsigned long pfn; | 1007 | unsigned long pfn, end_pfn = 0; |
1008 | 1008 | ||
1009 | if (!mfn) | 1009 | if (!mfn) |
1010 | return; | 1010 | return end_pfn; |
1011 | |||
1011 | pfn = mfn_to_pfn(mfn); | 1012 | pfn = mfn_to_pfn(mfn); |
1012 | if (phys_to_machine_mapping_valid(pfn)) | 1013 | if (phys_to_machine_mapping_valid(pfn)) { |
1013 | memblock_reserve(PFN_PHYS(pfn), PAGE_SIZE); | 1014 | end_pfn = PFN_PHYS(pfn) + PAGE_SIZE; |
1015 | memblock_reserve(PFN_PHYS(pfn), end_pfn); | ||
1016 | } | ||
1017 | return end_pfn; | ||
1014 | } | 1018 | } |
1015 | static void __init xen_reserve_internals(void) | 1019 | static void __init xen_reserve_internals(void) |
1016 | { | 1020 | { |
1017 | unsigned long size; | 1021 | unsigned long size; |
1022 | unsigned long last_phys = 0; | ||
1018 | 1023 | ||
1019 | if (!xen_pv_domain()) | 1024 | if (!xen_pv_domain()) |
1020 | return; | 1025 | return; |
@@ -1022,12 +1027,13 @@ static void __init xen_reserve_internals(void) | |||
1022 | /* xen_start_info does not exist in the M2P, hence can't use | 1027 | /* xen_start_info does not exist in the M2P, hence can't use |
1023 | * xen_reserve_mfn. */ | 1028 | * xen_reserve_mfn. */ |
1024 | memblock_reserve(__pa(xen_start_info), PAGE_SIZE); | 1029 | memblock_reserve(__pa(xen_start_info), PAGE_SIZE); |
1030 | last_phys = __pa(xen_start_info) + PAGE_SIZE; | ||
1025 | 1031 | ||
1026 | xen_reserve_mfn(PFN_DOWN(xen_start_info->shared_info)); | 1032 | last_phys = max(xen_reserve_mfn(PFN_DOWN(xen_start_info->shared_info)), last_phys); |
1027 | xen_reserve_mfn(xen_start_info->store_mfn); | 1033 | last_phys = max(xen_reserve_mfn(xen_start_info->store_mfn), last_phys); |
1028 | 1034 | ||
1029 | if (!xen_initial_domain()) | 1035 | if (!xen_initial_domain()) |
1030 | xen_reserve_mfn(xen_start_info->console.domU.mfn); | 1036 | last_phys = max(xen_reserve_mfn(xen_start_info->console.domU.mfn), last_phys); |
1031 | 1037 | ||
1032 | if (xen_feature(XENFEAT_auto_translated_physmap)) | 1038 | if (xen_feature(XENFEAT_auto_translated_physmap)) |
1033 | return; | 1039 | return; |
@@ -1043,8 +1049,14 @@ static void __init xen_reserve_internals(void) | |||
1043 | * a lot (and call memblock_reserve for each PAGE), so lets just use | 1049 | * a lot (and call memblock_reserve for each PAGE), so lets just use |
1044 | * the easy way and reserve it wholesale. */ | 1050 | * the easy way and reserve it wholesale. */ |
1045 | memblock_reserve(__pa(xen_start_info->mfn_list), size); | 1051 | memblock_reserve(__pa(xen_start_info->mfn_list), size); |
1046 | 1052 | last_phys = max(__pa(xen_start_info->mfn_list) + size, last_phys); | |
1047 | /* The pagetables are reserved in mmu.c */ | 1053 | /* The pagetables are reserved in mmu.c */ |
1054 | |||
1055 | /* Under 64-bit hypervisor with a 32-bit domain, the hypervisor | ||
1056 | * offsets the pt_base by two pages. Hence the reservation that is done | ||
1057 | * in mmu.c misses two pages. We correct it here if we detect this. */ | ||
1058 | if (last_phys < __pa(xen_start_info->pt_base)) | ||
1059 | memblock_reserve(last_phys, __pa(xen_start_info->pt_base) - last_phys); | ||
1048 | } | 1060 | } |
1049 | void xen_setup_shared_info(void) | 1061 | void xen_setup_shared_info(void) |
1050 | { | 1062 | { |