Print this page
6062 Workaround broken KVM handling of directed EOIs
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/i86pc/io/pcplusmp/apic_regops.c
          +++ new/usr/src/uts/i86pc/io/pcplusmp/apic_regops.c
↓ open down ↓ 16 lines elided ↑ open up ↑
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  /*
  26   26   * Copyright 2014 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
       27 + * Copyright (c) 2014 by Delphix. All rights reserved.
  27   28   */
  28   29  
  29   30  #include <sys/cpuvar.h>
  30   31  #include <sys/psm.h>
  31   32  #include <sys/archsystm.h>
  32   33  #include <sys/apic.h>
  33   34  #include <sys/sunddi.h>
  34   35  #include <sys/ddi_impldefs.h>
  35   36  #include <sys/mach_intr.h>
  36   37  #include <sys/sysmacros.h>
↓ open down ↓ 22 lines elided ↑ open up ↑
  59   60   * -----------------------------------------------------------
  60   61   *      0                       0       APIC is disabled
  61   62   *      0                       1       Invalid
  62   63   *      1                       0       APIC is enabled in xAPIC mode
  63   64   *      1                       1       APIC is enabled in X2APIC mode
  64   65   * -----------------------------------------------------------
  65   66   */
  66   67  int     x2apic_enable = 1;
  67   68  apic_mode_t apic_mode = LOCAL_APIC;     /* Default mode is Local APIC */
  68   69  
       70 +/* See apic_directed_EOI_supported().  Currently 3-state variable. */
       71 +volatile int apic_directed_eoi_state = 2;
       72 +
  69   73  /* Uses MMIO (Memory Mapped IO) */
  70   74  static apic_reg_ops_t local_apic_regs_ops = {
  71   75          local_apic_read,
  72   76          local_apic_write,
  73   77          get_local_apic_pri,
  74   78          local_apic_write_task_reg,
  75   79          local_apic_write_int_cmd,
  76   80          apic_send_EOI,
  77   81  };
  78   82  
↓ open down ↓ 208 lines elided ↑ open up ↑
 287  291  apic_set_directed_EOI_handler()
 288  292  {
 289  293          apic_reg_ops->apic_send_eoi = apic_send_directed_EOI;
 290  294  }
 291  295  
 292  296  int
 293  297  apic_directed_EOI_supported()
 294  298  {
 295  299          uint32_t ver;
 296  300  
      301 +        /*
      302 +         * There are some known issues with some versions of Linux KVM and QEMU
      303 +         * where by directed EOIs do not properly function and instead get
      304 +         * coalesced at the hypervisor, causing the host not to see interrupts.
      305 +         * Thus, when the platform is KVM, we would like to disable it by
      306 +         * default, but keep it available otherwise.
      307 +         *
      308 +         * We use a three-state variable (apic_directed_eoi_state) to determine
      309 +         * how we handle directed EOI.
      310 +         *
      311 +         * 0 --> Don't do directed EOI at all.
      312 +         * 1 --> Do directed EOI if available, no matter the HW environment.
      313 +         * 2 --> Don't do directed EOI on KVM, but do it otherwise if available.
      314 +         *
      315 +         * If some grinning weirdo put something else in there, treat it as '2'
      316 +         * (i.e. the current default).
      317 +         *
      318 +         * Note, at this time illumos KVM does not identify as KVM. If it does,
      319 +         * we'll need to do some work to determine if it should be caught by
      320 +         * this or if it should show up as its own value of platform_type.
      321 +         */
      322 +        switch (apic_directed_eoi_state) {
      323 +        case 0:
      324 +                /* Don't do it at all. */
      325 +                return (0);
      326 +        case 1:
      327 +                break;
      328 +        case 2:
      329 +        default:
      330 +                /* Only do it if we aren't on KVM. */
      331 +                if (get_hwenv() == HW_KVM)
      332 +                        return (0);
      333 +                /* FALLTHRU */
      334 +        }
      335 +
 297  336          ver = apic_reg_ops->apic_read(APIC_VERS_REG);
 298  337          if (ver & APIC_DIRECTED_EOI_BIT)
 299  338                  return (1);
 300  339  
 301  340          return (0);
 302  341  }
 303  342  
 304  343  /*
 305  344   * Change apic_reg_ops depending upon the apic_mode.
 306  345   */
↓ open down ↓ 97 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX