bnc#828623 - bnc#839596 - VUL-0: CVE-2013-1442: XSA-62: xen: Information leak on AVX and/or LWP capable CPUs 5242a1b5-x86-xsave-initialize-extended-register-state-when-guests-enable-it.patch - bnc#840592 - VUL-0: CVE-2013-4355: XSA-63: xen: Information leaks through I/O instruction emulation CVE-2013-4355-xsa63.patch - bnc#840593 - VUL-0: CVE-2013-4356: XSA-64: xen: Memory accessible by 64-bit PV guests under live migration CVE-2013-4356-xsa64.patch - bnc#841766 - VUL-1: CVE-2013-4361: XSA-66: xen: Information leak through fbld instruction emulation CVE-2013-4361-xsa66.patch - bnc#833796 - L3: Xen: migration broken from xsave-capable to xsave-incapable host 52205e27-x86-xsave-initialization-improvements.patch 522dc0e6-x86-xsave-fix-migration-from-xsave-capable-to-xsave-incapable-host.patch - bnc#839600 - [HP BCS SLES11 Bug]: In HP’s UEFI x86_64 platform and sles11sp3 with xen environment, xen hypervisor will panic on multiple blades nPar. 523172d5-x86-fix-memory-cut-off-when-using-PFN-compression.patch - bnc#833251 - [HP BCS SLES11 Bug]: In HP’s UEFI x86_64 platform and with xen environment, in booting stage ,xen hypervisor will panic. 522d896b-x86-EFI-properly-handle-run-time-memory-regions-outside-the-1-1-map.patch - bnc#834751 - [HP BCS SLES11 Bug]: In xen, “shutdown –y 0 –h” cannot power off system 522d896b-x86-EFI-properly-handle-run-time-memory-regions-outside-the-1-1-map.patch OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=274
196 lines
7.1 KiB
Diff
196 lines
7.1 KiB
Diff
References: bnc#833251, bnc#834751
|
|
|
|
# Commit a350f3f43bcfac9c1591e28d8e43c505fcb172a5
|
|
# Date 2013-09-09 10:40:11 +0200
|
|
# Author Jan Beulich <jbeulich@suse.com>
|
|
# Committer Jan Beulich <jbeulich@suse.com>
|
|
x86/EFI: properly handle run time memory regions outside the 1:1 map
|
|
|
|
Namely with PFN compression, MMIO ranges that the firmware may need
|
|
runtime access to can live in the holes that gets shrunk/eliminated by
|
|
PFN compression, and hence no mappings would result from simply
|
|
copying Xen's direct mapping table's L3 page table entries. Build
|
|
mappings for this "manually" in the EFI runtime call 1:1 page tables.
|
|
|
|
Use the opportunity to also properly identify (via a forcibly undefined
|
|
manifest constant) all the disabled code regions associated with it not
|
|
being acceptable for us to call SetVirtualAddressMap().
|
|
|
|
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
|
|
|
--- a/xen/arch/x86/efi/boot.c
|
|
+++ b/xen/arch/x86/efi/boot.c
|
|
@@ -26,6 +26,9 @@
|
|
#include <asm/msr.h>
|
|
#include <asm/processor.h>
|
|
|
|
+/* Using SetVirtualAddressMap() is incompatible with kexec: */
|
|
+#undef USE_SET_VIRTUAL_ADDRESS_MAP
|
|
+
|
|
#define SHIM_LOCK_PROTOCOL_GUID \
|
|
{ 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
|
|
|
|
@@ -1434,7 +1437,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
|
|
|
|
/* Adjust pointers into EFI. */
|
|
efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START;
|
|
-#if 0 /* Only needed when using virtual mode (see efi_init_memory()). */
|
|
+#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
|
|
efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START;
|
|
#endif
|
|
efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START;
|
|
@@ -1477,6 +1480,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SY
|
|
for( ; ; ); /* not reached */
|
|
}
|
|
|
|
+#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
|
|
static __init void copy_mapping(unsigned long mfn, unsigned long end,
|
|
bool_t (*is_valid)(unsigned long smfn,
|
|
unsigned long emfn))
|
|
@@ -1520,6 +1524,7 @@ static bool_t __init rt_range_valid(unsi
|
|
{
|
|
return 1;
|
|
}
|
|
+#endif
|
|
|
|
#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \
|
|
(EFI_PAGE_SHIFT + BITS_PER_LONG - 32))
|
|
@@ -1527,6 +1532,13 @@ static bool_t __init rt_range_valid(unsi
|
|
void __init efi_init_memory(void)
|
|
{
|
|
unsigned int i;
|
|
+#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
|
|
+ struct rt_extra {
|
|
+ struct rt_extra *next;
|
|
+ unsigned long smfn, emfn;
|
|
+ unsigned int prot;
|
|
+ } *extra, *extra_head = NULL;
|
|
+#endif
|
|
|
|
printk(XENLOG_INFO "EFI memory map:\n");
|
|
for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
|
|
@@ -1573,6 +1585,8 @@ void __init efi_init_memory(void)
|
|
!(smfn & pfn_hole_mask) &&
|
|
!((smfn ^ (emfn - 1)) & ~pfn_pdx_bottom_mask) )
|
|
{
|
|
+ if ( (unsigned long)mfn_to_virt(emfn - 1) >= HYPERVISOR_VIRT_END )
|
|
+ prot &= ~_PAGE_GLOBAL;
|
|
if ( map_pages_to_xen((unsigned long)mfn_to_virt(smfn),
|
|
smfn, emfn - smfn, prot) == 0 )
|
|
desc->VirtualStart =
|
|
@@ -1581,15 +1595,29 @@ void __init efi_init_memory(void)
|
|
printk(XENLOG_ERR "Could not map MFNs %#lx-%#lx\n",
|
|
smfn, emfn - 1);
|
|
}
|
|
+#ifndef USE_SET_VIRTUAL_ADDRESS_MAP
|
|
+ else if ( !((desc->PhysicalStart + len - 1) >> (VADDR_BITS - 1)) &&
|
|
+ (extra = xmalloc(struct rt_extra)) != NULL )
|
|
+ {
|
|
+ extra->smfn = smfn;
|
|
+ extra->emfn = emfn;
|
|
+ extra->prot = prot & ~_PAGE_GLOBAL;
|
|
+ extra->next = extra_head;
|
|
+ extra_head = extra;
|
|
+ desc->VirtualStart = desc->PhysicalStart;
|
|
+ }
|
|
+#endif
|
|
else
|
|
{
|
|
+#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
|
|
/* XXX allocate e.g. down from FIXADDR_START */
|
|
+#endif
|
|
printk(XENLOG_ERR "No mapping for MFNs %#lx-%#lx\n",
|
|
smfn, emfn - 1);
|
|
}
|
|
}
|
|
|
|
-#if 0 /* Incompatible with kexec. */
|
|
+#ifdef USE_SET_VIRTUAL_ADDRESS_MAP
|
|
efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size,
|
|
mdesc_ver, efi_memmap);
|
|
#else
|
|
@@ -1600,20 +1628,74 @@ void __init efi_init_memory(void)
|
|
|
|
copy_mapping(0, max_page, ram_range_valid);
|
|
|
|
- /* Insert non-RAM runtime mappings. */
|
|
+ /* Insert non-RAM runtime mappings inside the direct map. */
|
|
for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
|
|
{
|
|
const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
|
|
|
|
- if ( desc->Attribute & EFI_MEMORY_RUNTIME )
|
|
+ if ( (desc->Attribute & EFI_MEMORY_RUNTIME) &&
|
|
+ desc->VirtualStart != INVALID_VIRTUAL_ADDRESS &&
|
|
+ desc->VirtualStart != desc->PhysicalStart )
|
|
+ copy_mapping(PFN_DOWN(desc->PhysicalStart),
|
|
+ PFN_UP(desc->PhysicalStart +
|
|
+ (desc->NumberOfPages << EFI_PAGE_SHIFT)),
|
|
+ rt_range_valid);
|
|
+ }
|
|
+
|
|
+ /* Insert non-RAM runtime mappings outside of the direct map. */
|
|
+ while ( (extra = extra_head) != NULL )
|
|
+ {
|
|
+ unsigned long addr = extra->smfn << PAGE_SHIFT;
|
|
+ l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(addr)];
|
|
+ l3_pgentry_t *pl3e;
|
|
+ l2_pgentry_t *pl2e;
|
|
+ l1_pgentry_t *l1t;
|
|
+
|
|
+ if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
|
|
{
|
|
- if ( desc->VirtualStart != INVALID_VIRTUAL_ADDRESS )
|
|
- copy_mapping(PFN_DOWN(desc->PhysicalStart),
|
|
- PFN_UP(desc->PhysicalStart +
|
|
- (desc->NumberOfPages << EFI_PAGE_SHIFT)),
|
|
- rt_range_valid);
|
|
- else
|
|
- /* XXX */;
|
|
+ pl3e = alloc_xen_pagetable();
|
|
+ BUG_ON(!pl3e);
|
|
+ clear_page(pl3e);
|
|
+ efi_l4_pgtable[l4_table_offset(addr)] =
|
|
+ l4e_from_paddr(virt_to_maddr(pl3e), __PAGE_HYPERVISOR);
|
|
+ }
|
|
+ else
|
|
+ pl3e = l4e_to_l3e(l4e);
|
|
+ pl3e += l3_table_offset(addr);
|
|
+ if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
|
|
+ {
|
|
+ pl2e = alloc_xen_pagetable();
|
|
+ BUG_ON(!pl2e);
|
|
+ clear_page(pl2e);
|
|
+ *pl3e = l3e_from_paddr(virt_to_maddr(pl2e), __PAGE_HYPERVISOR);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ BUG_ON(l3e_get_flags(*pl3e) & _PAGE_PSE);
|
|
+ pl2e = l3e_to_l2e(*pl3e);
|
|
+ }
|
|
+ pl2e += l2_table_offset(addr);
|
|
+ if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
|
|
+ {
|
|
+ l1t = alloc_xen_pagetable();
|
|
+ BUG_ON(!l1t);
|
|
+ clear_page(l1t);
|
|
+ *pl2e = l2e_from_paddr(virt_to_maddr(l1t), __PAGE_HYPERVISOR);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ BUG_ON(l2e_get_flags(*pl2e) & _PAGE_PSE);
|
|
+ l1t = l2e_to_l1e(*pl2e);
|
|
+ }
|
|
+ for ( i = l1_table_offset(addr);
|
|
+ i < L1_PAGETABLE_ENTRIES && extra->smfn < extra->emfn;
|
|
+ ++i, ++extra->smfn )
|
|
+ l1t[i] = l1e_from_pfn(extra->smfn, extra->prot);
|
|
+
|
|
+ if ( extra->smfn == extra->emfn )
|
|
+ {
|
|
+ extra_head = extra->next;
|
|
+ xfree(extra);
|
|
}
|
|
}
|
|
|