diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pv/pvbus.c | 81 | ||||
-rw-r--r-- | sys/dev/pv/pvreg.h | 49 | ||||
-rw-r--r-- | sys/dev/pv/pvvar.h | 28 | ||||
-rw-r--r-- | sys/dev/pv/vmt.c | 7 |
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); |