Skip to content

Commit c40a13f

Browse files
committed
Merge: CNB96: timekeeping: add clocksource ID and infrastructure for converting to/from a base clock
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/5380 JIRA: https://issues.redhat.com/browse/RHEL-61639 First, the cross-timestamp mechanism which allows to correlate hardware clocks uses clocksource pointers for describing the correlation. That's suboptimal as drivers need to obtain the pointer, which requires needless exports and exposing internals. This can be avoided by adding clocksource IDs to all clocksources in the tree which can be exposed to this mechanism. Second, hardware time stamps like provided by PTP clock implementations are based on a clock which feeds both the PCIe device and the system clock. For further processing the underlying hardware clock timestamp must be converted to the system clock. Right now this requires drivers to invoke an architecture specific conversion function, e.g. to convert the ART (Always Running Timer) timestamp to a TSC timestamp. This can be avoided by moving this functionality to the core code by providing a base clock property for the system clock which contains the conversion factors and assigning a clocksource ID to the base clock. Commits: ``` 5f10376 ("add missing includes and forward declarations to networking includes under linux/") c55cbfc ("x86/tsc: Correct kernel-doc notation") 93630d6 ("timekeeping: Add clocksource ID to struct system_counterval_t") a2c1fe7 ("x86/tsc: Add clocksource ID, set system_counterval_t.cs_id") 576bd49 ("x86/kvm, ptp/kvm: Add clocksource ID, set system_counterval_t.cs_id") 9be3b2f ("ptp/kvm, arm_arch_timer: Set system_counterval_t.cs_id to constant") 4b7f521 ("timekeeping: Evaluate system_counterval_t.cs_id instead of .cs") b152688 ("treewide: Remove system_counterval_t.cs, which is never read") 27f6a9c ("kvmclock: Unexport kvmclock clocksource") 6b2e299 ("timekeeping: Provide infrastructure for converting to/from a base clock") 3a52886 ("x86/tsc: Provide ART base clock information for TSC") bd48b50 ("e1000e: Replace convert_art_to_tsc()") fcb0591 ("igc: Remove convert_art_ns_to_tsc()") f5e1d0d ("stmmac: intel: Remove convert_art_to_tsc()") b3266ed ("ALSA: hda: Remove convert_art_to_tsc()") d4bea54 ("ice/ptp: Remove convert_art_to_tsc()") 0f532a7 ("x86/tsc: Remove obsolete ART to TSC conversion functions") 02ecee0 ("timekeeping: Add function to convert realtime to base clock") ``` Signed-off-by: Ivan Vecera <ivecera@redhat.com> Approved-by: Phil Auld <pauld@redhat.com> Approved-by: Tony Camuso <tcamuso@redhat.com> Approved-by: Corinna Vinschen <vinschen@redhat.com> Approved-by: Chris von Recklinghausen <crecklin@redhat.com> Approved-by: Mark Salter <msalter@redhat.com> Approved-by: Davide Caratti <dcaratti@redhat.com> Approved-by: Prarit Bhargava <prarit@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Rado Vrbovsky <rvrbovsk@redhat.com>
2 parents 41aef81 + 593b876 commit c40a13f

File tree

33 files changed

+279
-114
lines changed

33 files changed

+279
-114
lines changed

arch/x86/include/asm/kvmclock.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
#include <linux/percpu.h>
66

7-
extern struct clocksource kvm_clock;
8-
97
DECLARE_PER_CPU(struct pvclock_vsyscall_time_info *, hv_clock_per_cpu);
108

119
static __always_inline struct pvclock_vcpu_time_info *this_cpu_pvti(void)

arch/x86/include/asm/tsc.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ static inline cycles_t get_cycles(void)
2727
}
2828
#define get_cycles get_cycles
2929

30-
extern struct system_counterval_t convert_art_to_tsc(u64 art);
31-
extern struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns);
32-
3330
extern void tsc_early_init(void);
3431
extern void tsc_init(void);
3532
extern void mark_tsc_unstable(char *reason);

arch/x86/kernel/kvmclock.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,15 +154,15 @@ static int kvm_cs_enable(struct clocksource *cs)
154154
return 0;
155155
}
156156

157-
struct clocksource kvm_clock = {
157+
static struct clocksource kvm_clock = {
158158
.name = "kvm-clock",
159159
.read = kvm_clock_get_cycles,
160160
.rating = 400,
161161
.mask = CLOCKSOURCE_MASK(64),
162162
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
163+
.id = CSID_X86_KVM_CLK,
163164
.enable = kvm_cs_enable,
164165
};
165-
EXPORT_SYMBOL_GPL(kvm_clock);
166166

167167
static void kvm_register_clock(char *txt)
168168
{

arch/x86/kernel/tsc.c

Lines changed: 26 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ int tsc_clocksource_reliable;
5050

5151
static int __read_mostly tsc_force_recalibrate;
5252

53-
static u32 art_to_tsc_numerator;
54-
static u32 art_to_tsc_denominator;
55-
static u64 art_to_tsc_offset;
56-
static struct clocksource *art_related_clocksource;
53+
static struct clocksource_base art_base_clk = {
54+
.id = CSID_X86_ART,
55+
};
56+
static bool have_art;
5757

5858
struct cyc2ns {
5959
struct cyc2ns_data data[2]; /* 0 + 2*16 = 32 */
@@ -652,7 +652,7 @@ static unsigned long quick_pit_calibrate(void)
652652
}
653653

654654
/**
655-
* native_calibrate_tsc
655+
* native_calibrate_tsc - determine TSC frequency
656656
* Determine TSC frequency via CPUID, else return 0.
657657
*/
658658
unsigned long native_calibrate_tsc(void)
@@ -1074,7 +1074,7 @@ core_initcall(cpufreq_register_tsc_scaling);
10741074
*/
10751075
static void __init detect_art(void)
10761076
{
1077-
unsigned int unused[2];
1077+
unsigned int unused;
10781078

10791079
if (boot_cpu_data.cpuid_level < ART_CPUID_LEAF)
10801080
return;
@@ -1089,13 +1089,14 @@ static void __init detect_art(void)
10891089
tsc_async_resets)
10901090
return;
10911091

1092-
cpuid(ART_CPUID_LEAF, &art_to_tsc_denominator,
1093-
&art_to_tsc_numerator, unused, unused+1);
1092+
cpuid(ART_CPUID_LEAF, &art_base_clk.denominator,
1093+
&art_base_clk.numerator, &art_base_clk.freq_khz, &unused);
10941094

1095-
if (art_to_tsc_denominator < ART_MIN_DENOMINATOR)
1095+
art_base_clk.freq_khz /= KHZ;
1096+
if (art_base_clk.denominator < ART_MIN_DENOMINATOR)
10961097
return;
10971098

1098-
rdmsrl(MSR_IA32_TSC_ADJUST, art_to_tsc_offset);
1099+
rdmsrl(MSR_IA32_TSC_ADJUST, art_base_clk.offset);
10991100

11001101
/* Make this sticky over multiple CPU init calls */
11011102
setup_force_cpu_cap(X86_FEATURE_ART);
@@ -1168,6 +1169,7 @@ static struct clocksource clocksource_tsc_early = {
11681169
.mask = CLOCKSOURCE_MASK(64),
11691170
.flags = CLOCK_SOURCE_IS_CONTINUOUS |
11701171
CLOCK_SOURCE_MUST_VERIFY,
1172+
.id = CSID_X86_TSC_EARLY,
11711173
.vdso_clock_mode = VDSO_CLOCKMODE_TSC,
11721174
.enable = tsc_cs_enable,
11731175
.resume = tsc_resume,
@@ -1190,6 +1192,7 @@ static struct clocksource clocksource_tsc = {
11901192
CLOCK_SOURCE_VALID_FOR_HRES |
11911193
CLOCK_SOURCE_MUST_VERIFY |
11921194
CLOCK_SOURCE_VERIFY_PERCPU,
1195+
.id = CSID_X86_TSC,
11931196
.vdso_clock_mode = VDSO_CLOCKMODE_TSC,
11941197
.enable = tsc_cs_enable,
11951198
.resume = tsc_resume,
@@ -1294,70 +1297,11 @@ int unsynchronized_tsc(void)
12941297
return 0;
12951298
}
12961299

1297-
/*
1298-
* Convert ART to TSC given numerator/denominator found in detect_art()
1299-
*/
1300-
struct system_counterval_t convert_art_to_tsc(u64 art)
1301-
{
1302-
u64 tmp, res, rem;
1303-
1304-
rem = do_div(art, art_to_tsc_denominator);
1305-
1306-
res = art * art_to_tsc_numerator;
1307-
tmp = rem * art_to_tsc_numerator;
1308-
1309-
do_div(tmp, art_to_tsc_denominator);
1310-
res += tmp + art_to_tsc_offset;
1311-
1312-
return (struct system_counterval_t) {.cs = art_related_clocksource,
1313-
.cycles = res};
1314-
}
1315-
EXPORT_SYMBOL(convert_art_to_tsc);
1316-
1317-
/**
1318-
* convert_art_ns_to_tsc() - Convert ART in nanoseconds to TSC.
1319-
* @art_ns: ART (Always Running Timer) in unit of nanoseconds
1320-
*
1321-
* PTM requires all timestamps to be in units of nanoseconds. When user
1322-
* software requests a cross-timestamp, this function converts system timestamp
1323-
* to TSC.
1324-
*
1325-
* This is valid when CPU feature flag X86_FEATURE_TSC_KNOWN_FREQ is set
1326-
* indicating the tsc_khz is derived from CPUID[15H]. Drivers should check
1327-
* that this flag is set before conversion to TSC is attempted.
1328-
*
1329-
* Return:
1330-
* struct system_counterval_t - system counter value with the pointer to the
1331-
* corresponding clocksource
1332-
* @cycles: System counter value
1333-
* @cs: Clocksource corresponding to system counter value. Used
1334-
* by timekeeping code to verify comparability of two cycle
1335-
* values.
1336-
*/
1337-
1338-
struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns)
1339-
{
1340-
u64 tmp, res, rem;
1341-
1342-
rem = do_div(art_ns, USEC_PER_SEC);
1343-
1344-
res = art_ns * tsc_khz;
1345-
tmp = rem * tsc_khz;
1346-
1347-
do_div(tmp, USEC_PER_SEC);
1348-
res += tmp;
1349-
1350-
return (struct system_counterval_t) { .cs = art_related_clocksource,
1351-
.cycles = res};
1352-
}
1353-
EXPORT_SYMBOL(convert_art_ns_to_tsc);
1354-
1355-
13561300
static void tsc_refine_calibration_work(struct work_struct *work);
13571301
static DECLARE_DELAYED_WORK(tsc_irqwork, tsc_refine_calibration_work);
13581302
/**
13591303
* tsc_refine_calibration_work - Further refine tsc freq calibration
1360-
* @work - ignored.
1304+
* @work: ignored.
13611305
*
13621306
* This functions uses delayed work over a period of a
13631307
* second to further refine the TSC freq value. Since this is
@@ -1454,8 +1398,10 @@ static void tsc_refine_calibration_work(struct work_struct *work)
14541398
if (tsc_unstable)
14551399
goto unreg;
14561400

1457-
if (boot_cpu_has(X86_FEATURE_ART))
1458-
art_related_clocksource = &clocksource_tsc;
1401+
if (boot_cpu_has(X86_FEATURE_ART)) {
1402+
have_art = true;
1403+
clocksource_tsc.base = &art_base_clk;
1404+
}
14591405
clocksource_register_khz(&clocksource_tsc, tsc_khz);
14601406
unreg:
14611407
clocksource_unregister(&clocksource_tsc_early);
@@ -1480,8 +1426,10 @@ static int __init init_tsc_clocksource(void)
14801426
* the refined calibration and directly register it as a clocksource.
14811427
*/
14821428
if (boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ)) {
1483-
if (boot_cpu_has(X86_FEATURE_ART))
1484-
art_related_clocksource = &clocksource_tsc;
1429+
if (boot_cpu_has(X86_FEATURE_ART)) {
1430+
have_art = true;
1431+
clocksource_tsc.base = &art_base_clk;
1432+
}
14851433
clocksource_register_khz(&clocksource_tsc, tsc_khz);
14861434
clocksource_unregister(&clocksource_tsc_early);
14871435

@@ -1505,10 +1453,12 @@ static bool __init determine_cpu_tsc_frequencies(bool early)
15051453

15061454
if (early) {
15071455
cpu_khz = x86_platform.calibrate_cpu();
1508-
if (tsc_early_khz)
1456+
if (tsc_early_khz) {
15091457
tsc_khz = tsc_early_khz;
1510-
else
1458+
} else {
15111459
tsc_khz = x86_platform.calibrate_tsc();
1460+
clocksource_tsc.freq_khz = tsc_khz;
1461+
}
15121462
} else {
15131463
/* We should not be here with non-native cpu calibration */
15141464
WARN_ON(x86_platform.calibrate_cpu != native_calibrate_cpu);

drivers/clocksource/arm_arch_timer.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1777,7 +1777,7 @@ TIMER_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
17771777
#endif
17781778

17791779
int kvm_arch_ptp_get_crosststamp(u64 *cycle, struct timespec64 *ts,
1780-
struct clocksource **cs)
1780+
enum clocksource_ids *cs_id)
17811781
{
17821782
struct arm_smccc_res hvc_res;
17831783
u32 ptp_counter;
@@ -1801,8 +1801,8 @@ int kvm_arch_ptp_get_crosststamp(u64 *cycle, struct timespec64 *ts,
18011801
*ts = ktime_to_timespec64(ktime);
18021802
if (cycle)
18031803
*cycle = (u64)hvc_res.a2 << 32 | hvc_res.a3;
1804-
if (cs)
1805-
*cs = &clocksource_counter;
1804+
if (cs_id)
1805+
*cs_id = CSID_ARM_ARCH_COUNTER;
18061806

18071807
return 0;
18081808
}

drivers/net/ethernet/intel/e1000e/ptp.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ static int e1000e_phc_get_syncdevicetime(ktime_t *device,
124124
sys_cycles = er32(PLTSTMPH);
125125
sys_cycles <<= 32;
126126
sys_cycles |= er32(PLTSTMPL);
127-
*system = convert_art_to_tsc(sys_cycles);
127+
system->cycles = sys_cycles;
128+
system->cs_id = CSID_X86_ART;
128129

129130
return 0;
130131
}

drivers/net/ethernet/intel/ice/ice_ptp.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2218,7 +2218,8 @@ ice_ptp_get_syncdevicetime(ktime_t *device,
22182218
hh_ts_lo = rd32(hw, GLHH_ART_TIME_L);
22192219
hh_ts_hi = rd32(hw, GLHH_ART_TIME_H);
22202220
hh_ts = ((u64)hh_ts_hi << 32) | hh_ts_lo;
2221-
*system = convert_art_ns_to_tsc(hh_ts);
2221+
system->cycles = hh_ts;
2222+
system->cs_id = CSID_X86_ART;
22222223
/* Read Device source clock time */
22232224
hh_ts_lo = rd32(hw, GLTSYN_HHTIME_L(tmr_idx));
22242225
hh_ts_hi = rd32(hw, GLTSYN_HHTIME_H(tmr_idx));

drivers/net/ethernet/intel/igc/igc_ptp.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -901,7 +901,11 @@ static bool igc_is_crosststamp_supported(struct igc_adapter *adapter)
901901
static struct system_counterval_t igc_device_tstamp_to_system(u64 tstamp)
902902
{
903903
#if IS_ENABLED(CONFIG_X86_TSC) && !defined(CONFIG_UML)
904-
return convert_art_ns_to_tsc(tstamp);
904+
return (struct system_counterval_t) {
905+
.cs_id = CSID_X86_ART,
906+
.cycles = tstamp,
907+
.use_nsecs = true,
908+
};
905909
#else
906910
return (struct system_counterval_t) { };
907911
#endif

drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,10 +390,11 @@ static int intel_crosststamp(ktime_t *device,
390390
*device = ns_to_ktime(ptp_time);
391391
read_unlock_irqrestore(&priv->ptp_lock, flags);
392392
get_arttime(priv->mii, intel_priv->mdio_adhoc_addr, &art_time);
393-
*system = convert_art_to_tsc(art_time);
393+
system->cycles = art_time;
394394
}
395395

396396
system->cycles *= intel_priv->crossts_adj;
397+
system->cs_id = CSID_X86_ART;
397398
priv->plat->flags &= ~STMMAC_FLAG_INT_SNAPSHOT_EN;
398399

399400
return 0;

drivers/ptp/ptp_kvm_common.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ static int ptp_kvm_get_time_fn(ktime_t *device_time,
2828
struct system_counterval_t *system_counter,
2929
void *ctx)
3030
{
31-
long ret;
32-
u64 cycle;
31+
enum clocksource_ids cs_id;
3332
struct timespec64 tspec;
34-
struct clocksource *cs;
33+
u64 cycle;
34+
int ret;
3535

3636
spin_lock(&kvm_ptp_lock);
3737

3838
preempt_disable_notrace();
39-
ret = kvm_arch_ptp_get_crosststamp(&cycle, &tspec, &cs);
39+
ret = kvm_arch_ptp_get_crosststamp(&cycle, &tspec, &cs_id);
4040
if (ret) {
4141
spin_unlock(&kvm_ptp_lock);
4242
preempt_enable_notrace();
@@ -46,7 +46,7 @@ static int ptp_kvm_get_time_fn(ktime_t *device_time,
4646
preempt_enable_notrace();
4747

4848
system_counter->cycles = cycle;
49-
system_counter->cs = cs;
49+
system_counter->cs_id = cs_id;
5050

5151
*device_time = timespec64_to_ktime(tspec);
5252

0 commit comments

Comments
 (0)