ppc/pnv: Fix TIMA indirect access
When the TIMA of a CPU needs to be accessed from the indirect page, the thread id of the target CPU is first stored in the PC_TCTXT_INDIR0 register. This thread id is relative to the chip and not to the system. Introduce a helper routine to look for a CPU of a given PIR and fix pnv_xive_get_indirect_tctx() to scan only the threads of the local chip and not the whole machine. Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20191125065820.927-8-clg@kaod.org> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
5014c60261
commit
119eaa9d11
@ -1400,12 +1400,13 @@ static const MemoryRegionOps pnv_xive_ic_lsi_ops = {
|
||||
*/
|
||||
|
||||
/*
|
||||
* When the TIMA is accessed from the indirect page, the thread id
|
||||
* (PIR) has to be configured in the IC registers before. This is used
|
||||
* for resets and for debug purpose also.
|
||||
* When the TIMA is accessed from the indirect page, the thread id of
|
||||
* the target CPU is configured in the PC_TCTXT_INDIR0 register before
|
||||
* use. This is used for resets and for debug purpose also.
|
||||
*/
|
||||
static XiveTCTX *pnv_xive_get_indirect_tctx(PnvXive *xive)
|
||||
{
|
||||
PnvChip *chip = xive->chip;
|
||||
uint64_t tctxt_indir = xive->regs[PC_TCTXT_INDIR0 >> 3];
|
||||
PowerPCCPU *cpu = NULL;
|
||||
int pir;
|
||||
@ -1415,15 +1416,15 @@ static XiveTCTX *pnv_xive_get_indirect_tctx(PnvXive *xive)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pir = GETFIELD(PC_TCTXT_INDIR_THRDID, tctxt_indir) & 0xff;
|
||||
cpu = ppc_get_vcpu_by_pir(pir);
|
||||
pir = (chip->chip_id << 8) | GETFIELD(PC_TCTXT_INDIR_THRDID, tctxt_indir);
|
||||
cpu = pnv_chip_find_cpu(chip, pir);
|
||||
if (!cpu) {
|
||||
xive_error(xive, "IC: invalid PIR %x for indirect access", pir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check that HW thread is XIVE enabled */
|
||||
if (!(xive->regs[PC_THREAD_EN_REG0 >> 3] & PPC_BIT(pir & 0x3f))) {
|
||||
if (!pnv_xive_is_cpu_enabled(xive, cpu)) {
|
||||
xive_error(xive, "IC: CPU %x is not enabled", pir);
|
||||
}
|
||||
|
||||
|
17
hw/ppc/pnv.c
17
hw/ppc/pnv.c
@ -1371,6 +1371,23 @@ static void pnv_chip_class_init(ObjectClass *klass, void *data)
|
||||
dc->desc = "PowerNV Chip";
|
||||
}
|
||||
|
||||
PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < chip->nr_cores; i++) {
|
||||
PnvCore *pc = chip->cores[i];
|
||||
CPUCore *cc = CPU_CORE(pc);
|
||||
|
||||
for (j = 0; j < cc->nr_threads; j++) {
|
||||
if (ppc_cpu_pir(pc->threads[j]) == pir) {
|
||||
return pc->threads[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
|
||||
{
|
||||
PnvMachineState *pnv = PNV_MACHINE(xi);
|
||||
|
@ -162,6 +162,8 @@ typedef struct PnvChipClass {
|
||||
#define PNV_CHIP_INDEX(chip) \
|
||||
(((chip)->chip_id >> 2) * 2 + ((chip)->chip_id & 0x3))
|
||||
|
||||
PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir);
|
||||
|
||||
#define TYPE_PNV_MACHINE MACHINE_TYPE_NAME("powernv")
|
||||
#define PNV_MACHINE(obj) \
|
||||
OBJECT_CHECK(PnvMachineState, (obj), TYPE_PNV_MACHINE)
|
||||
|
Loading…
Reference in New Issue
Block a user