mirror of https://github.com/xemu-project/xemu.git
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
|
* When the TIMA is accessed from the indirect page, the thread id of
|
||||||
* (PIR) has to be configured in the IC registers before. This is used
|
* the target CPU is configured in the PC_TCTXT_INDIR0 register before
|
||||||
* for resets and for debug purpose also.
|
* use. This is used for resets and for debug purpose also.
|
||||||
*/
|
*/
|
||||||
static XiveTCTX *pnv_xive_get_indirect_tctx(PnvXive *xive)
|
static XiveTCTX *pnv_xive_get_indirect_tctx(PnvXive *xive)
|
||||||
{
|
{
|
||||||
|
PnvChip *chip = xive->chip;
|
||||||
uint64_t tctxt_indir = xive->regs[PC_TCTXT_INDIR0 >> 3];
|
uint64_t tctxt_indir = xive->regs[PC_TCTXT_INDIR0 >> 3];
|
||||||
PowerPCCPU *cpu = NULL;
|
PowerPCCPU *cpu = NULL;
|
||||||
int pir;
|
int pir;
|
||||||
|
@ -1415,15 +1416,15 @@ static XiveTCTX *pnv_xive_get_indirect_tctx(PnvXive *xive)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pir = GETFIELD(PC_TCTXT_INDIR_THRDID, tctxt_indir) & 0xff;
|
pir = (chip->chip_id << 8) | GETFIELD(PC_TCTXT_INDIR_THRDID, tctxt_indir);
|
||||||
cpu = ppc_get_vcpu_by_pir(pir);
|
cpu = pnv_chip_find_cpu(chip, pir);
|
||||||
if (!cpu) {
|
if (!cpu) {
|
||||||
xive_error(xive, "IC: invalid PIR %x for indirect access", pir);
|
xive_error(xive, "IC: invalid PIR %x for indirect access", pir);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that HW thread is XIVE enabled */
|
/* 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);
|
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";
|
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)
|
static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
|
||||||
{
|
{
|
||||||
PnvMachineState *pnv = PNV_MACHINE(xi);
|
PnvMachineState *pnv = PNV_MACHINE(xi);
|
||||||
|
|
|
@ -162,6 +162,8 @@ typedef struct PnvChipClass {
|
||||||
#define PNV_CHIP_INDEX(chip) \
|
#define PNV_CHIP_INDEX(chip) \
|
||||||
(((chip)->chip_id >> 2) * 2 + ((chip)->chip_id & 0x3))
|
(((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 TYPE_PNV_MACHINE MACHINE_TYPE_NAME("powernv")
|
||||||
#define PNV_MACHINE(obj) \
|
#define PNV_MACHINE(obj) \
|
||||||
OBJECT_CHECK(PnvMachineState, (obj), TYPE_PNV_MACHINE)
|
OBJECT_CHECK(PnvMachineState, (obj), TYPE_PNV_MACHINE)
|
||||||
|
|
Loading…
Reference in New Issue