sse-counter.c (14420B)
1/* 2 * Arm SSE Subsystem System Counter 3 * 4 * Copyright (c) 2020 Linaro Limited 5 * Written by Peter Maydell 6 * 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. 10 */ 11 12/* 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/ 16 * 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. 22 * 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. 28 */ 29#include "qemu/osdep.h" 30#include "qemu/log.h" 31#include "qemu/timer.h" 32#include "qapi/error.h" 33#include "trace.h" 34#include "hw/timer/sse-counter.h" 35#include "hw/sysbus.h" 36#include "hw/registerfields.h" 37#include "hw/clock.h" 38#include "hw/qdev-clock.h" 39#include "migration/vmstate.h" 40 41/* Registers in the control frame */ 42REG32(CNTCR, 0x0) 43 FIELD(CNTCR, EN, 0, 1) 44 FIELD(CNTCR, HDBG, 1, 1) 45 FIELD(CNTCR, SCEN, 2, 1) 46 FIELD(CNTCR, INTRMASK, 3, 1) 47 FIELD(CNTCR, PSLVERRDIS, 4, 1) 48 FIELD(CNTCR, INTRCLR, 5, 1) 49/* 50 * Although CNTCR defines interrupt-related bits, the counter doesn't 51 * appear to actually have an interrupt output. So INTRCLR is 52 * effectively a RAZ/WI bit, as are the reserved bits [31:6]. 53 */ 54#define CNTCR_VALID_MASK (R_CNTCR_EN_MASK | R_CNTCR_HDBG_MASK | \ 55 R_CNTCR_SCEN_MASK | R_CNTCR_INTRMASK_MASK | \ 56 R_CNTCR_PSLVERRDIS_MASK) 57REG32(CNTSR, 0x4) 58REG32(CNTCV_LO, 0x8) 59REG32(CNTCV_HI, 0xc) 60REG32(CNTSCR, 0x10) /* Aliased with CNTSCR0 */ 61REG32(CNTID, 0x1c) 62 FIELD(CNTID, CNTSC, 0, 4) 63 FIELD(CNTID, CNTCS, 16, 1) 64 FIELD(CNTID, CNTSELCLK, 17, 2) 65 FIELD(CNTID, CNTSCR_OVR, 19, 1) 66REG32(CNTSCR0, 0xd0) 67REG32(CNTSCR1, 0xd4) 68 69/* Registers in the status frame */ 70REG32(STATUS_CNTCV_LO, 0x0) 71REG32(STATUS_CNTCV_HI, 0x4) 72 73/* Standard ID registers, present in both frames */ 74REG32(PID4, 0xFD0) 75REG32(PID5, 0xFD4) 76REG32(PID6, 0xFD8) 77REG32(PID7, 0xFDC) 78REG32(PID0, 0xFE0) 79REG32(PID1, 0xFE4) 80REG32(PID2, 0xFE8) 81REG32(PID3, 0xFEC) 82REG32(CID0, 0xFF0) 83REG32(CID1, 0xFF4) 84REG32(CID2, 0xFF8) 85REG32(CID3, 0xFFC) 86 87/* PID/CID values */ 88static const int control_id[] = { 89 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */ 90 0xba, 0xb0, 0x0b, 0x00, /* PID0..PID3 */ 91 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */ 92}; 93 94static const int status_id[] = { 95 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */ 96 0xbb, 0xb0, 0x0b, 0x00, /* PID0..PID3 */ 97 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */ 98}; 99 100static void sse_counter_notify_users(SSECounter *s) 101{ 102 /* 103 * Notify users of the count timestamp that they may 104 * need to recalculate. 105 */ 106 notifier_list_notify(&s->notifier_list, NULL); 107} 108 109static bool sse_counter_enabled(SSECounter *s) 110{ 111 return (s->cntcr & R_CNTCR_EN_MASK) != 0; 112} 113 114uint64_t sse_counter_tick_to_time(SSECounter *s, uint64_t tick) 115{ 116 if (!sse_counter_enabled(s)) { 117 return UINT64_MAX; 118 } 119 120 tick -= s->ticks_then; 121 122 if (s->cntcr & R_CNTCR_SCEN_MASK) { 123 /* Adjust the tick count to account for the scale factor */ 124 tick = muldiv64(tick, 0x01000000, s->cntscr0); 125 } 126 127 return s->ns_then + clock_ticks_to_ns(s->clk, tick); 128} 129 130void sse_counter_register_consumer(SSECounter *s, Notifier *notifier) 131{ 132 /* 133 * For the moment we assume that both we and the devices 134 * which consume us last for the life of the simulation, 135 * and so there is no mechanism for removing a notifier. 136 */ 137 notifier_list_add(&s->notifier_list, notifier); 138} 139 140uint64_t sse_counter_for_timestamp(SSECounter *s, uint64_t now) 141{ 142 /* Return the CNTCV value for a particular timestamp (clock ns value). */ 143 uint64_t ticks; 144 145 if (!sse_counter_enabled(s)) { 146 /* Counter is disabled and does not increment */ 147 return s->ticks_then; 148 } 149 150 ticks = clock_ns_to_ticks(s->clk, now - s->ns_then); 151 if (s->cntcr & R_CNTCR_SCEN_MASK) { 152 /* 153 * Scaling is enabled. The CNTSCR value is the amount added to 154 * the underlying 88-bit counter for every tick of the 155 * underlying clock; CNTCV is the top 64 bits of that full 156 * 88-bit value. Multiplying the tick count by CNTSCR tells us 157 * how much the full 88-bit counter has moved on; we then 158 * divide that by 0x01000000 to find out how much the 64-bit 159 * visible portion has advanced. muldiv64() gives us the 160 * necessary at-least-88-bit precision for the intermediate 161 * result. 162 */ 163 ticks = muldiv64(ticks, s->cntscr0, 0x01000000); 164 } 165 return s->ticks_then + ticks; 166} 167 168static uint64_t sse_cntcv(SSECounter *s) 169{ 170 /* Return the CNTCV value for the current time */ 171 return sse_counter_for_timestamp(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); 172} 173 174static void sse_write_cntcv(SSECounter *s, uint32_t value, unsigned startbit) 175{ 176 /* 177 * Write one 32-bit half of the counter value; startbit is the 178 * bit position of this half in the 64-bit word, either 0 or 32. 179 */ 180 uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 181 uint64_t cntcv = sse_counter_for_timestamp(s, now); 182 183 cntcv = deposit64(cntcv, startbit, 32, value); 184 s->ticks_then = cntcv; 185 s->ns_then = now; 186 sse_counter_notify_users(s); 187} 188 189static uint64_t sse_counter_control_read(void *opaque, hwaddr offset, 190 unsigned size) 191{ 192 SSECounter *s = SSE_COUNTER(opaque); 193 uint64_t r; 194 195 switch (offset) { 196 case A_CNTCR: 197 r = s->cntcr; 198 break; 199 case A_CNTSR: 200 /* 201 * The only bit here is DBGH, indicating that the counter has been 202 * halted via the Halt-on-Debug signal. We don't implement halting 203 * debug, so the whole register always reads as zero. 204 */ 205 r = 0; 206 break; 207 case A_CNTCV_LO: 208 r = extract64(sse_cntcv(s), 0, 32); 209 break; 210 case A_CNTCV_HI: 211 r = extract64(sse_cntcv(s), 32, 32); 212 break; 213 case A_CNTID: 214 /* 215 * For our implementation: 216 * - CNTSCR can only be written when CNTCR.EN == 0 217 * - HWCLKSW=0, so selected clock is always CLK0 218 * - counter scaling is implemented 219 */ 220 r = (1 << R_CNTID_CNTSELCLK_SHIFT) | (1 << R_CNTID_CNTSC_SHIFT); 221 break; 222 case A_CNTSCR: 223 case A_CNTSCR0: 224 r = s->cntscr0; 225 break; 226 case A_CNTSCR1: 227 /* If HWCLKSW == 0, CNTSCR1 is RAZ/WI */ 228 r = 0; 229 break; 230 case A_PID4 ... A_CID3: 231 r = control_id[(offset - A_PID4) / 4]; 232 break; 233 default: 234 qemu_log_mask(LOG_GUEST_ERROR, 235 "SSE System Counter control frame read: bad offset 0x%x", 236 (unsigned)offset); 237 r = 0; 238 break; 239 } 240 241 trace_sse_counter_control_read(offset, r, size); 242 return r; 243} 244 245static void sse_counter_control_write(void *opaque, hwaddr offset, 246 uint64_t value, unsigned size) 247{ 248 SSECounter *s = SSE_COUNTER(opaque); 249 250 trace_sse_counter_control_write(offset, value, size); 251 252 switch (offset) { 253 case A_CNTCR: 254 /* 255 * Although CNTCR defines interrupt-related bits, the counter doesn't 256 * appear to actually have an interrupt output. So INTRCLR is 257 * effectively a RAZ/WI bit, as are the reserved bits [31:6]. 258 * The documentation does not explicitly say so, but we assume 259 * that changing the scale factor while the counter is enabled 260 * by toggling CNTCR.SCEN has the same behaviour (making the counter 261 * value UNKNOWN) as changing it by writing to CNTSCR, and so we 262 * don't need to try to recalculate for that case. 263 */ 264 value &= CNTCR_VALID_MASK; 265 if ((value ^ s->cntcr) & R_CNTCR_EN_MASK) { 266 /* 267 * Whether the counter is being enabled or disabled, the 268 * required action is the same: sync the (ns_then, ticks_then) 269 * tuple. 270 */ 271 uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 272 s->ticks_then = sse_counter_for_timestamp(s, now); 273 s->ns_then = now; 274 sse_counter_notify_users(s); 275 } 276 s->cntcr = value; 277 break; 278 case A_CNTCV_LO: 279 sse_write_cntcv(s, value, 0); 280 break; 281 case A_CNTCV_HI: 282 sse_write_cntcv(s, value, 32); 283 break; 284 case A_CNTSCR: 285 case A_CNTSCR0: 286 /* 287 * If the scale registers are changed when the counter is enabled, 288 * the count value becomes UNKNOWN. So we don't try to recalculate 289 * anything here but only do it on a write to CNTCR.EN. 290 */ 291 s->cntscr0 = value; 292 break; 293 case A_CNTSCR1: 294 /* If HWCLKSW == 0, CNTSCR1 is RAZ/WI */ 295 break; 296 case A_CNTSR: 297 case A_CNTID: 298 case A_PID4 ... A_CID3: 299 qemu_log_mask(LOG_GUEST_ERROR, 300 "SSE System Counter control frame: write to RO offset 0x%x\n", 301 (unsigned)offset); 302 break; 303 default: 304 qemu_log_mask(LOG_GUEST_ERROR, 305 "SSE System Counter control frame: write to bad offset 0x%x\n", 306 (unsigned)offset); 307 break; 308 } 309} 310 311static uint64_t sse_counter_status_read(void *opaque, hwaddr offset, 312 unsigned size) 313{ 314 SSECounter *s = SSE_COUNTER(opaque); 315 uint64_t r; 316 317 switch (offset) { 318 case A_STATUS_CNTCV_LO: 319 r = extract64(sse_cntcv(s), 0, 32); 320 break; 321 case A_STATUS_CNTCV_HI: 322 r = extract64(sse_cntcv(s), 32, 32); 323 break; 324 case A_PID4 ... A_CID3: 325 r = status_id[(offset - A_PID4) / 4]; 326 break; 327 default: 328 qemu_log_mask(LOG_GUEST_ERROR, 329 "SSE System Counter status frame read: bad offset 0x%x", 330 (unsigned)offset); 331 r = 0; 332 break; 333 } 334 335 trace_sse_counter_status_read(offset, r, size); 336 return r; 337} 338 339static void sse_counter_status_write(void *opaque, hwaddr offset, 340 uint64_t value, unsigned size) 341{ 342 trace_sse_counter_status_write(offset, value, size); 343 344 switch (offset) { 345 case A_STATUS_CNTCV_LO: 346 case A_STATUS_CNTCV_HI: 347 case A_PID4 ... A_CID3: 348 qemu_log_mask(LOG_GUEST_ERROR, 349 "SSE System Counter status frame: write to RO offset 0x%x\n", 350 (unsigned)offset); 351 break; 352 default: 353 qemu_log_mask(LOG_GUEST_ERROR, 354 "SSE System Counter status frame: write to bad offset 0x%x\n", 355 (unsigned)offset); 356 break; 357 } 358} 359 360static const MemoryRegionOps sse_counter_control_ops = { 361 .read = sse_counter_control_read, 362 .write = sse_counter_control_write, 363 .endianness = DEVICE_LITTLE_ENDIAN, 364 .valid.min_access_size = 4, 365 .valid.max_access_size = 4, 366}; 367 368static const MemoryRegionOps sse_counter_status_ops = { 369 .read = sse_counter_status_read, 370 .write = sse_counter_status_write, 371 .endianness = DEVICE_LITTLE_ENDIAN, 372 .valid.min_access_size = 4, 373 .valid.max_access_size = 4, 374}; 375 376static void sse_counter_reset(DeviceState *dev) 377{ 378 SSECounter *s = SSE_COUNTER(dev); 379 380 trace_sse_counter_reset(); 381 382 s->cntcr = 0; 383 s->cntscr0 = 0x01000000; 384 s->ns_then = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 385 s->ticks_then = 0; 386} 387 388static void sse_clk_callback(void *opaque, ClockEvent event) 389{ 390 SSECounter *s = SSE_COUNTER(opaque); 391 uint64_t now; 392 393 switch (event) { 394 case ClockPreUpdate: 395 /* 396 * Before the clock period updates, set (ticks_then, ns_then) 397 * to the current time and tick count (as calculated with 398 * the old clock period). 399 */ 400 if (sse_counter_enabled(s)) { 401 now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 402 s->ticks_then = sse_counter_for_timestamp(s, now); 403 s->ns_then = now; 404 } 405 break; 406 case ClockUpdate: 407 sse_counter_notify_users(s); 408 break; 409 default: 410 break; 411 } 412} 413 414static void sse_counter_init(Object *obj) 415{ 416 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 417 SSECounter *s = SSE_COUNTER(obj); 418 419 notifier_list_init(&s->notifier_list); 420 421 s->clk = qdev_init_clock_in(DEVICE(obj), "CLK", sse_clk_callback, s, 422 ClockPreUpdate | ClockUpdate); 423 memory_region_init_io(&s->control_mr, obj, &sse_counter_control_ops, 424 s, "sse-counter-control", 0x1000); 425 memory_region_init_io(&s->status_mr, obj, &sse_counter_status_ops, 426 s, "sse-counter-status", 0x1000); 427 sysbus_init_mmio(sbd, &s->control_mr); 428 sysbus_init_mmio(sbd, &s->status_mr); 429} 430 431static void sse_counter_realize(DeviceState *dev, Error **errp) 432{ 433 SSECounter *s = SSE_COUNTER(dev); 434 435 if (!clock_has_source(s->clk)) { 436 error_setg(errp, "SSE system counter: CLK must be connected"); 437 return; 438 } 439} 440 441static const VMStateDescription sse_counter_vmstate = { 442 .name = "sse-counter", 443 .version_id = 1, 444 .minimum_version_id = 1, 445 .fields = (VMStateField[]) { 446 VMSTATE_CLOCK(clk, SSECounter), 447 VMSTATE_END_OF_LIST() 448 } 449}; 450 451static void sse_counter_class_init(ObjectClass *klass, void *data) 452{ 453 DeviceClass *dc = DEVICE_CLASS(klass); 454 455 dc->realize = sse_counter_realize; 456 dc->vmsd = &sse_counter_vmstate; 457 dc->reset = sse_counter_reset; 458} 459 460static const TypeInfo sse_counter_info = { 461 .name = TYPE_SSE_COUNTER, 462 .parent = TYPE_SYS_BUS_DEVICE, 463 .instance_size = sizeof(SSECounter), 464 .instance_init = sse_counter_init, 465 .class_init = sse_counter_class_init, 466}; 467 468static void sse_counter_register_types(void) 469{ 470 type_register_static(&sse_counter_info); 471} 472 473type_init(sse_counter_register_types);