Merge branch 'linus' into x86/urgent, to refresh the tree
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
@@ -2,7 +2,11 @@
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
|
||||
extra-y := head_$(BITS).o head$(BITS).o head.o vmlinux.lds
|
||||
extra-y := head_$(BITS).o
|
||||
extra-y += head$(BITS).o
|
||||
extra-y += ebda.o
|
||||
extra-y += platform-quirks.o
|
||||
extra-y += vmlinux.lds
|
||||
|
||||
CPPFLAGS_vmlinux.lds += -U$(UTS_MACHINE)
|
||||
|
||||
|
@@ -136,7 +136,7 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
|
||||
{
|
||||
struct acpi_table_madt *madt = NULL;
|
||||
|
||||
if (!cpu_has_apic)
|
||||
if (!boot_cpu_has(X86_FEATURE_APIC))
|
||||
return -EINVAL;
|
||||
|
||||
madt = (struct acpi_table_madt *)table;
|
||||
@@ -913,6 +913,15 @@ late_initcall(hpet_insert_resource);
|
||||
|
||||
static int __init acpi_parse_fadt(struct acpi_table_header *table)
|
||||
{
|
||||
if (!(acpi_gbl_FADT.boot_flags & ACPI_FADT_LEGACY_DEVICES)) {
|
||||
pr_debug("ACPI: no legacy devices present\n");
|
||||
x86_platform.legacy.devices.pnpbios = 0;
|
||||
}
|
||||
|
||||
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) {
|
||||
pr_debug("ACPI: not registering RTC platform device\n");
|
||||
x86_platform.legacy.rtc = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_PM_TIMER
|
||||
/* detect the location of the ACPI PM Timer */
|
||||
@@ -951,7 +960,7 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (!cpu_has_apic)
|
||||
if (!boot_cpu_has(X86_FEATURE_APIC))
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
@@ -979,7 +988,7 @@ static int __init acpi_parse_madt_lapic_entries(void)
|
||||
int ret;
|
||||
struct acpi_subtable_proc madt_proc[2];
|
||||
|
||||
if (!cpu_has_apic)
|
||||
if (!boot_cpu_has(X86_FEATURE_APIC))
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
@@ -1125,7 +1134,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)
|
||||
if (acpi_disabled || acpi_noirq)
|
||||
return -ENODEV;
|
||||
|
||||
if (!cpu_has_apic)
|
||||
if (!boot_cpu_has(X86_FEATURE_APIC))
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include <linux/stop_machine.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kdebug.h>
|
||||
#include <asm/text-patching.h>
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
@@ -607,7 +607,7 @@ static void __init lapic_cal_handler(struct clock_event_device *dev)
|
||||
long tapic = apic_read(APIC_TMCCT);
|
||||
unsigned long pm = acpi_pm_read_early();
|
||||
|
||||
if (cpu_has_tsc)
|
||||
if (boot_cpu_has(X86_FEATURE_TSC))
|
||||
tsc = rdtsc();
|
||||
|
||||
switch (lapic_cal_loops++) {
|
||||
@@ -668,7 +668,7 @@ calibrate_by_pmtimer(long deltapm, long *delta, long *deltatsc)
|
||||
*delta = (long)res;
|
||||
|
||||
/* Correct the tsc counter value */
|
||||
if (cpu_has_tsc) {
|
||||
if (boot_cpu_has(X86_FEATURE_TSC)) {
|
||||
res = (((u64)(*deltatsc)) * pm_100ms);
|
||||
do_div(res, deltapm);
|
||||
apic_printk(APIC_VERBOSE, "TSC delta adjusted to "
|
||||
@@ -760,7 +760,7 @@ static int __init calibrate_APIC_clock(void)
|
||||
apic_printk(APIC_VERBOSE, "..... calibration result: %u\n",
|
||||
lapic_timer_frequency);
|
||||
|
||||
if (cpu_has_tsc) {
|
||||
if (boot_cpu_has(X86_FEATURE_TSC)) {
|
||||
apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
|
||||
"%ld.%04ld MHz.\n",
|
||||
(deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ),
|
||||
@@ -1085,7 +1085,7 @@ void lapic_shutdown(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!cpu_has_apic && !apic_from_smp_config())
|
||||
if (!boot_cpu_has(X86_FEATURE_APIC) && !apic_from_smp_config())
|
||||
return;
|
||||
|
||||
local_irq_save(flags);
|
||||
@@ -1134,7 +1134,7 @@ void __init init_bsp_APIC(void)
|
||||
* Don't do the setup now if we have a SMP BIOS as the
|
||||
* through-I/O-APIC virtual wire mode might be active.
|
||||
*/
|
||||
if (smp_found_config || !cpu_has_apic)
|
||||
if (smp_found_config || !boot_cpu_has(X86_FEATURE_APIC))
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -1227,7 +1227,7 @@ void setup_local_APIC(void)
|
||||
unsigned long long tsc = 0, ntsc;
|
||||
long long max_loops = cpu_khz ? cpu_khz : 1000000;
|
||||
|
||||
if (cpu_has_tsc)
|
||||
if (boot_cpu_has(X86_FEATURE_TSC))
|
||||
tsc = rdtsc();
|
||||
|
||||
if (disable_apic) {
|
||||
@@ -1311,7 +1311,7 @@ void setup_local_APIC(void)
|
||||
break;
|
||||
}
|
||||
if (queued) {
|
||||
if (cpu_has_tsc && cpu_khz) {
|
||||
if (boot_cpu_has(X86_FEATURE_TSC) && cpu_khz) {
|
||||
ntsc = rdtsc();
|
||||
max_loops = (cpu_khz << 10) - (ntsc - tsc);
|
||||
} else
|
||||
@@ -1445,7 +1445,7 @@ static void __x2apic_disable(void)
|
||||
{
|
||||
u64 msr;
|
||||
|
||||
if (!cpu_has_apic)
|
||||
if (!boot_cpu_has(X86_FEATURE_APIC))
|
||||
return;
|
||||
|
||||
rdmsrl(MSR_IA32_APICBASE, msr);
|
||||
@@ -1561,7 +1561,7 @@ void __init check_x2apic(void)
|
||||
pr_info("x2apic: enabled by BIOS, switching to x2apic ops\n");
|
||||
x2apic_mode = 1;
|
||||
x2apic_state = X2APIC_ON;
|
||||
} else if (!cpu_has_x2apic) {
|
||||
} else if (!boot_cpu_has(X86_FEATURE_X2APIC)) {
|
||||
x2apic_state = X2APIC_DISABLED;
|
||||
}
|
||||
}
|
||||
@@ -1632,7 +1632,7 @@ void __init enable_IR_x2apic(void)
|
||||
*/
|
||||
static int __init detect_init_APIC(void)
|
||||
{
|
||||
if (!cpu_has_apic) {
|
||||
if (!boot_cpu_has(X86_FEATURE_APIC)) {
|
||||
pr_info("No local APIC present\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -1711,14 +1711,14 @@ static int __init detect_init_APIC(void)
|
||||
goto no_apic;
|
||||
case X86_VENDOR_INTEL:
|
||||
if (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15 ||
|
||||
(boot_cpu_data.x86 == 5 && cpu_has_apic))
|
||||
(boot_cpu_data.x86 == 5 && boot_cpu_has(X86_FEATURE_APIC)))
|
||||
break;
|
||||
goto no_apic;
|
||||
default:
|
||||
goto no_apic;
|
||||
}
|
||||
|
||||
if (!cpu_has_apic) {
|
||||
if (!boot_cpu_has(X86_FEATURE_APIC)) {
|
||||
/*
|
||||
* Over-ride BIOS and try to enable the local APIC only if
|
||||
* "lapic" specified.
|
||||
@@ -2233,19 +2233,19 @@ int __init APIC_init_uniprocessor(void)
|
||||
return -1;
|
||||
}
|
||||
#ifdef CONFIG_X86_64
|
||||
if (!cpu_has_apic) {
|
||||
if (!boot_cpu_has(X86_FEATURE_APIC)) {
|
||||
disable_apic = 1;
|
||||
pr_info("Apic disabled by BIOS\n");
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
if (!smp_found_config && !cpu_has_apic)
|
||||
if (!smp_found_config && !boot_cpu_has(X86_FEATURE_APIC))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Complain if the BIOS pretends there is one.
|
||||
*/
|
||||
if (!cpu_has_apic &&
|
||||
if (!boot_cpu_has(X86_FEATURE_APIC) &&
|
||||
APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
|
||||
pr_err("BIOS bug, local APIC 0x%x not detected!...\n",
|
||||
boot_cpu_physical_apicid);
|
||||
@@ -2426,7 +2426,7 @@ static void apic_pm_activate(void)
|
||||
static int __init init_lapic_sysfs(void)
|
||||
{
|
||||
/* XXX: remove suspend/resume procs if !apic_pm_state.active? */
|
||||
if (cpu_has_apic)
|
||||
if (boot_cpu_has(X86_FEATURE_APIC))
|
||||
register_syscore_ops(&lapic_syscore_ops);
|
||||
|
||||
return 0;
|
||||
|
@@ -100,13 +100,13 @@ static void noop_vector_allocation_domain(int cpu, struct cpumask *retmask,
|
||||
|
||||
static u32 noop_apic_read(u32 reg)
|
||||
{
|
||||
WARN_ON_ONCE((cpu_has_apic && !disable_apic));
|
||||
WARN_ON_ONCE(boot_cpu_has(X86_FEATURE_APIC) && !disable_apic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void noop_apic_write(u32 reg, u32 v)
|
||||
{
|
||||
WARN_ON_ONCE(cpu_has_apic && !disable_apic);
|
||||
WARN_ON_ONCE(boot_cpu_has(X86_FEATURE_APIC) && !disable_apic);
|
||||
}
|
||||
|
||||
struct apic apic_noop = {
|
||||
|
@@ -1454,7 +1454,7 @@ void native_disable_io_apic(void)
|
||||
ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
|
||||
}
|
||||
|
||||
if (cpu_has_apic || apic_from_smp_config())
|
||||
if (boot_cpu_has(X86_FEATURE_APIC) || apic_from_smp_config())
|
||||
disconnect_bsp_APIC(ioapic_i8259.pin != -1);
|
||||
}
|
||||
|
||||
|
@@ -230,7 +230,7 @@ int safe_smp_processor_id(void)
|
||||
{
|
||||
int apicid, cpuid;
|
||||
|
||||
if (!cpu_has_apic)
|
||||
if (!boot_cpu_has(X86_FEATURE_APIC))
|
||||
return 0;
|
||||
|
||||
apicid = hard_smp_processor_id();
|
||||
|
@@ -944,7 +944,7 @@ static int __init print_ICs(void)
|
||||
print_PIC();
|
||||
|
||||
/* don't print out if apic is not there */
|
||||
if (!cpu_has_apic && !apic_from_smp_config())
|
||||
if (!boot_cpu_has(X86_FEATURE_APIC) && !apic_from_smp_config())
|
||||
return 0;
|
||||
|
||||
print_local_APICs(show_lapic);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -2267,7 +2267,7 @@ static int __init apm_init(void)
|
||||
|
||||
dmi_check_system(apm_dmi_table);
|
||||
|
||||
if (apm_info.bios.version == 0 || paravirt_enabled() || machine_is_olpc()) {
|
||||
if (apm_info.bios.version == 0 || machine_is_olpc()) {
|
||||
printk(KERN_INFO "apm: BIOS not found.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@@ -80,6 +80,7 @@ void common(void) {
|
||||
OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch);
|
||||
OFFSET(BP_version, boot_params, hdr.version);
|
||||
OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment);
|
||||
OFFSET(BP_init_size, boot_params, hdr.init_size);
|
||||
OFFSET(BP_pref_address, boot_params, hdr.pref_address);
|
||||
OFFSET(BP_code32_start, boot_params, hdr.code32_start);
|
||||
|
||||
|
@@ -565,14 +565,17 @@ static void early_init_amd(struct cpuinfo_x86 *c)
|
||||
* can safely set X86_FEATURE_EXTD_APICID unconditionally for families
|
||||
* after 16h.
|
||||
*/
|
||||
if (cpu_has_apic && c->x86 > 0x16) {
|
||||
set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
|
||||
} else if (cpu_has_apic && c->x86 >= 0xf) {
|
||||
/* check CPU config space for extended APIC ID */
|
||||
unsigned int val;
|
||||
val = read_pci_config(0, 24, 0, 0x68);
|
||||
if ((val & ((1 << 17) | (1 << 18))) == ((1 << 17) | (1 << 18)))
|
||||
if (boot_cpu_has(X86_FEATURE_APIC)) {
|
||||
if (c->x86 > 0x16)
|
||||
set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
|
||||
else if (c->x86 >= 0xf) {
|
||||
/* check CPU config space for extended APIC ID */
|
||||
unsigned int val;
|
||||
|
||||
val = read_pci_config(0, 24, 0, 0x68);
|
||||
if ((val >> 17 & 0x3) == 0x3)
|
||||
set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -628,6 +631,7 @@ static void init_amd_k8(struct cpuinfo_x86 *c)
|
||||
*/
|
||||
msr_set_bit(MSR_K7_HWCR, 6);
|
||||
#endif
|
||||
set_cpu_bug(c, X86_BUG_SWAPGS_FENCE);
|
||||
}
|
||||
|
||||
static void init_amd_gh(struct cpuinfo_x86 *c)
|
||||
@@ -746,7 +750,7 @@ static void init_amd(struct cpuinfo_x86 *c)
|
||||
if (c->x86 >= 0xf)
|
||||
set_cpu_cap(c, X86_FEATURE_K8);
|
||||
|
||||
if (cpu_has_xmm2) {
|
||||
if (cpu_has(c, X86_FEATURE_XMM2)) {
|
||||
/* MFENCE stops RDTSC speculation */
|
||||
set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
|
||||
}
|
||||
|
@@ -437,7 +437,7 @@ void load_percpu_segment(int cpu)
|
||||
#ifdef CONFIG_X86_32
|
||||
loadsegment(fs, __KERNEL_PERCPU);
|
||||
#else
|
||||
loadsegment(gs, 0);
|
||||
__loadsegment_simple(gs, 0);
|
||||
wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu));
|
||||
#endif
|
||||
load_stack_canary_segment();
|
||||
@@ -724,6 +724,13 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
|
||||
}
|
||||
}
|
||||
|
||||
if (c->extended_cpuid_level >= 0x80000007) {
|
||||
cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
c->x86_capability[CPUID_8000_0007_EBX] = ebx;
|
||||
c->x86_power = edx;
|
||||
}
|
||||
|
||||
if (c->extended_cpuid_level >= 0x80000008) {
|
||||
cpuid(0x80000008, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
@@ -736,9 +743,6 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
|
||||
c->x86_phys_bits = 36;
|
||||
#endif
|
||||
|
||||
if (c->extended_cpuid_level >= 0x80000007)
|
||||
c->x86_power = cpuid_edx(0x80000007);
|
||||
|
||||
if (c->extended_cpuid_level >= 0x8000000a)
|
||||
c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a);
|
||||
|
||||
@@ -869,30 +873,34 @@ static void detect_nopl(struct cpuinfo_x86 *c)
|
||||
#else
|
||||
set_cpu_cap(c, X86_FEATURE_NOPL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void detect_null_seg_behavior(struct cpuinfo_x86 *c)
|
||||
{
|
||||
#ifdef CONFIG_X86_64
|
||||
/*
|
||||
* ESPFIX is a strange bug. All real CPUs have it. Paravirt
|
||||
* systems that run Linux at CPL > 0 may or may not have the
|
||||
* issue, but, even if they have the issue, there's absolutely
|
||||
* nothing we can do about it because we can't use the real IRET
|
||||
* instruction.
|
||||
* Empirically, writing zero to a segment selector on AMD does
|
||||
* not clear the base, whereas writing zero to a segment
|
||||
* selector on Intel does clear the base. Intel's behavior
|
||||
* allows slightly faster context switches in the common case
|
||||
* where GS is unused by the prev and next threads.
|
||||
*
|
||||
* NB: For the time being, only 32-bit kernels support
|
||||
* X86_BUG_ESPFIX as such. 64-bit kernels directly choose
|
||||
* whether to apply espfix using paravirt hooks. If any
|
||||
* non-paravirt system ever shows up that does *not* have the
|
||||
* ESPFIX issue, we can change this.
|
||||
* Since neither vendor documents this anywhere that I can see,
|
||||
* detect it directly instead of hardcoding the choice by
|
||||
* vendor.
|
||||
*
|
||||
* I've designated AMD's behavior as the "bug" because it's
|
||||
* counterintuitive and less friendly.
|
||||
*/
|
||||
#ifdef CONFIG_X86_32
|
||||
#ifdef CONFIG_PARAVIRT
|
||||
do {
|
||||
extern void native_iret(void);
|
||||
if (pv_cpu_ops.iret == native_iret)
|
||||
set_cpu_bug(c, X86_BUG_ESPFIX);
|
||||
} while (0);
|
||||
#else
|
||||
set_cpu_bug(c, X86_BUG_ESPFIX);
|
||||
#endif
|
||||
|
||||
unsigned long old_base, tmp;
|
||||
rdmsrl(MSR_FS_BASE, old_base);
|
||||
wrmsrl(MSR_FS_BASE, 1);
|
||||
loadsegment(fs, 0);
|
||||
rdmsrl(MSR_FS_BASE, tmp);
|
||||
if (tmp != 0)
|
||||
set_cpu_bug(c, X86_BUG_NULL_SEG);
|
||||
wrmsrl(MSR_FS_BASE, old_base);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -928,6 +936,33 @@ static void generic_identify(struct cpuinfo_x86 *c)
|
||||
get_model_name(c); /* Default name */
|
||||
|
||||
detect_nopl(c);
|
||||
|
||||
detect_null_seg_behavior(c);
|
||||
|
||||
/*
|
||||
* ESPFIX is a strange bug. All real CPUs have it. Paravirt
|
||||
* systems that run Linux at CPL > 0 may or may not have the
|
||||
* issue, but, even if they have the issue, there's absolutely
|
||||
* nothing we can do about it because we can't use the real IRET
|
||||
* instruction.
|
||||
*
|
||||
* NB: For the time being, only 32-bit kernels support
|
||||
* X86_BUG_ESPFIX as such. 64-bit kernels directly choose
|
||||
* whether to apply espfix using paravirt hooks. If any
|
||||
* non-paravirt system ever shows up that does *not* have the
|
||||
* ESPFIX issue, we can change this.
|
||||
*/
|
||||
#ifdef CONFIG_X86_32
|
||||
# ifdef CONFIG_PARAVIRT
|
||||
do {
|
||||
extern void native_iret(void);
|
||||
if (pv_cpu_ops.iret == native_iret)
|
||||
set_cpu_bug(c, X86_BUG_ESPFIX);
|
||||
} while (0);
|
||||
# else
|
||||
set_cpu_bug(c, X86_BUG_ESPFIX);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static void x86_init_cache_qos(struct cpuinfo_x86 *c)
|
||||
@@ -1083,12 +1118,12 @@ void enable_sep_cpu(void)
|
||||
struct tss_struct *tss;
|
||||
int cpu;
|
||||
|
||||
if (!boot_cpu_has(X86_FEATURE_SEP))
|
||||
return;
|
||||
|
||||
cpu = get_cpu();
|
||||
tss = &per_cpu(cpu_tss, cpu);
|
||||
|
||||
if (!boot_cpu_has(X86_FEATURE_SEP))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* We cache MSR_IA32_SYSENTER_CS's value in the TSS's ss1 field --
|
||||
* see the big comment in struct x86_hw_tss's definition.
|
||||
@@ -1103,7 +1138,6 @@ void enable_sep_cpu(void)
|
||||
|
||||
wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long)entry_SYSENTER_32, 0);
|
||||
|
||||
out:
|
||||
put_cpu();
|
||||
}
|
||||
#endif
|
||||
@@ -1535,7 +1569,7 @@ void cpu_init(void)
|
||||
pr_info("Initializing CPU#%d\n", cpu);
|
||||
|
||||
if (cpu_feature_enabled(X86_FEATURE_VME) ||
|
||||
cpu_has_tsc ||
|
||||
boot_cpu_has(X86_FEATURE_TSC) ||
|
||||
boot_cpu_has(X86_FEATURE_DE))
|
||||
cr4_clear_bits(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
|
||||
|
||||
|
@@ -333,7 +333,7 @@ static void init_cyrix(struct cpuinfo_x86 *c)
|
||||
switch (dir0_lsn) {
|
||||
case 0xd: /* either a 486SLC or DLC w/o DEVID */
|
||||
dir0_msn = 0;
|
||||
p = Cx486_name[(cpu_has_fpu ? 1 : 0)];
|
||||
p = Cx486_name[!!boot_cpu_has(X86_FEATURE_FPU)];
|
||||
break;
|
||||
|
||||
case 0xe: /* a 486S A step */
|
||||
|
@@ -187,9 +187,9 @@ static void early_init_intel(struct cpuinfo_x86 *c)
|
||||
* the TLB when any changes are made to any of the page table entries.
|
||||
* The operating system must reload CR3 to cause the TLB to be flushed"
|
||||
*
|
||||
* As a result cpu_has_pge() in arch/x86/include/asm/tlbflush.h should
|
||||
* be false so that __flush_tlb_all() causes CR3 insted of CR4.PGE
|
||||
* to be modified
|
||||
* As a result, boot_cpu_has(X86_FEATURE_PGE) in arch/x86/include/asm/tlbflush.h
|
||||
* should be false so that __flush_tlb_all() causes CR3 insted of CR4.PGE
|
||||
* to be modified.
|
||||
*/
|
||||
if (c->x86 == 5 && c->x86_model == 9) {
|
||||
pr_info("Disabling PGE capability bit\n");
|
||||
@@ -270,7 +270,7 @@ static void intel_workarounds(struct cpuinfo_x86 *c)
|
||||
* The Quark is also family 5, but does not have the same bug.
|
||||
*/
|
||||
clear_cpu_bug(c, X86_BUG_F00F);
|
||||
if (!paravirt_enabled() && c->x86 == 5 && c->x86_model < 9) {
|
||||
if (c->x86 == 5 && c->x86_model < 9) {
|
||||
static int f00f_workaround_enabled;
|
||||
|
||||
set_cpu_bug(c, X86_BUG_F00F);
|
||||
@@ -318,7 +318,7 @@ static void intel_workarounds(struct cpuinfo_x86 *c)
|
||||
* integrated APIC (see 11AP erratum in "Pentium Processor
|
||||
* Specification Update").
|
||||
*/
|
||||
if (cpu_has_apic && (c->x86<<8 | c->x86_model<<4) == 0x520 &&
|
||||
if (boot_cpu_has(X86_FEATURE_APIC) && (c->x86<<8 | c->x86_model<<4) == 0x520 &&
|
||||
(c->x86_mask < 0x6 || c->x86_mask == 0xb))
|
||||
set_cpu_bug(c, X86_BUG_11AP);
|
||||
|
||||
@@ -493,7 +493,7 @@ static void init_intel(struct cpuinfo_x86 *c)
|
||||
set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
|
||||
}
|
||||
|
||||
if (cpu_has_xmm2)
|
||||
if (cpu_has(c, X86_FEATURE_XMM2))
|
||||
set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
|
||||
|
||||
if (boot_cpu_has(X86_FEATURE_DS)) {
|
||||
@@ -505,7 +505,7 @@ static void init_intel(struct cpuinfo_x86 *c)
|
||||
set_cpu_cap(c, X86_FEATURE_PEBS);
|
||||
}
|
||||
|
||||
if (c->x86 == 6 && cpu_has_clflush &&
|
||||
if (c->x86 == 6 && boot_cpu_has(X86_FEATURE_CLFLUSH) &&
|
||||
(c->x86_model == 29 || c->x86_model == 46 || c->x86_model == 47))
|
||||
set_cpu_bug(c, X86_BUG_CLFLUSH_MONITOR);
|
||||
|
||||
|
@@ -26,6 +26,52 @@ static struct gen_pool *mce_evt_pool;
|
||||
static LLIST_HEAD(mce_event_llist);
|
||||
static char gen_pool_buf[MCE_POOLSZ];
|
||||
|
||||
/*
|
||||
* Compare the record "t" with each of the records on list "l" to see if
|
||||
* an equivalent one is present in the list.
|
||||
*/
|
||||
static bool is_duplicate_mce_record(struct mce_evt_llist *t, struct mce_evt_llist *l)
|
||||
{
|
||||
struct mce_evt_llist *node;
|
||||
struct mce *m1, *m2;
|
||||
|
||||
m1 = &t->mce;
|
||||
|
||||
llist_for_each_entry(node, &l->llnode, llnode) {
|
||||
m2 = &node->mce;
|
||||
|
||||
if (!mce_cmp(m1, m2))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* The system has panicked - we'd like to peruse the list of MCE records
|
||||
* that have been queued, but not seen by anyone yet. The list is in
|
||||
* reverse time order, so we need to reverse it. While doing that we can
|
||||
* also drop duplicate records (these were logged because some banks are
|
||||
* shared between cores or by all threads on a socket).
|
||||
*/
|
||||
struct llist_node *mce_gen_pool_prepare_records(void)
|
||||
{
|
||||
struct llist_node *head;
|
||||
LLIST_HEAD(new_head);
|
||||
struct mce_evt_llist *node, *t;
|
||||
|
||||
head = llist_del_all(&mce_event_llist);
|
||||
if (!head)
|
||||
return NULL;
|
||||
|
||||
/* squeeze out duplicates while reversing order */
|
||||
llist_for_each_entry_safe(node, t, head, llnode) {
|
||||
if (!is_duplicate_mce_record(node, t))
|
||||
llist_add(&node->llnode, &new_head);
|
||||
}
|
||||
|
||||
return new_head.first;
|
||||
}
|
||||
|
||||
void mce_gen_pool_process(void)
|
||||
{
|
||||
struct llist_node *head;
|
||||
|
@@ -35,6 +35,7 @@ void mce_gen_pool_process(void);
|
||||
bool mce_gen_pool_empty(void);
|
||||
int mce_gen_pool_add(struct mce *mce);
|
||||
int mce_gen_pool_init(void);
|
||||
struct llist_node *mce_gen_pool_prepare_records(void);
|
||||
|
||||
extern int (*mce_severity)(struct mce *a, int tolerant, char **msg, bool is_excp);
|
||||
struct dentry *mce_get_debugfs_dir(void);
|
||||
@@ -81,3 +82,17 @@ static inline int apei_clear_mce(u64 record_id)
|
||||
#endif
|
||||
|
||||
void mce_inject_log(struct mce *m);
|
||||
|
||||
/*
|
||||
* We consider records to be equivalent if bank+status+addr+misc all match.
|
||||
* This is only used when the system is going down because of a fatal error
|
||||
* to avoid cluttering the console log with essentially repeated information.
|
||||
* In normal processing all errors seen are logged.
|
||||
*/
|
||||
static inline bool mce_cmp(struct mce *m1, struct mce *m2)
|
||||
{
|
||||
return m1->bank != m2->bank ||
|
||||
m1->status != m2->status ||
|
||||
m1->addr != m2->addr ||
|
||||
m1->misc != m2->misc;
|
||||
}
|
||||
|
@@ -204,6 +204,33 @@ static int error_context(struct mce *m)
|
||||
return IN_KERNEL;
|
||||
}
|
||||
|
||||
static int mce_severity_amd_smca(struct mce *m, int err_ctx)
|
||||
{
|
||||
u32 addr = MSR_AMD64_SMCA_MCx_CONFIG(m->bank);
|
||||
u32 low, high;
|
||||
|
||||
/*
|
||||
* We need to look at the following bits:
|
||||
* - "succor" bit (data poisoning support), and
|
||||
* - TCC bit (Task Context Corrupt)
|
||||
* in MCi_STATUS to determine error severity.
|
||||
*/
|
||||
if (!mce_flags.succor)
|
||||
return MCE_PANIC_SEVERITY;
|
||||
|
||||
if (rdmsr_safe(addr, &low, &high))
|
||||
return MCE_PANIC_SEVERITY;
|
||||
|
||||
/* TCC (Task context corrupt). If set and if IN_KERNEL, panic. */
|
||||
if ((low & MCI_CONFIG_MCAX) &&
|
||||
(m->status & MCI_STATUS_TCC) &&
|
||||
(err_ctx == IN_KERNEL))
|
||||
return MCE_PANIC_SEVERITY;
|
||||
|
||||
/* ...otherwise invoke hwpoison handler. */
|
||||
return MCE_AR_SEVERITY;
|
||||
}
|
||||
|
||||
/*
|
||||
* See AMD Error Scope Hierarchy table in a newer BKDG. For example
|
||||
* 49125_15h_Models_30h-3Fh_BKDG.pdf, section "RAS Features"
|
||||
@@ -225,6 +252,9 @@ static int mce_severity_amd(struct mce *m, int tolerant, char **msg, bool is_exc
|
||||
* to at least kill process to prolong system operation.
|
||||
*/
|
||||
if (mce_flags.overflow_recov) {
|
||||
if (mce_flags.smca)
|
||||
return mce_severity_amd_smca(m, ctx);
|
||||
|
||||
/* software can try to contain */
|
||||
if (!(m->mcgstatus & MCG_STATUS_RIPV) && (ctx == IN_KERNEL))
|
||||
return MCE_PANIC_SEVERITY;
|
||||
|
@@ -161,7 +161,6 @@ void mce_log(struct mce *mce)
|
||||
if (!mce_gen_pool_add(mce))
|
||||
irq_work_queue(&mce_irq_work);
|
||||
|
||||
mce->finished = 0;
|
||||
wmb();
|
||||
for (;;) {
|
||||
entry = mce_log_get_idx_check(mcelog.next);
|
||||
@@ -194,7 +193,6 @@ void mce_log(struct mce *mce)
|
||||
mcelog.entry[entry].finished = 1;
|
||||
wmb();
|
||||
|
||||
mce->finished = 1;
|
||||
set_bit(0, &mce_need_notify);
|
||||
}
|
||||
|
||||
@@ -224,6 +222,53 @@ void mce_unregister_decode_chain(struct notifier_block *nb)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mce_unregister_decode_chain);
|
||||
|
||||
static inline u32 ctl_reg(int bank)
|
||||
{
|
||||
return MSR_IA32_MCx_CTL(bank);
|
||||
}
|
||||
|
||||
static inline u32 status_reg(int bank)
|
||||
{
|
||||
return MSR_IA32_MCx_STATUS(bank);
|
||||
}
|
||||
|
||||
static inline u32 addr_reg(int bank)
|
||||
{
|
||||
return MSR_IA32_MCx_ADDR(bank);
|
||||
}
|
||||
|
||||
static inline u32 misc_reg(int bank)
|
||||
{
|
||||
return MSR_IA32_MCx_MISC(bank);
|
||||
}
|
||||
|
||||
static inline u32 smca_ctl_reg(int bank)
|
||||
{
|
||||
return MSR_AMD64_SMCA_MCx_CTL(bank);
|
||||
}
|
||||
|
||||
static inline u32 smca_status_reg(int bank)
|
||||
{
|
||||
return MSR_AMD64_SMCA_MCx_STATUS(bank);
|
||||
}
|
||||
|
||||
static inline u32 smca_addr_reg(int bank)
|
||||
{
|
||||
return MSR_AMD64_SMCA_MCx_ADDR(bank);
|
||||
}
|
||||
|
||||
static inline u32 smca_misc_reg(int bank)
|
||||
{
|
||||
return MSR_AMD64_SMCA_MCx_MISC(bank);
|
||||
}
|
||||
|
||||
struct mca_msr_regs msr_ops = {
|
||||
.ctl = ctl_reg,
|
||||
.status = status_reg,
|
||||
.addr = addr_reg,
|
||||
.misc = misc_reg
|
||||
};
|
||||
|
||||
static void print_mce(struct mce *m)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -290,7 +335,9 @@ static void wait_for_panic(void)
|
||||
|
||||
static void mce_panic(const char *msg, struct mce *final, char *exp)
|
||||
{
|
||||
int i, apei_err = 0;
|
||||
int apei_err = 0;
|
||||
struct llist_node *pending;
|
||||
struct mce_evt_llist *l;
|
||||
|
||||
if (!fake_panic) {
|
||||
/*
|
||||
@@ -307,11 +354,10 @@ static void mce_panic(const char *msg, struct mce *final, char *exp)
|
||||
if (atomic_inc_return(&mce_fake_panicked) > 1)
|
||||
return;
|
||||
}
|
||||
pending = mce_gen_pool_prepare_records();
|
||||
/* First print corrected ones that are still unlogged */
|
||||
for (i = 0; i < MCE_LOG_LEN; i++) {
|
||||
struct mce *m = &mcelog.entry[i];
|
||||
if (!(m->status & MCI_STATUS_VAL))
|
||||
continue;
|
||||
llist_for_each_entry(l, pending, llnode) {
|
||||
struct mce *m = &l->mce;
|
||||
if (!(m->status & MCI_STATUS_UC)) {
|
||||
print_mce(m);
|
||||
if (!apei_err)
|
||||
@@ -319,13 +365,11 @@ static void mce_panic(const char *msg, struct mce *final, char *exp)
|
||||
}
|
||||
}
|
||||
/* Now print uncorrected but with the final one last */
|
||||
for (i = 0; i < MCE_LOG_LEN; i++) {
|
||||
struct mce *m = &mcelog.entry[i];
|
||||
if (!(m->status & MCI_STATUS_VAL))
|
||||
continue;
|
||||
llist_for_each_entry(l, pending, llnode) {
|
||||
struct mce *m = &l->mce;
|
||||
if (!(m->status & MCI_STATUS_UC))
|
||||
continue;
|
||||
if (!final || memcmp(m, final, sizeof(struct mce))) {
|
||||
if (!final || mce_cmp(m, final)) {
|
||||
print_mce(m);
|
||||
if (!apei_err)
|
||||
apei_err = apei_write_mce(m);
|
||||
@@ -356,11 +400,11 @@ static int msr_to_offset(u32 msr)
|
||||
|
||||
if (msr == mca_cfg.rip_msr)
|
||||
return offsetof(struct mce, ip);
|
||||
if (msr == MSR_IA32_MCx_STATUS(bank))
|
||||
if (msr == msr_ops.status(bank))
|
||||
return offsetof(struct mce, status);
|
||||
if (msr == MSR_IA32_MCx_ADDR(bank))
|
||||
if (msr == msr_ops.addr(bank))
|
||||
return offsetof(struct mce, addr);
|
||||
if (msr == MSR_IA32_MCx_MISC(bank))
|
||||
if (msr == msr_ops.misc(bank))
|
||||
return offsetof(struct mce, misc);
|
||||
if (msr == MSR_IA32_MCG_STATUS)
|
||||
return offsetof(struct mce, mcgstatus);
|
||||
@@ -523,9 +567,9 @@ static struct notifier_block mce_srao_nb = {
|
||||
static void mce_read_aux(struct mce *m, int i)
|
||||
{
|
||||
if (m->status & MCI_STATUS_MISCV)
|
||||
m->misc = mce_rdmsrl(MSR_IA32_MCx_MISC(i));
|
||||
m->misc = mce_rdmsrl(msr_ops.misc(i));
|
||||
if (m->status & MCI_STATUS_ADDRV) {
|
||||
m->addr = mce_rdmsrl(MSR_IA32_MCx_ADDR(i));
|
||||
m->addr = mce_rdmsrl(msr_ops.addr(i));
|
||||
|
||||
/*
|
||||
* Mask the reported address by the reported granularity.
|
||||
@@ -607,7 +651,7 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
|
||||
m.tsc = 0;
|
||||
|
||||
barrier();
|
||||
m.status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i));
|
||||
m.status = mce_rdmsrl(msr_ops.status(i));
|
||||
if (!(m.status & MCI_STATUS_VAL))
|
||||
continue;
|
||||
|
||||
@@ -654,7 +698,7 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
|
||||
/*
|
||||
* Clear state for this bank.
|
||||
*/
|
||||
mce_wrmsrl(MSR_IA32_MCx_STATUS(i), 0);
|
||||
mce_wrmsrl(msr_ops.status(i), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -679,7 +723,7 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,
|
||||
char *tmp;
|
||||
|
||||
for (i = 0; i < mca_cfg.banks; i++) {
|
||||
m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i));
|
||||
m->status = mce_rdmsrl(msr_ops.status(i));
|
||||
if (m->status & MCI_STATUS_VAL) {
|
||||
__set_bit(i, validp);
|
||||
if (quirk_no_way_out)
|
||||
@@ -830,9 +874,9 @@ static int mce_start(int *no_way_out)
|
||||
|
||||
atomic_add(*no_way_out, &global_nwo);
|
||||
/*
|
||||
* global_nwo should be updated before mce_callin
|
||||
* Rely on the implied barrier below, such that global_nwo
|
||||
* is updated before mce_callin.
|
||||
*/
|
||||
smp_wmb();
|
||||
order = atomic_inc_return(&mce_callin);
|
||||
|
||||
/*
|
||||
@@ -957,7 +1001,7 @@ static void mce_clear_state(unsigned long *toclear)
|
||||
|
||||
for (i = 0; i < mca_cfg.banks; i++) {
|
||||
if (test_bit(i, toclear))
|
||||
mce_wrmsrl(MSR_IA32_MCx_STATUS(i), 0);
|
||||
mce_wrmsrl(msr_ops.status(i), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -994,11 +1038,12 @@ void do_machine_check(struct pt_regs *regs, long error_code)
|
||||
int i;
|
||||
int worst = 0;
|
||||
int severity;
|
||||
|
||||
/*
|
||||
* Establish sequential order between the CPUs entering the machine
|
||||
* check handler.
|
||||
*/
|
||||
int order;
|
||||
int order = -1;
|
||||
/*
|
||||
* If no_way_out gets set, there is no safe way to recover from this
|
||||
* MCE. If mca_cfg.tolerant is cranked up, we'll try anyway.
|
||||
@@ -1012,7 +1057,12 @@ void do_machine_check(struct pt_regs *regs, long error_code)
|
||||
DECLARE_BITMAP(toclear, MAX_NR_BANKS);
|
||||
DECLARE_BITMAP(valid_banks, MAX_NR_BANKS);
|
||||
char *msg = "Unknown";
|
||||
int lmce = 0;
|
||||
|
||||
/*
|
||||
* MCEs are always local on AMD. Same is determined by MCG_STATUS_LMCES
|
||||
* on Intel.
|
||||
*/
|
||||
int lmce = 1;
|
||||
|
||||
/* If this CPU is offline, just bail out. */
|
||||
if (cpu_is_offline(smp_processor_id())) {
|
||||
@@ -1051,19 +1101,20 @@ void do_machine_check(struct pt_regs *regs, long error_code)
|
||||
kill_it = 1;
|
||||
|
||||
/*
|
||||
* Check if this MCE is signaled to only this logical processor
|
||||
* Check if this MCE is signaled to only this logical processor,
|
||||
* on Intel only.
|
||||
*/
|
||||
if (m.mcgstatus & MCG_STATUS_LMCES)
|
||||
lmce = 1;
|
||||
else {
|
||||
/*
|
||||
* Go through all the banks in exclusion of the other CPUs.
|
||||
* This way we don't report duplicated events on shared banks
|
||||
* because the first one to see it will clear it.
|
||||
* If this is a Local MCE, then no need to perform rendezvous.
|
||||
*/
|
||||
if (m.cpuvendor == X86_VENDOR_INTEL)
|
||||
lmce = m.mcgstatus & MCG_STATUS_LMCES;
|
||||
|
||||
/*
|
||||
* Go through all banks in exclusion of the other CPUs. This way we
|
||||
* don't report duplicated events on shared banks because the first one
|
||||
* to see it will clear it. If this is a Local MCE, then no need to
|
||||
* perform rendezvous.
|
||||
*/
|
||||
if (!lmce)
|
||||
order = mce_start(&no_way_out);
|
||||
}
|
||||
|
||||
for (i = 0; i < cfg->banks; i++) {
|
||||
__clear_bit(i, toclear);
|
||||
@@ -1076,7 +1127,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
|
||||
m.addr = 0;
|
||||
m.bank = i;
|
||||
|
||||
m.status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i));
|
||||
m.status = mce_rdmsrl(msr_ops.status(i));
|
||||
if ((m.status & MCI_STATUS_VAL) == 0)
|
||||
continue;
|
||||
|
||||
@@ -1420,7 +1471,6 @@ static void __mcheck_cpu_init_generic(void)
|
||||
enum mcp_flags m_fl = 0;
|
||||
mce_banks_t all_banks;
|
||||
u64 cap;
|
||||
int i;
|
||||
|
||||
if (!mca_cfg.bootlog)
|
||||
m_fl = MCP_DONTLOG;
|
||||
@@ -1436,14 +1486,19 @@ static void __mcheck_cpu_init_generic(void)
|
||||
rdmsrl(MSR_IA32_MCG_CAP, cap);
|
||||
if (cap & MCG_CTL_P)
|
||||
wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
|
||||
}
|
||||
|
||||
static void __mcheck_cpu_init_clear_banks(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mca_cfg.banks; i++) {
|
||||
struct mce_bank *b = &mce_banks[i];
|
||||
|
||||
if (!b->init)
|
||||
continue;
|
||||
wrmsrl(MSR_IA32_MCx_CTL(i), b->ctl);
|
||||
wrmsrl(MSR_IA32_MCx_STATUS(i), 0);
|
||||
wrmsrl(msr_ops.ctl(i), b->ctl);
|
||||
wrmsrl(msr_ops.status(i), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1495,7 +1550,7 @@ static int __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
|
||||
*/
|
||||
clear_bit(10, (unsigned long *)&mce_banks[4].ctl);
|
||||
}
|
||||
if (c->x86 <= 17 && cfg->bootlog < 0) {
|
||||
if (c->x86 < 17 && cfg->bootlog < 0) {
|
||||
/*
|
||||
* Lots of broken BIOS around that don't clear them
|
||||
* by default and leave crap in there. Don't log:
|
||||
@@ -1628,11 +1683,19 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
|
||||
break;
|
||||
|
||||
case X86_VENDOR_AMD: {
|
||||
u32 ebx = cpuid_ebx(0x80000007);
|
||||
mce_flags.overflow_recov = !!cpu_has(c, X86_FEATURE_OVERFLOW_RECOV);
|
||||
mce_flags.succor = !!cpu_has(c, X86_FEATURE_SUCCOR);
|
||||
mce_flags.smca = !!cpu_has(c, X86_FEATURE_SMCA);
|
||||
|
||||
mce_flags.overflow_recov = !!(ebx & BIT(0));
|
||||
mce_flags.succor = !!(ebx & BIT(1));
|
||||
mce_flags.smca = !!(ebx & BIT(3));
|
||||
/*
|
||||
* Install proper ops for Scalable MCA enabled processors
|
||||
*/
|
||||
if (mce_flags.smca) {
|
||||
msr_ops.ctl = smca_ctl_reg;
|
||||
msr_ops.status = smca_status_reg;
|
||||
msr_ops.addr = smca_addr_reg;
|
||||
msr_ops.misc = smca_misc_reg;
|
||||
}
|
||||
mce_amd_feature_init(c);
|
||||
|
||||
break;
|
||||
@@ -1717,6 +1780,7 @@ void mcheck_cpu_init(struct cpuinfo_x86 *c)
|
||||
|
||||
__mcheck_cpu_init_generic();
|
||||
__mcheck_cpu_init_vendor(c);
|
||||
__mcheck_cpu_init_clear_banks();
|
||||
__mcheck_cpu_init_timer();
|
||||
}
|
||||
|
||||
@@ -2082,7 +2146,7 @@ static void mce_disable_error_reporting(void)
|
||||
struct mce_bank *b = &mce_banks[i];
|
||||
|
||||
if (b->init)
|
||||
wrmsrl(MSR_IA32_MCx_CTL(i), 0);
|
||||
wrmsrl(msr_ops.ctl(i), 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -2121,6 +2185,7 @@ static void mce_syscore_resume(void)
|
||||
{
|
||||
__mcheck_cpu_init_generic();
|
||||
__mcheck_cpu_init_vendor(raw_cpu_ptr(&cpu_info));
|
||||
__mcheck_cpu_init_clear_banks();
|
||||
}
|
||||
|
||||
static struct syscore_ops mce_syscore_ops = {
|
||||
@@ -2138,6 +2203,7 @@ static void mce_cpu_restart(void *data)
|
||||
if (!mce_available(raw_cpu_ptr(&cpu_info)))
|
||||
return;
|
||||
__mcheck_cpu_init_generic();
|
||||
__mcheck_cpu_init_clear_banks();
|
||||
__mcheck_cpu_init_timer();
|
||||
}
|
||||
|
||||
@@ -2413,7 +2479,7 @@ static void mce_reenable_cpu(void *h)
|
||||
struct mce_bank *b = &mce_banks[i];
|
||||
|
||||
if (b->init)
|
||||
wrmsrl(MSR_IA32_MCx_CTL(i), b->ctl);
|
||||
wrmsrl(msr_ops.ctl(i), b->ctl);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -54,14 +54,6 @@
|
||||
/* Threshold LVT offset is at MSR0xC0000410[15:12] */
|
||||
#define SMCA_THR_LVT_OFF 0xF000
|
||||
|
||||
/*
|
||||
* OS is required to set the MCAX bit to acknowledge that it is now using the
|
||||
* new MSR ranges and new registers under each bank. It also means that the OS
|
||||
* will configure deferred errors in the new MCx_CONFIG register. If the bit is
|
||||
* not set, uncorrectable errors will cause a system panic.
|
||||
*/
|
||||
#define SMCA_MCAX_EN_OFF 0x1
|
||||
|
||||
static const char * const th_names[] = {
|
||||
"load_store",
|
||||
"insn_fetch",
|
||||
@@ -333,7 +325,7 @@ static u32 get_block_address(u32 current_addr, u32 low, u32 high,
|
||||
/* Fall back to method we used for older processors: */
|
||||
switch (block) {
|
||||
case 0:
|
||||
addr = MSR_IA32_MCx_MISC(bank);
|
||||
addr = msr_ops.misc(bank);
|
||||
break;
|
||||
case 1:
|
||||
offset = ((low & MASK_BLKPTR_LO) >> 21);
|
||||
@@ -351,6 +343,7 @@ prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr,
|
||||
int offset, u32 misc_high)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
u32 smca_low, smca_high, smca_addr;
|
||||
struct threshold_block b;
|
||||
int new;
|
||||
|
||||
@@ -369,24 +362,49 @@ prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr,
|
||||
|
||||
b.interrupt_enable = 1;
|
||||
|
||||
if (mce_flags.smca) {
|
||||
u32 smca_low, smca_high;
|
||||
u32 smca_addr = MSR_AMD64_SMCA_MCx_CONFIG(bank);
|
||||
|
||||
if (!rdmsr_safe(smca_addr, &smca_low, &smca_high)) {
|
||||
smca_high |= SMCA_MCAX_EN_OFF;
|
||||
wrmsr(smca_addr, smca_low, smca_high);
|
||||
}
|
||||
|
||||
/* Gather LVT offset for thresholding: */
|
||||
if (rdmsr_safe(MSR_CU_DEF_ERR, &smca_low, &smca_high))
|
||||
goto out;
|
||||
|
||||
new = (smca_low & SMCA_THR_LVT_OFF) >> 12;
|
||||
} else {
|
||||
if (!mce_flags.smca) {
|
||||
new = (misc_high & MASK_LVTOFF_HI) >> 20;
|
||||
goto set_offset;
|
||||
}
|
||||
|
||||
smca_addr = MSR_AMD64_SMCA_MCx_CONFIG(bank);
|
||||
|
||||
if (!rdmsr_safe(smca_addr, &smca_low, &smca_high)) {
|
||||
/*
|
||||
* OS is required to set the MCAX bit to acknowledge that it is
|
||||
* now using the new MSR ranges and new registers under each
|
||||
* bank. It also means that the OS will configure deferred
|
||||
* errors in the new MCx_CONFIG register. If the bit is not set,
|
||||
* uncorrectable errors will cause a system panic.
|
||||
*
|
||||
* MCA_CONFIG[MCAX] is bit 32 (0 in the high portion of the MSR.)
|
||||
*/
|
||||
smca_high |= BIT(0);
|
||||
|
||||
/*
|
||||
* SMCA logs Deferred Error information in MCA_DE{STAT,ADDR}
|
||||
* registers with the option of additionally logging to
|
||||
* MCA_{STATUS,ADDR} if MCA_CONFIG[LogDeferredInMcaStat] is set.
|
||||
*
|
||||
* This bit is usually set by BIOS to retain the old behavior
|
||||
* for OSes that don't use the new registers. Linux supports the
|
||||
* new registers so let's disable that additional logging here.
|
||||
*
|
||||
* MCA_CONFIG[LogDeferredInMcaStat] is bit 34 (bit 2 in the high
|
||||
* portion of the MSR).
|
||||
*/
|
||||
smca_high &= ~BIT(2);
|
||||
|
||||
wrmsr(smca_addr, smca_low, smca_high);
|
||||
}
|
||||
|
||||
/* Gather LVT offset for thresholding: */
|
||||
if (rdmsr_safe(MSR_CU_DEF_ERR, &smca_low, &smca_high))
|
||||
goto out;
|
||||
|
||||
new = (smca_low & SMCA_THR_LVT_OFF) >> 12;
|
||||
|
||||
set_offset:
|
||||
offset = setup_APIC_mce_threshold(offset, new);
|
||||
|
||||
if ((offset == new) && (mce_threshold_vector != amd_threshold_interrupt))
|
||||
@@ -430,12 +448,23 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
|
||||
deferred_error_interrupt_enable(c);
|
||||
}
|
||||
|
||||
static void __log_error(unsigned int bank, bool threshold_err, u64 misc)
|
||||
static void
|
||||
__log_error(unsigned int bank, bool deferred_err, bool threshold_err, u64 misc)
|
||||
{
|
||||
u32 msr_status = msr_ops.status(bank);
|
||||
u32 msr_addr = msr_ops.addr(bank);
|
||||
struct mce m;
|
||||
u64 status;
|
||||
|
||||
rdmsrl(MSR_IA32_MCx_STATUS(bank), status);
|
||||
WARN_ON_ONCE(deferred_err && threshold_err);
|
||||
|
||||
if (deferred_err && mce_flags.smca) {
|
||||
msr_status = MSR_AMD64_SMCA_MCx_DESTAT(bank);
|
||||
msr_addr = MSR_AMD64_SMCA_MCx_DEADDR(bank);
|
||||
}
|
||||
|
||||
rdmsrl(msr_status, status);
|
||||
|
||||
if (!(status & MCI_STATUS_VAL))
|
||||
return;
|
||||
|
||||
@@ -448,10 +477,11 @@ static void __log_error(unsigned int bank, bool threshold_err, u64 misc)
|
||||
m.misc = misc;
|
||||
|
||||
if (m.status & MCI_STATUS_ADDRV)
|
||||
rdmsrl(MSR_IA32_MCx_ADDR(bank), m.addr);
|
||||
rdmsrl(msr_addr, m.addr);
|
||||
|
||||
mce_log(&m);
|
||||
wrmsrl(MSR_IA32_MCx_STATUS(bank), 0);
|
||||
|
||||
wrmsrl(msr_status, 0);
|
||||
}
|
||||
|
||||
static inline void __smp_deferred_error_interrupt(void)
|
||||
@@ -479,17 +509,21 @@ asmlinkage __visible void smp_trace_deferred_error_interrupt(void)
|
||||
/* APIC interrupt handler for deferred errors */
|
||||
static void amd_deferred_error_interrupt(void)
|
||||
{
|
||||
u64 status;
|
||||
unsigned int bank;
|
||||
u32 msr_status;
|
||||
u64 status;
|
||||
|
||||
for (bank = 0; bank < mca_cfg.banks; ++bank) {
|
||||
rdmsrl(MSR_IA32_MCx_STATUS(bank), status);
|
||||
msr_status = (mce_flags.smca) ? MSR_AMD64_SMCA_MCx_DESTAT(bank)
|
||||
: msr_ops.status(bank);
|
||||
|
||||
rdmsrl(msr_status, status);
|
||||
|
||||
if (!(status & MCI_STATUS_VAL) ||
|
||||
!(status & MCI_STATUS_DEFERRED))
|
||||
continue;
|
||||
|
||||
__log_error(bank, false, 0);
|
||||
__log_error(bank, true, false, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -544,7 +578,7 @@ static void amd_threshold_interrupt(void)
|
||||
return;
|
||||
|
||||
log:
|
||||
__log_error(bank, true, ((u64)high << 32) | low);
|
||||
__log_error(bank, false, true, ((u64)high << 32) | low);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -84,7 +84,7 @@ static int cmci_supported(int *banks)
|
||||
*/
|
||||
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
|
||||
return 0;
|
||||
if (!cpu_has_apic || lapic_get_maxlvt() < 6)
|
||||
if (!boot_cpu_has(X86_FEATURE_APIC) || lapic_get_maxlvt() < 6)
|
||||
return 0;
|
||||
rdmsrl(MSR_IA32_MCG_CAP, cap);
|
||||
*banks = min_t(unsigned, MAX_NR_BANKS, cap & 0xff);
|
||||
|
@@ -450,7 +450,7 @@ asmlinkage __visible void smp_trace_thermal_interrupt(struct pt_regs *regs)
|
||||
/* Thermal monitoring depends on APIC, ACPI and clock modulation */
|
||||
static int intel_thermal_supported(struct cpuinfo_x86 *c)
|
||||
{
|
||||
if (!cpu_has_apic)
|
||||
if (!boot_cpu_has(X86_FEATURE_APIC))
|
||||
return 0;
|
||||
if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC))
|
||||
return 0;
|
||||
|
@@ -137,7 +137,7 @@ static void prepare_set(void)
|
||||
u32 cr0;
|
||||
|
||||
/* Save value of CR4 and clear Page Global Enable (bit 7) */
|
||||
if (cpu_has_pge) {
|
||||
if (boot_cpu_has(X86_FEATURE_PGE)) {
|
||||
cr4 = __read_cr4();
|
||||
__write_cr4(cr4 & ~X86_CR4_PGE);
|
||||
}
|
||||
@@ -170,7 +170,7 @@ static void post_set(void)
|
||||
write_cr0(read_cr0() & ~X86_CR0_CD);
|
||||
|
||||
/* Restore value of CR4 */
|
||||
if (cpu_has_pge)
|
||||
if (boot_cpu_has(X86_FEATURE_PGE))
|
||||
__write_cr4(cr4);
|
||||
}
|
||||
|
||||
|
@@ -444,11 +444,24 @@ static void __init print_mtrr_state(void)
|
||||
pr_debug("TOM2: %016llx aka %lldM\n", mtrr_tom2, mtrr_tom2>>20);
|
||||
}
|
||||
|
||||
/* PAT setup for BP. We need to go through sync steps here */
|
||||
void __init mtrr_bp_pat_init(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
prepare_set();
|
||||
|
||||
pat_init();
|
||||
|
||||
post_set();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/* Grab all of the MTRR state for this CPU into *state */
|
||||
bool __init get_mtrr_state(void)
|
||||
{
|
||||
struct mtrr_var_range *vrs;
|
||||
unsigned long flags;
|
||||
unsigned lo, dummy;
|
||||
unsigned int i;
|
||||
|
||||
@@ -481,15 +494,6 @@ bool __init get_mtrr_state(void)
|
||||
|
||||
mtrr_state_set = 1;
|
||||
|
||||
/* PAT setup for BP. We need to go through sync steps here */
|
||||
local_irq_save(flags);
|
||||
prepare_set();
|
||||
|
||||
pat_init();
|
||||
|
||||
post_set();
|
||||
local_irq_restore(flags);
|
||||
|
||||
return !!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED);
|
||||
}
|
||||
|
||||
@@ -741,7 +745,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock)
|
||||
wbinvd();
|
||||
|
||||
/* Save value of CR4 and clear Page Global Enable (bit 7) */
|
||||
if (cpu_has_pge) {
|
||||
if (boot_cpu_has(X86_FEATURE_PGE)) {
|
||||
cr4 = __read_cr4();
|
||||
__write_cr4(cr4 & ~X86_CR4_PGE);
|
||||
}
|
||||
@@ -771,7 +775,7 @@ static void post_set(void) __releases(set_atomicity_lock)
|
||||
write_cr0(read_cr0() & ~X86_CR0_CD);
|
||||
|
||||
/* Restore value of CR4 */
|
||||
if (cpu_has_pge)
|
||||
if (boot_cpu_has(X86_FEATURE_PGE))
|
||||
__write_cr4(cr4);
|
||||
raw_spin_unlock(&set_atomicity_lock);
|
||||
}
|
||||
|
@@ -752,6 +752,9 @@ void __init mtrr_bp_init(void)
|
||||
/* BIOS may override */
|
||||
__mtrr_enabled = get_mtrr_state();
|
||||
|
||||
if (mtrr_enabled())
|
||||
mtrr_bp_pat_init();
|
||||
|
||||
if (mtrr_cleanup(phys_addr)) {
|
||||
changed_by_mtrr_cleanup = 1;
|
||||
mtrr_if->set_all();
|
||||
@@ -759,8 +762,16 @@ void __init mtrr_bp_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (!mtrr_enabled())
|
||||
if (!mtrr_enabled()) {
|
||||
pr_info("MTRR: Disabled\n");
|
||||
|
||||
/*
|
||||
* PAT initialization relies on MTRR's rendezvous handler.
|
||||
* Skip PAT init until the handler can initialize both
|
||||
* features independently.
|
||||
*/
|
||||
pat_disable("MTRRs disabled, skipping PAT initialization too.");
|
||||
}
|
||||
}
|
||||
|
||||
void mtrr_ap_init(void)
|
||||
|
@@ -52,6 +52,7 @@ void set_mtrr_prepare_save(struct set_mtrr_context *ctxt);
|
||||
void fill_mtrr_var_range(unsigned int index,
|
||||
u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi);
|
||||
bool get_mtrr_state(void);
|
||||
void mtrr_bp_pat_init(void);
|
||||
|
||||
extern void set_mtrr_ops(const struct mtrr_ops *ops);
|
||||
|
||||
|
@@ -94,7 +94,7 @@ static void __init vmware_platform_setup(void)
|
||||
*/
|
||||
static uint32_t __init vmware_platform(void)
|
||||
{
|
||||
if (cpu_has_hypervisor) {
|
||||
if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
|
||||
unsigned int eax;
|
||||
unsigned int hyper_vendor_id[3];
|
||||
|
||||
|
@@ -151,7 +151,7 @@ static void __init dtb_lapic_setup(void)
|
||||
return;
|
||||
|
||||
/* Did the boot loader setup the local APIC ? */
|
||||
if (!cpu_has_apic) {
|
||||
if (!boot_cpu_has(X86_FEATURE_APIC)) {
|
||||
if (apic_force_enable(r.start))
|
||||
return;
|
||||
}
|
||||
|
@@ -260,19 +260,12 @@ int __die(const char *str, struct pt_regs *regs, long err)
|
||||
unsigned long sp;
|
||||
#endif
|
||||
printk(KERN_DEFAULT
|
||||
"%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
|
||||
#ifdef CONFIG_PREEMPT
|
||||
printk("PREEMPT ");
|
||||
#endif
|
||||
#ifdef CONFIG_SMP
|
||||
printk("SMP ");
|
||||
#endif
|
||||
if (debug_pagealloc_enabled())
|
||||
printk("DEBUG_PAGEALLOC ");
|
||||
#ifdef CONFIG_KASAN
|
||||
printk("KASAN");
|
||||
#endif
|
||||
printk("\n");
|
||||
"%s: %04lx [#%d]%s%s%s%s\n", str, err & 0xffff, ++die_counter,
|
||||
IS_ENABLED(CONFIG_PREEMPT) ? " PREEMPT" : "",
|
||||
IS_ENABLED(CONFIG_SMP) ? " SMP" : "",
|
||||
debug_pagealloc_enabled() ? " DEBUG_PAGEALLOC" : "",
|
||||
IS_ENABLED(CONFIG_KASAN) ? " KASAN" : "");
|
||||
|
||||
if (notify_die(DIE_OOPS, str, regs, err,
|
||||
current->thread.trap_nr, SIGSEGV) == NOTIFY_STOP)
|
||||
return 1;
|
||||
|
@@ -38,7 +38,7 @@ void __init reserve_ebda_region(void)
|
||||
* that the paravirt case can handle memory setup
|
||||
* correctly, without our help.
|
||||
*/
|
||||
if (paravirt_enabled())
|
||||
if (!x86_platform.legacy.ebda_search)
|
||||
return;
|
||||
|
||||
/* end of low (conventional) memory */
|
@@ -21,11 +21,15 @@ static double __initdata y = 3145727.0;
|
||||
* We should really only care about bugs here
|
||||
* anyway. Not features.
|
||||
*/
|
||||
static void __init check_fpu(void)
|
||||
void __init fpu__init_check_bugs(void)
|
||||
{
|
||||
u32 cr0_saved;
|
||||
s32 fdiv_bug;
|
||||
|
||||
/* kernel_fpu_begin/end() relies on patched alternative instructions. */
|
||||
if (!boot_cpu_has(X86_FEATURE_FPU))
|
||||
return;
|
||||
|
||||
/* We might have CR0::TS set already, clear it: */
|
||||
cr0_saved = read_cr0();
|
||||
write_cr0(cr0_saved & ~X86_CR0_TS);
|
||||
@@ -59,13 +63,3 @@ static void __init check_fpu(void)
|
||||
pr_warn("Hmm, FPU with FDIV bug\n");
|
||||
}
|
||||
}
|
||||
|
||||
void __init fpu__init_check_bugs(void)
|
||||
{
|
||||
/*
|
||||
* kernel_fpu_begin/end() in check_fpu() relies on the patched
|
||||
* alternative instructions.
|
||||
*/
|
||||
if (cpu_has_fpu)
|
||||
check_fpu();
|
||||
}
|
||||
|
@@ -217,14 +217,14 @@ static inline void fpstate_init_fstate(struct fregs_state *fp)
|
||||
|
||||
void fpstate_init(union fpregs_state *state)
|
||||
{
|
||||
if (!cpu_has_fpu) {
|
||||
if (!static_cpu_has(X86_FEATURE_FPU)) {
|
||||
fpstate_init_soft(&state->soft);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(state, 0, xstate_size);
|
||||
|
||||
if (cpu_has_fxsr)
|
||||
if (static_cpu_has(X86_FEATURE_FXSR))
|
||||
fpstate_init_fxstate(&state->fxsave);
|
||||
else
|
||||
fpstate_init_fstate(&state->fsave);
|
||||
@@ -237,7 +237,7 @@ int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)
|
||||
dst_fpu->fpregs_active = 0;
|
||||
dst_fpu->last_cpu = -1;
|
||||
|
||||
if (!src_fpu->fpstate_active || !cpu_has_fpu)
|
||||
if (!src_fpu->fpstate_active || !static_cpu_has(X86_FEATURE_FPU))
|
||||
return 0;
|
||||
|
||||
WARN_ON_FPU(src_fpu != ¤t->thread.fpu);
|
||||
@@ -506,33 +506,6 @@ void fpu__clear(struct fpu *fpu)
|
||||
* x87 math exception handling:
|
||||
*/
|
||||
|
||||
static inline unsigned short get_fpu_cwd(struct fpu *fpu)
|
||||
{
|
||||
if (cpu_has_fxsr) {
|
||||
return fpu->state.fxsave.cwd;
|
||||
} else {
|
||||
return (unsigned short)fpu->state.fsave.cwd;
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned short get_fpu_swd(struct fpu *fpu)
|
||||
{
|
||||
if (cpu_has_fxsr) {
|
||||
return fpu->state.fxsave.swd;
|
||||
} else {
|
||||
return (unsigned short)fpu->state.fsave.swd;
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned short get_fpu_mxcsr(struct fpu *fpu)
|
||||
{
|
||||
if (cpu_has_xmm) {
|
||||
return fpu->state.fxsave.mxcsr;
|
||||
} else {
|
||||
return MXCSR_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
int fpu__exception_code(struct fpu *fpu, int trap_nr)
|
||||
{
|
||||
int err;
|
||||
@@ -547,10 +520,15 @@ int fpu__exception_code(struct fpu *fpu, int trap_nr)
|
||||
* so if this combination doesn't produce any single exception,
|
||||
* then we have a bad program that isn't synchronizing its FPU usage
|
||||
* and it will suffer the consequences since we won't be able to
|
||||
* fully reproduce the context of the exception
|
||||
* fully reproduce the context of the exception.
|
||||
*/
|
||||
cwd = get_fpu_cwd(fpu);
|
||||
swd = get_fpu_swd(fpu);
|
||||
if (boot_cpu_has(X86_FEATURE_FXSR)) {
|
||||
cwd = fpu->state.fxsave.cwd;
|
||||
swd = fpu->state.fxsave.swd;
|
||||
} else {
|
||||
cwd = (unsigned short)fpu->state.fsave.cwd;
|
||||
swd = (unsigned short)fpu->state.fsave.swd;
|
||||
}
|
||||
|
||||
err = swd & ~cwd;
|
||||
} else {
|
||||
@@ -560,7 +538,11 @@ int fpu__exception_code(struct fpu *fpu, int trap_nr)
|
||||
* unmasked exception was caught we must mask the exception mask bits
|
||||
* at 0x1f80, and then use these to mask the exception bits at 0x3f.
|
||||
*/
|
||||
unsigned short mxcsr = get_fpu_mxcsr(fpu);
|
||||
unsigned short mxcsr = MXCSR_DEFAULT;
|
||||
|
||||
if (boot_cpu_has(X86_FEATURE_XMM))
|
||||
mxcsr = fpu->state.fxsave.mxcsr;
|
||||
|
||||
err = ~(mxcsr >> 7) & mxcsr;
|
||||
}
|
||||
|
||||
|
@@ -29,22 +29,22 @@ static void fpu__init_cpu_generic(void)
|
||||
unsigned long cr0;
|
||||
unsigned long cr4_mask = 0;
|
||||
|
||||
if (cpu_has_fxsr)
|
||||
if (boot_cpu_has(X86_FEATURE_FXSR))
|
||||
cr4_mask |= X86_CR4_OSFXSR;
|
||||
if (cpu_has_xmm)
|
||||
if (boot_cpu_has(X86_FEATURE_XMM))
|
||||
cr4_mask |= X86_CR4_OSXMMEXCPT;
|
||||
if (cr4_mask)
|
||||
cr4_set_bits(cr4_mask);
|
||||
|
||||
cr0 = read_cr0();
|
||||
cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */
|
||||
if (!cpu_has_fpu)
|
||||
if (!boot_cpu_has(X86_FEATURE_FPU))
|
||||
cr0 |= X86_CR0_EM;
|
||||
write_cr0(cr0);
|
||||
|
||||
/* Flush out any pending x87 state: */
|
||||
#ifdef CONFIG_MATH_EMULATION
|
||||
if (!cpu_has_fpu)
|
||||
if (!boot_cpu_has(X86_FEATURE_FPU))
|
||||
fpstate_init_soft(¤t->thread.fpu.state.soft);
|
||||
else
|
||||
#endif
|
||||
@@ -89,7 +89,7 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
|
||||
}
|
||||
|
||||
#ifndef CONFIG_MATH_EMULATION
|
||||
if (!cpu_has_fpu) {
|
||||
if (!boot_cpu_has(X86_FEATURE_FPU)) {
|
||||
pr_emerg("x86/fpu: Giving up, no FPU found and no math emulation present\n");
|
||||
for (;;)
|
||||
asm volatile("hlt");
|
||||
@@ -106,7 +106,7 @@ static void __init fpu__init_system_mxcsr(void)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
|
||||
if (cpu_has_fxsr) {
|
||||
if (boot_cpu_has(X86_FEATURE_FXSR)) {
|
||||
/* Static because GCC does not get 16-byte stack alignment right: */
|
||||
static struct fxregs_state fxregs __initdata;
|
||||
|
||||
@@ -212,7 +212,7 @@ static void __init fpu__init_system_xstate_size_legacy(void)
|
||||
* fpu__init_system_xstate().
|
||||
*/
|
||||
|
||||
if (!cpu_has_fpu) {
|
||||
if (!boot_cpu_has(X86_FEATURE_FPU)) {
|
||||
/*
|
||||
* Disable xsave as we do not support it if i387
|
||||
* emulation is enabled.
|
||||
@@ -221,7 +221,7 @@ static void __init fpu__init_system_xstate_size_legacy(void)
|
||||
setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
|
||||
xstate_size = sizeof(struct swregs_state);
|
||||
} else {
|
||||
if (cpu_has_fxsr)
|
||||
if (boot_cpu_has(X86_FEATURE_FXSR))
|
||||
xstate_size = sizeof(struct fxregs_state);
|
||||
else
|
||||
xstate_size = sizeof(struct fregs_state);
|
||||
|
@@ -21,7 +21,10 @@ int regset_xregset_fpregs_active(struct task_struct *target, const struct user_r
|
||||
{
|
||||
struct fpu *target_fpu = &target->thread.fpu;
|
||||
|
||||
return (cpu_has_fxsr && target_fpu->fpstate_active) ? regset->n : 0;
|
||||
if (boot_cpu_has(X86_FEATURE_FXSR) && target_fpu->fpstate_active)
|
||||
return regset->n;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xfpregs_get(struct task_struct *target, const struct user_regset *regset,
|
||||
@@ -30,7 +33,7 @@ int xfpregs_get(struct task_struct *target, const struct user_regset *regset,
|
||||
{
|
||||
struct fpu *fpu = &target->thread.fpu;
|
||||
|
||||
if (!cpu_has_fxsr)
|
||||
if (!boot_cpu_has(X86_FEATURE_FXSR))
|
||||
return -ENODEV;
|
||||
|
||||
fpu__activate_fpstate_read(fpu);
|
||||
@@ -47,7 +50,7 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
|
||||
struct fpu *fpu = &target->thread.fpu;
|
||||
int ret;
|
||||
|
||||
if (!cpu_has_fxsr)
|
||||
if (!boot_cpu_has(X86_FEATURE_FXSR))
|
||||
return -ENODEV;
|
||||
|
||||
fpu__activate_fpstate_write(fpu);
|
||||
@@ -65,7 +68,7 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
|
||||
* update the header bits in the xsave header, indicating the
|
||||
* presence of FP and SSE state.
|
||||
*/
|
||||
if (cpu_has_xsave)
|
||||
if (boot_cpu_has(X86_FEATURE_XSAVE))
|
||||
fpu->state.xsave.header.xfeatures |= XFEATURE_MASK_FPSSE;
|
||||
|
||||
return ret;
|
||||
@@ -79,7 +82,7 @@ int xstateregs_get(struct task_struct *target, const struct user_regset *regset,
|
||||
struct xregs_state *xsave;
|
||||
int ret;
|
||||
|
||||
if (!cpu_has_xsave)
|
||||
if (!boot_cpu_has(X86_FEATURE_XSAVE))
|
||||
return -ENODEV;
|
||||
|
||||
fpu__activate_fpstate_read(fpu);
|
||||
@@ -108,7 +111,7 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
|
||||
struct xregs_state *xsave;
|
||||
int ret;
|
||||
|
||||
if (!cpu_has_xsave)
|
||||
if (!boot_cpu_has(X86_FEATURE_XSAVE))
|
||||
return -ENODEV;
|
||||
|
||||
fpu__activate_fpstate_write(fpu);
|
||||
@@ -275,10 +278,10 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset,
|
||||
|
||||
fpu__activate_fpstate_read(fpu);
|
||||
|
||||
if (!static_cpu_has(X86_FEATURE_FPU))
|
||||
if (!boot_cpu_has(X86_FEATURE_FPU))
|
||||
return fpregs_soft_get(target, regset, pos, count, kbuf, ubuf);
|
||||
|
||||
if (!cpu_has_fxsr)
|
||||
if (!boot_cpu_has(X86_FEATURE_FXSR))
|
||||
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
&fpu->state.fsave, 0,
|
||||
-1);
|
||||
@@ -306,10 +309,10 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
|
||||
fpu__activate_fpstate_write(fpu);
|
||||
fpstate_sanitize_xstate(fpu);
|
||||
|
||||
if (!static_cpu_has(X86_FEATURE_FPU))
|
||||
if (!boot_cpu_has(X86_FEATURE_FPU))
|
||||
return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf);
|
||||
|
||||
if (!cpu_has_fxsr)
|
||||
if (!boot_cpu_has(X86_FEATURE_FXSR))
|
||||
return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
&fpu->state.fsave, 0,
|
||||
-1);
|
||||
@@ -325,7 +328,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
|
||||
* update the header bit in the xsave header, indicating the
|
||||
* presence of FP.
|
||||
*/
|
||||
if (cpu_has_xsave)
|
||||
if (boot_cpu_has(X86_FEATURE_XSAVE))
|
||||
fpu->state.xsave.header.xfeatures |= XFEATURE_MASK_FP;
|
||||
return ret;
|
||||
}
|
||||
|
@@ -190,7 +190,7 @@ void fpstate_sanitize_xstate(struct fpu *fpu)
|
||||
*/
|
||||
void fpu__init_cpu_xstate(void)
|
||||
{
|
||||
if (!cpu_has_xsave || !xfeatures_mask)
|
||||
if (!boot_cpu_has(X86_FEATURE_XSAVE) || !xfeatures_mask)
|
||||
return;
|
||||
|
||||
cr4_set_bits(X86_CR4_OSXSAVE);
|
||||
@@ -280,7 +280,7 @@ static void __init setup_xstate_comp(void)
|
||||
xstate_comp_offsets[0] = 0;
|
||||
xstate_comp_offsets[1] = offsetof(struct fxregs_state, xmm_space);
|
||||
|
||||
if (!cpu_has_xsaves) {
|
||||
if (!boot_cpu_has(X86_FEATURE_XSAVES)) {
|
||||
for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) {
|
||||
if (xfeature_enabled(i)) {
|
||||
xstate_comp_offsets[i] = xstate_offsets[i];
|
||||
@@ -316,13 +316,13 @@ static void __init setup_init_fpu_buf(void)
|
||||
WARN_ON_FPU(!on_boot_cpu);
|
||||
on_boot_cpu = 0;
|
||||
|
||||
if (!cpu_has_xsave)
|
||||
if (!boot_cpu_has(X86_FEATURE_XSAVE))
|
||||
return;
|
||||
|
||||
setup_xstate_features();
|
||||
print_xstate_features();
|
||||
|
||||
if (cpu_has_xsaves) {
|
||||
if (boot_cpu_has(X86_FEATURE_XSAVES)) {
|
||||
init_fpstate.xsave.header.xcomp_bv = (u64)1 << 63 | xfeatures_mask;
|
||||
init_fpstate.xsave.header.xfeatures = xfeatures_mask;
|
||||
}
|
||||
@@ -417,7 +417,7 @@ static int xfeature_size(int xfeature_nr)
|
||||
*/
|
||||
static int using_compacted_format(void)
|
||||
{
|
||||
return cpu_has_xsaves;
|
||||
return boot_cpu_has(X86_FEATURE_XSAVES);
|
||||
}
|
||||
|
||||
static void __xstate_dump_leaves(void)
|
||||
@@ -549,7 +549,7 @@ static unsigned int __init calculate_xstate_size(void)
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
unsigned int calculated_xstate_size;
|
||||
|
||||
if (!cpu_has_xsaves) {
|
||||
if (!boot_cpu_has(X86_FEATURE_XSAVES)) {
|
||||
/*
|
||||
* - CPUID function 0DH, sub-function 0:
|
||||
* EBX enumerates the size (in bytes) required by
|
||||
@@ -630,7 +630,7 @@ void __init fpu__init_system_xstate(void)
|
||||
WARN_ON_FPU(!on_boot_cpu);
|
||||
on_boot_cpu = 0;
|
||||
|
||||
if (!cpu_has_xsave) {
|
||||
if (!boot_cpu_has(X86_FEATURE_XSAVE)) {
|
||||
pr_info("x86/fpu: Legacy x87 FPU detected.\n");
|
||||
return;
|
||||
}
|
||||
@@ -667,7 +667,7 @@ void __init fpu__init_system_xstate(void)
|
||||
pr_info("x86/fpu: Enabled xstate features 0x%llx, context size is %d bytes, using '%s' format.\n",
|
||||
xfeatures_mask,
|
||||
xstate_size,
|
||||
cpu_has_xsaves ? "compacted" : "standard");
|
||||
boot_cpu_has(X86_FEATURE_XSAVES) ? "compacted" : "standard");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -678,7 +678,7 @@ void fpu__resume_cpu(void)
|
||||
/*
|
||||
* Restore XCR0 on xsave capable CPUs:
|
||||
*/
|
||||
if (cpu_has_xsave)
|
||||
if (boot_cpu_has(X86_FEATURE_XSAVE))
|
||||
xsetbv(XCR_XFEATURE_ENABLED_MASK, xfeatures_mask);
|
||||
}
|
||||
|
||||
|
@@ -34,6 +34,8 @@ asmlinkage __visible void __init i386_start_kernel(void)
|
||||
cr4_init_shadow();
|
||||
sanitize_boot_params(&boot_params);
|
||||
|
||||
x86_early_init_platform_quirks();
|
||||
|
||||
/* Call the subarch specific early setup function */
|
||||
switch (boot_params.hdr.hardware_subarch) {
|
||||
case X86_SUBARCH_INTEL_MID:
|
||||
|
@@ -182,6 +182,7 @@ void __init x86_64_start_reservations(char *real_mode_data)
|
||||
if (!boot_params.hdr.version)
|
||||
copy_bootdata(__va(real_mode_data));
|
||||
|
||||
x86_early_init_platform_quirks();
|
||||
reserve_ebda_region();
|
||||
|
||||
switch (boot_params.hdr.hardware_subarch) {
|
||||
|
@@ -555,62 +555,53 @@ early_idt_handler_common:
|
||||
*/
|
||||
cld
|
||||
|
||||
cmpl $2,(%esp) # X86_TRAP_NMI
|
||||
je .Lis_nmi # Ignore NMI
|
||||
|
||||
cmpl $2,%ss:early_recursion_flag
|
||||
je hlt_loop
|
||||
incl %ss:early_recursion_flag
|
||||
|
||||
push %eax # 16(%esp)
|
||||
push %ecx # 12(%esp)
|
||||
push %edx # 8(%esp)
|
||||
push %ds # 4(%esp)
|
||||
push %es # 0(%esp)
|
||||
movl $(__KERNEL_DS),%eax
|
||||
movl %eax,%ds
|
||||
movl %eax,%es
|
||||
/* The vector number is in pt_regs->gs */
|
||||
|
||||
cmpl $(__KERNEL_CS),32(%esp)
|
||||
jne 10f
|
||||
cld
|
||||
pushl %fs /* pt_regs->fs */
|
||||
movw $0, 2(%esp) /* clear high bits (some CPUs leave garbage) */
|
||||
pushl %es /* pt_regs->es */
|
||||
movw $0, 2(%esp) /* clear high bits (some CPUs leave garbage) */
|
||||
pushl %ds /* pt_regs->ds */
|
||||
movw $0, 2(%esp) /* clear high bits (some CPUs leave garbage) */
|
||||
pushl %eax /* pt_regs->ax */
|
||||
pushl %ebp /* pt_regs->bp */
|
||||
pushl %edi /* pt_regs->di */
|
||||
pushl %esi /* pt_regs->si */
|
||||
pushl %edx /* pt_regs->dx */
|
||||
pushl %ecx /* pt_regs->cx */
|
||||
pushl %ebx /* pt_regs->bx */
|
||||
|
||||
leal 28(%esp),%eax # Pointer to %eip
|
||||
call early_fixup_exception
|
||||
andl %eax,%eax
|
||||
jnz ex_entry /* found an exception entry */
|
||||
/* Fix up DS and ES */
|
||||
movl $(__KERNEL_DS), %ecx
|
||||
movl %ecx, %ds
|
||||
movl %ecx, %es
|
||||
|
||||
10:
|
||||
#ifdef CONFIG_PRINTK
|
||||
xorl %eax,%eax
|
||||
movw %ax,2(%esp) /* clean up the segment values on some cpus */
|
||||
movw %ax,6(%esp)
|
||||
movw %ax,34(%esp)
|
||||
leal 40(%esp),%eax
|
||||
pushl %eax /* %esp before the exception */
|
||||
pushl %ebx
|
||||
pushl %ebp
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
movl %cr2,%eax
|
||||
pushl %eax
|
||||
pushl (20+6*4)(%esp) /* trapno */
|
||||
pushl $fault_msg
|
||||
call printk
|
||||
#endif
|
||||
call dump_stack
|
||||
hlt_loop:
|
||||
hlt
|
||||
jmp hlt_loop
|
||||
/* Load the vector number into EDX */
|
||||
movl PT_GS(%esp), %edx
|
||||
|
||||
ex_entry:
|
||||
pop %es
|
||||
pop %ds
|
||||
pop %edx
|
||||
pop %ecx
|
||||
pop %eax
|
||||
decl %ss:early_recursion_flag
|
||||
.Lis_nmi:
|
||||
addl $8,%esp /* drop vector number and error code */
|
||||
/* Load GS into pt_regs->gs and clear high bits */
|
||||
movw %gs, PT_GS(%esp)
|
||||
movw $0, PT_GS+2(%esp)
|
||||
|
||||
movl %esp, %eax /* args are pt_regs (EAX), trapnr (EDX) */
|
||||
call early_fixup_exception
|
||||
|
||||
popl %ebx /* pt_regs->bx */
|
||||
popl %ecx /* pt_regs->cx */
|
||||
popl %edx /* pt_regs->dx */
|
||||
popl %esi /* pt_regs->si */
|
||||
popl %edi /* pt_regs->di */
|
||||
popl %ebp /* pt_regs->bp */
|
||||
popl %eax /* pt_regs->ax */
|
||||
popl %ds /* pt_regs->ds */
|
||||
popl %es /* pt_regs->es */
|
||||
popl %fs /* pt_regs->fs */
|
||||
popl %gs /* pt_regs->gs */
|
||||
decl %ss:early_recursion_flag
|
||||
addl $4, %esp /* pop pt_regs->orig_ax */
|
||||
iret
|
||||
ENDPROC(early_idt_handler_common)
|
||||
|
||||
@@ -647,10 +638,14 @@ ignore_int:
|
||||
popl %eax
|
||||
#endif
|
||||
iret
|
||||
|
||||
hlt_loop:
|
||||
hlt
|
||||
jmp hlt_loop
|
||||
ENDPROC(ignore_int)
|
||||
__INITDATA
|
||||
.align 4
|
||||
early_recursion_flag:
|
||||
GLOBAL(early_recursion_flag)
|
||||
.long 0
|
||||
|
||||
__REFDATA
|
||||
@@ -715,19 +710,6 @@ __INITRODATA
|
||||
int_msg:
|
||||
.asciz "Unknown interrupt or fault at: %p %p %p\n"
|
||||
|
||||
fault_msg:
|
||||
/* fault info: */
|
||||
.ascii "BUG: Int %d: CR2 %p\n"
|
||||
/* regs pushed in early_idt_handler: */
|
||||
.ascii " EDI %p ESI %p EBP %p EBX %p\n"
|
||||
.ascii " ESP %p ES %p DS %p\n"
|
||||
.ascii " EDX %p ECX %p EAX %p\n"
|
||||
/* fault frame: */
|
||||
.ascii " vec %p err %p EIP %p CS %p flg %p\n"
|
||||
.ascii "Stack: %p %p %p %p %p %p %p %p\n"
|
||||
.ascii " %p %p %p %p %p %p %p %p\n"
|
||||
.asciz " %p %p %p %p %p %p %p %p\n"
|
||||
|
||||
#include "../../x86/xen/xen-head.S"
|
||||
|
||||
/*
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include <asm/processor-flags.h>
|
||||
#include <asm/percpu.h>
|
||||
#include <asm/nops.h>
|
||||
#include "../entry/calling.h"
|
||||
|
||||
#ifdef CONFIG_PARAVIRT
|
||||
#include <asm/asm-offsets.h>
|
||||
@@ -64,6 +65,14 @@ startup_64:
|
||||
* tables and then reload them.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Setup stack for verify_cpu(). "-8" because stack_start is defined
|
||||
* this way, see below. Our best guess is a NULL ptr for stack
|
||||
* termination heuristics and we don't want to break anything which
|
||||
* might depend on it (kgdb, ...).
|
||||
*/
|
||||
leaq (__end_init_task - 8)(%rip), %rsp
|
||||
|
||||
/* Sanitize CPU configuration */
|
||||
call verify_cpu
|
||||
|
||||
@@ -350,90 +359,48 @@ early_idt_handler_common:
|
||||
*/
|
||||
cld
|
||||
|
||||
cmpl $2,(%rsp) # X86_TRAP_NMI
|
||||
je .Lis_nmi # Ignore NMI
|
||||
|
||||
cmpl $2,early_recursion_flag(%rip)
|
||||
jz 1f
|
||||
incl early_recursion_flag(%rip)
|
||||
|
||||
pushq %rax # 64(%rsp)
|
||||
pushq %rcx # 56(%rsp)
|
||||
pushq %rdx # 48(%rsp)
|
||||
pushq %rsi # 40(%rsp)
|
||||
pushq %rdi # 32(%rsp)
|
||||
pushq %r8 # 24(%rsp)
|
||||
pushq %r9 # 16(%rsp)
|
||||
pushq %r10 # 8(%rsp)
|
||||
pushq %r11 # 0(%rsp)
|
||||
/* The vector number is currently in the pt_regs->di slot. */
|
||||
pushq %rsi /* pt_regs->si */
|
||||
movq 8(%rsp), %rsi /* RSI = vector number */
|
||||
movq %rdi, 8(%rsp) /* pt_regs->di = RDI */
|
||||
pushq %rdx /* pt_regs->dx */
|
||||
pushq %rcx /* pt_regs->cx */
|
||||
pushq %rax /* pt_regs->ax */
|
||||
pushq %r8 /* pt_regs->r8 */
|
||||
pushq %r9 /* pt_regs->r9 */
|
||||
pushq %r10 /* pt_regs->r10 */
|
||||
pushq %r11 /* pt_regs->r11 */
|
||||
pushq %rbx /* pt_regs->bx */
|
||||
pushq %rbp /* pt_regs->bp */
|
||||
pushq %r12 /* pt_regs->r12 */
|
||||
pushq %r13 /* pt_regs->r13 */
|
||||
pushq %r14 /* pt_regs->r14 */
|
||||
pushq %r15 /* pt_regs->r15 */
|
||||
|
||||
cmpl $__KERNEL_CS,96(%rsp)
|
||||
jne 11f
|
||||
|
||||
cmpl $14,72(%rsp) # Page fault?
|
||||
cmpq $14,%rsi /* Page fault? */
|
||||
jnz 10f
|
||||
GET_CR2_INTO(%rdi) # can clobber any volatile register if pv
|
||||
GET_CR2_INTO(%rdi) /* Can clobber any volatile register if pv */
|
||||
call early_make_pgtable
|
||||
andl %eax,%eax
|
||||
jz 20f # All good
|
||||
jz 20f /* All good */
|
||||
|
||||
10:
|
||||
leaq 88(%rsp),%rdi # Pointer to %rip
|
||||
movq %rsp,%rdi /* RDI = pt_regs; RSI is already trapnr */
|
||||
call early_fixup_exception
|
||||
andl %eax,%eax
|
||||
jnz 20f # Found an exception entry
|
||||
|
||||
11:
|
||||
#ifdef CONFIG_EARLY_PRINTK
|
||||
GET_CR2_INTO(%r9) # can clobber any volatile register if pv
|
||||
movl 80(%rsp),%r8d # error code
|
||||
movl 72(%rsp),%esi # vector number
|
||||
movl 96(%rsp),%edx # %cs
|
||||
movq 88(%rsp),%rcx # %rip
|
||||
xorl %eax,%eax
|
||||
leaq early_idt_msg(%rip),%rdi
|
||||
call early_printk
|
||||
cmpl $2,early_recursion_flag(%rip)
|
||||
jz 1f
|
||||
call dump_stack
|
||||
#ifdef CONFIG_KALLSYMS
|
||||
leaq early_idt_ripmsg(%rip),%rdi
|
||||
movq 40(%rsp),%rsi # %rip again
|
||||
call __print_symbol
|
||||
#endif
|
||||
#endif /* EARLY_PRINTK */
|
||||
1: hlt
|
||||
jmp 1b
|
||||
|
||||
20: # Exception table entry found or page table generated
|
||||
popq %r11
|
||||
popq %r10
|
||||
popq %r9
|
||||
popq %r8
|
||||
popq %rdi
|
||||
popq %rsi
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rax
|
||||
20:
|
||||
decl early_recursion_flag(%rip)
|
||||
.Lis_nmi:
|
||||
addq $16,%rsp # drop vector number and error code
|
||||
INTERRUPT_RETURN
|
||||
jmp restore_regs_and_iret
|
||||
ENDPROC(early_idt_handler_common)
|
||||
|
||||
__INITDATA
|
||||
|
||||
.balign 4
|
||||
early_recursion_flag:
|
||||
GLOBAL(early_recursion_flag)
|
||||
.long 0
|
||||
|
||||
#ifdef CONFIG_EARLY_PRINTK
|
||||
early_idt_msg:
|
||||
.asciz "PANIC: early exception %02lx rip %lx:%lx error %lx cr2 %lx\n"
|
||||
early_idt_ripmsg:
|
||||
.asciz "RIP %s\n"
|
||||
#endif /* CONFIG_EARLY_PRINTK */
|
||||
|
||||
#define NEXT_PAGE(name) \
|
||||
.balign PAGE_SIZE; \
|
||||
GLOBAL(name)
|
||||
|
@@ -54,7 +54,7 @@ struct hpet_dev {
|
||||
char name[10];
|
||||
};
|
||||
|
||||
inline struct hpet_dev *EVT_TO_HPET_DEV(struct clock_event_device *evtdev)
|
||||
static inline struct hpet_dev *EVT_TO_HPET_DEV(struct clock_event_device *evtdev)
|
||||
{
|
||||
return container_of(evtdev, struct hpet_dev, evt);
|
||||
}
|
||||
@@ -773,7 +773,6 @@ static struct clocksource clocksource_hpet = {
|
||||
.mask = HPET_MASK,
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
.resume = hpet_resume_counter,
|
||||
.archdata = { .vclock_mode = VCLOCK_HPET },
|
||||
};
|
||||
|
||||
static int hpet_clocksource_register(void)
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include <linux/cpu.h>
|
||||
#include <asm/kprobes.h>
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/text-patching.h>
|
||||
|
||||
#ifdef HAVE_JUMP_LABEL
|
||||
|
||||
|
@@ -45,6 +45,7 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/memory.h>
|
||||
|
||||
#include <asm/text-patching.h>
|
||||
#include <asm/debugreg.h>
|
||||
#include <asm/apicdef.h>
|
||||
#include <asm/apic.h>
|
||||
|
@@ -51,6 +51,7 @@
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/frame.h>
|
||||
|
||||
#include <asm/text-patching.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/ftrace.h>
|
||||
|
||||
#include <asm/text-patching.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
@@ -285,14 +285,6 @@ static void __init paravirt_ops_setup(void)
|
||||
{
|
||||
pv_info.name = "KVM";
|
||||
|
||||
/*
|
||||
* KVM isn't paravirt in the sense of paravirt_enabled. A KVM
|
||||
* guest kernel works like a bare metal kernel with additional
|
||||
* features, and paravirt_enabled is about features that are
|
||||
* missing.
|
||||
*/
|
||||
pv_info.paravirt_enabled = 0;
|
||||
|
||||
if (kvm_para_has_feature(KVM_FEATURE_NOP_IO_DELAY))
|
||||
pv_cpu_ops.io_delay = kvm_io_delay;
|
||||
|
||||
@@ -522,7 +514,7 @@ static noinline uint32_t __kvm_cpuid_base(void)
|
||||
if (boot_cpu_data.cpuid_level < 0)
|
||||
return 0; /* So we don't blow up on old processors */
|
||||
|
||||
if (cpu_has_hypervisor)
|
||||
if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
|
||||
return hypervisor_cpuid_base("KVMKVMKVM\0\0\0", 0);
|
||||
|
||||
return 0;
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include <linux/jump_label.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <asm/text-patching.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/setup.h>
|
||||
|
@@ -294,7 +294,6 @@ enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
|
||||
|
||||
struct pv_info pv_info = {
|
||||
.name = "bare hardware",
|
||||
.paravirt_enabled = 0,
|
||||
.kernel_rpl = 0,
|
||||
.shared_kernel_pmd = 1, /* Only used when CONFIG_X86_PAE is set */
|
||||
|
||||
@@ -339,8 +338,10 @@ __visible struct pv_cpu_ops pv_cpu_ops = {
|
||||
.write_cr8 = native_write_cr8,
|
||||
#endif
|
||||
.wbinvd = native_wbinvd,
|
||||
.read_msr = native_read_msr_safe,
|
||||
.write_msr = native_write_msr_safe,
|
||||
.read_msr = native_read_msr,
|
||||
.write_msr = native_write_msr,
|
||||
.read_msr_safe = native_read_msr_safe,
|
||||
.write_msr_safe = native_write_msr_safe,
|
||||
.read_pmc = native_read_pmc,
|
||||
.load_tr_desc = native_load_tr_desc,
|
||||
.set_ldt = native_set_ldt,
|
||||
|
@@ -72,7 +72,7 @@ void __init check_iommu_entries(struct iommu_table_entry *start,
|
||||
}
|
||||
}
|
||||
#else
|
||||
inline void check_iommu_entries(struct iommu_table_entry *start,
|
||||
void __init check_iommu_entries(struct iommu_table_entry *start,
|
||||
struct iommu_table_entry *finish)
|
||||
{
|
||||
}
|
||||
|
35
arch/x86/kernel/platform-quirks.c
Normal file
35
arch/x86/kernel/platform-quirks.c
Normal file
@@ -0,0 +1,35 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/bios_ebda.h>
|
||||
|
||||
void __init x86_early_init_platform_quirks(void)
|
||||
{
|
||||
x86_platform.legacy.rtc = 1;
|
||||
x86_platform.legacy.ebda_search = 0;
|
||||
x86_platform.legacy.devices.pnpbios = 1;
|
||||
|
||||
switch (boot_params.hdr.hardware_subarch) {
|
||||
case X86_SUBARCH_PC:
|
||||
x86_platform.legacy.ebda_search = 1;
|
||||
break;
|
||||
case X86_SUBARCH_XEN:
|
||||
case X86_SUBARCH_LGUEST:
|
||||
case X86_SUBARCH_INTEL_MID:
|
||||
case X86_SUBARCH_CE4100:
|
||||
x86_platform.legacy.devices.pnpbios = 0;
|
||||
x86_platform.legacy.rtc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (x86_platform.set_legacy_features)
|
||||
x86_platform.set_legacy_features();
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PNPBIOS)
|
||||
bool __init arch_pnpbios_disabled(void)
|
||||
{
|
||||
return x86_platform.legacy.devices.pnpbios == 0;
|
||||
}
|
||||
#endif
|
@@ -136,25 +136,6 @@ void release_thread(struct task_struct *dead_task)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
|
||||
{
|
||||
struct user_desc ud = {
|
||||
.base_addr = addr,
|
||||
.limit = 0xfffff,
|
||||
.seg_32bit = 1,
|
||||
.limit_in_pages = 1,
|
||||
.useable = 1,
|
||||
};
|
||||
struct desc_struct *desc = t->thread.tls_array;
|
||||
desc += tls;
|
||||
fill_ldt(desc, &ud);
|
||||
}
|
||||
|
||||
static inline u32 read_32bit_tls(struct task_struct *t, int tls)
|
||||
{
|
||||
return get_desc_base(&t->thread.tls_array[tls]);
|
||||
}
|
||||
|
||||
int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
|
||||
unsigned long arg, struct task_struct *p, unsigned long tls)
|
||||
{
|
||||
@@ -169,9 +150,9 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
|
||||
p->thread.io_bitmap_ptr = NULL;
|
||||
|
||||
savesegment(gs, p->thread.gsindex);
|
||||
p->thread.gs = p->thread.gsindex ? 0 : me->thread.gs;
|
||||
p->thread.gsbase = p->thread.gsindex ? 0 : me->thread.gsbase;
|
||||
savesegment(fs, p->thread.fsindex);
|
||||
p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs;
|
||||
p->thread.fsbase = p->thread.fsindex ? 0 : me->thread.fsbase;
|
||||
savesegment(es, p->thread.es);
|
||||
savesegment(ds, p->thread.ds);
|
||||
memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
|
||||
@@ -210,7 +191,7 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
|
||||
*/
|
||||
if (clone_flags & CLONE_SETTLS) {
|
||||
#ifdef CONFIG_IA32_EMULATION
|
||||
if (is_ia32_task())
|
||||
if (in_ia32_syscall())
|
||||
err = do_set_thread_area(p, -1,
|
||||
(struct user_desc __user *)tls, 0);
|
||||
else
|
||||
@@ -282,7 +263,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
|
||||
struct fpu *next_fpu = &next->fpu;
|
||||
int cpu = smp_processor_id();
|
||||
struct tss_struct *tss = &per_cpu(cpu_tss, cpu);
|
||||
unsigned fsindex, gsindex;
|
||||
unsigned prev_fsindex, prev_gsindex;
|
||||
fpu_switch_t fpu_switch;
|
||||
|
||||
fpu_switch = switch_fpu_prepare(prev_fpu, next_fpu, cpu);
|
||||
@@ -292,8 +273,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
|
||||
*
|
||||
* (e.g. xen_load_tls())
|
||||
*/
|
||||
savesegment(fs, fsindex);
|
||||
savesegment(gs, gsindex);
|
||||
savesegment(fs, prev_fsindex);
|
||||
savesegment(gs, prev_gsindex);
|
||||
|
||||
/*
|
||||
* Load TLS before restoring any segments so that segment loads
|
||||
@@ -336,66 +317,104 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
|
||||
* Switch FS and GS.
|
||||
*
|
||||
* These are even more complicated than DS and ES: they have
|
||||
* 64-bit bases are that controlled by arch_prctl. Those bases
|
||||
* only differ from the values in the GDT or LDT if the selector
|
||||
* is 0.
|
||||
* 64-bit bases are that controlled by arch_prctl. The bases
|
||||
* don't necessarily match the selectors, as user code can do
|
||||
* any number of things to cause them to be inconsistent.
|
||||
*
|
||||
* Loading the segment register resets the hidden base part of
|
||||
* the register to 0 or the value from the GDT / LDT. If the
|
||||
* next base address zero, writing 0 to the segment register is
|
||||
* much faster than using wrmsr to explicitly zero the base.
|
||||
* We don't promise to preserve the bases if the selectors are
|
||||
* nonzero. We also don't promise to preserve the base if the
|
||||
* selector is zero and the base doesn't match whatever was
|
||||
* most recently passed to ARCH_SET_FS/GS. (If/when the
|
||||
* FSGSBASE instructions are enabled, we'll need to offer
|
||||
* stronger guarantees.)
|
||||
*
|
||||
* The thread_struct.fs and thread_struct.gs values are 0
|
||||
* if the fs and gs bases respectively are not overridden
|
||||
* from the values implied by fsindex and gsindex. They
|
||||
* are nonzero, and store the nonzero base addresses, if
|
||||
* the bases are overridden.
|
||||
*
|
||||
* (fs != 0 && fsindex != 0) || (gs != 0 && gsindex != 0) should
|
||||
* be impossible.
|
||||
*
|
||||
* Therefore we need to reload the segment registers if either
|
||||
* the old or new selector is nonzero, and we need to override
|
||||
* the base address if next thread expects it to be overridden.
|
||||
*
|
||||
* This code is unnecessarily slow in the case where the old and
|
||||
* new indexes are zero and the new base is nonzero -- it will
|
||||
* unnecessarily write 0 to the selector before writing the new
|
||||
* base address.
|
||||
*
|
||||
* Note: This all depends on arch_prctl being the only way that
|
||||
* user code can override the segment base. Once wrfsbase and
|
||||
* wrgsbase are enabled, most of this code will need to change.
|
||||
* As an invariant,
|
||||
* (fsbase != 0 && fsindex != 0) || (gsbase != 0 && gsindex != 0) is
|
||||
* impossible.
|
||||
*/
|
||||
if (unlikely(fsindex | next->fsindex | prev->fs)) {
|
||||
if (next->fsindex) {
|
||||
/* Loading a nonzero value into FS sets the index and base. */
|
||||
loadsegment(fs, next->fsindex);
|
||||
|
||||
/*
|
||||
* If user code wrote a nonzero value to FS, then it also
|
||||
* cleared the overridden base address.
|
||||
*
|
||||
* XXX: if user code wrote 0 to FS and cleared the base
|
||||
* address itself, we won't notice and we'll incorrectly
|
||||
* restore the prior base address next time we reschdule
|
||||
* the process.
|
||||
*/
|
||||
if (fsindex)
|
||||
prev->fs = 0;
|
||||
} else {
|
||||
if (next->fsbase) {
|
||||
/* Next index is zero but next base is nonzero. */
|
||||
if (prev_fsindex)
|
||||
loadsegment(fs, 0);
|
||||
wrmsrl(MSR_FS_BASE, next->fsbase);
|
||||
} else {
|
||||
/* Next base and index are both zero. */
|
||||
if (static_cpu_has_bug(X86_BUG_NULL_SEG)) {
|
||||
/*
|
||||
* We don't know the previous base and can't
|
||||
* find out without RDMSR. Forcibly clear it.
|
||||
*/
|
||||
loadsegment(fs, __USER_DS);
|
||||
loadsegment(fs, 0);
|
||||
} else {
|
||||
/*
|
||||
* If the previous index is zero and ARCH_SET_FS
|
||||
* didn't change the base, then the base is
|
||||
* also zero and we don't need to do anything.
|
||||
*/
|
||||
if (prev->fsbase || prev_fsindex)
|
||||
loadsegment(fs, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (next->fs)
|
||||
wrmsrl(MSR_FS_BASE, next->fs);
|
||||
prev->fsindex = fsindex;
|
||||
/*
|
||||
* Save the old state and preserve the invariant.
|
||||
* NB: if prev_fsindex == 0, then we can't reliably learn the base
|
||||
* without RDMSR because Intel user code can zero it without telling
|
||||
* us and AMD user code can program any 32-bit value without telling
|
||||
* us.
|
||||
*/
|
||||
if (prev_fsindex)
|
||||
prev->fsbase = 0;
|
||||
prev->fsindex = prev_fsindex;
|
||||
|
||||
if (unlikely(gsindex | next->gsindex | prev->gs)) {
|
||||
if (next->gsindex) {
|
||||
/* Loading a nonzero value into GS sets the index and base. */
|
||||
load_gs_index(next->gsindex);
|
||||
|
||||
/* This works (and fails) the same way as fsindex above. */
|
||||
if (gsindex)
|
||||
prev->gs = 0;
|
||||
} else {
|
||||
if (next->gsbase) {
|
||||
/* Next index is zero but next base is nonzero. */
|
||||
if (prev_gsindex)
|
||||
load_gs_index(0);
|
||||
wrmsrl(MSR_KERNEL_GS_BASE, next->gsbase);
|
||||
} else {
|
||||
/* Next base and index are both zero. */
|
||||
if (static_cpu_has_bug(X86_BUG_NULL_SEG)) {
|
||||
/*
|
||||
* We don't know the previous base and can't
|
||||
* find out without RDMSR. Forcibly clear it.
|
||||
*
|
||||
* This contains a pointless SWAPGS pair.
|
||||
* Fixing it would involve an explicit check
|
||||
* for Xen or a new pvop.
|
||||
*/
|
||||
load_gs_index(__USER_DS);
|
||||
load_gs_index(0);
|
||||
} else {
|
||||
/*
|
||||
* If the previous index is zero and ARCH_SET_GS
|
||||
* didn't change the base, then the base is
|
||||
* also zero and we don't need to do anything.
|
||||
*/
|
||||
if (prev->gsbase || prev_gsindex)
|
||||
load_gs_index(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (next->gs)
|
||||
wrmsrl(MSR_KERNEL_GS_BASE, next->gs);
|
||||
prev->gsindex = gsindex;
|
||||
/*
|
||||
* Save the old state and preserve the invariant.
|
||||
* NB: if prev_gsindex == 0, then we can't reliably learn the base
|
||||
* without RDMSR because Intel user code can zero it without telling
|
||||
* us and AMD user code can program any 32-bit value without telling
|
||||
* us.
|
||||
*/
|
||||
if (prev_gsindex)
|
||||
prev->gsbase = 0;
|
||||
prev->gsindex = prev_gsindex;
|
||||
|
||||
switch_fpu_finish(next_fpu, fpu_switch);
|
||||
|
||||
@@ -516,23 +535,11 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
|
||||
if (addr >= TASK_SIZE_OF(task))
|
||||
return -EPERM;
|
||||
cpu = get_cpu();
|
||||
/* handle small bases via the GDT because that's faster to
|
||||
switch. */
|
||||
if (addr <= 0xffffffff) {
|
||||
set_32bit_tls(task, GS_TLS, addr);
|
||||
if (doit) {
|
||||
load_TLS(&task->thread, cpu);
|
||||
load_gs_index(GS_TLS_SEL);
|
||||
}
|
||||
task->thread.gsindex = GS_TLS_SEL;
|
||||
task->thread.gs = 0;
|
||||
} else {
|
||||
task->thread.gsindex = 0;
|
||||
task->thread.gs = addr;
|
||||
if (doit) {
|
||||
load_gs_index(0);
|
||||
ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, addr);
|
||||
}
|
||||
task->thread.gsindex = 0;
|
||||
task->thread.gsbase = addr;
|
||||
if (doit) {
|
||||
load_gs_index(0);
|
||||
ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, addr);
|
||||
}
|
||||
put_cpu();
|
||||
break;
|
||||
@@ -542,52 +549,30 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
|
||||
if (addr >= TASK_SIZE_OF(task))
|
||||
return -EPERM;
|
||||
cpu = get_cpu();
|
||||
/* handle small bases via the GDT because that's faster to
|
||||
switch. */
|
||||
if (addr <= 0xffffffff) {
|
||||
set_32bit_tls(task, FS_TLS, addr);
|
||||
if (doit) {
|
||||
load_TLS(&task->thread, cpu);
|
||||
loadsegment(fs, FS_TLS_SEL);
|
||||
}
|
||||
task->thread.fsindex = FS_TLS_SEL;
|
||||
task->thread.fs = 0;
|
||||
} else {
|
||||
task->thread.fsindex = 0;
|
||||
task->thread.fs = addr;
|
||||
if (doit) {
|
||||
/* set the selector to 0 to not confuse
|
||||
__switch_to */
|
||||
loadsegment(fs, 0);
|
||||
ret = wrmsrl_safe(MSR_FS_BASE, addr);
|
||||
}
|
||||
task->thread.fsindex = 0;
|
||||
task->thread.fsbase = addr;
|
||||
if (doit) {
|
||||
/* set the selector to 0 to not confuse __switch_to */
|
||||
loadsegment(fs, 0);
|
||||
ret = wrmsrl_safe(MSR_FS_BASE, addr);
|
||||
}
|
||||
put_cpu();
|
||||
break;
|
||||
case ARCH_GET_FS: {
|
||||
unsigned long base;
|
||||
if (task->thread.fsindex == FS_TLS_SEL)
|
||||
base = read_32bit_tls(task, FS_TLS);
|
||||
else if (doit)
|
||||
if (doit)
|
||||
rdmsrl(MSR_FS_BASE, base);
|
||||
else
|
||||
base = task->thread.fs;
|
||||
base = task->thread.fsbase;
|
||||
ret = put_user(base, (unsigned long __user *)addr);
|
||||
break;
|
||||
}
|
||||
case ARCH_GET_GS: {
|
||||
unsigned long base;
|
||||
unsigned gsindex;
|
||||
if (task->thread.gsindex == GS_TLS_SEL)
|
||||
base = read_32bit_tls(task, GS_TLS);
|
||||
else if (doit) {
|
||||
savesegment(gs, gsindex);
|
||||
if (gsindex)
|
||||
rdmsrl(MSR_KERNEL_GS_BASE, base);
|
||||
else
|
||||
base = task->thread.gs;
|
||||
} else
|
||||
base = task->thread.gs;
|
||||
if (doit)
|
||||
rdmsrl(MSR_KERNEL_GS_BASE, base);
|
||||
else
|
||||
base = task->thread.gsbase;
|
||||
ret = put_user(base, (unsigned long __user *)addr);
|
||||
break;
|
||||
}
|
||||
|
@@ -303,29 +303,11 @@ static int set_segment_reg(struct task_struct *task,
|
||||
|
||||
switch (offset) {
|
||||
case offsetof(struct user_regs_struct,fs):
|
||||
/*
|
||||
* If this is setting fs as for normal 64-bit use but
|
||||
* setting fs_base has implicitly changed it, leave it.
|
||||
*/
|
||||
if ((value == FS_TLS_SEL && task->thread.fsindex == 0 &&
|
||||
task->thread.fs != 0) ||
|
||||
(value == 0 && task->thread.fsindex == FS_TLS_SEL &&
|
||||
task->thread.fs == 0))
|
||||
break;
|
||||
task->thread.fsindex = value;
|
||||
if (task == current)
|
||||
loadsegment(fs, task->thread.fsindex);
|
||||
break;
|
||||
case offsetof(struct user_regs_struct,gs):
|
||||
/*
|
||||
* If this is setting gs as for normal 64-bit use but
|
||||
* setting gs_base has implicitly changed it, leave it.
|
||||
*/
|
||||
if ((value == GS_TLS_SEL && task->thread.gsindex == 0 &&
|
||||
task->thread.gs != 0) ||
|
||||
(value == 0 && task->thread.gsindex == GS_TLS_SEL &&
|
||||
task->thread.gs == 0))
|
||||
break;
|
||||
task->thread.gsindex = value;
|
||||
if (task == current)
|
||||
load_gs_index(task->thread.gsindex);
|
||||
@@ -417,7 +399,7 @@ static int putreg(struct task_struct *child,
|
||||
* to set either thread.fs or thread.fsindex and the
|
||||
* corresponding GDT slot.
|
||||
*/
|
||||
if (child->thread.fs != value)
|
||||
if (child->thread.fsbase != value)
|
||||
return do_arch_prctl(child, ARCH_SET_FS, value);
|
||||
return 0;
|
||||
case offsetof(struct user_regs_struct,gs_base):
|
||||
@@ -426,7 +408,7 @@ static int putreg(struct task_struct *child,
|
||||
*/
|
||||
if (value >= TASK_SIZE_OF(child))
|
||||
return -EIO;
|
||||
if (child->thread.gs != value)
|
||||
if (child->thread.gsbase != value)
|
||||
return do_arch_prctl(child, ARCH_SET_GS, value);
|
||||
return 0;
|
||||
#endif
|
||||
@@ -453,31 +435,17 @@ static unsigned long getreg(struct task_struct *task, unsigned long offset)
|
||||
#ifdef CONFIG_X86_64
|
||||
case offsetof(struct user_regs_struct, fs_base): {
|
||||
/*
|
||||
* do_arch_prctl may have used a GDT slot instead of
|
||||
* the MSR. To userland, it appears the same either
|
||||
* way, except the %fs segment selector might not be 0.
|
||||
* XXX: This will not behave as expected if called on
|
||||
* current or if fsindex != 0.
|
||||
*/
|
||||
unsigned int seg = task->thread.fsindex;
|
||||
if (task->thread.fs != 0)
|
||||
return task->thread.fs;
|
||||
if (task == current)
|
||||
asm("movl %%fs,%0" : "=r" (seg));
|
||||
if (seg != FS_TLS_SEL)
|
||||
return 0;
|
||||
return get_desc_base(&task->thread.tls_array[FS_TLS]);
|
||||
return task->thread.fsbase;
|
||||
}
|
||||
case offsetof(struct user_regs_struct, gs_base): {
|
||||
/*
|
||||
* Exactly the same here as the %fs handling above.
|
||||
* XXX: This will not behave as expected if called on
|
||||
* current or if fsindex != 0.
|
||||
*/
|
||||
unsigned int seg = task->thread.gsindex;
|
||||
if (task->thread.gs != 0)
|
||||
return task->thread.gs;
|
||||
if (task == current)
|
||||
asm("movl %%gs,%0" : "=r" (seg));
|
||||
if (seg != GS_TLS_SEL)
|
||||
return 0;
|
||||
return get_desc_base(&task->thread.tls_array[GS_TLS]);
|
||||
return task->thread.gsbase;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1266,7 +1234,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
||||
compat_ulong_t caddr, compat_ulong_t cdata)
|
||||
{
|
||||
#ifdef CONFIG_X86_X32_ABI
|
||||
if (!is_ia32_task())
|
||||
if (!in_ia32_syscall())
|
||||
return x32_arch_ptrace(child, request, caddr, cdata);
|
||||
#endif
|
||||
#ifdef CONFIG_IA32_EMULATION
|
||||
|
@@ -535,6 +535,15 @@ static void native_machine_emergency_restart(void)
|
||||
mode = reboot_mode == REBOOT_WARM ? 0x1234 : 0;
|
||||
*((unsigned short *)__va(0x472)) = mode;
|
||||
|
||||
/*
|
||||
* If an EFI capsule has been registered with the firmware then
|
||||
* override the reboot= parameter.
|
||||
*/
|
||||
if (efi_capsule_pending(NULL)) {
|
||||
pr_info("EFI capsule is pending, forcing EFI reboot.\n");
|
||||
reboot_type = BOOT_EFI;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
/* Could also try the reset bit in the Hammer NB */
|
||||
switch (reboot_type) {
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include <asm/time.h>
|
||||
#include <asm/intel-mid.h>
|
||||
#include <asm/rtc.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
/*
|
||||
@@ -185,22 +186,7 @@ static __init int add_rtc_cmos(void)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (of_have_populated_dt())
|
||||
return 0;
|
||||
|
||||
/* Intel MID platforms don't have ioport rtc */
|
||||
if (intel_mid_identify_cpu())
|
||||
return -ENODEV;
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) {
|
||||
/* This warning can likely go away again in a year or two. */
|
||||
pr_info("ACPI: not registering RTC platform device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (paravirt_enabled() && !paravirt_has(RTC))
|
||||
if (!x86_platform.legacy.rtc)
|
||||
return -ENODEV;
|
||||
|
||||
platform_device_register(&rtc_device);
|
||||
|
@@ -248,18 +248,17 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
|
||||
if (config_enabled(CONFIG_X86_64))
|
||||
sp -= 128;
|
||||
|
||||
if (!onsigstack) {
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
if (ka->sa.sa_flags & SA_ONSTACK) {
|
||||
if (current->sas_ss_size)
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
} else if (config_enabled(CONFIG_X86_32) &&
|
||||
(regs->ss & 0xffff) != __USER_DS &&
|
||||
!(ka->sa.sa_flags & SA_RESTORER) &&
|
||||
ka->sa.sa_restorer) {
|
||||
/* This is the legacy signal stack switching. */
|
||||
sp = (unsigned long) ka->sa.sa_restorer;
|
||||
}
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
if (ka->sa.sa_flags & SA_ONSTACK) {
|
||||
if (sas_ss_flags(sp) == 0)
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
} else if (config_enabled(CONFIG_X86_32) &&
|
||||
!onsigstack &&
|
||||
(regs->ss & 0xffff) != __USER_DS &&
|
||||
!(ka->sa.sa_flags & SA_RESTORER) &&
|
||||
ka->sa.sa_restorer) {
|
||||
/* This is the legacy signal stack switching. */
|
||||
sp = (unsigned long) ka->sa.sa_restorer;
|
||||
}
|
||||
|
||||
if (fpu->fpstate_active) {
|
||||
@@ -391,7 +390,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
|
||||
put_user_ex(&frame->uc, &frame->puc);
|
||||
|
||||
/* Create the ucontext. */
|
||||
if (cpu_has_xsave)
|
||||
if (boot_cpu_has(X86_FEATURE_XSAVE))
|
||||
put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
|
||||
else
|
||||
put_user_ex(0, &frame->uc.uc_flags);
|
||||
@@ -442,7 +441,7 @@ static unsigned long frame_uc_flags(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (cpu_has_xsave)
|
||||
if (boot_cpu_has(X86_FEATURE_XSAVE))
|
||||
flags = UC_FP_XSTATE | UC_SIGCONTEXT_SS;
|
||||
else
|
||||
flags = UC_SIGCONTEXT_SS;
|
||||
@@ -762,7 +761,7 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||
static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs)
|
||||
{
|
||||
#ifdef CONFIG_X86_64
|
||||
if (is_ia32_task())
|
||||
if (in_ia32_syscall())
|
||||
return __NR_ia32_restart_syscall;
|
||||
#endif
|
||||
#ifdef CONFIG_X86_X32_ABI
|
||||
|
@@ -1236,7 +1236,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
|
||||
* If we couldn't find a local APIC, then get out of here now!
|
||||
*/
|
||||
if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) &&
|
||||
!cpu_has_apic) {
|
||||
!boot_cpu_has(X86_FEATURE_APIC)) {
|
||||
if (!disable_apic) {
|
||||
pr_err("BIOS bug, local APIC #%d not detected!...\n",
|
||||
boot_cpu_physical_apicid);
|
||||
|
@@ -68,6 +68,21 @@ struct efifb_dmi_info efifb_dmi_list[] = {
|
||||
[M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE }
|
||||
};
|
||||
|
||||
void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < M_UNKNOWN; i++) {
|
||||
if (efifb_dmi_list[i].base != 0 &&
|
||||
!strcmp(opt, efifb_dmi_list[i].optname)) {
|
||||
si->lfb_base = efifb_dmi_list[i].base;
|
||||
si->lfb_linelength = efifb_dmi_list[i].stride;
|
||||
si->lfb_width = efifb_dmi_list[i].width;
|
||||
si->lfb_height = efifb_dmi_list[i].height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define choose_value(dmivalue, fwvalue, field, flags) ({ \
|
||||
typeof(fwvalue) _ret_ = fwvalue; \
|
||||
if ((flags) & (field)) \
|
||||
|
@@ -74,12 +74,6 @@ void __init tboot_probe(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/* only a natively booted kernel should be using TXT */
|
||||
if (paravirt_enabled()) {
|
||||
pr_warning("non-0 tboot_addr but pv_ops is enabled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Map and check for tboot UUID. */
|
||||
set_fixmap(FIX_TBOOT_BASE, boot_params.tboot_addr);
|
||||
tboot = (struct tboot *)fix_to_virt(FIX_TBOOT_BASE);
|
||||
|
@@ -40,7 +40,7 @@
|
||||
static inline void flush_tce(void* tceaddr)
|
||||
{
|
||||
/* a single tce can't cross a cache line */
|
||||
if (cpu_has_clflush)
|
||||
if (boot_cpu_has(X86_FEATURE_CLFLUSH))
|
||||
clflush(tceaddr);
|
||||
else
|
||||
wbinvd();
|
||||
|
@@ -114,6 +114,7 @@ int do_set_thread_area(struct task_struct *p, int idx,
|
||||
int can_allocate)
|
||||
{
|
||||
struct user_desc info;
|
||||
unsigned short __maybe_unused sel, modified_sel;
|
||||
|
||||
if (copy_from_user(&info, u_info, sizeof(info)))
|
||||
return -EFAULT;
|
||||
@@ -141,6 +142,47 @@ int do_set_thread_area(struct task_struct *p, int idx,
|
||||
|
||||
set_tls_desc(p, idx, &info, 1);
|
||||
|
||||
/*
|
||||
* If DS, ES, FS, or GS points to the modified segment, forcibly
|
||||
* refresh it. Only needed on x86_64 because x86_32 reloads them
|
||||
* on return to user mode.
|
||||
*/
|
||||
modified_sel = (idx << 3) | 3;
|
||||
|
||||
if (p == current) {
|
||||
#ifdef CONFIG_X86_64
|
||||
savesegment(ds, sel);
|
||||
if (sel == modified_sel)
|
||||
loadsegment(ds, sel);
|
||||
|
||||
savesegment(es, sel);
|
||||
if (sel == modified_sel)
|
||||
loadsegment(es, sel);
|
||||
|
||||
savesegment(fs, sel);
|
||||
if (sel == modified_sel)
|
||||
loadsegment(fs, sel);
|
||||
|
||||
savesegment(gs, sel);
|
||||
if (sel == modified_sel)
|
||||
load_gs_index(sel);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_32_LAZY_GS
|
||||
savesegment(gs, sel);
|
||||
if (sel == modified_sel)
|
||||
loadsegment(gs, sel);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef CONFIG_X86_64
|
||||
if (p->thread.fsindex == modified_sel)
|
||||
p->thread.fsbase = info.base_addr;
|
||||
|
||||
if (p->thread.gsindex == modified_sel)
|
||||
p->thread.gsbase = info.base_addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -51,6 +51,7 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/debugreg.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <asm/text-patching.h>
|
||||
#include <asm/ftrace.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/desc.h>
|
||||
|
@@ -36,7 +36,7 @@ static int __read_mostly tsc_unstable;
|
||||
|
||||
/* native_sched_clock() is called before tsc_init(), so
|
||||
we must start with the TSC soft disabled to prevent
|
||||
erroneous rdtsc usage on !cpu_has_tsc processors */
|
||||
erroneous rdtsc usage on !boot_cpu_has(X86_FEATURE_TSC) processors */
|
||||
static int __read_mostly tsc_disabled = -1;
|
||||
|
||||
static DEFINE_STATIC_KEY_FALSE(__use_tsc);
|
||||
@@ -834,15 +834,15 @@ int recalibrate_cpu_khz(void)
|
||||
#ifndef CONFIG_SMP
|
||||
unsigned long cpu_khz_old = cpu_khz;
|
||||
|
||||
if (cpu_has_tsc) {
|
||||
tsc_khz = x86_platform.calibrate_tsc();
|
||||
cpu_khz = tsc_khz;
|
||||
cpu_data(0).loops_per_jiffy =
|
||||
cpufreq_scale(cpu_data(0).loops_per_jiffy,
|
||||
cpu_khz_old, cpu_khz);
|
||||
return 0;
|
||||
} else
|
||||
if (!boot_cpu_has(X86_FEATURE_TSC))
|
||||
return -ENODEV;
|
||||
|
||||
tsc_khz = x86_platform.calibrate_tsc();
|
||||
cpu_khz = tsc_khz;
|
||||
cpu_data(0).loops_per_jiffy = cpufreq_scale(cpu_data(0).loops_per_jiffy,
|
||||
cpu_khz_old, cpu_khz);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -ENODEV;
|
||||
#endif
|
||||
@@ -922,9 +922,6 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
|
||||
struct cpufreq_freqs *freq = data;
|
||||
unsigned long *lpj;
|
||||
|
||||
if (cpu_has(&cpu_data(freq->cpu), X86_FEATURE_CONSTANT_TSC))
|
||||
return 0;
|
||||
|
||||
lpj = &boot_cpu_data.loops_per_jiffy;
|
||||
#ifdef CONFIG_SMP
|
||||
if (!(freq->flags & CPUFREQ_CONST_LOOPS))
|
||||
@@ -954,9 +951,9 @@ static struct notifier_block time_cpufreq_notifier_block = {
|
||||
.notifier_call = time_cpufreq_notifier
|
||||
};
|
||||
|
||||
static int __init cpufreq_tsc(void)
|
||||
static int __init cpufreq_register_tsc_scaling(void)
|
||||
{
|
||||
if (!cpu_has_tsc)
|
||||
if (!boot_cpu_has(X86_FEATURE_TSC))
|
||||
return 0;
|
||||
if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
|
||||
return 0;
|
||||
@@ -965,7 +962,7 @@ static int __init cpufreq_tsc(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
core_initcall(cpufreq_tsc);
|
||||
core_initcall(cpufreq_register_tsc_scaling);
|
||||
|
||||
#endif /* CONFIG_CPU_FREQ */
|
||||
|
||||
@@ -1081,7 +1078,7 @@ static void __init check_system_tsc_reliable(void)
|
||||
*/
|
||||
int unsynchronized_tsc(void)
|
||||
{
|
||||
if (!cpu_has_tsc || tsc_unstable)
|
||||
if (!boot_cpu_has(X86_FEATURE_TSC) || tsc_unstable)
|
||||
return 1;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
@@ -1205,7 +1202,7 @@ out:
|
||||
|
||||
static int __init init_tsc_clocksource(void)
|
||||
{
|
||||
if (!cpu_has_tsc || tsc_disabled > 0 || !tsc_khz)
|
||||
if (!boot_cpu_has(X86_FEATURE_TSC) || tsc_disabled > 0 || !tsc_khz)
|
||||
return 0;
|
||||
|
||||
if (tsc_clocksource_reliable)
|
||||
@@ -1242,7 +1239,7 @@ void __init tsc_init(void)
|
||||
u64 lpj;
|
||||
int cpu;
|
||||
|
||||
if (!cpu_has_tsc) {
|
||||
if (!boot_cpu_has(X86_FEATURE_TSC)) {
|
||||
setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
|
||||
return;
|
||||
}
|
||||
|
@@ -516,7 +516,7 @@ struct uprobe_xol_ops {
|
||||
|
||||
static inline int sizeof_long(void)
|
||||
{
|
||||
return is_ia32_task() ? 4 : 8;
|
||||
return in_ia32_syscall() ? 4 : 8;
|
||||
}
|
||||
|
||||
static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
||||
@@ -578,7 +578,7 @@ static void default_abort_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
|
||||
riprel_post_xol(auprobe, regs);
|
||||
}
|
||||
|
||||
static struct uprobe_xol_ops default_xol_ops = {
|
||||
static const struct uprobe_xol_ops default_xol_ops = {
|
||||
.pre_xol = default_pre_xol_op,
|
||||
.post_xol = default_post_xol_op,
|
||||
.abort = default_abort_op,
|
||||
@@ -695,7 +695,7 @@ static void branch_clear_offset(struct arch_uprobe *auprobe, struct insn *insn)
|
||||
0, insn->immediate.nbytes);
|
||||
}
|
||||
|
||||
static struct uprobe_xol_ops branch_xol_ops = {
|
||||
static const struct uprobe_xol_ops branch_xol_ops = {
|
||||
.emulate = branch_emulate_op,
|
||||
.post_xol = branch_post_xol_op,
|
||||
};
|
||||
|
@@ -334,7 +334,7 @@ SECTIONS
|
||||
__brk_limit = .;
|
||||
}
|
||||
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
. = ALIGN(PAGE_SIZE); /* keep VO_INIT_SIZE page aligned */
|
||||
_end = .;
|
||||
|
||||
STABS_DEBUG
|
||||
|
Reference in New Issue
Block a user