Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/arm64/kvm/hyp/nvhe/clock.c
170998 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright (C) 2025 Google LLC
4
* Author: Vincent Donnefort <[email protected]>
5
*/
6
7
#include <nvhe/clock.h>
8
9
#include <asm/arch_timer.h>
10
#include <asm/div64.h>
11
12
static struct clock_data {
13
struct {
14
u32 mult;
15
u32 shift;
16
u64 epoch_ns;
17
u64 epoch_cyc;
18
u64 cyc_overflow64;
19
} data[2];
20
u64 cur;
21
} trace_clock_data;
22
23
static u64 __clock_mult_uint128(u64 cyc, u32 mult, u32 shift)
24
{
25
__uint128_t ns = (__uint128_t)cyc * mult;
26
27
ns >>= shift;
28
29
return (u64)ns;
30
}
31
32
/* Does not guarantee no reader on the modified bank. */
33
void trace_clock_update(u32 mult, u32 shift, u64 epoch_ns, u64 epoch_cyc)
34
{
35
struct clock_data *clock = &trace_clock_data;
36
u64 bank = clock->cur ^ 1;
37
38
clock->data[bank].mult = mult;
39
clock->data[bank].shift = shift;
40
clock->data[bank].epoch_ns = epoch_ns;
41
clock->data[bank].epoch_cyc = epoch_cyc;
42
clock->data[bank].cyc_overflow64 = ULONG_MAX / mult;
43
44
smp_store_release(&clock->cur, bank);
45
}
46
47
/* Use untrusted host data */
48
u64 trace_clock(void)
49
{
50
struct clock_data *clock = &trace_clock_data;
51
u64 bank = smp_load_acquire(&clock->cur);
52
u64 cyc, ns;
53
54
cyc = __arch_counter_get_cntvct() - clock->data[bank].epoch_cyc;
55
56
if (likely(cyc < clock->data[bank].cyc_overflow64)) {
57
ns = cyc * clock->data[bank].mult;
58
ns >>= clock->data[bank].shift;
59
} else {
60
ns = __clock_mult_uint128(cyc, clock->data[bank].mult,
61
clock->data[bank].shift);
62
}
63
64
return (u64)ns + clock->data[bank].epoch_ns;
65
}
66
67