aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-01-16 12:11:50 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-01-16 12:11:50 -0500
commit2409c873be56278ea41c345b453f76813e5c3fed (patch)
tree749750109b4f9c44c1dbc5b2e209f3ff72ae44bf /arch
parentc4ef9bc4f7e1807d499d3d427712df9f8aa2dcbb (diff)
parente43b3cec711a61edf047adf6204d542f3a659ef8 (diff)
Merge branch 'x86/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Peter Anvin: "This is mainly a workaround for a bug in Sandy Bridge graphics which causes corruption of certain memory pages." * 'x86/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/Sandy Bridge: Sandy Bridge workaround depends on CONFIG_PCI x86/Sandy Bridge: mark arrays in __init functions as __initconst x86/Sandy Bridge: reserve pages when integrated graphics is present x86, efi: correct precedence of operators in setup_efi_pci
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/boot/compressed/eboot.c2
-rw-r--r--arch/x86/kernel/setup.c80
2 files changed, 81 insertions, 1 deletions
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index b1942e222768..18e329ca108e 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -302,7 +302,7 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
302 if (status != EFI_SUCCESS) 302 if (status != EFI_SUCCESS)
303 continue; 303 continue;
304 304
305 if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) 305 if (!(attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM))
306 continue; 306 continue;
307 307
308 if (!pci->romimage || !pci->romsize) 308 if (!pci->romimage || !pci->romsize)
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 23ddd558fbd5..00f6c1472b85 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -610,6 +610,83 @@ static __init void reserve_ibft_region(void)
610 610
611static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10; 611static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10;
612 612
613static bool __init snb_gfx_workaround_needed(void)
614{
615#ifdef CONFIG_PCI
616 int i;
617 u16 vendor, devid;
618 static const __initconst u16 snb_ids[] = {
619 0x0102,
620 0x0112,
621 0x0122,
622 0x0106,
623 0x0116,
624 0x0126,
625 0x010a,
626 };
627
628 /* Assume no if something weird is going on with PCI */
629 if (!early_pci_allowed())
630 return false;
631
632 vendor = read_pci_config_16(0, 2, 0, PCI_VENDOR_ID);
633 if (vendor != 0x8086)
634 return false;
635
636 devid = read_pci_config_16(0, 2, 0, PCI_DEVICE_ID);
637 for (i = 0; i < ARRAY_SIZE(snb_ids); i++)
638 if (devid == snb_ids[i])
639 return true;
640#endif
641
642 return false;
643}
644
645/*
646 * Sandy Bridge graphics has trouble with certain ranges, exclude
647 * them from allocation.
648 */
649static void __init trim_snb_memory(void)
650{
651 static const __initconst unsigned long bad_pages[] = {
652 0x20050000,
653 0x20110000,
654 0x20130000,
655 0x20138000,
656 0x40004000,
657 };
658 int i;
659
660 if (!snb_gfx_workaround_needed())
661 return;
662
663 printk(KERN_DEBUG "reserving inaccessible SNB gfx pages\n");
664
665 /*
666 * Reserve all memory below the 1 MB mark that has not
667 * already been reserved.
668 */
669 memblock_reserve(0, 1<<20);
670
671 for (i = 0; i < ARRAY_SIZE(bad_pages); i++) {
672 if (memblock_reserve(bad_pages[i], PAGE_SIZE))
673 printk(KERN_WARNING "failed to reserve 0x%08lx\n",
674 bad_pages[i]);
675 }
676}
677
678/*
679 * Here we put platform-specific memory range workarounds, i.e.
680 * memory known to be corrupt or otherwise in need to be reserved on
681 * specific platforms.
682 *
683 * If this gets used more widely it could use a real dispatch mechanism.
684 */
685static void __init trim_platform_memory_ranges(void)
686{
687 trim_snb_memory();
688}
689
613static void __init trim_bios_range(void) 690static void __init trim_bios_range(void)
614{ 691{
615 /* 692 /*
@@ -630,6 +707,7 @@ static void __init trim_bios_range(void)
630 * take them out. 707 * take them out.
631 */ 708 */
632 e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1); 709 e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1);
710
633 sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); 711 sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
634} 712}
635 713
@@ -908,6 +986,8 @@ void __init setup_arch(char **cmdline_p)
908 986
909 setup_real_mode(); 987 setup_real_mode();
910 988
989 trim_platform_memory_ranges();
990
911 init_gbpages(); 991 init_gbpages();
912 992
913 /* max_pfn_mapped is updated here */ 993 /* max_pfn_mapped is updated here */