]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'stable/generic' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 10 Jan 2011 16:48:29 +0000 (08:48 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 10 Jan 2011 16:48:29 +0000 (08:48 -0800)
* 'stable/generic' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
  xen: HVM X2APIC support
  apic: Move hypervisor detection of x2apic to hypervisor.h

1  2 
arch/x86/kernel/apic/apic.c
arch/x86/xen/enlighten.c

index 79e6baa8aa0a77f323051b1f67a2037aad3b9817,8408f2d19819a2c1635f54e022c429c7decde1b3..a51345ba449e90a280e8fa1cdce90755abba4c26
@@@ -31,6 -31,7 +31,6 @@@
  #include <linux/init.h>
  #include <linux/cpu.h>
  #include <linux/dmi.h>
 -#include <linux/nmi.h>
  #include <linux/smp.h>
  #include <linux/mm.h>
  
@@@ -49,8 -50,8 +49,8 @@@
  #include <asm/mtrr.h>
  #include <asm/smp.h>
  #include <asm/mce.h>
- #include <asm/kvm_para.h>
  #include <asm/tsc.h>
+ #include <asm/hypervisor.h>
  
  unsigned int num_processors;
  
@@@ -431,18 -432,17 +431,18 @@@ int setup_APIC_eilvt(u8 offset, u8 vect
        reserved = reserve_eilvt_offset(offset, new);
  
        if (reserved != new) {
 -              pr_err(FW_BUG "cpu %d, try to setup vector 0x%x, but "
 -                     "vector 0x%x was already reserved by another core, "
 -                     "APIC%lX=0x%x\n",
 -                     smp_processor_id(), new, reserved, reg, old);
 +              pr_err(FW_BUG "cpu %d, try to use APIC%lX (LVT offset %d) for "
 +                     "vector 0x%x, but the register is already in use for "
 +                     "vector 0x%x on another cpu\n",
 +                     smp_processor_id(), reg, offset, new, reserved);
                return -EINVAL;
        }
  
        if (!eilvt_entry_is_changeable(old, new)) {
 -              pr_err(FW_BUG "cpu %d, try to setup vector 0x%x but "
 -                     "register already in use, APIC%lX=0x%x\n",
 -                     smp_processor_id(), new, reg, old);
 +              pr_err(FW_BUG "cpu %d, try to use APIC%lX (LVT offset %d) for "
 +                     "vector 0x%x, but the register is already in use for "
 +                     "vector 0x%x on this cpu\n",
 +                     smp_processor_id(), reg, offset, new, old);
                return -EBUSY;
        }
  
@@@ -516,7 -516,7 +516,7 @@@ static void __cpuinit setup_APIC_timer(
  {
        struct clock_event_device *levt = &__get_cpu_var(lapic_events);
  
 -      if (cpu_has(&current_cpu_data, X86_FEATURE_ARAT)) {
 +      if (cpu_has(__this_cpu_ptr(&cpu_info), X86_FEATURE_ARAT)) {
                lapic_clockevent.features &= ~CLOCK_EVT_FEAT_C3STOP;
                /* Make LAPIC timer preferrable over percpu HPET */
                lapic_clockevent.rating = 150;
@@@ -799,7 -799,11 +799,7 @@@ void __init setup_boot_APIC_clock(void
         * PIT/HPET going.  Otherwise register lapic as a dummy
         * device.
         */
 -      if (nmi_watchdog != NMI_IO_APIC)
 -              lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
 -      else
 -              pr_warning("APIC timer registered as dummy,"
 -                      " due to nmi_watchdog=%d!\n", nmi_watchdog);
 +      lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
  
        /* Setup the lapic or request the broadcast */
        setup_APIC_timer();
@@@ -1191,15 -1195,12 +1191,15 @@@ static void __cpuinit lapic_setup_esr(v
                        oldvalue, value);
  }
  
 -
  /**
   * setup_local_APIC - setup the local APIC
 + *
 + * Used to setup local APIC while initializing BSP or bringin up APs.
 + * Always called with preemption disabled.
   */
  void __cpuinit setup_local_APIC(void)
  {
 +      int cpu = smp_processor_id();
        unsigned int value, queued;
        int i, j, acked = 0;
        unsigned long long tsc = 0, ntsc;
  #endif
        perf_events_lapic_init();
  
 -      preempt_disable();
 -
        /*
         * Double-check whether this APIC is really registered.
         * This is meaningless in clustered apic mode, so we skip it.
         * TODO: set up through-local-APIC from through-I/O-APIC? --macro
         */
        value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
 -      if (!smp_processor_id() && (pic_mode || !value)) {
 +      if (!cpu && (pic_mode || !value)) {
                value = APIC_DM_EXTINT;
 -              apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n",
 -                              smp_processor_id());
 +              apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", cpu);
        } else {
                value = APIC_DM_EXTINT | APIC_LVT_MASKED;
 -              apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n",
 -                              smp_processor_id());
 +              apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", cpu);
        }
        apic_write(APIC_LVT0, value);
  
        /*
         * only the BP should see the LINT1 NMI signal, obviously.
         */
 -      if (!smp_processor_id())
 +      if (!cpu)
                value = APIC_DM_NMI;
        else
                value = APIC_DM_NMI | APIC_LVT_MASKED;
                value |= APIC_LVT_LEVEL_TRIGGER;
        apic_write(APIC_LVT1, value);
  
 -      preempt_enable();
 -
  #ifdef CONFIG_X86_MCE_INTEL
        /* Recheck CMCI information after local APIC is up on CPU #0 */
 -      if (smp_processor_id() == 0)
 +      if (!cpu)
                cmci_recheck();
  #endif
  }
@@@ -1380,15 -1387,8 +1380,15 @@@ void __cpuinit end_local_APIC_setup(voi
        }
  #endif
  
 -      setup_apic_nmi_watchdog(NULL);
        apic_pm_activate();
 +
 +      /*
 +       * Now that local APIC setup is completed for BP, configure the fault
 +       * handling for interrupt remapping.
 +       */
 +      if (!smp_processor_id() && intr_remapping_enabled)
 +              enable_drhd_fault_handling();
 +
  }
  
  #ifdef CONFIG_X86_X2APIC
@@@ -1476,7 -1476,8 +1476,8 @@@ void __init enable_IR_x2apic(void
                /* IR is required if there is APIC ID > 255 even when running
                 * under KVM
                 */
-               if (max_physical_apicid > 255 || !kvm_para_available())
+               if (max_physical_apicid > 255 ||
+                   !hypervisor_x2apic_available())
                        goto nox2apic;
                /*
                 * without IR all CPUs can be addressed by IOAPIC/MSI
@@@ -1530,60 -1531,13 +1531,60 @@@ static int __init detect_init_APIC(void
        return 0;
  }
  #else
 +
 +static int apic_verify(void)
 +{
 +      u32 features, h, l;
 +
 +      /*
 +       * The APIC feature bit should now be enabled
 +       * in `cpuid'
 +       */
 +      features = cpuid_edx(1);
 +      if (!(features & (1 << X86_FEATURE_APIC))) {
 +              pr_warning("Could not enable APIC!\n");
 +              return -1;
 +      }
 +      set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
 +      mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
 +
 +      /* The BIOS may have set up the APIC at some other address */
 +      rdmsr(MSR_IA32_APICBASE, l, h);
 +      if (l & MSR_IA32_APICBASE_ENABLE)
 +              mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
 +
 +      pr_info("Found and enabled local APIC!\n");
 +      return 0;
 +}
 +
 +int apic_force_enable(void)
 +{
 +      u32 h, l;
 +
 +      if (disable_apic)
 +              return -1;
 +
 +      /*
 +       * Some BIOSes disable the local APIC in the APIC_BASE
 +       * MSR. This can only be done in software for Intel P6 or later
 +       * and AMD K7 (Model > 1) or later.
 +       */
 +      rdmsr(MSR_IA32_APICBASE, l, h);
 +      if (!(l & MSR_IA32_APICBASE_ENABLE)) {
 +              pr_info("Local APIC disabled by BIOS -- reenabling.\n");
 +              l &= ~MSR_IA32_APICBASE_BASE;
 +              l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
 +              wrmsr(MSR_IA32_APICBASE, l, h);
 +              enabled_via_apicbase = 1;
 +      }
 +      return apic_verify();
 +}
 +
  /*
   * Detect and initialize APIC
   */
  static int __init detect_init_APIC(void)
  {
 -      u32 h, l, features;
 -
        /* Disabled by kernel option? */
        if (disable_apic)
                return -1;
                                "you can enable it with \"lapic\"\n");
                        return -1;
                }
 -              /*
 -               * Some BIOSes disable the local APIC in the APIC_BASE
 -               * MSR. This can only be done in software for Intel P6 or later
 -               * and AMD K7 (Model > 1) or later.
 -               */
 -              rdmsr(MSR_IA32_APICBASE, l, h);
 -              if (!(l & MSR_IA32_APICBASE_ENABLE)) {
 -                      pr_info("Local APIC disabled by BIOS -- reenabling.\n");
 -                      l &= ~MSR_IA32_APICBASE_BASE;
 -                      l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
 -                      wrmsr(MSR_IA32_APICBASE, l, h);
 -                      enabled_via_apicbase = 1;
 -              }
 -      }
 -      /*
 -       * The APIC feature bit should now be enabled
 -       * in `cpuid'
 -       */
 -      features = cpuid_edx(1);
 -      if (!(features & (1 << X86_FEATURE_APIC))) {
 -              pr_warning("Could not enable APIC!\n");
 -              return -1;
 +              if (apic_force_enable())
 +                      return -1;
 +      } else {
 +              if (apic_verify())
 +                      return -1;
        }
 -      set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
 -      mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
 -
 -      /* The BIOS may have set up the APIC at some other address */
 -      rdmsr(MSR_IA32_APICBASE, l, h);
 -      if (l & MSR_IA32_APICBASE_ENABLE)
 -              mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
 -
 -      pr_info("Found and enabled local APIC!\n");
  
        apic_pm_activate();
  
@@@ -1630,6 -1610,28 +1631,6 @@@ no_apic
  }
  #endif
  
 -#ifdef CONFIG_X86_64
 -void __init early_init_lapic_mapping(void)
 -{
 -      /*
 -       * If no local APIC can be found then go out
 -       * : it means there is no mpatable and MADT
 -       */
 -      if (!smp_found_config)
 -              return;
 -
 -      set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
 -      apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
 -                  APIC_BASE, mp_lapic_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
   */
@@@ -1655,7 -1657,10 +1656,7 @@@ void __init init_apic_mappings(void
                 * acpi_register_lapic_address()
                 */
                if (!acpi_lapic && !smp_found_config)
 -                      set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
 -
 -              apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n",
 -                                      APIC_BASE, apic_phys);
 +                      register_lapic_address(apic_phys);
        }
  
        /*
        }
  }
  
 +void __init register_lapic_address(unsigned long address)
 +{
 +      mp_lapic_addr = address;
 +
 +      if (!x2apic_mode) {
 +              set_fixmap_nocache(FIX_APIC_BASE, address);
 +              apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
 +                          APIC_BASE, mp_lapic_addr);
 +      }
 +      if (boot_cpu_physical_apicid == -1U) {
 +              boot_cpu_physical_apicid  = read_apic_id();
 +              apic_version[boot_cpu_physical_apicid] =
 +                       GET_APIC_VERSION(apic_read(APIC_LVR));
 +      }
 +}
 +
  /*
   * This initializes the IO-APIC and APIC hardware if this is
   * a UP kernel.
   */
 -int apic_version[MAX_APICS];
 +int apic_version[MAX_LOCAL_APIC];
  
  int __init APIC_init_uniprocessor(void)
  {
                setup_IO_APIC();
        else {
                nr_ioapics = 0;
 -              localise_nmi_watchdog();
        }
 -#else
 -      localise_nmi_watchdog();
  #endif
  
        x86_init.timers.setup_percpu_clockev();
 -#ifdef CONFIG_X86_64
 -      check_nmi_watchdog();
 -#endif
 -
        return 0;
  }
  
diff --combined arch/x86/xen/enlighten.c
index aa8c89ae54cfaf08318b3d9718187dbaa4c41c24,5b8986fe3371a3be66eadb3bfac127598f7df5ae..6aba2a23e2c312520244ee4235c112b71de3378d
@@@ -574,8 -574,8 +574,8 @@@ static void xen_write_idt_entry(gate_de
  
        preempt_disable();
  
 -      start = __get_cpu_var(idt_desc).address;
 -      end = start + __get_cpu_var(idt_desc).size + 1;
 +      start = __this_cpu_read(idt_desc.address);
 +      end = start + __this_cpu_read(idt_desc.size) + 1;
  
        xen_mc_flush();
  
@@@ -1256,25 -1256,6 +1256,6 @@@ asmlinkage void __init xen_start_kernel
  #endif
  }
  
- static uint32_t xen_cpuid_base(void)
- {
-       uint32_t base, eax, ebx, ecx, edx;
-       char signature[13];
-       for (base = 0x40000000; base < 0x40010000; base += 0x100) {
-               cpuid(base, &eax, &ebx, &ecx, &edx);
-               *(uint32_t *)(signature + 0) = ebx;
-               *(uint32_t *)(signature + 4) = ecx;
-               *(uint32_t *)(signature + 8) = edx;
-               signature[12] = 0;
-               if (!strcmp("XenVMMXenVMM", signature) && ((eax - base) >= 2))
-                       return base;
-       }
-       return 0;
- }
  static int init_hvm_pv_info(int *major, int *minor)
  {
        uint32_t eax, ebx, ecx, edx, pages, msr, base;
@@@ -1384,6 -1365,18 +1365,18 @@@ static bool __init xen_hvm_platform(voi
        return true;
  }
  
+ bool xen_hvm_need_lapic(void)
+ {
+       if (xen_pv_domain())
+               return false;
+       if (!xen_hvm_domain())
+               return false;
+       if (xen_feature(XENFEAT_hvm_pirqs) && xen_have_vector_callback)
+               return false;
+       return true;
+ }
+ EXPORT_SYMBOL_GPL(xen_hvm_need_lapic);
  const __refconst struct hypervisor_x86 x86_hyper_xen_hvm = {
        .name                   = "Xen HVM",
        .detect                 = xen_hvm_platform,