diff options
author | Xiaojuan Yang <yangxiaojuan@loongson.cn> | 2022-07-05 14:49:00 +0800 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2022-07-05 16:25:17 +0530 |
commit | ddf93261847df55137436abe429aae7f9d8228dd (patch) | |
tree | df643314296f894d227ac269bfac43ec7df7d037 | |
parent | 0df0a6655522f9a9df78aeab39a96f2d0f181c92 (diff) |
hw/intc/loongarch_ipi: Fix ipi device access of 64bits
In general loongarch ipi device, 32bit registers is emulated, however for
anysend/mailsend device only 64bit register access is supported. So separate
the ipi memory region into two regions, including 32 bits and 64 bits.
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Message-Id: <20220705064901.2353349-2-yangxiaojuan@loongson.cn>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r-- | hw/intc/loongarch_ipi.c | 38 | ||||
-rw-r--r-- | hw/loongarch/loongson3.c | 5 | ||||
-rw-r--r-- | include/hw/intc/loongarch_ipi.h | 7 |
3 files changed, 39 insertions, 11 deletions
diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c index 66bee93675..b8b1b9cd53 100644 --- a/hw/intc/loongarch_ipi.c +++ b/hw/intc/loongarch_ipi.c @@ -150,12 +150,6 @@ static void loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val, case IOCSR_IPI_SEND: ipi_send(val); break; - case IOCSR_MAIL_SEND: - mail_send(val); - break; - case IOCSR_ANY_SEND: - any_send(val); - break; default: qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr); break; @@ -172,6 +166,32 @@ static const MemoryRegionOps loongarch_ipi_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; +/* mail send and any send only support writeq */ +static void loongarch_ipi_writeq(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + addr &= 0xfff; + switch (addr) { + case MAIL_SEND_OFFSET: + mail_send(val); + break; + case ANY_SEND_OFFSET: + any_send(val); + break; + default: + break; + } +} + +static const MemoryRegionOps loongarch_ipi64_ops = { + .write = loongarch_ipi_writeq, + .impl.min_access_size = 8, + .impl.max_access_size = 8, + .valid.min_access_size = 8, + .valid.max_access_size = 8, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + static void loongarch_ipi_init(Object *obj) { int cpu; @@ -187,8 +207,12 @@ static void loongarch_ipi_init(Object *obj) lams = LOONGARCH_MACHINE(machine); for (cpu = 0; cpu < MAX_IPI_CORE_NUM; cpu++) { memory_region_init_io(&s->ipi_iocsr_mem[cpu], obj, &loongarch_ipi_ops, - &lams->ipi_core[cpu], "loongarch_ipi_iocsr", 0x100); + &lams->ipi_core[cpu], "loongarch_ipi_iocsr", 0x48); sysbus_init_mmio(sbd, &s->ipi_iocsr_mem[cpu]); + + memory_region_init_io(&s->ipi64_iocsr_mem[cpu], obj, &loongarch_ipi64_ops, + &lams->ipi_core[cpu], "loongarch_ipi64_iocsr", 0x118); + sysbus_init_mmio(sbd, &s->ipi64_iocsr_mem[cpu]); qdev_init_gpio_out(DEVICE(obj), &lams->ipi_core[cpu].irq, 1); } } diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c index 403dd91e11..15fddfc4f5 100644 --- a/hw/loongarch/loongson3.c +++ b/hw/loongarch/loongson3.c @@ -230,7 +230,10 @@ static void loongarch_irq_init(LoongArchMachineState *lams) /* IPI iocsr memory region */ memory_region_add_subregion(&env->system_iocsr, SMP_IPI_MAILBOX, sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), - cpu)); + cpu * 2)); + memory_region_add_subregion(&env->system_iocsr, MAIL_SEND_ADDR, + sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), + cpu * 2 + 1)); /* extioi iocsr memory region */ memory_region_add_subregion(&env->system_iocsr, APIC_BASE, sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi), diff --git a/include/hw/intc/loongarch_ipi.h b/include/hw/intc/loongarch_ipi.h index 996ed7ea93..0ee48fca55 100644 --- a/include/hw/intc/loongarch_ipi.h +++ b/include/hw/intc/loongarch_ipi.h @@ -24,8 +24,9 @@ #define IOCSR_MAIL_SEND 0x48 #define IOCSR_ANY_SEND 0x158 -/* IPI system memory address */ -#define IPI_SYSTEM_MEM 0x1fe01000 +#define MAIL_SEND_ADDR (SMP_IPI_MAILBOX + IOCSR_MAIL_SEND) +#define MAIL_SEND_OFFSET 0 +#define ANY_SEND_OFFSET (IOCSR_ANY_SEND - IOCSR_MAIL_SEND) #define MAX_IPI_CORE_NUM 4 #define MAX_IPI_MBX_NUM 4 @@ -46,7 +47,7 @@ typedef struct IPICore { struct LoongArchIPI { SysBusDevice parent_obj; MemoryRegion ipi_iocsr_mem[MAX_IPI_CORE_NUM]; - MemoryRegion ipi_system_mem[MAX_IPI_CORE_NUM]; + MemoryRegion ipi64_iocsr_mem[MAX_IPI_CORE_NUM]; }; #endif |