direct-io.hg

changeset 4548:8ce73ebd1311

bitkeeper revision 1.1308 (4260510bQdQyEJ4w-XdZSU5iSTB_Pg)

The attached patch apic.patch updates xen/arch/x86/apic.c so that it is based on linux 2.6.10 code. A few changes made to linux required reworking functions in other files as well so I held off on those changes. For example, setup_APIC_timer(void *) changed to setup_APIC_timer(unsigned int). The change has no real bearing on the Xen code -- it's just a question of how close to linux one wants to be. However, that change goes with a change to smp_call_function which would affect quite a few other files/functions so I left it as is. Most of the other changes are trivial.
xen/ac_timer.h was included but not needed by apic.c so I removed it from the list of #includes.

The new apic.c includes two new files: asm/io_ports.h and asm/mach_apic.h. Patches to create those files are included as well.
author iap10@freefall.cl.cam.ac.uk
date Fri Apr 15 23:40:59 2005 +0000 (2005-04-15)
parents 73ef7f1fc714
children d3c7465e457a
files .rootkeys xen/arch/x86/apic.c xen/include/asm-x86/io_ports.h xen/include/asm-x86/mach_apic.h
line diff
     1.1 --- a/.rootkeys	Fri Apr 15 23:32:51 2005 +0000
     1.2 +++ b/.rootkeys	Fri Apr 15 23:40:59 2005 +0000
     1.3 @@ -1323,8 +1323,10 @@ 3ddb79c3TMDjkxVndKFKnGiwY0HzDg xen/inclu
     1.4  4204e7acwXDo-5iAAiO2eQbtDeYZXA xen/include/asm-x86/init.h
     1.5  3ddb79c3fQ_O3o5NHK2N8AJdk0Ea4Q xen/include/asm-x86/io.h
     1.6  3ddb79c2TKeScYHQZreTdHqYNLbehQ xen/include/asm-x86/io_apic.h
     1.7 +42605109qxLSrHVE2SRhGXmgk907iw xen/include/asm-x86/io_ports.h
     1.8  3ddb79c2L7rTlFzazOLW1XuSZefpFw xen/include/asm-x86/irq.h
     1.9  404f1b93OjLO4bFfBXYNaJdIqlNz-Q xen/include/asm-x86/ldt.h
    1.10 +4260510aYPj2kr6rMbBfMxcvvmXndQ xen/include/asm-x86/mach_apic.h
    1.11  3ddb79c3I98vWcQR8xEo34JMJ4Ahyw xen/include/asm-x86/mc146818rtc.h
    1.12  40ec25fd7cSvbP7Biw91zaU_g0xsEQ xen/include/asm-x86/mm.h
    1.13  3ddb79c3n_UbPuxlkNxvvLycClIkxA xen/include/asm-x86/mpspec.h
     2.1 --- a/xen/arch/x86/apic.c	Fri Apr 15 23:32:51 2005 +0000
     2.2 +++ b/xen/arch/x86/apic.c	Fri Apr 15 23:40:59 2005 +0000
     2.3 @@ -1,4 +1,6 @@
     2.4  /*
     2.5 + *      based on linux-2.6.10/arch/i386/kernel/apic.c
     2.6 + *
     2.7   *  Local APIC handling, local APIC timers
     2.8   *
     2.9   *  (c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
    2.10 @@ -10,11 +12,11 @@
    2.11   *                  for testing these extensively.
    2.12   *	Maciej W. Rozycki	:	Various updates and fixes.
    2.13   *	Mikael Pettersson	:	Power Management for UP-APIC.
    2.14 + *    Pavel Machek and
    2.15 + *    Mikael Pettersson    :    PM converted to driver model.
    2.16   */
    2.17  
    2.18 -
    2.19  #include <xen/config.h>
    2.20 -#include <xen/ac_timer.h>
    2.21  #include <xen/perfc.h>
    2.22  #include <xen/errno.h>
    2.23  #include <xen/init.h>
    2.24 @@ -32,7 +34,8 @@
    2.25  #include <asm/hardirq.h>
    2.26  #include <asm/apic.h>
    2.27  #include <asm/io_apic.h>
    2.28 -
    2.29 +#include <asm/mach_apic.h>
    2.30 +#include <asm/io_ports.h>
    2.31  
    2.32  /* Using APIC to generate smp_local_timer_interrupt? */
    2.33  int using_apic_timer = 0;
    2.34 @@ -80,6 +83,16 @@ void clear_local_APIC(void)
    2.35          apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
    2.36      }
    2.37  
    2.38 +#if 0
    2.39 +/* lets not touch this if we didn't frob it */
    2.40 +#ifdef CONFIG_X86_MCE_P4THERMAL
    2.41 +    if (maxlvt >= 5) {
    2.42 +        v = apic_read(APIC_LVTTHMR);
    2.43 +        apic_write_around(APIC_LVTTHMR, v | APIC_LVT_MASKED);
    2.44 +    }
    2.45 +#endif
    2.46 +#endif
    2.47 +
    2.48      /*
    2.49       * Clean APIC state for other OSs:
    2.50       */
    2.51 @@ -90,9 +103,17 @@ void clear_local_APIC(void)
    2.52          apic_write_around(APIC_LVTERR, APIC_LVT_MASKED);
    2.53      if (maxlvt >= 4)
    2.54          apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
    2.55 +
    2.56 +#if 0
    2.57 +#ifdef CONFIG_X86_MCE_P4THERMAL
    2.58 +    if (maxlvt >= 5)
    2.59 +        apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED);
    2.60 +#endif
    2.61 +#endif 
    2.62 +
    2.63      v = GET_APIC_VERSION(apic_read(APIC_LVR));
    2.64      if (APIC_INTEGRATED(v)) {	/* !82489DX */
    2.65 -        if (maxlvt > 3)
    2.66 +        if (maxlvt > 3)        /* Due to Pentium errata 3AP and 11AP. */
    2.67              apic_write(APIC_ESR, 0);
    2.68          apic_read(APIC_ESR);
    2.69      }
    2.70 @@ -113,6 +134,9 @@ void __init connect_bsp_APIC(void)
    2.71          outb(0x70, 0x22);
    2.72          outb(0x01, 0x23);
    2.73      }
    2.74 +#if 0
    2.75 +    enable_apic_mode();
    2.76 +#endif
    2.77  }
    2.78  
    2.79  void disconnect_bsp_APIC(void)
    2.80 @@ -193,12 +217,6 @@ int __init verify_local_APIC(void)
    2.81       */
    2.82      reg0 = apic_read(APIC_ID);
    2.83      Dprintk("Getting ID: %x\n", reg0);
    2.84 -    apic_write(APIC_ID, reg0 ^ APIC_ID_MASK);
    2.85 -    reg1 = apic_read(APIC_ID);
    2.86 -    Dprintk("Getting ID: %x\n", reg1);
    2.87 -    apic_write(APIC_ID, reg0);
    2.88 -    if (reg1 != (reg0 ^ APIC_ID_MASK))
    2.89 -        return 0;
    2.90  
    2.91      /*
    2.92       * The next two are just to see if we have sane values.
    2.93 @@ -215,6 +233,10 @@ int __init verify_local_APIC(void)
    2.94  
    2.95  void __init sync_Arb_IDs(void)
    2.96  {
    2.97 +    /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */
    2.98 +    unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
    2.99 +    if (ver >= 0x14)    /* P4 or higher */
   2.100 +        return;
   2.101      /*
   2.102       * Wait for idle.
   2.103       */
   2.104 @@ -240,15 +262,17 @@ void __init init_bsp_APIC(void)
   2.105  {
   2.106  }
   2.107  
   2.108 -static unsigned long calculate_ldr(unsigned long old)
   2.109 -{
   2.110 -    unsigned long id = 1UL << smp_processor_id();
   2.111 -    return (old & ~APIC_LDR_MASK)|SET_APIC_LOGICAL_ID(id);
   2.112 -}
   2.113 -
   2.114  void __init setup_local_APIC (void)
   2.115  {
   2.116 -    unsigned long value, ver, maxlvt;
   2.117 +    unsigned long oldvalue, value, ver, maxlvt;
   2.118 +
   2.119 +    /* Pound the ESR really hard over the head with a big hammer - mbligh */
   2.120 +    if (esr_disable) {
   2.121 +        apic_write(APIC_ESR, 0);
   2.122 +        apic_write(APIC_ESR, 0);
   2.123 +        apic_write(APIC_ESR, 0);
   2.124 +        apic_write(APIC_ESR, 0);
   2.125 +    }
   2.126  
   2.127      value = apic_read(APIC_LVR);
   2.128      ver = GET_APIC_VERSION(value);
   2.129 @@ -256,8 +280,10 @@ void __init setup_local_APIC (void)
   2.130      if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f)
   2.131          __error_in_apic_c();
   2.132  
   2.133 -    /* Double-check wether this APIC is really registered. */
   2.134 -    if (!test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map))
   2.135 +    /*
   2.136 +     * Double-check whether this APIC is really registered.
   2.137 +     */
   2.138 +    if (!apic_id_registered())
   2.139          BUG();
   2.140  
   2.141      /*
   2.142 @@ -265,19 +291,7 @@ void __init setup_local_APIC (void)
   2.143       * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
   2.144       * document number 292116).  So here it goes...
   2.145       */
   2.146 -
   2.147 -    /*
   2.148 -     * In clustered apic mode, the firmware does this for us 
   2.149 -     * Put the APIC into flat delivery mode.
   2.150 -     * Must be "all ones" explicitly for 82489DX.
   2.151 -     */
   2.152 -    apic_write_around(APIC_DFR, APIC_DFR_FLAT);
   2.153 -
   2.154 -    /*
   2.155 -     * Set up the logical destination ID.
   2.156 -     */
   2.157 -    value = apic_read(APIC_LDR);
   2.158 -    apic_write_around(APIC_LDR, calculate_ldr(value));
   2.159 +    init_apic_ldr();
   2.160  
   2.161      /*
   2.162       * Set Task Priority to 'accept all'. We never change this
   2.163 @@ -297,10 +311,35 @@ void __init setup_local_APIC (void)
   2.164       */
   2.165      value |= APIC_SPIV_APIC_ENABLED;
   2.166  
   2.167 +    /*
   2.168 +     * Some unknown Intel IO/APIC (or APIC) errata is biting us with
   2.169 +     * certain networking cards. If high frequency interrupts are
   2.170 +     * happening on a particular IOAPIC pin, plus the IOAPIC routing
   2.171 +     * entry is masked/unmasked at a high rate as well then sooner or
   2.172 +     * later IOAPIC line gets 'stuck', no more interrupts are received
   2.173 +     * from the device. If focus CPU is disabled then the hang goes
   2.174 +     * away, oh well :-(
   2.175 +     *
   2.176 +     * [ This bug can be reproduced easily with a level-triggered
   2.177 +     *   PCI Ne2000 networking cards and PII/PIII processors, dual
   2.178 +     *   BX chipset. ]
   2.179 +     */
   2.180 +    /*
   2.181 +     * Actually disabling the focus CPU check just makes the hang less
   2.182 +     * frequent as it makes the interrupt distributon model be more
   2.183 +     * like LRU than MRU (the short-term load is more even across CPUs).
   2.184 +     * See also the comment in end_level_ioapic_irq().  --macro
   2.185 +     */
   2.186 +#if 1
   2.187      /* Enable focus processor (bit==0) */
   2.188      value &= ~APIC_SPIV_FOCUS_DISABLED;
   2.189 -
   2.190 -    /* Set spurious IRQ vector */
   2.191 +#else
   2.192 +    /* Disable focus processor (bit==1) */
   2.193 +    value |= APIC_SPIV_FOCUS_DISABLED;
   2.194 +#endif
   2.195 +    /*
   2.196 +     * Set spurious IRQ vector
   2.197 +     */
   2.198      value |= SPURIOUS_APIC_VECTOR;
   2.199      apic_write_around(APIC_SPIV, value);
   2.200  
   2.201 @@ -315,7 +354,7 @@ void __init setup_local_APIC (void)
   2.202       * TODO: set up through-local-APIC from through-I/O-APIC? --macro
   2.203       */
   2.204      value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
   2.205 -    if (!smp_processor_id()) { 
   2.206 +    if (!smp_processor_id() && (pic_mode || !value)) {
   2.207          value = APIC_DM_EXTINT;
   2.208          printk("enabled ExtINT on CPU#%d\n", smp_processor_id());
   2.209      } else {
   2.210 @@ -335,33 +374,43 @@ void __init setup_local_APIC (void)
   2.211          value |= APIC_LVT_LEVEL_TRIGGER;
   2.212      apic_write_around(APIC_LVT1, value);
   2.213  
   2.214 -    if (APIC_INTEGRATED(ver)) {     /* !82489DX */
   2.215 +    if (APIC_INTEGRATED(ver) && !esr_disable) {        /* !82489DX */
   2.216          maxlvt = get_maxlvt();
   2.217          if (maxlvt > 3)     /* Due to the Pentium erratum 3AP. */
   2.218              apic_write(APIC_ESR, 0);
   2.219 -        value = apic_read(APIC_ESR);
   2.220 -        printk("ESR value before enabling vector: %08lx\n", value);
   2.221 +        oldvalue = apic_read(APIC_ESR);
   2.222  
   2.223 -        value = ERROR_APIC_VECTOR;      /* enables sending errors */
   2.224 +        value = ERROR_APIC_VECTOR;      // enables sending errors
   2.225          apic_write_around(APIC_LVTERR, value);
   2.226 -        /* spec says clear errors after enabling vector. */
   2.227 +        /*
   2.228 +         * spec says clear errors after enabling vector.
   2.229 +         */
   2.230          if (maxlvt > 3)
   2.231              apic_write(APIC_ESR, 0);
   2.232          value = apic_read(APIC_ESR);
   2.233 -        printk("ESR value after enabling vector: %08lx\n", value);
   2.234 +        if (value != oldvalue)
   2.235 +            printk("ESR value before enabling vector: 0x%08lx "
   2.236 +                "after: 0x%08lx\n", oldvalue, value);
   2.237      } else {
   2.238 +        if (esr_disable)    
   2.239 +            /* 
   2.240 +             * Something untraceble is creating bad interrupts on 
   2.241 +             * secondary quads ... for the moment, just leave the
   2.242 +             * ESR disabled - we can't do anything useful with the
   2.243 +             * errors anyway - mbligh
   2.244 +             */
   2.245 +            printk("Leaving ESR disabled.\n");
   2.246 +        else 
   2.247          printk("No ESR for 82489DX.\n");
   2.248      }
   2.249  
   2.250 -    if ( (smp_processor_id() == 0) && (nmi_watchdog == NMI_LOCAL_APIC) )
   2.251 +    if (nmi_watchdog == NMI_LOCAL_APIC)
   2.252          setup_apic_nmi_watchdog();
   2.253 +#if 0
   2.254 +    apic_pm_activate();
   2.255 +#endif
   2.256  }
   2.257  
   2.258 -
   2.259 -static inline void apic_pm_init1(void) { }
   2.260 -static inline void apic_pm_init2(void) { }
   2.261 -
   2.262 -
   2.263  /*
   2.264   * Detect and enable local APICs on non-SMP boards.
   2.265   * Original code written by Keir Fraser.
   2.266 @@ -372,19 +421,23 @@ static int __init detect_init_APIC (void
   2.267      u32 h, l, features;
   2.268      extern void get_cpu_vendor(struct cpuinfo_x86*);
   2.269  
   2.270 +#if 0
   2.271 +    /* Disabled by kernel option? */
   2.272 +    if (enable_local_apic < 0)
   2.273 +        return -1;
   2.274 +#endif
   2.275 +
   2.276      /* Workaround for us being called before identify_cpu(). */
   2.277      get_cpu_vendor(&boot_cpu_data);
   2.278  
   2.279      switch (boot_cpu_data.x86_vendor) {
   2.280      case X86_VENDOR_AMD:
   2.281 -        if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1)
   2.282 -            break;
   2.283 -        if (boot_cpu_data.x86 == 15 && cpu_has_apic)
   2.284 +        if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
   2.285 +            (boot_cpu_data.x86 == 15))        
   2.286              break;
   2.287          goto no_apic;
   2.288      case X86_VENDOR_INTEL:
   2.289 -        if (boot_cpu_data.x86 == 6 ||
   2.290 -            (boot_cpu_data.x86 == 15 && cpu_has_apic) ||
   2.291 +        if (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15 ||
   2.292              (boot_cpu_data.x86 == 5 && cpu_has_apic))
   2.293              break;
   2.294          goto no_apic;
   2.295 @@ -394,9 +447,21 @@ static int __init detect_init_APIC (void
   2.296  
   2.297      if (!cpu_has_apic) {
   2.298          /*
   2.299 +         * Over-ride BIOS and try to enable the local
   2.300 +         * APIC only if "lapic" specified.
   2.301 +         */
   2.302 +#if 0
   2.303 +        if (enable_local_apic <= 0) {
   2.304 +            printk("Local APIC disabled by BIOS -- "
   2.305 +                   "you can enable it with \"lapic\"\n");
   2.306 +            return -1;
   2.307 +        }
   2.308 +#endif
   2.309 +        /*
   2.310           * Some BIOSes disable the local APIC in the
   2.311           * APIC_BASE MSR. This can only be done in
   2.312 -         * software for Intel P6 and AMD K7 (Model > 1).
   2.313 +         * software for Intel P6 or later and AMD K7
   2.314 +         * (Model > 1) or later.
   2.315           */
   2.316          rdmsr(MSR_IA32_APICBASE, l, h);
   2.317          if (!(l & MSR_IA32_APICBASE_ENABLE)) {
   2.318 @@ -407,17 +472,17 @@ static int __init detect_init_APIC (void
   2.319              enabled_via_apicbase = 1;
   2.320          }
   2.321      }
   2.322 -
   2.323 -    /* The APIC feature bit should now be enabled in `cpuid' */
   2.324 +    /*
   2.325 +     * The APIC feature bit should now be enabled
   2.326 +     * in `cpuid'
   2.327 +     */
   2.328      features = cpuid_edx(1);
   2.329      if (!(features & (1 << X86_FEATURE_APIC))) {
   2.330          printk("Could not enable APIC!\n");
   2.331          return -1;
   2.332      }
   2.333 -
   2.334 -    set_bit(X86_FEATURE_APIC, &boot_cpu_data.x86_capability);
   2.335 +    set_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
   2.336      mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
   2.337 -    boot_cpu_physical_apicid = 0;
   2.338  
   2.339      /* The BIOS may have set up the APIC at some other address */
   2.340      rdmsr(MSR_IA32_APICBASE, l, h);
   2.341 @@ -428,21 +493,26 @@ static int __init detect_init_APIC (void
   2.342  		nmi_watchdog = NMI_LOCAL_APIC;
   2.343  
   2.344      printk("Found and enabled local APIC!\n");
   2.345 -    apic_pm_init1();
   2.346 +
   2.347 +#if 0
   2.348 +    apic_pm_activate();
   2.349 +#endif
   2.350 +
   2.351      return 0;
   2.352  
   2.353 - no_apic:
   2.354 +no_apic:
   2.355      printk("No local APIC present or hardware disabled\n");
   2.356      return -1;
   2.357  }
   2.358  
   2.359  void __init init_apic_mappings(void)
   2.360  {
   2.361 -    unsigned long apic_phys = 0;
   2.362 +    unsigned long apic_phys;
   2.363  
   2.364      /*
   2.365 -     * If no local APIC can be found then set up a fake all zeroes page to 
   2.366 -     * simulate the local APIC and another one for the IO-APIC.
   2.367 +     * If no local APIC can be found then set up a fake all
   2.368 +     * zeroes page to simulate the local APIC and another
   2.369 +     * one for the IO-APIC.
   2.370       */
   2.371      if (!smp_found_config && detect_init_APIC()) {
   2.372          apic_phys = alloc_xenheap_page();
   2.373 @@ -462,12 +532,26 @@ void __init init_apic_mappings(void)
   2.374  
   2.375  #ifdef CONFIG_X86_IO_APIC
   2.376      {
   2.377 -        unsigned long ioapic_phys = 0, idx = FIX_IO_APIC_BASE_0;
   2.378 +        unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
   2.379          int i;
   2.380  
   2.381          for (i = 0; i < nr_ioapics; i++) {
   2.382 -            if (smp_found_config)
   2.383 +            if (smp_found_config) {
   2.384                  ioapic_phys = mp_ioapics[i].mpc_apicaddr;
   2.385 +                if (!ioapic_phys) {
   2.386 +                    printk(KERN_ERR
   2.387 +                           "WARNING: bogus zero IO-APIC "
   2.388 +                           "address found in MPTABLE, "
   2.389 +                           "disabling IO/APIC support!\n");
   2.390 +                    smp_found_config = 0;
   2.391 +                    skip_ioapic_setup = 1;
   2.392 +                    goto fake_ioapic_page;
   2.393 +                }
   2.394 +            } else {
   2.395 +fake_ioapic_page:
   2.396 +                ioapic_phys = alloc_xenheap_page();
   2.397 +                ioapic_phys = __pa(ioapic_phys);
   2.398 +            }
   2.399              set_fixmap_nocache(idx, ioapic_phys);
   2.400              Dprintk("mapped IOAPIC to %08lx (%08lx)\n",
   2.401                      fix_to_virt(idx), ioapic_phys);
   2.402 @@ -504,33 +588,49 @@ static unsigned int __init get_8254_time
   2.403  {
   2.404      /*extern spinlock_t i8253_lock;*/
   2.405      /*unsigned long flags;*/
   2.406 +
   2.407      unsigned int count;
   2.408 +
   2.409      /*spin_lock_irqsave(&i8253_lock, flags);*/
   2.410 -    outb_p(0x00, 0x43);
   2.411 -    count = inb_p(0x40);
   2.412 -    count |= inb_p(0x40) << 8;
   2.413 +
   2.414 +    outb_p(0x00, PIT_MODE);
   2.415 +    count = inb_p(PIT_CH0);
   2.416 +    count |= inb_p(PIT_CH0) << 8;
   2.417 +
   2.418      /*spin_unlock_irqrestore(&i8253_lock, flags);*/
   2.419 +
   2.420      return count;
   2.421  }
   2.422  
   2.423 -void __init wait_8254_wraparound(void)
   2.424 +/* next tick in 8254 can be caught by catching timer wraparound */
   2.425 +static void __init wait_8254_wraparound(void)
   2.426  {
   2.427      unsigned int curr_count, prev_count=~0;
   2.428      int delta;
   2.429 +
   2.430      curr_count = get_8254_timer_count();
   2.431 +
   2.432      do {
   2.433          prev_count = curr_count;
   2.434          curr_count = get_8254_timer_count();
   2.435          delta = curr_count-prev_count;
   2.436 +
   2.437          /*
   2.438 -         * This limit for delta seems arbitrary, but it isn't, it's slightly 
   2.439 -         * above the level of error a buggy Mercury/Neptune chipset timer can 
   2.440 -         * cause.
   2.441 +     * This limit for delta seems arbitrary, but it isn't, it's
   2.442 +     * slightly above the level of error a buggy Mercury/Neptune
   2.443 +     * chipset timer can cause.
   2.444           */
   2.445 +
   2.446      } while (delta < 300);
   2.447  }
   2.448  
   2.449  /*
   2.450 + * Default initialization for 8254 timers. If we use other timers like HPET,
   2.451 + * we override this later
   2.452 + */
   2.453 +void (*wait_timer_tick)(void) = wait_8254_wraparound;
   2.454 +
   2.455 +/*
   2.456   * This function sets up the local APIC timer, with a timeout of
   2.457   * 'clocks' APIC bus clock. During calibration we actually call
   2.458   * this function with a very large value and read the current time after
   2.459 @@ -541,14 +641,32 @@ void __init wait_8254_wraparound(void)
   2.460   * We do reads before writes even if unnecessary, to get around the
   2.461   * P5 APIC double write bug.
   2.462   */
   2.463 +
   2.464  #define APIC_DIVISOR 1
   2.465 +
   2.466  static void __setup_APIC_LVTT(unsigned int clocks)
   2.467  {
   2.468 -    unsigned int lvtt1_value, tmp_value;
   2.469 -    lvtt1_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV)|LOCAL_TIMER_VECTOR;
   2.470 -    apic_write_around(APIC_LVTT, lvtt1_value);
   2.471 +    unsigned int lvtt_value, tmp_value, ver;
   2.472 +
   2.473 +    ver = GET_APIC_VERSION(apic_read(APIC_LVR));
   2.474 +    lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
   2.475 +    if (!APIC_INTEGRATED(ver))
   2.476 +        lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
   2.477 +    apic_write_around(APIC_LVTT, lvtt_value);
   2.478 +
   2.479 +#if 0
   2.480 +    /*
   2.481 +     * Divide PICLK by 16
   2.482 +     */
   2.483 +    tmp_value = apic_read(APIC_TDCR);
   2.484 +    apic_write_around(APIC_TDCR, (tmp_value
   2.485 +                & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
   2.486 +                | APIC_TDR_DIV_16);
   2.487 +#endif
   2.488 +
   2.489      tmp_value = apic_read(APIC_TDCR);
   2.490      apic_write_around(APIC_TDCR, (tmp_value | APIC_TDR_DIV_1));
   2.491 +
   2.492      apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
   2.493  }
   2.494  
   2.495 @@ -569,7 +687,7 @@ void setup_APIC_timer(void * data)
   2.496  /*
   2.497   * In this function we calibrate APIC bus clocks to the external timer.
   2.498   *
   2.499 - * As a result we have the Bys Speed and CPU speed in Hz.
   2.500 + * As a result we have the Bus Speed and CPU speed in Hz.
   2.501   * 
   2.502   * We want to do the calibration only once (for CPU0).  CPUs connected by the
   2.503   * same APIC bus have the very same bus frequency.
   2.504 @@ -586,48 +704,61 @@ int __init calibrate_APIC_clock(void)
   2.505      int i;
   2.506      const int LOOPS = HZ/10;
   2.507  
   2.508 +#if 0
   2.509 +    apic_printk(APIC_VERBOSE, "calibrating APIC timer ...\n");
   2.510 +#endif
   2.511      printk("Calibrating APIC timer for CPU%d...\n",  smp_processor_id());
   2.512  
   2.513 -    /* Put whatever arbitrary (but long enough) timeout
   2.514 +    /*
   2.515 +     * Put whatever arbitrary (but long enough) timeout
   2.516       * value into the APIC clock, we just want to get the
   2.517 -     * counter running for calibration. */
   2.518 +     * counter running for calibration.
   2.519 +     */
   2.520      __setup_APIC_LVTT(1000000000);
   2.521  
   2.522 -    /* The timer chip counts down to zero. Let's wait
   2.523 +    /*
   2.524 +     * The timer chip counts down to zero. Let's wait
   2.525       * for a wraparound to start exact measurement:
   2.526 -     * (the current tick might have been already half done) */
   2.527 -    wait_8254_wraparound();
   2.528 +     * (the current tick might have been already half done)
   2.529 +     */
   2.530 +
   2.531 +    wait_timer_tick();
   2.532  
   2.533 -    /* We wrapped around just now. Let's start: */
   2.534 +    /*
   2.535 +     * We wrapped around just now. Let's start:
   2.536 +     */
   2.537 +    if (cpu_has_tsc)
   2.538      rdtscll(t1);
   2.539      tt1 = apic_read(APIC_TMCCT);
   2.540  
   2.541 -    /* Let's wait LOOPS wraprounds: */
   2.542 +    /*
   2.543 +     * Let's wait LOOPS wraprounds:
   2.544 +     */
   2.545      for (i = 0; i < LOOPS; i++)
   2.546 -        wait_8254_wraparound();
   2.547 +        wait_timer_tick();
   2.548  
   2.549      tt2 = apic_read(APIC_TMCCT);
   2.550 +    if (cpu_has_tsc)
   2.551      rdtscll(t2);
   2.552  
   2.553 -    /* The APIC bus clock counter is 32 bits only, it
   2.554 +    /*
   2.555 +     * The APIC bus clock counter is 32 bits only, it
   2.556       * might have overflown, but note that we use signed
   2.557       * longs, thus no extra care needed.
   2.558 -     * underflown to be exact, as the timer counts down ;) */
   2.559 +     *
   2.560 +     * underflown to be exact, as the timer counts down ;)
   2.561 +     */
   2.562 +
   2.563      result = (tt1-tt2)*APIC_DIVISOR/LOOPS;
   2.564  
   2.565 -    printk("..... CPU speed is %ld.%04ld MHz.\n",
   2.566 -           ((long)(t2-t1)/LOOPS) / (1000000/HZ), 
   2.567 -           ((long)(t2-t1)/LOOPS) % (1000000/HZ));
   2.568 +    if (cpu_has_tsc)
   2.569 +        printk("..... CPU clock speed is %ld.%04ld MHz.\n",
   2.570 +            ((long)(t2-t1)/LOOPS)/(1000000/HZ),
   2.571 +            ((long)(t2-t1)/LOOPS)%(1000000/HZ));
   2.572  
   2.573 -    printk("..... Bus speed is %ld.%04ld MHz.\n",
   2.574 -           result / (1000000/HZ), 
   2.575 -           result % (1000000/HZ));
   2.576 -
   2.577 -    /*
   2.578 -     * KAF: Moved this to time.c where it's calculated relative to the TSC. 
   2.579 -     * Therefore works on machines with no local APIC.
   2.580 -     */
   2.581 -    /*cpu_freq = (u64)(((t2-t1)/LOOPS)*HZ);*/
   2.582 +    printk("..... host bus clock speed is %ld.%04ld MHz.\n",
   2.583 +        result/(1000000/HZ),
   2.584 +        result%(1000000/HZ));
   2.585  
   2.586      /* set up multipliers for accurate timer code */
   2.587      bus_freq   = result*HZ;
   2.588 @@ -637,6 +768,7 @@ int __init calibrate_APIC_clock(void)
   2.589      printk("..... bus_scale = 0x%08X\n", bus_scale);
   2.590      /* reset APIC to zero timeout value */
   2.591      __setup_APIC_LVTT(0);
   2.592 +
   2.593      return result;
   2.594  }
   2.595  
   2.596 @@ -729,13 +861,17 @@ void smp_apic_timer_interrupt(struct xen
   2.597      raise_softirq(AC_TIMER_SOFTIRQ);
   2.598  }
   2.599  
   2.600 +
   2.601  /*
   2.602   * This interrupt should _never_ happen with our APIC/SMP architecture
   2.603   */
   2.604 -asmlinkage void smp_spurious_interrupt(void)
   2.605 +asmlinkage void smp_spurious_interrupt(struct xen_regs *regs)
   2.606  {
   2.607      unsigned long v;
   2.608  
   2.609 +#if 0
   2.610 +    irq_enter();
   2.611 +#endif
   2.612      /*
   2.613       * Check if this really is a spurious interrupt and ACK it
   2.614       * if it is a vectored one.  Just in case...
   2.615 @@ -748,16 +884,22 @@ asmlinkage void smp_spurious_interrupt(v
   2.616      /* see sw-dev-man vol 3, chapter 7.4.13.5 */
   2.617      printk("spurious APIC interrupt on CPU#%d, should never happen.\n",
   2.618             smp_processor_id());
   2.619 +#if 0
   2.620 +    irq_exit();
   2.621 +#endif
   2.622  }
   2.623  
   2.624  /*
   2.625   * This interrupt should never happen with our APIC/SMP architecture
   2.626   */
   2.627  
   2.628 -asmlinkage void smp_error_interrupt(void)
   2.629 +asmlinkage void smp_error_interrupt(struct xen_regs *regs)
   2.630  {
   2.631      unsigned long v, v1;
   2.632  
   2.633 +#if 0
   2.634 +    irq_enter();
   2.635 +#endif
   2.636      /* First tickle the hardware, only then report what went on. -- REW */
   2.637      v = apic_read(APIC_ESR);
   2.638      apic_write(APIC_ESR, 0);
   2.639 @@ -775,8 +917,11 @@ asmlinkage void smp_error_interrupt(void
   2.640         6: Received illegal vector
   2.641         7: Illegal register address
   2.642      */
   2.643 -    printk ("APIC error on CPU%d: %02lx(%02lx)\n",
   2.644 +    Dprintk("APIC error on CPU%d: %02lx(%02lx)\n",
   2.645              smp_processor_id(), v , v1);
   2.646 +#if 0
   2.647 +    irq_exit();
   2.648 +#endif
   2.649  }
   2.650  
   2.651  /*
   2.652 @@ -785,14 +930,18 @@ asmlinkage void smp_error_interrupt(void
   2.653   */
   2.654  int __init APIC_init_uniprocessor (void)
   2.655  {
   2.656 +#if 0
   2.657 +    if (enable_local_apic < 0)
   2.658 +        clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
   2.659 +#endif
   2.660 +
   2.661      if (!smp_found_config && !cpu_has_apic)
   2.662          return -1;
   2.663  
   2.664      /*
   2.665       * Complain if the BIOS pretends there is one.
   2.666       */
   2.667 -    if (!cpu_has_apic&&APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]))
   2.668 -    {
   2.669 +    if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
   2.670          printk("BIOS bug, local APIC #%d not detected!...\n",
   2.671                 boot_cpu_physical_apicid);
   2.672          return -1;
   2.673 @@ -805,17 +954,26 @@ int __init APIC_init_uniprocessor (void)
   2.674  #ifdef CONFIG_SMP
   2.675      cpu_online_map = 1;
   2.676  #endif
   2.677 +#if 0
   2.678 +    phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
   2.679 +#endif
   2.680      phys_cpu_present_map = 1;
   2.681      apic_write_around(APIC_ID, boot_cpu_physical_apicid);
   2.682  
   2.683 -    apic_pm_init2();
   2.684 -
   2.685      setup_local_APIC();
   2.686  
   2.687 +#if 0
   2.688 +    if (nmi_watchdog == NMI_LOCAL_APIC)
   2.689 +        check_nmi_watchdog();
   2.690 +#endif
   2.691  #ifdef CONFIG_X86_IO_APIC
   2.692 -    if (smp_found_config && nr_ioapics)
   2.693 +    if (smp_found_config)
   2.694 +        if (!skip_ioapic_setup && nr_ioapics)
   2.695          setup_IO_APIC();
   2.696  #endif
   2.697 +#if 0
   2.698 +    setup_boot_APIC_clock();
   2.699 +#endif
   2.700      setup_APIC_clocks();
   2.701  
   2.702      return 0;
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xen/include/asm-x86/io_ports.h	Fri Apr 15 23:40:59 2005 +0000
     3.3 @@ -0,0 +1,30 @@
     3.4 +/*
     3.5 + *  based on linux-2.6.10/include/asm-i386/mach-default/io_ports.h
     3.6 + *
     3.7 + *  Machine specific IO port address definition for generic.
     3.8 + *  Written by Osamu Tomita <tomita@cinet.co.jp>
     3.9 + */
    3.10 +#ifndef _MACH_IO_PORTS_H
    3.11 +#define _MACH_IO_PORTS_H
    3.12 +
    3.13 +/* i8253A PIT registers */
    3.14 +#define PIT_MODE              0x43
    3.15 +#define PIT_CH0               0x40
    3.16 +#define PIT_CH2               0x42
    3.17 +
    3.18 +/* i8259A PIC registers */
    3.19 +#define PIC_MASTER_CMD        0x20
    3.20 +#define PIC_MASTER_IMR        0x21
    3.21 +#define PIC_MASTER_ISR        PIC_MASTER_CMD
    3.22 +#define PIC_MASTER_POLL       PIC_MASTER_ISR
    3.23 +#define PIC_MASTER_OCW3       PIC_MASTER_ISR
    3.24 +#define PIC_SLAVE_CMD         0xa0
    3.25 +#define PIC_SLAVE_IMR         0xa1
    3.26 +
    3.27 +/* i8259A PIC related value */
    3.28 +#define PIC_CASCADE_IR        2
    3.29 +#define MASTER_ICW4_DEFAULT   0x01
    3.30 +#define SLAVE_ICW4_DEFAULT    0x01
    3.31 +#define PIC_ICW4_AEOI         2
    3.32 +
    3.33 +#endif /* !_MACH_IO_PORTS_H */
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/xen/include/asm-x86/mach_apic.h	Fri Apr 15 23:40:59 2005 +0000
     4.3 @@ -0,0 +1,32 @@
     4.4 +/*
     4.5 + *  based on linux-2.6.10/include/asm-i386/mach-default/mach_apic.h
     4.6 + *
     4.7 + */
     4.8 +#ifndef __ASM_MACH_APIC_H
     4.9 +#define __ASM_MACH_APIC_H
    4.10 +
    4.11 +#define APIC_DFR_VALUE    (APIC_DFR_FLAT)
    4.12 +#define esr_disable (0)
    4.13 +
    4.14 +/*
    4.15 + * Set up the logical destination ID.
    4.16 + *
    4.17 + * Intel recommends to set DFR, LDR and TPR before enabling
    4.18 + * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
    4.19 + * document number 292116).  So here it goes...
    4.20 + */
    4.21 +static inline void init_apic_ldr(void)
    4.22 +{
    4.23 +    unsigned long val;
    4.24 +
    4.25 +    apic_write_around(APIC_DFR, APIC_DFR_VALUE);
    4.26 +    val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
    4.27 +    val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id());
    4.28 +    apic_write_around(APIC_LDR, val);
    4.29 +}
    4.30 +
    4.31 +static inline int apic_id_registered(void)
    4.32 +{
    4.33 +    return test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map);
    4.34 +}
    4.35 +#endif /* __ASM_MACH_APIC_H */