VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 29
- -- -EXTRAVERSION = -rc4
- EXTRAVERSION = -rc1
- EXTRAVERSION = -rc3
+ +++++EXTRAVERSION = -rc5
NAME = Erotic Pickled Herring
# *DOCUMENTATION*
# Where to locate arch specific headers
hdr-arch := $(SRCARCH)
+ ifeq ($(ARCH),m68knommu)
+ hdr-arch := m68k
+ endif
+
KCONFIG_CONFIG ?= .config
# SHELL used by kbuild
endif
# Force gcc to behave correct even for buggy distributions
--- - # Arch Makefiles may override this setting
+++ + ifndef CONFIG_CC_STACKPROTECTOR
KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
+++ + endif
ifdef CONFIG_FRAME_POINTER
KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
export MODLIB
- strip-symbols := $(srctree)/scripts/strip-symbols \
- $(wildcard $(srctree)/arch/$(ARCH)/scripts/strip-symbols)
-
#
- # INSTALL_MOD_STRIP, if defined, will cause modules to be stripped while
- # they get installed. If INSTALL_MOD_STRIP is '1', then the default
- # options (see below) will be used. Otherwise, INSTALL_MOD_STRIP will
- # be used as the option(s) to the objcopy command.
+ # INSTALL_MOD_STRIP, if defined, will cause modules to be
+ # stripped after they are installed. If INSTALL_MOD_STRIP is '1', then
+ # the default option --strip-debug will be used. Otherwise,
+ # INSTALL_MOD_STRIP will used as the options to the strip command.
+
ifdef INSTALL_MOD_STRIP
ifeq ($(INSTALL_MOD_STRIP),1)
- mod_strip_cmd = $(OBJCOPY) --strip-debug
- ifeq ($(CONFIG_KALLSYMS_ALL),$(CONFIG_KALLSYMS_STRIP_GENERATED))
- mod_strip_cmd += --wildcard $(addprefix --strip-symbols ,$(strip-symbols))
- endif
+ mod_strip_cmd = $(STRIP) --strip-debug
else
- mod_strip_cmd = $(OBJCOPY) $(INSTALL_MOD_STRIP)
+ mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP)
endif # INSTALL_MOD_STRIP=1
else
- mod_strip_cmd = false
+ mod_strip_cmd = true
endif # INSTALL_MOD_STRIP
export mod_strip_cmd
endif
kallsyms.o := .tmp_kallsyms$(last_kallsyms).o
- kallsyms.h := $(wildcard include/config/kallsyms/*.h) $(wildcard include/config/kallsyms/*/*.h)
define verify_kallsyms
$(Q)$(if $($(quiet)cmd_sysmap), \
# Generate .S file with all kernel symbols
quiet_cmd_kallsyms = KSYM $@
- cmd_kallsyms = { test $* -eq 0 || $(NM) -n $<; } \
- | $(KALLSYMS) $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) >$@
+ cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \
+ $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@
- quiet_cmd_kstrip = STRIP $@
- cmd_kstrip = $(OBJCOPY) --wildcard $(addprefix --strip$(if $(CONFIG_RELOCATABLE),-unneeded)-symbols ,$(filter %/scripts/strip-symbols,$^)) $< $@
-
- $(foreach n,0 1 2 3,.tmp_kallsyms$(n).o): KBUILD_AFLAGS += -Wa,--strip-local-absolute
- $(foreach n,0 1 2 3,.tmp_kallsyms$(n).o): %.o: %.S scripts FORCE
+ .tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
$(call if_changed_dep,as_o_S)
- ifeq ($(CONFIG_KALLSYMS_STRIP_GENERATED),y)
- strip-ext := .stripped
- endif
-
- .tmp_kallsyms%.S: .tmp_vmlinux%$(strip-ext) $(KALLSYMS) $(kallsyms.h)
+ .tmp_kallsyms%.S: .tmp_vmlinux% $(KALLSYMS)
$(call cmd,kallsyms)
- # make -jN seems to have problems with intermediate files, see bug #3330.
- .SECONDARY: $(foreach n,1 2 3,.tmp_vmlinux$(n).stripped)
- .tmp_vmlinux%.stripped: .tmp_vmlinux% $(strip-symbols) $(kallsyms.h)
- $(call cmd,kstrip)
-
- ifneq ($(CONFIG_DEBUG_INFO),y)
- .tmp_vmlinux%: LDFLAGS_vmlinux += -S
- endif
# .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version
- .tmp_vmlinux%: $(vmlinux-lds) $(vmlinux-all) FORCE
- $(if $(filter 1,$*),$(call if_changed_rule,ksym_ld),$(call if_changed,vmlinux__))
+ .tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE
+ $(call if_changed_rule,ksym_ld)
- .tmp_vmlinux0$(strip-ext):
- $(Q)echo "placeholder" >$@
+ .tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE
+ $(call if_changed,vmlinux__)
- .tmp_vmlinux1: .tmp_kallsyms0.o
- .tmp_vmlinux2: .tmp_kallsyms1.o
- .tmp_vmlinux3: .tmp_kallsyms2.o
+ .tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.o FORCE
+ $(call if_changed,vmlinux__)
# Needs to visit scripts/ before $(KALLSYMS) can be used.
$(KALLSYMS): scripts ;
/*
* Local APIC handling, local APIC timers
*
- - - * (c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
+ + + * (c) 1999, 2000, 2009 Ingo Molnar <mingo@redhat.com>
*
* Fixes
* Maciej W. Rozycki : Bits for genuine 82489DX APICs;
* Mikael Pettersson : PM converted to driver model.
*/
- - - #include <linux/init.h>
- - -
- - - #include <linux/mm.h>
- - - #include <linux/delay.h>
- - - #include <linux/bootmem.h>
- - - #include <linux/interrupt.h>
- - - #include <linux/mc146818rtc.h>
#include <linux/kernel_stat.h>
- - - #include <linux/sysdev.h>
- - - #include <linux/ioport.h>
- - - #include <linux/cpu.h>
- - - #include <linux/clockchips.h>
+ + + #include <linux/mc146818rtc.h>
#include <linux/acpi_pmtmr.h>
+ + + #include <linux/clockchips.h>
+ + + #include <linux/interrupt.h>
+ + + #include <linux/bootmem.h>
+ + + #include <linux/ftrace.h>
+ + + #include <linux/ioport.h>
#include <linux/module.h>
- - - #include <linux/dmi.h>
+ + + #include <linux/sysdev.h>
+ + + #include <linux/delay.h>
+ + + #include <linux/timex.h>
#include <linux/dmar.h>
- - - #include <linux/ftrace.h>
- - - #include <linux/smp.h>
+ + + #include <linux/init.h>
+ + + #include <linux/cpu.h>
+ + + #include <linux/dmi.h>
#include <linux/nmi.h>
- - - #include <linux/timex.h>
+ + + #include <linux/smp.h>
+ + + #include <linux/mm.h>
- - - #include <asm/atomic.h>
- - - #include <asm/mtrr.h>
- - - #include <asm/mpspec.h>
- - - #include <asm/desc.h>
#include <asm/arch_hooks.h>
- - - #include <asm/hpet.h>
#include <asm/pgalloc.h>
+ + + #include <asm/genapic.h>
+ + + #include <asm/atomic.h>
+ + + #include <asm/mpspec.h>
#include <asm/i8253.h>
- - - #include <asm/idle.h>
+ + + #include <asm/i8259.h>
#include <asm/proto.h>
#include <asm/apic.h>
- - - #include <asm/i8259.h>
+ + + #include <asm/desc.h>
+ + + #include <asm/hpet.h>
+ + + #include <asm/idle.h>
+ + + #include <asm/mtrr.h>
#include <asm/smp.h>
- - - #include <mach_apic.h>
- - - #include <mach_apicdef.h>
- - - #include <mach_ipi.h>
+ + + unsigned int num_processors;
+ + +
+ + + unsigned disabled_cpus __cpuinitdata;
+ + +
+ + + /* Processor that is doing the boot up */
+ + + unsigned int boot_cpu_physical_apicid = -1U;
/*
- - - * Sanity check
+ + + * The highest APIC ID seen during enumeration.
+ + + *
+ + + * This determines the messaging protocol we can use: if all APIC IDs
+ + + * are in the 0 ... 7 range, then we can use logical addressing which
+ + + * has some performance advantages (better broadcasting).
+ + + *
+ + + * If there's an APIC ID above 8, we use physical addressing.
*/
- - - #if ((SPURIOUS_APIC_VECTOR & 0x0F) != 0x0F)
- - - # error SPURIOUS_APIC_VECTOR definition error
- - - #endif
+ + + unsigned int max_physical_apicid;
+ + +
+ + + /*
+ + + * Bitmask of physically existing CPUs:
+ + + */
+ + + physid_mask_t phys_cpu_present_map;
+ + +
+ + + /*
+ + + * Map cpu index to physical APIC ID
+ + + */
+ + + DEFINE_EARLY_PER_CPU(u16, x86_cpu_to_apicid, BAD_APICID);
+ + + DEFINE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid, BAD_APICID);
+ + + EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_apicid);
+ + + EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
#ifdef CONFIG_X86_32
/*
static void lapic_timer_broadcast(const struct cpumask *mask)
{
#ifdef CONFIG_SMP
- - - send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
+ + + apic->send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
#endif
}
}
}
--- - static int __init calibrate_by_pmtimer(long deltapm, long *delta)
+++ + static int __init
+++ + calibrate_by_pmtimer(long deltapm, long *delta, long *deltatsc)
{
const long pm_100ms = PMTMR_TICKS_PER_SEC / 10;
const long pm_thresh = pm_100ms / 100;
return -1;
#endif
--- - apic_printk(APIC_VERBOSE, "... PM timer delta = %ld\n", deltapm);
+++ + apic_printk(APIC_VERBOSE, "... PM-Timer delta = %ld\n", deltapm);
/* Check, if the PM timer is available */
if (!deltapm)
if (deltapm > (pm_100ms - pm_thresh) &&
deltapm < (pm_100ms + pm_thresh)) {
--- - apic_printk(APIC_VERBOSE, "... PM timer result ok\n");
--- - } else {
--- - res = (((u64)deltapm) * mult) >> 22;
--- - do_div(res, 1000000);
--- - pr_warning("APIC calibration not consistent "
--- - "with PM Timer: %ldms instead of 100ms\n",
--- - (long)res);
--- - /* Correct the lapic counter value */
--- - res = (((u64)(*delta)) * pm_100ms);
+++ + apic_printk(APIC_VERBOSE, "... PM-Timer result ok\n");
+++ + return 0;
+++ + }
+++ +
+++ + res = (((u64)deltapm) * mult) >> 22;
+++ + do_div(res, 1000000);
+++ + pr_warning("APIC calibration not consistent "
+++ + "with PM-Timer: %ldms instead of 100ms\n",(long)res);
+++ +
+++ + /* Correct the lapic counter value */
+++ + res = (((u64)(*delta)) * pm_100ms);
+++ + do_div(res, deltapm);
+++ + pr_info("APIC delta adjusted to PM-Timer: "
+++ + "%lu (%ld)\n", (unsigned long)res, *delta);
+++ + *delta = (long)res;
+++ +
+++ + /* Correct the tsc counter value */
+++ + if (cpu_has_tsc) {
+++ + res = (((u64)(*deltatsc)) * pm_100ms);
do_div(res, deltapm);
--- - pr_info("APIC delta adjusted to PM-Timer: "
--- - "%lu (%ld)\n", (unsigned long)res, *delta);
--- - *delta = (long)res;
+++ + apic_printk(APIC_VERBOSE, "TSC delta adjusted to "
+++ + "PM-Timer: %lu (%ld) \n",
+++ + (unsigned long)res, *deltatsc);
+++ + *deltatsc = (long)res;
}
return 0;
struct clock_event_device *levt = &__get_cpu_var(lapic_events);
void (*real_handler)(struct clock_event_device *dev);
unsigned long deltaj;
--- - long delta;
+++ + long delta, deltatsc;
int pm_referenced = 0;
local_irq_disable();
delta = lapic_cal_t1 - lapic_cal_t2;
apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta);
+++ + deltatsc = (long)(lapic_cal_tsc2 - lapic_cal_tsc1);
+++ +
/* we trust the PM based calibration if possible */
pm_referenced = !calibrate_by_pmtimer(lapic_cal_pm2 - lapic_cal_pm1,
--- - &delta);
+++ + &delta, &deltatsc);
/* Calculate the scaled math multiplication factor */
lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS,
calibration_result);
if (cpu_has_tsc) {
--- - delta = (long)(lapic_cal_tsc2 - lapic_cal_tsc1);
apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
"%ld.%04ld MHz.\n",
--- - (delta / LAPIC_CAL_LOOPS) / (1000000 / HZ),
--- - (delta / LAPIC_CAL_LOOPS) % (1000000 / HZ));
+++ + (deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ),
+++ + (deltatsc / LAPIC_CAL_LOOPS) % (1000000 / HZ));
}
apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
{
unsigned int value;
+ /* APIC hasn't been mapped yet */
+ if (!apic_phys)
+ return;
+
clear_local_APIC();
/*
*/
reg0 = apic_read(APIC_ID);
apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0);
- - - apic_write(APIC_ID, reg0 ^ APIC_ID_MASK);
+ + + apic_write(APIC_ID, reg0 ^ apic->apic_id_mask);
reg1 = apic_read(APIC_ID);
apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1);
apic_write(APIC_ID, reg0);
- - - if (reg1 != (reg0 ^ APIC_ID_MASK))
+ + + if (reg1 != (reg0 ^ apic->apic_id_mask))
return 0;
/*
return;
}
- - - if (esr_disable) {
+ + + if (apic->disable_esr) {
/*
* Something untraceable is creating bad interrupts on
* secondary quads ... for the moment, just leave the
unsigned int value;
int i, j;
+ + + if (disable_apic) {
+ + + arch_disable_smp_support();
+ + + return;
+ + + }
+ + +
#ifdef CONFIG_X86_32
/* Pound the ESR really hard over the head with a big hammer - mbligh */
- - - if (lapic_is_integrated() && esr_disable) {
+ + + if (lapic_is_integrated() && apic->disable_esr) {
apic_write(APIC_ESR, 0);
apic_write(APIC_ESR, 0);
apic_write(APIC_ESR, 0);
* Double-check whether this APIC is really registered.
* This is meaningless in clustered apic mode, so we skip it.
*/
- - - if (!apic_id_registered())
+ + + if (!apic->apic_id_registered())
BUG();
/*
* an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
* document number 292116). So here it goes...
*/
- - - init_apic_ldr();
+ + + apic->init_apic_ldr();
/*
* Set Task Priority to 'accept all'. We never change this
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_AMD:
if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
- (boot_cpu_data.x86 == 15))
+ (boot_cpu_data.x86 >= 15))
break;
goto no_apic;
case X86_VENDOR_INTEL:
int __init APIC_init_uniprocessor(void)
{
- - - #ifdef CONFIG_X86_64
if (disable_apic) {
pr_info("Apic disabled\n");
return -1;
}
+ + + #ifdef CONFIG_X86_64
if (!cpu_has_apic) {
disable_apic = 1;
pr_info("Apic disabled by BIOS\n");
enable_IR_x2apic();
#endif
#ifdef CONFIG_X86_64
- - - setup_apic_routing();
+ + + default_setup_apic_routing();
#endif
verify_local_APIC();
physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map);
setup_local_APIC();
- -----#ifdef CONFIG_X86_64
+ +++++#ifdef CONFIG_X86_IO_APIC
/*
* Now enable IO-APICs, actually call clear_IO_APIC
- ----- * We need clear_IO_APIC before enabling vector on BP
+ +++++ * We need clear_IO_APIC before enabling error vector
*/
if (!skip_ioapic_setup && nr_ioapics)
enable_IO_APIC();
#endif
- -----#ifdef CONFIG_X86_IO_APIC
- ----- if (!smp_found_config || skip_ioapic_setup || !nr_ioapics)
- -----#endif
- ----- localise_nmi_watchdog();
end_local_APIC_setup();
#ifdef CONFIG_X86_IO_APIC
if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
setup_IO_APIC();
- -----# ifdef CONFIG_X86_64
- ----- else
+ +++++ else {
nr_ioapics = 0;
- -----# endif
+ +++++ localise_nmi_watchdog();
+ +++++ }
+ +++++#else
+ +++++ localise_nmi_watchdog();
#endif
+ +++++ setup_boot_clock();
#ifdef CONFIG_X86_64
- ----- setup_boot_APIC_clock();
check_nmi_watchdog();
- -----#else
- ----- setup_boot_clock();
#endif
return 0;
outb(0x01, 0x23);
}
#endif
- - - enable_apic_mode();
+ + + if (apic->enable_apic_mode)
+ + + apic->enable_apic_mode();
}
/**
num_processors++;
cpu = cpumask_next_zero(-1, cpu_present_mask);
+ if (version != apic_version[boot_cpu_physical_apicid])
+ WARN_ONCE(1,
+ "ACPI: apic version mismatch, bootcpu: %x cpu %d: %x\n",
+ apic_version[boot_cpu_physical_apicid], cpu, version);
+
physid_set(apicid, phys_cpu_present_map);
if (apicid == boot_cpu_physical_apicid) {
/*
}
#endif
- - - #if defined(CONFIG_X86_SMP) || defined(CONFIG_X86_64)
- - - /* are we being called early in kernel startup? */
- - - if (early_per_cpu_ptr(x86_cpu_to_apicid)) {
- - - u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid);
- - - u16 *bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
- - -
- - - cpu_to_apicid[cpu] = apicid;
- - - bios_cpu_apicid[cpu] = apicid;
- - - } else {
- - - per_cpu(x86_cpu_to_apicid, cpu) = apicid;
- - - per_cpu(x86_bios_cpu_apicid, cpu) = apicid;
- - - }
+ + + #if defined(CONFIG_SMP) || defined(CONFIG_X86_64)
+ + + early_per_cpu(x86_cpu_to_apicid, cpu) = apicid;
+ + + early_per_cpu(x86_bios_cpu_apicid, cpu) = apicid;
#endif
set_cpu_possible(cpu, true);
set_cpu_present(cpu, true);
}
- - - #ifdef CONFIG_X86_64
int hard_smp_processor_id(void)
{
return read_apic_id();
}
+ + +
+ + + void default_init_apic_ldr(void)
+ + + {
+ + + unsigned long val;
+ + +
+ + + apic_write(APIC_DFR, APIC_DFR_VALUE);
+ + + val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
+ + + val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id());
+ + + apic_write(APIC_LDR, val);
+ + + }
+ + +
+ + + #ifdef CONFIG_X86_32
+ + + int default_apicid_to_node(int logical_apicid)
+ + + {
+ + + #ifdef CONFIG_SMP
+ + + return apicid_2_node[hard_smp_processor_id()];
+ + + #else
+ + + return 0;
+ + + #endif
+ + + }
#endif
/*
#include <asm/asm.h>
#include <asm/numa.h>
#include <asm/smp.h>
+ + + #include <asm/cpu.h>
+ + + #include <asm/cpumask.h>
#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/mpspec.h>
#include <asm/apic.h>
- - - #include <mach_apic.h>
#include <asm/genapic.h>
+ + + #include <asm/genapic.h>
+ + + #include <asm/uv/uv.h>
#endif
- - - #include <asm/pda.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/desc.h>
#include <asm/sections.h>
#include <asm/setup.h>
#include <asm/hypervisor.h>
+++ + #include <asm/stackprotector.h>
#include "cpu.h"
/* representing cpus for which sibling maps can be computed */
cpumask_var_t cpu_sibling_setup_mask;
+ + + /* correctly size the local cpu masks */
+ + + void __init setup_cpu_local_masks(void)
+ + + {
+ + + alloc_bootmem_cpumask_var(&cpu_initialized_mask);
+ + + alloc_bootmem_cpumask_var(&cpu_callin_mask);
+ + + alloc_bootmem_cpumask_var(&cpu_callout_mask);
+ + + alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask);
+ + + }
+ + +
#else /* CONFIG_X86_32 */
cpumask_t cpu_callin_map;
static struct cpu_dev *this_cpu __cpuinitdata;
+ + + DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
#ifdef CONFIG_X86_64
- - - /* We need valid kernel segments for data and code in long mode too
- - - * IRET will check the segment types kkeil 2000/10/28
- - - * Also sysret mandates a special GDT layout
- - - */
- - - /* The TLS descriptors are currently at a different place compared to i386.
- - - Hopefully nobody expects them at a fixed place (Wine?) */
- - - DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = {
+ + + /*
+ + + * We need valid kernel segments for data and code in long mode too
+ + + * IRET will check the segment types kkeil 2000/10/28
+ + + * Also sysret mandates a special GDT layout
+ + + *
+ + + * The TLS descriptors are currently at a different place compared to i386.
+ + + * Hopefully nobody expects them at a fixed place (Wine?)
+ + + */
[GDT_ENTRY_KERNEL32_CS] = { { { 0x0000ffff, 0x00cf9b00 } } },
[GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00af9b00 } } },
[GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9300 } } },
[GDT_ENTRY_DEFAULT_USER32_CS] = { { { 0x0000ffff, 0x00cffb00 } } },
[GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } },
[GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } },
- - - } };
#else
- - - DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
[GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } },
[GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } },
[GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } },
[GDT_ENTRY_APMBIOS_BASE+2] = { { { 0x0000ffff, 0x00409200 } } },
[GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } },
- - - [GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } },
- - - } };
+ + + [GDT_ENTRY_PERCPU] = { { { 0x0000ffff, 0x00cf9200 } } },
+++ + GDT_STACK_CANARY_INIT
#endif
+ + + } };
EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
#ifdef CONFIG_X86_32
#endif
/*
- -- - ((s32)df->feature < 0 ?
- -- - (u32)df->feature > (u32)c->extended_cpuid_level :
- -- - (s32)df->feature > (s32)c->cpuid_level)) {
+ + * Some CPU features depend on higher CPUID levels, which may not always
+ + * be available due to CPUID level capping or broken virtualization
+ + * software. Add those features to this table to auto-disable them.
+ + */
+ + struct cpuid_dependent_feature {
+ + u32 feature;
+ + u32 level;
+ + };
+ + static const struct cpuid_dependent_feature __cpuinitconst
+ + cpuid_dependent_features[] = {
+ + { X86_FEATURE_MWAIT, 0x00000005 },
+ + { X86_FEATURE_DCA, 0x00000009 },
+ + { X86_FEATURE_XSAVE, 0x0000000d },
+ + { 0, 0 }
+ + };
+ +
+ + static void __cpuinit filter_cpuid_features(struct cpuinfo_x86 *c, bool warn)
+ + {
+ + const struct cpuid_dependent_feature *df;
+ + for (df = cpuid_dependent_features; df->feature; df++) {
+ + /*
+ + * Note: cpuid_level is set to -1 if unavailable, but
+ + * extended_extended_level is set to 0 if unavailable
+ + * and the legitimate extended levels are all negative
+ + * when signed; hence the weird messing around with
+ + * signs here...
+ + */
+ + if (cpu_has(c, df->feature) &&
- -- -}
++ ++++ ((s32)df->level < 0 ?
++ ++++ (u32)df->level > (u32)c->extended_cpuid_level :
++ ++++ (s32)df->level > (s32)c->cpuid_level)) {
+ + clear_cpu_cap(c, df->feature);
+ + if (warn)
+ + printk(KERN_WARNING
+ + "CPU: CPU feature %s disabled "
+ + "due to lack of CPUID level 0x%x\n",
+ + x86_cap_flags[df->feature],
+ + df->level);
+ + }
+ + }
++ ++++}
+ +
+ + /*
* Naming convention should be: <Name> [(<Codename>)]
* This table only is used unless init_<vendor>() below doesn't set it;
* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used
__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
+ + + void load_percpu_segment(int cpu)
+ + + {
+ + + #ifdef CONFIG_X86_32
+ + + loadsegment(fs, __KERNEL_PERCPU);
+ + + #else
+ + + loadsegment(gs, 0);
+ + + wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu));
+ + + #endif
+++ + load_stack_canary_segment();
+ + + }
+ + +
/* Current gdt points %fs at the "master" per-cpu area: after this,
* it's on the real one. */
- - - void switch_to_new_gdt(void)
+ + + void switch_to_new_gdt(int cpu)
{
struct desc_ptr gdt_descr;
- - - gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
+ + + gdt_descr.address = (long)get_cpu_gdt_table(cpu);
gdt_descr.size = GDT_SIZE - 1;
load_gdt(&gdt_descr);
- - - #ifdef CONFIG_X86_32
- - - asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory");
- - - #endif
+ + + /* Reload the per-cpu base */
+ + +
+ + + load_percpu_segment(cpu);
}
static struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
}
index_msb = get_count_order(smp_num_siblings);
- - - #ifdef CONFIG_X86_64
- - - c->phys_proc_id = phys_pkg_id(index_msb);
- - - #else
- - - c->phys_proc_id = phys_pkg_id(c->initial_apicid, index_msb);
- - - #endif
+ + + c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, index_msb);
smp_num_siblings = smp_num_siblings / c->x86_max_cores;
core_bits = get_count_order(c->x86_max_cores);
- - - #ifdef CONFIG_X86_64
- - - c->cpu_core_id = phys_pkg_id(index_msb) &
- ((1 << core_bits) - 1);
- #else
- c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) &
+ + + c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, index_msb) &
((1 << core_bits) - 1);
- - #else
- - c->cpu_core_id = phys_pkg_id(c->initial_apicid, index_msb) &
- - ((1 << core_bits) - 1);
- - - #endif
}
out:
if (this_cpu->c_early_init)
this_cpu->c_early_init(c);
#ifdef CONFIG_SMP
c->cpu_index = boot_cpu_id;
#endif
+ + filter_cpuid_features(c, false);
}
void __init early_cpu_init(void)
c->initial_apicid = (cpuid_ebx(1) >> 24) & 0xFF;
#ifdef CONFIG_X86_32
# ifdef CONFIG_X86_HT
- - - c->apicid = phys_pkg_id(c->initial_apicid, 0);
+ + + c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
# else
c->apicid = c->initial_apicid;
# endif
this_cpu->c_identify(c);
#ifdef CONFIG_X86_64
- - - c->apicid = phys_pkg_id(0);
+ + + c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
#endif
/*
* we do "generic changes."
*/
+ + /* Filter out anything that depends on CPUID levels we don't have */
+ + filter_cpuid_features(c, true);
+ +
/* If the model name is still unset, do table lookup. */
if (!c->x86_model_id[0]) {
char *p;
__setup("clearcpuid=", setup_disablecpuid);
#ifdef CONFIG_X86_64
- - - struct x8664_pda **_cpu_pda __read_mostly;
- - - EXPORT_SYMBOL(_cpu_pda);
- - -
struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
- - - static char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss;
- -
- - void __cpuinit pda_init(int cpu)
- - {
- - struct x8664_pda *pda = cpu_pda(cpu);
+ + + DEFINE_PER_CPU_FIRST(union irq_stack_union,
+ + + irq_stack_union) __aligned(PAGE_SIZE);
- #ifdef CONFIG_SMP
- DEFINE_PER_CPU(char *, irq_stack_ptr); /* will be set during per cpu init */
- #else
+ + + DEFINE_PER_CPU(char *, irq_stack_ptr) =
- per_cpu_var(irq_stack_union.irq_stack) + IRQ_STACK_SIZE - 64;
- #endif
+++ + init_per_cpu_var(irq_stack_union.irq_stack) + IRQ_STACK_SIZE - 64;
- - /* Setup up data that may be needed in __get_free_pages early */
- - loadsegment(fs, 0);
- - loadsegment(gs, 0);
- - /* Memory clobbers used to order PDA accessed */
- - mb();
- - wrmsrl(MSR_GS_BASE, pda);
- - mb();
- -
- - pda->cpunumber = cpu;
- - pda->irqcount = -1;
- - pda->kernelstack = (unsigned long)stack_thread_info() -
- - PDA_STACKOFFSET + THREAD_SIZE;
- - pda->active_mm = &init_mm;
- - pda->mmu_state = 0;
- -
- - if (cpu == 0) {
- - /* others are initialized in smpboot.c */
- - pda->pcurrent = &init_task;
- - pda->irqstackptr = boot_cpu_stack;
- - pda->irqstackptr += IRQSTACKSIZE - 64;
- - } else {
- - if (!pda->irqstackptr) {
- - pda->irqstackptr = (char *)
- - __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
- - if (!pda->irqstackptr)
- - panic("cannot allocate irqstack for cpu %d",
- - cpu);
- - pda->irqstackptr += IRQSTACKSIZE - 64;
- - }
- void __cpuinit pda_init(int cpu)
- {
- struct x8664_pda *pda = cpu_pda(cpu);
-
- /* Setup up data that may be needed in __get_free_pages early */
- loadsegment(fs, 0);
- loadsegment(gs, 0);
- /* Memory clobbers used to order PDA accessed */
- mb();
- wrmsrl(MSR_GS_BASE, pda);
- mb();
-
- pda->cpunumber = cpu;
- pda->irqcount = -1;
- pda->kernelstack = (unsigned long)stack_thread_info() -
- PDA_STACKOFFSET + THREAD_SIZE;
- pda->active_mm = &init_mm;
- pda->mmu_state = 0;
-
- if (cpu == 0) {
- /* others are initialized in smpboot.c */
- pda->pcurrent = &init_task;
- pda->irqstackptr = boot_cpu_stack;
- pda->irqstackptr += IRQSTACKSIZE - 64;
- } else {
- if (!pda->irqstackptr) {
- pda->irqstackptr = (char *)
- __get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
- if (!pda->irqstackptr)
- panic("cannot allocate irqstack for cpu %d",
- cpu);
- pda->irqstackptr += IRQSTACKSIZE - 64;
- }
+ + + DEFINE_PER_CPU(unsigned long, kernel_stack) =
+ + + (unsigned long)&init_thread_union - KERNEL_STACK_OFFSET + THREAD_SIZE;
+ + + EXPORT_PER_CPU_SYMBOL(kernel_stack);
- - - if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE)
- - - pda->nodenumber = cpu_to_node(cpu);
- - - }
- - - }
+ + + DEFINE_PER_CPU(unsigned int, irq_count) = -1;
- - - static char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ +
- - - DEBUG_STKSZ] __page_aligned_bss;
+ + + static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks
+ + + [(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ])
+ + + __aligned(PAGE_SIZE);
extern asmlinkage void ignore_sysret(void);
*/
DEFINE_PER_CPU(struct orig_ist, orig_ist);
--- - #else
+++ + #else /* x86_64 */
+ +
-- /* Make sure %fs is initialized properly in idle threads */
+++ + #ifdef CONFIG_CC_STACKPROTECTOR
+++ + DEFINE_PER_CPU(unsigned long, stack_canary);
+++ + #endif
++
- - /* Make sure %fs is initialized properly in idle threads */
+++ + /* Make sure %fs and %gs are initialized properly in idle threads */
struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
{
memset(regs, 0, sizeof(struct pt_regs));
regs->fs = __KERNEL_PERCPU;
+++ + regs->gs = __KERNEL_STACK_CANARY;
return regs;
}
--- - #endif
+++ + #endif /* x86_64 */
/*
* cpu_init() initializes state that is per-CPU. Some data is already
struct tss_struct *t = &per_cpu(init_tss, cpu);
struct orig_ist *orig_ist = &per_cpu(orig_ist, cpu);
unsigned long v;
struct task_struct *me;
int i;
- - - /* CPU 0 is initialised in head64.c */
- - - if (cpu != 0)
- - - pda_init(cpu);
- - - else
- - - estacks = boot_exception_stacks;
+ + + #ifdef CONFIG_NUMA
+ + + if (cpu != 0 && percpu_read(node_number) == 0 &&
+ + + cpu_to_node(cpu) != NUMA_NO_NODE)
+ + + percpu_write(node_number, cpu_to_node(cpu));
+ + + #endif
me = current;
* and set up the GDT descriptor:
*/
- - - switch_to_new_gdt();
+ + + switch_to_new_gdt(cpu);
+ + + loadsegment(fs, 0);
+ + +
load_idt((const struct desc_ptr *)&idt_descr);
memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8);
* set up and load the per-CPU TSS
*/
if (!orig_ist->ist[0]) {
- - - static const unsigned int order[N_EXCEPTION_STACKS] = {
- - - [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
- - - [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
+ + + static const unsigned int sizes[N_EXCEPTION_STACKS] = {
+ + + [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STKSZ,
+ + + [DEBUG_STACK - 1] = DEBUG_STKSZ
};
+ + + char *estacks = per_cpu(exception_stacks, cpu);
for (v = 0; v < N_EXCEPTION_STACKS; v++) {
- - - if (cpu) {
- - - estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
- - - if (!estacks)
- - - panic("Cannot allocate exception "
- - - "stack %ld %d\n", v, cpu);
- - - }
- - - estacks += PAGE_SIZE << order[v];
+ + + estacks += sizes[v];
orig_ist->ist[v] = t->x86_tss.ist[v] =
(unsigned long)estacks;
}
*/
if (kgdb_connected && arch_kgdb_ops.correct_hw_break)
arch_kgdb_ops.correct_hw_break();
- - - else {
+ + + else
#endif
- - - /*
- - - * Clear all 6 debug registers:
- - - */
- - -
- - - set_debugreg(0UL, 0);
- - - set_debugreg(0UL, 1);
- - - set_debugreg(0UL, 2);
- - - set_debugreg(0UL, 3);
- - - set_debugreg(0UL, 6);
- - - set_debugreg(0UL, 7);
- - - #ifdef CONFIG_KGDB
- - - /* If the kgdb is connected no debug regs should be altered. */
+ + + {
+ + + /*
+ + + * Clear all 6 debug registers:
+ + + */
+ + + set_debugreg(0UL, 0);
+ + + set_debugreg(0UL, 1);
+ + + set_debugreg(0UL, 2);
+ + + set_debugreg(0UL, 3);
+ + + set_debugreg(0UL, 6);
+ + + set_debugreg(0UL, 7);
}
- - - #endif
fpu_init();
clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
load_idt(&idt_descr);
- - - switch_to_new_gdt();
+ + + switch_to_new_gdt(cpu);
/*
* Set up and load the per-CPU TSS and LDT
__set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
#endif
--- - /* Clear %gs. */
--- - asm volatile ("mov %0, %%gs" : : "r" (0));
--- -
/* Clear all 6 debug registers: */
set_debugreg(0, 0);
set_debugreg(0, 1);
#include <asm/desc.h>
#include <asm/i387.h>
- - - #include <mach_traps.h>
+ + + #include <asm/mach_traps.h>
#ifdef CONFIG_X86_64
#include <asm/pgalloc.h>
#include <asm/proto.h>
- - - #include <asm/pda.h>
#else
#include <asm/processor-flags.h>
#include <asm/arch_hooks.h>
local_irq_enable();
}
+++++ +static inline void conditional_cli(struct pt_regs *regs)
+++++ +{
+++++ + if (regs->flags & X86_EFLAGS_IF)
+++++ + local_irq_disable();
+++++ +}
+++++ +
static inline void preempt_conditional_cli(struct pt_regs *regs)
{
if (regs->flags & X86_EFLAGS_IF)
#ifdef CONFIG_X86_32
debug_vm86:
+++++ + /* reenable preemption: handle_vm86_trap() might sleep */
+++++ + dec_preempt_count();
handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
----- - preempt_conditional_cli(regs);
+++++ + conditional_cli(regs);
return;
#endif
EXPORT_SYMBOL_GPL(math_state_restore);
#ifndef CONFIG_MATH_EMULATION
- - asmlinkage void math_emulate(long arg)
+ + void math_emulate(struct math_emu_info *info)
{
printk(KERN_EMERG
"math-emulation not enabled and no coprocessor found.\n");
}
#endif /* CONFIG_MATH_EMULATION */
- - dotraplinkage void __kprobes do_device_not_available(struct pt_regs regs)
+ + dotraplinkage void __kprobes
- - do_device_not_available(struct pt_regs *regs, long error)
+++ + do_device_not_available(struct pt_regs *regs, long error_code)
{
#ifdef CONFIG_X86_32
if (read_cr0() & X86_CR0_EM) {
- - conditional_sti(®s);
+ + struct math_emu_info info = { };
+ +
- - math_emulate(0);
+ + conditional_sti(regs);
- - info.regs = ®s;
+ +
+++ + info.regs = regs;
+ + math_emulate(&info);
} else {
math_state_restore(); /* interrupts still off */
- - conditional_sti(®s);
+ + conditional_sti(regs);
}
#else
math_state_restore();