From owner-svn-src-stable-10@freebsd.org Wed Jan 4 01:58:40 2017 Return-Path: Delivered-To: svn-src-stable-10@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 02C2AC9C910; Wed, 4 Jan 2017 01:58:40 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D11791054; Wed, 4 Jan 2017 01:58:39 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v041wdE8018207; Wed, 4 Jan 2017 01:58:39 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v041wcnU018203; Wed, 4 Jan 2017 01:58:38 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201701040158.v041wcnU018203@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Wed, 4 Jan 2017 01:58:38 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r311223 - in stable/10: include sys/dev/hyperv/include sys/dev/hyperv/vmbus sys/dev/hyperv/vmbus/amd64 X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 04 Jan 2017 01:58:40 -0000 Author: sephe Date: Wed Jan 4 01:58:38 2017 New Revision: 311223 URL: https://svnweb.freebsd.org/changeset/base/311223 Log: MFC 310048,310101 310048 hyperv: Implement "enlightened" time counter, which is rdtsc based. Reviewed by: kib Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8763 310101 hyperv: Allow userland to ro-mmap reference TSC page This paves way to implement VDSO for the enlightened time counter. Reviewed by: kib Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8768 Modified: stable/10/include/Makefile stable/10/sys/dev/hyperv/include/hyperv.h stable/10/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c stable/10/sys/dev/hyperv/vmbus/hyperv_reg.h Directory Properties: stable/10/ (props changed) Modified: stable/10/include/Makefile ============================================================================== --- stable/10/include/Makefile Wed Jan 4 01:44:45 2017 (r311222) +++ stable/10/include/Makefile Wed Jan 4 01:58:38 2017 (r311223) @@ -184,6 +184,9 @@ copies: ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 nand_dev.h \ ${DESTDIR}${INCLUDEDIR}/dev/nand .endif + 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 @@ -287,6 +290,11 @@ symlinks: ${DESTDIR}${INCLUDEDIR}/dev/nand; \ done .endif + 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 \ Modified: stable/10/sys/dev/hyperv/include/hyperv.h ============================================================================== --- stable/10/sys/dev/hyperv/include/hyperv.h Wed Jan 4 01:44:45 2017 (r311222) +++ stable/10/sys/dev/hyperv/include/hyperv.h Wed Jan 4 01:58:38 2017 (r311223) @@ -31,10 +31,10 @@ #ifndef _HYPERV_H_ #define _HYPERV_H_ -#include +#ifdef _KERNEL -#include -#include +#include +#include #define MSR_HV_TIME_REF_COUNT 0x40000020 @@ -45,6 +45,7 @@ #define CPUID_HV_MSR_HYPERCALL 0x0020 /* MSR_HV_GUEST_OS_ID * MSR_HV_HYPERCALL */ #define CPUID_HV_MSR_VP_INDEX 0x0040 /* MSR_HV_VP_INDEX */ +#define CPUID_HV_MSR_REFERENCE_TSC 0x0200 /* MSR_HV_REFERENCE_TSC */ #define CPUID_HV_MSR_GUEST_IDLE 0x0400 /* MSR_HV_GUEST_IDLE */ #ifndef NANOSEC @@ -53,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_ */ Modified: stable/10/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c Wed Jan 4 01:44:45 2017 (r311222) +++ stable/10/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c Wed Jan 4 01:58:38 2017 (r311223) @@ -28,7 +28,52 @@ __FBSDID("$FreeBSD$"); #include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include #include +#include +#include + +struct hyperv_reftsc_ctx { + struct hyperv_reftsc *tsc_ref; + 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, + .tc_counter_mask = 0xffffffff, + .tc_frequency = HYPERV_TIMER_FREQ, + .tc_name = "Hyper-V-TSC", + .tc_quality = 3000, + .tc_flags = 0, + .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 hypercall_md(volatile void *hc_addr, uint64_t in_val, @@ -41,3 +86,122 @@ hypercall_md(volatile void *hc_addr, uin "c" (in_val), "d" (in_paddr), "m" (hc_addr)); 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) \ +{ \ + struct hyperv_reftsc *tsc_ref = hyperv_ref_tsc.tsc_ref; \ + uint32_t seq; \ + \ + while ((seq = tsc_ref->tsc_seq) != 0) { \ + uint64_t disc, ret, tsc, scale; \ + int64_t ofs; \ + \ + __compiler_membar(); \ + scale = tsc_ref->tsc_scale; \ + ofs = tsc_ref->tsc_ofs; \ + \ + fence(); \ + tsc = rdtsc(); \ + \ + /* ret = ((tsc * scale) >> 64) + ofs */ \ + __asm__ __volatile__ ("mulq %3" : \ + "=d" (ret), "=a" (disc) : \ + "a" (tsc), "r" (scale)); \ + ret += ofs; \ + \ + __compiler_membar(); \ + if (tsc_ref->tsc_seq == seq) \ + return (ret); \ + \ + /* Sequence changed; re-sync. */ \ + } \ + /* Fallback to the generic timecounter, i.e. rdmsr. */ \ + return (rdmsr(MSR_HV_TIME_REF_COUNT)); \ +} \ +struct __hack + +HYPERV_TSC_TIMECOUNT(lfence); +HYPERV_TSC_TIMECOUNT(mfence); + +static void +hyperv_tsc_tcinit(void *dummy __unused) +{ + uint64_t val, orig; + + if ((hyperv_features & + (CPUID_HV_MSR_TIME_REFCNT | CPUID_HV_MSR_REFERENCE_TSC)) != + (CPUID_HV_MSR_TIME_REFCNT | CPUID_HV_MSR_REFERENCE_TSC) || + (cpu_feature & CPUID_SSE2) == 0) /* SSE2 for mfence/lfence */ + return; + + switch (cpu_vendor_id) { + case CPU_VENDOR_AMD: + hyperv_tsc_timecounter.tc_get_timecount = + hyperv_tsc_timecount_mfence; + break; + + case CPU_VENDOR_INTEL: + hyperv_tsc_timecounter.tc_get_timecount = + hyperv_tsc_timecount_lfence; + break; + + default: + /* Unsupport CPU vendors. */ + return; + } + + hyperv_ref_tsc.tsc_ref = hyperv_dmamem_alloc(NULL, PAGE_SIZE, 0, + sizeof(struct hyperv_reftsc), &hyperv_ref_tsc.tsc_ref_dma, + BUS_DMA_WAITOK | BUS_DMA_ZERO); + if (hyperv_ref_tsc.tsc_ref == NULL) { + printf("hyperv: reftsc page allocation failed\n"); + return; + } + + orig = rdmsr(MSR_HV_REFERENCE_TSC); + val = MSR_HV_REFTSC_ENABLE | (orig & MSR_HV_REFTSC_RSVD_MASK) | + ((hyperv_ref_tsc.tsc_ref_dma.hv_paddr >> PAGE_SHIFT) << + MSR_HV_REFTSC_PGSHIFT); + wrmsr(MSR_HV_REFERENCE_TSC, val); + + /* 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); Modified: stable/10/sys/dev/hyperv/vmbus/hyperv_reg.h ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/hyperv_reg.h Wed Jan 4 01:44:45 2017 (r311222) +++ stable/10/sys/dev/hyperv/vmbus/hyperv_reg.h Wed Jan 4 01:58:38 2017 (r311223) @@ -57,6 +57,11 @@ #define MSR_HV_VP_INDEX 0x40000002 +#define MSR_HV_REFERENCE_TSC 0x40000021 +#define MSR_HV_REFTSC_ENABLE 0x0001ULL +#define MSR_HV_REFTSC_RSVD_MASK 0x0ffeULL +#define MSR_HV_REFTSC_PGSHIFT 12 + #define MSR_HV_SCONTROL 0x40000080 #define MSR_HV_SCTRL_ENABLE 0x0001ULL #define MSR_HV_SCTRL_RSVD_MASK 0xfffffffffffffffeULL