aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXudong Hao <xudong.hao@intel.com>2013-04-02 11:21:55 +0200
committerJan Beulich <jbeulich@suse.com>2013-04-02 11:21:55 +0200
commit7947b74a37020b15a69e2aa1e1e5ede9516c77cd (patch)
tree0e78f6b8818efecffc1ecc4f49a50c964aad3671
parent2328ed01762e4f2023bddda3de323de5311c813c (diff)
downloadxen-7947b74a37020b15a69e2aa1e1e5ede9516c77cd.tar.gz
xen-7947b74a37020b15a69e2aa1e1e5ede9516c77cd.tar.bz2
xen-7947b74a37020b15a69e2aa1e1e5ede9516c77cd.zip
x86: reserve pages when SandyBridge integrated graphics
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> master changeset: db537fe3023bf157b85c8246782cb72a6f989b31 master date: 2013-03-26 14:22:07 +0100
-rw-r--r--xen/arch/x86/mm.c20
-rw-r--r--xen/common/page_alloc.c23
-rw-r--r--xen/drivers/passthrough/vtd/quirks.c2
-rw-r--r--xen/include/asm-x86/mm.h1
-rw-r--r--xen/include/asm-x86/pci.h5
5 files changed, 50 insertions, 1 deletions
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 1aeacbd299..8444610dbd 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -120,6 +120,7 @@
#include <xen/trace.h>
#include <asm/setup.h>
#include <asm/fixmap.h>
+#include <asm/pci.h>
/*
* Mapping of first 2 or 4 megabytes of memory. This is mapped with 4kB
@@ -5849,6 +5850,25 @@ void arch_dump_shared_mem_info(void)
}
#endif
+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
diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 95bd7949f7..fbdff5cbd0 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -151,6 +151,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);
@@ -161,6 +165,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' )
diff --git a/xen/drivers/passthrough/vtd/quirks.c b/xen/drivers/passthrough/vtd/quirks.c
index ee87d105f2..8010f38445 100644
--- a/xen/drivers/passthrough/vtd/quirks.c
+++ b/xen/drivers/passthrough/vtd/quirks.c
@@ -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;
diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
index 2ed53d9416..a7bb3bb3f0 100644
--- a/xen/include/asm-x86/mm.h
+++ b/xen/include/asm-x86/mm.h
@@ -342,6 +342,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.
*
diff --git a/xen/include/asm-x86/pci.h b/xen/include/asm-x86/pci.h
index 7bcb7027d0..e0598fd5dc 100644
--- a/xen/include/asm-x86/pci.h
+++ b/xen/include/asm-x86/pci.h
@@ -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;
};