Print this page
    
re #13140 rb4270 hvm_sd module missing dependencies on scsi and cmlb
re #13166 rb4270 Check for Xen HVM even if CPUID signature returns Microsoft Hv
re #13187 rb4270 Fix Xen HVM related warnings
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/i86pc/os/xpv_platform.c
          +++ new/usr/src/uts/i86pc/os/xpv_platform.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   */
  24   24  
  25   25  #include <sys/types.h>
  26   26  #include <sys/archsystm.h>
  27   27  #include <sys/machsystm.h>
  28   28  #include <sys/sunndi.h>
  29   29  #include <sys/sunddi.h>
  30   30  #include <sys/ddi_subrdefs.h>
  31   31  #include <sys/xpv_support.h>
  32   32  #include <sys/xen_errno.h>
  33   33  #include <sys/hypervisor.h>
  34   34  #include <sys/gnttab.h>
  35   35  #include <sys/xenbus_comms.h>
  36   36  #include <sys/xenbus_impl.h>
  37   37  #include <sys/sysmacros.h>
  38   38  #include <sys/x86_archext.h>
  39   39  #include <sys/mman.h>
  40   40  #include <sys/stat.h>
  41   41  #include <sys/conf.h>
  42   42  #include <sys/devops.h>
  43   43  #include <sys/pc_mmu.h>
  44   44  #include <sys/cmn_err.h>
  45   45  #include <sys/cpr.h>
  46   46  #include <sys/ddi.h>
  47   47  #include <vm/seg_kmem.h>
  48   48  #include <vm/as.h>
  49   49  #include <vm/hat_pte.h>
  50   50  #include <vm/hat_i86.h>
  51   51  
  52   52  static int xen_hvm_inited;
  53   53  
  54   54  /*
  55   55   * This structure is ordinarily constructed by Xen. In the HVM world, we
  56   56   * manually fill in the few fields the PV drivers need.
  57   57   */
  58   58  static start_info_t __xen_info;
  59   59  start_info_t *xen_info = NULL;
  60   60  
  61   61  static int xen_bits = -1;
  62   62  static int xen_major = -1, xen_minor = -1;
  63   63  
  64   64  /*
  65   65   * Feature bits; more bits will be added, like direct I/O, etc.
  66   66   */
  67   67  #define XEN_HVM_HYPERCALLS      0x0001
  68   68  #define XEN_HVM_TLBFLUSH        0x0002
  69   69  static uint64_t xen_hvm_features;
  70   70  
  71   71  /* Metadata page shared between domain and Xen */
  72   72  shared_info_t *HYPERVISOR_shared_info = NULL;
  73   73  pfn_t xen_shared_info_frame;
  74   74  
  75   75  /* Page containing code to issue hypercalls.  */
  76   76  extern caddr_t hypercall_page;
  77   77  extern caddr_t hypercall_shared_info_page;
  78   78  
  79   79  static int
  80   80  hvm_get_param(int param_id, uint64_t *val)
  81   81  {
  82   82          struct xen_hvm_param xhp;
  83   83  
  84   84          xhp.domid = DOMID_SELF;
  85   85          xhp.index = param_id;
  86   86          if ((HYPERVISOR_hvm_op(HVMOP_get_param, &xhp) < 0))
  87   87                  return (-1);
  88   88          *val = xhp.value;
  89   89          return (0);
  90   90  }
  91   91  
  
    | 
      ↓ open down ↓ | 
    91 lines elided | 
    
      ↑ open up ↑ | 
  
  92   92  void
  93   93  xen_hvm_init(void)
  94   94  {
  95   95          struct cpuid_regs cp;
  96   96          uint32_t xen_signature[4], base;
  97   97          char *xen_str;
  98   98          struct xen_add_to_physmap xatp;
  99   99          xen_capabilities_info_t caps;
 100  100          pfn_t pfn;
 101  101          uint64_t msrval, val;
      102 +        extern int apix_enable;
 102  103  
 103  104          if (xen_hvm_inited != 0)
 104  105                  return;
 105  106  
 106  107          xen_hvm_inited = 1;
 107  108  
 108  109          /*
 109  110           * Xen's pseudo-cpuid function returns a string representing
 110  111           * the Xen signature in %ebx, %ecx, and %edx.
 111  112           * Loop over the base values, since it may be different if
 112  113           * the hypervisor has hyper-v emulation switched on.
 113  114           *
 114  115           * %eax contains the maximum supported cpuid function.
 115  116           */
 116  117          for (base = 0x40000000; base < 0x40010000; base += 0x100) {
 117  118                  cp.cp_eax = base;
 118  119                  (void) __cpuid_insn(&cp);
 119  120                  xen_signature[0] = cp.cp_ebx;
 120  121                  xen_signature[1] = cp.cp_ecx;
 121  122                  xen_signature[2] = cp.cp_edx;
 122  123                  xen_signature[3] = 0;
 123  124                  xen_str = (char *)xen_signature;
 124  125                  if (strcmp("XenVMMXenVMM", xen_str)  == 0 &&
 125  126                      cp.cp_eax >= (base + 2))
 126  127                          break;
 127  128          }
 128  129          if (base >= 0x40010000)
 129  130                  return;
 130  131  
 131  132          /*
 132  133           * cpuid function at base + 1 returns the Xen version in %eax.  The
 133  134           * top 16 bits are the major version, the bottom 16 are the minor
 134  135           * version.
 135  136           */
 136  137          cp.cp_eax = base + 1;
 137  138          (void) __cpuid_insn(&cp);
 138  139          xen_major = cp.cp_eax >> 16;
 139  140          xen_minor = cp.cp_eax & 0xffff;
 140  141  
 141  142          /*
 142  143           * Below version 3.1 we can't do anything special as a HVM domain;
 143  144           * the PV drivers don't work, many hypercalls are not available,
 144  145           * etc.
 145  146           */
 146  147          if (xen_major < 3 || (xen_major == 3 && xen_minor < 1))
 147  148                  return;
 148  149  
 149  150          /*
 150  151           * cpuid function at base + 2 returns information about the
 151  152           * hypercall page.  %eax nominally contains the number of pages
 152  153           * with hypercall code, but according to the Xen guys, "I'll
 153  154           * guarantee that remains one forever more, so you can just
 154  155           * allocate a single page and get quite upset if you ever see CPUID
 155  156           * return more than one page."  %ebx contains an MSR we use to ask
 156  157           * Xen to remap each page at a specific pfn.
 157  158           */
 158  159          cp.cp_eax = base + 2;
 159  160          (void) __cpuid_insn(&cp);
 160  161  
 161  162          /*
 162  163           * Let Xen know where we want the hypercall page mapped.  We
 163  164           * already have a page allocated in the .text section to simplify
 164  165           * the wrapper code.
 165  166           */
 166  167          pfn = va_to_pfn(&hypercall_page);
 167  168          msrval = mmu_ptob(pfn);
 168  169          wrmsr(cp.cp_ebx, msrval);
 169  170  
 170  171          /* Fill in the xen_info data */
 171  172          xen_info = &__xen_info;
 172  173          (void) sprintf(xen_info->magic, "xen-%d.%d", xen_major, xen_minor);
 173  174  
 174  175          if (hvm_get_param(HVM_PARAM_STORE_PFN, &val) < 0)
 175  176                  return;
 176  177          /*
 177  178           * The first hypercall worked, so mark hypercalls as working.
 178  179           */
 179  180          xen_hvm_features |= XEN_HVM_HYPERCALLS;
 180  181  
 181  182          xen_info->store_mfn = (mfn_t)val;
 182  183          if (hvm_get_param(HVM_PARAM_STORE_EVTCHN, &val) < 0)
 183  184                  return;
 184  185          xen_info->store_evtchn = (mfn_t)val;
 185  186  
 186  187          /* Figure out whether the hypervisor is 32-bit or 64-bit.  */
 187  188          if ((HYPERVISOR_xen_version(XENVER_capabilities, &caps) == 0)) {
 188  189                  ((char *)(caps))[sizeof (caps) - 1] = '\0';
 189  190                  if (strstr(caps, "x86_64") != NULL)
 190  191                          xen_bits = 64;
 191  192                  else if (strstr(caps, "x86_32") != NULL)
 192  193                          xen_bits = 32;
 193  194          }
 194  195  
 195  196          if (xen_bits < 0)
 196  197                  return;
 197  198  #ifdef __amd64
 198  199          ASSERT(xen_bits == 64);
 199  200  #endif
 200  201  
 201  202          /*
 202  203           * Allocate space for the shared_info page and tell Xen where it
 203  204           * is.
 204  205           */
 205  206          xen_shared_info_frame = va_to_pfn(&hypercall_shared_info_page);
 206  207          xatp.domid = DOMID_SELF;
 207  208          xatp.idx = 0;
 208  209          xatp.space = XENMAPSPACE_shared_info;
 209  210          xatp.gpfn = xen_shared_info_frame;
  
    | 
      ↓ open down ↓ | 
    98 lines elided | 
    
      ↑ open up ↑ | 
  
 210  211          if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0)
 211  212                  return;
 212  213  
 213  214          HYPERVISOR_shared_info = (void *)&hypercall_shared_info_page;
 214  215  
 215  216          /*
 216  217           * A working HVM tlb flush hypercall was introduced in Xen 3.3.
 217  218           */
 218  219          if (xen_major > 3 || (xen_major == 3 && xen_minor >= 3))
 219  220                  xen_hvm_features |= XEN_HVM_TLBFLUSH;
      221 +
      222 +        /* FIXME Disable apix for the time being */
      223 +        apix_enable = 0;
 220  224  }
 221  225  
 222  226  /*
 223  227   * Returns:
 224  228   *          -1 if a feature is not available
 225  229   *          1 if a boolean feature is available
 226  230   *          > 0 if numeric feature is available
 227  231   */
 228  232  int
 229  233  xpv_feature(int which)
 230  234  {
 231  235          switch (which) {
 232  236          case XPVF_BITS:
 233  237                  return (xen_bits);
 234  238          case XPVF_VERSION_MAJOR:
 235  239                  return (xen_major);
 236  240          case XPVF_VERSION_MINOR:
 237  241                  return (xen_minor);
 238  242          case XPVF_HYPERCALLS:
 239  243                  if (xen_hvm_features & XEN_HVM_HYPERCALLS)
 240  244                          return (1);
 241  245                  break;
 242  246          case XPVF_SHARED_INFO:
 243  247                  if (HYPERVISOR_shared_info != NULL)
 244  248                          return (1);
 245  249                  break;
 246  250          case XPVF_TLB_FLUSH:
 247  251                  if (xen_hvm_features & XEN_HVM_TLBFLUSH)
 248  252                          return (1);
 249  253                  break;
 250  254          default:
 251  255                  break;
 252  256          }
 253  257  
 254  258          return (-1);
 255  259  }
  
    | 
      ↓ open down ↓ | 
    26 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX