[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 08/10] hw/loongarch: Fix ipi device access of 64bits
From: |
Xiaojuan Yang |
Subject: |
[PATCH 08/10] hw/loongarch: Fix ipi device access of 64bits |
Date: |
Wed, 22 Jun 2022 18:42:59 +0800 |
1.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.
2.By the document of ipi mailsend device, byte is written only when the mask bit
is 0. The original code discards mask bit and overwrite the data always, this
patch fixes the issue.
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
---
hw/intc/loongarch_ipi.c | 85 ++++++++++++++++++++++-----------
hw/loongarch/loongson3.c | 5 +-
include/hw/intc/loongarch_ipi.h | 8 ++--
3 files changed, 65 insertions(+), 33 deletions(-)
diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
index 66bee93675..57d7965289 100644
--- a/hw/intc/loongarch_ipi.c
+++ b/hw/intc/loongarch_ipi.c
@@ -50,35 +50,40 @@ static uint64_t loongarch_ipi_readl(void *opaque, hwaddr
addr, unsigned size)
return ret;
}
-static int get_ipi_data(target_ulong val)
+static void send_ipi_data(CPULoongArchState *env, target_ulong val,
target_ulong addr)
{
int i, mask, data;
- data = val >> 32;
- mask = (val >> 27) & 0xf;
-
+ data = address_space_ldl(&env->address_space_iocsr, addr,
+ MEMTXATTRS_UNSPECIFIED, NULL);
+ mask = 0;
for (i = 0; i < 4; i++) {
- if ((mask >> i) & 1) {
- data &= ~(0xff << (i * 8));
+ /* bit 27 - 30 is mask for byte write */
+ if (val & (0x1UL << (27 + i))) {
+ mask |= 0xff << (i * 8);
}
}
- return data;
+
+ data &= mask;
+ data |= (val >> 32) & ~mask;
+ address_space_stl(&env->address_space_iocsr, addr,
+ data, MEMTXATTRS_UNSPECIFIED, NULL);
}
static void ipi_send(uint64_t val)
{
int cpuid, data;
CPULoongArchState *env;
+ CPUState *cs;
+ LoongArchCPU *cpu;
cpuid = (val >> 16) & 0x3ff;
/* IPI status vector */
data = 1 << (val & 0x1f);
- qemu_mutex_lock_iothread();
- CPUState *cs = qemu_get_cpu(cpuid);
- LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ cs = qemu_get_cpu(cpuid);
+ cpu = LOONGARCH_CPU(cs);
env = &cpu->env;
loongarch_cpu_set_irq(cpu, IRQ_IPI, 1);
- qemu_mutex_unlock_iothread();
address_space_stl(&env->address_space_iocsr, 0x1008,
data, MEMTXATTRS_UNSPECIFIED, NULL);
@@ -86,23 +91,23 @@ static void ipi_send(uint64_t val)
static void mail_send(uint64_t val)
{
- int cpuid, data;
+ int cpuid;
hwaddr addr;
CPULoongArchState *env;
+ CPUState *cs;
+ LoongArchCPU *cpu;
cpuid = (val >> 16) & 0x3ff;
addr = 0x1020 + (val & 0x1c);
- CPUState *cs = qemu_get_cpu(cpuid);
- LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+ cs = qemu_get_cpu(cpuid);
+ cpu = LOONGARCH_CPU(cs);
env = &cpu->env;
- data = get_ipi_data(val);
- address_space_stl(&env->address_space_iocsr, addr,
- data, MEMTXATTRS_UNSPECIFIED, NULL);
+ send_ipi_data(env, val, addr);
}
static void any_send(uint64_t val)
{
- int cpuid, data;
+ int cpuid;
hwaddr addr;
CPULoongArchState *env;
@@ -111,9 +116,7 @@ static void any_send(uint64_t val)
CPUState *cs = qemu_get_cpu(cpuid);
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
env = &cpu->env;
- data = get_ipi_data(val);
- address_space_stl(&env->address_space_iocsr, addr,
- data, MEMTXATTRS_UNSPECIFIED, NULL);
+ send_ipi_data(env, val, addr);
}
static void loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
@@ -150,12 +153,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 +169,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 = 4,
+ .valid.max_access_size = 8,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
static void loongarch_ipi_init(Object *obj)
{
int cpu;
@@ -185,10 +208,16 @@ static void loongarch_ipi_init(Object *obj)
return;
}
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 4b58a76025..a06fed7797 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -453,7 +453,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..a98c3dd4a3 100644
--- a/include/hw/intc/loongarch_ipi.h
+++ b/include/hw/intc/loongarch_ipi.h
@@ -23,9 +23,9 @@
#define IOCSR_IPI_SEND 0x40
#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 +46,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
--
2.31.1
- [PATCH 00/10] Add functions for LoongArch virt machine, Xiaojuan Yang, 2022/06/22
- [PATCH 02/10] hw/loongarch: Add fw_cfg table support, Xiaojuan Yang, 2022/06/22
- [PATCH 08/10] hw/loongarch: Fix ipi device access of 64bits,
Xiaojuan Yang <=
- [PATCH 04/10] hw/loongarch: Add linux kernel booting support, Xiaojuan Yang, 2022/06/22
- [PATCH 03/10] hw/loongarch: Add uefi bios loading support, Xiaojuan Yang, 2022/06/22
- [PATCH 06/10] hw/loongarch: Add acpi ged support, Xiaojuan Yang, 2022/06/22
- [PATCH 10/10] target/loongarch: Add lock when writing timer clear reg, Xiaojuan Yang, 2022/06/22
- [PATCH 07/10] hw/loongarch: Add fdt support, Xiaojuan Yang, 2022/06/22
- [PATCH 05/10] hw/loongarch: Add smbios support, Xiaojuan Yang, 2022/06/22
- [PATCH 09/10] target/loongarch: Fix the meaning of ECFG reg's VS field, Xiaojuan Yang, 2022/06/22
- [PATCH 01/10] hw/loongarch: rename macro prefix LS_PCI to LS7A_PCI, Xiaojuan Yang, 2022/06/22