1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
/*
* Arm SSE Subsystem System Counter
*
* Copyright (c) 2020 Linaro Limited
* Written by Peter Maydell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 or
* (at your option) any later version.
*/
/*
* This is a model of the "System counter" which is documented in
* the Arm SSE-123 Example Subsystem Technical Reference Manual:
* https://developer.arm.com/documentation/101370/latest/
*
* QEMU interface:
* + Clock input "CLK": clock
* + sysbus MMIO region 0: the control register frame
* + sysbus MMIO region 1: the status register frame
*
* Consumers of the system counter's timestamp, such as the SSE
* System Timer device, can also use the APIs sse_counter_for_timestamp(),
* sse_counter_tick_to_time() and sse_counter_register_consumer() to
* interact with an instance of the System Counter. Generally the
* consumer device should have a QOM link property which the board
* code can set to the appropriate instance of the system counter.
*/
#ifndef SSE_COUNTER_H
#define SSE_COUNTER_H
#include "hw/sysbus.h"
#include "qom/object.h"
#include "qemu/notify.h"
#define TYPE_SSE_COUNTER "sse-counter"
OBJECT_DECLARE_SIMPLE_TYPE(SSECounter, SSE_COUNTER)
struct SSECounter {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion control_mr;
MemoryRegion status_mr;
Clock *clk;
NotifierList notifier_list;
uint32_t cntcr;
uint32_t cntscr0;
/*
* These are used for handling clock frequency changes: they are a
* tuple of (QEMU_CLOCK_VIRTUAL timestamp, CNTCV at that time),
* taken when the clock frequency changes. sse_cntcv() needs them
* to calculate the current CNTCV.
*/
uint64_t ns_then;
uint64_t ticks_then;
};
/*
* These functions are the interface by which a consumer of
* the system timestamp (such as the SSE system timer device)
* can communicate with the SSECounter.
*/
/**
* sse_counter_for_timestamp:
* @counter: SSECounter
* @ns: timestamp of QEMU_CLOCK_VIRTUAL in nanoseconds
*
* Returns the value of the timestamp counter at the specified
* point in time (assuming that no changes to scale factor, enable, etc
* happen in the meantime).
*/
uint64_t sse_counter_for_timestamp(SSECounter *counter, uint64_t ns);
/**
* sse_counter_tick_to_time:
* @counter: SSECounter
* @tick: tick value
*
* Returns the time (a QEMU_CLOCK_VIRTUAL timestamp in nanoseconds)
* when the timestamp counter will reach the specified tick count.
* If the counter is not currently running, returns UINT64_MAX.
*/
uint64_t sse_counter_tick_to_time(SSECounter *counter, uint64_t tick);
/**
* sse_counter_register_consumer:
* @counter: SSECounter
* @notifier: Notifier which is notified on counter changes
*
* Registers @notifier with the SSECounter. When the counter's
* configuration changes in a way that might invalidate information
* previously returned via sse_counter_for_timestamp() or
* sse_counter_tick_to_time(), the notifier will be called.
* Devices which consume the timestamp counter can use this as
* a cue to recalculate timer events.
*/
void sse_counter_register_consumer(SSECounter *counter, Notifier *notifier);
#endif
|