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