2 * Arm SSE Subsystem System Counter
4 * Copyright (c) 2020 Linaro Limited
5 * Written by Peter Maydell
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 or
9 * (at your option) any later version.
13 * This is a model of the "System counter" which is documented in
14 * the Arm SSE-123 Example Subsystem Technical Reference Manual:
15 * https://developer.arm.com/documentation/101370/latest/
17 * The system counter is a non-stop 64-bit up-counter. It provides
18 * this count value to other devices like the SSE system timer,
19 * which are driven by this system timestamp rather than directly
20 * from a clock. Internally to the counter the count is actually
21 * 88-bit precision (64.24 fixed point), with a programmable scale factor.
23 * The hardware has the optional feature that it supports dynamic
24 * clock switching, where two clock inputs are connected, and which
25 * one is used is selected via a CLKSEL input signal. Since the
26 * users of this device in QEMU don't use this feature, we only model
27 * the HWCLKSW=0 configuration.
29 #include "qemu/osdep.h"
31 #include "qemu/timer.h"
32 #include "qapi/error.h"
34 #include "hw/timer/sse-counter.h"
35 #include "hw/sysbus.h"
37 #include "hw/registerfields.h"
39 #include "hw/qdev-clock.h"
40 #include "migration/vmstate.h"
42 /* Registers in the control frame */
44 FIELD(CNTCR
, EN
, 0, 1)
45 FIELD(CNTCR
, HDBG
, 1, 1)
46 FIELD(CNTCR
, SCEN
, 2, 1)
47 FIELD(CNTCR
, INTRMASK
, 3, 1)
48 FIELD(CNTCR
, PSLVERRDIS
, 4, 1)
49 FIELD(CNTCR
, INTRCLR
, 5, 1)
51 * Although CNTCR defines interrupt-related bits, the counter doesn't
52 * appear to actually have an interrupt output. So INTRCLR is
53 * effectively a RAZ/WI bit, as are the reserved bits [31:6].
55 #define CNTCR_VALID_MASK (R_CNTCR_EN_MASK | R_CNTCR_HDBG_MASK | \
56 R_CNTCR_SCEN_MASK | R_CNTCR_INTRMASK_MASK | \
57 R_CNTCR_PSLVERRDIS_MASK)
61 REG32(CNTSCR
, 0x10) /* Aliased with CNTSCR0 */
63 FIELD(CNTID
, CNTSC
, 0, 4)
64 FIELD(CNTID
, CNTCS
, 16, 1)
65 FIELD(CNTID
, CNTSELCLK
, 17, 2)
66 FIELD(CNTID
, CNTSCR_OVR
, 19, 1)
70 /* Registers in the status frame */
71 REG32(STATUS_CNTCV_LO
, 0x0)
72 REG32(STATUS_CNTCV_HI
, 0x4)
74 /* Standard ID registers, present in both frames */
89 static const int control_id
[] = {
90 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
91 0xba, 0xb0, 0x0b, 0x00, /* PID0..PID3 */
92 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
95 static const int status_id
[] = {
96 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
97 0xbb, 0xb0, 0x0b, 0x00, /* PID0..PID3 */
98 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
101 static void sse_counter_notify_users(SSECounter
*s
)
104 * Notify users of the count timestamp that they may
105 * need to recalculate.
107 notifier_list_notify(&s
->notifier_list
, NULL
);
110 static bool sse_counter_enabled(SSECounter
*s
)
112 return (s
->cntcr
& R_CNTCR_EN_MASK
) != 0;
115 uint64_t sse_counter_tick_to_time(SSECounter
*s
, uint64_t tick
)
117 if (!sse_counter_enabled(s
)) {
121 tick
-= s
->ticks_then
;
123 if (s
->cntcr
& R_CNTCR_SCEN_MASK
) {
124 /* Adjust the tick count to account for the scale factor */
125 tick
= muldiv64(tick
, 0x01000000, s
->cntscr0
);
128 return s
->ns_then
+ clock_ticks_to_ns(s
->clk
, tick
);
131 void sse_counter_register_consumer(SSECounter
*s
, Notifier
*notifier
)
134 * For the moment we assume that both we and the devices
135 * which consume us last for the life of the simulation,
136 * and so there is no mechanism for removing a notifier.
138 notifier_list_add(&s
->notifier_list
, notifier
);
141 uint64_t sse_counter_for_timestamp(SSECounter
*s
, uint64_t now
)
143 /* Return the CNTCV value for a particular timestamp (clock ns value). */
146 if (!sse_counter_enabled(s
)) {
147 /* Counter is disabled and does not increment */
148 return s
->ticks_then
;
151 ticks
= clock_ns_to_ticks(s
->clk
, now
- s
->ns_then
);
152 if (s
->cntcr
& R_CNTCR_SCEN_MASK
) {
154 * Scaling is enabled. The CNTSCR value is the amount added to
155 * the underlying 88-bit counter for every tick of the
156 * underlying clock; CNTCV is the top 64 bits of that full
157 * 88-bit value. Multiplying the tick count by CNTSCR tells us
158 * how much the full 88-bit counter has moved on; we then
159 * divide that by 0x01000000 to find out how much the 64-bit
160 * visible portion has advanced. muldiv64() gives us the
161 * necessary at-least-88-bit precision for the intermediate
164 ticks
= muldiv64(ticks
, s
->cntscr0
, 0x01000000);
166 return s
->ticks_then
+ ticks
;
169 static uint64_t sse_cntcv(SSECounter
*s
)
171 /* Return the CNTCV value for the current time */
172 return sse_counter_for_timestamp(s
, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
));
175 static void sse_write_cntcv(SSECounter
*s
, uint32_t value
, unsigned startbit
)
178 * Write one 32-bit half of the counter value; startbit is the
179 * bit position of this half in the 64-bit word, either 0 or 32.
181 uint64_t now
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
182 uint64_t cntcv
= sse_counter_for_timestamp(s
, now
);
184 cntcv
= deposit64(cntcv
, startbit
, 32, value
);
185 s
->ticks_then
= cntcv
;
187 sse_counter_notify_users(s
);
190 static uint64_t sse_counter_control_read(void *opaque
, hwaddr offset
,
193 SSECounter
*s
= SSE_COUNTER(opaque
);
202 * The only bit here is DBGH, indicating that the counter has been
203 * halted via the Halt-on-Debug signal. We don't implement halting
204 * debug, so the whole register always reads as zero.
209 r
= extract64(sse_cntcv(s
), 0, 32);
212 r
= extract64(sse_cntcv(s
), 32, 32);
216 * For our implementation:
217 * - CNTSCR can only be written when CNTCR.EN == 0
218 * - HWCLKSW=0, so selected clock is always CLK0
219 * - counter scaling is implemented
221 r
= (1 << R_CNTID_CNTSELCLK_SHIFT
) | (1 << R_CNTID_CNTSC_SHIFT
);
228 /* If HWCLKSW == 0, CNTSCR1 is RAZ/WI */
231 case A_PID4
... A_CID3
:
232 r
= control_id
[(offset
- A_PID4
) / 4];
235 qemu_log_mask(LOG_GUEST_ERROR
,
236 "SSE System Counter control frame read: bad offset 0x%x",
242 trace_sse_counter_control_read(offset
, r
, size
);
246 static void sse_counter_control_write(void *opaque
, hwaddr offset
,
247 uint64_t value
, unsigned size
)
249 SSECounter
*s
= SSE_COUNTER(opaque
);
251 trace_sse_counter_control_write(offset
, value
, size
);
256 * Although CNTCR defines interrupt-related bits, the counter doesn't
257 * appear to actually have an interrupt output. So INTRCLR is
258 * effectively a RAZ/WI bit, as are the reserved bits [31:6].
259 * The documentation does not explicitly say so, but we assume
260 * that changing the scale factor while the counter is enabled
261 * by toggling CNTCR.SCEN has the same behaviour (making the counter
262 * value UNKNOWN) as changing it by writing to CNTSCR, and so we
263 * don't need to try to recalculate for that case.
265 value
&= CNTCR_VALID_MASK
;
266 if ((value
^ s
->cntcr
) & R_CNTCR_EN_MASK
) {
268 * Whether the counter is being enabled or disabled, the
269 * required action is the same: sync the (ns_then, ticks_then)
272 uint64_t now
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
273 s
->ticks_then
= sse_counter_for_timestamp(s
, now
);
275 sse_counter_notify_users(s
);
280 sse_write_cntcv(s
, value
, 0);
283 sse_write_cntcv(s
, value
, 32);
288 * If the scale registers are changed when the counter is enabled,
289 * the count value becomes UNKNOWN. So we don't try to recalculate
290 * anything here but only do it on a write to CNTCR.EN.
295 /* If HWCLKSW == 0, CNTSCR1 is RAZ/WI */
299 case A_PID4
... A_CID3
:
300 qemu_log_mask(LOG_GUEST_ERROR
,
301 "SSE System Counter control frame: write to RO offset 0x%x\n",
305 qemu_log_mask(LOG_GUEST_ERROR
,
306 "SSE System Counter control frame: write to bad offset 0x%x\n",
312 static uint64_t sse_counter_status_read(void *opaque
, hwaddr offset
,
315 SSECounter
*s
= SSE_COUNTER(opaque
);
319 case A_STATUS_CNTCV_LO
:
320 r
= extract64(sse_cntcv(s
), 0, 32);
322 case A_STATUS_CNTCV_HI
:
323 r
= extract64(sse_cntcv(s
), 32, 32);
325 case A_PID4
... A_CID3
:
326 r
= status_id
[(offset
- A_PID4
) / 4];
329 qemu_log_mask(LOG_GUEST_ERROR
,
330 "SSE System Counter status frame read: bad offset 0x%x",
336 trace_sse_counter_status_read(offset
, r
, size
);
340 static void sse_counter_status_write(void *opaque
, hwaddr offset
,
341 uint64_t value
, unsigned size
)
343 trace_sse_counter_status_write(offset
, value
, size
);
346 case A_STATUS_CNTCV_LO
:
347 case A_STATUS_CNTCV_HI
:
348 case A_PID4
... A_CID3
:
349 qemu_log_mask(LOG_GUEST_ERROR
,
350 "SSE System Counter status frame: write to RO offset 0x%x\n",
354 qemu_log_mask(LOG_GUEST_ERROR
,
355 "SSE System Counter status frame: write to bad offset 0x%x\n",
361 static const MemoryRegionOps sse_counter_control_ops
= {
362 .read
= sse_counter_control_read
,
363 .write
= sse_counter_control_write
,
364 .endianness
= DEVICE_LITTLE_ENDIAN
,
365 .valid
.min_access_size
= 4,
366 .valid
.max_access_size
= 4,
369 static const MemoryRegionOps sse_counter_status_ops
= {
370 .read
= sse_counter_status_read
,
371 .write
= sse_counter_status_write
,
372 .endianness
= DEVICE_LITTLE_ENDIAN
,
373 .valid
.min_access_size
= 4,
374 .valid
.max_access_size
= 4,
377 static void sse_counter_reset(DeviceState
*dev
)
379 SSECounter
*s
= SSE_COUNTER(dev
);
381 trace_sse_counter_reset();
384 s
->cntscr0
= 0x01000000;
385 s
->ns_then
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
389 static void sse_clk_callback(void *opaque
, ClockEvent event
)
391 SSECounter
*s
= SSE_COUNTER(opaque
);
397 * Before the clock period updates, set (ticks_then, ns_then)
398 * to the current time and tick count (as calculated with
399 * the old clock period).
401 if (sse_counter_enabled(s
)) {
402 now
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
403 s
->ticks_then
= sse_counter_for_timestamp(s
, now
);
408 sse_counter_notify_users(s
);
415 static void sse_counter_init(Object
*obj
)
417 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
418 SSECounter
*s
= SSE_COUNTER(obj
);
420 notifier_list_init(&s
->notifier_list
);
422 s
->clk
= qdev_init_clock_in(DEVICE(obj
), "CLK", sse_clk_callback
, s
,
423 ClockPreUpdate
| ClockUpdate
);
424 memory_region_init_io(&s
->control_mr
, obj
, &sse_counter_control_ops
,
425 s
, "sse-counter-control", 0x1000);
426 memory_region_init_io(&s
->status_mr
, obj
, &sse_counter_status_ops
,
427 s
, "sse-counter-status", 0x1000);
428 sysbus_init_mmio(sbd
, &s
->control_mr
);
429 sysbus_init_mmio(sbd
, &s
->status_mr
);
432 static void sse_counter_realize(DeviceState
*dev
, Error
**errp
)
434 SSECounter
*s
= SSE_COUNTER(dev
);
436 if (!clock_has_source(s
->clk
)) {
437 error_setg(errp
, "SSE system counter: CLK must be connected");
442 static const VMStateDescription sse_counter_vmstate
= {
443 .name
= "sse-counter",
445 .minimum_version_id
= 1,
446 .fields
= (VMStateField
[]) {
447 VMSTATE_CLOCK(clk
, SSECounter
),
448 VMSTATE_END_OF_LIST()
452 static void sse_counter_class_init(ObjectClass
*klass
, void *data
)
454 DeviceClass
*dc
= DEVICE_CLASS(klass
);
456 dc
->realize
= sse_counter_realize
;
457 dc
->vmsd
= &sse_counter_vmstate
;
458 dc
->reset
= sse_counter_reset
;
461 static const TypeInfo sse_counter_info
= {
462 .name
= TYPE_SSE_COUNTER
,
463 .parent
= TYPE_SYS_BUS_DEVICE
,
464 .instance_size
= sizeof(SSECounter
),
465 .instance_init
= sse_counter_init
,
466 .class_init
= sse_counter_class_init
,
469 static void sse_counter_register_types(void)
471 type_register_static(&sse_counter_info
);
474 type_init(sse_counter_register_types
);