1349b53ddSStuart Maybee /* 2349b53ddSStuart Maybee * CDDL HEADER START 3349b53ddSStuart Maybee * 4349b53ddSStuart Maybee * The contents of this file are subject to the terms of the 5349b53ddSStuart Maybee * Common Development and Distribution License (the "License"). 6349b53ddSStuart Maybee * You may not use this file except in compliance with the License. 7349b53ddSStuart Maybee * 8349b53ddSStuart Maybee * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9349b53ddSStuart Maybee * or http://www.opensolaris.org/os/licensing. 10349b53ddSStuart Maybee * See the License for the specific language governing permissions 11349b53ddSStuart Maybee * and limitations under the License. 12349b53ddSStuart Maybee * 13349b53ddSStuart Maybee * When distributing Covered Code, include this CDDL HEADER in each 14349b53ddSStuart Maybee * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15349b53ddSStuart Maybee * If applicable, add the following below this CDDL HEADER, with the 16349b53ddSStuart Maybee * fields enclosed by brackets "[]" replaced with your own identifying 17349b53ddSStuart Maybee * information: Portions Copyright [yyyy] [name of copyright owner] 18349b53ddSStuart Maybee * 19349b53ddSStuart Maybee * CDDL HEADER END 20349b53ddSStuart Maybee */ 21349b53ddSStuart Maybee /* 22*6e5580c9SFrank Van Der Linden * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 23349b53ddSStuart Maybee */ 24349b53ddSStuart Maybee 25349b53ddSStuart Maybee #include <sys/types.h> 26349b53ddSStuart Maybee #include <sys/archsystm.h> 27349b53ddSStuart Maybee #include <sys/machsystm.h> 28349b53ddSStuart Maybee #include <sys/sunndi.h> 29349b53ddSStuart Maybee #include <sys/sunddi.h> 30349b53ddSStuart Maybee #include <sys/ddi_subrdefs.h> 31349b53ddSStuart Maybee #include <sys/xpv_support.h> 32349b53ddSStuart Maybee #include <sys/xen_errno.h> 33349b53ddSStuart Maybee #include <sys/hypervisor.h> 34349b53ddSStuart Maybee #include <sys/gnttab.h> 35349b53ddSStuart Maybee #include <sys/xenbus_comms.h> 36349b53ddSStuart Maybee #include <sys/xenbus_impl.h> 37349b53ddSStuart Maybee #include <sys/sysmacros.h> 38349b53ddSStuart Maybee #include <sys/x86_archext.h> 39349b53ddSStuart Maybee #include <sys/mman.h> 40349b53ddSStuart Maybee #include <sys/stat.h> 41349b53ddSStuart Maybee #include <sys/conf.h> 42349b53ddSStuart Maybee #include <sys/devops.h> 43349b53ddSStuart Maybee #include <sys/pc_mmu.h> 44349b53ddSStuart Maybee #include <sys/cmn_err.h> 45349b53ddSStuart Maybee #include <sys/cpr.h> 46349b53ddSStuart Maybee #include <sys/ddi.h> 47349b53ddSStuart Maybee #include <vm/seg_kmem.h> 48349b53ddSStuart Maybee #include <vm/as.h> 49349b53ddSStuart Maybee #include <vm/hat_pte.h> 50349b53ddSStuart Maybee #include <vm/hat_i86.h> 51349b53ddSStuart Maybee 52349b53ddSStuart Maybee static int xen_hvm_inited; 53349b53ddSStuart Maybee 54349b53ddSStuart Maybee /* 55349b53ddSStuart Maybee * This structure is ordinarily constructed by Xen. In the HVM world, we 56349b53ddSStuart Maybee * manually fill in the few fields the PV drivers need. 57349b53ddSStuart Maybee */ 58349b53ddSStuart Maybee static start_info_t __xen_info; 59349b53ddSStuart Maybee start_info_t *xen_info = NULL; 60349b53ddSStuart Maybee 61349b53ddSStuart Maybee static int xen_bits = -1; 62349b53ddSStuart Maybee static int xen_major = -1, xen_minor = -1; 63349b53ddSStuart Maybee 64349b53ddSStuart Maybee /* 65349b53ddSStuart Maybee * Feature bits; more bits will be added, like direct I/O, etc. 66349b53ddSStuart Maybee */ 67349b53ddSStuart Maybee #define XEN_HVM_HYPERCALLS 0x0001 68349b53ddSStuart Maybee #define XEN_HVM_TLBFLUSH 0x0002 69349b53ddSStuart Maybee static uint64_t xen_hvm_features; 70349b53ddSStuart Maybee 71349b53ddSStuart Maybee /* Metadata page shared between domain and Xen */ 72349b53ddSStuart Maybee shared_info_t *HYPERVISOR_shared_info = NULL; 73349b53ddSStuart Maybee pfn_t xen_shared_info_frame; 74349b53ddSStuart Maybee 75349b53ddSStuart Maybee /* Page containing code to issue hypercalls. */ 76349b53ddSStuart Maybee extern caddr_t hypercall_page; 77349b53ddSStuart Maybee extern caddr_t hypercall_shared_info_page; 78349b53ddSStuart Maybee 79349b53ddSStuart Maybee static int 80349b53ddSStuart Maybee hvm_get_param(int param_id, uint64_t *val) 81349b53ddSStuart Maybee { 82349b53ddSStuart Maybee struct xen_hvm_param xhp; 83349b53ddSStuart Maybee 84349b53ddSStuart Maybee xhp.domid = DOMID_SELF; 85349b53ddSStuart Maybee xhp.index = param_id; 86349b53ddSStuart Maybee if ((HYPERVISOR_hvm_op(HVMOP_get_param, &xhp) < 0)) 87349b53ddSStuart Maybee return (-1); 88349b53ddSStuart Maybee *val = xhp.value; 89349b53ddSStuart Maybee return (0); 90349b53ddSStuart Maybee } 91349b53ddSStuart Maybee 92349b53ddSStuart Maybee void 93349b53ddSStuart Maybee xen_hvm_init(void) 94349b53ddSStuart Maybee { 95349b53ddSStuart Maybee struct cpuid_regs cp; 96*6e5580c9SFrank Van Der Linden uint32_t xen_signature[4], base; 97349b53ddSStuart Maybee char *xen_str; 98349b53ddSStuart Maybee struct xen_add_to_physmap xatp; 99349b53ddSStuart Maybee xen_capabilities_info_t caps; 100349b53ddSStuart Maybee pfn_t pfn; 101349b53ddSStuart Maybee uint64_t msrval, val; 102349b53ddSStuart Maybee 103349b53ddSStuart Maybee if (xen_hvm_inited != 0) 104349b53ddSStuart Maybee return; 105349b53ddSStuart Maybee 106349b53ddSStuart Maybee xen_hvm_inited = 1; 107349b53ddSStuart Maybee 108349b53ddSStuart Maybee /* 109*6e5580c9SFrank Van Der Linden * Xen's pseudo-cpuid function returns a string representing 110*6e5580c9SFrank Van Der Linden * the Xen signature in %ebx, %ecx, and %edx. 111*6e5580c9SFrank Van Der Linden * Loop over the base values, since it may be different if 112*6e5580c9SFrank Van Der Linden * the hypervisor has hyper-v emulation switched on. 113*6e5580c9SFrank Van Der Linden * 114349b53ddSStuart Maybee * %eax contains the maximum supported cpuid function. 115349b53ddSStuart Maybee */ 116*6e5580c9SFrank Van Der Linden for (base = 0x40000000; base < 0x40010000; base += 0x100) { 117*6e5580c9SFrank Van Der Linden cp.cp_eax = base; 118349b53ddSStuart Maybee (void) __cpuid_insn(&cp); 119349b53ddSStuart Maybee xen_signature[0] = cp.cp_ebx; 120349b53ddSStuart Maybee xen_signature[1] = cp.cp_ecx; 121349b53ddSStuart Maybee xen_signature[2] = cp.cp_edx; 122349b53ddSStuart Maybee xen_signature[3] = 0; 123349b53ddSStuart Maybee xen_str = (char *)xen_signature; 124*6e5580c9SFrank Van Der Linden if (strcmp("XenVMMXenVMM", xen_str) == 0 && 125*6e5580c9SFrank Van Der Linden cp.cp_eax >= (base + 2)) 126*6e5580c9SFrank Van Der Linden break; 127*6e5580c9SFrank Van Der Linden } 128*6e5580c9SFrank Van Der Linden if (base >= 0x40010000) 129349b53ddSStuart Maybee return; 130349b53ddSStuart Maybee 131349b53ddSStuart Maybee /* 132*6e5580c9SFrank Van Der Linden * cpuid function at base + 1 returns the Xen version in %eax. The 133349b53ddSStuart Maybee * top 16 bits are the major version, the bottom 16 are the minor 134349b53ddSStuart Maybee * version. 135349b53ddSStuart Maybee */ 136*6e5580c9SFrank Van Der Linden cp.cp_eax = base + 1; 137349b53ddSStuart Maybee (void) __cpuid_insn(&cp); 138349b53ddSStuart Maybee xen_major = cp.cp_eax >> 16; 139349b53ddSStuart Maybee xen_minor = cp.cp_eax & 0xffff; 140349b53ddSStuart Maybee 141349b53ddSStuart Maybee /* 142349b53ddSStuart Maybee * Below version 3.1 we can't do anything special as a HVM domain; 143349b53ddSStuart Maybee * the PV drivers don't work, many hypercalls are not available, 144349b53ddSStuart Maybee * etc. 145349b53ddSStuart Maybee */ 146349b53ddSStuart Maybee if (xen_major < 3 || (xen_major == 3 && xen_minor < 1)) 147349b53ddSStuart Maybee return; 148349b53ddSStuart Maybee 149349b53ddSStuart Maybee /* 150*6e5580c9SFrank Van Der Linden * cpuid function at base + 2 returns information about the 151349b53ddSStuart Maybee * hypercall page. %eax nominally contains the number of pages 152349b53ddSStuart Maybee * with hypercall code, but according to the Xen guys, "I'll 153349b53ddSStuart Maybee * guarantee that remains one forever more, so you can just 154349b53ddSStuart Maybee * allocate a single page and get quite upset if you ever see CPUID 155349b53ddSStuart Maybee * return more than one page." %ebx contains an MSR we use to ask 156349b53ddSStuart Maybee * Xen to remap each page at a specific pfn. 157349b53ddSStuart Maybee */ 158*6e5580c9SFrank Van Der Linden cp.cp_eax = base + 2; 159349b53ddSStuart Maybee (void) __cpuid_insn(&cp); 160349b53ddSStuart Maybee 161349b53ddSStuart Maybee /* 162349b53ddSStuart Maybee * Let Xen know where we want the hypercall page mapped. We 163349b53ddSStuart Maybee * already have a page allocated in the .text section to simplify 164349b53ddSStuart Maybee * the wrapper code. 165349b53ddSStuart Maybee */ 166349b53ddSStuart Maybee pfn = va_to_pfn(&hypercall_page); 167349b53ddSStuart Maybee msrval = mmu_ptob(pfn); 168349b53ddSStuart Maybee wrmsr(cp.cp_ebx, msrval); 169349b53ddSStuart Maybee 170349b53ddSStuart Maybee /* Fill in the xen_info data */ 171349b53ddSStuart Maybee xen_info = &__xen_info; 172349b53ddSStuart Maybee (void) sprintf(xen_info->magic, "xen-%d.%d", xen_major, xen_minor); 173349b53ddSStuart Maybee 174349b53ddSStuart Maybee if (hvm_get_param(HVM_PARAM_STORE_PFN, &val) < 0) 175349b53ddSStuart Maybee return; 176349b53ddSStuart Maybee /* 177349b53ddSStuart Maybee * The first hypercall worked, so mark hypercalls as working. 178349b53ddSStuart Maybee */ 179349b53ddSStuart Maybee xen_hvm_features |= XEN_HVM_HYPERCALLS; 180349b53ddSStuart Maybee 181349b53ddSStuart Maybee xen_info->store_mfn = (mfn_t)val; 182349b53ddSStuart Maybee if (hvm_get_param(HVM_PARAM_STORE_EVTCHN, &val) < 0) 183349b53ddSStuart Maybee return; 184349b53ddSStuart Maybee xen_info->store_evtchn = (mfn_t)val; 185349b53ddSStuart Maybee 186349b53ddSStuart Maybee /* Figure out whether the hypervisor is 32-bit or 64-bit. */ 187349b53ddSStuart Maybee if ((HYPERVISOR_xen_version(XENVER_capabilities, &caps) == 0)) { 188349b53ddSStuart Maybee ((char *)(caps))[sizeof (caps) - 1] = '\0'; 189349b53ddSStuart Maybee if (strstr(caps, "x86_64") != NULL) 190349b53ddSStuart Maybee xen_bits = 64; 191349b53ddSStuart Maybee else if (strstr(caps, "x86_32") != NULL) 192349b53ddSStuart Maybee xen_bits = 32; 193349b53ddSStuart Maybee } 194349b53ddSStuart Maybee 195349b53ddSStuart Maybee if (xen_bits < 0) 196349b53ddSStuart Maybee return; 197349b53ddSStuart Maybee #ifdef __amd64 198349b53ddSStuart Maybee ASSERT(xen_bits == 64); 199349b53ddSStuart Maybee #endif 200349b53ddSStuart Maybee 201349b53ddSStuart Maybee /* 202349b53ddSStuart Maybee * Allocate space for the shared_info page and tell Xen where it 203349b53ddSStuart Maybee * is. 204349b53ddSStuart Maybee */ 205349b53ddSStuart Maybee xen_shared_info_frame = va_to_pfn(&hypercall_shared_info_page); 206349b53ddSStuart Maybee xatp.domid = DOMID_SELF; 207349b53ddSStuart Maybee xatp.idx = 0; 208349b53ddSStuart Maybee xatp.space = XENMAPSPACE_shared_info; 209349b53ddSStuart Maybee xatp.gpfn = xen_shared_info_frame; 210349b53ddSStuart Maybee if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0) 211349b53ddSStuart Maybee return; 212349b53ddSStuart Maybee 213349b53ddSStuart Maybee HYPERVISOR_shared_info = (void *)&hypercall_shared_info_page; 214349b53ddSStuart Maybee 215349b53ddSStuart Maybee /* 216349b53ddSStuart Maybee * A working HVM tlb flush hypercall was introduced in Xen 3.3. 217349b53ddSStuart Maybee */ 218349b53ddSStuart Maybee if (xen_major > 3 || (xen_major == 3 && xen_minor >= 3)) 219349b53ddSStuart Maybee xen_hvm_features |= XEN_HVM_TLBFLUSH; 220349b53ddSStuart Maybee } 221349b53ddSStuart Maybee 222349b53ddSStuart Maybee /* 223349b53ddSStuart Maybee * Returns: 224349b53ddSStuart Maybee * -1 if a feature is not available 225349b53ddSStuart Maybee * 1 if a boolean feature is available 226349b53ddSStuart Maybee * > 0 if numeric feature is available 227349b53ddSStuart Maybee */ 228349b53ddSStuart Maybee int 229349b53ddSStuart Maybee xpv_feature(int which) 230349b53ddSStuart Maybee { 231349b53ddSStuart Maybee switch (which) { 232349b53ddSStuart Maybee case XPVF_BITS: 233349b53ddSStuart Maybee return (xen_bits); 234349b53ddSStuart Maybee case XPVF_VERSION_MAJOR: 235349b53ddSStuart Maybee return (xen_major); 236349b53ddSStuart Maybee case XPVF_VERSION_MINOR: 237349b53ddSStuart Maybee return (xen_minor); 238349b53ddSStuart Maybee case XPVF_HYPERCALLS: 239349b53ddSStuart Maybee if (xen_hvm_features & XEN_HVM_HYPERCALLS) 240349b53ddSStuart Maybee return (1); 241349b53ddSStuart Maybee break; 242349b53ddSStuart Maybee case XPVF_SHARED_INFO: 243349b53ddSStuart Maybee if (HYPERVISOR_shared_info != NULL) 244349b53ddSStuart Maybee return (1); 245349b53ddSStuart Maybee break; 246349b53ddSStuart Maybee case XPVF_TLB_FLUSH: 247349b53ddSStuart Maybee if (xen_hvm_features & XEN_HVM_TLBFLUSH) 248349b53ddSStuart Maybee return (1); 249349b53ddSStuart Maybee break; 250349b53ddSStuart Maybee default: 251349b53ddSStuart Maybee break; 252349b53ddSStuart Maybee } 253349b53ddSStuart Maybee 254349b53ddSStuart Maybee return (-1); 255349b53ddSStuart Maybee } 256