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