qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

hw/arm/iotkit-sysctl: Implement CPUWAIT and INITSVTOR*

The CPUWAIT register acts as a sort of power-control: if a bit
in it is 1 then the CPU will have been forced into waiting
when the system was reset (which in QEMU we model as the
CPU starting powered off). Writing a 0 to the register will
allow the CPU to boot (for QEMU, we model this as powering
it on). Note that writing 0 to the register does not power
off a CPU.

For this to work correctly we need to also honour the
INITSVTOR* registers, which let the guest control where the
CPU will load its SP and PC from when it comes out of reset.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190219125808.25174-8-peter.maydell@linaro.org

+37 -4
+37 -4
hw/misc/iotkit-sysctl.c
··· 25 25 #include "hw/sysbus.h" 26 26 #include "hw/registerfields.h" 27 27 #include "hw/misc/iotkit-sysctl.h" 28 + #include "target/arm/arm-powerctl.h" 29 + #include "target/arm/cpu.h" 28 30 29 31 REG32(SECDBGSTAT, 0x0) 30 32 REG32(SECDBGSET, 0x4) ··· 68 70 0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */ 69 71 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */ 70 72 }; 73 + 74 + /* 75 + * Set the initial secure vector table offset address for the core. 76 + * This will take effect when the CPU next resets. 77 + */ 78 + static void set_init_vtor(uint64_t cpuid, uint32_t vtor) 79 + { 80 + Object *cpuobj = OBJECT(arm_get_cpu_by_id(cpuid)); 81 + 82 + if (cpuobj) { 83 + if (object_property_find(cpuobj, "init-svtor", NULL)) { 84 + object_property_set_uint(cpuobj, vtor, "init-svtor", &error_abort); 85 + } 86 + } 87 + } 71 88 72 89 static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset, 73 90 unsigned size) ··· 229 246 s->gretreg = value; 230 247 break; 231 248 case A_INITSVTOR0: 232 - qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl INITSVTOR0 unimplemented\n"); 233 249 s->initsvtor0 = value; 250 + set_init_vtor(0, s->initsvtor0); 234 251 break; 235 252 case A_CPUWAIT: 236 - qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CPUWAIT unimplemented\n"); 253 + if ((s->cpuwait & 1) && !(value & 1)) { 254 + /* Powering up CPU 0 */ 255 + arm_set_cpu_on_and_reset(0); 256 + } 257 + if ((s->cpuwait & 2) && !(value & 2)) { 258 + /* Powering up CPU 1 */ 259 + arm_set_cpu_on_and_reset(1); 260 + } 237 261 s->cpuwait = value; 238 262 break; 239 263 case A_WICCTRL: ··· 287 311 if (!s->is_sse200) { 288 312 goto bad_offset; 289 313 } 290 - qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl INITSVTOR1 unimplemented\n"); 291 314 s->initsvtor1 = value; 315 + set_init_vtor(1, s->initsvtor1); 292 316 break; 293 317 case A_EWCTRL: 294 318 if (!s->is_sse200) { ··· 382 406 s->gretreg = 0; 383 407 s->initsvtor0 = 0x10000000; 384 408 s->initsvtor1 = 0x10000000; 385 - s->cpuwait = 0; 409 + if (s->is_sse200) { 410 + /* 411 + * CPU 0 starts on, CPU 1 starts off. In real hardware this is 412 + * configurable by the SoC integrator as a verilog parameter. 413 + */ 414 + s->cpuwait = 2; 415 + } else { 416 + /* CPU 0 starts on */ 417 + s->cpuwait = 0; 418 + } 386 419 s->wicctrl = 0; 387 420 s->scsecctrl = 0; 388 421 s->fclk_div = 0;