[ ... ] >>>> +/* >>>> + * The allocation of VP blocks is a complex operation in OPAL and the >>>> + * VP identifiers have a relation with the number of HW chips, the >>>> + * size of the VP blocks, VP grouping, etc. The QEMU sPAPR XIVE >>>> + * controller model does not have the same constraints and can use a >>>> + * simple mapping scheme of the CPU vcpu_id >>>> + * >>>> + * These identifiers are never returned to the OS. >>>> + */ >>>> + >>>> +#define SPAPR_XIVE_VP_BASE 0x400 >>> >>> 0x400 == 1024. Could we ever have the possibility of needing to >>> consider both physical NVTs and PAPR NVTs at the same time? >> >> They would not be in the same CAM line: OS ring vs. PHYS ring. > > Hm. They still inhabit the same NVT number space though, don't they?
No. skiboot reserves the range of VPs for the HW at init. https://github.com/open-power/skiboot/blob/master/hw/xive.c#L1093 > I'm thinking about the END->NVT stage of the process here, rather than > the NVT->TCTX stage. > > Oh, also, you're using "VP" here which IIUC == "NVT". Can we > standardize on one, please. VP is used in Linux/KVM Linux/Native and skiboot. Yes. it's a mess. Let's have consistent naming in QEMU and use NVT. >>> If so, does this base leave enough space for the physical ones? >> >> I only used 0x400 to map the VP identifier to the ones allocated by KVM. >> 0x0 would be fine but to exercise the model, it's better having a different >> base. >> >>>> +uint32_t spapr_xive_nvt_to_target(sPAPRXive *xive, uint8_t nvt_blk, >>>> + uint32_t nvt_idx) >>>> +{ >>>> + return nvt_idx - SPAPR_XIVE_VP_BASE; >>>> +} >>>> + >>>> +int spapr_xive_cpu_to_nvt(sPAPRXive *xive, PowerPCCPU *cpu, >>>> + uint8_t *out_nvt_blk, uint32_t *out_nvt_idx) >>> >>> A number of these conversions will come out a bit simpler if we pass >>> the block and index around as a single word in most places. >> >> Yes I have to check the whole patchset first. These prototype changes >> are not too difficult in terms of code complexity but they do break >> how patches apply and PowerNV is also using the idx and blk much more >> explicitly. the block has a meaning on bare metal. So I am a bit >> reluctant to do so. I will check. > > Yeah, based on your comments here and earlier, I'm not sure that's a > good idea any more either. > >>>> +{ >>>> + XiveRouter *xrtr = XIVE_ROUTER(xive); >>>> + >>>> + if (!cpu) { >>>> + return -1; >>>> + } >>>> + >>>> + if (out_nvt_blk) { >>>> + /* For testing purpose, we could use 0 for nvt_blk */ >>>> + *out_nvt_blk = xrtr->chip_id; >>> >>> I don't see any point using the chip_id here, which is currently >>> always set to 0 for PAPR anyway. If we just hardwire this to 0 it >>> removes the only use here of xrtr, which will allow some further >>> simplifications in the caller, I think. >> >> You are right about the simplification. It was one way to exercise >> the router model and remove any shortcuts in the indexing. I kept >> it to be sure I was not tempted to invent new ones. I think we can >> remove it before merging. >> >>> >>>> + } >>>> + >>>> + if (out_nvt_blk) { >>>> + *out_nvt_idx = SPAPR_XIVE_VP_BASE + cpu->vcpu_id; >>>> + } >>>> + return 0; >>>> +} >>>> + >>>> +int spapr_xive_target_to_nvt(sPAPRXive *xive, uint32_t target, >>>> + uint8_t *out_nvt_blk, uint32_t *out_nvt_idx) >>> >>> I suspect some, maybe most of these conversion functions could be static. >> >> static inline ? > > It's in a .c file so you don't need the "inline" - the compiler can > work out whether it's a good idea to inline on its own. It is used in the hcall file also. But we are going to change that. Thanks, C. > >>> >>>> +{ >>>> + return spapr_xive_cpu_to_nvt(xive, spapr_find_cpu(target), >>>> out_nvt_blk, >>>> + out_nvt_idx); >>>> +} >>>> + >>>> +/* >>>> + * sPAPR END indexing uses a simple mapping of the CPU vcpu_id, 8 >>>> + * priorities per CPU >>>> + */ >>>> +int spapr_xive_end_to_target(sPAPRXive *xive, uint8_t end_blk, uint32_t >>>> end_idx, >>>> + uint32_t *out_server, uint8_t *out_prio) >>>> +{ >>>> + if (out_server) { >>>> + *out_server = end_idx >> 3; >>>> + } >>>> + >>>> + if (out_prio) { >>>> + *out_prio = end_idx & 0x7; >>>> + } >>>> + return 0; >>>> +} >>>> + >>>> +int spapr_xive_cpu_to_end(sPAPRXive *xive, PowerPCCPU *cpu, uint8_t prio, >>>> + uint8_t *out_end_blk, uint32_t *out_end_idx) >>>> +{ >>>> + XiveRouter *xrtr = XIVE_ROUTER(xive); >>>> + >>>> + if (!cpu) { >>>> + return -1; >>> >>> Is there ever a reason this would be called with cpu == NULL? If not >>> might as well just assert() here rather than pushing the error >>> handling back to the caller. >> >> ok. yes. >> >>> >>>> + } >>>> + >>>> + if (out_end_blk) { >>>> + /* For testing purpose, we could use 0 for nvt_blk */ >>>> + *out_end_blk = xrtr->chip_id; >>> >>> Again, I don't see any point to using the chip_id, which is pretty >>> meaningless for PAPR. >>> >>>> + } >>>> + >>>> + if (out_end_idx) { >>>> + *out_end_idx = (cpu->vcpu_id << 3) + prio; >>>> + } >>>> + return 0; >>>> +} >>>> + >>>> +int spapr_xive_target_to_end(sPAPRXive *xive, uint32_t target, uint8_t >>>> prio, >>>> + uint8_t *out_end_blk, uint32_t *out_end_idx) >>>> +{ >>>> + return spapr_xive_cpu_to_end(xive, spapr_find_cpu(target), prio, >>>> + out_end_blk, out_end_idx); >>>> +} >>>> + >>>> static const VMStateDescription vmstate_spapr_xive_end = { >>>> .name = TYPE_SPAPR_XIVE "/end", >>>> .version_id = 1, >>>> @@ -263,6 +396,9 @@ static void spapr_xive_class_init(ObjectClass *klass, >>>> void *data) >>>> xrc->set_eas = spapr_xive_set_eas; >>>> xrc->get_end = spapr_xive_get_end; >>>> xrc->set_end = spapr_xive_set_end; >>>> + xrc->get_nvt = spapr_xive_get_nvt; >>>> + xrc->set_nvt = spapr_xive_set_nvt; >>>> + xrc->reset_tctx = spapr_xive_reset_tctx; >>>> } >>>> >>>> static const TypeInfo spapr_xive_info = { >>>> diff --git a/hw/intc/xive.c b/hw/intc/xive.c >>>> index c49932d2b799..fc6ef5895e6d 100644 >>>> --- a/hw/intc/xive.c >>>> +++ b/hw/intc/xive.c >>>> @@ -481,6 +481,7 @@ static uint32_t xive_tctx_hw_cam_line(XiveTCTX *tctx, >>>> bool block_group) >>>> static void xive_tctx_reset(void *dev) >>>> { >>>> XiveTCTX *tctx = XIVE_TCTX(dev); >>>> + XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(tctx->xrtr); >>>> >>>> memset(tctx->regs, 0, sizeof(tctx->regs)); >>>> >>>> @@ -495,6 +496,14 @@ static void xive_tctx_reset(void *dev) >>>> */ >>>> tctx->regs[TM_QW1_OS + TM_PIPR] = >>>> ipb_to_pipr(tctx->regs[TM_QW1_OS + TM_IPB]); >>>> + >>>> + /* >>>> + * QEMU sPAPR XIVE only. To let the controller model reset the OS >>>> + * CAM line with the VP identifier. >>>> + */ >>>> + if (xrc->reset_tctx) { >>>> + xrc->reset_tctx(tctx->xrtr, tctx); >>>> + } >>> >>> AFAICT this whole function is only used from PAPR, so you can just >>> move the whole thing to the papr code and avoid the hook function. >> >> Yes we could add a loop on all CPUs and reset all the XiveTCTX from >> the machine or a spapr_irq->reset handler. We will need at some time >> anyhow. >> >> Thanks, >> >> C. >> >> >>> >>>> } >>>> >>>> static void xive_tctx_realize(DeviceState *dev, Error **errp) >>> >> >