]> xenbits.xensource.com Git - xen.git/commitdiff
x86: reserve pages when SandyBridge integrated graphics
authorXudong Hao <xudong.hao@intel.com>
Tue, 26 Mar 2013 13:22:07 +0000 (14:22 +0100)
committerJan Beulich <jbeulich@suse.com>
Tue, 26 Mar 2013 13:22:07 +0000 (14:22 +0100)
SNB graphics devices have a bug that prevent them from accessing certain
memory ranges, namely anything below 1M and in the pages listed in the
table.

Xen does not initialize below 1MB to heap, i.e. below 1MB pages don't be
allocated, so it's unnecessary to reserve memory below the 1 MB mark
that has not already been reserved.

So reserve those pages listed in the table at xen boot if set detect a
SNB gfx device on the CPU to avoid GPU hangs.

Signed-off-by: Xudong Hao <xudong.hao@intel.com>
Acked-by: Keir Fraser <keir@xen.org>
xen/arch/x86/mm.c
xen/common/page_alloc.c
xen/drivers/passthrough/vtd/quirks.c
xen/include/asm-x86/mm.h
xen/include/asm-x86/pci.h

index d00d9a2a703b41110be857cae19aefd4f6bb7cdc..58e140203d3372d773e151e347c625148081dbc8 100644 (file)
 #include <xen/trace.h>
 #include <asm/setup.h>
 #include <asm/fixmap.h>
+#include <asm/pci.h>
 
 /* Mapping of the fixmap space needed early. */
 l1_pgentry_t __attribute__ ((__section__ (".bss.page_aligned")))
@@ -5824,6 +5825,25 @@ void arch_dump_shared_mem_info(void)
             mem_sharing_get_nr_saved_mfns());
 }
 
+const unsigned long *__init get_platform_badpages(unsigned int *array_size)
+{
+    u32 igd_id;
+    static unsigned long __initdata bad_pages[] = {
+        0x20050000,
+        0x20110000,
+        0x20130000,
+        0x20138000,
+        0x40004000,
+    };
+
+    *array_size = ARRAY_SIZE(bad_pages);
+    igd_id = pci_conf_read32(0, 0, 2, 0, 0);
+    if ( !IS_SNB_GFX(igd_id) )
+        return NULL;
+
+    return bad_pages;
+}
+
 /*
  * Local variables:
  * mode: C
index aefef297900e094baa99032ad5acda0b5c2ec40d..203f77a4852952aac66cd7eb8e5d2a787a10b95b 100644 (file)
@@ -152,6 +152,10 @@ void __init init_boot_pages(paddr_t ps, paddr_t pe)
 {
     unsigned long bad_spfn, bad_epfn;
     const char *p;
+#ifdef CONFIG_X86
+    const unsigned long *badpage = NULL;
+    unsigned int i, array_size;
+#endif
 
     ps = round_pgup(ps);
     pe = round_pgdown(pe);
@@ -162,6 +166,25 @@ void __init init_boot_pages(paddr_t ps, paddr_t pe)
 
     bootmem_region_add(ps >> PAGE_SHIFT, pe >> PAGE_SHIFT);
 
+#ifdef CONFIG_X86
+    /* 
+     * Here we put platform-specific memory range workarounds, i.e.
+     * memory known to be corrupt or otherwise in need to be reserved on
+     * specific platforms.
+     * We get these certain pages and remove them from memory region list.
+     */
+    badpage = get_platform_badpages(&array_size);
+    if ( badpage )
+    {
+        for ( i = 0; i < array_size; i++ )
+        {
+            bootmem_region_zap(*badpage >> PAGE_SHIFT,
+                               (*badpage >> PAGE_SHIFT) + 1);
+            badpage++;
+        }
+    }
+#endif
+
     /* Check new pages against the bad-page list. */
     p = opt_badpage;
     while ( *p != '\0' )
index 6d839c08bfc504b7c7c9cb7a3b6d3836dccaa3fc..7f6c3a75c5bf53635d33e4fc7d20c44837c19a36 100644 (file)
@@ -31,6 +31,7 @@
 #include <xen/keyhandler.h>
 #include <asm/msi.h>
 #include <asm/irq.h>
+#include <asm/pci.h>
 #include <mach_apic.h>
 #include "iommu.h"
 #include "dmar.h"
@@ -47,7 +48,6 @@
 #define IS_CTG(id)    (id == 0x2a408086)
 #define IS_ILK(id)    (id == 0x00408086 || id == 0x00448086 || id== 0x00628086 || id == 0x006A8086)
 #define IS_CPT(id)    (id == 0x01008086 || id == 0x01048086)
-#define IS_SNB_GFX(id) (id == 0x01068086 || id == 0x01168086 || id == 0x01268086 || id == 0x01028086 || id == 0x01128086 || id == 0x01228086 || id == 0x010A8086)
 
 static u32 __read_mostly ioh_id;
 static u32 __initdata igd_id;
index 41d320926494775bbd578981f8a8512e22f1abcd..031525735bd8cbbb6761ebb967f50900f8945455 100644 (file)
@@ -322,6 +322,7 @@ int is_iomem_page(unsigned long mfn);
 
 void clear_superpage_mark(struct page_info *page);
 
+const unsigned long *get_platform_badpages(unsigned int *array_size);
 /* Per page locks:
  * page_lock() is used for two purposes: pte serialization, and memory sharing.
  *
index 7bcb7027d000255c36f8581e3dc3f6bef16a8d22..e0598fd5dc064ea7c8a1f6a76b519df592f03553 100644 (file)
@@ -1,6 +1,11 @@
 #ifndef __X86_PCI_H__
 #define __X86_PCI_H__
 
+#define IS_SNB_GFX(id) (id == 0x01068086 || id == 0x01168086 \
+                        || id == 0x01268086 || id == 0x01028086 \
+                        || id == 0x01128086 || id == 0x01228086 \
+                        || id == 0x010A8086 )
+
 struct arch_pci_dev {
     vmask_t used_vectors;
 };