CHERIoT RTOS
A compartmentalised RTOS for CHERIoT hardware
Loading...
Searching...
No Matches
platform-time.h
Go to the documentation of this file.
1// Copyright SCI Semiconductor and CHERIoT Contributors.
2// SPDX-License-Identifier: MIT
3#pragma once
4
5#include <cdefs.h>
6#include <stdint.h>
7
8/**
9 * @file `platform-time.h` defines the interface for the timer that is used to
10 * implement a monotonic clock. This is the generic implementation that
11 * assumes that the time value is exposed via a CSR. If your board exposes
12 * this via an MMIO region then it must provide a different implementation.
13 */
14
15/**
16 * `CHERIOT_PLATFORM_TIME_HIGH` is a macro that can be defined by platform
17 * headers that include this via `#include_next`. This defines the name for
18 * the CSR that provides the top 32 bits of a 64-bit counter.
19 */
20#ifndef CHERIOT_PLATFORM_TIME_HIGH
21# define CHERIOT_PLATFORM_TIME_HIGH mcycleh
22#endif
23
24/**
25 * `CHERIOT_PLATFORM_TIME_LOW` is a macro that can be defined by platform
26 * headers that include this via `#include_next`. This defines the name for
27 * the CSR that provides the top 32 bits of a 64-bit counter.
28 */
29#ifndef CHERIOT_PLATFORM_TIME_LOW
30# define CHERIOT_PLATFORM_TIME_LOW mcycle
31#endif
32
33/**
34 * Platform-specific hook for reading the current monotonic time. This should
35 * be implemented to return the time that increments with the rate defined by
36 * the `CPU_TIMER_HZ` macro and must be the same timer used by the scheduler.
37 */
38__if_c(static) inline uint64_t platform_monotonic_time_read()
39{
40 uint32_t mtimehBefore;
41 uint32_t mtime;
42 uint32_t mtimehAfter;
43 /* Read the two 32-bit time CSRs. Read the high value first, and then check
44 * whether it has changed. This can happen in two situations:
45 *
46 * If we are reading near the point where the low value overflows. This
47 * would cause the read of high then low to appear almost 2^32 ticks in the
48 * past.
49 *
50 * If we are preempted in the middle of the read, it's possible that the
51 * value of the high counter may be incremented (possibly by more than one)
52 * and the value of the low would change an arbitrary amount.
53 *
54 * Note that, if not called with interrupts disabled, it's still possible
55 * that we are preempted immediately *after* this returns, so the time read
56 * here may be an arbitrary time in the past, but it is guaranteed to be a
57 * point between when this function is entered and when it returns.
58 */
59 do
60 {
61 __asm__ volatile("csrr %0, " __XSTRING(CHERIOT_PLATFORM_TIME_HIGH)
62 : "=r"(mtimehBefore));
63 __asm__ volatile("csrr %0, " __XSTRING(CHERIOT_PLATFORM_TIME_LOW)
64 : "=r"(mtime));
65 __asm__ volatile("csrr %0, " __XSTRING(CHERIOT_PLATFORM_TIME_HIGH)
66 : "=r"(mtimehAfter));
67 } while (mtimehBefore != mtimehAfter);
68 // This header is included from C and C++, don't do C++-specific lints in
69 // it. NOLINTNEXTLINE(google-readability-casting)
70 return ((uint64_t)(mtimehAfter) << 32) + mtime;
71}
#define CHERIOT_PLATFORM_TIME_HIGH
CHERIOT_PLATFORM_TIME_HIGH is a macro that can be defined by platform headers that include this via #...
#define CHERIOT_PLATFORM_TIME_LOW
CHERIOT_PLATFORM_TIME_LOW is a macro that can be defined by platform headers that include this via #i...
union __if_c() __TimeoutArgument
A union to hold timeouts that are passed down to end up in the scheduler.
Definition timeout.h:116