/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <sys/archsystm.h>
#include <sys/machsystm.h>
#include <sys/ddi_subrdefs.h>
#include <sys/xpv_support.h>
#include <sys/xen_errno.h>
#include <sys/hypervisor.h>
#include <sys/xenbus_comms.h>
#include <sys/xenbus_impl.h>
#include <sys/sysmacros.h>
#include <sys/x86_archext.h>
#include <vm/seg_kmem.h>
static int xen_hvm_inited;
/*
* This structure is ordinarily constructed by Xen. In the HVM world, we
* manually fill in the few fields the PV drivers need.
*/
/*
* Feature bits; more bits will be added, like direct I/O, etc.
*/
/* Metadata page shared between domain and Xen */
/* Page containing code to issue hypercalls. */
extern caddr_t hypercall_page;
extern caddr_t hypercall_shared_info_page;
static int
{
return (-1);
return (0);
}
void
xen_hvm_init(void)
{
char *xen_str;
if (xen_hvm_inited != 0)
return;
xen_hvm_inited = 1;
/*
* Xen's pseudo-cpuid function returns a string representing
* the Xen signature in %ebx, %ecx, and %edx.
* Loop over the base values, since it may be different if
* the hypervisor has hyper-v emulation switched on.
*
* %eax contains the maximum supported cpuid function.
*/
(void) __cpuid_insn(&cp);
xen_signature[3] = 0;
xen_str = (char *)xen_signature;
break;
}
if (base >= 0x40010000)
return;
/*
* cpuid function at base + 1 returns the Xen version in %eax. The
* top 16 bits are the major version, the bottom 16 are the minor
* version.
*/
(void) __cpuid_insn(&cp);
/*
* Below version 3.1 we can't do anything special as a HVM domain;
* the PV drivers don't work, many hypercalls are not available,
* etc.
*/
return;
/*
* cpuid function at base + 2 returns information about the
* hypercall page. %eax nominally contains the number of pages
* with hypercall code, but according to the Xen guys, "I'll
* guarantee that remains one forever more, so you can just
* allocate a single page and get quite upset if you ever see CPUID
* return more than one page." %ebx contains an MSR we use to ask
* Xen to remap each page at a specific pfn.
*/
(void) __cpuid_insn(&cp);
/*
* Let Xen know where we want the hypercall page mapped. We
* already have a page allocated in the .text section to simplify
* the wrapper code.
*/
/* Fill in the xen_info data */
xen_info = &__xen_info;
return;
/*
* The first hypercall worked, so mark hypercalls as working.
*/
return;
/* Figure out whether the hypervisor is 32-bit or 64-bit. */
xen_bits = 64;
xen_bits = 32;
}
if (xen_bits < 0)
return;
#ifdef __amd64
#endif
/*
* Allocate space for the shared_info page and tell Xen where it
* is.
*/
return;
HYPERVISOR_shared_info = (void *)&hypercall_shared_info_page;
/*
* A working HVM tlb flush hypercall was introduced in Xen 3.3.
*/
}
/*
* Returns:
* -1 if a feature is not available
* 1 if a boolean feature is available
* > 0 if numeric feature is available
*/
int
{
switch (which) {
case XPVF_BITS:
return (xen_bits);
case XPVF_VERSION_MAJOR:
return (xen_major);
case XPVF_VERSION_MINOR:
return (xen_minor);
case XPVF_HYPERCALLS:
return (1);
break;
case XPVF_SHARED_INFO:
if (HYPERVISOR_shared_info != NULL)
return (1);
break;
case XPVF_TLB_FLUSH:
if (xen_hvm_features & XEN_HVM_TLBFLUSH)
return (1);
break;
default:
break;
}
return (-1);
}