ia64/xen-unstable
changeset 17552:9fd00ff95068
x86: Support x2APIC mode.
Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
line diff
1.1 --- a/xen/arch/x86/apic.c Thu May 01 11:30:42 2008 +0100 1.2 +++ b/xen/arch/x86/apic.c Thu May 01 11:34:56 2008 +0100 1.3 @@ -47,6 +47,8 @@ int enable_local_apic __initdata = 0; /* 1.4 */ 1.5 int apic_verbosity; 1.6 1.7 +int x2apic_enabled __read_mostly = 0; 1.8 + 1.9 1.10 static void apic_pm_activate(void); 1.11 1.12 @@ -306,7 +308,10 @@ int __init verify_local_APIC(void) 1.13 */ 1.14 reg0 = apic_read(APIC_LVR); 1.15 apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg0); 1.16 - apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK); 1.17 + 1.18 + /* We don't try writing LVR in x2APIC mode since that incurs #GP. */ 1.19 + if ( !x2apic_enabled ) 1.20 + apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK); 1.21 reg1 = apic_read(APIC_LVR); 1.22 apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg1); 1.23 1.24 @@ -610,7 +615,8 @@ int lapic_suspend(void) 1.25 apic_pm_state.apic_id = apic_read(APIC_ID); 1.26 apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI); 1.27 apic_pm_state.apic_ldr = apic_read(APIC_LDR); 1.28 - apic_pm_state.apic_dfr = apic_read(APIC_DFR); 1.29 + if ( !x2apic_enabled ) 1.30 + apic_pm_state.apic_dfr = apic_read(APIC_DFR); 1.31 apic_pm_state.apic_spiv = apic_read(APIC_SPIV); 1.32 apic_pm_state.apic_lvtt = apic_read(APIC_LVTT); 1.33 apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC); 1.34 @@ -643,14 +649,20 @@ int lapic_resume(void) 1.35 * FIXME! This will be wrong if we ever support suspend on 1.36 * SMP! We'll need to do this as part of the CPU restore! 1.37 */ 1.38 - rdmsr(MSR_IA32_APICBASE, l, h); 1.39 - l &= ~MSR_IA32_APICBASE_BASE; 1.40 - l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; 1.41 - wrmsr(MSR_IA32_APICBASE, l, h); 1.42 + if ( !x2apic_enabled ) 1.43 + { 1.44 + rdmsr(MSR_IA32_APICBASE, l, h); 1.45 + l &= ~MSR_IA32_APICBASE_BASE; 1.46 + l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; 1.47 + wrmsr(MSR_IA32_APICBASE, l, h); 1.48 + } 1.49 + else 1.50 + enable_x2apic(); 1.51 1.52 apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); 1.53 apic_write(APIC_ID, apic_pm_state.apic_id); 1.54 - apic_write(APIC_DFR, apic_pm_state.apic_dfr); 1.55 + if ( !x2apic_enabled ) 1.56 + apic_write(APIC_DFR, apic_pm_state.apic_dfr); 1.57 apic_write(APIC_LDR, apic_pm_state.apic_ldr); 1.58 apic_write(APIC_TASKPRI, apic_pm_state.apic_taskpri); 1.59 apic_write(APIC_SPIV, apic_pm_state.apic_spiv); 1.60 @@ -809,10 +821,29 @@ no_apic: 1.61 return -1; 1.62 } 1.63 1.64 +void enable_x2apic(void) 1.65 +{ 1.66 + u32 lo, hi; 1.67 + 1.68 + rdmsr(MSR_IA32_APICBASE, lo, hi); 1.69 + if ( !(lo & MSR_IA32_APICBASE_EXTD) ) 1.70 + { 1.71 + lo |= MSR_IA32_APICBASE_ENABLE | MSR_IA32_APICBASE_EXTD; 1.72 + wrmsr(MSR_IA32_APICBASE, lo, 0); 1.73 + printk("x2APIC mode enabled.\n"); 1.74 + } 1.75 + else 1.76 + printk("x2APIC mode enabled by BIOS.\n"); 1.77 + 1.78 + x2apic_enabled = 1; 1.79 +} 1.80 + 1.81 void __init init_apic_mappings(void) 1.82 { 1.83 unsigned long apic_phys; 1.84 1.85 + if ( x2apic_enabled ) 1.86 + goto __next; 1.87 /* 1.88 * If no local APIC can be found then set up a fake all 1.89 * zeroes page to simulate the local APIC and another 1.90 @@ -828,12 +859,13 @@ void __init init_apic_mappings(void) 1.91 apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n", APIC_BASE, 1.92 apic_phys); 1.93 1.94 +__next: 1.95 /* 1.96 * Fetch the APIC ID of the BSP in case we have a 1.97 * default configuration (or the MP table is broken). 1.98 */ 1.99 if (boot_cpu_physical_apicid == -1U) 1.100 - boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); 1.101 + boot_cpu_physical_apicid = get_apic_id(); 1.102 1.103 #ifdef CONFIG_X86_IO_APIC 1.104 { 1.105 @@ -1271,7 +1303,7 @@ int __init APIC_init_uniprocessor (void) 1.106 * might be zero if read from MP tables. Get it from LAPIC. 1.107 */ 1.108 #ifdef CONFIG_CRASH_DUMP 1.109 - boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); 1.110 + boot_cpu_physical_apicid = get_apic_id(); 1.111 #endif 1.112 phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); 1.113
2.1 --- a/xen/arch/x86/genapic/Makefile Thu May 01 11:30:42 2008 +0100 2.2 +++ b/xen/arch/x86/genapic/Makefile Thu May 01 11:34:56 2008 +0100 2.3 @@ -1,4 +1,5 @@ 2.4 obj-y += bigsmp.o 2.5 +obj-y += x2apic.o 2.6 obj-y += default.o 2.7 obj-y += delivery.o 2.8 obj-y += probe.o
3.1 --- a/xen/arch/x86/genapic/delivery.c Thu May 01 11:30:42 2008 +0100 3.2 +++ b/xen/arch/x86/genapic/delivery.c Thu May 01 11:34:56 2008 +0100 3.3 @@ -17,7 +17,7 @@ void init_apic_ldr_flat(void) 3.4 3.5 apic_write_around(APIC_DFR, APIC_DFR_FLAT); 3.6 val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; 3.7 - val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id()); 3.8 + val |= SET_xAPIC_LOGICAL_ID(1UL << smp_processor_id()); 3.9 apic_write_around(APIC_LDR, val); 3.10 } 3.11
4.1 --- a/xen/arch/x86/genapic/probe.c Thu May 01 11:30:42 2008 +0100 4.2 +++ b/xen/arch/x86/genapic/probe.c Thu May 01 11:34:56 2008 +0100 4.3 @@ -14,6 +14,7 @@ 4.4 #include <asm/apicdef.h> 4.5 #include <asm/genapic.h> 4.6 4.7 +extern struct genapic apic_x2apic; 4.8 extern struct genapic apic_summit; 4.9 extern struct genapic apic_bigsmp; 4.10 extern struct genapic apic_default; 4.11 @@ -21,6 +22,7 @@ extern struct genapic apic_default; 4.12 struct genapic *genapic; 4.13 4.14 struct genapic *apic_probe[] __initdata = { 4.15 + &apic_x2apic, 4.16 &apic_summit, 4.17 &apic_bigsmp, 4.18 &apic_default, /* must be last */
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/xen/arch/x86/genapic/x2apic.c Thu May 01 11:34:56 2008 +0100 5.3 @@ -0,0 +1,79 @@ 5.4 +/* 5.5 + * x2APIC driver. 5.6 + * 5.7 + * Copyright (c) 2008, Intel Corporation. 5.8 + * 5.9 + * This program is free software; you can redistribute it and/or modify it 5.10 + * under the terms and conditions of the GNU General Public License, 5.11 + * version 2, as published by the Free Software Foundation. 5.12 + * 5.13 + * This program is distributed in the hope it will be useful, but WITHOUT 5.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.15 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 5.16 + * more details. 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License along with 5.19 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 5.20 + * Place - Suite 330, Boston, MA 02111-1307 USA. 5.21 + */ 5.22 + 5.23 +#include <xen/cpumask.h> 5.24 +#include <asm/apicdef.h> 5.25 +#include <asm/genapic.h> 5.26 +#include <xen/smp.h> 5.27 +#include <asm/mach-default/mach_mpparse.h> 5.28 + 5.29 +__init int probe_x2apic(void) 5.30 +{ 5.31 + return x2apic_is_available(); 5.32 +} 5.33 + 5.34 +struct genapic apic_x2apic= { 5.35 + APIC_INIT("x2apic", probe_x2apic), 5.36 + GENAPIC_X2APIC 5.37 +}; 5.38 + 5.39 +void init_apic_ldr_x2apic(void) 5.40 +{ 5.41 + /* We only use physical delivery mode. */ 5.42 + return; 5.43 +} 5.44 + 5.45 +void clustered_apic_check_x2apic(void) 5.46 +{ 5.47 + /* We only use physical delivery mode. */ 5.48 + return; 5.49 +} 5.50 + 5.51 +cpumask_t target_cpus_x2apic(void) 5.52 +{ 5.53 + /* Deliver interrupts only to CPU0 for now */ 5.54 + return cpumask_of_cpu(0); 5.55 +} 5.56 + 5.57 +unsigned int cpu_mask_to_apicid_x2apic(cpumask_t cpumask) 5.58 +{ 5.59 + return cpu_physical_id(first_cpu(cpumask)); 5.60 +} 5.61 + 5.62 +void send_IPI_mask_x2apic(cpumask_t cpumask, int vector) 5.63 +{ 5.64 + unsigned int query_cpu; 5.65 + u32 cfg, dest; 5.66 + unsigned long flags; 5.67 + 5.68 + ASSERT(cpus_subset(cpumask, cpu_online_map)); 5.69 + ASSERT(!cpus_empty(cpumask)); 5.70 + 5.71 + local_irq_save(flags); 5.72 + 5.73 + cfg = APIC_DM_FIXED | 0 /* no shorthand */ | APIC_DEST_PHYSICAL | vector; 5.74 + for_each_cpu_mask(query_cpu, cpumask) 5.75 + { 5.76 + dest = cpu_physical_id(query_cpu); 5.77 + apic_icr_write(cfg, dest); 5.78 + } 5.79 + 5.80 + local_irq_restore(flags); 5.81 +} 5.82 +
6.1 --- a/xen/arch/x86/hvm/vlapic.c Thu May 01 11:30:42 2008 +0100 6.2 +++ b/xen/arch/x86/hvm/vlapic.c Thu May 01 11:34:56 2008 +0100 6.3 @@ -171,7 +171,7 @@ int vlapic_match_logical_addr(struct vla 6.4 int result = 0; 6.5 uint8_t logical_id; 6.6 6.7 - logical_id = GET_APIC_LOGICAL_ID(vlapic_get_reg(vlapic, APIC_LDR)); 6.8 + logical_id = GET_xAPIC_LOGICAL_ID(vlapic_get_reg(vlapic, APIC_LDR)); 6.9 6.10 switch ( vlapic_get_reg(vlapic, APIC_DFR) ) 6.11 { 6.12 @@ -484,7 +484,7 @@ void vlapic_EOI_set(struct vlapic *vlapi 6.13 static int vlapic_ipi( 6.14 struct vlapic *vlapic, uint32_t icr_low, uint32_t icr_high) 6.15 { 6.16 - unsigned int dest = GET_APIC_DEST_FIELD(icr_high); 6.17 + unsigned int dest = GET_xAPIC_DEST_FIELD(icr_high); 6.18 unsigned int short_hand = icr_low & APIC_SHORT_MASK; 6.19 unsigned int trig_mode = icr_low & APIC_INT_LEVELTRIG; 6.20 unsigned int level = icr_low & APIC_INT_ASSERT;
7.1 --- a/xen/arch/x86/io_apic.c Thu May 01 11:30:42 2008 +0100 7.2 +++ b/xen/arch/x86/io_apic.c Thu May 01 11:34:56 2008 +0100 7.3 @@ -1125,7 +1125,7 @@ void disable_IO_APIC(void) 7.4 entry.delivery_mode = dest_ExtINT; /* ExtInt */ 7.5 entry.vector = 0; 7.6 entry.dest.physical.physical_dest = 7.7 - GET_APIC_ID(apic_read(APIC_ID)); 7.8 + get_apic_id(); 7.9 7.10 /* 7.11 * Add it to the IO-APIC irq-routing table:
8.1 --- a/xen/arch/x86/mpparse.c Thu May 01 11:30:42 2008 +0100 8.2 +++ b/xen/arch/x86/mpparse.c Thu May 01 11:34:56 2008 +0100 8.3 @@ -814,12 +814,15 @@ void __init find_smp_config (void) 8.4 void __init mp_register_lapic_address ( 8.5 u64 address) 8.6 { 8.7 - mp_lapic_addr = (unsigned long) address; 8.8 + if ( !x2apic_enabled ) 8.9 + { 8.10 + mp_lapic_addr = (unsigned long) address; 8.11 8.12 - set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); 8.13 + set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); 8.14 + } 8.15 8.16 if (boot_cpu_physical_apicid == -1U) 8.17 - boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); 8.18 + boot_cpu_physical_apicid = get_apic_id(); 8.19 8.20 Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid); 8.21 }
9.1 --- a/xen/arch/x86/nmi.c Thu May 01 11:30:42 2008 +0100 9.2 +++ b/xen/arch/x86/nmi.c Thu May 01 11:34:56 2008 +0100 9.3 @@ -434,14 +434,13 @@ void nmi_watchdog_tick(struct cpu_user_r 9.4 */ 9.5 static void do_nmi_trigger(unsigned char key) 9.6 { 9.7 - u32 id = GET_APIC_ID(apic_read(APIC_ID)); 9.8 + u32 id = get_apic_id(); 9.9 9.10 printk("Triggering NMI on APIC ID %x\n", id); 9.11 9.12 local_irq_disable(); 9.13 apic_wait_icr_idle(); 9.14 - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id)); 9.15 - apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_PHYSICAL); 9.16 + apic_icr_write(APIC_DM_NMI | APIC_DEST_PHYSICAL, id); 9.17 local_irq_enable(); 9.18 } 9.19
10.1 --- a/xen/arch/x86/setup.c Thu May 01 11:30:42 2008 +0100 10.2 +++ b/xen/arch/x86/setup.c Thu May 01 11:34:56 2008 +0100 10.3 @@ -890,6 +890,9 @@ void __init __start_xen(unsigned long mb 10.4 10.5 generic_apic_probe(); 10.6 10.7 + if ( x2apic_is_available() ) 10.8 + enable_x2apic(); 10.9 + 10.10 acpi_boot_init(); 10.11 10.12 init_cpu_to_node();
11.1 --- a/xen/arch/x86/shutdown.c Thu May 01 11:30:42 2008 +0100 11.2 +++ b/xen/arch/x86/shutdown.c Thu May 01 11:34:56 2008 +0100 11.3 @@ -209,7 +209,7 @@ void machine_restart(void) 11.4 local_irq_enable(); 11.5 11.6 /* Ensure we are the boot CPU. */ 11.7 - if ( GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_physical_apicid ) 11.8 + if ( get_apic_id() != boot_cpu_physical_apicid ) 11.9 { 11.10 /* Send IPI to the boot CPU (logical cpu 0). */ 11.11 on_selected_cpus(cpumask_of_cpu(0), (void *)machine_restart,
12.1 --- a/xen/arch/x86/smp.c Thu May 01 11:30:42 2008 +0100 12.2 +++ b/xen/arch/x86/smp.c Thu May 01 11:34:56 2008 +0100 12.3 @@ -72,11 +72,14 @@ static inline int __prepare_ICR (unsigne 12.4 12.5 static inline int __prepare_ICR2 (unsigned int mask) 12.6 { 12.7 - return SET_APIC_DEST_FIELD(mask); 12.8 + return SET_xAPIC_DEST_FIELD(mask); 12.9 } 12.10 12.11 void apic_wait_icr_idle(void) 12.12 { 12.13 + if ( x2apic_enabled ) 12.14 + return; 12.15 + 12.16 while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY ) 12.17 cpu_relax(); 12.18 }
13.1 --- a/xen/arch/x86/smpboot.c Thu May 01 11:30:42 2008 +0100 13.2 +++ b/xen/arch/x86/smpboot.c Thu May 01 11:34:56 2008 +0100 13.3 @@ -325,10 +325,13 @@ void __devinit smp_callin(void) 13.4 */ 13.5 wait_for_init_deassert(&init_deasserted); 13.6 13.7 + if ( x2apic_is_available() ) 13.8 + enable_x2apic(); 13.9 + 13.10 /* 13.11 * (This works even if the APIC is not enabled.) 13.12 */ 13.13 - phys_id = GET_APIC_ID(apic_read(APIC_ID)); 13.14 + phys_id = get_apic_id(); 13.15 cpuid = smp_processor_id(); 13.16 if (cpu_isset(cpuid, cpu_callin_map)) { 13.17 printk("huh, phys CPU#%d, CPU#%d already present??\n", 13.18 @@ -548,7 +551,7 @@ u32 cpu_2_logical_apicid[NR_CPUS] __read 13.19 static void map_cpu_to_logical_apicid(void) 13.20 { 13.21 int cpu = smp_processor_id(); 13.22 - int apicid = hard_smp_processor_id(); 13.23 + int apicid = logical_smp_processor_id(); 13.24 13.25 cpu_2_logical_apicid[cpu] = apicid; 13.26 } 13.27 @@ -575,8 +578,7 @@ static inline void __inquire_remote_apic 13.28 */ 13.29 apic_wait_icr_idle(); 13.30 13.31 - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); 13.32 - apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]); 13.33 + apic_icr_write(APIC_DM_REMRD | regs[i], apicid); 13.34 13.35 timeout = 0; 13.36 do { 13.37 @@ -597,6 +599,21 @@ static inline void __inquire_remote_apic 13.38 #endif 13.39 13.40 #ifdef WAKE_SECONDARY_VIA_NMI 13.41 + 13.42 +static int logical_apicid_to_cpu(int logical_apicid) 13.43 +{ 13.44 + int i; 13.45 + 13.46 + for ( i = 0; i < sizeof(cpu_2_logical_apicid); i++ ) 13.47 + if ( cpu_2_logical_apicid[i] == logical_apicid ) 13.48 + break; 13.49 + 13.50 + if ( i == sizeof(cpu_2_logical_apicid) ); 13.51 + i = -1; /* not found */ 13.52 + 13.53 + return i; 13.54 +} 13.55 + 13.56 /* 13.57 * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal 13.58 * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this 13.59 @@ -607,20 +624,26 @@ wakeup_secondary_cpu(int logical_apicid, 13.60 { 13.61 unsigned long send_status = 0, accept_status = 0; 13.62 int timeout, maxlvt; 13.63 + int dest_cpu; 13.64 + u32 dest; 13.65 13.66 - /* Target chip */ 13.67 - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid)); 13.68 + dest_cpu = logical_apicid_to_cpu(logical_apicid); 13.69 + BUG_ON(dest_cpu == -1); 13.70 + 13.71 + dest = cpu_physical_id(dest_cpu); 13.72 13.73 /* Boot on the stack */ 13.74 - /* Kick the second */ 13.75 - apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL); 13.76 + apic_icr_write(APIC_DM_NMI | APIC_DEST_PHYSICAL, dest_cpu); 13.77 13.78 Dprintk("Waiting for send to finish...\n"); 13.79 timeout = 0; 13.80 do { 13.81 Dprintk("+"); 13.82 udelay(100); 13.83 - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; 13.84 + if ( !x2apic_enabled ) 13.85 + send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; 13.86 + else 13.87 + send_status = 0; /* We go out of the loop directly. */ 13.88 } while (send_status && (timeout++ < 1000)); 13.89 13.90 /* 13.91 @@ -666,40 +689,37 @@ wakeup_secondary_cpu(int phys_apicid, un 13.92 Dprintk("Asserting INIT.\n"); 13.93 13.94 /* 13.95 - * Turn INIT on target chip 13.96 + * Turn INIT on target chip via IPI 13.97 */ 13.98 - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); 13.99 - 13.100 - /* 13.101 - * Send IPI 13.102 - */ 13.103 - apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT 13.104 - | APIC_DM_INIT); 13.105 + apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT, 13.106 + phys_apicid); 13.107 13.108 Dprintk("Waiting for send to finish...\n"); 13.109 timeout = 0; 13.110 do { 13.111 Dprintk("+"); 13.112 udelay(100); 13.113 - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; 13.114 + if ( !x2apic_enabled ) 13.115 + send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; 13.116 + else 13.117 + send_status = 0; /* We go out of the loop dirctly. */ 13.118 } while (send_status && (timeout++ < 1000)); 13.119 13.120 mdelay(10); 13.121 13.122 Dprintk("Deasserting INIT.\n"); 13.123 13.124 - /* Target chip */ 13.125 - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); 13.126 - 13.127 - /* Send IPI */ 13.128 - apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT); 13.129 + apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid); 13.130 13.131 Dprintk("Waiting for send to finish...\n"); 13.132 timeout = 0; 13.133 do { 13.134 Dprintk("+"); 13.135 udelay(100); 13.136 - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; 13.137 + if ( !x2apic_enabled ) 13.138 + send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; 13.139 + else 13.140 + send_status = 0; /* We go out of the loop dirctly. */ 13.141 } while (send_status && (timeout++ < 1000)); 13.142 13.143 atomic_set(&init_deasserted, 1); 13.144 @@ -731,15 +751,9 @@ wakeup_secondary_cpu(int phys_apicid, un 13.145 13.146 /* 13.147 * STARTUP IPI 13.148 + * Boot on the stack 13.149 */ 13.150 - 13.151 - /* Target chip */ 13.152 - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid)); 13.153 - 13.154 - /* Boot on the stack */ 13.155 - /* Kick the second */ 13.156 - apic_write_around(APIC_ICR, APIC_DM_STARTUP 13.157 - | (start_eip >> 12)); 13.158 + apic_icr_write(APIC_DM_STARTUP | (start_eip >> 12), phys_apicid); 13.159 13.160 /* 13.161 * Give the other CPU some time to accept the IPI. 13.162 @@ -753,7 +767,10 @@ wakeup_secondary_cpu(int phys_apicid, un 13.163 do { 13.164 Dprintk("+"); 13.165 udelay(100); 13.166 - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; 13.167 + if ( !x2apic_enabled ) 13.168 + send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; 13.169 + else 13.170 + send_status = 0; /* We go out of the loop dirctly. */ 13.171 } while (send_status && (timeout++ < 1000)); 13.172 13.173 /* 13.174 @@ -988,7 +1005,7 @@ static void __init smp_boot_cpus(unsigne 13.175 printk("CPU%d: ", 0); 13.176 print_cpu_info(&cpu_data[0]); 13.177 13.178 - boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); 13.179 + boot_cpu_physical_apicid = get_apic_id(); 13.180 x86_cpu_to_apicid[0] = boot_cpu_physical_apicid; 13.181 13.182 stack_base[0] = stack_start.esp;
14.1 --- a/xen/include/asm-x86/apic.h Thu May 01 11:30:42 2008 +0100 14.2 +++ b/xen/include/asm-x86/apic.h Thu May 01 11:34:56 2008 +0100 14.3 @@ -16,6 +16,21 @@ 14.4 #define APIC_DEBUG 2 14.5 14.6 extern int apic_verbosity; 14.7 +extern int x2apic_enabled; 14.8 + 14.9 +extern void enable_x2apic(void); 14.10 + 14.11 +static __inline int x2apic_is_available(void) 14.12 +{ 14.13 + unsigned int op = 1, eax, ecx; 14.14 + 14.15 + asm ( "cpuid" 14.16 + : "=a" (eax), "=c" (ecx) 14.17 + : "0" (op) 14.18 + : "bx", "dx" ); 14.19 + 14.20 + return (ecx & (1U << 21)); 14.21 +} 14.22 14.23 /* 14.24 * Define the default level of output to be very little 14.25 @@ -35,19 +50,103 @@ extern int apic_verbosity; 14.26 * Basic functions accessing APICs. 14.27 */ 14.28 14.29 +static __inline void apic_mem_write(unsigned long reg, u32 v) 14.30 +{ 14.31 + *((volatile u32 *)(APIC_BASE+reg)) = v; 14.32 +} 14.33 + 14.34 +static __inline void apic_mem_write_atomic(unsigned long reg, u32 v) 14.35 +{ 14.36 + (void)xchg((volatile u32 *)(APIC_BASE+reg), v); 14.37 +} 14.38 + 14.39 +static __inline u32 apic_mem_read(unsigned long reg) 14.40 +{ 14.41 + return *((volatile u32 *)(APIC_BASE+reg)); 14.42 +} 14.43 + 14.44 +/* NOTE: in x2APIC mode, we should use apic_icr_write()/apic_icr_read() to 14.45 + * access the 64-bit ICR register. 14.46 + */ 14.47 + 14.48 +static __inline void apic_wrmsr(unsigned long reg, u32 low, u32 high) 14.49 +{ 14.50 + __asm__ __volatile__("wrmsr" 14.51 + : /* no outputs */ 14.52 + : "c" (APIC_MSR_BASE + (reg >> 4)), "a" (low), "d" (high)); 14.53 +} 14.54 + 14.55 +static __inline void apic_rdmsr(unsigned long reg, u32 *low, u32 *high) 14.56 +{ 14.57 + __asm__ __volatile__("rdmsr" 14.58 + : "=a" (*low), "=d" (*high) 14.59 + : "c" (APIC_MSR_BASE + (reg >> 4))); 14.60 +} 14.61 + 14.62 static __inline void apic_write(unsigned long reg, u32 v) 14.63 { 14.64 - *((volatile u32 *)(APIC_BASE+reg)) = v; 14.65 + 14.66 + if ( x2apic_enabled ) 14.67 + apic_wrmsr(reg, v, 0); 14.68 + else 14.69 + apic_mem_write(reg, v); 14.70 } 14.71 14.72 static __inline void apic_write_atomic(unsigned long reg, u32 v) 14.73 { 14.74 - (void)xchg((volatile u32 *)(APIC_BASE+reg), v); 14.75 + if ( x2apic_enabled ) 14.76 + apic_wrmsr(reg, v, 0); 14.77 + else 14.78 + apic_mem_write_atomic(reg, v); 14.79 } 14.80 14.81 static __inline u32 apic_read(unsigned long reg) 14.82 { 14.83 - return *((volatile u32 *)(APIC_BASE+reg)); 14.84 + u32 lo, hi; 14.85 + 14.86 + if ( x2apic_enabled ) 14.87 + apic_rdmsr(reg, &lo, &hi); 14.88 + else 14.89 + lo = apic_mem_read(reg); 14.90 + return lo; 14.91 +} 14.92 + 14.93 +static __inline u64 apic_icr_read(void) 14.94 +{ 14.95 + u32 lo, hi; 14.96 + 14.97 + if ( x2apic_enabled ) 14.98 + apic_rdmsr(APIC_ICR, &lo, &hi); 14.99 + else 14.100 + { 14.101 + lo = apic_mem_read(APIC_ICR); 14.102 + hi = apic_mem_read(APIC_ICR2); 14.103 + } 14.104 + 14.105 + return ((u64)lo) | (((u64)hi) << 32); 14.106 +} 14.107 + 14.108 +static __inline void apic_icr_write(u32 low, u32 dest) 14.109 +{ 14.110 + if ( x2apic_enabled ) 14.111 + apic_wrmsr(APIC_ICR, low, dest); 14.112 + else 14.113 + { 14.114 + apic_mem_write(APIC_ICR2, dest << 24); 14.115 + apic_mem_write(APIC_ICR, low); 14.116 + } 14.117 +} 14.118 + 14.119 +static __inline u32 get_apic_id(void) /* Get the physical APIC id */ 14.120 +{ 14.121 + u32 id = apic_read(APIC_ID); 14.122 + return x2apic_enabled ? id : GET_xAPIC_ID(id); 14.123 +} 14.124 + 14.125 +static __inline u32 get_logical_apic_id(void) 14.126 +{ 14.127 + u32 logical_id = apic_read(APIC_LDR); 14.128 + return x2apic_enabled ? logical_id : GET_xAPIC_LOGICAL_ID(logical_id); 14.129 } 14.130 14.131 void apic_wait_icr_idle(void);
15.1 --- a/xen/include/asm-x86/apicdef.h Thu May 01 11:30:42 2008 +0100 15.2 +++ b/xen/include/asm-x86/apicdef.h Thu May 01 11:34:56 2008 +0100 15.3 @@ -12,8 +12,8 @@ 15.4 15.5 #define APIC_ID 0x20 15.6 #define APIC_ID_MASK (0xFFu<<24) 15.7 -#define GET_APIC_ID(x) (((x)>>24)&0xFFu) 15.8 -#define SET_APIC_ID(x) (((x)<<24)) 15.9 +#define GET_xAPIC_ID(x) (((x)>>24)&0xFFu) 15.10 +#define SET_xAPIC_ID(x) (((x)<<24)) 15.11 #define APIC_LVR 0x30 15.12 #define APIC_LVR_MASK 0xFF00FF 15.13 #define GET_APIC_VERSION(x) ((x)&0xFF) 15.14 @@ -30,8 +30,8 @@ 15.15 #define APIC_RRR 0xC0 15.16 #define APIC_LDR 0xD0 15.17 #define APIC_LDR_MASK (0xFF<<24) 15.18 -#define GET_APIC_LOGICAL_ID(x) (((x)>>24)&0xFF) 15.19 -#define SET_APIC_LOGICAL_ID(x) (((x)<<24)) 15.20 +#define GET_xAPIC_LOGICAL_ID(x) (((x)>>24)&0xFF) 15.21 +#define SET_xAPIC_LOGICAL_ID(x) (((x)<<24)) 15.22 #define APIC_ALL_CPUS 0xFF 15.23 #define APIC_DFR 0xE0 15.24 #define APIC_DFR_CLUSTER 0x0FFFFFFFul 15.25 @@ -74,8 +74,8 @@ 15.26 #define APIC_DM_EXTINT 0x00700 15.27 #define APIC_VECTOR_MASK 0x000FF 15.28 #define APIC_ICR2 0x310 15.29 -#define GET_APIC_DEST_FIELD(x) (((x)>>24)&0xFF) 15.30 -#define SET_APIC_DEST_FIELD(x) ((x)<<24) 15.31 +#define GET_xAPIC_DEST_FIELD(x) (((x)>>24)&0xFF) 15.32 +#define SET_xAPIC_DEST_FIELD(x) ((x)<<24) 15.33 #define APIC_LVTT 0x320 15.34 #define APIC_LVTTHMR 0x330 15.35 #define APIC_LVTPC 0x340 15.36 @@ -103,6 +103,10 @@ 15.37 #define APIC_TMICT 0x380 15.38 #define APIC_TMCCT 0x390 15.39 #define APIC_TDCR 0x3E0 15.40 + 15.41 +/* Only available in x2APIC mode */ 15.42 +#define APIC_SELF_IPI 0x400 15.43 + 15.44 #define APIC_TDR_DIV_TMBASE (1<<2) 15.45 #define APIC_TDR_DIV_1 0xB 15.46 #define APIC_TDR_DIV_2 0x0 15.47 @@ -115,6 +119,9 @@ 15.48 15.49 #define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) 15.50 15.51 +/* It's only used in x2APIC mode of an x2APIC unit. */ 15.52 +#define APIC_MSR_BASE 0x800 15.53 + 15.54 #ifdef __i386__ 15.55 #define MAX_IO_APICS 64 15.56 #else
16.1 --- a/xen/include/asm-x86/cpufeature.h Thu May 01 11:30:42 2008 +0100 16.2 +++ b/xen/include/asm-x86/cpufeature.h Thu May 01 11:34:56 2008 +0100 16.3 @@ -92,6 +92,7 @@ 16.4 #define X86_FEATURE_DCA (4*32+18) /* Direct Cache Access */ 16.5 #define X86_FEATURE_SSE4_1 (4*32+19) /* Streaming SIMD Extensions 4.1 */ 16.6 #define X86_FEATURE_SSE4_2 (4*32+20) /* Streaming SIMD Extensions 4.2 */ 16.7 +#define X86_FEATURE_X2APIC (4*32+21) /* Extended xAPIC */ 16.8 #define X86_FEATURE_POPCNT (4*32+23) /* POPCNT instruction */ 16.9 16.10 /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ 16.11 @@ -182,6 +183,7 @@ 16.12 #define cpu_has_ffxsr ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) \ 16.13 && boot_cpu_has(X86_FEATURE_FFXSR)) 16.14 16.15 +#define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC) 16.16 #endif /* __ASM_I386_CPUFEATURE_H */ 16.17 16.18 /*
17.1 --- a/xen/include/asm-x86/genapic.h Thu May 01 11:30:42 2008 +0100 17.2 +++ b/xen/include/asm-x86/genapic.h Thu May 01 11:34:56 2008 +0100 17.3 @@ -62,6 +62,20 @@ void send_IPI_mask_flat(cpumask_t mask, 17.4 .cpu_mask_to_apicid = cpu_mask_to_apicid_flat, \ 17.5 .send_IPI_mask = send_IPI_mask_flat 17.6 17.7 +void init_apic_ldr_x2apic(void); 17.8 +void clustered_apic_check_x2apic(void); 17.9 +cpumask_t target_cpus_x2apic(void); 17.10 +unsigned int cpu_mask_to_apicid_x2apic(cpumask_t cpumask); 17.11 +void send_IPI_mask_x2apic(cpumask_t mask, int vector); 17.12 +#define GENAPIC_X2APIC \ 17.13 + .int_delivery_mode = dest_Fixed, \ 17.14 + .int_dest_mode = 0 /* physical delivery */, \ 17.15 + .init_apic_ldr = init_apic_ldr_x2apic, \ 17.16 + .clustered_apic_check = clustered_apic_check_x2apic, \ 17.17 + .target_cpus = target_cpus_x2apic, \ 17.18 + .cpu_mask_to_apicid = cpu_mask_to_apicid_x2apic, \ 17.19 + .send_IPI_mask = send_IPI_mask_x2apic 17.20 + 17.21 void init_apic_ldr_phys(void); 17.22 void clustered_apic_check_phys(void); 17.23 cpumask_t target_cpus_phys(void);
18.1 --- a/xen/include/asm-x86/hvm/vlapic.h Thu May 01 11:30:42 2008 +0100 18.2 +++ b/xen/include/asm-x86/hvm/vlapic.h Thu May 01 11:34:56 2008 +0100 18.3 @@ -34,7 +34,7 @@ 18.4 #define vlapic_domain(vpic) (vlapic_vcpu(vlapic)->domain) 18.5 18.6 #define VLAPIC_ID(vlapic) \ 18.7 - (GET_APIC_ID(vlapic_get_reg((vlapic), APIC_ID))) 18.8 + (GET_xAPIC_ID(vlapic_get_reg((vlapic), APIC_ID))) 18.9 18.10 /* 18.11 * APIC can be disabled in two ways:
19.1 --- a/xen/include/asm-x86/mach-generic/mach_apic.h Thu May 01 11:30:42 2008 +0100 19.2 +++ b/xen/include/asm-x86/mach-generic/mach_apic.h Thu May 01 11:34:56 2008 +0100 19.3 @@ -62,7 +62,7 @@ extern void generic_bigsmp_probe(void); 19.4 */ 19.5 static inline int apic_id_registered(void) 19.6 { 19.7 - return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), 19.8 + return physid_isset(get_apic_id(), 19.9 phys_cpu_present_map); 19.10 } 19.11
20.1 --- a/xen/include/asm-x86/msr-index.h Thu May 01 11:30:42 2008 +0100 20.2 +++ b/xen/include/asm-x86/msr-index.h Thu May 01 11:34:56 2008 +0100 20.3 @@ -236,6 +236,7 @@ 20.4 20.5 #define MSR_IA32_APICBASE 0x0000001b 20.6 #define MSR_IA32_APICBASE_BSP (1<<8) 20.7 +#define MSR_IA32_APICBASE_EXTD (1<<10) 20.8 #define MSR_IA32_APICBASE_ENABLE (1<<11) 20.9 #define MSR_IA32_APICBASE_BASE (0xfffff<<12) 20.10
21.1 --- a/xen/include/asm-x86/smp.h Thu May 01 11:30:42 2008 +0100 21.2 +++ b/xen/include/asm-x86/smp.h Thu May 01 11:34:56 2008 +0100 21.3 @@ -90,13 +90,13 @@ static inline int num_booting_cpus(void) 21.4 static inline int hard_smp_processor_id(void) 21.5 { 21.6 /* we don't want to mark this access volatile - bad code generation */ 21.7 - return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID)); 21.8 + return get_apic_id(); 21.9 } 21.10 21.11 static __inline int logical_smp_processor_id(void) 21.12 { 21.13 /* we don't want to mark this access volatile - bad code generation */ 21.14 - return GET_APIC_LOGICAL_ID(*(unsigned int *)(APIC_BASE+APIC_LDR)); 21.15 + return get_logical_apic_id(); 21.16 } 21.17 21.18 #endif