From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37135) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gQ6iI-0002rY-St for qemu-devel@nongnu.org; Fri, 23 Nov 2018 03:21:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gQ6iF-0007Yp-60 for qemu-devel@nongnu.org; Fri, 23 Nov 2018 03:21:22 -0500 Received: from 4.mo1.mail-out.ovh.net ([46.105.76.26]:53771) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gQ6iE-0007Rf-NH for qemu-devel@nongnu.org; Fri, 23 Nov 2018 03:21:19 -0500 Received: from player776.ha.ovh.net (unknown [10.109.159.68]) by mo1.mail-out.ovh.net (Postfix) with ESMTP id BA2AC1464BE for ; Fri, 23 Nov 2018 09:21:14 +0100 (CET) References: <20181116105729.23240-1-clg@kaod.org> <20181116105729.23240-2-clg@kaod.org> <20181122030516.GB10448@umbus.fritz.box> <658dc2ad-e862-4777-9ed5-1ba82a074aa6@kaod.org> <20181123003115.GR10448@umbus.fritz.box> From: =?UTF-8?Q?C=c3=a9dric_Le_Goater?= Message-ID: Date: Fri, 23 Nov 2018 09:21:08 +0100 MIME-Version: 1.0 In-Reply-To: <20181123003115.GR10448@umbus.fritz.box> Content-Type: text/plain; charset=windows-1252 Content-Language: en-US Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH v5 01/36] ppc/xive: introduce a XIVE interrupt source model List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: David Gibson Cc: qemu-ppc@nongnu.org, qemu-devel@nongnu.org, Benjamin Herrenschmidt On 11/23/18 1:31 AM, David Gibson wrote: > On Thu, Nov 22, 2018 at 08:25:06AM +0100, C=E9dric Le Goater wrote: >> On 11/22/18 4:05 AM, David Gibson wrote: >>> On Fri, Nov 16, 2018 at 11:56:54AM +0100, C=E9dric Le Goater wrote: >>>> The first sub-engine of the overall XIVE architecture is the Interru= pt >>>> Virtualization Source Engine (IVSE). An IVSE can be integrated into >>>> another logic, like in a PCI PHB or in the main interrupt controller >>>> to manage IPIs. >>>> >>>> Each IVSE instance is associated with an Event State Buffer (ESB) th= at >>>> contains a two bit state entry for each possible event source. When = an >>>> event is signaled to the IVSE, by MMIO or some other means, the >>>> associated interrupt state bits are fetched from the ESB and >>>> modified. Depending on the resulting ESB state, the event is forward= ed >>>> to the IVRE sub-engine of the controller doing the routing. >>>> >>>> Each supported ESB entry is associated with either a single or a >>>> even/odd pair of pages which provides commands to manage the source: >>>> to EOI, to turn off the source for instance. >>>> >>>> On a sPAPR machine, the O/S will obtain the page address of the ESB >>>> entry associated with a source and its characteristic using the >>>> H_INT_GET_SOURCE_INFO hcall. On PowerNV, a similar OPAL call is used= . >>>> >>>> The xive_source_notify() routine is in charge forwarding the source >>>> event notification to the routing engine. It will be filled later on= . >>>> >>>> Signed-off-by: C=E9dric Le Goater >>> >>> Ok, this is looking basically pretty good. Few details to query >>> below. >>> >>> >>>> --- >>>> default-configs/ppc64-softmmu.mak | 1 + >>>> include/hw/ppc/xive.h | 130 ++++++++++ >>>> hw/intc/xive.c | 379 +++++++++++++++++++++++++++= +++ >>>> hw/intc/Makefile.objs | 1 + >>>> 4 files changed, 511 insertions(+) >>>> create mode 100644 include/hw/ppc/xive.h >>>> create mode 100644 hw/intc/xive.c >>>> >>>> diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc= 64-softmmu.mak >>>> index aec2855750d6..2d1e7c5c4668 100644 >>>> --- a/default-configs/ppc64-softmmu.mak >>>> +++ b/default-configs/ppc64-softmmu.mak >>>> @@ -16,6 +16,7 @@ CONFIG_VIRTIO_VGA=3Dy >>>> CONFIG_XICS=3D$(CONFIG_PSERIES) >>>> CONFIG_XICS_SPAPR=3D$(CONFIG_PSERIES) >>>> CONFIG_XICS_KVM=3D$(call land,$(CONFIG_PSERIES),$(CONFIG_KVM)) >>>> +CONFIG_XIVE=3D$(CONFIG_PSERIES) >>>> CONFIG_MEM_DEVICE=3Dy >>>> CONFIG_DIMM=3Dy >>>> CONFIG_SPAPR_RNG=3Dy >>>> diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h >>>> new file mode 100644 >>>> index 000000000000..5fec4b08705d >>>> --- /dev/null >>>> +++ b/include/hw/ppc/xive.h >>>> @@ -0,0 +1,130 @@ >>>> +/* >>>> + * QEMU PowerPC XIVE interrupt controller model >>>> + * >>>> + * Copyright (c) 2017-2018, IBM Corporation. >>>> + * >>>> + * This code is licensed under the GPL version 2 or later. See the >>>> + * COPYING file in the top-level directory. >>> >>> A cheat sheet in the top of this header with the old and new XIVE >>> terms would quite nice to have. >> >> Yes. It's a good place. I will put the XIVE acronyms here : >> =20 >> EA Event Assignment >> EISN Effective Interrupt Source Number >> END Event Notification Descriptor >> ESB Event State Buffer >> EQ Event Queue >> LISN Logical Interrupt Source Number >> NVT Notification Virtual Target >> TIMA Thread Interrupt Management Area >> ... >=20 > That sounds good, but what I'd also like is showing that NVT =3D=3D VP = and > EAS =3D=3D IVT and so forth. sure. I will add that.=20 skiboot and PowerNV Linux are using a mixed version and I wonder if I=20 should not clarify that also, skiboot at least.=20 >>>> + */ >>>> + >>>> +#ifndef PPC_XIVE_H >>>> +#define PPC_XIVE_H >>>> + >>>> +#include "hw/sysbus.h" >>> >>> So, I'm a bit dubious about making the XiveSource a SysBus device - >>> I'm concerned it won't play well with tying it into the other devices >>> like PHB that "own" it in real hardware. >> >> It does but I can take a look at changing it to a DeviceState. The=20 >> reset handlers might be a concern. >=20 > As "non bus" device I think you'd need to register your own reset > handler rather than just setting dc->reset. Otherwise, I think that > should work. yes. I will give a look/try, it might not be such a problem.=20 >>> I think we'd be better off making it a direct descendent of >>> TYPE_DEVICE which constructs the MMIO region, but doesn't map it. >> >> At a moment, I started working on a XiveESB object doing what I think=20 >> you are suggesting and I removed it. I am reluctant adding more=20 >> complexity now, the patchset is just growing and growing ...=20 >> >> But I agree there are fundamentals to get right for KVM. Let's talk=20 >> about it after you have looked at the overall patchset, at least up=20 >> to KVM initial support. >=20 > Hm, ok. >=20 >>> Then we can havea SysBusDevice (and/or other) wrapper which >>> instantiates the XiveSource core and maps it into somewhere >>> accessible. >> >> The XIVE controller model does the mapping of the source currently. >=20 > I'm.. I'm not sure what you mean by that. We have a > sysbus_init_mmio() right here which effectively maps in the MMIO > region AFAICT. yes. what I meant is that the XIVE controller model does all the=20 mapping, for the TIMA and for the ESB pages of the XiveSource.=20 This is a 'critical' part of the XIVE model because the region have=20 a different nature under KVM, which requires the KVM device to be=20 created before the region are, and to be destroyed when the device is.=20 It took me a while to get all in place to support all aspects of=20 the model: KVM and not KVM, switch of interrupt controller, machine=20 reset, post_load, PowerNV devices, etc. So expect some resistant=20 from me on that topic.=20 Thanks, C. >> In the case of sPAPR, the controller model controls the TIMA and=20 >> for PowerNV, there are quite few others MMIO regions to handle. >> >>> >>>> + >>>> +/* >>>> + * XIVE Interrupt Source >>>> + */ >>>> + >>>> +#define TYPE_XIVE_SOURCE "xive-source" >>>> +#define XIVE_SOURCE(obj) OBJECT_CHECK(XiveSource, (obj), TYPE_XIVE_= SOURCE) >>>> + >>>> +/* >>>> + * XIVE Interrupt Source characteristics, which define how the ESB = are >>>> + * controlled. >>>> + */ >>>> +#define XIVE_SRC_H_INT_ESB 0x1 /* ESB managed with hcall H_INT_= ESB */ >>>> +#define XIVE_SRC_STORE_EOI 0x2 /* Store EOI supported */ >>>> + >>>> +typedef struct XiveSource { >>>> + SysBusDevice parent; >>>> + >>>> + /* IRQs */ >>>> + uint32_t nr_irqs; >>>> + qemu_irq *qirqs; >>>> + >>>> + /* PQ bits */ >>>> + uint8_t *status; >>>> + >>>> + /* ESB memory region */ >>>> + uint64_t esb_flags; >>>> + uint32_t esb_shift; >>>> + MemoryRegion esb_mmio; >>>> +} XiveSource; >>>> + >>>> +/* >>>> + * ESB MMIO setting. Can be one page, for both source triggering an= d >>>> + * source management, or two different pages. See below for magic >>>> + * values. >>>> + */ >>>> +#define XIVE_ESB_4K 12 /* PSI HB only */ >>>> +#define XIVE_ESB_4K_2PAGE 13 >>>> +#define XIVE_ESB_64K 16 >>>> +#define XIVE_ESB_64K_2PAGE 17 >>>> + >>>> +static inline bool xive_source_esb_has_2page(XiveSource *xsrc) >>>> +{ >>>> + return xsrc->esb_shift =3D=3D XIVE_ESB_64K_2PAGE || >>>> + xsrc->esb_shift =3D=3D XIVE_ESB_4K_2PAGE; >>>> +} >>>> + >>>> +/* The trigger page is always the first/even page */ >>>> +static inline hwaddr xive_source_esb_page(XiveSource *xsrc, uint32_= t srcno) >>> >>> This function doesn't appear to be used anywhere except.. >> >> It's used in patch 16 adding the hcalls also. >> >>>> +{ >>>> + assert(srcno < xsrc->nr_irqs); >>>> + return (1ull << xsrc->esb_shift) * srcno; >>>> +} >>>> + >>>> +/* In a two pages ESB MMIO setting, the odd page is for management = */ >>>> +static inline hwaddr xive_source_esb_mgmt(XiveSource *xsrc, int src= no) >>> >>> >>> ..here, and this function doesn't appear to be used anywhere. >> >> It's used in patch 16 adding the hcalls and patch 23 for KVM. >> >> This is basic ESB support which I thought belong to the patch on sourc= es. >> =20 >>> >>>> +{ >>>> + hwaddr addr =3D xive_source_esb_page(xsrc, srcno); >>>> + >>>> + if (xive_source_esb_has_2page(xsrc)) { >>>> + addr +=3D (1 << (xsrc->esb_shift - 1)); >>>> + } >>>> + >>>> + return addr; >>>> +} >>>> + >>>> +/* >>>> + * Each interrupt source has a 2-bit state machine which can be >>>> + * controlled by MMIO. P indicates that an interrupt is pending (ha= s >>>> + * been sent to a queue and is waiting for an EOI). Q indicates tha= t >>>> + * the interrupt has been triggered while pending. >>>> + * >>>> + * This acts as a coalescing mechanism in order to guarantee that a >>>> + * given interrupt only occurs at most once in a queue. >>>> + * >>>> + * When doing an EOI, the Q bit will indicate if the interrupt >>>> + * needs to be re-triggered. >>>> + */ >>>> +#define XIVE_ESB_VAL_P 0x2 >>>> +#define XIVE_ESB_VAL_Q 0x1 >>>> + >>>> +#define XIVE_ESB_RESET 0x0 >>>> +#define XIVE_ESB_PENDING XIVE_ESB_VAL_P >>>> +#define XIVE_ESB_QUEUED (XIVE_ESB_VAL_P | XIVE_ESB_VAL_Q) >>>> +#define XIVE_ESB_OFF XIVE_ESB_VAL_Q >>>> + >>>> +/* >>>> + * "magic" Event State Buffer (ESB) MMIO offsets. >>>> + * >>>> + * The following offsets into the ESB MMIO allow to read or manipul= ate >>>> + * the PQ bits. They must be used with an 8-byte load instruction. >>>> + * They all return the previous state of the interrupt (atomically)= . >>>> + * >>>> + * Additionally, some ESB pages support doing an EOI via a store an= d >>>> + * some ESBs support doing a trigger via a separate trigger page. >>>> + */ >>>> +#define XIVE_ESB_STORE_EOI 0x400 /* Store */ >>>> +#define XIVE_ESB_LOAD_EOI 0x000 /* Load */ >>>> +#define XIVE_ESB_GET 0x800 /* Load */ >>>> +#define XIVE_ESB_SET_PQ_00 0xc00 /* Load */ >>>> +#define XIVE_ESB_SET_PQ_01 0xd00 /* Load */ >>>> +#define XIVE_ESB_SET_PQ_10 0xe00 /* Load */ >>>> +#define XIVE_ESB_SET_PQ_11 0xf00 /* Load */ >>>> + >>>> +uint8_t xive_source_esb_get(XiveSource *xsrc, uint32_t srcno); >>>> +uint8_t xive_source_esb_set(XiveSource *xsrc, uint32_t srcno, uint8= _t pq); >>>> + >>>> +void xive_source_pic_print_info(XiveSource *xsrc, uint32_t offset, >>>> + Monitor *mon); >>>> + >>>> +static inline qemu_irq xive_source_qirq(XiveSource *xsrc, uint32_t = srcno) >>>> +{ >>>> + assert(srcno < xsrc->nr_irqs); >>>> + return xsrc->qirqs[srcno]; >>>> +} >>>> + >>>> +#endif /* PPC_XIVE_H */ >>>> diff --git a/hw/intc/xive.c b/hw/intc/xive.c >>>> new file mode 100644 >>>> index 000000000000..f7621f84828c >>>> --- /dev/null >>>> +++ b/hw/intc/xive.c >>>> @@ -0,0 +1,379 @@ >>>> +/* >>>> + * QEMU PowerPC XIVE interrupt controller model >>>> + * >>>> + * Copyright (c) 2017-2018, IBM Corporation. >>>> + * >>>> + * This code is licensed under the GPL version 2 or later. See the >>>> + * COPYING file in the top-level directory. >>>> + */ >>>> + >>>> +#include "qemu/osdep.h" >>>> +#include "qemu/log.h" >>>> +#include "qapi/error.h" >>>> +#include "target/ppc/cpu.h" >>>> +#include "sysemu/cpus.h" >>>> +#include "sysemu/dma.h" >>>> +#include "monitor/monitor.h" >>>> +#include "hw/ppc/xive.h" >>>> + >>>> +/* >>>> + * XIVE ESB helpers >>>> + */ >>>> + >>>> +static uint8_t xive_esb_set(uint8_t *pq, uint8_t value) >>>> +{ >>>> + uint8_t old_pq =3D *pq & 0x3; >>>> + >>>> + *pq &=3D ~0x3; >>>> + *pq |=3D value & 0x3; >>>> + >>>> + return old_pq; >>>> +} >>>> + >>>> +static bool xive_esb_trigger(uint8_t *pq) >>>> +{ >>>> + uint8_t old_pq =3D *pq & 0x3; >>>> + >>>> + switch (old_pq) { >>>> + case XIVE_ESB_RESET: >>>> + xive_esb_set(pq, XIVE_ESB_PENDING); >>>> + return true; >>>> + case XIVE_ESB_PENDING: >>>> + case XIVE_ESB_QUEUED: >>>> + xive_esb_set(pq, XIVE_ESB_QUEUED); >>>> + return false; >>>> + case XIVE_ESB_OFF: >>>> + xive_esb_set(pq, XIVE_ESB_OFF); >>>> + return false; >>>> + default: >>>> + g_assert_not_reached(); >>>> + } >>>> +} >>>> + >>>> +static bool xive_esb_eoi(uint8_t *pq) >>>> +{ >>>> + uint8_t old_pq =3D *pq & 0x3; >>>> + >>>> + switch (old_pq) { >>>> + case XIVE_ESB_RESET: >>>> + case XIVE_ESB_PENDING: >>>> + xive_esb_set(pq, XIVE_ESB_RESET); >>>> + return false; >>>> + case XIVE_ESB_QUEUED: >>>> + xive_esb_set(pq, XIVE_ESB_PENDING); >>>> + return true; >>>> + case XIVE_ESB_OFF: >>>> + xive_esb_set(pq, XIVE_ESB_OFF); >>>> + return false; >>>> + default: >>>> + g_assert_not_reached(); >>>> + } >>>> +} >>>> + >>>> +/* >>>> + * XIVE Interrupt Source (or IVSE) >>>> + */ >>>> + >>>> +uint8_t xive_source_esb_get(XiveSource *xsrc, uint32_t srcno) >>>> +{ >>>> + assert(srcno < xsrc->nr_irqs); >>>> + >>>> + return xsrc->status[srcno] & 0x3; >>>> +} >>>> + >>>> +uint8_t xive_source_esb_set(XiveSource *xsrc, uint32_t srcno, uint8= _t pq) >>>> +{ >>>> + assert(srcno < xsrc->nr_irqs); >>>> + >>>> + return xive_esb_set(&xsrc->status[srcno], pq); >>>> +} >>>> + >>>> +/* >>>> + * Returns whether the event notification should be forwarded. >>>> + */ >>>> +static bool xive_source_esb_trigger(XiveSource *xsrc, uint32_t srcn= o) >>>> +{ >>>> + assert(srcno < xsrc->nr_irqs); >>>> + >>>> + return xive_esb_trigger(&xsrc->status[srcno]); >>>> +} >>>> + >>>> +/* >>>> + * Returns whether the event notification should be forwarded. >>>> + */ >>>> +static bool xive_source_esb_eoi(XiveSource *xsrc, uint32_t srcno) >>>> +{ >>>> + assert(srcno < xsrc->nr_irqs); >>>> + >>>> + return xive_esb_eoi(&xsrc->status[srcno]); >>>> +} >>>> + >>>> +/* >>>> + * Forward the source event notification to the Router >>>> + */ >>>> +static void xive_source_notify(XiveSource *xsrc, int srcno) >>>> +{ >>>> + >>>> +} >>>> + >>>> +/* >>>> + * In a two pages ESB MMIO setting, even page is the trigger page, = odd >>>> + * page is for management >>>> + */ >>>> +static inline bool addr_is_even(hwaddr addr, uint32_t shift) >>>> +{ >>>> + return !((addr >> shift) & 1); >>>> +} >>>> + >>>> +static inline bool xive_source_is_trigger_page(XiveSource *xsrc, hw= addr addr) >>>> +{ >>>> + return xive_source_esb_has_2page(xsrc) && >>>> + addr_is_even(addr, xsrc->esb_shift - 1); >>>> +} >>>> + >>>> +/* >>>> + * ESB MMIO loads >>>> + * Trigger page Management/EOI page >>>> + * 2 pages setting even odd >>>> + * >>>> + * 0x000 .. 0x3FF -1 EOI and return 0|1 >>>> + * 0x400 .. 0x7FF -1 EOI and return 0|1 >>>> + * 0x800 .. 0xBFF -1 return PQ >>>> + * 0xC00 .. 0xCFF -1 return PQ and atomically PQ= =3D0 >>>> + * 0xD00 .. 0xDFF -1 return PQ and atomically PQ= =3D0 >>>> + * 0xE00 .. 0xDFF -1 return PQ and atomically PQ= =3D1 >>>> + * 0xF00 .. 0xDFF -1 return PQ and atomically PQ= =3D1 >>>> + */ >>> >>> I can't quite make sense of this table. What do the -1s represent, >> >> the value returned by the load. >> >>> and how does it relate to the non-2page case? >> >> one page ESB support trigger and management on the same page. So for l= oads, >> the odd page behavior applies. =20 >> >>>> +static uint64_t xive_source_esb_read(void *opaque, hwaddr addr, uns= igned size) >>>> +{ >>>> + XiveSource *xsrc =3D XIVE_SOURCE(opaque); >>>> + uint32_t offset =3D addr & 0xFFF; >>>> + uint32_t srcno =3D addr >> xsrc->esb_shift; >>>> + uint64_t ret =3D -1; >>>> + >>>> + /* In a two pages ESB MMIO setting, trigger page should not be = read */ >>>> + if (xive_source_is_trigger_page(xsrc, addr)) { >>>> + qemu_log_mask(LOG_GUEST_ERROR, >>>> + "XIVE: invalid load on IRQ %d trigger page at= " >>>> + "0x%"HWADDR_PRIx"\n", srcno, addr); >>>> + return -1; >>>> + } >>>> + >>>> + switch (offset) { >>>> + case XIVE_ESB_LOAD_EOI ... XIVE_ESB_LOAD_EOI + 0x7FF: >>>> + ret =3D xive_source_esb_eoi(xsrc, srcno); >>>> + >>>> + /* Forward the source event notification for routing */ >>>> + if (ret) { >>>> + xive_source_notify(xsrc, srcno); >>>> + } >>>> + break; >>>> + >>>> + case XIVE_ESB_GET ... XIVE_ESB_GET + 0x3FF: >>>> + ret =3D xive_source_esb_get(xsrc, srcno); >>>> + 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 =3D xive_source_esb_set(xsrc, srcno, (offset >> 8) & 0x= 3); >>>> + break; >>>> + default: >>>> + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid ESB load addr= %x\n", >>>> + offset); >>>> + } >>>> + >>>> + return ret; >>>> +} >>>> + >>>> +/* >>>> + * ESB MMIO stores >>>> + * Trigger page Management/EOI page >>>> + * 2 pages setting even odd >>> >>> As with the previous table, I don't quite understand what the heading= s >>> above mean. >> >> one page ESB support trigger and management on the same page. So for s= tores, >> the odd page behavior applies. >> >> The headings can be improved. I will think of something. >> >>>> + * 0x000 .. 0x3FF Trigger Trigger >>>> + * 0x400 .. 0x7FF Trigger EOI >>>> + * 0x800 .. 0xBFF Trigger undefined >>>> + * 0xC00 .. 0xCFF Trigger PQ=3D00 >>>> + * 0xD00 .. 0xDFF Trigger PQ=3D01 >>>> + * 0xE00 .. 0xDFF Trigger PQ=3D10 >>>> + * 0xF00 .. 0xDFF Trigger PQ=3D11 >>>> + */ >>>> +static void xive_source_esb_write(void *opaque, hwaddr addr, >>>> + uint64_t value, unsigned size) >>>> +{ >>>> + XiveSource *xsrc =3D XIVE_SOURCE(opaque); >>>> + uint32_t offset =3D addr & 0xFFF; >>>> + uint32_t srcno =3D addr >> xsrc->esb_shift; >>>> + bool notify =3D false; >>>> + >>>> + /* In a two pages ESB MMIO setting, trigger page only triggers = */ >>>> + if (xive_source_is_trigger_page(xsrc, addr)) { >>>> + notify =3D xive_source_esb_trigger(xsrc, srcno); >>>> + goto out; >>>> + } >>>> + >>>> + switch (offset) { >>>> + case 0 ... 0x3FF: >>>> + notify =3D xive_source_esb_trigger(xsrc, srcno); >>>> + break; >>>> + >>>> + case XIVE_ESB_STORE_EOI ... XIVE_ESB_STORE_EOI + 0x3FF: >>>> + if (!(xsrc->esb_flags & XIVE_SRC_STORE_EOI)) { >>>> + qemu_log_mask(LOG_GUEST_ERROR, >>>> + "XIVE: invalid Store EOI for IRQ %d\n", s= rcno); >>>> + return; >>>> + } >>>> + >>>> + notify =3D xive_source_esb_eoi(xsrc, srcno); >>>> + 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: >>>> + xive_source_esb_set(xsrc, srcno, (offset >> 8) & 0x3); >>>> + break; >>>> + >>>> + default: >>>> + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid ESB write add= r %x\n", >>>> + offset); >>>> + return; >>>> + } >>>> + >>>> +out: >>>> + /* Forward the source event notification for routing */ >>>> + if (notify) { >>>> + xive_source_notify(xsrc, srcno); >>>> + } >>>> +} >>>> + >>>> +static const MemoryRegionOps xive_source_esb_ops =3D { >>>> + .read =3D xive_source_esb_read, >>>> + .write =3D xive_source_esb_write, >>>> + .endianness =3D DEVICE_BIG_ENDIAN, >>>> + .valid =3D { >>>> + .min_access_size =3D 8, >>>> + .max_access_size =3D 8, >>>> + }, >>>> + .impl =3D { >>>> + .min_access_size =3D 8, >>>> + .max_access_size =3D 8, >>>> + }, >>>> +}; >>>> + >>>> +static void xive_source_set_irq(void *opaque, int srcno, int val) >>>> +{ >>>> + XiveSource *xsrc =3D XIVE_SOURCE(opaque); >>>> + bool notify =3D false; >>>> + >>>> + if (val) { >>>> + notify =3D xive_source_esb_trigger(xsrc, srcno); >>>> + } >>>> + >>>> + /* Forward the source event notification for routing */ >>>> + if (notify) { >>>> + xive_source_notify(xsrc, srcno); >>>> + } >>>> +} >>>> + >>>> +void xive_source_pic_print_info(XiveSource *xsrc, uint32_t offset, = Monitor *mon) >>>> +{ >>>> + int i; >>>> + >>>> + for (i =3D 0; i < xsrc->nr_irqs; i++) { >>>> + uint8_t pq =3D xive_source_esb_get(xsrc, i); >>>> + >>>> + if (pq =3D=3D XIVE_ESB_OFF) { >>>> + continue; >>>> + } >>>> + >>>> + monitor_printf(mon, " %08x %c%c\n", i + offset, >>>> + pq & XIVE_ESB_VAL_P ? 'P' : '-', >>>> + pq & XIVE_ESB_VAL_Q ? 'Q' : '-'); >>>> + } >>>> +} >>>> + >>>> +static void xive_source_reset(DeviceState *dev) >>>> +{ >>>> + XiveSource *xsrc =3D XIVE_SOURCE(dev); >>>> + >>>> + /* PQs are initialized to 0b01 which corresponds to "ints off" = */ >>>> + memset(xsrc->status, 0x1, xsrc->nr_irqs); >>> >>> You've already got XIVE_ESB_OFF defined to make this a little clearer= . >> >> Sure. >> >> Thanks, >> >> C.=20 >> >> >>> >>>> +} >>>> + >>>> +static void xive_source_realize(DeviceState *dev, Error **errp) >>>> +{ >>>> + XiveSource *xsrc =3D XIVE_SOURCE(dev); >>>> + >>>> + if (!xsrc->nr_irqs) { >>>> + error_setg(errp, "Number of interrupt needs to be greater t= han 0"); >>>> + return; >>>> + } >>>> + >>>> + if (xsrc->esb_shift !=3D XIVE_ESB_4K && >>>> + xsrc->esb_shift !=3D XIVE_ESB_4K_2PAGE && >>>> + xsrc->esb_shift !=3D XIVE_ESB_64K && >>>> + xsrc->esb_shift !=3D XIVE_ESB_64K_2PAGE) { >>>> + error_setg(errp, "Invalid ESB shift setting"); >>>> + return; >>>> + } >>>> + >>>> + xsrc->qirqs =3D qemu_allocate_irqs(xive_source_set_irq, xsrc, >>>> + xsrc->nr_irqs); >>>> + >>>> + xsrc->status =3D g_malloc0(xsrc->nr_irqs); >>>> + >>>> + memory_region_init_io(&xsrc->esb_mmio, OBJECT(xsrc), >>>> + &xive_source_esb_ops, xsrc, "xive.esb", >>>> + (1ull << xsrc->esb_shift) * xsrc->nr_irqs= ); >>>> + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &xsrc->esb_mmio); >>>> +} >>>> + >>>> +static const VMStateDescription vmstate_xive_source =3D { >>>> + .name =3D TYPE_XIVE_SOURCE, >>>> + .version_id =3D 1, >>>> + .minimum_version_id =3D 1, >>>> + .fields =3D (VMStateField[]) { >>>> + VMSTATE_UINT32_EQUAL(nr_irqs, XiveSource, NULL), >>>> + VMSTATE_VBUFFER_UINT32(status, XiveSource, 1, NULL, nr_irqs= ), >>>> + VMSTATE_END_OF_LIST() >>>> + }, >>>> +}; >>>> + >>>> +/* >>>> + * The default XIVE interrupt source setting for the ESB MMIOs is t= wo >>>> + * 64k pages without Store EOI, to be in sync with KVM. >>>> + */ >>>> +static Property xive_source_properties[] =3D { >>>> + DEFINE_PROP_UINT64("flags", XiveSource, esb_flags, 0), >>>> + DEFINE_PROP_UINT32("nr-irqs", XiveSource, nr_irqs, 0), >>>> + DEFINE_PROP_UINT32("shift", XiveSource, esb_shift, XIVE_ESB_64K= _2PAGE), >>>> + DEFINE_PROP_END_OF_LIST(), >>>> +}; >>>> + >>>> +static void xive_source_class_init(ObjectClass *klass, void *data) >>>> +{ >>>> + DeviceClass *dc =3D DEVICE_CLASS(klass); >>>> + >>>> + dc->desc =3D "XIVE Interrupt Source"; >>>> + dc->props =3D xive_source_properties; >>>> + dc->realize =3D xive_source_realize; >>>> + dc->reset =3D xive_source_reset; >>>> + dc->vmsd =3D &vmstate_xive_source; >>>> +} >>>> + >>>> +static const TypeInfo xive_source_info =3D { >>>> + .name =3D TYPE_XIVE_SOURCE, >>>> + .parent =3D TYPE_SYS_BUS_DEVICE, >>>> + .instance_size =3D sizeof(XiveSource), >>>> + .class_init =3D xive_source_class_init, >>>> +}; >>>> + >>>> +static void xive_register_types(void) >>>> +{ >>>> + type_register_static(&xive_source_info); >>>> +} >>>> + >>>> +type_init(xive_register_types) >>>> diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs >>>> index 0e9963f5eecc..72a46ed91c31 100644 >>>> --- a/hw/intc/Makefile.objs >>>> +++ b/hw/intc/Makefile.objs >>>> @@ -37,6 +37,7 @@ obj-$(CONFIG_SH4) +=3D sh_intc.o >>>> obj-$(CONFIG_XICS) +=3D xics.o >>>> obj-$(CONFIG_XICS_SPAPR) +=3D xics_spapr.o >>>> obj-$(CONFIG_XICS_KVM) +=3D xics_kvm.o >>>> +obj-$(CONFIG_XIVE) +=3D xive.o >>>> obj-$(CONFIG_POWERNV) +=3D xics_pnv.o >>>> obj-$(CONFIG_ALLWINNER_A10_PIC) +=3D allwinner-a10-pic.o >>>> obj-$(CONFIG_S390_FLIC) +=3D s390_flic.o >>> >> >=20