Skip to content

Commit

Permalink
ppc/pnv: Clarify how the TIMA is accessed on a multichip system
Browse files Browse the repository at this point in the history
The TIMA region gives access to the thread interrupt context registers
of a CPU. It is mapped at the same address on all chips and can be
accessed by any CPU of the system. To identify the chip from which the
access is being done, the PowerBUS uses a 'chip' field in the
load/store messages. QEMU does not model these messages, instead, we
extract the chip id from the CPU PIR and do a lookup at the machine
level to fetch the targeted interrupt controller.

Introduce pnv_get_chip() and pnv_xive_tm_get_xive() helpers to clarify
this process in pnv_xive_get_tctx(). The latter will be removed in the
subsequent patches but the same principle will be kept.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Message-Id: <20191125065820.927-14-clg@kaod.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
  • Loading branch information
legoater authored and dgibson committed Dec 16, 2019
1 parent 74f23d4 commit 5373c61
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 17 deletions.
40 changes: 23 additions & 17 deletions hw/intc/pnv_xive.c
Expand Up @@ -439,31 +439,37 @@ static int pnv_xive_match_nvt(XivePresenter *xptr, uint8_t format,
return count;
}

/*
* The TIMA MMIO space is shared among the chips and to identify the
* chip from which the access is being done, we extract the chip id
* from the PIR.
*/
static PnvXive *pnv_xive_tm_get_xive(PowerPCCPU *cpu)
{
int pir = ppc_cpu_pir(cpu);
PnvChip *chip;
PnvXive *xive;

chip = pnv_get_chip(PNV9_PIR2CHIP(pir));
assert(chip);
xive = &PNV9_CHIP(chip)->xive;

if (!pnv_xive_is_cpu_enabled(xive, cpu)) {
xive_error(xive, "IC: CPU %x is not enabled", pir);
}
return xive;
}

static XiveTCTX *pnv_xive_get_tctx(XiveRouter *xrtr, CPUState *cs)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
XiveTCTX *tctx = XIVE_TCTX(pnv_cpu_state(cpu)->intc);
PnvXive *xive = NULL;
CPUPPCState *env = &cpu->env;
int pir = env->spr_cb[SPR_PIR].default_value;
PnvXive *xive = pnv_xive_tm_get_xive(cpu);

/*
* Perform an extra check on the HW thread enablement.
*
* The TIMA is shared among the chips and to identify the chip
* from which the access is being done, we extract the chip id
* from the PIR.
*/
xive = pnv_xive_get_ic((pir >> 8) & 0xf);
if (!xive) {
return NULL;
}

if (!(xive->regs[PC_THREAD_EN_REG0 >> 3] & PPC_BIT(pir & 0x3f))) {
xive_error(PNV_XIVE(xrtr), "IC: CPU %x is not enabled", pir);
}

return tctx;
return XIVE_TCTX(pnv_cpu_state(cpu)->intc);
}

/*
Expand Down
14 changes: 14 additions & 0 deletions hw/ppc/pnv.c
Expand Up @@ -1472,6 +1472,20 @@ static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
return total_count;
}

PnvChip *pnv_get_chip(uint32_t chip_id)
{
PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
int i;

for (i = 0; i < pnv->num_chips; i++) {
PnvChip *chip = pnv->chips[i];
if (chip->chip_id == chip_id) {
return chip;
}
}
return NULL;
}

static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
Expand Down
3 changes: 3 additions & 0 deletions include/hw/ppc/pnv.h
Expand Up @@ -103,6 +103,7 @@ typedef struct Pnv9Chip {
* A SMT8 fused core is a pair of SMT4 cores.
*/
#define PNV9_PIR2FUSEDCORE(pir) (((pir) >> 3) & 0xf)
#define PNV9_PIR2CHIP(pir) (((pir) >> 8) & 0x7f)

typedef struct PnvChipClass {
/*< private >*/
Expand Down Expand Up @@ -197,6 +198,8 @@ static inline bool pnv_is_power9(PnvMachineState *pnv)
return pnv_chip_is_power9(pnv->chips[0]);
}

PnvChip *pnv_get_chip(uint32_t chip_id);

#define PNV_FDT_ADDR 0x01000000
#define PNV_TIMEBASE_FREQ 512000000ULL

Expand Down

0 comments on commit 5373c61

Please sign in to comment.