#include "qemu/osdep.h"
#include "qemu/datadir.h"
+#include "qemu/log.h"
#include "qemu/units.h"
#include "qemu/cutils.h"
#include "qapi/error.h"
}
}
+static uint64_t pnv_handle_sprd_load(CPUPPCState *env)
+{
+ PowerPCCPU *cpu = env_archcpu(env);
+ PnvCore *pc = pnv_cpu_state(cpu)->pnv_core;
+ uint64_t sprc = env->spr[SPR_POWER_SPRC];
+
+ if (pc->big_core) {
+ pc = pnv_chip_find_core(pc->chip, CPU_CORE(pc)->core_id & ~0x1);
+ }
+
+ switch (sprc & 0x3e0) {
+ case 0: /* SCRATCH0-3 */
+ case 1: /* SCRATCH4-7 */
+ return pc->scratch[(sprc >> 3) & 0x7];
+
+ case 0x1e0: /* core thread state */
+ if (env->excp_model == POWERPC_EXCP_POWER9) {
+ /*
+ * Only implement for POWER9 because skiboot uses it to check
+ * big-core mode. Other bits are unimplemented so we would
+ * prefer to get unimplemented message on POWER10 if it were
+ * used anywhere.
+ */
+ if (pc->big_core) {
+ return PPC_BIT(63);
+ } else {
+ return 0;
+ }
+ }
+ /* fallthru */
+
+ default:
+ qemu_log_mask(LOG_UNIMP, "mfSPRD: Unimplemented SPRC:0x"
+ TARGET_FMT_lx"\n", sprc);
+ break;
+ }
+ return 0;
+}
+
+static void pnv_handle_sprd_store(CPUPPCState *env, uint64_t val)
+{
+ PowerPCCPU *cpu = env_archcpu(env);
+ uint64_t sprc = env->spr[SPR_POWER_SPRC];
+ PnvCore *pc = pnv_cpu_state(cpu)->pnv_core;
+ int nr;
+
+ if (pc->big_core) {
+ pc = pnv_chip_find_core(pc->chip, CPU_CORE(pc)->core_id & ~0x1);
+ }
+
+ switch (sprc & 0x3e0) {
+ case 0: /* SCRATCH0-3 */
+ case 1: /* SCRATCH4-7 */
+ /*
+ * Log stores to SCRATCH, because some firmware uses these for
+ * debugging and logging, but they would normally be read by the BMC,
+ * which is not implemented in QEMU yet. This gives a way to get at the
+ * information. Could also dump these upon checkstop.
+ */
+ nr = (sprc >> 3) & 0x7;
+ pc->scratch[nr] = val;
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "mtSPRD: Unimplemented SPRC:0x"
+ TARGET_FMT_lx"\n", sprc);
+ break;
+ }
+}
+
static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
{
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
Pnv9Chip *chip9 = PNV9_CHIP(dev);
PnvChip *chip = PNV_CHIP(dev);
Pnv9Psi *psi9 = &chip9->psi;
+ PowerPCCPU *cpu;
+ PowerPCCPUClass *cpu_class;
Error *local_err = NULL;
int i;
return;
}
+ /* Set handlers for Special registers, such as SPRD */
+ cpu = chip->cores[0]->threads[0];
+ cpu_class = POWERPC_CPU_GET_CLASS(cpu);
+ cpu_class->load_sprd = pnv_handle_sprd_load;
+ cpu_class->store_sprd = pnv_handle_sprd_store;
+
/* XIVE interrupt controller (POWER9) */
object_property_set_int(OBJECT(&chip9->xive), "ic-bar",
PNV9_XIVE_IC_BASE(chip), &error_fatal);
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
PnvChip *chip = PNV_CHIP(dev);
Pnv10Chip *chip10 = PNV10_CHIP(dev);
+ PowerPCCPU *cpu;
+ PowerPCCPUClass *cpu_class;
Error *local_err = NULL;
int i;
return;
}
+ /* Set handlers for Special registers, such as SPRD */
+ cpu = chip->cores[0]->threads[0];
+ cpu_class = POWERPC_CPU_GET_CLASS(cpu);
+ cpu_class->load_sprd = pnv_handle_sprd_load;
+ cpu_class->store_sprd = pnv_handle_sprd_store;
+
/* XIVE2 interrupt controller (POWER10) */
object_property_set_int(OBJECT(&chip10->xive), "ic-bar",
PNV10_XIVE2_IC_BASE(chip), &error_fatal);
* accessed by powernv machines.
*/
PowerPCCPU *cpu = env_archcpu(env);
- PnvCore *pc = pnv_cpu_state(cpu)->pnv_core;
- target_ulong sprc = env->spr[SPR_POWER_SPRC];
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
- if (pc->big_core) {
- pc = pnv_chip_find_core(pc->chip, CPU_CORE(pc)->core_id & ~0x1);
+ if (pcc->load_sprd) {
+ return pcc->load_sprd(env);
}
- switch (sprc & 0x3e0) {
- case 0: /* SCRATCH0-3 */
- case 1: /* SCRATCH4-7 */
- return pc->scratch[(sprc >> 3) & 0x7];
-
- case 0x1e0: /* core thread state */
- if (env->excp_model == POWERPC_EXCP_POWER9) {
- /*
- * Only implement for POWER9 because skiboot uses it to check
- * big-core mode. Other bits are unimplemented so we would
- * prefer to get unimplemented message on POWER10 if it were
- * used anywhere.
- */
- if (pc->big_core) {
- return PPC_BIT(63);
- } else {
- return 0;
- }
- }
- /* fallthru */
-
- default:
- qemu_log_mask(LOG_UNIMP, "mfSPRD: Unimplemented SPRC:0x"
- TARGET_FMT_lx"\n", sprc);
- break;
- }
return 0;
}
void helper_store_sprd(CPUPPCState *env, target_ulong val)
{
- target_ulong sprc = env->spr[SPR_POWER_SPRC];
PowerPCCPU *cpu = env_archcpu(env);
- PnvCore *pc = pnv_cpu_state(cpu)->pnv_core;
- int nr;
-
- if (pc->big_core) {
- pc = pnv_chip_find_core(pc->chip, CPU_CORE(pc)->core_id & ~0x1);
- }
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
- switch (sprc & 0x3e0) {
- case 0: /* SCRATCH0-3 */
- case 1: /* SCRATCH4-7 */
- /*
- * Log stores to SCRATCH, because some firmware uses these for
- * debugging and logging, but they would normally be read by the BMC,
- * which is not implemented in QEMU yet. This gives a way to get at the
- * information. Could also dump these upon checkstop.
- */
- nr = (sprc >> 3) & 0x7;
- pc->scratch[nr] = val;
- break;
- default:
- qemu_log_mask(LOG_UNIMP, "mtSPRD: Unimplemented SPRC:0x"
- TARGET_FMT_lx"\n", sprc);
- break;
+ if (pcc->store_sprd) {
+ return pcc->store_sprd(env, val);
}
}