diff options
| -rw-r--r-- | arch/x86/boot/compressed/eboot.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/setup.c | 80 |
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 | ||
| 611 | static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10; | 611 | static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10; |
| 612 | 612 | ||
| 613 | static 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 | */ | ||
| 649 | static 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 | */ | ||
| 685 | static void __init trim_platform_memory_ranges(void) | ||
| 686 | { | ||
| 687 | trim_snb_memory(); | ||
| 688 | } | ||
| 689 | |||
| 613 | static void __init trim_bios_range(void) | 690 | static 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 */ |
