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