summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pv/pvbus.c81
-rw-r--r--sys/dev/pv/pvreg.h49
-rw-r--r--sys/dev/pv/pvvar.h28
-rw-r--r--sys/dev/pv/vmt.c7
4 files changed, 121 insertions, 44 deletions
diff --git a/sys/dev/pv/pvbus.c b/sys/dev/pv/pvbus.c
index 33a1ccb48ee..4ee70ddede5 100644
--- a/sys/dev/pv/pvbus.c
+++ b/sys/dev/pv/pvbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pvbus.c,v 1.3 2015/07/23 12:08:42 reyk Exp $ */
+/* $OpenBSD: pvbus.c,v 1.4 2015/07/28 09:48:52 reyk Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -49,6 +49,9 @@ void pvbus_attach(struct device *, struct device *, void *);
int pvbus_print(void *, const char *);
int pvbus_search(struct device *, void *, void *);
+void pvbus_kvm(struct pvbus_softc *, struct pvbus_hv *);
+void pvbus_hyperv(struct pvbus_softc *, struct pvbus_hv *);
+
struct cfattach pvbus_ca = {
sizeof(struct pvbus_softc),
pvbus_match,
@@ -66,14 +69,13 @@ struct cfdriver pvbus_cd = {
struct pvbus_type {
const char *signature;
const char *name;
- unsigned int type;
-} pvbus_types[] = {
- { "KVMKVMKVM\0\0\0", "KVM", PVBUS_KVM },
- { "Microsoft Hv", "Hyper-V", PVBUS_HYPERV },
- { "VMwareVMware", "VMware", PVBUS_VMWARE },
- { "XenVMMXenVMM", "Xen", PVBUS_XEN },
- { "bhyve bhyve ", "bhyve", PVBUS_BHYVE },
- { NULL }
+ void (*init)(struct pvbus_softc *, struct pvbus_hv *);
+} pvbus_types[PVBUS_MAX] = {
+ { "KVMKVMKVM\0\0\0", "KVM", pvbus_kvm },
+ { "Microsoft Hv", "Hyper-V", pvbus_hyperv },
+ { "VMwareVMware", "VMware", NULL },
+ { "XenVMMXenVMM", "Xen", NULL },
+ { "bhyve bhyve ", "bhyve", NULL }
};
int
@@ -96,16 +98,17 @@ void
pvbus_attach(struct device *parent, struct device *self, void *aux)
{
struct pvbus_softc *sc = (struct pvbus_softc *)self;
+ struct pvbus_hv *hv;
uint32_t reg0, base;
union {
uint32_t regs[3];
char str[CPUID_HV_SIGNATURE_STRLEN];
} r;
- int i;
+ int i, cnt;
printf(":");
- for (base = CPUID_HV_SIGNATURE_START;
+ for (base = CPUID_HV_SIGNATURE_START, cnt = 0;
base < CPUID_HV_SIGNATURE_END;
base += CPUID_HV_SIGNATURE_STEP) {
CPUID(base, reg0, r.regs[0], r.regs[1], r.regs[2]);
@@ -118,32 +121,23 @@ pvbus_attach(struct device *parent, struct device *self, void *aux)
goto out;
}
- for (i = 0; pvbus_types[i].signature != NULL; i++) {
+ for (i = 0; i < PVBUS_MAX; i++) {
if (memcmp(pvbus_types[i].signature, r.str,
CPUID_HV_SIGNATURE_STRLEN) != 0)
continue;
- sc->pvbus_types |= pvbus_types[i].type;
+ hv = &sc->pvbus_hv[i];
+ hv->hv_base = base;
+ if (cnt++)
+ printf(",");
printf(" %s", pvbus_types[i].name);
+ if (pvbus_types[i].init != NULL)
+ (pvbus_types[i].init)(sc, hv);
}
}
out:
printf("\n");
-
-#ifdef notyet
- /* XXX get hypervisor-specific features */
- if (sc->pvbus_types & PVBUS_KVM) {
- kvm_cpuid_base = base;
- CPUID(base + CPUID_OFFSET_KVM_FEATURES,
- reg0, r.regs[0], r.regs[1], r.regs[2]);
- kvm_features = reg0;
- }
- if (sc->pvbus_types & PVBUS_HYPERV) {
- /* XXX */
- }
-#endif
-
config_search(pvbus_search, self, sc);
}
@@ -178,7 +172,7 @@ pvbus_search(struct device *parent, void *arg, void *aux)
struct pv_attach_args pva;
pva.pva_busname = cf->cf_driver->cd_name;
- pva.pva_types = sc->pvbus_types;
+ pva.pva_hv = sc->pvbus_hv;
if (cf->cf_attach->ca_match(parent, cf, &pva) > 0)
config_attach(parent, cf, &pva, pvbus_print);
@@ -194,3 +188,34 @@ pvbus_print(void *aux, const char *pnp)
printf("%s at %s", pva->pva_busname, pnp);
return (UNCONF);
}
+
+void
+pvbus_kvm(struct pvbus_softc *sc, struct pvbus_hv *hv)
+{
+ uint32_t regs[4];
+
+ CPUID(hv->hv_base + CPUID_OFFSET_KVM_FEATURES,
+ regs[0], regs[1], regs[2], regs[3]);
+ hv->hv_features = regs[0];
+}
+
+void
+pvbus_hyperv(struct pvbus_softc *sc, struct pvbus_hv *hv)
+{
+ uint32_t regs[4];
+
+ CPUID(hv->hv_base + CPUID_OFFSET_HYPERV_FEATURES,
+ regs[0], regs[1], regs[2], regs[3]);
+ hv->hv_features = regs[0];
+
+ CPUID(hv->hv_base + CPUID_OFFSET_HYPERV_VERSION,
+ regs[0], regs[1], regs[2], regs[3]);
+ hv->hv_version = regs[1];
+
+ printf(" %u.%u.%u",
+ (regs[1] & HYPERV_VERSION_EBX_MAJOR_M) >>
+ HYPERV_VERSION_EBX_MAJOR_S,
+ (regs[1] & HYPERV_VERSION_EBX_MINOR_M) >>
+ HYPERV_VERSION_EBX_MINOR_S,
+ regs[0]);
+}
diff --git a/sys/dev/pv/pvreg.h b/sys/dev/pv/pvreg.h
index 1fa19dee558..41485dd305f 100644
--- a/sys/dev/pv/pvreg.h
+++ b/sys/dev/pv/pvreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pvreg.h,v 1.1 2015/07/21 03:38:22 reyk Exp $ */
+/* $OpenBSD: pvreg.h,v 1.2 2015/07/28 09:48:52 reyk Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -25,7 +25,9 @@
#define CPUID_HV_SIGNATURE_STEP 0x100
#define CPUID_HV_SIGNATURE_STRLEN 12
-/* KVM */
+/*
+ * KVM
+ */
#define CPUID_OFFSET_KVM_FEATURES 0x1
#define KVM_FEATURE_CLOCKSOURCE 0 /* deprecated */
@@ -38,8 +40,47 @@
#define KVM_FEATURE_PV_UNHALT 7
#define KVM_FEATURE_CLOCKSOURCE_STABLE_BIT 24
-#define MSR_KVM_EOI_EN 0x4b564d04
-
+#define KVM_MSR_EOI_EN 0x4b564d04
#define KVM_PV_EOI_BIT 0
+/*
+ * Hyper-V
+ */
+#define CPUID_OFFSET_HYPERV_INTERFACE 0x1
+#define CPUID_OFFSET_HYPERV_VERSION 0x2
+#define CPUID_OFFSET_HYPERV_FEATURES 0x3
+#define CPUID_OFFSET_HYPERV_ENLIGHTENMENT_INFO 0x4
+#define CPUID_OFFSET_HYPERV_IMPL_LIMITS 0x5
+
+#define HYPERV_VERSION_EAX_BUILD_NUMBER 0
+#define HYPERV_VERSION_EBX_MAJOR_M 0xffff0000
+#define HYPERV_VERSION_EBX_MAJOR_S 16
+#define HYPERV_VERSION_EBX_MINOR_M 0x0000ffff
+#define HYPERV_VERSION_EBX_MINOR_S 0
+#define HYPERV_VERSION_ECX_SERVICE_PACK 0
+#define HYPERV_VERSION_EDX_SERVICE_BRANCH_M 0xff000000
+#define HYPERV_VERSION_EDX_SERVICE_BRANCH_S 24
+#define HYPERV_VERSION_EDX_SERVICE_NUMBER_M 0x00ffffff
+#define HYPERV_VERSION_EDX_SERVICE_NUMBER_S 0
+
+#define HYPERV_VERSION_WS2008 0x00060000
+#define HYPERV_VERSION_WIN7 0x00060001
+#define HYPERV_VERSION_WIN8 0x00060002
+#define HYPERV_VERSION_WIN8_1 0x00060003
+#define HYPERV_VERSION_WIN10 0x00100000
+
+#define HYPERV_FEATURE_EAX_VP_RUNTIME 0
+#define HYPERV_FEATURE_EAX_TIME_REF_COUNT 1
+#define HYPERV_FEATURE_EAX_SYNIC 2
+#define HYPERV_FEATURE_EAX_STIMER 3
+#define HYPERV_FEATURE_EAX_APIC 4
+#define HYPERV_FEATURE_EAX_HYPERCALL 5
+#define HYPERV_FEATURE_EAX_VP_INDEX 6
+#define HYPERV_FEATURE_EAX_MSR_RESET 7
+#define HYPERV_FEATURE_EAX_STATS_PAGES 8
+#define HYPERV_FEATURE_EAX_REF_TSC 9
+#define HYPERV_FEATURE_EAX_GUEST_IDLE 10
+#define HYPERV_FEATURE_EAX_TIMER_FREQ 11
+#define HYPERV_FEATURE_EAX_DEBUG 12
+
#endif /* _DEV_PV_PVBUS_H_ */
diff --git a/sys/dev/pv/pvvar.h b/sys/dev/pv/pvvar.h
index c5b5777e2ec..c44ed5b4fe7 100644
--- a/sys/dev/pv/pvvar.h
+++ b/sys/dev/pv/pvvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pvvar.h,v 1.3 2015/07/23 12:08:42 reyk Exp $ */
+/* $OpenBSD: pvvar.h,v 1.4 2015/07/28 09:48:52 reyk Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -19,9 +19,25 @@
#ifndef _DEV_PV_PVVAR_H_
#define _DEV_PV_PVVAR_H_
+enum {
+ PVBUS_KVM,
+ PVBUS_HYPERV,
+ PVBUS_VMWARE,
+ PVBUS_XEN,
+ PVBUS_BHYVE,
+
+ PVBUS_MAX
+};
+
+struct pvbus_hv {
+ uint32_t hv_base;
+ uint32_t hv_features;
+ uint32_t hv_version;
+};
+
struct pvbus_softc {
struct device pvbus_dev;
- uint8_t pvbus_types;
+ struct pvbus_hv pvbus_hv[PVBUS_MAX];
};
struct pvbus_attach_args {
@@ -30,17 +46,11 @@ struct pvbus_attach_args {
struct pv_attach_args {
const char *pva_busname;
- uint8_t pva_types; /* detected hv types */
+ struct pvbus_hv *pva_hv;
};
extern int has_hv_cpuid;
-#define PVBUS_KVM 0x01
-#define PVBUS_HYPERV 0x02
-#define PVBUS_VMWARE 0x04
-#define PVBUS_XEN 0x08
-#define PVBUS_BHYVE 0x10
-
int pvbus_probe(void);
#endif /* _DEV_PV_PVBUS_H_ */
diff --git a/sys/dev/pv/vmt.c b/sys/dev/pv/vmt.c
index 52f9cd884bc..0281b4e39b8 100644
--- a/sys/dev/pv/vmt.c
+++ b/sys/dev/pv/vmt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmt.c,v 1.2 2015/07/21 17:59:58 reyk Exp $ */
+/* $OpenBSD: vmt.c,v 1.3 2015/07/28 09:48:52 reyk Exp $ */
/*
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
@@ -318,9 +318,10 @@ vmt_probe(void)
int
vmt_match(struct device *parent, void *match, void *aux)
{
- struct pv_attach_args *pva = aux;
+ struct pv_attach_args *pva = aux;
+ struct pvbus_hv *hv = &pva->pva_hv[PVBUS_VMWARE];
- if ((pva->pva_types & PVBUS_VMWARE) == 0)
+ if (hv->hv_base == 0)
return (0);
if (!vmt_probe())
return (0);