merge apic_32.c and apic_64.c
cover merge apic_32.c and apic_64.c
calibrated_APIC_clock still have two copies.
it seems we should use 32 bit, because some system may not has tsc but it is some long than 64 bits...
Thanks
Yinghai Lu
PATCH 1/18 x86: apic_64.c - setup_APIC_timer has to be __cpuinit function
From: Cyrill Gorcunov <[email protected]>
There is no need to hold this code if CPU_HOTPLUG is not defined
--- arch/x86/kernel/apic_64.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/x86/kernel/apic_64.c +1 -1
@@ -400,7 +400,7 @@ static void lapic_timer_broadcast(cpumask_t mask)* Setup the local APIC timer for this CPU. Copy the initilized values * of the boot CPU and register the clock event in the framework. */ -static void setup_APIC_timer (void ) +static void __cpuinit setup_APIC_timer (void ) {struct clock_event_device *levt = &__get_cpu_var (lapic_events);
Signature · 1 line
1.5.4.5
PATCH 2/18 x86: apic - introduce get_physical_broadcast for 64bit
In reply to Yinghai LuFrom: Cyrill Gorcunov <[email protected]>
We don't really use it now on 64bit mode but
could reserve it for future.
--- arch/x86/kernel/apic_64.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
arch/x86/kernel/apic_64.c +10 -0
@@ -244,6 +244,16 @@ void __cpuinit enable_NMI_through_LVT0(void)apic_write (APIC_LVT0 , v); } +#ifdef CONFIG_X86_32 +/** +* get_physical_broadcast - Get number of physical broadcast IDs +*/ +int get_physical_broadcast (void ) +{ +return modern_apic () ?0xff :0xf ; +} +#endif +/** * lapic_get_maxlvt - get the maximum number of local vector table entries */
Signature · 1 line
1.5.4.5
PATCH 3/18 x86: apic - unify setup_apicpmtimer
In reply to Yinghai LuFrom: Cyrill Gorcunov <[email protected]>
--- arch/x86/kernel/apic_32.c | 10 ++++++++++ arch/x86/kernel/apic_64.c | 2 ++ 2 files changed, 12 insertions(+), 0 deletions(-)
arch/x86/kernel/apic_32.c +10 -0
@@ -1774,6 +1774,16 @@ static int __init parse_nolapic_timer(char *arg) }early_param ("nolapic_timer" , parse_nolapic_timer); +#ifdef CONFIG_X86_64 +static __init int setup_apicpmtimer (char *s) +{ + apic_calibrate_pmtmr =1 ; +notsc_setup (NULL ); +return 0 ; +} +__setup ("apicpmtimer" , setup_apicpmtimer); +#endif +static int __init apic_set_verbosity (char *arg) {if (!arg) {
arch/x86/kernel/apic_64.c +2 -0
@@ -1810,6 +1810,7 @@ static int __init parse_nolapic_timer(char *arg) }early_param ("nolapic_timer" , parse_nolapic_timer); +#ifdef CONFIG_X86_64 static __init int setup_apicpmtimer (char *s) { apic_calibrate_pmtmr =1 ;
@@ -1817,6 +1818,7 @@ static __init int setup_apicpmtimer(char *s) return 0; }__setup ("apicpmtimer" , setup_apicpmtimer); +#endif static int __init apic_set_verbosity (char *arg) {
Signature · 1 line
1.5.4.5
PATCH 4/18 x86: apic_64.c - add sanity check for spurious vector definition
In reply to Yinghai LuFrom: Cyrill Gorcunov <[email protected]>
Do not check for SPUTIOUS_APIC_VECTOR definition twice. Check it once - is what we need.
--- arch/x86/kernel/apic_64.c | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-)
arch/x86/kernel/apic_64.c +7 -2
@@ -46,6 +46,13 @@#include <mach_ipi.h> #include <mach_apic.h> +/* +* Sanity check +*/ +#if ((SPURIOUS_APIC_VECTOR &0x0F ) !=0x0F ) +# error SPURIOUS_APIC_VECTOR definition error +#endif +/* Disable local APIC timer from the kernel commandline or via dmi quirk */ static int disable_apic_timer__cpuinitdata ;static int apic_calibrate_pmtmr__initdata ;
@@ -939,8 +946,6 @@ void __cpuinit setup_local_APIC(void)preempt_disable (); value =apic_read (APIC_LVR ); -BUILD_BUG_ON ((SPURIOUS_APIC_VECTOR &0x0f ) !=0x0f ); -/* * Double-check whether this APIC is really registered. * This is meaningless in clustered apic mode, so we skip it.
Signature · 1 line
1.5.4.5
PATCH 5/18 x86: apic - unify setup_local_APIC
In reply to Yinghai LuFrom: Cyrill Gorcunov <[email protected]>
- remove useless read of APIC_LVR
- wrap with preempt_disable/enable
- check for integrated APIC just in place
v2: fix by Yinghai Lu.
fix lapic_is_intergrated using
let 64bit to have pic_mode
--- arch/x86/kernel/apic_32.c | 21 ++++++++++++++---- arch/x86/kernel/apic_64.c | 51 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 10 deletions(-)
arch/x86/kernel/apic_32.c +16 -5
@@ -1033,9 +1033,10 @@ static void __cpuinit lapic_setup_esr(void)*/ void __cpuinit setup_local_APIC (void ) { -unsigned long value, integrated; +unsigned int value;int i, j; +#ifdef CONFIG_X86_32 /* Pound the ESR really hard over the head with a big hammer - mbligh */ if (esr_disable) {apic_write (APIC_ESR ,0 );
@@ -1043,14 +1044,16 @@ void __cpuinit setup_local_APIC(void)apic_write (APIC_ESR ,0 ); apic_write(APIC_ESR, 0); } +#endif - integrated =lapic_is_integrated (); +preempt_disable ();/* * Double-check whether this APIC is really registered. +* This is meaningless in clustered apic mode, so we skip it. */ if (!apic_id_registered ()) -WARN_ON_ONCE (1 ); +BUG ();/* * Intel recommends to set DFR, LDR and TPR before enabling
@@ -1096,6 +1099,7 @@ void __cpuinit setup_local_APIC(void)*/ value |=APIC_SPIV_APIC_ENABLED ; +#ifdef CONFIG_X86_32 /* * Some unknown Intel IO/APIC (or APIC) errata is biting us with * certain networking cards. If high frequency interrupts are
@@ -1116,8 +1120,13 @@ void __cpuinit setup_local_APIC(void)* See also the comment in end_level_ioapic_irq(). --macro */ -/* Enable focus processor (bit==0) */ +/* +* - enable focus processor (bit==0) +* - 64bit mode always use processor focus +* so no need to set it +*/ value &= ~APIC_SPIV_FOCUS_DISABLED ; +#endif /* * Set spurious IRQ vector
@@ -1154,9 +1163,11 @@ void __cpuinit setup_local_APIC(void) value =APIC_DM_NMI ; else value =APIC_DM_NMI |APIC_LVT_MASKED ; -if (!integrated)/* 82489DX */ +if (!lapic_is_integrated ())/* 82489DX */ value |=APIC_LVT_LEVEL_TRIGGER ;apic_write (APIC_LVT1 , value); + +preempt_enable (); }void __cpuinit end_local_APIC_setup (void )
arch/x86/kernel/apic_64.c +46 -5
88 lines not on this page · raw message
Signature · 1 line
1.5.4.5
PATCH 6/18 x86: apic_32.c should use __cpuinit section
In reply to Yinghai LuFrom: Cyrill Gorcunov <[email protected]>
All callers are __init or __cpuinit so there is no need to hold this code without CPU_HOTPLUG being set.
--- arch/x86/kernel/apic_32.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
arch/x86/kernel/apic_32.c +3 -3
@@ -383,7 +383,7 @@ static void lapic_timer_broadcast(cpumask_t mask)* Setup the local APIC timer for this CPU. Copy the initilized values * of the boot CPU and register the clock event in the framework. */ -static void __devinit setup_APIC_timer (void ) +static void __cpuinit setup_APIC_timer (void ) {struct clock_event_device *levt = &__get_cpu_var (lapic_events);
@@ -652,7 +652,7 @@ void __init setup_boot_APIC_clock(void)setup_APIC_timer (); } -void __devinit setup_secondary_APIC_clock (void ) +void __cpuinit setup_secondary_APIC_clock (void ) {setup_APIC_timer (); }
@@ -1713,7 +1713,7 @@ static struct sys_device device_lapic = { .cls = &lapic_sysclass, }; -static void __devinit apic_pm_activate (void ) +static void __cpuinit apic_pm_activate (void ) { apic_pm_state.active =1 ; }
Signature · 1 line
1.5.4.5
PATCH 7/18 x86: apic - unify smp_apic_timer_interrupt
In reply to Yinghai LuFrom: Cyrill Gorcunov <[email protected]>
--- arch/x86/kernel/apic_32.c | 3 +++ arch/x86/kernel/apic_64.c | 2 ++ 2 files changed, 5 insertions(+), 0 deletions(-)
arch/x86/kernel/apic_32.c +3 -0
@@ -718,6 +718,9 @@ void smp_apic_timer_interrupt(struct pt_regs *regs)* Besides, if we don't timer interrupts ignore the global * interrupt lock, which is the WrongThing (tm) to do. */ +#ifdef CONFIG_X86_64 +exit_idle (); +#endif irq_enter ();local_apic_timer_interrupt ();irq_exit ();
arch/x86/kernel/apic_64.c +2 -0
@@ -625,7 +625,9 @@ void smp_apic_timer_interrupt(struct pt_regs *regs)* Besides, if we don't timer interrupts ignore the global * interrupt lock, which is the WrongThing (tm) to do. */ +#ifdef CONFIG_X86_64 exit_idle (); +#endif irq_enter ();local_apic_timer_interrupt ();irq_exit ();
Signature · 1 line
1.5.4.5
PATCH 8/18 x86: apic_xx.c order variables
In reply to Yinghai Lu--- arch/x86/kernel/apic_32.c | 46 ++++++++++++++++++++++-------------------- arch/x86/kernel/apic_64.c | 48 ++++++++++++++++++++++++++++++--------------- 2 files changed, 56 insertions(+), 38 deletions(-)
arch/x86/kernel/apic_32.c +24 -22
@@ -50,16 +50,37 @@# error SPURIOUS_APIC_VECTOR definition error#endif -unsigned long mp_lapic_addr; - +#ifdef CONFIG_X86_32 /* * Knob to control our willingness to enable the local APIC. * * +1=force-enable */ static int force_enable_local_apic; -int disable_apic; +/* +* APIC command line parameters +*/ +static int __init parse_lapic (char *arg) +{ + force_enable_local_apic =1 ; +return 0 ; +} +early_param ("lapic" , parse_lapic); +#endif +#ifdef CONFIG_X86_64 +static int apic_calibrate_pmtmr__initdata ; +static __init int setup_apicpmtimer (char *s) +{ + apic_calibrate_pmtmr =1 ; +notsc_setup (NULL ); +return 0 ; +} +__setup ("apicpmtimer" , setup_apicpmtimer); +#endif + +unsigned long mp_lapic_addr; +int disable_apic;/* Disable local APIC timer from the kernel commandline or via dmi quirk */ static int disable_apic_timer__cpuinitdata ;/* Local APIC timer works in C2 */
@@ -1742,15 +1763,6 @@ static void apic_pm_activate(void) { }#endif /* CONFIG_PM */ -/* -* APIC command line parameters -*/ -static int __init parse_lapic (char *arg) -{ - force_enable_local_apic =1 ; -return 0 ; -} -early_param ("lapic" , parse_lapic);static int __init setup_disableapic (char *arg) {
@@ -1788,16 +1800,6 @@ static int __init parse_nolapic_timer(char *arg) }early_param ("nolapic_timer" , parse_nolapic_timer); -#ifdef CONFIG_X86_64 -static __init int setup_apicpmtimer (char *s) -{ - apic_calibrate_pmtmr =1 ; -notsc_setup (NULL ); -return 0 ; -} -__setup ("apicpmtimer" , setup_apicpmtimer); -#endif -static int __init apic_set_verbosity (char *arg) {if (!arg) {
arch/x86/kernel/apic_64.c +32 -16
72 lines not on this page · raw message
Signature · 1 line
1.5.4.5
PATCH 9/18 x86: use HAVE_X2APIC in apic_64.c
In reply to Yinghai Lu--- arch/x86/kernel/apic_64.c | 35 +++++++++++++++++++++++------------ 1 files changed, 23 insertions(+), 12 deletions(-)
arch/x86/kernel/apic_64.c +23 -12
@@ -82,10 +82,23 @@ static __init int setup_apicpmtimer(char *s)__setup ("apicpmtimer" , setup_apicpmtimer);#endif -int disable_x2apic; +#ifdef CONFIG_X86_64 +#define HAVE_X2APIC +#endif + +#ifdef HAVE_X2APIC int x2apic;/* x2apic enabled before OS handover */ int x2apic_preenabled; +int disable_x2apic; +static __init int setup_nox2apic (char *str) +{ + disable_x2apic =1 ; +setup_clear_cpu_cap (X86_FEATURE_X2APIC ); +return 0 ; +} +early_param ("nox2apic" , setup_nox2apic); +#endif unsigned long mp_lapic_addr;int disable_apic;
@@ -228,6 +241,7 @@ static struct apic_ops xapic_ops = {struct apic_ops __read_mostly *apic_ops = &xapic_ops;EXPORT_SYMBOL_GPL (apic_ops); +#ifdef HAVE_X2APIC static void x2apic_wait_icr_idle (void ) {/* no need to wait for icr idle in x2apic */
@@ -261,6 +275,7 @@ static struct apic_ops x2apic_ops = { .wait_icr_idle = x2apic_wait_icr_idle, .safe_wait_icr_idle = safe_x2apic_wait_icr_idle, }; +#endif /** * enable_NMI_through_LVT0 - enable NMI through local vector table 0
@@ -1125,6 +1140,7 @@ void __cpuinit end_local_APIC_setup(void)apic_pm_activate (); } +#ifdef HAVE_X2APIC void check_x2apic (void ) {int msr, msr2;
@@ -1243,6 +1259,7 @@ end: return; } +#endif /* HAVE_X2APIC */ /* * Detect and enable local APICs on non-SMP boards.
@@ -1291,10 +1308,12 @@ void __init early_init_lapic_mapping(void)*/ void __init init_apic_mappings (void ) { +#ifdef HAVE_X2APIC if (x2apic) { boot_cpu_physical_apicid =read_apic_id ();return ; } +#endif /* * If no local APIC can be found then set up a fake all
@@ -1335,8 +1354,9 @@ int __init APIC_init_uniprocessor(void)printk (KERN_INFO "Apic disabled by BIOS\n" );return -1 ; } - +#ifdef HAVE_X2APIC enable_IR_x2apic (); +#endif setup_apic_routing ();verify_local_APIC ();
@@ -1672,7 +1692,7 @@ static int lapic_resume(struct sys_device *dev)local_irq_save (flags); -#ifdef CONFIG_X86_64 +#ifdef HAVE_X2APIC if (x2apic)enable_x2apic ();else
@@ -1836,15 +1856,6 @@ __cpuinit int apic_is_clustered_box(void)return (clusters >2 ); } -static __init int setup_nox2apic (char *str) -{ - disable_x2apic =1 ; -clear_cpu_cap (&boot_cpu_data,X86_FEATURE_X2APIC ); -return 0 ; -} -early_param ("nox2apic" , setup_nox2apic); - -/* * APIC command line parameters */
Signature · 1 line
1.5.4.5
PATCH 10/18 x86: add hard_smp_prossor_id with MACRO in io_apic_xx.c
In reply to Yinghai Lu--- arch/x86/kernel/apic_32.c | 7 +++++++ arch/x86/kernel/apic_64.c | 2 ++ 2 files changed, 9 insertions(+), 0 deletions(-)
arch/x86/kernel/apic_32.c +7 -0
@@ -1600,6 +1600,13 @@ void __cpuinit generic_processor_info(int apicid, int version)cpu_set (cpu, cpu_present_map); } +#ifdef CONFIG_X86_64 +int hard_smp_processor_id (void ) +{ +return read_apic_id (); +} +#endif +/* * Power management */
arch/x86/kernel/apic_64.c +2 -0
@@ -1612,10 +1612,12 @@ void __cpuinit generic_processor_info(int apicid, int version)cpu_set (cpu, cpu_present_map); } +#ifdef CONFIG_X86_64 int hard_smp_processor_id (void ) {return read_apic_id (); } +#endif /* * Power management
Signature · 1 line
1.5.4.5
PATCH 11/18 x86: make apic_32/64.c more like
In reply to Yinghai Luexcept x2apic, detec_init_APIC, and calibrating_APIC_clock
--- arch/x86/kernel/apic_32.c | 125 ++++++++++++++++++++++++++++++++++++++++---- arch/x86/kernel/apic_64.c | 10 +++- 2 files changed, 122 insertions(+), 13 deletions(-)
arch/x86/kernel/apic_32.c +113 -12
@@ -66,6 +66,9 @@ static int __init parse_lapic(char *arg) return 0; }early_param ("lapic" , parse_lapic); +/* Local APIC was disabled by the BIOS and enabled by the kernel */ +static int enabled_via_apicbase; +#endif #ifdef CONFIG_X86_64
@@ -131,9 +134,6 @@ static struct clock_event_device lapic_clockevent = { }; static DEFINE_PER_CPU(struct clock_event_device, lapic_events); -/* Local APIC was disabled by the BIOS and enabled by the kernel */ -static int enabled_via_apicbase; -static unsigned long apic_phys;/*
@@ -240,6 +240,7 @@ void __cpuinit enable_NMI_through_LVT0(void)apic_write (APIC_LVT0 , v); } +#ifdef CONFIG_X86_32 /** * get_physical_broadcast - Get number of physical broadcast IDs */
@@ -247,6 +248,7 @@ int get_physical_broadcast(void) {return modern_apic () ?0xff :0xf ; } +#endif /** * lapic_get_maxlvt - get the maximum number of local vector table entries
@@ -1291,6 +1293,32 @@ no_apic:return -1 ; } +#ifdef CONFIG_X86_64 +void __init early_init_lapic_mapping (void ) +{ +unsigned long phys_addr; + +/* +* If no local APIC can be found then go out +* : it means there is no mpatable and MADT +*/ +if (!smp_found_config) +return ; + + phys_addr = mp_lapic_addr; + +set_fixmap_nocache (FIX_APIC_BASE , phys_addr); +apic_printk (APIC_VERBOSE ,"mapped APIC to %16lx (%16lx)\n" , +APIC_BASE , phys_addr); + +/* +* Fetch the APIC ID of the BSP in case we have a +* default configuration (or the MP table is broken). +*/ + boot_cpu_physical_apicid =read_apic_id (); +} +#endif +/** * init_apic_mappings - initialize APIC mappings */
@@ -1308,8 +1336,8 @@ void __init init_apic_mappings(void) apic_phys = mp_lapic_addr;set_fixmap_nocache (FIX_APIC_BASE , apic_phys); -printk (KERN_DEBUG "mapped APIC to %08lx (%08lx)\n" ,APIC_BASE , - apic_phys); +apic_printk (APIC_VERBOSE ,"mapped APIC to %16lx (%16lx)\n" , +APIC_BASE , apic_phys);/* * Fetch the APIC ID of the BSP in case we have a
@@ -1317,14 +1345,12 @@ void __init init_apic_mappings(void)*/ if (boot_cpu_physical_apicid ==-1U ) boot_cpu_physical_apicid =read_apic_id (); - }/* * This initializes the IO-APIC and APIC hardware if this is * a UP kernel. */ -int apic_version[MAX_APICS ];int __init APIC_init_uniprocessor (void )
@@ -1682,11 +1708,6 @@ static int lapic_resume(struct sys_device *dev)local_irq_save (flags); -#ifdef CONFIG_X86_64 -if (x2apic) -enable_x2apic (); - else -#endif {/* * Make sure the APICBASE points to the right address
@@ -1770,7 +1791,87 @@ static void apic_pm_activate(void) { }#endif /* CONFIG_PM */ +#ifdef CONFIG_X86_64 +/* +* apic_is_clustered_box() -- Check if we can expect good TSC +* +* Thus far, the major user of this is IBM's Summit2 series: +* +* Clustered boxes may have unsynced TSC problems if they are +* multi-chassis. Use available data to take a good guess. +* If in doubt, go HPET. +*/ +__cpuinit int apic_is_clustered_box (void ) +{ +int i, clusters, zeros; +unsigned id; +u16 *bios_cpu_apicid; +DECLARE_BITMAP (clustermap,NUM_APIC_CLUSTERS ); + +/* +* there is not this kind of box with AMD CPU yet. +* Some AMD box with quadcore cpu and 8 sockets apicid +* will be [4, 0x23] or [8, 0x27] could be thought to +* vsmp box still need checking... +*/ +if ((boot_cpu_data.x86_vendor ==X86_VENDOR_AMD ) && !is_vsmp_box ()) +return 0 ; + + bios_cpu_apicid =early_per_cpu_ptr (x86_bios_cpu_apicid); +bitmap_zero (clustermap,NUM_APIC_CLUSTERS ); + +for (i =0 ; i <NR_CPUS ; i++) { +/* are we being called early in kernel startup? */ +if (bios_cpu_apicid) { + id = bios_cpu_apicid[i]; + } +else if (i < nr_cpu_ids) { +if (cpu_present (i)) + id =per_cpu (x86_bios_cpu_apicid, i); +else +continue ; + } +else +break ; +if (id !=BAD_APICID ) +__set_bit (APIC_CLUSTERID (id), clustermap); + } + +/* Problem: Partially populated chassis may not have CPUs in some of +* the APIC clusters they have been allocated. Only present CPUs have +* x86_bios_cpu_apicid entries, thus causing zeroes in the bitmap. +* Since clusters are allocated sequentially, count zeros only if +* they are bounded by ones. +*/ + clusters =0 ; + zeros =0 ; +for (i =0 ; i <NUM_APIC_CLUSTERS ; i++) { +if (test_bit (i, clustermap)) { + clusters +=1 + zeros; + zeros =0 ; + }else + ++zeros; + } + +/* ScaleMP vSMPowered boxes have one cluster per board and TSCs are +* not guaranteed to be synced between boards +*/ +if (is_vsmp_box () && clusters >1 ) +return 1 ; + +/* +* If clusters > 2, then should be multi-chassis. +* May have to revisit this when multi-core + hyperthreaded CPUs come +* out, but AFAIK this will work even for them. +*/ +return (clusters >2 ); +} +#endif + +/* +* APIC command line parameters +*/ static int __init setup_disableapic (char *arg) { disable_apic =1 ;
arch/x86/kernel/apic_64.c +9 -1
@@ -69,6 +69,9 @@ static int __init parse_lapic(char *arg) return 0; }early_param ("lapic" , parse_lapic); +/* Local APIC was disabled by the BIOS and enabled by the kernel */ +static int enabled_via_apicbase; +#endif #ifdef CONFIG_X86_64
@@ -1279,6 +1282,7 @@ static int __init detect_init_APIC(void)return 0 ; } +#ifdef CONFIG_X86_64 void __init early_init_lapic_mapping (void ) {unsigned long phys_addr;
@@ -1302,6 +1306,7 @@ void __init early_init_lapic_mapping(void)*/ boot_cpu_physical_apicid = read_apic_id(); } +#endif /** * init_apic_mappings - initialize APIC mappings
@@ -1334,7 +1339,8 @@ void __init init_apic_mappings(void)* Fetch the APIC ID of the BSP in case we have a * default configuration (or the MP table is broken). */ - boot_cpu_physical_apicid =read_apic_id (); +if (boot_cpu_physical_apicid ==-1U ) + boot_cpu_physical_apicid =read_apic_id (); }/*
@@ -1782,6 +1788,7 @@ static void apic_pm_activate(void) { }#endif /* CONFIG_PM */ +#ifdef CONFIG_X86_64 /* * apic_is_clustered_box() -- Check if we can expect good TSC *
@@ -1857,6 +1864,7 @@ __cpuinit int apic_is_clustered_box(void)*/ return (clusters > 2); } +#endif /* * APIC command line parameters
Signature · 1 line
1.5.4.5
PATCH 12/18 x86: merge APIC_init_uniprocessor
In reply to Yinghai Lu--- arch/x86/kernel/apic_32.c | 51 +++++++++++++++++++++++++++++++++++++++----- arch/x86/kernel/apic_64.c | 48 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 90 insertions(+), 9 deletions(-)
arch/x86/kernel/apic_32.c +45 -6
@@ -1355,6 +1355,17 @@ int apic_version[MAX_APICS];int __init APIC_init_uniprocessor (void ) { +#ifdef CONFIG_X86_64 +if (disable_apic) { +printk (KERN_INFO "Apic disabled\n" ); +return -1 ; + } +if (!cpu_has_apic) { + disable_apic =1 ; +printk (KERN_INFO "Apic disabled by BIOS\n" ); +return -1 ; + } +#else if (!smp_found_config && !cpu_has_apic)return -1 ;
@@ -1368,34 +1379,62 @@ int __init APIC_init_uniprocessor(void)clear_cpu_cap (&boot_cpu_data,X86_FEATURE_APIC );return -1 ; } +#endif +#ifdef HAVE_X2APIC +enable_IR_x2apic (); +#endif +#ifdef CONFIG_X86_64 +setup_apic_routing (); +#endif verify_local_APIC (); -connect_bsp_APIC (); +#ifdef CONFIG_X86_64 +apic_write (APIC_ID ,SET_APIC_ID (boot_cpu_physical_apicid)); +#else /* * Hack: In case of kdump, after a crash, kernel might be booting * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid * might be zero if read from MP tables. Get it from LAPIC. */ -#ifdef CONFIG_CRASH_DUMP +# ifdef CONFIG_CRASH_DUMP boot_cpu_physical_apicid =read_apic_id (); +# endif #endif physid_set_mask_of_physid (boot_cpu_physical_apicid, &phys_cpu_present_map); -setup_local_APIC (); +#ifdef CONFIG_X86_64 +/* +* Now enable IO-APICs, actually call clear_IO_APIC +* We need clear_IO_APIC before enabling vector on BP +*/ +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) -if (!skip_ioapic_setup && nr_ioapics) -setup_IO_APIC (); +if (smp_found_config && !skip_ioapic_setup && nr_ioapics) +setup_IO_APIC (); +# ifdef CONFIG_X86_64 + else + nr_ioapics =0 ; +# endif #endif + +#ifdef CONFIG_X86_64 +setup_boot_APIC_clock (); +check_nmi_watchdog (); +#else setup_boot_clock (); +#endif return 0 ; }
arch/x86/kernel/apic_64.c +45 -3
88 lines not on this page · raw message
Signature · 1 line
1.5.4.5
PATCH 13/18 x86: copy detect_init_APIC to the other
In reply to Yinghai Lu--- arch/x86/kernel/apic_32.c | 20 +++++++++++ arch/x86/kernel/apic_64.c | 82 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 1 deletions(-)
arch/x86/kernel/apic_32.c +20 -0
@@ -1214,6 +1214,25 @@ void __cpuinit end_local_APIC_setup(void)apic_pm_activate (); } +#ifdef CONFIG_X86_64 +/* +* Detect and enable local APICs on non-SMP boards. +* Original code written by Keir Fraser. +* On AMD64 we trust the BIOS - if it says no APIC it is likely +* not correctly set up (usually the APIC timer won't work etc.) +*/ +static int __init detect_init_APIC (void ) +{ +if (!cpu_has_apic) { +printk (KERN_INFO "No local APIC present\n" ); +return -1 ; + } + + mp_lapic_addr =APIC_DEFAULT_PHYS_BASE ; + boot_cpu_physical_apicid =0 ; +return 0 ; +} +#else /* * Detect and initialize APIC */
@@ -1292,6 +1311,7 @@ no_apic:printk (KERN_INFO "No local APIC present or hardware disabled\n" ); return -1; } +#endif #ifdef CONFIG_X86_64 void __init early_init_lapic_mapping (void )
arch/x86/kernel/apic_64.c +81 -1
100 lines not on this page · raw message
Signature · 1 line
1.5.4.5
PATCH 14/18 x86: merge header files in apic_xx.c
In reply to Yinghai Lu--- arch/x86/kernel/apic_32.c | 8 ++++++++ arch/x86/kernel/apic_64.c | 7 ++++++- 2 files changed, 14 insertions(+), 1 deletions(-)
arch/x86/kernel/apic_32.c +8 -0
@@ -23,11 +23,13 @@#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/acpi_pmtmr.h> #include <linux/module.h> #include <linux/dmi.h> +#include <linux/dmar.h> #include <asm/atomic.h> #include <asm/smp.h>
@@ -36,8 +38,14 @@#include <asm/desc.h> #include <asm/arch_hooks.h> #include <asm/hpet.h> +#include <asm/pgalloc.h> #include <asm/i8253.h> #include <asm/nmi.h> +#include <asm/idle.h> +#include <asm/proto.h> +#include <asm/timex.h> +#include <asm/apic.h> +#include <asm/i8259.h> #include <mach_apic.h> #include <mach_apicdef.h>
arch/x86/kernel/apic_64.c +6 -1
@@ -24,9 +24,11 @@#include <linux/kernel_stat.h> #include <linux/sysdev.h> #include <linux/ioport.h> +#include <linux/cpu.h> #include <linux/clockchips.h> #include <linux/acpi_pmtmr.h> #include <linux/module.h> +#include <linux/dmi.h> #include <linux/dmar.h> #include <asm/atomic.h>
@@ -34,8 +36,10 @@#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/i8253.h> #include <asm/nmi.h> #include <asm/idle.h> #include <asm/proto.h>
@@ -43,8 +47,9 @@#include <asm/apic.h> #include <asm/i8259.h> -#include <mach_ipi.h> #include <mach_apic.h> +#include <mach_apicdef.h> +#include <mach_ipi.h> /* * Sanity check
Signature · 1 line
1.5.4.5
PATCH 15/18 x86: apic unify smp_spurious/error_interrupt
In reply to Yinghai Lu--- arch/x86/kernel/apic_32.c | 24 +++++++++++++++++++++--- arch/x86/kernel/apic_64.c | 24 ++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 5 deletions(-)
arch/x86/kernel/apic_32.c +21 -3
@@ -1474,10 +1474,17 @@ int __init APIC_init_uniprocessor(void)/* * This interrupt should _never_ happen with our APIC/SMP architecture */ +#ifdef CONFIG_X86_64 +asmlinkage void smp_spurious_interrupt(void) +#else void smp_spurious_interrupt(struct pt_regs *regs) +#endif { -unsigned long v; +u32 v; +#ifdef CONFIG_X86_64 +exit_idle (); +#endif irq_enter ();/* * Check if this really is a spurious interrupt and ACK it
@@ -1488,20 +1495,31 @@ void smp_spurious_interrupt(struct pt_regs *regs)if (v & (1 << (SPURIOUS_APIC_VECTOR &0x1f )))ack_APIC_irq (); +#ifdef CONFIG_X86_64 +add_pda (irq_spurious_count,1 ); +#else /* see sw-dev-man vol 3, chapter 7.4.13.5 */ printk (KERN_INFO "spurious APIC interrupt on CPU#%d, " "should never happen.\n" ,smp_processor_id ());__get_cpu_var (irq_stat).irq_spurious_count++; +#endif irq_exit (); }/* * This interrupt should never happen with our APIC/SMP architecture */ +#ifdef CONFIG_X86_64 +asmlinkage void smp_error_interrupt(void) +#else void smp_error_interrupt(struct pt_regs *regs) +#endif { -unsigned long v, v1; +u32 v, v1; +#ifdef CONFIG_X86_64 +exit_idle (); +#endif irq_enter ();/* First tickle the hardware, only then report what went on. -- REW */ v =apic_read (APIC_ESR );
@@ -1520,7 +1538,7 @@ void smp_error_interrupt(struct pt_regs *regs)6: Received illegal vector 7: Illegal register address */ -printk (KERN_DEBUG "APIC error on CPU%d: %02lx(%02lx)\n" , +printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n" ,smp_processor_id (), v , v1);irq_exit (); }
arch/x86/kernel/apic_64.c +22 -2
@@ -1528,10 +1528,17 @@ int __init APIC_init_uniprocessor(void)/* * This interrupt should _never_ happen with our APIC/SMP architecture */ +#ifdef CONFIG_X86_64 asmlinkage void smp_spurious_interrupt(void) +#else +void smp_spurious_interrupt(struct pt_regs *regs) +#endif { -unsigned int v; +u32 v; + +#ifdef CONFIG_X86_64 exit_idle (); +#endif irq_enter ();/* * Check if this really is a spurious interrupt and ACK it
@@ -1542,18 +1549,31 @@ asmlinkage void smp_spurious_interrupt(void)if (v & (1 << (SPURIOUS_APIC_VECTOR &0x1f )))ack_APIC_irq (); +#ifdef CONFIG_X86_64 add_pda (irq_spurious_count,1 ); +#else +/* see sw-dev-man vol 3, chapter 7.4.13.5 */ +printk (KERN_INFO "spurious APIC interrupt on CPU#%d, " +"should never happen.\n" ,smp_processor_id ()); +__get_cpu_var (irq_stat).irq_spurious_count++; +#endif irq_exit (); }/* * This interrupt should never happen with our APIC/SMP architecture */ +#ifdef CONFIG_X86_64 asmlinkage void smp_error_interrupt(void) +#else +void smp_error_interrupt(struct pt_regs *regs) +#endif { -unsigned int v, v1; +u32 v, v1; +#ifdef CONFIG_X86_64 exit_idle (); +#endif irq_enter ();/* First tickle the hardware, only then report what went on. -- REW */ v =apic_read (APIC_ESR );
Signature · 1 line
1.5.4.5
PATCH 16/18 x86: apic copy calibrate_APIC_clock to each other in apic_32/64.c
In reply to Yinghai Lu--- arch/x86/kernel/apic_32.c | 86 ++++++++++++++++++ arch/x86/kernel/apic_64.c | 215 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 301 insertions(+), 0 deletions(-)
arch/x86/kernel/apic_32.c +86 -0
@@ -424,6 +424,90 @@ static void __cpuinit setup_APIC_timer(void)clockevents_register_device (levt); } +#ifdef CONFIG_X86_64 +/* +* In this function we calibrate APIC bus clocks to the external +* timer. Unfortunately we cannot use jiffies and the timer irq +* to calibrate, since some later bootup code depends on getting +* the first irq? Ugh. +* +* We want to do the calibration only once since we +* want to have local timer irqs syncron. CPUs connected +* by the same APIC bus have the very same bus frequency. +* And we want to have irqs off anyways, no accidental +* APIC irq that way. +*/ + +#define TICK_COUNT 100000000 + +static int __init calibrate_APIC_clock (void ) +{ +unsigned apic, apic_start; +unsigned long tsc, tsc_start; +int result; + +local_irq_disable (); + +/* +* Put whatever arbitrary (but long enough) timeout +* value into the APIC clock, we just want to get the +* counter running for calibration. +* +* No interrupt enable ! +*/ +__setup_APIC_LVTT (250000000 ,0 ,0 ); + + apic_start =apic_read (APIC_TMCCT ); +#ifdef CONFIG_X86_PM_TIMER +if (apic_calibrate_pmtmr && pmtmr_ioport) { +pmtimer_wait (5000 );/* 5ms wait */ + apic =apic_read (APIC_TMCCT ); + result = (apic_start - apic) *1000L /5 ; + } else +#endif + { +rdtscll (tsc_start); + +do { + apic =apic_read (APIC_TMCCT ); +rdtscll (tsc); + }while ((tsc - tsc_start) <TICK_COUNT && + (apic_start - apic) <TICK_COUNT ); + + result = (apic_start - apic) *1000L * tsc_khz / + (tsc - tsc_start); + } + +local_irq_enable (); + +printk (KERN_DEBUG "APIC timer calibration result %d\n" , result); + +printk (KERN_INFO "Detected %d.%03d MHz APIC timer.\n" , + result /1000 /1000 , result /1000 %1000 ); + +/* Calculate the scaled math multiplication factor */ + lapic_clockevent.mult =div_sc (result,NSEC_PER_SEC , + lapic_clockevent.shift); + lapic_clockevent.max_delta_ns = +clockevent_delta2ns (0x7FFFFF , &lapic_clockevent); + lapic_clockevent.min_delta_ns = +clockevent_delta2ns (0xF , &lapic_clockevent); + + calibration_result = (result *APIC_DIVISOR ) /HZ ; + +/* +* Do a sanity check on the APIC calibration result +*/ +if (calibration_result < (1000000 /HZ )) { +printk (KERN_WARNING +"APIC frequency too slow, disabling apic timer\n" ); +return -1 ; + } + +return 0 ; +} + +#else /* * In this functions we calibrate APIC bus clocks to the external timer. *
@@ -635,6 +719,8 @@ static int __init calibrate_APIC_clock(void) return 0; } +#endif +/* * Setup the boot APIC *
arch/x86/kernel/apic_64.c +215 -0
227 lines not on this page · raw message
Signature · 1 line
1.5.4.5
PATCH 17/18 x86: apic copy apic_64.c to apic_32.c
In reply to Yinghai Lu--- arch/x86/kernel/apic_32.c | 188 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 188 insertions(+), 0 deletions(-)
arch/x86/kernel/apic_32.c +188 -0
@@ -90,6 +90,24 @@ static __init int setup_apicpmtimer(char *s)__setup ("apicpmtimer" , setup_apicpmtimer);#endif +#ifdef CONFIG_X86_64 +#define HAVE_X2APIC +#endif + +#ifdef HAVE_X2APIC +int x2apic; +/* x2apic enabled before OS handover */ +int x2apic_preenabled; +int disable_x2apic; +static __init int setup_nox2apic (char *str) +{ + disable_x2apic =1 ; +setup_clear_cpu_cap (X86_FEATURE_X2APIC ); +return 0 ; +} +early_param ("nox2apic" , setup_nox2apic); +#endif +unsigned long mp_lapic_addr;int disable_apic;/* Disable local APIC timer from the kernel commandline or via dmi quirk */
@@ -231,6 +249,42 @@ static struct apic_ops xapic_ops = {struct apic_ops __read_mostly *apic_ops = &xapic_ops;EXPORT_SYMBOL_GPL (apic_ops); +#ifdef HAVE_X2APIC +static void x2apic_wait_icr_idle (void ) +{ +/* no need to wait for icr idle in x2apic */ +return ; +} + +static u32 safe_x2apic_wait_icr_idle (void ) +{ +/* no need to wait for icr idle in x2apic */ +return 0 ; +} + +void x2apic_icr_write (u32 low,u32 id) +{ +wrmsrl (APIC_BASE_MSR + (APIC_ICR >>4 ), ((__u64 ) id) <<32 | low); +} + +u64 x2apic_icr_read (void ) +{ +unsigned long val; + +rdmsrl (APIC_BASE_MSR + (APIC_ICR >>4 ), val); +return val; +} + +static struct apic_ops x2apic_ops = { + .read = native_apic_msr_read, + .write = native_apic_msr_write, + .icr_read = x2apic_icr_read, + .icr_write = x2apic_icr_write, + .wait_icr_idle = x2apic_wait_icr_idle, + .safe_wait_icr_idle = safe_x2apic_wait_icr_idle, +}; +#endif +/** * enable_NMI_through_LVT0 - enable NMI through local vector table 0 */
@@ -1308,6 +1362,127 @@ void __cpuinit end_local_APIC_setup(void)apic_pm_activate (); } +#ifdef HAVE_X2APIC +void check_x2apic (void ) +{ +int msr, msr2; + +rdmsr (MSR_IA32_APICBASE , msr, msr2); + +if (msr &X2APIC_ENABLE ) { +printk ("x2apic enabled by BIOS, switching to x2apic ops\n" ); + x2apic_preenabled = x2apic =1 ; + apic_ops = &x2apic_ops; + } +} + +void enable_x2apic (void ) +{ +int msr, msr2; + +rdmsr (MSR_IA32_APICBASE , msr, msr2); +if (!(msr &X2APIC_ENABLE )) { +printk ("Enabling x2apic\n" ); +wrmsr (MSR_IA32_APICBASE , msr |X2APIC_ENABLE ,0 ); + } +} + +void enable_IR_x2apic (void ) +{ +#ifdef CONFIG_INTR_REMAP +int ret; +unsigned long flags; + +if (!cpu_has_x2apic) +return ; + +if (!x2apic_preenabled && disable_x2apic) { +printk (KERN_INFO +"Skipped enabling x2apic and Interrupt-remapping " +"because of nox2apic\n" ); +return ; + } + +if (x2apic_preenabled && disable_x2apic) +panic ("Bios already enabled x2apic, can't enforce nox2apic" ); + +if (!x2apic_preenabled && skip_ioapic_setup) { +printk (KERN_INFO +"Skipped enabling x2apic and Interrupt-remapping " +"because of skipping io-apic setup\n" ); +return ; + } + + ret =dmar_table_init (); +if (ret) { +printk (KERN_INFO +"dmar_table_init() failed with %d:\n" , ret); + +if (x2apic_preenabled) +panic ("x2apic enabled by bios. But IR enabling failed" ); +else +printk (KERN_INFO +"Not enabling x2apic,Intr-remapping\n" ); +return ; + } + +local_irq_save (flags); +mask_8259A (); +save_mask_IO_APIC_setup (); + + ret =enable_intr_remapping (1 ); + +if (ret && x2apic_preenabled) { +local_irq_restore (flags); +panic ("x2apic enabled by bios. But IR enabling failed" ); + } + +if (ret) + goto end; + +if (!x2apic) { + x2apic =1 ; + apic_ops = &x2apic_ops; +enable_x2apic (); + } +end: +if (ret) +/* +* IR enabling failed +*/ +restore_IO_APIC_setup (); +else +reinit_intr_remapped_IO_APIC (x2apic_preenabled); + +unmask_8259A (); +local_irq_restore (flags); + +if (!ret) { +if (!x2apic_preenabled) +printk (KERN_INFO +"Enabled x2apic and interrupt-remapping\n" ); +else +printk (KERN_INFO +"Enabled Interrupt-remapping\n" ); + }else +printk (KERN_ERR +"Failed to enable Interrupt-remapping and x2apic\n" ); +#else +if (!cpu_has_x2apic) +return ; + +if (x2apic_preenabled) +panic ("x2apic enabled prior OS handover," +" enable CONFIG_INTR_REMAP" ); + +printk (KERN_INFO "Enable CONFIG_INTR_REMAP for enabling intr-remapping " +" and x2apic\n" ); +#endif + +return ; +} +#endif /* HAVE_X2APIC */ +#ifdef CONFIG_X86_64 /* * Detect and enable local APICs on non-SMP boards.
@@ -1438,6 +1613,13 @@ void __init early_init_lapic_mapping(void)*/ void __init init_apic_mappings (void ) { +#ifdef HAVE_X2APIC +if (x2apic) { + boot_cpu_physical_apicid =read_apic_id (); +return ; + } +#endif +/* * If no local APIC can be found then set up a fake all * zeroes page to simulate the local APIC and another
@@ -1501,6 +1683,7 @@ int __init APIC_init_uniprocessor(void)#ifdef CONFIG_X86_64 setup_apic_routing ();#endif +verify_local_APIC ();connect_bsp_APIC ();
@@ -1879,6 +2062,11 @@ static int lapic_resume(struct sys_device *dev)local_irq_save (flags); +#ifdef HAVE_X2APIC +if (x2apic) +enable_x2apic (); + else +#endif {/* * Make sure the APICBASE points to the right address
Signature · 1 line
1.5.4.5
PATCH 18/18 x86: rename apic_32.c and apic_64.c to apic.c
In reply to Yinghai Lu---
arch/x86/kernel/Makefile | 2 +-
arch/x86/kernel/{apic_32.c => apic.c} | 0
arch/x86/kernel/Makefile | 2
arch/x86/kernel/apic.c | 2311 ++++++++++++++++++++++++++++++++++++++++++++++
arch/x86/kernel/apic_32.c | 2311 ----------------------------------------------
arch/x86/kernel/apic_64.c | 2311 ----------------------------------------------
4 files changed, 2312 insertions(+), 4623 deletions(-)
rename arch/x86/kernel/{apic_32.c => apic.c} (100%)
delete mode 100644 arch/x86/kernel/apic_64.carch/x86/kernel/Makefile +1 -1
@@ -64,7 +64,7 @@ obj-$(CONFIG_X86_32_SMP) += smpcommon.o obj-$(CONFIG_X86_64_SMP) += tsc_sync.o smpcommon.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o obj-$(CONFIG_X86_MPPARSE) += mpparse.o -obj-$(CONFIG_X86_LOCAL_APIC) += apic_$(BITS).o nmi.o +obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups_32.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
arch/x86/kernel/apic_64.c deleted +0 -2311
2,311 lines not on this page · raw message
arch/x86/kernel/apic_32.c deleted +0 -2311
681 lines not on this page · raw message
arch/x86/kernel/apic.c new file +2311 -0
2,311 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.
Quoted 3 lines · Yinghai Lu
calibrated_APIC_clockstill have two copies.
it seems we should use 32 bit, because some system may not has tsc but it is some long than 64 bits...
correct, the 32-bit calibration code looks more mature, so we should pick that. (after making sure it's properly 64-bit clean)
Ingo
very nice series! I've applied it to tip/irq/sparseirq and did a test-integration with tip/master - lets see how it behaves in -tip testing.
Ingo