From: Ross Philipson Date: Tue, 3 Mar 2009 14:53:39 +0000 (+0000) Subject: Newer better workaround for incorrect RMRRs in BIOS - in X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=86b5490b68b5ff8365654d30e9f55e4da518f1ba;p=xenclient%2Fxen.git Newer better workaround for incorrect RMRRs in BIOS - in sync with upstream. Committer: Ross Philipson Changes to be committed: modified: xen/arch/ia64/xen/mm.c modified: xen/arch/x86/mm.c modified: xen/drivers/passthrough/vtd/dmar.c modified: xen/drivers/passthrough/vtd/iommu.c modified: xen/include/xen/mm.h --- diff --git a/xen/arch/ia64/xen/mm.c b/xen/arch/ia64/xen/mm.c index 1a4c24d..6d570b2 100644 --- a/xen/arch/ia64/xen/mm.c +++ b/xen/arch/ia64/xen/mm.c @@ -3180,17 +3180,58 @@ int get_page_type(struct page_info *page, u32 type) return 1; } -int page_is_ram_type(unsigned long mfn, unsigned long type) /* CS 19085 mem to page */ -{ - /** - * N.B. This function should really be enhanced to return what is more in line with the e820 - * semantics for usable and reservered RAM. For example type RAM_TYPE_CONVENTIONAL can - * include the areas freed after OS loader calls ExitBootServices: - * EFI_LOADER_CODE, EFI_LOADER_DATA, EFI_BOOT_SERVICES_CODE, EFI_BOOT_SERVICES_DATA, and EFI_CONVENTIONAL_MEMORY - * The reserved regions would include: - * EFI_RUNTIME_SERVICES_CODE, EFI_RUNTIME_SERVICES_DATA, EFI_MEMORY_MAPPED_IO, EFI_MEMORY_MAPPED_IO_PORT_SPACE and EFI_PAL_CODE - */ - return (efi_mem_type(pfn_to_paddr(mfn)) == EFI_CONVENTIONAL_MEMORY); +int page_is_ram_type(unsigned long mfn, unsigned long type) +{ + /* N.B. I believe the implementation below is correct for determing EFI memory types. + It needs testing but it is only used once in vga.c right now for conventional ram + (and xc not really interested in IA64). */ + u32 mem_type = efi_mem_type(pfn_to_paddr(mfn)); + + if (type & RAM_TYPE_CONVENTIONAL) + { + switch (mem_type) + { + case EFI_BOOT_SERVICES_CODE: + case EFI_BOOT_SERVICES_DATA: + case EFI_LOADER_CODE: + case EFI_LOADER_DATA: + case EFI_CONVENTIONAL_MEMORY: + return 1; + default: + break; + } + } + if (type & RAM_TYPE_RESERVED) + { + switch (mem_type) + { + case EFI_RUNTIME_SERVICES_CODE: + case EFI_RUNTIME_SERVICES_DATA: + case EFI_RESERVED_TYPE: + case EFI_MEMORY_MAPPED_IO: + case EFI_MEMORY_MAPPED_IO_PORT_SPACE: + case EFI_PAL_CODE: + return 1; + default: + break; + } + } + if (type & RAM_TYPE_ACPI) + { + switch (mem_type) + { + case EFI_ACPI_RECLAIM_MEMORY: + case EFI_ACPI_MEMORY_NVS: + return 1; + default: + break; + } + } + else if (type & RAM_TYPE_UNUSABLE) + { + return (mem_type == EFI_UNUSABLE_MEMORY); + } + return 0; } long diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 4e8dd2d..c5d8226 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -304,6 +304,15 @@ int page_is_ram_type(unsigned long mfn, unsigned long mem_type) /* CS 19085 mem if (mem_type & RAM_TYPE_RESERVED) break; continue; + case E820_UNUSABLE: + if (mem_type & RAM_TYPE_UNUSABLE) + break; + continue; + case E820_ACPI: + case E820_NVS: + if (mem_type & RAM_TYPE_ACPI) + break; + continue; default: /* unknown */ continue; diff --git a/xen/drivers/passthrough/vtd/dmar.c b/xen/drivers/passthrough/vtd/dmar.c index 245b1a7..94a5c80 100644 --- a/xen/drivers/passthrough/vtd/dmar.c +++ b/xen/drivers/passthrough/vtd/dmar.c @@ -365,7 +365,7 @@ acpi_parse_one_rmrr(struct acpi_dmar_entry_header *header) { dprintk(XENLOG_WARNING VTDPREFIX, "RMRR address range not in reserved memory base = %"PRIx64" end = %"PRIx64"; " \ - "iommu_include_reserved parameter may be needed\n", + "iommu_inclusive_mapping=1 parameter may be needed\n", rmrr->base_address, rmrr->end_address); } #endif diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index b48d500..5bfedbb 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -34,16 +34,16 @@ #include "extern.h" #include "vtd.h" +/* iommu_inclusive_mapping: when set, all memory below 4GB is included in dom0 1-1 iommu mappings except xen and unusable regions */ +static int iommu_inclusive_mapping = 0; +boolean_param("iommu_inclusive_mapping", iommu_inclusive_mapping); + #define domain_iommu_domid(d) ((d)->arch.hvm_domain.hvm_iommu.iommu_domid) static spinlock_t domid_bitmap_lock; /* protect domain id bitmap */ static int domid_bitmap_size; /* domain id bitmap size in bits */ static unsigned long *domid_bitmap; /* iommu domain id bitmap */ -/* iommu_include_reserved: include reserved memory ranges in dom0 1-1 iommu mappings if set */ -static int iommu_include_reserved = 0; -boolean_param("iommu_include_reserved", iommu_include_reserved); - static void setup_dom0_devices(struct domain *d); static void setup_dom0_rmrr(struct domain *d); @@ -1030,7 +1030,6 @@ static int intel_iommu_domain_init(struct domain *d) struct iommu *iommu = NULL; struct acpi_drhd_unit *drhd; u64 i; - u32 mem_type; drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list); iommu = drhd->iommu; @@ -1041,21 +1040,28 @@ static int intel_iommu_domain_init(struct domain *d) { extern int xen_in_range(paddr_t start, paddr_t end); - /* input param overrides default memory mapping */ - mem_type = RAM_TYPE_CONVENTIONAL; - if (iommu_include_reserved) - mem_type |= RAM_TYPE_RESERVED; - /* * Set up 1:1 page table for dom0 except the critical segments * like Xen and tboot. */ for ( i = 0; i < max_page; i++ ) { - /* CS 19084 remove tboot_in_range, CS 19085 use page_is_conventional_ram */ - /* Modified to include reserved memory regions - this fix will be pushed upstream */ - if ( !page_is_ram_type(i, mem_type) || - xen_in_range(i << PAGE_SHIFT, (i + 1) << PAGE_SHIFT) ) + /* Set up 1:1 mapping for dom0 */ + if ( !page_is_ram_type(i, RAM_TYPE_CONVENTIONAL) ) + { + /* Default it to use only conventional RAM areas and let RMRRs include needed reserved regions */ + if (iommu_inclusive_mapping) + { + /* When set, the inclusive mapping maps in everything below 4GB except unusable ranges */ + if ( (i >= 0x100000) || page_is_ram_type(i, RAM_TYPE_UNUSABLE) ) + continue; + } + else + continue; + } + + /* Exclude Xen bits */ + if ( xen_in_range(i << PAGE_SHIFT, (i + 1) << PAGE_SHIFT) ) continue; iommu_map_page(d, i, i); diff --git a/xen/include/xen/mm.h b/xen/include/xen/mm.h index 02eacf5..9024540 100644 --- a/xen/include/xen/mm.h +++ b/xen/include/xen/mm.h @@ -103,6 +103,8 @@ int guest_remove_page(struct domain *d, unsigned long gmfn); #define RAM_TYPE_CONVENTIONAL 0x00000001 #define RAM_TYPE_RESERVED 0x00000002 +#define RAM_TYPE_UNUSABLE 0x00000004 +#define RAM_TYPE_ACPI 0x00000008 /* Returns TRUE if the whole page at @mfn is of the requested RAM type(s) above. */ int page_is_ram_type(unsigned long mfn, unsigned long mem_type);