Commit bdb0ae6a authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Peter Anvin:
 "This is a collection of miscellaneous fixes, the most important one is
  the fix for the Samsung laptop bricking issue (auto-blacklisting the
  samsung-laptop driver); the efi_enabled() changes you see below are
  prerequisites for that fix.

  The other issues fixed are booting on OLPC XO-1.5, an UV fix, NMI
  debugging, and requiring CAP_SYS_RAWIO for MSR references, just as
  with I/O port references."

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  samsung-laptop: Disable on EFI hardware
  efi: Make 'efi_enabled' a function to query EFI facilities
  smp: Fix SMP function call empty cpu mask race
  x86/msr: Add capabilities check
  x86/dma-debug: Bump PREALLOC_DMA_DEBUG_ENTRIES
  x86/olpc: Fix olpc-xo1-sci.c build errors
  arch/x86/platform/uv: Fix incorrect tlb flush all issue
  x86-64: Fix unwind annotations in recent NMI changes
  x86-32: Start out cr0 clean, disable paging before modifying cr3/4
parents 0fe94b9e e0094244
...@@ -2138,6 +2138,7 @@ config OLPC_XO1_RTC ...@@ -2138,6 +2138,7 @@ config OLPC_XO1_RTC
config OLPC_XO1_SCI config OLPC_XO1_SCI
bool "OLPC XO-1 SCI extras" bool "OLPC XO-1 SCI extras"
depends on OLPC && OLPC_XO1_PM depends on OLPC && OLPC_XO1_PM
depends on INPUT=y
select POWER_SUPPLY select POWER_SUPPLY
select GPIO_CS5535 select GPIO_CS5535
select MFD_CORE select MFD_CORE
......
...@@ -94,6 +94,7 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, ...@@ -94,6 +94,7 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
#endif /* CONFIG_X86_32 */ #endif /* CONFIG_X86_32 */
extern int add_efi_memmap; extern int add_efi_memmap;
extern unsigned long x86_efi_facility;
extern void efi_set_executable(efi_memory_desc_t *md, bool executable); extern void efi_set_executable(efi_memory_desc_t *md, bool executable);
extern int efi_memblock_x86_reserve_range(void); extern int efi_memblock_x86_reserve_range(void);
extern void efi_call_phys_prelog(void); extern void efi_call_phys_prelog(void);
......
...@@ -16,7 +16,7 @@ extern void uv_system_init(void); ...@@ -16,7 +16,7 @@ extern void uv_system_init(void);
extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
struct mm_struct *mm, struct mm_struct *mm,
unsigned long start, unsigned long start,
unsigned end, unsigned long end,
unsigned int cpu); unsigned int cpu);
#else /* X86_UV */ #else /* X86_UV */
......
...@@ -1781,6 +1781,7 @@ first_nmi: ...@@ -1781,6 +1781,7 @@ first_nmi:
* Leave room for the "copied" frame * Leave room for the "copied" frame
*/ */
subq $(5*8), %rsp subq $(5*8), %rsp
CFI_ADJUST_CFA_OFFSET 5*8
/* Copy the stack frame to the Saved frame */ /* Copy the stack frame to the Saved frame */
.rept 5 .rept 5
...@@ -1863,10 +1864,8 @@ end_repeat_nmi: ...@@ -1863,10 +1864,8 @@ end_repeat_nmi:
nmi_swapgs: nmi_swapgs:
SWAPGS_UNSAFE_STACK SWAPGS_UNSAFE_STACK
nmi_restore: nmi_restore:
RESTORE_ALL 8 /* Pop the extra iret frame at once */
RESTORE_ALL 6*8
/* Pop the extra iret frame */
addq $(5*8), %rsp
/* Clear the NMI executing stack variable */ /* Clear the NMI executing stack variable */
movq $0, 5*8(%rsp) movq $0, 5*8(%rsp)
......
...@@ -300,6 +300,12 @@ ENTRY(startup_32_smp) ...@@ -300,6 +300,12 @@ ENTRY(startup_32_smp)
leal -__PAGE_OFFSET(%ecx),%esp leal -__PAGE_OFFSET(%ecx),%esp
default_entry: default_entry:
#define CR0_STATE (X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \
X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \
X86_CR0_PG)
movl $(CR0_STATE & ~X86_CR0_PG),%eax
movl %eax,%cr0
/* /*
* New page tables may be in 4Mbyte page mode and may * New page tables may be in 4Mbyte page mode and may
* be using the global pages. * be using the global pages.
...@@ -364,8 +370,7 @@ default_entry: ...@@ -364,8 +370,7 @@ default_entry:
*/ */
movl $pa(initial_page_table), %eax movl $pa(initial_page_table), %eax
movl %eax,%cr3 /* set the page table pointer.. */ movl %eax,%cr3 /* set the page table pointer.. */
movl %cr0,%eax movl $CR0_STATE,%eax
orl $X86_CR0_PG,%eax
movl %eax,%cr0 /* ..and set paging (PG) bit */ movl %eax,%cr0 /* ..and set paging (PG) bit */
ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */ ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */
1: 1:
......
...@@ -174,6 +174,9 @@ static int msr_open(struct inode *inode, struct file *file) ...@@ -174,6 +174,9 @@ static int msr_open(struct inode *inode, struct file *file)
unsigned int cpu; unsigned int cpu;
struct cpuinfo_x86 *c; struct cpuinfo_x86 *c;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
cpu = iminor(file->f_path.dentry->d_inode); cpu = iminor(file->f_path.dentry->d_inode);
if (cpu >= nr_cpu_ids || !cpu_online(cpu)) if (cpu >= nr_cpu_ids || !cpu_online(cpu))
return -ENXIO; /* No such CPU */ return -ENXIO; /* No such CPU */
......
...@@ -56,7 +56,7 @@ struct device x86_dma_fallback_dev = { ...@@ -56,7 +56,7 @@ struct device x86_dma_fallback_dev = {
EXPORT_SYMBOL(x86_dma_fallback_dev); EXPORT_SYMBOL(x86_dma_fallback_dev);
/* Number of entries preallocated for DMA-API debugging */ /* Number of entries preallocated for DMA-API debugging */
#define PREALLOC_DMA_DEBUG_ENTRIES 32768 #define PREALLOC_DMA_DEBUG_ENTRIES 65536
int dma_set_mask(struct device *dev, u64 mask) int dma_set_mask(struct device *dev, u64 mask)
{ {
......
...@@ -584,7 +584,7 @@ static void native_machine_emergency_restart(void) ...@@ -584,7 +584,7 @@ static void native_machine_emergency_restart(void)
break; break;
case BOOT_EFI: case BOOT_EFI:
if (efi_enabled) if (efi_enabled(EFI_RUNTIME_SERVICES))
efi.reset_system(reboot_mode ? efi.reset_system(reboot_mode ?
EFI_RESET_WARM : EFI_RESET_WARM :
EFI_RESET_COLD, EFI_RESET_COLD,
......
...@@ -807,15 +807,15 @@ void __init setup_arch(char **cmdline_p) ...@@ -807,15 +807,15 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_EFI #ifdef CONFIG_EFI
if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
"EL32", 4)) { "EL32", 4)) {
efi_enabled = 1; set_bit(EFI_BOOT, &x86_efi_facility);
efi_64bit = false;
} else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, } else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
"EL64", 4)) { "EL64", 4)) {
efi_enabled = 1; set_bit(EFI_BOOT, &x86_efi_facility);
efi_64bit = true; set_bit(EFI_64BIT, &x86_efi_facility);
} }
if (efi_enabled && efi_memblock_x86_reserve_range())
efi_enabled = 0; if (efi_enabled(EFI_BOOT))
efi_memblock_x86_reserve_range();
#endif #endif
x86_init.oem.arch_setup(); x86_init.oem.arch_setup();
...@@ -888,7 +888,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -888,7 +888,7 @@ void __init setup_arch(char **cmdline_p)
finish_e820_parsing(); finish_e820_parsing();
if (efi_enabled) if (efi_enabled(EFI_BOOT))
efi_init(); efi_init();
dmi_scan_machine(); dmi_scan_machine();
...@@ -971,7 +971,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -971,7 +971,7 @@ void __init setup_arch(char **cmdline_p)
* The EFI specification says that boot service code won't be called * The EFI specification says that boot service code won't be called
* after ExitBootServices(). This is, in fact, a lie. * after ExitBootServices(). This is, in fact, a lie.
*/ */
if (efi_enabled) if (efi_enabled(EFI_MEMMAP))
efi_reserve_boot_services(); efi_reserve_boot_services();
/* preallocate 4k for mptable mpc */ /* preallocate 4k for mptable mpc */
...@@ -1114,7 +1114,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -1114,7 +1114,7 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_VT #ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE) #if defined(CONFIG_VGA_CONSOLE)
if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY)) if (!efi_enabled(EFI_BOOT) || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
conswitchp = &vga_con; conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE) #elif defined(CONFIG_DUMMY_CONSOLE)
conswitchp = &dummy_con; conswitchp = &dummy_con;
...@@ -1131,14 +1131,14 @@ void __init setup_arch(char **cmdline_p) ...@@ -1131,14 +1131,14 @@ void __init setup_arch(char **cmdline_p)
register_refined_jiffies(CLOCK_TICK_RATE); register_refined_jiffies(CLOCK_TICK_RATE);
#ifdef CONFIG_EFI #ifdef CONFIG_EFI
/* Once setup is done above, disable efi_enabled on mismatched /* Once setup is done above, unmap the EFI memory map on
* firmware/kernel archtectures since there is no support for * mismatched firmware/kernel archtectures since there is no
* runtime services. * support for runtime services.
*/ */
if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) { if (efi_enabled(EFI_BOOT) &&
IS_ENABLED(CONFIG_X86_64) != efi_enabled(EFI_64BIT)) {
pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
efi_unmap_memmap(); efi_unmap_memmap();
efi_enabled = 0;
} }
#endif #endif
} }
......
...@@ -51,9 +51,6 @@ ...@@ -51,9 +51,6 @@
#define EFI_DEBUG 1 #define EFI_DEBUG 1
int efi_enabled;
EXPORT_SYMBOL(efi_enabled);
struct efi __read_mostly efi = { struct efi __read_mostly efi = {
.mps = EFI_INVALID_TABLE_ADDR, .mps = EFI_INVALID_TABLE_ADDR,
.acpi = EFI_INVALID_TABLE_ADDR, .acpi = EFI_INVALID_TABLE_ADDR,
...@@ -69,19 +66,28 @@ EXPORT_SYMBOL(efi); ...@@ -69,19 +66,28 @@ EXPORT_SYMBOL(efi);
struct efi_memory_map memmap; struct efi_memory_map memmap;
bool efi_64bit;
static struct efi efi_phys __initdata; static struct efi efi_phys __initdata;
static efi_system_table_t efi_systab __initdata; static efi_system_table_t efi_systab __initdata;
static inline bool efi_is_native(void) static inline bool efi_is_native(void)
{ {
return IS_ENABLED(CONFIG_X86_64) == efi_64bit; return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT);
}
unsigned long x86_efi_facility;
/*
* Returns 1 if 'facility' is enabled, 0 otherwise.
*/
int efi_enabled(int facility)
{
return test_bit(facility, &x86_efi_facility) != 0;
} }
EXPORT_SYMBOL(efi_enabled);
static int __init setup_noefi(char *arg) static int __init setup_noefi(char *arg)
{ {
efi_enabled = 0; clear_bit(EFI_BOOT, &x86_efi_facility);
return 0; return 0;
} }
early_param("noefi", setup_noefi); early_param("noefi", setup_noefi);
...@@ -426,6 +432,7 @@ void __init efi_reserve_boot_services(void) ...@@ -426,6 +432,7 @@ void __init efi_reserve_boot_services(void)
void __init efi_unmap_memmap(void) void __init efi_unmap_memmap(void)
{ {
clear_bit(EFI_MEMMAP, &x86_efi_facility);
if (memmap.map) { if (memmap.map) {
early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
memmap.map = NULL; memmap.map = NULL;
...@@ -460,7 +467,7 @@ void __init efi_free_boot_services(void) ...@@ -460,7 +467,7 @@ void __init efi_free_boot_services(void)
static int __init efi_systab_init(void *phys) static int __init efi_systab_init(void *phys)
{ {
if (efi_64bit) { if (efi_enabled(EFI_64BIT)) {
efi_system_table_64_t *systab64; efi_system_table_64_t *systab64;
u64 tmp = 0; u64 tmp = 0;
...@@ -552,7 +559,7 @@ static int __init efi_config_init(u64 tables, int nr_tables) ...@@ -552,7 +559,7 @@ static int __init efi_config_init(u64 tables, int nr_tables)
void *config_tables, *tablep; void *config_tables, *tablep;
int i, sz; int i, sz;
if (efi_64bit) if (efi_enabled(EFI_64BIT))
sz = sizeof(efi_config_table_64_t); sz = sizeof(efi_config_table_64_t);
else else
sz = sizeof(efi_config_table_32_t); sz = sizeof(efi_config_table_32_t);
...@@ -572,7 +579,7 @@ static int __init efi_config_init(u64 tables, int nr_tables) ...@@ -572,7 +579,7 @@ static int __init efi_config_init(u64 tables, int nr_tables)
efi_guid_t guid; efi_guid_t guid;
unsigned long table; unsigned long table;
if (efi_64bit) { if (efi_enabled(EFI_64BIT)) {
u64 table64; u64 table64;
guid = ((efi_config_table_64_t *)tablep)->guid; guid = ((efi_config_table_64_t *)tablep)->guid;
table64 = ((efi_config_table_64_t *)tablep)->table; table64 = ((efi_config_table_64_t *)tablep)->table;
...@@ -684,7 +691,6 @@ void __init efi_init(void) ...@@ -684,7 +691,6 @@ void __init efi_init(void)
if (boot_params.efi_info.efi_systab_hi || if (boot_params.efi_info.efi_systab_hi ||
boot_params.efi_info.efi_memmap_hi) { boot_params.efi_info.efi_memmap_hi) {
pr_info("Table located above 4GB, disabling EFI.\n"); pr_info("Table located above 4GB, disabling EFI.\n");
efi_enabled = 0;
return; return;
} }
efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab;
...@@ -694,10 +700,10 @@ void __init efi_init(void) ...@@ -694,10 +700,10 @@ void __init efi_init(void)
((__u64)boot_params.efi_info.efi_systab_hi<<32)); ((__u64)boot_params.efi_info.efi_systab_hi<<32));
#endif #endif
if (efi_systab_init(efi_phys.systab)) { if (efi_systab_init(efi_phys.systab))
efi_enabled = 0;
return; return;
}
set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility);
/* /*
* Show what we know for posterity * Show what we know for posterity
...@@ -715,10 +721,10 @@ void __init efi_init(void) ...@@ -715,10 +721,10 @@ void __init efi_init(void)
efi.systab->hdr.revision >> 16, efi.systab->hdr.revision >> 16,
efi.systab->hdr.revision & 0xffff, vendor); efi.systab->hdr.revision & 0xffff, vendor);
if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) { if (efi_config_init(efi.systab->tables, efi.systab->nr_tables))
efi_enabled = 0;
return; return;
}
set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
/* /*
* Note: We currently don't support runtime services on an EFI * Note: We currently don't support runtime services on an EFI
...@@ -727,15 +733,17 @@ void __init efi_init(void) ...@@ -727,15 +733,17 @@ void __init efi_init(void)
if (!efi_is_native()) if (!efi_is_native())
pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
else if (efi_runtime_init()) { else {
efi_enabled = 0; if (efi_runtime_init())
return; return;
set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
} }
if (efi_memmap_init()) { if (efi_memmap_init())
efi_enabled = 0;
return; return;
}
set_bit(EFI_MEMMAP, &x86_efi_facility);
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
if (efi_is_native()) { if (efi_is_native()) {
x86_platform.get_wallclock = efi_get_time; x86_platform.get_wallclock = efi_get_time;
...@@ -969,6 +977,9 @@ u32 efi_mem_type(unsigned long phys_addr) ...@@ -969,6 +977,9 @@ u32 efi_mem_type(unsigned long phys_addr)
efi_memory_desc_t *md; efi_memory_desc_t *md;
void *p; void *p;
if (!efi_enabled(EFI_MEMMAP))
return 0;
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
md = p; md = p;
if ((md->phys_addr <= phys_addr) && if ((md->phys_addr <= phys_addr) &&
......
...@@ -1034,7 +1034,8 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp, ...@@ -1034,7 +1034,8 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp,
* globally purge translation cache of a virtual address or all TLB's * globally purge translation cache of a virtual address or all TLB's
* @cpumask: mask of all cpu's in which the address is to be removed * @cpumask: mask of all cpu's in which the address is to be removed
* @mm: mm_struct containing virtual address range * @mm: mm_struct containing virtual address range
* @va: virtual address to be removed (or TLB_FLUSH_ALL for all TLB's on cpu) * @start: start virtual address to be removed from TLB
* @end: end virtual address to be remove from TLB
* @cpu: the current cpu * @cpu: the current cpu
* *
* This is the entry point for initiating any UV global TLB shootdown. * This is the entry point for initiating any UV global TLB shootdown.
...@@ -1056,7 +1057,7 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp, ...@@ -1056,7 +1057,7 @@ static int set_distrib_bits(struct cpumask *flush_mask, struct bau_control *bcp,
*/ */
const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
struct mm_struct *mm, unsigned long start, struct mm_struct *mm, unsigned long start,
unsigned end, unsigned int cpu) unsigned long end, unsigned int cpu)
{ {
int locals = 0; int locals = 0;
int remotes = 0; int remotes = 0;
...@@ -1113,7 +1114,10 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, ...@@ -1113,7 +1114,10 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
record_send_statistics(stat, locals, hubs, remotes, bau_desc); record_send_statistics(stat, locals, hubs, remotes, bau_desc);
bau_desc->payload.address = start; if (!end || (end - start) <= PAGE_SIZE)
bau_desc->payload.address = start;
else
bau_desc->payload.address = TLB_FLUSH_ALL;
bau_desc->payload.sending_cpu = cpu; bau_desc->payload.sending_cpu = cpu;
/* /*
* uv_flush_send_and_wait returns 0 if all cpu's were messaged, * uv_flush_send_and_wait returns 0 if all cpu's were messaged,
......
...@@ -250,7 +250,7 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) ...@@ -250,7 +250,7 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
return acpi_rsdp; return acpi_rsdp;
#endif #endif
if (efi_enabled) { if (efi_enabled(EFI_CONFIG_TABLES)) {
if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
return efi.acpi20; return efi.acpi20;
else if (efi.acpi != EFI_INVALID_TABLE_ADDR) else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
......
...@@ -471,7 +471,7 @@ void __init dmi_scan_machine(void) ...@@ -471,7 +471,7 @@ void __init dmi_scan_machine(void)
char __iomem *p, *q; char __iomem *p, *q;
int rc; int rc;
if (efi_enabled) { if (efi_enabled(EFI_CONFIG_TABLES)) {
if (efi.smbios == EFI_INVALID_TABLE_ADDR) if (efi.smbios == EFI_INVALID_TABLE_ADDR)
goto error; goto error;
......
...@@ -1782,7 +1782,7 @@ efivars_init(void) ...@@ -1782,7 +1782,7 @@ efivars_init(void)
printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION, printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
EFIVARS_DATE); EFIVARS_DATE);
if (!efi_enabled) if (!efi_enabled(EFI_RUNTIME_SERVICES))
return 0; return 0;
/* For now we'll register the efi directory at /sys/firmware/efi */ /* For now we'll register the efi directory at /sys/firmware/efi */
...@@ -1822,7 +1822,7 @@ efivars_init(void) ...@@ -1822,7 +1822,7 @@ efivars_init(void)
static void __exit static void __exit
efivars_exit(void) efivars_exit(void)
{ {
if (efi_enabled) { if (efi_enabled(EFI_RUNTIME_SERVICES)) {
unregister_efivars(&__efivars); unregister_efivars(&__efivars);
kobject_put(efi_kobj); kobject_put(efi_kobj);
} }
......
...@@ -99,7 +99,7 @@ unsigned long __init find_ibft_region(unsigned long *sizep) ...@@ -99,7 +99,7 @@ unsigned long __init find_ibft_region(unsigned long *sizep)
/* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will /* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will
* only use ACPI for this */ * only use ACPI for this */
if (!efi_enabled) if (!efi_enabled(EFI_BOOT))
find_ibft_in_mem(); find_ibft_in_mem();
if (ibft_addr) { if (ibft_addr) {
......
...@@ -429,7 +429,8 @@ bool radeon_card_posted(struct radeon_device *rdev) ...@@ -429,7 +429,8 @@ bool radeon_card_posted(struct radeon_device *rdev)
{ {
uint32_t reg; uint32_t reg;
if (efi_enabled && rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) if (efi_enabled(EFI_BOOT) &&
rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE)
return false; return false;
/* first check CRTCs */ /* first check CRTCs */
......
...@@ -244,7 +244,7 @@ static int __init ibm_rtl_init(void) { ...@@ -244,7 +244,7 @@ static int __init ibm_rtl_init(void) {
if (force) if (force)
pr_warn("module loaded by force\n"); pr_warn("module loaded by force\n");
/* first ensure that we are running on IBM HW */ /* first ensure that we are running on IBM HW */
else if (efi_enabled || !dmi_check_system(ibm_rtl_dmi_table)) else if (efi_enabled(EFI_BOOT) || !dmi_check_system(ibm_rtl_dmi_table))
return -ENODEV; return -ENODEV;
/* Get the address for the Extended BIOS Data Area */ /* Get the address for the Extended BIOS Data Area */
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/efi.h>
#include <acpi/video.h> #include <acpi/video.h>
/* /*
...@@ -1544,6 +1545,9 @@ static int __init samsung_init(void) ...@@ -1544,6 +1545,9 @@ static int __init samsung_init(void)
struct samsung_laptop *samsung; struct samsung_laptop *samsung;
int ret; int ret;
if (efi_enabled(EFI_BOOT))
return -ENODEV;
quirks = &samsung_unknown; quirks = &samsung_unknown;
if (!force && !dmi_check_system(samsung_dmi_table)) if (!force && !dmi_check_system(samsung_dmi_table))
return -ENODEV; return -ENODEV;
......
...@@ -633,7 +633,7 @@ static int isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -633,7 +633,7 @@ static int isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return -ENOMEM; return -ENOMEM;
pci_set_drvdata(pdev, pci_info); pci_set_drvdata(pdev, pci_info);
if (efi_enabled) if (efi_enabled(EFI_RUNTIME_SERVICES))
orom = isci_get_efi_var(pdev); orom = isci_get_efi_var(pdev);
if (!orom) if (!orom)
......
...@@ -618,18 +618,30 @@ extern int __init efi_setup_pcdp_console(char *); ...@@ -618,18 +618,30 @@ extern int __init efi_setup_pcdp_console(char *);
#endif #endif
/* /*
* We play games with efi_enabled so that the compiler will, if possible, remove * We play games with efi_enabled so that the compiler will, if
* EFI-related code altogether. * possible, remove EFI-related code altogether.
*/ */
#define EFI_BOOT 0 /* Were we booted from EFI? */
#define EFI_SYSTEM_TABLES 1 /* Can we use EFI system tables? */
#define EFI_CONFIG_TABLES 2 /* Can we use EFI config tables? */
#define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */
#define EFI_MEMMAP 4 /* Can we use EFI memory map? */
#define EFI_64BIT 5 /* Is the firmware 64-bit? */
#ifdef CONFIG_EFI #ifdef CONFIG_EFI
# ifdef CONFIG_X86 # ifdef CONFIG_X86
extern int efi_enabled; extern int efi_enabled(int facility);
extern bool efi_64bit;
# else # else
# define efi_enabled 1 static inline int efi_enabled(int facility)
{
return 1;
}
# endif # endif
#else #else
# define efi_enabled 0 static inline int efi_enabled(int facility)
{
return 0;
}
#endif #endif
/* /*
......
...@@ -604,7 +604,7 @@ asmlinkage void __init start_kernel(void) ...@@ -604,7 +604,7 @@ asmlinkage void __init start_kernel(void)
pidmap_init(); pidmap_init();
anon_vma_init(); anon_vma_init();
#ifdef CONFIG_X86 #ifdef CONFIG_X86
if (efi_enabled) if (efi_enabled(EFI_RUNTIME_SERVICES))
efi_enter_virtual_mode(); efi_enter_virtual_mode();
#endif #endif
thread_info_cache_init(); thread_info_cache_init();
...@@ -632,7 +632,7 @@ asmlinkage void __init start_kernel(void) ...@@ -632,7 +632,7 @@ asmlinkage void __init start_kernel(void)
acpi_early_init(); /* before LAPIC and SMP init */ acpi_early_init(); /* before LAPIC and SMP init */
sfi_init_late(); sfi_init_late();
if (efi_enabled) { if (efi_enabled(EFI_RUNTIME_SERVICES)) {
efi_late_init(); efi_late_init();
efi_free_boot_services(); efi_free_boot_services();
} }
......
...@@ -33,6 +33,7 @@ struct call_function_data { ...@@ -33,6 +33,7 @@ struct call_function_data {
struct call_single_data csd; struct call_single_data csd;
atomic_t refs; atomic_t refs;
cpumask_var_t cpumask; cpumask_var_t cpumask;
cpumask_var_t cpumask_ipi;
}; };
static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, cfd_data); static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, cfd_data);
...@@ -56,6 +57,9 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) ...@@ -56,6 +57,9 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu)
if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL, if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL,
cpu_to_node(cpu))) cpu_to_node(cpu)))
return notifier_from_errno(-ENOMEM); return notifier_from_errno(-ENOMEM);
if (!zalloc_cpumask_var_node(&cfd->cpumask_ipi, GFP_KERNEL,
cpu_to_node(cpu)))
return notifier_from_errno(-ENOMEM);
break; break;
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
...@@ -65,6 +69,7 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) ...@@ -65,6 +69,7 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu)
case CPU_DEAD: case CPU_DEAD:
case CPU_DEAD_FROZEN: case CPU_DEAD_FROZEN:
free_cpumask_var(cfd->cpumask); free_cpumask_var(cfd->cpumask);
free_cpumask_var(cfd->cpumask_ipi);
break; break;
#endif #endif
}; };
...@@ -526,6 +531,12 @@ void smp_call_function_many(const struct cpumask *mask, ...@@ -526,6 +531,12 @@ void smp_call_function_many(const struct cpumask *mask,
return; return;
} }
/*
* After we put an entry into the list, data->cpumask
* may be cleared again when another CPU sends another IPI for
* a SMP function call, so data->cpumask will be zero.
*/
cpumask_copy(data->cpumask_ipi, data->cpumask);
raw_spin_lock_irqsave(&call_function.lock, flags); raw_spin_lock_irqsave(&call_function.lock, flags);
/* /*
* Place entry at the _HEAD_ of the list, so that any cpu still * Place entry at the _HEAD_ of the list, so that any cpu still
...@@ -549,7 +560,7 @@ void smp_call_function_many(const struct cpumask *mask, ...@@ -549,7 +560,7 @@ void smp_call_function_many(const struct cpumask *mask,
smp_mb(); smp_mb();
/* Send a message to all CPUs in the map */ /* Send a message to all CPUs in the map */
arch_send_call_function_ipi_mask(data->cpumask); arch_send_call_function_ipi_mask(data->cpumask_ipi);
/* Optionally wait for the CPUs to complete */ /* Optionally wait for the CPUs to complete */
if (wait) if (wait)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment