[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [RFC PATCH 14/26] ppc/xive: add MMIO handlers to the XI
From: |
Cédric Le Goater |
Subject: |
Re: [Qemu-devel] [RFC PATCH 14/26] ppc/xive: add MMIO handlers to the XIVE interrupt presenter model |
Date: |
Mon, 24 Jul 2017 16:44:00 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 |
On 07/24/2017 08:35 AM, David Gibson wrote:
> On Wed, Jul 05, 2017 at 07:13:27PM +0200, Cédric Le Goater wrote:
>> The Thread Interrupt Management Area for the OS is mostly used to
>> acknowledge interrupts and set the CPPR of the CPU.
>>
>> The TIMA is mapped at the same address for each CPU. 'current_cpu' is
>> used to retrieve the targeted interrupt presenter object.
>>
>> Signed-off-by: Cédric Le Goater <address@hidden>
>
> Am I right in thinking that this shoehorns the XIVE TIMA state into
> the existing XICS ICP object. That.. doesn't seem like a good idea.
The TIMA memory region is under the XIVE object because it is
unique for the system. The lookup of the ICP is simply done using
'current_cpu'. The TIMA state is under the ICPState, yes, but this
model does not seem incorrect to me as this state contains the
interrupt information presented to a CPU.
Thanks,
C.
>> ---
>> hw/intc/xive-internal.h | 4 ++
>> hw/intc/xive.c | 187
>> ++++++++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 191 insertions(+)
>>
>> diff --git a/hw/intc/xive-internal.h b/hw/intc/xive-internal.h
>> index ba5e648a5258..5e8b78a1ea6a 100644
>> --- a/hw/intc/xive-internal.h
>> +++ b/hw/intc/xive-internal.h
>> @@ -200,6 +200,10 @@ struct XIVE {
>> /* ESB and TIMA memory location */
>> hwaddr vc_base;
>> MemoryRegion esb_iomem;
>> +
>> + uint32_t tm_shift;
>> + hwaddr tm_base;
>> + MemoryRegion tm_iomem;
>> };
>>
>> void xive_reset(void *dev);
>> diff --git a/hw/intc/xive.c b/hw/intc/xive.c
>> index c08a4f8efb58..82b2f0dcda0b 100644
>> --- a/hw/intc/xive.c
>> +++ b/hw/intc/xive.c
>> @@ -26,6 +26,180 @@
>>
>> #include "xive-internal.h"
>>
>> +static uint8_t priority_to_ipb(uint8_t priority)
>> +{
>> + return priority < XIVE_EQ_PRIORITY_COUNT ? 1 << (7 - priority) : 0;
>> +}
>> +
>> +static uint64_t xive_icp_accept(XiveICPState *xicp)
>> +{
>> + ICPState *icp = ICP(xicp);
>> + uint8_t nsr = xicp->tima_os[TM_NSR];
>> +
>> + qemu_irq_lower(icp->output);
>> +
>> + if (xicp->tima_os[TM_NSR] & TM_QW1_NSR_EO) {
>> + uint8_t cppr = xicp->tima_os[TM_PIPR];
>> +
>> + xicp->tima_os[TM_CPPR] = cppr;
>> +
>> + /* Reset the pending buffer bit */
>> + xicp->tima_os[TM_IPB] &= ~priority_to_ipb(cppr);
>> +
>> + /* Drop Exception bit for OS */
>> + xicp->tima_os[TM_NSR] &= ~TM_QW1_NSR_EO;
>> + }
>> +
>> + return (nsr << 8) | xicp->tima_os[TM_CPPR];
>> +}
>> +
>> +static void xive_icp_set_cppr(XiveICPState *xicp, uint8_t cppr)
>> +{
>> + if (cppr > XIVE_PRIORITY_MAX) {
>> + cppr = 0xff;
>> + }
>> +
>> + xicp->tima_os[TM_CPPR] = cppr;
>> +}
>> +
>> +/*
>> + * Thread Interrupt Management Area MMIO
>> + */
>> +static uint64_t xive_tm_read_special(XiveICPState *icp, hwaddr offset,
>> + unsigned size)
>> +{
>> + uint64_t ret = -1;
>> +
>> + if (offset == TM_SPC_ACK_OS_REG && size == 2) {
>> + ret = xive_icp_accept(icp);
>> + } else {
>> + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid TIMA read @%"
>> + HWADDR_PRIx" size %d\n", offset, size);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static uint64_t xive_tm_read(void *opaque, hwaddr offset, unsigned size)
>> +{
>> + PowerPCCPU *cpu = POWERPC_CPU(current_cpu);
>> + XiveICPState *icp = XIVE_ICP(cpu->intc);
>> + uint64_t ret = -1;
>> + int i;
>> +
>> + if (offset >= TM_SPC_ACK_EBB) {
>> + return xive_tm_read_special(icp, offset, size);
>> + }
>> +
>> + if (offset & TM_QW1_OS) {
>> + switch (size) {
>> + case 1:
>> + case 2:
>> + case 4:
>> + case 8:
>> + if (QEMU_IS_ALIGNED(offset, size)) {
>> + ret = 0;
>> + for (i = 0; i < size; i++) {
>> + ret |= icp->tima[offset + i] << (8 * i);
>> + }
>> + } else {
>> + qemu_log_mask(LOG_GUEST_ERROR,
>> + "XIVE: invalid TIMA read alignment @%"
>> + HWADDR_PRIx" size %d\n", offset, size);
>> + }
>> + break;
>> + default:
>> + g_assert_not_reached();
>> + }
>> + } else {
>> + qemu_log_mask(LOG_UNIMP, "XIVE: does handle non-OS TIMA ring @%"
>> + HWADDR_PRIx"\n", offset);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static bool xive_tm_is_readonly(uint8_t index)
>> +{
>> + /* Let's be optimistic and prepare ground for HV mode support */
>> + switch (index) {
>> + case TM_QW1_OS + TM_CPPR:
>> + return false;
>> + default:
>> + return true;
>> + }
>> +}
>> +
>> +static void xive_tm_write_special(XiveICPState *xicp, hwaddr offset,
>> + uint64_t value, unsigned size)
>> +{
>> + if (offset == TM_SPC_SET_OS_PENDING && size == 1) {
>> + xicp->tima_os[TM_IPB] |= priority_to_ipb(value & 0xff);
>> + } else {
>> + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid TIMA write @%"
>> + HWADDR_PRIx" size %d\n", offset, size);
>> + }
>> +
>> + /* TODO: support TM_SPC_ACK_OS_EL */
>> +}
>> +
>> +static void xive_tm_write(void *opaque, hwaddr offset,
>> + uint64_t value, unsigned size)
>> +{
>> + PowerPCCPU *cpu = POWERPC_CPU(current_cpu);
>> + XiveICPState *icp = XIVE_ICP(cpu->intc);
>> + int i;
>> +
>> + if (offset >= TM_SPC_ACK_EBB) {
>> + xive_tm_write_special(icp, offset, value, size);
>> + return;
>> + }
>> +
>> + if (offset & TM_QW1_OS) {
>> + switch (size) {
>> + case 1:
>> + if (offset == TM_QW1_OS + TM_CPPR) {
>> + xive_icp_set_cppr(icp, value & 0xff);
>> + }
>> + break;
>> + case 4:
>> + case 8:
>> + if (QEMU_IS_ALIGNED(offset, size)) {
>> + for (i = 0; i < size; i++) {
>> + if (!xive_tm_is_readonly(offset + i)) {
>> + icp->tima[offset + i] = (value >> (8 * i)) & 0xff;
>> + }
>> + }
>> + } else {
>> + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid TIMA write @%"
>> + HWADDR_PRIx" size %d\n", offset, size);
>> + }
>> + break;
>> + default:
>> + qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid TIMA write @%"
>> + HWADDR_PRIx" size %d\n", offset, size);
>> + }
>> + } else {
>> + qemu_log_mask(LOG_UNIMP, "XIVE: does handle non-OS TIMA ring @%"
>> + HWADDR_PRIx"\n", offset);
>> + }
>> +}
>> +
>> +
>> +static const MemoryRegionOps xive_tm_ops = {
>> + .read = xive_tm_read,
>> + .write = xive_tm_write,
>> + .endianness = DEVICE_BIG_ENDIAN,
>> + .valid = {
>> + .min_access_size = 1,
>> + .max_access_size = 8,
>> + },
>> + .impl = {
>> + .min_access_size = 1,
>> + .max_access_size = 8,
>> + },
>> +};
>> +
>> static void xive_icp_reset(ICPState *icp)
>> {
>> XiveICPState *xicp = XIVE_ICP(icp);
>> @@ -453,6 +627,11 @@ static const TypeInfo xive_ics_info = {
>> #define P9_MMIO_BASE 0x006000000000000ull
>> #define P9_CHIP_BASE(id) (P9_MMIO_BASE | (0x40000000000ull * (uint64_t)
>> (id)))
>>
>> +/* Thread Interrupt Management Area MMIO */
>> +#define TM_BAR_DEFAULT 0x30203180000ull
>> +#define TM_SHIFT 16
>> +#define TM_BAR_SIZE (XIVE_TM_RING_COUNT * (1 << TM_SHIFT))
>> +
>> static uint64_t xive_esb_default_read(void *p, hwaddr offset, unsigned size)
>> {
>> qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n",
>> @@ -541,6 +720,14 @@ static void xive_realize(DeviceState *dev, Error **errp)
>> NULL, "xive.esb", VC_BAR_SIZE);
>> sysbus_init_mmio(SYS_BUS_DEVICE(dev), &x->esb_iomem);
>>
>> + /* TM BAR. Same address for each chip */
>> + x->tm_base = (P9_MMIO_BASE | TM_BAR_DEFAULT);
>> + x->tm_shift = TM_SHIFT;
>> +
>> + memory_region_init_io(&x->tm_iomem, OBJECT(x), &xive_tm_ops, x,
>> + "xive.tm", TM_BAR_SIZE);
>> + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &x->tm_iomem);
>> +
>> qemu_register_reset(xive_reset, dev);
>> }
>>
>
- [Qemu-devel] [RFC PATCH 11/26] ppc/xics: introduce a print_info() handler to the ICS and ICP objects, (continued)
- [Qemu-devel] [RFC PATCH 12/26] ppc/xive: add a print_info() handler for the interrupt source, Cédric Le Goater, 2017/07/05
- [Qemu-devel] [RFC PATCH 13/26] ppc/xive: introduce a XIVE interrupt presenter model, Cédric Le Goater, 2017/07/05
- [Qemu-devel] [RFC PATCH 14/26] ppc/xive: add MMIO handlers to the XIVE interrupt presenter model, Cédric Le Goater, 2017/07/05
- Re: [Qemu-devel] [RFC PATCH 14/26] ppc/xive: add MMIO handlers to the XIVE interrupt presenter model, David Gibson, 2017/07/24
- Re: [Qemu-devel] [RFC PATCH 14/26] ppc/xive: add MMIO handlers to the XIVE interrupt presenter model,
Cédric Le Goater <=
- Re: [Qemu-devel] [RFC PATCH 14/26] ppc/xive: add MMIO handlers to the XIVE interrupt presenter model, David Gibson, 2017/07/25
- Re: [Qemu-devel] [RFC PATCH 14/26] ppc/xive: add MMIO handlers to the XIVE interrupt presenter model, Cédric Le Goater, 2017/07/25
- Re: [Qemu-devel] [RFC PATCH 14/26] ppc/xive: add MMIO handlers to the XIVE interrupt presenter model, David Gibson, 2017/07/25
- Re: [Qemu-devel] [RFC PATCH 14/26] ppc/xive: add MMIO handlers to the XIVE interrupt presenter model, Cédric Le Goater, 2017/07/25
- Re: [Qemu-devel] [RFC PATCH 14/26] ppc/xive: add MMIO handlers to the XIVE interrupt presenter model, David Gibson, 2017/07/25
[Qemu-devel] [RFC PATCH 15/26] ppc/xive: push EQ data in OS event queues, Cédric Le Goater, 2017/07/05
[Qemu-devel] [RFC PATCH 16/26] ppc/xive: notify CPU when interrupt priority is more privileged, Cédric Le Goater, 2017/07/05
[Qemu-devel] [RFC PATCH 17/26] ppc/xive: add hcalls support, Cédric Le Goater, 2017/07/05