From 43a02131947097389a971434f30b4627962ea721 Mon Sep 17 00:00:00 2001 From: sephe Date: Thu, 15 Dec 2016 03:32:24 +0000 Subject: [PATCH] hyperv: Allow userland to ro-mmap reference TSC page This paves way to implement VDSO for the enlightened time counter. Reviewed by: kib MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8768 --- include/Makefile | 8 ++++ sys/dev/hyperv/include/hyperv.h | 31 ++++++++++--- sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c | 49 +++++++++++++++++++++ sys/dev/hyperv/vmbus/hyperv_reg.h | 11 ----- 4 files changed, 83 insertions(+), 16 deletions(-) diff --git a/include/Makefile b/include/Makefile index af291fa24b03..3032785e2543 100644 --- a/include/Makefile +++ b/include/Makefile @@ -185,6 +185,9 @@ copies: .PHONY .META ${DESTDIR}${INCLUDEDIR}/dev/evdev; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 uinput.h \ ${DESTDIR}${INCLUDEDIR}/dev/evdev + cd ${.CURDIR}/../sys/dev/hyperv/include; \ + ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 hyperv.h \ + ${DESTDIR}${INCLUDEDIR}/dev/hyperv cd ${.CURDIR}/../sys/dev/hyperv/utilities; \ ${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 hv_snapshot.h \ ${DESTDIR}${INCLUDEDIR}/dev/hyperv @@ -293,6 +296,11 @@ symlinks: .PHONY .META ln -fs ../../../../sys/dev/evdev/$$h \ ${DESTDIR}${INCLUDEDIR}/dev/evdev; \ done + cd ${.CURDIR}/../sys/dev/hyperv/include; \ + for h in hyperv.h; do \ + ${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/hyperv/include/$$h \ + ${DESTDIR}${INCLUDEDIR}/dev/hyperv; \ + done cd ${.CURDIR}/../sys/dev/hyperv/utilities; \ for h in hv_snapshot.h; do \ ${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/hyperv/utilities/$$h \ diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h index 44851444d26f..0eda9f0691a3 100644 --- a/sys/dev/hyperv/include/hyperv.h +++ b/sys/dev/hyperv/include/hyperv.h @@ -31,10 +31,10 @@ #ifndef _HYPERV_H_ #define _HYPERV_H_ -#include +#ifdef _KERNEL -#include -#include +#include +#include #define MSR_HV_TIME_REF_COUNT 0x40000020 @@ -54,14 +54,35 @@ #define HYPERV_TIMER_NS_FACTOR 100ULL #define HYPERV_TIMER_FREQ (NANOSEC / HYPERV_TIMER_NS_FACTOR) +#endif /* _KERNEL */ + +#define HYPERV_REFTSC_DEVNAME "hv_tsc" + +/* + * Hyper-V Reference TSC + */ +struct hyperv_reftsc { + volatile uint32_t tsc_seq; + volatile uint32_t tsc_rsvd1; + volatile uint64_t tsc_scale; + volatile int64_t tsc_ofs; +} __packed __aligned(PAGE_SIZE); +#ifdef CTASSERT +CTASSERT(sizeof(struct hyperv_reftsc) == PAGE_SIZE); +#endif + +#ifdef _KERNEL + struct hyperv_guid { - uint8_t hv_guid[16]; + uint8_t hv_guid[16]; } __packed; -#define HYPERV_GUID_STRLEN 40 +#define HYPERV_GUID_STRLEN 40 int hyperv_guid2str(const struct hyperv_guid *, char *, size_t); extern u_int hyperv_features; /* CPUID_HV_MSR_ */ +#endif /* _KERNEL */ + #endif /* _HYPERV_H_ */ diff --git a/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c b/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c index 712a6e22994b..abf0372bb31e 100644 --- a/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c +++ b/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c @@ -28,6 +28,8 @@ __FBSDID("$FreeBSD$"); #include +#include +#include #include #include #include @@ -35,6 +37,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include + +#include #include #include @@ -47,6 +52,9 @@ struct hyperv_reftsc_ctx { struct hyperv_dma tsc_ref_dma; }; +static d_open_t hyperv_tsc_open; +static d_mmap_t hyperv_tsc_mmap; + static struct timecounter hyperv_tsc_timecounter = { .tc_get_timecount = NULL, /* based on CPU vendor. */ .tc_poll_pps = NULL, @@ -58,6 +66,13 @@ static struct timecounter hyperv_tsc_timecounter = { .tc_priv = NULL }; +static struct cdevsw hyperv_tsc_cdevsw = { + .d_version = D_VERSION, + .d_open = hyperv_tsc_open, + .d_mmap = hyperv_tsc_mmap, + .d_name = HYPERV_REFTSC_DEVNAME +}; + static struct hyperv_reftsc_ctx hyperv_ref_tsc; uint64_t @@ -72,6 +87,36 @@ hypercall_md(volatile void *hc_addr, uint64_t in_val, return (status); } +static int +hyperv_tsc_open(struct cdev *dev __unused, int oflags, int devtype __unused, + struct thread *td __unused) +{ + + if (oflags & FWRITE) + return (EPERM); + return (0); +} + +static int +hyperv_tsc_mmap(struct cdev *dev __unused, vm_ooffset_t offset, + vm_paddr_t *paddr, int nprot __unused, vm_memattr_t *memattr __unused) +{ + + KASSERT(hyperv_ref_tsc.tsc_ref != NULL, ("reftsc has not been setup")); + + /* + * NOTE: + * 'nprot' does not contain information interested to us; + * WR-open is blocked by d_open. + */ + + if (offset != 0) + return (EOPNOTSUPP); + + *paddr = hyperv_ref_tsc.tsc_ref_dma.hv_paddr; + return (0); +} + #define HYPERV_TSC_TIMECOUNT(fence) \ static u_int \ hyperv_tsc_timecount_##fence(struct timecounter *tc) \ @@ -150,6 +195,10 @@ hyperv_tsc_tcinit(void *dummy __unused) /* Register "enlightened" timecounter. */ tc_init(&hyperv_tsc_timecounter); + + /* Add device for mmap(2). */ + make_dev(&hyperv_tsc_cdevsw, 0, UID_ROOT, GID_WHEEL, 0444, + HYPERV_REFTSC_DEVNAME); } SYSINIT(hyperv_tsc_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, hyperv_tsc_tcinit, NULL); diff --git a/sys/dev/hyperv/vmbus/hyperv_reg.h b/sys/dev/hyperv/vmbus/hyperv_reg.h index 263a191fec23..b3b133c84881 100644 --- a/sys/dev/hyperv/vmbus/hyperv_reg.h +++ b/sys/dev/hyperv/vmbus/hyperv_reg.h @@ -128,17 +128,6 @@ #define CPUID_LEAF_HV_LIMITS 0x40000005 #define CPUID_LEAF_HV_HWFEATURES 0x40000006 -/* - * Hyper-V Reference TSC - */ -struct hyperv_reftsc { - volatile uint32_t tsc_seq; - volatile uint32_t tsc_rsvd1; - volatile uint64_t tsc_scale; - volatile int64_t tsc_ofs; -} __packed __aligned(PAGE_SIZE); -CTASSERT(sizeof(struct hyperv_reftsc) == PAGE_SIZE); - /* * Hyper-V Monitor Notification Facility */ -- 2.39.5