Received: by 10.213.65.68 with SMTP id h4csp45492imn; Thu, 15 Mar 2018 09:05:16 -0700 (PDT) X-Google-Smtp-Source: AG47ELt7KWx/26ITUzrJBLm9AkRvo3T4yu4/2e8LaKfMV0o9YF2qqZyn1MaN8rApiQipUWASZ+xp X-Received: by 10.98.69.76 with SMTP id s73mr8234838pfa.31.1521129916482; Thu, 15 Mar 2018 09:05:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521129916; cv=none; d=google.com; s=arc-20160816; b=vbpummOf4kUu6zbSKPljZqQK86hXhnC7HQTghg6qClQNtsFIL76Ce/TuxVwM1ZXGVl u+nS+e9AusEenBcCtwz2Jd5iSq25jRy26NxE+5ZZHJ5/6NPhecfyR0RSEYKSQlbeMrho vgtSvsF3Zl40tG7FJzF3pdKJNl7eCBLa75th15niK5jkub1GOS+oLRBP7fxBJFGOo8Bs +6FjPb77V3UWGk+yGoY9HTY0d8bTzXPGi4y3piZw8CLC/iyeqiEIuSGAwLfQx/mou2tv BgeD+gZWN1M5M3sJk8s5q19J4naDb4uPNROujES8DjXEkr5fBs+usxWDo4nS4r6DKzPI GMPw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=45vVHHA8JHSL92uoreSd9Ruzs5QhxBhdRxpENFr6pL8=; b=iE8rVdDh0hSFEjCcONCUduKYQpoU+SEooSdZVHPTXA/KPBAGqw0F3pnGv53be5j3cs yLc8ylpDYJOnXo+Cx9ySd8JOArs4ojjW6CqmUai2qJZk0JAEXpLfOObvQm0Dpqw7jDeL thILpaajaoh2u/8GYhcXB/niKwTcn3qVbSOPW9SQaishMVeX1H0X/c4y2WMlTyR+yviO FinNakAlDb7hq9PQMV91+F7KwZU89YRAFmerR/Bse8BsB8DZBsV+ap/SlStnwwZ/Kf47 5VvgKZO77ObqZcXq2gov+N9ZvsYJGbD8Spy20oJvKL5pTRyXL1IqOhGup1KQ56h2symH rZhg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=M+/6mERE; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b1si3593415pgf.323.2018.03.15.09.05.01; Thu, 15 Mar 2018 09:05:16 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=M+/6mERE; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932978AbeCOQBI (ORCPT + 99 others); Thu, 15 Mar 2018 12:01:08 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:38818 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932941AbeCOQBF (ORCPT ); Thu, 15 Mar 2018 12:01:05 -0400 Received: by mail-wm0-f67.google.com with SMTP id z9so11437873wmb.3 for ; Thu, 15 Mar 2018 09:01:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=45vVHHA8JHSL92uoreSd9Ruzs5QhxBhdRxpENFr6pL8=; b=M+/6mERENHH+ckVj4XwYU351GlCQQdsTNF7HWWbm/CIxT1qli5vsEJ3VMR7B2OHf5o 8ueGybTDpOohQO5YUv/ypCAtemAP304RC18TUAhkWQqC4Kv21KgGVrtZFiKMnhgdsibv sEgWAe1nr8HSJQqu+K3MHMFbcJWsMDaZHl2HB53sLDfN489btoNYd35p5l6SpCXC+dO9 bIhfMmSKqxf15OliQFSYnE+pZHR8EGvUVJ/9gpwZpQQvy9FtBdXuHIljyBpFBV2d3s/Z v0IiOUyeTWc8z+XaVnLLOIJVLPwuAIkmD+SURJPjreMZLqsxJQ2IjPphIcniyeyNDFm3 ZJvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=45vVHHA8JHSL92uoreSd9Ruzs5QhxBhdRxpENFr6pL8=; b=cLkXco/CQHITLgBK20WY+GfEy2g/hIi3GjtHKvAAdCJCCl4xsVu453bNdDv/fDNrQr twlrpZQL0xAOi7uvtrWaE0zTQWCy55sp9y4hKm3as7MDhgfYnI1hi1jHBx34PBB52qxD oEBNhoNVFW3Uk9msD1l9GXtgGnWurDnwyHKP52Im8r61HEy4LMqHflFKYW9ZKm6Y+rtf wi6kNWpOtPD7LwH0yPuW2xJnZzp0cDy0sXb5LOJYb8Tx3lQW1cWiKJ1cJrwkIxiW1yBm NkCPtqEqSyAx3WtB84MYNjs8oMjSP7V/+o3FiV+gwC5iqAUv5zpdnihzpgMfhIh7s7XO LiTw== X-Gm-Message-State: AElRT7FRWC/mOVF/DJtwmT6Yyk7TgpyrYGIcsOfBViAUQJ9QQ0xOZtmO 49gOZtmWbut+s8t9XWuAOf9n3N6E X-Received: by 10.80.203.5 with SMTP id g5mr9270341edi.4.1521129663254; Thu, 15 Mar 2018 09:01:03 -0700 (PDT) Received: from localhost.localdomain ([83.147.149.202]) by smtp.gmail.com with ESMTPSA id z7sm2508306edb.46.2018.03.15.09.01.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 15 Mar 2018 09:01:02 -0700 (PDT) From: jason.vas.dias@gmail.com To: linux-kernel@vger.kernel.org Cc: x86@kernel.org, tglx@linutronix.de, mingo@kernel.org, peterz@infradead.org, andi@firstfloor.org Subject: [PATCH v4.16-rc5 3/3] x86/vdso: on Intel, VDSO should handle CLOCK_MONOTONIC_RAW Date: Thu, 15 Mar 2018 16:00:48 +0000 Message-Id: <1521129648-20889-4-git-send-email-jason.vas.dias@gmail.com> X-Mailer: git-send-email 2.8.2 In-Reply-To: <1521129648-20889-1-git-send-email-jason.vas.dias@gmail.com> References: <1521129648-20889-1-git-send-email-jason.vas.dias@gmail.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org diff --git a/arch/x86/entry/vdso/vclock_gettime.c b/arch/x86/entry/vdso/vclock_gettime.c index 03f3904..61d9633 100644 --- a/arch/x86/entry/vdso/vclock_gettime.c +++ b/arch/x86/entry/vdso/vclock_gettime.c @@ -21,12 +21,15 @@ #include #include #include +#include #define gtod (&VVAR(vsyscall_gtod_data)) extern int __vdso_clock_gettime(clockid_t clock, struct timespec *ts); extern int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz); extern time_t __vdso_time(time_t *t); +extern unsigned int __vdso_tsc_calibration( + struct linux_tsc_calibration_s *tsc_cal); #ifdef CONFIG_PARAVIRT_CLOCK extern u8 pvclock_page @@ -383,3 +386,25 @@ notrace time_t __vdso_time(time_t *t) } time_t time(time_t *t) __attribute__((weak, alias("__vdso_time"))); + +notrace unsigned int +__vdso_linux_tsc_calibration(struct linux_tsc_calibration_s *tsc_cal) +{ + unsigned long seq; + + do { + seq = gtod_read_begin(gtod); + if ((gtod->vclock_mode == VCLOCK_TSC) && + (tsc_cal != ((void *)0UL))) { + tsc_cal->tsc_khz = gtod->tsc_khz; + tsc_cal->mult = gtod->raw_mult; + tsc_cal->shift = gtod->raw_shift; + return 1; + } + } while (unlikely(gtod_read_retry(gtod, seq))); + + return 0; +} + +unsigned int linux_tsc_calibration(struct linux_tsc_calibration_s *tsc_cal) + __attribute((weak, alias("__vdso_linux_tsc_calibration"))); diff --git a/arch/x86/entry/vdso/vdso.lds.S b/arch/x86/entry/vdso/vdso.lds.S index d3a2dce..e0b5cce 100644 --- a/arch/x86/entry/vdso/vdso.lds.S +++ b/arch/x86/entry/vdso/vdso.lds.S @@ -25,6 +25,8 @@ VERSION { __vdso_getcpu; time; __vdso_time; + linux_tsc_calibration; + __vdso_linux_tsc_calibration; local: *; }; } diff --git a/arch/x86/entry/vdso/vdso32/vdso32.lds.S b/arch/x86/entry/vdso/vdso32/vdso32.lds.S index 422764a..17fd07f 100644 --- a/arch/x86/entry/vdso/vdso32/vdso32.lds.S +++ b/arch/x86/entry/vdso/vdso32/vdso32.lds.S @@ -26,6 +26,7 @@ VERSION __vdso_clock_gettime; __vdso_gettimeofday; __vdso_time; + __vdso_linux_tsc_calibration; }; LINUX_2.5 { diff --git a/arch/x86/entry/vdso/vdsox32.lds.S b/arch/x86/entry/vdso/vdsox32.lds.S index 05cd1c5..7acac71 100644 --- a/arch/x86/entry/vdso/vdsox32.lds.S +++ b/arch/x86/entry/vdso/vdsox32.lds.S @@ -21,6 +21,7 @@ VERSION { __vdso_gettimeofday; __vdso_getcpu; __vdso_time; + __vdso_linux_tsc_calibration; local: *; }; } diff --git a/arch/x86/include/uapi/asm/vdso_tsc_calibration.h b/arch/x86/include/uapi/asm/vdso_tsc_calibration.h new file mode 100644 index 0000000..ce4b5a45 --- /dev/null +++ b/arch/x86/include/uapi/asm/vdso_tsc_calibration.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ASM_X86_VDSO_TSC_CALIBRATION_H +#define _ASM_X86_VDSO_TSC_CALIBRATION_H +/* + * Programs that want to use rdtsc / rdtscp instructions + * from user-space can make use of the Linux kernel TSC calibration + * by calling : + * __vdso_linux_tsc_calibration(struct linux_tsc_calibration_s *); + * ( one has to resolve this symbol as in + * tools/testing/selftests/vDSO/parse_vdso.c + * ) + * which fills in a structure + * with the following layout : + */ + +/** struct linux_tsc_calibration_s - + * mult: amount to multiply 64-bit TSC value by + * shift: the right shift to apply to (mult*TSC) yielding nanoseconds + * tsc_khz: the calibrated TSC frequency in KHz from which previous + * members calculated + */ +struct linux_tsc_calibration_s { + + unsigned int mult; + unsigned int shift; + unsigned int tsc_khz; + +}; + +/* To use: + * + * static unsigned + * (*linux_tsc_cal)(struct linux_tsc_calibration_s *linux_tsc_cal) = + * vdso_sym("LINUX_2.6", "__vdso_linux_tsc_calibration"); + * if(linux_tsc_cal == ((void *)0)) + * { fprintf(stderr,"the patch providing __vdso_linux_tsc_calibration" + * " is not applied to the kernel.\n"); + * return ERROR; + * } + * static struct linux_tsc_calibration clock_source={0}; + * if((clock_source.mult==0) && ! (*linux_tsc_cal)(&clock_source) ) + * fprintf(stderr,"TSC is not the system clocksource.\n"); + * unsigned int tsc_lo, tsc_hi, tsc_cpu; + * asm volatile + * ( "rdtscp" : (=a) tsc_hi, (=d) tsc_lo, (=c) tsc_cpu ); + * unsigned long tsc = (((unsigned long)tsc_hi) << 32) | tsc_lo; + * unsigned long nanoseconds = + * (( clock_source . mult ) * tsc ) >> (clock_source . shift); + * + * nanoseconds is now TSC value converted to nanoseconds, + * according to Linux' clocksource calibration values. + * Incidentally, 'tsc_cpu' is the number of the CPU the task is running on. + * + * But better results are obtained by applying this to the difference (delta) + * and adding this to some previous timespec value: + * static u64 previous_tsc=0, previous_nsec=0, previous_sec=0; + * u64 tsc = rdtscp(); + * u64 delta = tsc - previous_tsc; + * u64 nsec = ((delta * clock_source.mult) + previous_nsec ) + * >> clock_source.shift; + * ts->tv_sec = previous_sec + (nsec / NSEC_PER_SEC); + * ts->tv_nsec = nsec % NSEC_PER_SEC; + * previous_tsc = tsc + * previous_sec = ts->tv_sec; + * previous_nsec = ts->tv_nsec << clock_source.shift; + * return ts; + * This is broadly like the approach taken by Linux kernel & in VDSO . + * + * Or, in user-space, with floating point, one could use the rdtscp value as + * number of picoseconds : + * u64 ns = lround( ((double)rdtscp()) + * / (((double)clock_source.tsc_khz) / 1e3) + * ); + * (ie. if tsc_khz is 3000 , there are 3 tsc ticks per nanosecond, + * so divide tsc ticks by 3). + * + * There should actually be very little difference between the two + * values obtained (@ 0.02% ) by either method. + */ + +#endif