[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-ppc] [PATCH v6 06/37] ppc/xive: add support for the END Event
From: |
Cédric Le Goater |
Subject: |
Re: [Qemu-ppc] [PATCH v6 06/37] ppc/xive: add support for the END Event State buffers |
Date: |
Thu, 6 Dec 2018 07:30:34 +0100 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.3.0 |
On 12/6/18 5:09 AM, David Gibson wrote:
> On Thu, Dec 06, 2018 at 12:22:20AM +0100, Cédric Le Goater wrote:
>> The Event Notification Descriptor (END) XIVE structure also contains
>> two Event State Buffers providing further coalescing of interrupts,
>> one for the notification event (ESn) and one for the escalation events
>> (ESe). A MMIO page is assigned for each to control the EOI through
>> loads only. Stores are not allowed.
>>
>> The END ESBs are modeled through an object resembling the 'XiveSource'
>> It is stateless as the END state bits are backed into the XiveEND
>> structure under the XiveRouter and the MMIO accesses follow the same
>> rules as for the standard source ESBs.
>>
>> END ESBs are not supported by the Linux drivers neither on OPAL nor on
>> sPAPR. Nevetherless, it provides a mean to study the question in the
>> future and validates a bit more the XIVE model.
>>
>> Signed-off-by: Cédric Le Goater <address@hidden>
>> ---
>> include/hw/ppc/xive.h | 22 ++++++
>> hw/intc/xive.c | 173 +++++++++++++++++++++++++++++++++++++++++-
>> 2 files changed, 193 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
>> index d1b4c6c78ec5..d67b0785df7c 100644
>> --- a/include/hw/ppc/xive.h
>> +++ b/include/hw/ppc/xive.h
>> @@ -305,6 +305,8 @@ static inline void xive_source_irq_set(XiveSource *xsrc,
>> uint32_t srcno,
>>
>> typedef struct XiveRouter {
>> SysBusDevice parent;
>> +
>> + uint32_t chip_id;
>
> I still don't think you need this..
I know :)
>
>> } XiveRouter;
>>
>> #define TYPE_XIVE_ROUTER "xive-router"
>> @@ -336,6 +338,26 @@ int xive_router_get_end(XiveRouter *xrtr, uint8_t
>> end_blk, uint32_t end_idx,
>> int xive_router_write_end(XiveRouter *xrtr, uint8_t end_blk, uint32_t
>> end_idx,
>> XiveEND *end, uint8_t word_number);
>>
>> +/*
>> + * XIVE END ESBs
>> + */
>> +
>> +#define TYPE_XIVE_END_SOURCE "xive-end-source"
>> +#define XIVE_END_SOURCE(obj) \
>> + OBJECT_CHECK(XiveENDSource, (obj), TYPE_XIVE_END_SOURCE)
>> +
>> +typedef struct XiveENDSource {
>> + DeviceState parent;
>> +
>> + uint32_t nr_ends;
>> +
>> + /* ESB memory region */
>> + uint32_t esb_shift;
>> + MemoryRegion esb_mmio;
>> +
>> + XiveRouter *xrtr;
>
> ..or this..
>
>> +} XiveENDSource;
>> +
>> /*
>> * For legacy compatibility, the exceptions define up to 256 different
>> * priorities. P9 implements only 9 levels : 8 active levels [0 - 7]
>> diff --git a/hw/intc/xive.c b/hw/intc/xive.c
>> index 41d8ba1540d0..83686e260df5 100644
>> --- a/hw/intc/xive.c
>> +++ b/hw/intc/xive.c
>> @@ -612,8 +612,18 @@ static void xive_router_end_notify(XiveRouter *xrtr,
>> uint8_t end_blk,
>> * even futher coalescing in the Router
>> */
>> if (!xive_end_is_notify(&end)) {
>> - qemu_log_mask(LOG_UNIMP, "XIVE: !UCOND_NOTIFY not implemented\n");
>> - return;
>> + uint8_t pq = GETFIELD_BE32(END_W1_ESn, end.w1);
>> + bool notify = xive_esb_trigger(&pq);
>> +
>> + if (pq != GETFIELD_BE32(END_W1_ESn, end.w1)) {
>> + end.w1 = SETFIELD_BE32(END_W1_ESn, end.w1, pq);
>> + xive_router_write_end(xrtr, end_blk, end_idx, &end, 1);
>> + }
>> +
>> + /* ESn[Q]=1 : end of notification */
>> + if (!notify) {
>> + return;
>> + }
>> }
>>
>> /*
>> @@ -658,12 +668,18 @@ static void xive_router_notify(XiveNotifier *xn,
>> uint32_t lisn)
>> GETFIELD_BE64(EAS_END_DATA, eas.w));
>> }
>>
>> +static Property xive_router_properties[] = {
>> + DEFINE_PROP_UINT32("chip-id", XiveRouter, chip_id, 0),
>> + DEFINE_PROP_END_OF_LIST(),
>> +};
>> +
>> static void xive_router_class_init(ObjectClass *klass, void *data)
>> {
>> DeviceClass *dc = DEVICE_CLASS(klass);
>> XiveNotifierClass *xnc = XIVE_NOTIFIER_CLASS(klass);
>>
>> dc->desc = "XIVE Router Engine";
>> + dc->props = xive_router_properties;
>> xnc->notify = xive_router_notify;
>> }
>>
>> @@ -692,6 +708,158 @@ void xive_eas_pic_print_info(XiveEAS *eas, uint32_t
>> lisn, Monitor *mon)
>> (uint32_t) GETFIELD_BE64(EAS_END_DATA, eas->w));
>> }
>>
>> +/*
>> + * END ESB MMIO loads
>> + */
>> +static uint64_t xive_end_source_read(void *opaque, hwaddr addr, unsigned
>> size)
>> +{
>> + XiveENDSource *xsrc = XIVE_END_SOURCE(opaque);
>> + XiveRouter *xrtr = xsrc->xrtr;
>> + uint32_t offset = addr & 0xFFF;
>> + uint8_t end_blk;
>> + uint32_t end_idx;
>> + XiveEND end;
>> + uint32_t end_esmask;
>> + uint8_t pq;
>> + uint64_t ret = -1;
>> +
>> + end_blk = xrtr->chip_id;
>
> .. instead I think it makes more sense to just configure the end_blk
> directly on the end_source, rather than reaching into another object
> to
Ah. That's what I was asking in an email. I missed the answer maybe.
Let's drop it and sPAPRXive block will be 0.
>
>> + end_idx = addr >> (xsrc->esb_shift + 1);
>> +
>> + if (xive_router_get_end(xrtr, end_blk, end_idx, &end)) {
>> + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: No END %x/%x\n", end_blk,
>> + end_idx);
>> + return -1;
>> + }
>> +
>> + if (!xive_end_is_valid(&end)) {
>> + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: END %x/%x is invalid\n",
>> + end_blk, end_idx);
>> + return -1;
>> + }
>> +
>> + end_esmask = addr_is_even(addr, xsrc->esb_shift) ? END_W1_ESn :
>> END_W1_ESe;
>> + pq = GETFIELD_BE32(end_esmask, end.w1);
>> +
>> + switch (offset) {
>> + case XIVE_ESB_LOAD_EOI ... XIVE_ESB_LOAD_EOI + 0x7FF:
>> + ret = xive_esb_eoi(&pq);
>> +
>> + /* Forward the source event notification for routing ?? */
>> + break;
>> +
>> + case XIVE_ESB_GET ... XIVE_ESB_GET + 0x3FF:
>> + ret = pq;
>> + break;
>> +
>> + case XIVE_ESB_SET_PQ_00 ... XIVE_ESB_SET_PQ_00 + 0x0FF:
>> + case XIVE_ESB_SET_PQ_01 ... XIVE_ESB_SET_PQ_01 + 0x0FF:
>> + case XIVE_ESB_SET_PQ_10 ... XIVE_ESB_SET_PQ_10 + 0x0FF:
>> + case XIVE_ESB_SET_PQ_11 ... XIVE_ESB_SET_PQ_11 + 0x0FF:
>> + ret = xive_esb_set(&pq, (offset >> 8) & 0x3);
>> + break;
>> + default:
>> + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid END ESB load addr
>> %d\n",
>> + offset);
>> + return -1;
>> + }
>> +
>> + if (pq != GETFIELD_BE32(end_esmask, end.w1)) {
>> + end.w1 = SETFIELD_BE32(end_esmask, end.w1, pq);
>> + xive_router_write_end(xrtr, end_blk, end_idx, &end, 1);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +/*
>> + * END ESB MMIO stores are invalid
>> + */
>> +static void xive_end_source_write(void *opaque, hwaddr addr,
>> + uint64_t value, unsigned size)
>> +{
>> + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid ESB write addr 0x%"
>> + HWADDR_PRIx"\n", addr);
>> +}
>> +
>> +static const MemoryRegionOps xive_end_source_ops = {
>> + .read = xive_end_source_read,
>> + .write = xive_end_source_write,
>> + .endianness = DEVICE_BIG_ENDIAN,
>> + .valid = {
>> + .min_access_size = 8,
>> + .max_access_size = 8,
>> + },
>> + .impl = {
>> + .min_access_size = 8,
>> + .max_access_size = 8,
>> + },
>> +};
>> +
>> +static void xive_source_end_reset(void *dev)
>> +{
>> + /* TODO: Loop on all ENDs and mask off the ESn and ESe */
>
> IIUC you're talking about actually writing the (potentially in memory)
> END structures. I don't think that makes sense for the END source
> hardware model. I'm guessing you want this for PAPR, where the ENDs
> are in virtual hardware
That's done already.
> rather than guest memory, but in that case I
> think the reset handling should be in the PAPR specific Xive object,
> not the end_source itself.
I will remove the TODO, it's obsolete.
Thanks,
C.
>
>> +}
>> +
>> +static void xive_end_source_realize(DeviceState *dev, Error **errp)
>> +{
>> + XiveENDSource *xsrc = XIVE_END_SOURCE(dev);
>> + Object *obj;
>> + Error *local_err = NULL;
>> +
>> + obj = object_property_get_link(OBJECT(dev), "xive", &local_err);
>> + if (!obj) {
>> + error_propagate(errp, local_err);
>> + error_prepend(errp, "required link 'xive' not found: ");
>> + return;
>> + }
>> +
>> + xsrc->xrtr = XIVE_ROUTER(obj);
>> +
>> + if (!xsrc->nr_ends) {
>> + error_setg(errp, "Number of interrupt needs to be greater than 0");
>> + return;
>> + }
>> +
>> + if (xsrc->esb_shift != XIVE_ESB_4K &&
>> + xsrc->esb_shift != XIVE_ESB_64K) {
>> + error_setg(errp, "Invalid ESB shift setting");
>> + return;
>> + }
>> +
>> + /*
>> + * Each END is assigned an even/odd pair of MMIO pages, the even page
>> + * manages the ESn field while the odd page manages the ESe field.
>> + */
>> + memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc),
>> + &xive_end_source_ops, xsrc, "xive.end",
>> + (1ull << (xsrc->esb_shift + 1)) * xsrc->nr_ends);
>> +
>> + qemu_register_reset(xive_source_end_reset, dev);
>> +}
>> +
>> +static Property xive_end_source_properties[] = {
>> + DEFINE_PROP_UINT32("nr-ends", XiveENDSource, nr_ends, 0),
>> + DEFINE_PROP_UINT32("shift", XiveENDSource, esb_shift, XIVE_ESB_64K),
>> + DEFINE_PROP_END_OF_LIST(),
>> +};
>> +
>> +static void xive_end_source_class_init(ObjectClass *klass, void *data)
>> +{
>> + DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> + dc->desc = "XIVE END Source";
>> + dc->props = xive_end_source_properties;
>> + dc->realize = xive_end_source_realize;
>> +}
>> +
>> +static const TypeInfo xive_end_source_info = {
>> + .name = TYPE_XIVE_END_SOURCE,
>> + .parent = TYPE_DEVICE,
>> + .instance_size = sizeof(XiveENDSource),
>> + .class_init = xive_end_source_class_init,
>> +};
>> +
>> /*
>> * XIVE Fabric
>> */
>> @@ -706,6 +874,7 @@ static void xive_register_types(void)
>> type_register_static(&xive_source_info);
>> type_register_static(&xive_fabric_info);
>> type_register_static(&xive_router_info);
>> + type_register_static(&xive_end_source_info);
>> }
>>
>> type_init(xive_register_types)
>
- [Qemu-ppc] [PATCH v6 04/37] ppc/xive: introduce the XiveRouter model, (continued)
- [Qemu-ppc] [PATCH v6 04/37] ppc/xive: introduce the XiveRouter model, Cédric Le Goater, 2018/12/05
- [Qemu-ppc] [PATCH v6 05/37] ppc/xive: introduce the XIVE Event Notification Descriptors, Cédric Le Goater, 2018/12/05
- [Qemu-ppc] [PATCH v6 06/37] ppc/xive: add support for the END Event State buffers, Cédric Le Goater, 2018/12/05
- [Qemu-ppc] [PATCH v6 07/37] ppc/xive: introduce the XIVE interrupt thread context, Cédric Le Goater, 2018/12/05
- [Qemu-ppc] [PATCH v6 08/37] ppc/xive: introduce a simplified XIVE presenter, Cédric Le Goater, 2018/12/05
- [Qemu-ppc] [PATCH v6 09/37] ppc/xive: notify the CPU when the interrupt priority is more privileged, Cédric Le Goater, 2018/12/05