ia64/xen-unstable

changeset 17552:9fd00ff95068

x86: Support x2APIC mode.
Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu May 01 11:34:56 2008 +0100 (2008-05-01)
parents f13ff27fa0d1
children 806e7fa30264
files xen/arch/x86/apic.c xen/arch/x86/genapic/Makefile xen/arch/x86/genapic/delivery.c xen/arch/x86/genapic/probe.c xen/arch/x86/genapic/x2apic.c xen/arch/x86/hvm/vlapic.c xen/arch/x86/io_apic.c xen/arch/x86/mpparse.c xen/arch/x86/nmi.c xen/arch/x86/setup.c xen/arch/x86/shutdown.c xen/arch/x86/smp.c xen/arch/x86/smpboot.c xen/include/asm-x86/apic.h xen/include/asm-x86/apicdef.h xen/include/asm-x86/cpufeature.h xen/include/asm-x86/genapic.h xen/include/asm-x86/hvm/vlapic.h xen/include/asm-x86/mach-generic/mach_apic.h xen/include/asm-x86/msr-index.h xen/include/asm-x86/smp.h
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_write(unsigned long reg, u32 v)
   14.30 +static __inline void apic_mem_write(unsigned long reg, u32 v)
   14.31  {
   14.32  	*((volatile u32 *)(APIC_BASE+reg)) = v;
   14.33  }
   14.34  
   14.35 -static __inline void apic_write_atomic(unsigned long reg, u32 v)
   14.36 +static __inline void apic_mem_write_atomic(unsigned long reg, u32 v)
   14.37  {
   14.38  	(void)xchg((volatile u32 *)(APIC_BASE+reg), v);
   14.39  }
   14.40  
   14.41 +static __inline u32 apic_mem_read(unsigned long reg)
   14.42 +{
   14.43 +	return *((volatile u32 *)(APIC_BASE+reg));
   14.44 +}
   14.45 +
   14.46 +/* NOTE: in x2APIC mode, we should use apic_icr_write()/apic_icr_read() to
   14.47 + * access the 64-bit ICR register.
   14.48 + */
   14.49 +
   14.50 +static __inline void apic_wrmsr(unsigned long reg, u32 low, u32 high)
   14.51 +{
   14.52 +    __asm__ __volatile__("wrmsr"
   14.53 +            : /* no outputs */
   14.54 +            : "c" (APIC_MSR_BASE + (reg >> 4)), "a" (low), "d" (high));
   14.55 +}
   14.56 +
   14.57 +static __inline void apic_rdmsr(unsigned long reg, u32 *low, u32 *high)
   14.58 +{
   14.59 +    __asm__ __volatile__("rdmsr"
   14.60 +            : "=a" (*low), "=d" (*high)
   14.61 +            : "c" (APIC_MSR_BASE + (reg >> 4)));
   14.62 +}
   14.63 +
   14.64 +static __inline void apic_write(unsigned long reg, u32 v)
   14.65 +{
   14.66 +
   14.67 +    if ( x2apic_enabled )
   14.68 +        apic_wrmsr(reg, v, 0);
   14.69 +    else
   14.70 +        apic_mem_write(reg, v);
   14.71 +}
   14.72 +
   14.73 +static __inline void apic_write_atomic(unsigned long reg, u32 v)
   14.74 +{
   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