Re: [PATCH] mips64el-softmmu: Enable MTTCG

2024-06-07 Thread Jiaxun Yang



在2024年6月5日六月 下午1:47,Jiaxun Yang写道:
[...]
> I'll try to upgrade kernel used in this test.

Unfortunately, we don't have kernel build from reliable source
for that test.

I requested Debian project to build kernel for us[1].

[1]: https://salsa.debian.org/kernel-team/linux/-/merge_requests/1074

Thanks
>
> Thanks
> - Jiaxun
>>
[...]
>
> -- 
> - Jiaxun

-- 
- Jiaxun



Re: [PATCH] mips64el-softmmu: Enable MTTCG

2024-06-05 Thread Jiaxun Yang



在2024年6月4日六月 下午1:43,Alex Bennée写道:
[...]
>
> I'm a little uncomfortable about making the success of MTTCG depend on
> the user options passed to the kernel.

Yes, I agree, it sounds awkward.

>
> How come a non-icount run depends on how many instructions are being run
> on each core? Why is time not based on the wallclock time and by
> definition synced between all cores?

That's the problem of Guest Kernel, the synchronisation mechanism is poorly
written that relies on instruction latency too much. I have patch pending to
improve it at guest side, but we can't fix it in existing binary.

This clock, CP0_Counter, as per ISA spec, is independent between cores and
needs to be synchronized by software. We can emulate it as a monotonic clock
source and Linux should be happy with it, but that is violating ISA spec.

>
>> In non-MTTCG build, the execution is slow enough so kernel won't
>> observe back drifts.
>>
>> Test results:
>>
>> With clocksource=MIPS
>> ```
>>  ~/tmp/retry/retry.py -n 100 -c -- ./qemu-system-mips64el \
>> -display none -vga none -serial mon:stdio \
>> -machine malta -kernel ./vmlinux-4.7.0-rc1.I6400 \
>> -cpu I6400 -smp 8 -vga std \
>> -append "printk.time=0 clocksource=MIPS console=tty0 console=ttyS0 
>> panic=-1" \
>> --no-reboot
>>
>> 100, 0, PASS, 5.258126, 100, 100, -
>> Results summary:
>> 0: 100 times (100.00%), avg time 6.508 (55.53 varience/7.45 deviation)
>> Ran command 100 times, 100 passes
>> ```
>>
>> With linux-next:
>> ```
>>  ~/tmp/retry/retry.py -n 100 -c -- ./qemu-system-mips64el \
>> -display none -vga none -serial mon:stdio \
>> -machine malta -kernel ~/linux-next/vmlinux \
>> -cpu I6400 -smp 8 -vga std \
>> -append "printk.time=0 console=tty0 console=ttyS0 panic=-1" \
>> --no-reboot
>>
>> 100, 0, PASS, 4.507921, 100, 100, -
>> Results summary:
>> 0: 100 times (100.00%), avg time 4.233 (0.04 varience/0.21 deviation)
>> Ran command 100 times, 100 passes
>> ```
>>
>> Signed-off-by: Jiaxun Yang 
>> ---
>> I'll leave the test case alone as it's already marked as
>> QEMU_TEST_FLAKY_TESTS
>
> We should ensure we have some testing enabled if we switch this on. Was
> the FLAKY test marked for MTTCG issues or something else?

Tracking history, I think it was because this issue is still popping up after
disabling MTTCG.

I'll try to upgrade kernel used in this test.

Thanks
- Jiaxun
>
>> ---
>>  configs/targets/mips64el-softmmu.mak | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/configs/targets/mips64el-softmmu.mak 
>> b/configs/targets/mips64el-softmmu.mak
>> index 8d9ab3ddc4b1..199b1d909a7d 100644
>> --- a/configs/targets/mips64el-softmmu.mak
>> +++ b/configs/targets/mips64el-softmmu.mak
>> @@ -1,3 +1,4 @@
>>  TARGET_ARCH=mips64
>>  TARGET_BASE_ARCH=mips
>> +TARGET_SUPPORTS_MTTCG=y
>>  TARGET_NEED_FDT=y
>>
>> ---
>> base-commit: 248f6f62df073a3b4158fd0093863ab885feabb5
>> change-id: 20240511-mips_mttcg-47a6b19074b3
>>
>> Best regards,
>
> -- 
> Alex Bennée
> Virtualisation Tech Lead @ Linaro

-- 
- Jiaxun



[PATCH v3 1/4] hw/intc: Remove loongarch_ipi.c

2024-06-04 Thread Jiaxun Yang
It was missed out in previous commit.

Fixes: b4a12dfc2132 ("hw/intc/loongarch_ipi: Rename as loongson_ipi")
Signed-off-by: Jiaxun Yang 
---
 hw/intc/loongarch_ipi.c | 347 
 1 file changed, 347 deletions(-)

diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
deleted file mode 100644
index 44b3b9c138d6..
--- a/hw/intc/loongarch_ipi.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * LoongArch ipi interrupt support
- *
- * Copyright (C) 2021 Loongson Technology Corporation Limited
- */
-
-#include "qemu/osdep.h"
-#include "hw/boards.h"
-#include "hw/sysbus.h"
-#include "hw/intc/loongarch_ipi.h"
-#include "hw/irq.h"
-#include "hw/qdev-properties.h"
-#include "qapi/error.h"
-#include "qemu/log.h"
-#include "exec/address-spaces.h"
-#include "migration/vmstate.h"
-#include "target/loongarch/cpu.h"
-#include "trace.h"
-
-static MemTxResult loongarch_ipi_readl(void *opaque, hwaddr addr,
-   uint64_t *data,
-   unsigned size, MemTxAttrs attrs)
-{
-IPICore *s;
-LoongArchIPI *ipi = opaque;
-uint64_t ret = 0;
-int index = 0;
-
-s = >cpu[attrs.requester_id];
-addr &= 0xff;
-switch (addr) {
-case CORE_STATUS_OFF:
-ret = s->status;
-break;
-case CORE_EN_OFF:
-ret = s->en;
-break;
-case CORE_SET_OFF:
-ret = 0;
-break;
-case CORE_CLEAR_OFF:
-ret = 0;
-break;
-case CORE_BUF_20 ... CORE_BUF_38 + 4:
-index = (addr - CORE_BUF_20) >> 2;
-ret = s->buf[index];
-break;
-default:
-qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr);
-break;
-}
-
-trace_loongarch_ipi_read(size, (uint64_t)addr, ret);
-*data = ret;
-return MEMTX_OK;
-}
-
-static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr,
-  MemTxAttrs attrs)
-{
-int i, mask = 0, data = 0;
-
-/*
- * bit 27-30 is mask for byte writing,
- * if the mask is 0, we need not to do anything.
- */
-if ((val >> 27) & 0xf) {
-data = address_space_ldl(env->address_space_iocsr, addr,
- attrs, NULL);
-for (i = 0; i < 4; i++) {
-/* get mask for byte writing */
-if (val & (0x1 << (27 + i))) {
-mask |= 0xff << (i * 8);
-}
-}
-}
-
-data &= mask;
-data |= (val >> 32) & ~mask;
-address_space_stl(env->address_space_iocsr, addr,
-  data, attrs, NULL);
-}
-
-static int archid_cmp(const void *a, const void *b)
-{
-   CPUArchId *archid_a = (CPUArchId *)a;
-   CPUArchId *archid_b = (CPUArchId *)b;
-
-   return archid_a->arch_id - archid_b->arch_id;
-}
-
-static CPUArchId *find_cpu_by_archid(MachineState *ms, uint32_t id)
-{
-CPUArchId apic_id, *found_cpu;
-
-apic_id.arch_id = id;
-found_cpu = bsearch(_id, ms->possible_cpus->cpus,
-ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus),
-archid_cmp);
-
-return found_cpu;
-}
-
-static CPUState *ipi_getcpu(int arch_id)
-{
-MachineState *machine = MACHINE(qdev_get_machine());
-CPUArchId *archid;
-
-archid = find_cpu_by_archid(machine, arch_id);
-if (archid) {
-return CPU(archid->cpu);
-}
-
-return NULL;
-}
-
-static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs)
-{
-uint32_t cpuid;
-hwaddr addr;
-CPUState *cs;
-
-cpuid = extract32(val, 16, 10);
-cs = ipi_getcpu(cpuid);
-if (cs == NULL) {
-return MEMTX_DECODE_ERROR;
-}
-
-/* override requester_id */
-addr = SMP_IPI_MAILBOX + CORE_BUF_20 + (val & 0x1c);
-attrs.requester_id = cs->cpu_index;
-send_ipi_data(_CPU(cs)->env, val, addr, attrs);
-return MEMTX_OK;
-}
-
-static MemTxResult any_send(uint64_t val, MemTxAttrs attrs)
-{
-uint32_t cpuid;
-hwaddr addr;
-CPUState *cs;
-
-cpuid = extract32(val, 16, 10);
-cs = ipi_getcpu(cpuid);
-if (cs == NULL) {
-return MEMTX_DECODE_ERROR;
-}
-
-/* override requester_id */
-addr = val & 0x;
-attrs.requester_id = cs->cpu_index;
-send_ipi_data(_CPU(cs)->env, val, addr, attrs);
-return MEMTX_OK;
-}
-
-static MemTxResult loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t 
val,
-unsigned size, MemTxAttrs attrs)
-{
-LoongArchIPI *ipi = opaque;
-IPICore *s;
-int index = 0;
-uint32_t cpuid;
-uint8_t vector;
-CPUState *cs;
-
-s = >cpu[attrs.requester_id];
-addr &= 0xff;
-trace_loongarch_ipi

[PATCH v3 4/4] hw/intc/loongson_ipi: Replace ipi_getcpu with cpu_by_arch_id

2024-06-04 Thread Jiaxun Yang
cpu_by_arch_id is doing the same thing as our ipi_getcpu logic.

Signed-off-by: Jiaxun Yang 
---
 hw/intc/loongson_ipi.c | 39 +++
 1 file changed, 3 insertions(+), 36 deletions(-)

diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c
index c8a25b4eb8e2..b3cda5972793 100644
--- a/hw/intc/loongson_ipi.c
+++ b/hw/intc/loongson_ipi.c
@@ -118,39 +118,6 @@ static MemTxResult send_ipi_data(CPUState *cpu, uint64_t 
val, hwaddr addr,
 return MEMTX_OK;
 }
 
-static int archid_cmp(const void *a, const void *b)
-{
-   CPUArchId *archid_a = (CPUArchId *)a;
-   CPUArchId *archid_b = (CPUArchId *)b;
-
-   return archid_a->arch_id - archid_b->arch_id;
-}
-
-static CPUArchId *find_cpu_by_archid(MachineState *ms, uint32_t id)
-{
-CPUArchId apic_id, *found_cpu;
-
-apic_id.arch_id = id;
-found_cpu = bsearch(_id, ms->possible_cpus->cpus,
-ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus),
-archid_cmp);
-
-return found_cpu;
-}
-
-static CPUState *ipi_getcpu(int arch_id)
-{
-MachineState *machine = MACHINE(qdev_get_machine());
-CPUArchId *archid;
-
-archid = find_cpu_by_archid(machine, arch_id);
-if (archid) {
-return CPU(archid->cpu);
-}
-
-return NULL;
-}
-
 static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs)
 {
 uint32_t cpuid;
@@ -158,7 +125,7 @@ static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs)
 CPUState *cs;
 
 cpuid = extract32(val, 16, 10);
-cs = ipi_getcpu(cpuid);
+cs = cpu_by_arch_id(cpuid);
 if (cs == NULL) {
 return MEMTX_DECODE_ERROR;
 }
@@ -176,7 +143,7 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs attrs)
 CPUState *cs;
 
 cpuid = extract32(val, 16, 10);
-cs = ipi_getcpu(cpuid);
+cs = cpu_by_arch_id(cpuid);
 if (cs == NULL) {
 return MEMTX_DECODE_ERROR;
 }
@@ -227,7 +194,7 @@ static MemTxResult loongson_ipi_core_writel(void *opaque, 
hwaddr addr,
 cpuid = extract32(val, 16, 10);
 /* IPI status vector */
 vector = extract8(val, 0, 5);
-cs = ipi_getcpu(cpuid);
+cs = cpu_by_arch_id(cpuid);
 if (cs == NULL || cs->cpu_index >= ipi->num_cpu) {
 return MEMTX_DECODE_ERROR;
 }

-- 
2.43.0




[PATCH v3 3/4] hw/mips/loongson3_virt: Wire up loongson_ipi device

2024-06-04 Thread Jiaxun Yang
Wire up loongson_ipi device for loongson3_virt machine, so we
can have SMP support for TCG backend as well.

Signed-off-by: Jiaxun Yang 
---
 hw/mips/Kconfig   |  1 +
 hw/mips/loongson3_bootp.c |  2 --
 hw/mips/loongson3_bootp.h |  3 +++
 hw/mips/loongson3_virt.c  | 39 +--
 4 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index a7f26edebe84..692bede538ee 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -67,6 +67,7 @@ config LOONGSON3V
 imply USB_OHCI_PCI
 select SERIAL
 select GOLDFISH_RTC
+select LOONGSON_IPI
 select LOONGSON_LIOINTC
 select PCI_EXPRESS_GENERIC_BRIDGE
 select MSI_NONBROKEN
diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
index 03a10b63c1b4..b97b81903b74 100644
--- a/hw/mips/loongson3_bootp.c
+++ b/hw/mips/loongson3_bootp.c
@@ -25,8 +25,6 @@
 #include "hw/boards.h"
 #include "hw/mips/loongson3_bootp.h"
 
-#define LOONGSON3_CORE_PER_NODE 4
-
 static void init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
 {
 struct efi_cpuinfo_loongson *c = g_cpuinfo;
diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h
index 1b0dd3b59171..9091265df7fc 100644
--- a/hw/mips/loongson3_bootp.h
+++ b/hw/mips/loongson3_bootp.h
@@ -200,6 +200,8 @@ struct boot_params {
 struct efi_reset_system_t reset_system;
 };
 
+#define LOONGSON3_CORE_PER_NODE 4
+
 /* Overall MMIO & Memory layout */
 enum {
 VIRT_LOWMEM,
@@ -211,6 +213,7 @@ enum {
 VIRT_BIOS_ROM,
 VIRT_UART,
 VIRT_LIOINTC,
+VIRT_IPI,
 VIRT_PCIE_MMIO,
 VIRT_HIGHMEM
 };
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index 440268a07430..3a4105228c1d 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -36,6 +36,7 @@
 #include "hw/mips/loongson3_bootp.h"
 #include "hw/misc/unimp.h"
 #include "hw/intc/i8259.h"
+#include "hw/intc/loongson_ipi.h"
 #include "hw/loader.h"
 #include "hw/isa/superio.h"
 #include "hw/pci/msi.h"
@@ -74,6 +75,7 @@ const MemMapEntry virt_memmap[] = {
 [VIRT_PCIE_ECAM] =   { 0x1a00, 0x200 },
 [VIRT_BIOS_ROM] ={ 0x1fc0,  0x20 },
 [VIRT_UART] ={ 0x1fe001e0,   0x8 },
+[VIRT_IPI] = { 0x3ff01000, 0x400 },
 [VIRT_LIOINTC] = { 0x3ff01400,  0x64 },
 [VIRT_PCIE_MMIO] =   { 0x4000,0x4000 },
 [VIRT_HIGHMEM] = { 0x8000,   0x0 }, /* Variable */
@@ -485,6 +487,7 @@ static void mips_loongson3_virt_init(MachineState *machine)
 Clock *cpuclk;
 CPUMIPSState *env;
 DeviceState *liointc;
+DeviceState *ipi = NULL;
 char *filename;
 const char *kernel_cmdline = machine->kernel_cmdline;
 const char *kernel_filename = machine->kernel_filename;
@@ -494,6 +497,7 @@ static void mips_loongson3_virt_init(MachineState *machine)
 MemoryRegion *ram = g_new(MemoryRegion, 1);
 MemoryRegion *bios = g_new(MemoryRegion, 1);
 MemoryRegion *iomem = g_new(MemoryRegion, 1);
+MemoryRegion *iocsr = g_new(MemoryRegion, 1);
 
 /* TODO: TCG will support all CPU types */
 if (!kvm_enabled()) {
@@ -527,6 +531,19 @@ static void mips_loongson3_virt_init(MachineState *machine)
 create_unimplemented_device("mmio fallback 0", 0x1000, 256 * MiB);
 create_unimplemented_device("mmio fallback 1", 0x3000, 256 * MiB);
 
+memory_region_init(iocsr, OBJECT(machine), "loongson3.iocsr", UINT32_MAX);
+
+/* IPI controller is in kernel for KVM */
+if (!kvm_enabled()) {
+ipi = qdev_new(TYPE_LOONGSON_IPI);
+qdev_prop_set_uint32(ipi, "num-cpu", machine->smp.cpus);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), _fatal);
+memory_region_add_subregion(iocsr, SMP_IPI_MAILBOX,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 0));
+memory_region_add_subregion(iocsr, MAIL_SEND_ADDR,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1));
+}
+
 liointc = qdev_new("loongson.liointc");
 sysbus_realize_and_unref(SYS_BUS_DEVICE(liointc), _fatal);
 
@@ -543,6 +560,8 @@ static void mips_loongson3_virt_init(MachineState *machine)
 clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ);
 
 for (i = 0; i < machine->smp.cpus; i++) {
+int node = i / LOONGSON3_CORE_PER_NODE;
+int core = i % LOONGSON3_CORE_PER_NODE;
 int ip;
 
 /* init CPUs */
@@ -553,12 +572,28 @@ static void mips_loongson3_virt_init(MachineState 
*machine)
 cpu_mips_clock_init(cpu);
 qemu_register_reset(main_cpu_reset, cpu);
 
-if (i >= 4) {
+if (ipi) {
+hwaddr base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base;
+base += core * 0x100;
+qdev_connect_gpio_out(ipi, i, cpu->env.irq[6]);
+sysbu

[PATCH v3 2/4] hw/intc/loongson_ipi: Provide per core MMIO address spaces

2024-06-04 Thread Jiaxun Yang
The real IPI hardware have dedicated MMIO registers mapped into
memory address space for every core. This is not used by LoongArch
guest software but it is essential for CPU without IOCSR such as
Loongson-3A1000.

Implement it with existing infrastructure.

Acked-by: Song Gao 
Signed-off-by: Jiaxun Yang 
---
 hw/intc/loongson_ipi.c | 81 --
 include/hw/intc/loongson_ipi.h |  2 ++
 2 files changed, 64 insertions(+), 19 deletions(-)

diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c
index 93cc50a37a11..c8a25b4eb8e2 100644
--- a/hw/intc/loongson_ipi.c
+++ b/hw/intc/loongson_ipi.c
@@ -23,16 +23,14 @@
 #endif
 #include "trace.h"
 
-static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr,
+static MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr,
uint64_t *data,
unsigned size, MemTxAttrs attrs)
 {
-IPICore *s;
-LoongsonIPI *ipi = opaque;
+IPICore *s = opaque;
 uint64_t ret = 0;
 int index = 0;
 
-s = >cpu[attrs.requester_id];
 addr &= 0xff;
 switch (addr) {
 case CORE_STATUS_OFF:
@@ -61,6 +59,21 @@ static MemTxResult loongson_ipi_readl(void *opaque, hwaddr 
addr,
 return MEMTX_OK;
 }
 
+static MemTxResult loongson_ipi_iocsr_readl(void *opaque, hwaddr addr,
+   uint64_t *data,
+   unsigned size, MemTxAttrs attrs)
+{
+LoongsonIPI *ipi = opaque;
+IPICore *s;
+
+if (attrs.requester_id >= ipi->num_cpu) {
+return MEMTX_DECODE_ERROR;
+}
+
+s = >cpu[attrs.requester_id];
+return loongson_ipi_core_readl(s, addr, data, size, attrs);
+}
+
 static AddressSpace *get_cpu_iocsr_as(CPUState *cpu)
 {
 #ifdef TARGET_LOONGARCH64
@@ -174,17 +187,17 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs 
attrs)
 return send_ipi_data(cs, val, addr, attrs);
 }
 
-static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
-unsigned size, MemTxAttrs attrs)
+static MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr,
+uint64_t val, unsigned size,
+MemTxAttrs attrs)
 {
-LoongsonIPI *ipi = opaque;
-IPICore *s;
+IPICore *s = opaque;
+LoongsonIPI *ipi = s->ipi;
 int index = 0;
 uint32_t cpuid;
 uint8_t vector;
 CPUState *cs;
 
-s = >cpu[attrs.requester_id];
 addr &= 0xff;
 trace_loongson_ipi_write(size, (uint64_t)addr, val);
 switch (addr) {
@@ -215,13 +228,11 @@ static MemTxResult loongson_ipi_writel(void *opaque, 
hwaddr addr, uint64_t val,
 /* IPI status vector */
 vector = extract8(val, 0, 5);
 cs = ipi_getcpu(cpuid);
-if (cs == NULL) {
+if (cs == NULL || cs->cpu_index >= ipi->num_cpu) {
 return MEMTX_DECODE_ERROR;
 }
-
-/* override requester_id */
-attrs.requester_id = cs->cpu_index;
-loongson_ipi_writel(ipi, CORE_SET_OFF, BIT(vector), 4, attrs);
+loongson_ipi_core_writel(>cpu[cs->cpu_index], CORE_SET_OFF,
+ BIT(vector), 4, attrs);
 break;
 default:
 qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr);
@@ -231,9 +242,34 @@ static MemTxResult loongson_ipi_writel(void *opaque, 
hwaddr addr, uint64_t val,
 return MEMTX_OK;
 }
 
-static const MemoryRegionOps loongson_ipi_ops = {
-.read_with_attrs = loongson_ipi_readl,
-.write_with_attrs = loongson_ipi_writel,
+static MemTxResult loongson_ipi_iocsr_writel(void *opaque, hwaddr addr,
+uint64_t val, unsigned size,
+MemTxAttrs attrs)
+{
+LoongsonIPI *ipi = opaque;
+IPICore *s;
+
+if (attrs.requester_id >= ipi->num_cpu) {
+return MEMTX_DECODE_ERROR;
+}
+
+s = >cpu[attrs.requester_id];
+return loongson_ipi_core_writel(s, addr, val, size, attrs);
+}
+
+static const MemoryRegionOps loongson_ipi_core_ops = {
+.read_with_attrs = loongson_ipi_core_readl,
+.write_with_attrs = loongson_ipi_core_writel,
+.impl.min_access_size = 4,
+.impl.max_access_size = 4,
+.valid.min_access_size = 4,
+.valid.max_access_size = 8,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static const MemoryRegionOps loongson_ipi_iocsr_ops = {
+.read_with_attrs = loongson_ipi_iocsr_readl,
+.write_with_attrs = loongson_ipi_iocsr_writel,
 .impl.min_access_size = 4,
 .impl.max_access_size = 4,
 .valid.min_access_size = 4,
@@ -282,7 +318,7 @@ static void loongson_ipi_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 
-memory_region_init_io(>ipi_iocsr_mem, OBJECT(dev), _ipi_ops,
+memory_region_init_i

[PATCH v3 0/4] hw/mips/loongson3_virt: Implement IPI support

2024-06-04 Thread Jiaxun Yang
Hi all,

This series enabled IPI support for loongson3 virt board, loosely
based on my previous work[1].
It generalized loongarch_ipi device to share among both loongarch
and MIPS machines. 

Thanks

[1]: https://lore.kernel.org/all/20230521102307.87081-1-jiaxun.y...@flygoat.com/

To: qemu-devel@nongnu.org
Cc: Song Gao 

Signed-off-by: Jiaxun Yang 
---
Changes in v3:
- Fix up sign off lines.
- Link to v2: 
https://lore.kernel.org/r/20240605-loongson3-ipi-v2-0-da26282e0...@flygoat.com

Changes in v2:
- Add a patch to remove loongarch_ipi.c (Gao)
- Change iocsr alias owner to CPU (philmd)
- New patch to remove ipi_getcpu
- Link to v1: 
https://lore.kernel.org/r/20240508-loongson3-ipi-v1-0-1a7b67704...@flygoat.com

---
Jiaxun Yang (4):
  hw/intc: Remove loongarch_ipi.c
  hw/intc/loongson_ipi: Provide per core MMIO address spaces
  hw/mips/loongson3_virt: Wire up loongson_ipi device
  hw/intc/loongson_ipi: Replace ipi_getcpu with cpu_by_arch_id

 hw/intc/loongarch_ipi.c| 347 -
 hw/intc/loongson_ipi.c | 120 +++---
 hw/mips/Kconfig|   1 +
 hw/mips/loongson3_bootp.c  |   2 -
 hw/mips/loongson3_bootp.h  |   3 +
 hw/mips/loongson3_virt.c   |  39 -
 include/hw/intc/loongson_ipi.h |   2 +
 7 files changed, 108 insertions(+), 406 deletions(-)
---
base-commit: d67a6e054b92e5e1cbb7b0bd5782a670cc7f0df7
change-id: 20240508-loongson3-ipi-65e99b47c400

Best regards,
-- 
Jiaxun Yang 




[PATCH v2 4/4] hw/intc/loongson_ipi: Replace ipi_getcpu with cpu_by_arch_id

2024-06-04 Thread Jiaxun Yang
cpu_by_arch_id is doing the same thing as our ipi_getcpu logic.

Signed-off-by: jiaxun.y...@flygoat.com 
---
 hw/intc/loongson_ipi.c | 39 +++
 1 file changed, 3 insertions(+), 36 deletions(-)

diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c
index c8a25b4eb8e2..b3cda5972793 100644
--- a/hw/intc/loongson_ipi.c
+++ b/hw/intc/loongson_ipi.c
@@ -118,39 +118,6 @@ static MemTxResult send_ipi_data(CPUState *cpu, uint64_t 
val, hwaddr addr,
 return MEMTX_OK;
 }
 
-static int archid_cmp(const void *a, const void *b)
-{
-   CPUArchId *archid_a = (CPUArchId *)a;
-   CPUArchId *archid_b = (CPUArchId *)b;
-
-   return archid_a->arch_id - archid_b->arch_id;
-}
-
-static CPUArchId *find_cpu_by_archid(MachineState *ms, uint32_t id)
-{
-CPUArchId apic_id, *found_cpu;
-
-apic_id.arch_id = id;
-found_cpu = bsearch(_id, ms->possible_cpus->cpus,
-ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus),
-archid_cmp);
-
-return found_cpu;
-}
-
-static CPUState *ipi_getcpu(int arch_id)
-{
-MachineState *machine = MACHINE(qdev_get_machine());
-CPUArchId *archid;
-
-archid = find_cpu_by_archid(machine, arch_id);
-if (archid) {
-return CPU(archid->cpu);
-}
-
-return NULL;
-}
-
 static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs)
 {
 uint32_t cpuid;
@@ -158,7 +125,7 @@ static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs)
 CPUState *cs;
 
 cpuid = extract32(val, 16, 10);
-cs = ipi_getcpu(cpuid);
+cs = cpu_by_arch_id(cpuid);
 if (cs == NULL) {
 return MEMTX_DECODE_ERROR;
 }
@@ -176,7 +143,7 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs attrs)
 CPUState *cs;
 
 cpuid = extract32(val, 16, 10);
-cs = ipi_getcpu(cpuid);
+cs = cpu_by_arch_id(cpuid);
 if (cs == NULL) {
 return MEMTX_DECODE_ERROR;
 }
@@ -227,7 +194,7 @@ static MemTxResult loongson_ipi_core_writel(void *opaque, 
hwaddr addr,
 cpuid = extract32(val, 16, 10);
 /* IPI status vector */
 vector = extract8(val, 0, 5);
-cs = ipi_getcpu(cpuid);
+cs = cpu_by_arch_id(cpuid);
 if (cs == NULL || cs->cpu_index >= ipi->num_cpu) {
 return MEMTX_DECODE_ERROR;
 }

-- 
2.43.0




[PATCH v2 3/4] hw/mips/loongson3_virt: Wire up loongson_ipi device

2024-06-04 Thread Jiaxun Yang
Wire up loongson_ipi device for loongson3_virt machine, so we
can have SMP support for TCG backend as well.

Signed-off-by: Jiaxun Yang 
---
 hw/mips/Kconfig   |  1 +
 hw/mips/loongson3_bootp.c |  2 --
 hw/mips/loongson3_bootp.h |  3 +++
 hw/mips/loongson3_virt.c  | 39 +--
 4 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index a7f26edebe84..692bede538ee 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -67,6 +67,7 @@ config LOONGSON3V
 imply USB_OHCI_PCI
 select SERIAL
 select GOLDFISH_RTC
+select LOONGSON_IPI
 select LOONGSON_LIOINTC
 select PCI_EXPRESS_GENERIC_BRIDGE
 select MSI_NONBROKEN
diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
index 03a10b63c1b4..b97b81903b74 100644
--- a/hw/mips/loongson3_bootp.c
+++ b/hw/mips/loongson3_bootp.c
@@ -25,8 +25,6 @@
 #include "hw/boards.h"
 #include "hw/mips/loongson3_bootp.h"
 
-#define LOONGSON3_CORE_PER_NODE 4
-
 static void init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
 {
 struct efi_cpuinfo_loongson *c = g_cpuinfo;
diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h
index 1b0dd3b59171..9091265df7fc 100644
--- a/hw/mips/loongson3_bootp.h
+++ b/hw/mips/loongson3_bootp.h
@@ -200,6 +200,8 @@ struct boot_params {
 struct efi_reset_system_t reset_system;
 };
 
+#define LOONGSON3_CORE_PER_NODE 4
+
 /* Overall MMIO & Memory layout */
 enum {
 VIRT_LOWMEM,
@@ -211,6 +213,7 @@ enum {
 VIRT_BIOS_ROM,
 VIRT_UART,
 VIRT_LIOINTC,
+VIRT_IPI,
 VIRT_PCIE_MMIO,
 VIRT_HIGHMEM
 };
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index 440268a07430..3a4105228c1d 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -36,6 +36,7 @@
 #include "hw/mips/loongson3_bootp.h"
 #include "hw/misc/unimp.h"
 #include "hw/intc/i8259.h"
+#include "hw/intc/loongson_ipi.h"
 #include "hw/loader.h"
 #include "hw/isa/superio.h"
 #include "hw/pci/msi.h"
@@ -74,6 +75,7 @@ const MemMapEntry virt_memmap[] = {
 [VIRT_PCIE_ECAM] =   { 0x1a00, 0x200 },
 [VIRT_BIOS_ROM] ={ 0x1fc0,  0x20 },
 [VIRT_UART] ={ 0x1fe001e0,   0x8 },
+[VIRT_IPI] = { 0x3ff01000, 0x400 },
 [VIRT_LIOINTC] = { 0x3ff01400,  0x64 },
 [VIRT_PCIE_MMIO] =   { 0x4000,0x4000 },
 [VIRT_HIGHMEM] = { 0x8000,   0x0 }, /* Variable */
@@ -485,6 +487,7 @@ static void mips_loongson3_virt_init(MachineState *machine)
 Clock *cpuclk;
 CPUMIPSState *env;
 DeviceState *liointc;
+DeviceState *ipi = NULL;
 char *filename;
 const char *kernel_cmdline = machine->kernel_cmdline;
 const char *kernel_filename = machine->kernel_filename;
@@ -494,6 +497,7 @@ static void mips_loongson3_virt_init(MachineState *machine)
 MemoryRegion *ram = g_new(MemoryRegion, 1);
 MemoryRegion *bios = g_new(MemoryRegion, 1);
 MemoryRegion *iomem = g_new(MemoryRegion, 1);
+MemoryRegion *iocsr = g_new(MemoryRegion, 1);
 
 /* TODO: TCG will support all CPU types */
 if (!kvm_enabled()) {
@@ -527,6 +531,19 @@ static void mips_loongson3_virt_init(MachineState *machine)
 create_unimplemented_device("mmio fallback 0", 0x1000, 256 * MiB);
 create_unimplemented_device("mmio fallback 1", 0x3000, 256 * MiB);
 
+memory_region_init(iocsr, OBJECT(machine), "loongson3.iocsr", UINT32_MAX);
+
+/* IPI controller is in kernel for KVM */
+if (!kvm_enabled()) {
+ipi = qdev_new(TYPE_LOONGSON_IPI);
+qdev_prop_set_uint32(ipi, "num-cpu", machine->smp.cpus);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), _fatal);
+memory_region_add_subregion(iocsr, SMP_IPI_MAILBOX,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 0));
+memory_region_add_subregion(iocsr, MAIL_SEND_ADDR,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1));
+}
+
 liointc = qdev_new("loongson.liointc");
 sysbus_realize_and_unref(SYS_BUS_DEVICE(liointc), _fatal);
 
@@ -543,6 +560,8 @@ static void mips_loongson3_virt_init(MachineState *machine)
 clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ);
 
 for (i = 0; i < machine->smp.cpus; i++) {
+int node = i / LOONGSON3_CORE_PER_NODE;
+int core = i % LOONGSON3_CORE_PER_NODE;
 int ip;
 
 /* init CPUs */
@@ -553,12 +572,28 @@ static void mips_loongson3_virt_init(MachineState 
*machine)
 cpu_mips_clock_init(cpu);
 qemu_register_reset(main_cpu_reset, cpu);
 
-if (i >= 4) {
+if (ipi) {
+hwaddr base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base;
+base += core * 0x100;
+qdev_connect_gpio_out(ipi, i, cpu->env.irq[6]);
+sysbu

[PATCH v2 2/4] hw/intc/loongson_ipi: Provide per core MMIO address spaces

2024-06-04 Thread Jiaxun Yang
The real IPI hardware have dedicated MMIO registers mapped into
memory address space for every core. This is not used by LoongArch
guest software but it is essential for CPU without IOCSR such as
Loongson-3A1000.

Implement it with existing infrastructure.

Acked-by: Song Gao 
Signed-off-by: Jiaxun Yang 
---
 hw/intc/loongson_ipi.c | 81 --
 include/hw/intc/loongson_ipi.h |  2 ++
 2 files changed, 64 insertions(+), 19 deletions(-)

diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c
index 93cc50a37a11..c8a25b4eb8e2 100644
--- a/hw/intc/loongson_ipi.c
+++ b/hw/intc/loongson_ipi.c
@@ -23,16 +23,14 @@
 #endif
 #include "trace.h"
 
-static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr,
+static MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr,
uint64_t *data,
unsigned size, MemTxAttrs attrs)
 {
-IPICore *s;
-LoongsonIPI *ipi = opaque;
+IPICore *s = opaque;
 uint64_t ret = 0;
 int index = 0;
 
-s = >cpu[attrs.requester_id];
 addr &= 0xff;
 switch (addr) {
 case CORE_STATUS_OFF:
@@ -61,6 +59,21 @@ static MemTxResult loongson_ipi_readl(void *opaque, hwaddr 
addr,
 return MEMTX_OK;
 }
 
+static MemTxResult loongson_ipi_iocsr_readl(void *opaque, hwaddr addr,
+   uint64_t *data,
+   unsigned size, MemTxAttrs attrs)
+{
+LoongsonIPI *ipi = opaque;
+IPICore *s;
+
+if (attrs.requester_id >= ipi->num_cpu) {
+return MEMTX_DECODE_ERROR;
+}
+
+s = >cpu[attrs.requester_id];
+return loongson_ipi_core_readl(s, addr, data, size, attrs);
+}
+
 static AddressSpace *get_cpu_iocsr_as(CPUState *cpu)
 {
 #ifdef TARGET_LOONGARCH64
@@ -174,17 +187,17 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs 
attrs)
 return send_ipi_data(cs, val, addr, attrs);
 }
 
-static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
-unsigned size, MemTxAttrs attrs)
+static MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr,
+uint64_t val, unsigned size,
+MemTxAttrs attrs)
 {
-LoongsonIPI *ipi = opaque;
-IPICore *s;
+IPICore *s = opaque;
+LoongsonIPI *ipi = s->ipi;
 int index = 0;
 uint32_t cpuid;
 uint8_t vector;
 CPUState *cs;
 
-s = >cpu[attrs.requester_id];
 addr &= 0xff;
 trace_loongson_ipi_write(size, (uint64_t)addr, val);
 switch (addr) {
@@ -215,13 +228,11 @@ static MemTxResult loongson_ipi_writel(void *opaque, 
hwaddr addr, uint64_t val,
 /* IPI status vector */
 vector = extract8(val, 0, 5);
 cs = ipi_getcpu(cpuid);
-if (cs == NULL) {
+if (cs == NULL || cs->cpu_index >= ipi->num_cpu) {
 return MEMTX_DECODE_ERROR;
 }
-
-/* override requester_id */
-attrs.requester_id = cs->cpu_index;
-loongson_ipi_writel(ipi, CORE_SET_OFF, BIT(vector), 4, attrs);
+loongson_ipi_core_writel(>cpu[cs->cpu_index], CORE_SET_OFF,
+ BIT(vector), 4, attrs);
 break;
 default:
 qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr);
@@ -231,9 +242,34 @@ static MemTxResult loongson_ipi_writel(void *opaque, 
hwaddr addr, uint64_t val,
 return MEMTX_OK;
 }
 
-static const MemoryRegionOps loongson_ipi_ops = {
-.read_with_attrs = loongson_ipi_readl,
-.write_with_attrs = loongson_ipi_writel,
+static MemTxResult loongson_ipi_iocsr_writel(void *opaque, hwaddr addr,
+uint64_t val, unsigned size,
+MemTxAttrs attrs)
+{
+LoongsonIPI *ipi = opaque;
+IPICore *s;
+
+if (attrs.requester_id >= ipi->num_cpu) {
+return MEMTX_DECODE_ERROR;
+}
+
+s = >cpu[attrs.requester_id];
+return loongson_ipi_core_writel(s, addr, val, size, attrs);
+}
+
+static const MemoryRegionOps loongson_ipi_core_ops = {
+.read_with_attrs = loongson_ipi_core_readl,
+.write_with_attrs = loongson_ipi_core_writel,
+.impl.min_access_size = 4,
+.impl.max_access_size = 4,
+.valid.min_access_size = 4,
+.valid.max_access_size = 8,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static const MemoryRegionOps loongson_ipi_iocsr_ops = {
+.read_with_attrs = loongson_ipi_iocsr_readl,
+.write_with_attrs = loongson_ipi_iocsr_writel,
 .impl.min_access_size = 4,
 .impl.max_access_size = 4,
 .valid.min_access_size = 4,
@@ -282,7 +318,7 @@ static void loongson_ipi_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 
-memory_region_init_io(>ipi_iocsr_mem, OBJECT(dev), _ipi_ops,
+memory_region_init_i

[PATCH v2 1/4] hw/intc: Remove loongarch_ipi.c

2024-06-04 Thread Jiaxun Yang
It was missed out in previous commit.

Fixes: b4a12dfc2132 ("hw/intc/loongarch_ipi: Rename as loongson_ipi")
Signed-off-by: jiaxun.y...@flygoat.com 
---
 hw/intc/loongarch_ipi.c | 347 
 1 file changed, 347 deletions(-)

diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
deleted file mode 100644
index 44b3b9c138d6..
--- a/hw/intc/loongarch_ipi.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * LoongArch ipi interrupt support
- *
- * Copyright (C) 2021 Loongson Technology Corporation Limited
- */
-
-#include "qemu/osdep.h"
-#include "hw/boards.h"
-#include "hw/sysbus.h"
-#include "hw/intc/loongarch_ipi.h"
-#include "hw/irq.h"
-#include "hw/qdev-properties.h"
-#include "qapi/error.h"
-#include "qemu/log.h"
-#include "exec/address-spaces.h"
-#include "migration/vmstate.h"
-#include "target/loongarch/cpu.h"
-#include "trace.h"
-
-static MemTxResult loongarch_ipi_readl(void *opaque, hwaddr addr,
-   uint64_t *data,
-   unsigned size, MemTxAttrs attrs)
-{
-IPICore *s;
-LoongArchIPI *ipi = opaque;
-uint64_t ret = 0;
-int index = 0;
-
-s = >cpu[attrs.requester_id];
-addr &= 0xff;
-switch (addr) {
-case CORE_STATUS_OFF:
-ret = s->status;
-break;
-case CORE_EN_OFF:
-ret = s->en;
-break;
-case CORE_SET_OFF:
-ret = 0;
-break;
-case CORE_CLEAR_OFF:
-ret = 0;
-break;
-case CORE_BUF_20 ... CORE_BUF_38 + 4:
-index = (addr - CORE_BUF_20) >> 2;
-ret = s->buf[index];
-break;
-default:
-qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr);
-break;
-}
-
-trace_loongarch_ipi_read(size, (uint64_t)addr, ret);
-*data = ret;
-return MEMTX_OK;
-}
-
-static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr,
-  MemTxAttrs attrs)
-{
-int i, mask = 0, data = 0;
-
-/*
- * bit 27-30 is mask for byte writing,
- * if the mask is 0, we need not to do anything.
- */
-if ((val >> 27) & 0xf) {
-data = address_space_ldl(env->address_space_iocsr, addr,
- attrs, NULL);
-for (i = 0; i < 4; i++) {
-/* get mask for byte writing */
-if (val & (0x1 << (27 + i))) {
-mask |= 0xff << (i * 8);
-}
-}
-}
-
-data &= mask;
-data |= (val >> 32) & ~mask;
-address_space_stl(env->address_space_iocsr, addr,
-  data, attrs, NULL);
-}
-
-static int archid_cmp(const void *a, const void *b)
-{
-   CPUArchId *archid_a = (CPUArchId *)a;
-   CPUArchId *archid_b = (CPUArchId *)b;
-
-   return archid_a->arch_id - archid_b->arch_id;
-}
-
-static CPUArchId *find_cpu_by_archid(MachineState *ms, uint32_t id)
-{
-CPUArchId apic_id, *found_cpu;
-
-apic_id.arch_id = id;
-found_cpu = bsearch(_id, ms->possible_cpus->cpus,
-ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus),
-archid_cmp);
-
-return found_cpu;
-}
-
-static CPUState *ipi_getcpu(int arch_id)
-{
-MachineState *machine = MACHINE(qdev_get_machine());
-CPUArchId *archid;
-
-archid = find_cpu_by_archid(machine, arch_id);
-if (archid) {
-return CPU(archid->cpu);
-}
-
-return NULL;
-}
-
-static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs)
-{
-uint32_t cpuid;
-hwaddr addr;
-CPUState *cs;
-
-cpuid = extract32(val, 16, 10);
-cs = ipi_getcpu(cpuid);
-if (cs == NULL) {
-return MEMTX_DECODE_ERROR;
-}
-
-/* override requester_id */
-addr = SMP_IPI_MAILBOX + CORE_BUF_20 + (val & 0x1c);
-attrs.requester_id = cs->cpu_index;
-send_ipi_data(_CPU(cs)->env, val, addr, attrs);
-return MEMTX_OK;
-}
-
-static MemTxResult any_send(uint64_t val, MemTxAttrs attrs)
-{
-uint32_t cpuid;
-hwaddr addr;
-CPUState *cs;
-
-cpuid = extract32(val, 16, 10);
-cs = ipi_getcpu(cpuid);
-if (cs == NULL) {
-return MEMTX_DECODE_ERROR;
-}
-
-/* override requester_id */
-addr = val & 0x;
-attrs.requester_id = cs->cpu_index;
-send_ipi_data(_CPU(cs)->env, val, addr, attrs);
-return MEMTX_OK;
-}
-
-static MemTxResult loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t 
val,
-unsigned size, MemTxAttrs attrs)
-{
-LoongArchIPI *ipi = opaque;
-IPICore *s;
-int index = 0;
-uint32_t cpuid;
-uint8_t vector;
-CPUState *cs;
-
-s = >cpu[attrs.requester_id];
-addr &= 0xff;
-trace_loongarch_ipi_write(size, (uint64_t)addr, val);
-switch (addr) {
-case CORE_STATUS_OFF:
-qemu_log_mask(LOG_GUEST_ERROR, "can not be written");
-break;
-case CORE_EN_OFF:
-s->en = val;
-break;
-case CORE_SET_OFF:
-

[PATCH v2 0/4] hw/mips/loongson3_virt: Implement IPI support

2024-06-04 Thread Jiaxun Yang
Hi all,

This series enabled IPI support for loongson3 virt board, loosely
based on my previous work[1].
It generalized loongarch_ipi device to share among both loongarch
and MIPS machines. 

Thanks

[1]: https://lore.kernel.org/all/20230521102307.87081-1-jiaxun.y...@flygoat.com/

To: qemu-devel@nongnu.org
Cc: Song Gao 

Signed-off-by: Jiaxun Yang 
---
Changes in v2:
- Add a patch to remove loongarch_ipi.c (Gao)
- Change iocsr alias owner to CPU (philmd)
- New patch to remove ipi_getcpu
- Link to v1: 
https://lore.kernel.org/r/20240508-loongson3-ipi-v1-0-1a7b67704...@flygoat.com

---
Jiaxun Yang (4):
  hw/intc: Remove loongarch_ipi.c
  hw/intc/loongson_ipi: Provide per core MMIO address spaces
  hw/mips/loongson3_virt: Wire up loongson_ipi device
  hw/intc/loongson_ipi: Replace ipi_getcpu with cpu_by_arch_id

 hw/intc/loongarch_ipi.c| 347 -
 hw/intc/loongson_ipi.c | 120 +++---
 hw/mips/Kconfig|   1 +
 hw/mips/loongson3_bootp.c  |   2 -
 hw/mips/loongson3_bootp.h  |   3 +
 hw/mips/loongson3_virt.c   |  39 -
 include/hw/intc/loongson_ipi.h |   2 +
 7 files changed, 108 insertions(+), 406 deletions(-)
---
base-commit: d67a6e054b92e5e1cbb7b0bd5782a670cc7f0df7
change-id: 20240508-loongson3-ipi-65e99b47c400

Best regards,
-- 
Jiaxun Yang 




Re: [PATCH 3/5] hw/intc/loongson_ipi: Implement IOCSR address space for MIPS

2024-06-04 Thread Jiaxun Yang



在2024年6月3日六月 下午4:45,Philippe Mathieu-Daudé写道:
[...]
>
> LoongsonIPI should have an array of CPUState[] and MemoryRegion[].
> (Or maybe add them to IPICore.)
> Expose them as QOM link properties.
>
> Caller wire them while creating the LoongsonIPI.
> Then loongson_ipi_realize() resolves them once.
> No need to call get_cpu_iocsr_as() and ipi_getcpu() for each MMIO
> access IMO.

I was tempted to do so but realized that arch_id might be discontinuous
for LoongArch.

@Song, can you confirm if it's viable?

Thanks
- Jiaxun
>
>> +
>> +if (!iocsr_as) {
>> +return MEMTX_DECODE_ERROR;
>> +}

-- 
- Jiaxun



Re: [PATCH] mips64el-softmmu: Enable MTTCG

2024-06-04 Thread Jiaxun Yang



在2024年6月3日六月 下午7:15,Pierrick Bouvier写道:
> On 5/11/24 13:26, Jiaxun Yang wrote:
>> MTTCG was disabled in a092a9554771 ("configure: disable MTTCG
>> for MIPS guests") due to test case instability.
>> 
>> I was able to reproduce this issue with in latest QEMU and look
>> into reason behind that.
>> 
>> What actually happend is kernel's CP0 timer synchronisation
>> mechanism assumed a consistent latency in memory access between
>> cores, which TCG can't guarantee. Thus there is a huge drift in
>> count value between cores, and in early kernel versions CP0 timer
>> is always used as sched_clock.
>> 
>> sched_clock drift back on some cores triggered RCU watchdog in
>> some extreme cases.
>> 
>> This can be resolved by setting clocksource to MIPS, which allows
>> clocksource to drift together with sched_clock. However this will
>> leed to other problems after boot.
>> 
>> Another option would beupdating kernel to later version, which
>> will use GIC as sched_clock.
>> 
>> In non-MTTCG build, the execution is slow enough so kernel won't
>> observe back drifts.
>> 
>> Test results:
>> 
>> With clocksource=MIPS
>> ```
>>   ~/tmp/retry/retry.py -n 100 -c -- ./qemu-system-mips64el \
>>  -display none -vga none -serial mon:stdio \
>>  -machine malta -kernel ./vmlinux-4.7.0-rc1.I6400 \
>>  -cpu I6400 -smp 8 -vga std \
>>  -append "printk.time=0 clocksource=MIPS console=tty0 console=ttyS0 
>> panic=-1" \
>>  --no-reboot
>> 
>> 100, 0, PASS, 5.258126, 100, 100, -
>> Results summary:
>> 0: 100 times (100.00%), avg time 6.508 (55.53 varience/7.45 deviation)
>> Ran command 100 times, 100 passes
>> ```
>> 
>> With linux-next:
>> ```
>>   ~/tmp/retry/retry.py -n 100 -c -- ./qemu-system-mips64el \
>>  -display none -vga none -serial mon:stdio \
>>  -machine malta -kernel ~/linux-next/vmlinux \
>>  -cpu I6400 -smp 8 -vga std \
>>  -append "printk.time=0 console=tty0 console=ttyS0 panic=-1" \
>>  --no-reboot
>> 
>> 100, 0, PASS, 4.507921, 100, 100, -
>> Results summary:
>> 0: 100 times (100.00%), avg time 4.233 (0.04 varience/0.21 deviation)
>> Ran command 100 times, 100 passes
>> ```
>> 
>> Signed-off-by: Jiaxun Yang 
>> ---
>> I'll leave the test case alone as it's already marked as 
>> QEMU_TEST_FLAKY_TESTS
>> ---
>>   configs/targets/mips64el-softmmu.mak | 1 +
>>   1 file changed, 1 insertion(+)
>> 
>> diff --git a/configs/targets/mips64el-softmmu.mak 
>> b/configs/targets/mips64el-softmmu.mak
>> index 8d9ab3ddc4b1..199b1d909a7d 100644
>> --- a/configs/targets/mips64el-softmmu.mak
>> +++ b/configs/targets/mips64el-softmmu.mak
>> @@ -1,3 +1,4 @@
>>   TARGET_ARCH=mips64
>>   TARGET_BASE_ARCH=mips
>> +TARGET_SUPPORTS_MTTCG=y
>>   TARGET_NEED_FDT=y
>> 
>> ---
>> base-commit: 248f6f62df073a3b4158fd0093863ab885feabb5
>> change-id: 20240511-mips_mttcg-47a6b19074b3
>> 
>> Best regards,
>
> Hi Jiaxun,
> Thanks for your analysis!
>
> We should see to update concerned test in another series.
> I'm not sure which way is preferred between updating kernel used or 
> changing current command line.
>
> Reviewed-by: Pierrick Bouvier 

I think updating kernel can prevent further problems.
Will test with latest Debian kernel.

Thanks!
-- 
- Jiaxun



Re: tests/avocado: Add LoongArch machine start test

2024-05-30 Thread Jiaxun Yang



在2024年5月31日五月 上午2:52,gaosong写道:
> 在 2024/5/30 下午9:16, Jiaxun Yang 写道:
>>
>> 在2024年5月30日五月 下午2:00,gaosong写道:
>> [...]
>>>> FYI, the test does not seem to work anymore - apparently the binaries
>>>> have changed and now the hashes do not match anymore. Could you please
>>>> update it? (preferably with some versioned binaries that do not change
>>>> in the course of time?)
>>>>
>>> Thank you,  I had send a patch to fix it.
>> Hi Song,
>>
>> As LoongArch EDK2 support has been merged long ago, do you to make a clean
>> build and add it to pc-bios directory?
> EDK2 LoongArchVirt under OvmfPkg is being committed to upstream.
>
> PR:
> https://github.com/tianocore/edk2/pull/5208

I meant here:

https://gitlab.com/qemu-project/qemu/-/tree/master/pc-bios?ref_type=heads

Thanks
>
> Thanks
> Song Gao
>>
>> Thanks
>> - Jiaxun

-- 
- Jiaxun



Re: tests/avocado: Add LoongArch machine start test

2024-05-30 Thread Jiaxun Yang



在2024年5月30日五月 下午2:00,gaosong写道:
[...]
>> FYI, the test does not seem to work anymore - apparently the binaries 
>> have changed and now the hashes do not match anymore. Could you please 
>> update it? (preferably with some versioned binaries that do not change 
>> in the course of time?)
>>
> Thank you,  I had send a patch to fix it.

Hi Song,

As LoongArch EDK2 support has been merged long ago, do you to make a clean
build and add it to pc-bios directory?

Thanks
- Jiaxun

>
> Thanks.
> Song Gao

-- 
- Jiaxun



Re: [PATCH] target/mips: Remove unused 'hw/misc/mips_itu.h' header

2024-05-29 Thread Jiaxun Yang



在2024年5月29日五月 下午4:52,Philippe Mathieu-Daudé写道:
> Since commit e1152f8166 ("target/mips: Remove helpers accessing
> SAAR registers") this header is not needed.
>
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Jiaxun Yang 

> ---
>  target/mips/tcg/sysemu/cp0_helper.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/target/mips/tcg/sysemu/cp0_helper.c 
> b/target/mips/tcg/sysemu/cp0_helper.c
> index ded6c78e9a..79a5c833ce 100644
> --- a/target/mips/tcg/sysemu/cp0_helper.c
> +++ b/target/mips/tcg/sysemu/cp0_helper.c
> @@ -28,7 +28,6 @@
>  #include "qemu/host-utils.h"
>  #include "exec/helper-proto.h"
>  #include "exec/exec-all.h"
> -#include "hw/misc/mips_itu.h"
> 
> 
>  /* SMP helpers.  */
> -- 
> 2.41.0

-- 
- Jiaxun



[PATCH 2/4] hw/m68k/virt: Add fw_cfg controller

2024-05-27 Thread Jiaxun Yang
Add a fw_cfg controller to pass essential information
to firmware.

Signed-off-by: Jiaxun Yang 
---
 hw/m68k/Kconfig   |  1 +
 hw/m68k/virt.c| 25 ++-
 include/standard-headers/asm-m68k/bootinfo-virt.h |  1 +
 3 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig
index 66e63cd60b57..4501da56ff6d 100644
--- a/hw/m68k/Kconfig
+++ b/hw/m68k/Kconfig
@@ -40,6 +40,7 @@ config M68K_VIRT
 default y
 depends on M68K
 select M68K_IRQC
+select FW_CFG_DMA
 select VIRT_CTRL
 select GOLDFISH_PIC
 select GOLDFISH_TTY
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index 7b3917dcbd2b..7590e6515ac3 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -42,7 +42,8 @@
  * CPU IRQ #1 -> PIC #1
  *   IRQ #1 -> virt-ctrl
  *   IRQ #2 -> xhci
- *   IRQ #3 to IRQ #31 -> unused
+ *   IRQ #3 -> fw_cfg
+ *   IRQ #4 to IRQ #31 -> unused
  *   IRQ #32 -> goldfish-tty
  * CPU IRQ #2 -> PIC #2
  *   IRQ #1 to IRQ #32 -> virtio-mmio from 1 to 32
@@ -80,6 +81,10 @@
 #define VIRT_CTRL_MMIO_BASE 0xff009000/* MMIO: 0xff009000 - 0xff009fff */
 #define VIRT_CTRL_IRQ_BASE  PIC_IRQ(1, 1) /* PIC: #1, IRQ: #1 */
 
+/* 1 fw_cfg */
+#define VIRT_FW_CFG_MMIO_BASE 0xff00a000/* MMIO: 0xff00a000 - 0xff00afff */
+#define VIRT_FW_CFG_IRQ_BASE  PIC_IRQ(1, 3) /* PIC: #1, IRQ: #3 */
+
 /*
  * virtio-mmio size is 0x200 bytes
  * we use 4 goldfish-pic to attach them,
@@ -116,6 +121,12 @@ static void rerandomize_rng_seed(void *opaque)
 be16_to_cpu(*(uint16_t *)rng_seed->data));
 }
 
+static void fw_cfg_boot_set(void *opaque, const char *boot_device,
+Error **errp)
+{
+fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
+}
+
 static void virt_init(MachineState *machine)
 {
 M68kCPU *cpu = NULL;
@@ -134,6 +145,7 @@ static void virt_init(MachineState *machine)
 SysBusDevice *sysbus;
 hwaddr io_base;
 int i;
+FWCfgState *fw_cfg;
 ResetInfo *reset_info;
 uint8_t rng_seed[32];
 
@@ -210,6 +222,15 @@ static void virt_init(MachineState *machine)
 dev = sysbus_create_simple(TYPE_VIRT_CTRL, VIRT_CTRL_MMIO_BASE,
PIC_GPIO(VIRT_CTRL_IRQ_BASE));
 
+/* fw_cfg */
+fw_cfg = fw_cfg_init_mem_wide(VIRT_FW_CFG_MMIO_BASE + 8,
+  VIRT_FW_CFG_MMIO_BASE, 8,
+  VIRT_FW_CFG_MMIO_BASE + 16,
+  _space_memory);
+fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
+qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
+rom_set_fw(fw_cfg);
+
 /* virtio-mmio */
 io_base = VIRT_VIRTIO_MMIO_BASE;
 for (i = 0; i < 128; i++) {
@@ -288,6 +309,8 @@ static void virt_init(MachineState *machine)
 BOOTINFO2(param_ptr, BI_VIRT_XHCI_BASE,
 VIRT_XHCI_MMIO_BASE, VIRT_XHCI_IRQ_BASE);
 }
+BOOTINFO2(param_ptr, BI_VIRT_FW_CFG_BASE,
+  VIRT_FW_CFG_MMIO_BASE, VIRT_FW_CFG_IRQ_BASE);
 
 if (kernel_cmdline) {
 BOOTINFOSTR(param_ptr, BI_COMMAND_LINE,
diff --git a/include/standard-headers/asm-m68k/bootinfo-virt.h 
b/include/standard-headers/asm-m68k/bootinfo-virt.h
index 1700c3ada765..7f90be1aa7bd 100644
--- a/include/standard-headers/asm-m68k/bootinfo-virt.h
+++ b/include/standard-headers/asm-m68k/bootinfo-virt.h
@@ -17,6 +17,7 @@
  * #define BI_VIRT_RNG_SEED0x8006 */
 
 #define BI_VIRT_XHCI_BASE  0x8007
+#define BI_VIRT_FW_CFG_BASE0x8008
 
 #define VIRT_BOOTI_VERSION MK_BI_VERSION(2, 0)
 

-- 
2.43.0




[PATCH 3/4] hw/m68k/virt: Add a pflash controller for BIOS firmware

2024-05-27 Thread Jiaxun Yang
Add a 8 MiB pflash controller for BIOS firmware, and boot
from it if possible.

Signed-off-by: Jiaxun Yang 
---
 hw/m68k/Kconfig   |  1 +
 hw/m68k/virt.c| 44 +++
 include/standard-headers/asm-m68k/bootinfo-virt.h |  1 +
 3 files changed, 46 insertions(+)

diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig
index 4501da56ff6d..f233a5948f19 100644
--- a/hw/m68k/Kconfig
+++ b/hw/m68k/Kconfig
@@ -42,6 +42,7 @@ config M68K_VIRT
 select M68K_IRQC
 select FW_CFG_DMA
 select VIRT_CTRL
+select PFLASH_CFI01
 select GOLDFISH_PIC
 select GOLDFISH_TTY
 select GOLDFISH_RTC
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index 7590e6515ac3..a2eebc0f2243 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -8,6 +8,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/datadir.h"
 #include "qemu/units.h"
 #include "qemu/guest-random.h"
 #include "sysemu/sysemu.h"
@@ -28,6 +29,7 @@
 #include "sysemu/runstate.h"
 #include "sysemu/reset.h"
 
+#include "hw/block/flash.h"
 #include "hw/intc/m68k_irqc.h"
 #include "hw/misc/virt_ctrl.h"
 #include "hw/char/goldfish_tty.h"
@@ -97,6 +99,10 @@
 #define VIRT_XHCI_MMIO_BASE 0xff02/* MMIO: 0xff02 - 0xff023fff */
 #define VIRT_XHCI_IRQ_BASE  PIC_IRQ(1, 2) /* PIC: #1, IRQ: #2 */
 
+#define VIRT_PFLASH_MMIO_BASE 0xff80  /* MMIO: 0xff80 - 0x 
*/
+#define VIRT_PFLASH_SIZE  0x80/* 8 MiB */
+#define VIRT_PFLASH_SECTOR_SIZE (128 * KiB)   /* 64 KiB */
+
 typedef struct {
 M68kCPU *cpu;
 hwaddr initial_pc;
@@ -139,6 +145,7 @@ static void virt_init(MachineState *machine)
 const char *initrd_filename = machine->initrd_filename;
 const char *kernel_cmdline = machine->kernel_cmdline;
 hwaddr parameters_base;
+DriveInfo *dinfo;
 DeviceState *dev;
 DeviceState *irqc_dev;
 DeviceState *pic_dev[VIRT_GF_PIC_NB];
@@ -165,6 +172,8 @@ static void virt_init(MachineState *machine)
 cpu = M68K_CPU(cpu_create(machine->cpu_type));
 
 reset_info->cpu = cpu;
+reset_info->initial_pc = VIRT_PFLASH_MMIO_BASE;
+reset_info->initial_stack = ram_size;
 qemu_register_reset(main_cpu_reset, reset_info);
 
 /* RAM */
@@ -253,6 +262,39 @@ static void virt_init(MachineState *machine)
 PIC_GPIO(VIRT_XHCI_IRQ_BASE));
 }
 
+/* pflash */
+dinfo = drive_get(IF_PFLASH, 0, 0);
+pflash_cfi01_register(VIRT_PFLASH_MMIO_BASE,
+  "virt.pflash0",
+   VIRT_PFLASH_SIZE,
+   dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
+   VIRT_PFLASH_SECTOR_SIZE, 4,
+   0x89, 0x18, 0, 0, 1);
+
+if (machine->firmware) {
+char *fn;
+int image_size;
+
+if (drive_get(IF_PFLASH, 0, 0)) {
+error_report("The contents of the first flash device may be "
+ "specified with -bios or with -drive if=pflash... "
+ "but you cannot use both options at once");
+exit(1);
+}
+fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware);
+if (!fn) {
+error_report("Could not find ROM image '%s'", machine->firmware);
+exit(1);
+}
+image_size = load_image_targphys(fn, VIRT_PFLASH_MMIO_BASE,
+ VIRT_PFLASH_SIZE);
+g_free(fn);
+if (image_size < 0) {
+error_report("Could not load ROM image '%s'", machine->firmware);
+exit(1);
+}
+}
+
 if (kernel_filename) {
 CPUState *cs = CPU(cpu);
 uint64_t high;
@@ -311,6 +353,8 @@ static void virt_init(MachineState *machine)
 }
 BOOTINFO2(param_ptr, BI_VIRT_FW_CFG_BASE,
   VIRT_FW_CFG_MMIO_BASE, VIRT_FW_CFG_IRQ_BASE);
+BOOTINFO2(param_ptr, BI_VIRT_PFLASH_BASE,
+VIRT_PFLASH_MMIO_BASE, 0);
 
 if (kernel_cmdline) {
 BOOTINFOSTR(param_ptr, BI_COMMAND_LINE,
diff --git a/include/standard-headers/asm-m68k/bootinfo-virt.h 
b/include/standard-headers/asm-m68k/bootinfo-virt.h
index 7f90be1aa7bd..21c9a98d2912 100644
--- a/include/standard-headers/asm-m68k/bootinfo-virt.h
+++ b/include/standard-headers/asm-m68k/bootinfo-virt.h
@@ -18,6 +18,7 @@
 
 #define BI_VIRT_XHCI_BASE  0x8007
 #define BI_VIRT_FW_CFG_BASE0x8008
+#define BI_VIRT_PFLASH_BASE0x8009
 
 #define VIRT_BOOTI_VERSION MK_BI_VERSION(2, 0)
 

-- 
2.43.0




[PATCH 1/4] hw/m68k/virt: Add a XHCI controller

2024-05-27 Thread Jiaxun Yang
VirtIO is somewhat limited on the diversity of devices.
We lack proper audio, webcam and so on support on m68k virt machine.

This can be improved by providing a XHCI controller, which enables
provision of many different discoverable devices.

Signed-off-by: Jiaxun Yang 
---
 hw/m68k/Kconfig   |  1 +
 hw/m68k/virt.c| 22 +-
 include/standard-headers/asm-m68k/bootinfo-virt.h |  2 ++
 3 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig
index 0092cda4e9c8..66e63cd60b57 100644
--- a/hw/m68k/Kconfig
+++ b/hw/m68k/Kconfig
@@ -44,4 +44,5 @@ config M68K_VIRT
 select GOLDFISH_PIC
 select GOLDFISH_TTY
 select GOLDFISH_RTC
+select USB_XHCI_SYSBUS
 select VIRTIO_MMIO
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index 09bc9bdfefb2..7b3917dcbd2b 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -33,13 +33,16 @@
 #include "hw/char/goldfish_tty.h"
 #include "hw/rtc/goldfish_rtc.h"
 #include "hw/intc/goldfish_pic.h"
+#include "hw/usb/hcd-xhci-sysbus.h"
 #include "hw/virtio/virtio-mmio.h"
 #include "hw/virtio/virtio-blk.h"
 
 /*
  * 6 goldfish-pic for CPU IRQ #1 to IRQ #6
  * CPU IRQ #1 -> PIC #1
- *   IRQ #1 to IRQ #31 -> unused
+ *   IRQ #1 -> virt-ctrl
+ *   IRQ #2 -> xhci
+ *   IRQ #3 to IRQ #31 -> unused
  *   IRQ #32 -> goldfish-tty
  * CPU IRQ #2 -> PIC #2
  *   IRQ #1 to IRQ #32 -> virtio-mmio from 1 to 32
@@ -86,6 +89,9 @@
 #define VIRT_VIRTIO_MMIO_BASE 0xff01 /* MMIO: 0xff01 - 0xff01 
*/
 #define VIRT_VIRTIO_IRQ_BASE  PIC_IRQ(2, 1)  /* PIC: 2, 3, 4, 5, IRQ: ALL */
 
+#define VIRT_XHCI_MMIO_BASE 0xff02/* MMIO: 0xff02 - 0xff023fff */
+#define VIRT_XHCI_IRQ_BASE  PIC_IRQ(1, 2) /* PIC: #1, IRQ: #2 */
+
 typedef struct {
 M68kCPU *cpu;
 hwaddr initial_pc;
@@ -216,6 +222,16 @@ static void virt_init(MachineState *machine)
 io_base += 0x200;
 }
 
+/* xhci */
+if (machine_usb(machine)) {
+dev = qdev_new(TYPE_XHCI_SYSBUS);
+qdev_prop_set_uint32(dev, "intrs", 1);
+sysbus_realize(SYS_BUS_DEVICE(dev), _fatal);
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, VIRT_XHCI_MMIO_BASE);
+sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
+PIC_GPIO(VIRT_XHCI_IRQ_BASE));
+}
+
 if (kernel_filename) {
 CPUState *cs = CPU(cpu);
 uint64_t high;
@@ -268,6 +284,10 @@ static void virt_init(MachineState *machine)
   VIRT_CTRL_MMIO_BASE, VIRT_CTRL_IRQ_BASE);
 BOOTINFO2(param_ptr, BI_VIRT_VIRTIO_BASE,
   VIRT_VIRTIO_MMIO_BASE, VIRT_VIRTIO_IRQ_BASE);
+if (machine_usb(machine)) {
+BOOTINFO2(param_ptr, BI_VIRT_XHCI_BASE,
+VIRT_XHCI_MMIO_BASE, VIRT_XHCI_IRQ_BASE);
+}
 
 if (kernel_cmdline) {
 BOOTINFOSTR(param_ptr, BI_COMMAND_LINE,
diff --git a/include/standard-headers/asm-m68k/bootinfo-virt.h 
b/include/standard-headers/asm-m68k/bootinfo-virt.h
index 75ac6bbd7d73..1700c3ada765 100644
--- a/include/standard-headers/asm-m68k/bootinfo-virt.h
+++ b/include/standard-headers/asm-m68k/bootinfo-virt.h
@@ -16,6 +16,8 @@
 /* No longer used -- replaced with BI_RNG_SEED -- but don't reuse this index:
  * #define BI_VIRT_RNG_SEED0x8006 */
 
+#define BI_VIRT_XHCI_BASE  0x8007
+
 #define VIRT_BOOTI_VERSION MK_BI_VERSION(2, 0)
 
 #endif /* _UAPI_ASM_M68K_BOOTINFO_MAC_H */

-- 
2.43.0




[PATCH 0/4] hw/m68k/virt: Add some devices

2024-05-27 Thread Jiaxun Yang
Hi all,

This series added some devices that I found lacking when
I was trying to port U-Boot to m68k virt machine.

Please review.
Thanks

Signed-off-by: Jiaxun Yang 
---
Jiaxun Yang (4):
  hw/m68k/virt: Add a XHCI controller
  hw/m68k/virt: Add fw_cfg controller
  hw/m68k/virt: Add a pflash controller for BIOS firmware
  hw/m68k/virt: Supply bootinfo for BIOS

 hw/m68k/Kconfig   |   3 +
 hw/m68k/virt.c| 231 --
 include/standard-headers/asm-m68k/bootinfo-virt.h |   4 +
 3 files changed, 176 insertions(+), 62 deletions(-)
---
base-commit: 60b54b67c63d8f076152e0f7dccf39854dfc6a77
change-id: 20240527-m68k-bios-a0a2370181f5

Best regards,
-- 
Jiaxun Yang 




[PATCH 4/4] hw/m68k/virt: Supply bootinfo for BIOS

2024-05-27 Thread Jiaxun Yang
We follow common function split between BIOS and QEMU loader,
When BIOS firmware is available QEMU does not load kernel/initrd
binary to memory, instead BIOS retrieve those binaries from fw_cfg.

A stripped version of bootinfo is placed at 1 KiB position of memory.
This allows BIOS to probe board level information. It does not contain
any booting related information (kernel, initrd, cmdline, random).

Signed-off-by: Jiaxun Yang 
---
 hw/m68k/virt.c | 160 -
 1 file changed, 90 insertions(+), 70 deletions(-)

diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index a2eebc0f2243..ea7a1bb430fc 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -138,13 +138,16 @@ static void virt_init(MachineState *machine)
 M68kCPU *cpu = NULL;
 int32_t kernel_size;
 uint64_t elf_entry;
-ram_addr_t initrd_base;
-int32_t initrd_size;
+ram_addr_t initrd_base = 0;
+int32_t initrd_size = 0;
+int32_t bootinfo_size;
+bool bios_loaded = false;
 ram_addr_t ram_size = machine->ram_size;
 const char *kernel_filename = machine->kernel_filename;
 const char *initrd_filename = machine->initrd_filename;
 const char *kernel_cmdline = machine->kernel_cmdline;
-hwaddr parameters_base;
+void *param_blob, *param_ptr, *param_rng_seed = NULL;
+hwaddr parameters_base = 1 * KiB;
 DriveInfo *dinfo;
 DeviceState *dev;
 DeviceState *irqc_dev;
@@ -264,6 +267,9 @@ static void virt_init(MachineState *machine)
 
 /* pflash */
 dinfo = drive_get(IF_PFLASH, 0, 0);
+if (dinfo) {
+bios_loaded = true;
+}
 pflash_cfi01_register(VIRT_PFLASH_MMIO_BASE,
   "virt.pflash0",
VIRT_PFLASH_SIZE,
@@ -293,18 +299,12 @@ static void virt_init(MachineState *machine)
 error_report("Could not load ROM image '%s'", machine->firmware);
 exit(1);
 }
+
+bios_loaded = true;
 }
 
-if (kernel_filename) {
-CPUState *cs = CPU(cpu);
+if (kernel_filename && !bios_loaded) {
 uint64_t high;
-void *param_blob, *param_ptr, *param_rng_seed;
-
-if (kernel_cmdline) {
-param_blob = g_malloc(strlen(kernel_cmdline) + 1024);
-} else {
-param_blob = g_malloc(1024);
-}
 
 kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
_entry, NULL, , NULL, 1,
@@ -315,57 +315,6 @@ static void virt_init(MachineState *machine)
 }
 reset_info->initial_pc = elf_entry;
 parameters_base = (high + 1) & ~1;
-param_ptr = param_blob;
-
-BOOTINFO1(param_ptr, BI_MACHTYPE, MACH_VIRT);
-if (m68k_feature(>env, M68K_FEATURE_M68020)) {
-BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68020);
-} else if (m68k_feature(>env, M68K_FEATURE_M68030)) {
-BOOTINFO1(param_ptr, BI_MMUTYPE, MMU_68030);
-BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68030);
-} else if (m68k_feature(>env, M68K_FEATURE_M68040)) {
-BOOTINFO1(param_ptr, BI_FPUTYPE, FPU_68040);
-BOOTINFO1(param_ptr, BI_MMUTYPE, MMU_68040);
-BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68040);
-} else if (m68k_feature(>env, M68K_FEATURE_M68060)) {
-BOOTINFO1(param_ptr, BI_FPUTYPE, FPU_68060);
-BOOTINFO1(param_ptr, BI_MMUTYPE, MMU_68060);
-BOOTINFO1(param_ptr, BI_CPUTYPE, CPU_68060);
-}
-BOOTINFO2(param_ptr, BI_MEMCHUNK, 0, ram_size);
-
-BOOTINFO1(param_ptr, BI_VIRT_QEMU_VERSION,
-  ((QEMU_VERSION_MAJOR << 24) | (QEMU_VERSION_MINOR << 16) |
-   (QEMU_VERSION_MICRO << 8)));
-BOOTINFO2(param_ptr, BI_VIRT_GF_PIC_BASE,
-  VIRT_GF_PIC_MMIO_BASE, VIRT_GF_PIC_IRQ_BASE);
-BOOTINFO2(param_ptr, BI_VIRT_GF_RTC_BASE,
-  VIRT_GF_RTC_MMIO_BASE, VIRT_GF_RTC_IRQ_BASE);
-BOOTINFO2(param_ptr, BI_VIRT_GF_TTY_BASE,
-  VIRT_GF_TTY_MMIO_BASE, VIRT_GF_TTY_IRQ_BASE);
-BOOTINFO2(param_ptr, BI_VIRT_CTRL_BASE,
-  VIRT_CTRL_MMIO_BASE, VIRT_CTRL_IRQ_BASE);
-BOOTINFO2(param_ptr, BI_VIRT_VIRTIO_BASE,
-  VIRT_VIRTIO_MMIO_BASE, VIRT_VIRTIO_IRQ_BASE);
-if (machine_usb(machine)) {
-BOOTINFO2(param_ptr, BI_VIRT_XHCI_BASE,
-VIRT_XHCI_MMIO_BASE, VIRT_XHCI_IRQ_BASE);
-}
-BOOTINFO2(param_ptr, BI_VIRT_FW_CFG_BASE,
-  VIRT_FW_CFG_MMIO_BASE, VIRT_FW_CFG_IRQ_BASE);
-BOOTINFO2(param_ptr, BI_VIRT_PFLASH_BASE,
-VIRT_PFLASH_MMIO_BASE, 0);
-
-if (kernel_cmdline) {
-BOOTINFOSTR(param_ptr, BI_COMMAND_LINE,
-kernel_cmdline);
-}
-
-/* Pass seed to RNG. */
-param_rng_seed = param_ptr;
-  

Re: [PULL 10/10] hw/loongarch/virt: Fix FDT memory node address width

2024-05-24 Thread Jiaxun Yang



在2024年5月24日五月 上午11:10,Michael Tokarev写道:
> 23.05.2024 04:46, Song Gao wrote:
>> From: Jiaxun Yang 
>> 
>> Higher bits for memory nodes were omitted at qemu_fdt_setprop_cells.
>> 
>> Cc: qemu-sta...@nongnu.org
>> Signed-off-by: Jiaxun Yang 
>> Reviewed-by: Song Gao 
>> Message-Id: <20240520-loongarch-fdt-memnode-v1-1-5ea9be939...@flygoat.com>
>> Signed-off-by: Song Gao 
>> ---
>>   hw/loongarch/virt.c | 3 ++-
>>   1 file changed, 2 insertions(+), 1 deletion(-)
>> 
>> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
>> index e3bdf085b5..3e6e93edf3 100644
>> --- a/hw/loongarch/virt.c
>> +++ b/hw/loongarch/virt.c
>> @@ -464,7 +464,8 @@ static void fdt_add_memory_node(MachineState *ms,
>>   char *nodename = g_strdup_printf("/memory@%" PRIx64, base);
>>   
>>   qemu_fdt_add_subnode(ms->fdt, nodename);
>> -qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0, base, 0, size);
>> +qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", base >> 32, base,
>> +   size >> 32, size);
>>   qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "memory");
>>   
>>   if (ms->numa_state && ms->numa_state->num_nodes) {
>
> This commit changes exactly the same place as the previous commit,
> v9.0.0-274-gb11f981452, "hw/loongarch: Fix fdt memory node wrong 'reg'".
>
> Was it the wrong fix?

Yes, I believe previous commit is the wrong fix on the same problem.

>
> Note the previous commit isn't in any released version of qemu.  So
> when picking up for any stable release, both needs to be picked up :)

Please go ahead!

Thanks
- Jiaxun

>
> Thanks,
>
> /mjt
> -- 
> GPG Key transition (from rsa2048 to rsa4096) since 2024-04-24.
> New key: rsa4096/61AD3D98ECDF2C8E  9D8B E14E 3F2A 9DD7 9199  28F1 61AD 
> 3D98 ECDF 2C8E
> Old key: rsa2048/457CE0A0804465C5  6EE1 95D1 886E 8FFB 810D  4324 457C 
> E0A0 8044 65C5
> Transition statement: http://www.corpit.ru/mjt/gpg-transition-2024.txt

-- 
- Jiaxun



Re: [PATCH v3 0/3] Add extioi virt extension support

2024-05-23 Thread Jiaxun Yang



在2024年5月21日五月 下午1:32,Song Gao写道:
> On LoongArch, IRQs can be routed to four vcpus with hardware extioi.
> This patch adds the extioi virt extension support so that the IRQ can
> route to 256 vcpus.

Hi Song,

Sorry for chime in here, I'm a little bit confused by this series, can
you give me a little bit of context behind?

I don't see this functionality on 3A5000/3A6000's user manual, so is this
some sort of undocumented hardware feature?

I checked openEuler kernel patch you referred, it seems like this applies to
hypervisor mode only. I suppose it should be handled by KVM subsystem in
kernel, why do we need this in user mode device emulation?

Currently, LoongArch's in-kernel irqchip functionality does not include such
feature, can we see KVM side support for this, or at least a draft 
specification?

Thanks
- Jiaxun

>
> v3:
> - Split patch2 to two small patch.
> - remove unused code.
> - loongarch_extioi_reset() clear status without checking virt extioi
>   features.
> - Link to v2: 
> https://patchew.org/QEMU/20240514090756.988096-1-gaos...@loongson.cn/
>
> v2:
> - Split the patch to two small patch.
> - Drop 'RFC' title. extioi virt extension suport only enable on kvm
>   mode and  the extioi driver need patch[1].
>   but this series do not affect the old codes in any way.
> - Link to v1: 
> https://lore.kernel.org/all/20240116022526.498613-1-gaos...@loongson.cn/#r
>
> [1]: 
> https://gitee.com/openeuler/kernel/commit/5d97cff72f91f4f20a536efd60eca75bfcb78a64
>
> Thanks.
> Song Gao
>
> Song Gao (3):
>   hw/intc/loongarch_extioi: Add extioi virt extension definition
>   hw/loongarch/virt: Enable extioi virt extension
>   hw/loongarch/virt: Use MemTxAttrs interface for misc ops
>
>  include/hw/intc/loongarch_extioi.h |  21 ++
>  include/hw/loongarch/virt.h|   2 +
>  target/loongarch/cpu.h |   1 +
>  hw/intc/loongarch_extioi.c |  88 +-
>  hw/loongarch/virt.c| 116 +
>  5 files changed, 210 insertions(+), 18 deletions(-)
>
> -- 
> 2.34.1

-- 
- Jiaxun



[PATCH] hw/loongarch/virt: Fix FDT memory node address width

2024-05-20 Thread Jiaxun Yang
Higher bits for memory nodes were omitted at qemu_fdt_setprop_cells.

Signed-off-by: Jiaxun Yang 
---
This should be stable backported, otherwise DT boot is totally broken.
---
 hw/loongarch/virt.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index f0640d2d8035..f97626bacf65 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -463,7 +463,8 @@ static void fdt_add_memory_node(MachineState *ms,
 char *nodename = g_strdup_printf("/memory@%" PRIx64, base);
 
 qemu_fdt_add_subnode(ms->fdt, nodename);
-qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0, base, 0, size);
+qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", base >> 32, base,
+   size >> 32, size);
 qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "memory");
 
 if (ms->numa_state && ms->numa_state->num_nodes) {

---
base-commit: 85ef20f1673feaa083f4acab8cf054df77b0dbed
change-id: 20240520-loongarch-fdt-memnode-e36c01ae9b6e

Best regards,
-- 
Jiaxun Yang 




Re: [PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support

2024-05-16 Thread Jiaxun Yang



在2024年5月8日五月 下午10:41,Philippe Mathieu-Daudé写道:
> On 8/5/24 15:06, Jiaxun Yang wrote:
>> Hi all,
>> 
>> This series enabled IPI support for loongson3 virt board, loosely
>> based on my previous work[1].
>> It generalized loongarch_ipi device to share among both loongarch
>> and MIPS machines.
>
>
>> Signed-off-by: Jiaxun Yang 
>> ---
>> Jiaxun Yang (5):
>>hw/intc/loongarch_ipi: Remove pointless MAX_CPU check
>>hw/intc/loongarch_ipi: Rename as loongson_ipi
>>hw/intc/loongson_ipi: Implement IOCSR address space for MIPS
>
> So far patches 1-3 queued to hw-misc tree, thanks.

Hi Philippe,

Thanks! What's your plan with the rest of the series and earlier MIPS
CPS SMP series?

Let me know if you need help on testing etc.

Thanks
-- 
- Jiaxun



[PATCH] hw/mips/loongson3_virt: Implement node counter timer

2024-05-12 Thread Jiaxun Yang
Node counter is a timer presents on Loongson-3 chips, which runs
as fast as CPU clock. It's being mapped into a MMIO location.

Emulate this for loongson3_virt machine, in hope that kernel can
use it as a better clock source.

Hardware's behavior on 32-bit read/write is also emulated in case
legacy kernel is trying to use it with hi/lo splitted read.

Signed-off-by: Jiaxun Yang 
---
 hw/mips/loongson3_bootp.h |  1 +
 hw/mips/loongson3_virt.c  | 38 ++
 2 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h
index 1b0dd3b59171..c6a435397d2c 100644
--- a/hw/mips/loongson3_bootp.h
+++ b/hw/mips/loongson3_bootp.h
@@ -210,6 +210,7 @@ enum {
 VIRT_PCIE_ECAM,
 VIRT_BIOS_ROM,
 VIRT_UART,
+VIRT_NODECNT,
 VIRT_LIOINTC,
 VIRT_PCIE_MMIO,
 VIRT_HIGHMEM
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index b10a611a98f4..b78ac8032096 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -74,6 +74,7 @@ const MemMapEntry virt_memmap[] = {
 [VIRT_PCIE_ECAM] =   { 0x1a00, 0x200 },
 [VIRT_BIOS_ROM] ={ 0x1fc0,  0x20 },
 [VIRT_UART] ={ 0x1fe001e0,   0x8 },
+[VIRT_NODECNT] = { 0x3ff00408,   0x8 },
 [VIRT_LIOINTC] = { 0x3ff01400,  0x64 },
 [VIRT_PCIE_MMIO] =   { 0x4000,0x4000 },
 [VIRT_HIGHMEM] = { 0x8000,   0x0 }, /* Variable */
@@ -92,6 +93,7 @@ static const MemMapEntry loader_rommap[] = {
 
 struct LoongsonMachineState {
 MachineState parent_obj;
+Clock *cpuclk;
 MemoryRegion *pio_alias;
 MemoryRegion *mmio_alias;
 MemoryRegion *ecam_alias;
@@ -145,6 +147,29 @@ static const MemoryRegionOps loongson3_pm_ops = {
 }
 };
 
+static uint64_t loongson3_nodecnt_read(void *opaque,
+hwaddr addr, unsigned size)
+{
+LoongsonMachineState *s = opaque;
+int64_t now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+uint64_t ticks = clock_ns_to_ticks(s->cpuclk, now_ns);
+
+if (addr == 0x4) {
+return ticks >> 32;
+}
+
+return ticks;
+}
+
+static const MemoryRegionOps loongson3_nodecnt_ops = {
+.read  = loongson3_nodecnt_read,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid.min_access_size = 4,
+.valid.max_access_size = 8,
+.impl.min_access_size = 4,
+.impl.max_access_size = 8,
+};
+
 #define DEF_LOONGSON3_FREQ (800 * 1000 * 1000)
 
 static uint64_t get_cpu_freq_hz(void)
@@ -463,7 +488,6 @@ static void mips_loongson3_virt_init(MachineState *machine)
 int i;
 long bios_size;
 MIPSCPU *cpu;
-Clock *cpuclk;
 CPUMIPSState *env;
 DeviceState *liointc;
 char *filename;
@@ -471,10 +495,12 @@ static void mips_loongson3_virt_init(MachineState 
*machine)
 const char *kernel_filename = machine->kernel_filename;
 const char *initrd_filename = machine->initrd_filename;
 ram_addr_t ram_size = machine->ram_size;
+LoongsonMachineState *ms = LOONGSON_MACHINE(machine);
 MemoryRegion *address_space_mem = get_system_memory();
 MemoryRegion *ram = g_new(MemoryRegion, 1);
 MemoryRegion *bios = g_new(MemoryRegion, 1);
 MemoryRegion *iomem = g_new(MemoryRegion, 1);
+MemoryRegion *nodecnt = g_new(MemoryRegion, 1);
 
 /* TODO: TCG will support all CPU types */
 if (!kvm_enabled()) {
@@ -520,14 +546,14 @@ static void mips_loongson3_virt_init(MachineState 
*machine)
 sysbus_create_simple("goldfish_rtc", virt_memmap[VIRT_RTC].base,
  qdev_get_gpio_in(liointc, RTC_IRQ));
 
-cpuclk = clock_new(OBJECT(machine), "cpu-refclk");
-clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ);
+ms->cpuclk = clock_new(OBJECT(machine), "cpu-refclk");
+clock_set_hz(ms->cpuclk, DEF_LOONGSON3_FREQ);
 
 for (i = 0; i < machine->smp.cpus; i++) {
 int ip;
 
 /* init CPUs */
-cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk);
+cpu = mips_cpu_create_with_clock(machine->cpu_type, ms->cpuclk);
 
 /* Init internal devices */
 cpu_mips_irq_init_cpu(cpu);
@@ -553,6 +579,8 @@ static void mips_loongson3_virt_init(MachineState *machine)
machine->ram, 0, virt_memmap[VIRT_LOWMEM].size);
 memory_region_init_io(iomem, NULL, _pm_ops,
NULL, "loongson3_pm", virt_memmap[VIRT_PM].size);
+memory_region_init_io(nodecnt, NULL, _nodecnt_ops, ms,
+  "loongson3_nodecnt", virt_memmap[VIRT_NODECNT].size);
 
 memory_region_add_subregion(address_space_mem,
   virt_memmap[VIRT_LOWMEM].base, ram);
@@ -562,6 +590,8 @@ static void mips_loongson3_virt_init(MachineState *machine)
   virt_memmap[VIRT_HIGHMEM].base, machine->ram);
 memory_

[PATCH] mips64el-softmmu: Enable MTTCG

2024-05-11 Thread Jiaxun Yang
MTTCG was disabled in a092a9554771 ("configure: disable MTTCG
for MIPS guests") due to test case instability.

I was able to reproduce this issue with in latest QEMU and look
into reason behind that.

What actually happend is kernel's CP0 timer synchronisation
mechanism assumed a consistent latency in memory access between
cores, which TCG can't guarantee. Thus there is a huge drift in
count value between cores, and in early kernel versions CP0 timer
is always used as sched_clock.

sched_clock drift back on some cores triggered RCU watchdog in
some extreme cases.

This can be resolved by setting clocksource to MIPS, which allows
clocksource to drift together with sched_clock. However this will
leed to other problems after boot.

Another option would beupdating kernel to later version, which
will use GIC as sched_clock.

In non-MTTCG build, the execution is slow enough so kernel won't
observe back drifts.

Test results:

With clocksource=MIPS
```
 ~/tmp/retry/retry.py -n 100 -c -- ./qemu-system-mips64el \
-display none -vga none -serial mon:stdio \
-machine malta -kernel ./vmlinux-4.7.0-rc1.I6400 \
-cpu I6400 -smp 8 -vga std \
-append "printk.time=0 clocksource=MIPS console=tty0 console=ttyS0 
panic=-1" \
--no-reboot

100, 0, PASS, 5.258126, 100, 100, -
Results summary:
0: 100 times (100.00%), avg time 6.508 (55.53 varience/7.45 deviation)
Ran command 100 times, 100 passes
```

With linux-next:
```
 ~/tmp/retry/retry.py -n 100 -c -- ./qemu-system-mips64el \
-display none -vga none -serial mon:stdio \
-machine malta -kernel ~/linux-next/vmlinux \
-cpu I6400 -smp 8 -vga std \
-append "printk.time=0 console=tty0 console=ttyS0 panic=-1" \
--no-reboot

100, 0, PASS, 4.507921, 100, 100, -
Results summary:
0: 100 times (100.00%), avg time 4.233 (0.04 varience/0.21 deviation)
Ran command 100 times, 100 passes
```

Signed-off-by: Jiaxun Yang 
---
I'll leave the test case alone as it's already marked as QEMU_TEST_FLAKY_TESTS
---
 configs/targets/mips64el-softmmu.mak | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/targets/mips64el-softmmu.mak 
b/configs/targets/mips64el-softmmu.mak
index 8d9ab3ddc4b1..199b1d909a7d 100644
--- a/configs/targets/mips64el-softmmu.mak
+++ b/configs/targets/mips64el-softmmu.mak
@@ -1,3 +1,4 @@
 TARGET_ARCH=mips64
 TARGET_BASE_ARCH=mips
+TARGET_SUPPORTS_MTTCG=y
 TARGET_NEED_FDT=y

---
base-commit: 248f6f62df073a3b4158fd0093863ab885feabb5
change-id: 20240511-mips_mttcg-47a6b19074b3

Best regards,
-- 
Jiaxun Yang 




Re: [PATCH] hw/mips/loongson3_virt: Emulate suspend function

2024-05-08 Thread Jiaxun Yang



在2024年5月8日五月 下午5:48,Philippe Mathieu-Daudé写道:
> On 8/5/24 17:35, Philippe Mathieu-Daudé wrote:
>> On 8/5/24 11:31, Jiaxun Yang wrote:
>>> Suspend function is emulated as what hardware actually do.
>>> Doorbell register fields are updates to include suspend value,
>>> suspend vector is encoded in firmware blob and fw_cfg is updated
>>> to include S3 bits as what x86 did.
>>>
>>> Signed-off-by: Jiaxun Yang 
>>> ---
>>>   hw/mips/loongson3_bootp.c |  1 +
>>>   hw/mips/loongson3_virt.c  | 19 +++
>>>   2 files changed, 20 insertions(+)
>> 
>> Thanks, patch queued.
>
> Fixed:
>
> ERROR: use g_memdup2() instead of unsafe g_memdup()
> #76: FILE: hw/mips/loongson3_virt.c:293:
> +fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6);

Thanks, I omitted this one as it is copied from hw/acpi/core.c

Should we fix that one as well?

-- 
- Jiaxun



[PATCH 0/5] hw/mips/loongson3_virt: Implement IPI support

2024-05-08 Thread Jiaxun Yang
Hi all,

This series enabled IPI support for loongson3 virt board, loosely
based on my previous work[1].
It generalized loongarch_ipi device to share among both loongarch
and MIPS machines. 

Thanks

[1]: https://lore.kernel.org/all/20230521102307.87081-1-jiaxun.y...@flygoat.com/

To: qemu-devel@nongnu.org
Cc: Song Gao 

Signed-off-by: Jiaxun Yang 
---
Jiaxun Yang (5):
  hw/intc/loongarch_ipi: Remove pointless MAX_CPU check
  hw/intc/loongarch_ipi: Rename as loongson_ipi
  hw/intc/loongson_ipi: Implement IOCSR address space for MIPS
  hw/intc/loongson_ipi: Provide per core MMIO address spaces
  hw/mips/loongson3_virt: Wire up loongson_ipi device

 MAINTAINERS|   4 +
 hw/intc/Kconfig|   2 +-
 hw/intc/loongarch_ipi.c|  19 +-
 hw/intc/loongson_ipi.c | 411 +
 hw/intc/meson.build|   2 +-
 hw/intc/trace-events   |   8 +-
 hw/loongarch/Kconfig   |   2 +-
 hw/loongarch/virt.c|   4 +-
 hw/mips/Kconfig|   1 +
 hw/mips/loongson3_bootp.c  |   2 -
 hw/mips/loongson3_bootp.h  |   3 +
 hw/mips/loongson3_virt.c   |  39 +-
 .../hw/intc/{loongarch_ipi.h => loongson_ipi.h}|  14 +-
 include/hw/loongarch/virt.h|   2 +-
 14 files changed, 475 insertions(+), 38 deletions(-)
---
base-commit: 248f6f62df073a3b4158fd0093863ab885feabb5
change-id: 20240508-loongson3-ipi-65e99b47c400

Best regards,
-- 
Jiaxun Yang 




[PATCH 5/5] hw/mips/loongson3_virt: Wire up loongson_ipi device

2024-05-08 Thread Jiaxun Yang
Wire up loongson_ipi device for loongson3_virt machine, so we
can have SMP support for TCG backend as well.

Signed-off-by: Jiaxun Yang 
---
 hw/mips/Kconfig   |  1 +
 hw/mips/loongson3_bootp.c |  2 --
 hw/mips/loongson3_bootp.h |  3 +++
 hw/mips/loongson3_virt.c  | 39 +--
 4 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index 5c83ef49cf6f..6f09fedc946e 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -57,6 +57,7 @@ config LOONGSON3V
 imply USB_OHCI_PCI
 select SERIAL
 select GOLDFISH_RTC
+select LOONGSON_IPI
 select LOONGSON_LIOINTC
 select PCI_EXPRESS_GENERIC_BRIDGE
 select MSI_NONBROKEN
diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
index f99af229327a..474d3556b2e5 100644
--- a/hw/mips/loongson3_bootp.c
+++ b/hw/mips/loongson3_bootp.c
@@ -25,8 +25,6 @@
 #include "hw/boards.h"
 #include "hw/mips/loongson3_bootp.h"
 
-#define LOONGSON3_CORE_PER_NODE 4
-
 static void init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
 {
 struct efi_cpuinfo_loongson *c = g_cpuinfo;
diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h
index 1b0dd3b59171..9091265df7fc 100644
--- a/hw/mips/loongson3_bootp.h
+++ b/hw/mips/loongson3_bootp.h
@@ -200,6 +200,8 @@ struct boot_params {
 struct efi_reset_system_t reset_system;
 };
 
+#define LOONGSON3_CORE_PER_NODE 4
+
 /* Overall MMIO & Memory layout */
 enum {
 VIRT_LOWMEM,
@@ -211,6 +213,7 @@ enum {
 VIRT_BIOS_ROM,
 VIRT_UART,
 VIRT_LIOINTC,
+VIRT_IPI,
 VIRT_PCIE_MMIO,
 VIRT_HIGHMEM
 };
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index b10a611a98f4..1052fb7d6747 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -36,6 +36,7 @@
 #include "hw/mips/loongson3_bootp.h"
 #include "hw/misc/unimp.h"
 #include "hw/intc/i8259.h"
+#include "hw/intc/loongson_ipi.h"
 #include "hw/loader.h"
 #include "hw/isa/superio.h"
 #include "hw/pci/msi.h"
@@ -74,6 +75,7 @@ const MemMapEntry virt_memmap[] = {
 [VIRT_PCIE_ECAM] =   { 0x1a00, 0x200 },
 [VIRT_BIOS_ROM] ={ 0x1fc0,  0x20 },
 [VIRT_UART] ={ 0x1fe001e0,   0x8 },
+[VIRT_IPI] = { 0x3ff01000, 0x400 },
 [VIRT_LIOINTC] = { 0x3ff01400,  0x64 },
 [VIRT_PCIE_MMIO] =   { 0x4000,0x4000 },
 [VIRT_HIGHMEM] = { 0x8000,   0x0 }, /* Variable */
@@ -466,6 +468,7 @@ static void mips_loongson3_virt_init(MachineState *machine)
 Clock *cpuclk;
 CPUMIPSState *env;
 DeviceState *liointc;
+DeviceState *ipi = NULL;
 char *filename;
 const char *kernel_cmdline = machine->kernel_cmdline;
 const char *kernel_filename = machine->kernel_filename;
@@ -475,6 +478,7 @@ static void mips_loongson3_virt_init(MachineState *machine)
 MemoryRegion *ram = g_new(MemoryRegion, 1);
 MemoryRegion *bios = g_new(MemoryRegion, 1);
 MemoryRegion *iomem = g_new(MemoryRegion, 1);
+MemoryRegion *iocsr = g_new(MemoryRegion, 1);
 
 /* TODO: TCG will support all CPU types */
 if (!kvm_enabled()) {
@@ -508,6 +512,19 @@ static void mips_loongson3_virt_init(MachineState *machine)
 create_unimplemented_device("mmio fallback 0", 0x1000, 256 * MiB);
 create_unimplemented_device("mmio fallback 1", 0x3000, 256 * MiB);
 
+memory_region_init(iocsr, OBJECT(machine), "loongson3.iocsr", UINT32_MAX);
+
+/* IPI controller is in kernel for KVM */
+if (!kvm_enabled()) {
+ipi = qdev_new(TYPE_LOONGSON_IPI);
+qdev_prop_set_uint32(ipi, "num-cpu", machine->smp.cpus);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), _fatal);
+memory_region_add_subregion(iocsr, SMP_IPI_MAILBOX,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 0));
+memory_region_add_subregion(iocsr, MAIL_SEND_ADDR,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1));
+}
+
 liointc = qdev_new("loongson.liointc");
 sysbus_realize_and_unref(SYS_BUS_DEVICE(liointc), _fatal);
 
@@ -524,6 +541,8 @@ static void mips_loongson3_virt_init(MachineState *machine)
 clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ);
 
 for (i = 0; i < machine->smp.cpus; i++) {
+int node = i / LOONGSON3_CORE_PER_NODE;
+int core = i % LOONGSON3_CORE_PER_NODE;
 int ip;
 
 /* init CPUs */
@@ -534,12 +553,28 @@ static void mips_loongson3_virt_init(MachineState 
*machine)
 cpu_mips_clock_init(cpu);
 qemu_register_reset(main_cpu_reset, cpu);
 
-if (i >= 4) {
+if (ipi) {
+hwaddr base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base;
+base += core * 0x100;
+qdev_connect_gpio_out(ipi, i, cpu->env.irq[6]);
+sysbu

[PATCH 4/5] hw/intc/loongson_ipi: Provide per core MMIO address spaces

2024-05-08 Thread Jiaxun Yang
The real IPI hardware have dedicated MMIO registers mapped into
memory address space for every core. This is not used by LoongArch
guest software but it is essential for CPU without IOCSR such as
Loongson-3A1000.

Implement it with existing infrastructure.

Signed-off-by: Jiaxun Yang 
---
 hw/intc/loongson_ipi.c | 81 --
 include/hw/intc/loongson_ipi.h |  2 ++
 2 files changed, 64 insertions(+), 19 deletions(-)

diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c
index 93cc50a37a11..c8a25b4eb8e2 100644
--- a/hw/intc/loongson_ipi.c
+++ b/hw/intc/loongson_ipi.c
@@ -23,16 +23,14 @@
 #endif
 #include "trace.h"
 
-static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr,
+static MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr,
uint64_t *data,
unsigned size, MemTxAttrs attrs)
 {
-IPICore *s;
-LoongsonIPI *ipi = opaque;
+IPICore *s = opaque;
 uint64_t ret = 0;
 int index = 0;
 
-s = >cpu[attrs.requester_id];
 addr &= 0xff;
 switch (addr) {
 case CORE_STATUS_OFF:
@@ -61,6 +59,21 @@ static MemTxResult loongson_ipi_readl(void *opaque, hwaddr 
addr,
 return MEMTX_OK;
 }
 
+static MemTxResult loongson_ipi_iocsr_readl(void *opaque, hwaddr addr,
+   uint64_t *data,
+   unsigned size, MemTxAttrs attrs)
+{
+LoongsonIPI *ipi = opaque;
+IPICore *s;
+
+if (attrs.requester_id >= ipi->num_cpu) {
+return MEMTX_DECODE_ERROR;
+}
+
+s = >cpu[attrs.requester_id];
+return loongson_ipi_core_readl(s, addr, data, size, attrs);
+}
+
 static AddressSpace *get_cpu_iocsr_as(CPUState *cpu)
 {
 #ifdef TARGET_LOONGARCH64
@@ -174,17 +187,17 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs 
attrs)
 return send_ipi_data(cs, val, addr, attrs);
 }
 
-static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
-unsigned size, MemTxAttrs attrs)
+static MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr,
+uint64_t val, unsigned size,
+MemTxAttrs attrs)
 {
-LoongsonIPI *ipi = opaque;
-IPICore *s;
+IPICore *s = opaque;
+LoongsonIPI *ipi = s->ipi;
 int index = 0;
 uint32_t cpuid;
 uint8_t vector;
 CPUState *cs;
 
-s = >cpu[attrs.requester_id];
 addr &= 0xff;
 trace_loongson_ipi_write(size, (uint64_t)addr, val);
 switch (addr) {
@@ -215,13 +228,11 @@ static MemTxResult loongson_ipi_writel(void *opaque, 
hwaddr addr, uint64_t val,
 /* IPI status vector */
 vector = extract8(val, 0, 5);
 cs = ipi_getcpu(cpuid);
-if (cs == NULL) {
+if (cs == NULL || cs->cpu_index >= ipi->num_cpu) {
 return MEMTX_DECODE_ERROR;
 }
-
-/* override requester_id */
-attrs.requester_id = cs->cpu_index;
-loongson_ipi_writel(ipi, CORE_SET_OFF, BIT(vector), 4, attrs);
+loongson_ipi_core_writel(>cpu[cs->cpu_index], CORE_SET_OFF,
+ BIT(vector), 4, attrs);
 break;
 default:
 qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr);
@@ -231,9 +242,34 @@ static MemTxResult loongson_ipi_writel(void *opaque, 
hwaddr addr, uint64_t val,
 return MEMTX_OK;
 }
 
-static const MemoryRegionOps loongson_ipi_ops = {
-.read_with_attrs = loongson_ipi_readl,
-.write_with_attrs = loongson_ipi_writel,
+static MemTxResult loongson_ipi_iocsr_writel(void *opaque, hwaddr addr,
+uint64_t val, unsigned size,
+MemTxAttrs attrs)
+{
+LoongsonIPI *ipi = opaque;
+IPICore *s;
+
+if (attrs.requester_id >= ipi->num_cpu) {
+return MEMTX_DECODE_ERROR;
+}
+
+s = >cpu[attrs.requester_id];
+return loongson_ipi_core_writel(s, addr, val, size, attrs);
+}
+
+static const MemoryRegionOps loongson_ipi_core_ops = {
+.read_with_attrs = loongson_ipi_core_readl,
+.write_with_attrs = loongson_ipi_core_writel,
+.impl.min_access_size = 4,
+.impl.max_access_size = 4,
+.valid.min_access_size = 4,
+.valid.max_access_size = 8,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static const MemoryRegionOps loongson_ipi_iocsr_ops = {
+.read_with_attrs = loongson_ipi_iocsr_readl,
+.write_with_attrs = loongson_ipi_iocsr_writel,
 .impl.min_access_size = 4,
 .impl.max_access_size = 4,
 .valid.min_access_size = 4,
@@ -282,7 +318,7 @@ static void loongson_ipi_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 
-memory_region_init_io(>ipi_iocsr_mem, OBJECT(dev), _ipi_ops,
+memory_region_init_io(>ipi_iocsr_mem, OBJECT(

[PATCH 1/5] hw/intc/loongarch_ipi: Remove pointless MAX_CPU check

2024-05-08 Thread Jiaxun Yang
Since cpuid will be checked by ipi_getcpu anyway, there is
no point to enforce MAX_CPU here.

This also saved us from including loongarch board header.

Signed-off-by: Jiaxun Yang 
---
 hw/intc/loongarch_ipi.c | 19 ++-
 hw/intc/trace-events|  2 --
 2 files changed, 2 insertions(+), 19 deletions(-)

diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
index a184112b0923..44b3b9c138d6 100644
--- a/hw/intc/loongarch_ipi.c
+++ b/hw/intc/loongarch_ipi.c
@@ -6,6 +6,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "hw/boards.h"
 #include "hw/sysbus.h"
 #include "hw/intc/loongarch_ipi.h"
 #include "hw/irq.h"
@@ -13,9 +14,8 @@
 #include "qapi/error.h"
 #include "qemu/log.h"
 #include "exec/address-spaces.h"
-#include "hw/loongarch/virt.h"
 #include "migration/vmstate.h"
-#include "target/loongarch/internals.h"
+#include "target/loongarch/cpu.h"
 #include "trace.h"
 
 static MemTxResult loongarch_ipi_readl(void *opaque, hwaddr addr,
@@ -122,11 +122,6 @@ static MemTxResult mail_send(uint64_t val, MemTxAttrs 
attrs)
 CPUState *cs;
 
 cpuid = extract32(val, 16, 10);
-if (cpuid >= LOONGARCH_MAX_CPUS) {
-trace_loongarch_ipi_unsupported_cpuid("IOCSR_MAIL_SEND", cpuid);
-return MEMTX_DECODE_ERROR;
-}
-
 cs = ipi_getcpu(cpuid);
 if (cs == NULL) {
 return MEMTX_DECODE_ERROR;
@@ -146,11 +141,6 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs attrs)
 CPUState *cs;
 
 cpuid = extract32(val, 16, 10);
-if (cpuid >= LOONGARCH_MAX_CPUS) {
-trace_loongarch_ipi_unsupported_cpuid("IOCSR_ANY_SEND", cpuid);
-return MEMTX_DECODE_ERROR;
-}
-
 cs = ipi_getcpu(cpuid);
 if (cs == NULL) {
 return MEMTX_DECODE_ERROR;
@@ -201,11 +191,6 @@ static MemTxResult loongarch_ipi_writel(void *opaque, 
hwaddr addr, uint64_t val,
 break;
 case IOCSR_IPI_SEND:
 cpuid = extract32(val, 16, 10);
-if (cpuid >= LOONGARCH_MAX_CPUS) {
-trace_loongarch_ipi_unsupported_cpuid("IOCSR_IPI_SEND", cpuid);
-return MEMTX_DECODE_ERROR;
-}
-
 /* IPI status vector */
 vector = extract8(val, 0, 5);
 cs = ipi_getcpu(cpuid);
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 47340b5bc138..a979784f9bee 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -294,8 +294,6 @@ sh_intc_set(int id, int enable) "setting interrupt group %d 
to %d"
 # loongarch_ipi.c
 loongarch_ipi_read(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 
0x%"PRIx64 "val: 0x%"PRIx64
 loongarch_ipi_write(unsigned size, uint64_t addr, uint64_t val) "size: %u 
addr: 0x%"PRIx64 "val: 0x%"PRIx64
-loongarch_ipi_unsupported_cpuid(const char *s, uint32_t cpuid) "%s unsupported 
cpuid 0x%" PRIx32
-
 # loongarch_pch_pic.c
 loongarch_pch_pic_irq_handler(int irq, int level) "irq %d level %d"
 loongarch_pch_pic_low_readw(unsigned size, uint64_t addr, uint64_t val) "size: 
%u addr: 0x%"PRIx64 "val: 0x%" PRIx64

-- 
2.34.1




[PATCH 2/5] hw/intc/loongarch_ipi: Rename as loongson_ipi

2024-05-08 Thread Jiaxun Yang
This device will be shared among LoongArch and MIPS
based Loongson machine, rename it as loongson_ipi
to reflect this nature.

Signed-off-by: Jiaxun Yang 
---
 MAINTAINERS|   4 +
 hw/intc/Kconfig|   2 +-
 hw/intc/loongson_ipi.c | 347 +
 hw/intc/meson.build|   2 +-
 hw/intc/trace-events   |   6 +-
 hw/loongarch/Kconfig   |   2 +-
 hw/loongarch/virt.c|   4 +-
 .../hw/intc/{loongarch_ipi.h => loongson_ipi.h}|  12 +-
 include/hw/loongarch/virt.h|   2 +-
 9 files changed, 366 insertions(+), 15 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 2f08cc528eb6..290dc3227baf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1241,7 +1241,9 @@ F: configs/devices/loongarch64-softmmu/default.mak
 F: hw/loongarch/
 F: include/hw/loongarch/virt.h
 F: include/hw/intc/loongarch_*.h
+F: include/hw/intc/loongson_ipi.h
 F: hw/intc/loongarch_*.c
+F: hw/intc/loongson_ipi.c
 F: include/hw/pci-host/ls7a.h
 F: hw/rtc/ls7a_rtc.c
 F: gdb-xml/loongarch*.xml
@@ -1375,10 +1377,12 @@ Loongson-3 virtual platforms
 M: Huacai Chen 
 R: Jiaxun Yang 
 S: Maintained
+F: hw/intc/loongson_ipi.c
 F: hw/intc/loongson_liointc.c
 F: hw/mips/loongson3_bootp.c
 F: hw/mips/loongson3_bootp.h
 F: hw/mips/loongson3_virt.c
+F: include/hw/intc/loongson_ipi.h
 F: include/hw/intc/loongson_liointc.h
 F: tests/avocado/machine_mips_loongson3v.py
 
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index ad59abebaa1d..58b6d3a71003 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -87,7 +87,7 @@ config GOLDFISH_PIC
 config M68K_IRQC
 bool
 
-config LOONGARCH_IPI
+config LOONGSON_IPI
 bool
 
 config LOONGARCH_PCH_PIC
diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c
new file mode 100644
index ..8c888da3b27c
--- /dev/null
+++ b/hw/intc/loongson_ipi.c
@@ -0,0 +1,347 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Loongson ipi interrupt support
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/boards.h"
+#include "hw/sysbus.h"
+#include "hw/intc/loongson_ipi.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "exec/address-spaces.h"
+#include "migration/vmstate.h"
+#include "target/loongarch/cpu.h"
+#include "trace.h"
+
+static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr,
+   uint64_t *data,
+   unsigned size, MemTxAttrs attrs)
+{
+IPICore *s;
+LoongsonIPI *ipi = opaque;
+uint64_t ret = 0;
+int index = 0;
+
+s = >cpu[attrs.requester_id];
+addr &= 0xff;
+switch (addr) {
+case CORE_STATUS_OFF:
+ret = s->status;
+break;
+case CORE_EN_OFF:
+ret = s->en;
+break;
+case CORE_SET_OFF:
+ret = 0;
+break;
+case CORE_CLEAR_OFF:
+ret = 0;
+break;
+case CORE_BUF_20 ... CORE_BUF_38 + 4:
+index = (addr - CORE_BUF_20) >> 2;
+ret = s->buf[index];
+break;
+default:
+qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr);
+break;
+}
+
+trace_loongson_ipi_read(size, (uint64_t)addr, ret);
+*data = ret;
+return MEMTX_OK;
+}
+
+static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr,
+  MemTxAttrs attrs)
+{
+int i, mask = 0, data = 0;
+
+/*
+ * bit 27-30 is mask for byte writing,
+ * if the mask is 0, we need not to do anything.
+ */
+if ((val >> 27) & 0xf) {
+data = address_space_ldl(env->address_space_iocsr, addr,
+ attrs, NULL);
+for (i = 0; i < 4; i++) {
+/* get mask for byte writing */
+if (val & (0x1 << (27 + i))) {
+mask |= 0xff << (i * 8);
+}
+}
+}
+
+data &= mask;
+data |= (val >> 32) & ~mask;
+address_space_stl(env->address_space_iocsr, addr,
+  data, attrs, NULL);
+}
+
+static int archid_cmp(const void *a, const void *b)
+{
+   CPUArchId *archid_a = (CPUArchId *)a;
+   CPUArchId *archid_b = (CPUArchId *)b;
+
+   return archid_a->arch_id - archid_b->arch_id;
+}
+
+static CPUArchId *find_cpu_by_archid(MachineState *ms, uint32_t id)
+{
+CPUArchId apic_id, *found_cpu;
+
+apic_id.arch_id = id;
+found_cpu = bsearch(_id, ms->possible_cpus->cpus,
+ms->possible_cpus->len, sizeof(*ms->possible_cpus->cpus),
+archid_cmp)

[PATCH 3/5] hw/intc/loongson_ipi: Implement IOCSR address space for MIPS

2024-05-08 Thread Jiaxun Yang
Implement IOCSR address space get functions for MIPS/Loongson CPUs.

For MIPS/Loongson without IOCSR (i.e. Loongson-3A1000), get_cpu_iocsr_as
will return as null, and send_ipi_data will fail with MEMTX_DECODE_ERROR,
which matches expected behavior on hardware.

Signed-off-by: Jiaxun Yang 
---
I understand that there was a review comment stating that I shouldn't
use TARGET_* macros in device drivers. But I still think this is the
best way to handle architectural difference. There are many TARGET_*
usages in hw/virtio for similiar purpose.
---
 hw/intc/loongson_ipi.c | 39 ++-
 1 file changed, 30 insertions(+), 9 deletions(-)

diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c
index 8c888da3b27c..93cc50a37a11 100644
--- a/hw/intc/loongson_ipi.c
+++ b/hw/intc/loongson_ipi.c
@@ -15,7 +15,12 @@
 #include "qemu/log.h"
 #include "exec/address-spaces.h"
 #include "migration/vmstate.h"
+#ifdef TARGET_LOONGARCH64
 #include "target/loongarch/cpu.h"
+#endif
+#ifdef TARGET_MIPS
+#include "target/mips/cpu.h"
+#endif
 #include "trace.h"
 
 static MemTxResult loongson_ipi_readl(void *opaque, hwaddr addr,
@@ -56,18 +61,35 @@ static MemTxResult loongson_ipi_readl(void *opaque, hwaddr 
addr,
 return MEMTX_OK;
 }
 
-static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr,
+static AddressSpace *get_cpu_iocsr_as(CPUState *cpu)
+{
+#ifdef TARGET_LOONGARCH64
+return LOONGARCH_CPU(cpu)->env.address_space_iocsr;
+#endif
+#ifdef TARGET_MIPS
+if (ase_lcsr_available(_CPU(cpu)->env)) {
+return _CPU(cpu)->env.iocsr.as;
+}
+#endif
+return NULL;
+}
+
+static MemTxResult send_ipi_data(CPUState *cpu, uint64_t val, hwaddr addr,
   MemTxAttrs attrs)
 {
 int i, mask = 0, data = 0;
+AddressSpace *iocsr_as = get_cpu_iocsr_as(cpu);
+
+if (!iocsr_as) {
+return MEMTX_DECODE_ERROR;
+}
 
 /*
  * bit 27-30 is mask for byte writing,
  * if the mask is 0, we need not to do anything.
  */
 if ((val >> 27) & 0xf) {
-data = address_space_ldl(env->address_space_iocsr, addr,
- attrs, NULL);
+data = address_space_ldl(iocsr_as, addr, attrs, NULL);
 for (i = 0; i < 4; i++) {
 /* get mask for byte writing */
 if (val & (0x1 << (27 + i))) {
@@ -78,8 +100,9 @@ static void send_ipi_data(CPULoongArchState *env, uint64_t 
val, hwaddr addr,
 
 data &= mask;
 data |= (val >> 32) & ~mask;
-address_space_stl(env->address_space_iocsr, addr,
-  data, attrs, NULL);
+address_space_stl(iocsr_as, addr, data, attrs, NULL);
+
+return MEMTX_OK;
 }
 
 static int archid_cmp(const void *a, const void *b)
@@ -130,8 +153,7 @@ static MemTxResult mail_send(uint64_t val, MemTxAttrs attrs)
 /* override requester_id */
 addr = SMP_IPI_MAILBOX + CORE_BUF_20 + (val & 0x1c);
 attrs.requester_id = cs->cpu_index;
-send_ipi_data(_CPU(cs)->env, val, addr, attrs);
-return MEMTX_OK;
+return send_ipi_data(cs, val, addr, attrs);
 }
 
 static MemTxResult any_send(uint64_t val, MemTxAttrs attrs)
@@ -149,8 +171,7 @@ static MemTxResult any_send(uint64_t val, MemTxAttrs attrs)
 /* override requester_id */
 addr = val & 0x;
 attrs.requester_id = cs->cpu_index;
-send_ipi_data(_CPU(cs)->env, val, addr, attrs);
-return MEMTX_OK;
+return send_ipi_data(cs, val, addr, attrs);
 }
 
 static MemTxResult loongson_ipi_writel(void *opaque, hwaddr addr, uint64_t val,

-- 
2.34.1




[PATCH] hw/mips/loongson3_virt: Emulate suspend function

2024-05-08 Thread Jiaxun Yang
Suspend function is emulated as what hardware actually do.
Doorbell register fields are updates to include suspend value,
suspend vector is encoded in firmware blob and fw_cfg is updated
to include S3 bits as what x86 did.

Signed-off-by: Jiaxun Yang 
---
 hw/mips/loongson3_bootp.c |  1 +
 hw/mips/loongson3_virt.c  | 19 +++
 2 files changed, 20 insertions(+)

diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
index f99af229327a..03a10b63c1b4 100644
--- a/hw/mips/loongson3_bootp.c
+++ b/hw/mips/loongson3_bootp.c
@@ -148,4 +148,5 @@ void init_reset_system(struct efi_reset_system_t *reset)
 reset->Shutdown = cpu_to_le64(0xbfc000a8);
 reset->ResetCold = cpu_to_le64(0xbfc00080);
 reset->ResetWarm = cpu_to_le64(0xbfc00080);
+reset->DoSuspend = cpu_to_le64(0xbfc000d0);
 }
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index 33eae01eca2b..f06518ad8f54 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -127,6 +127,9 @@ static void loongson3_pm_write(void *opaque, hwaddr addr,
 case 0x00:
 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
 return;
+case 0x01:
+qemu_system_suspend_request();
+return;
 case 0xff:
 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
 return;
@@ -250,6 +253,17 @@ static void init_boot_rom(void)
 0x240D00FF,   /* li  t1, 0xff 
*/
 0xA18D,   /* sb  t1, (t0) 
*/
 0x1000,   /* 1:  b   1b   
*/
+0x,   /* nop  
*/
+  /* Suspend  
*/
+0x3C0C9000,   /* dli t0, 0x900010080010   
*/
+0x358C,
+0x000C6438,
+0x358C1008,
+0x000C6438,
+0x358C0010,
+0x240D0001,   /* li  t1, 0x01 
*/
+0xA18D,   /* sb  t1, (t0) 
*/
+0x03e8,   /* jr  ra   
*/
 0x/* nop  
*/
 };
 
@@ -274,6 +288,10 @@ static void fw_conf_init(unsigned long ram_size)
 fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
 fw_cfg_add_i32(fw_cfg, FW_CFG_MACHINE_VERSION, 1);
 fw_cfg_add_i64(fw_cfg, FW_CFG_CPU_FREQ, get_cpu_freq_hz());
+
+uint8_t suspend[6] = {128, 0, 0, 129, 128, 128};
+fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6);
+
 qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
 }
 
@@ -551,6 +569,7 @@ static void mips_loongson3_virt_init(MachineState *machine)
machine->ram, 0, virt_memmap[VIRT_LOWMEM].size);
 memory_region_init_io(iomem, NULL, _pm_ops,
NULL, "loongson3_pm", virt_memmap[VIRT_PM].size);
+qemu_register_wakeup_support();
 
 memory_region_add_subregion(address_space_mem,
   virt_memmap[VIRT_LOWMEM].base, ram);

---
base-commit: d762bf97931b58839316b68a570eecc6143c9e3e
change-id: 20240508-loongson3v-suspend-cdd33a169eab

Best regards,
-- 
Jiaxun Yang 




[PATCH 5/5] hw/mips/boston: Implement multi core support

2024-05-06 Thread Jiaxun Yang
Implement multiple physical core support by passing topology
to CPS subsystem and generate cpu-map fdt node to decribe
new topology.

Signed-off-by: Jiaxun Yang 
---
 hw/mips/boston.c | 37 -
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/hw/mips/boston.c b/hw/mips/boston.c
index 1b44fb354c..4ed7d366fe 100644
--- a/hw/mips/boston.c
+++ b/hw/mips/boston.c
@@ -542,7 +542,10 @@ static const void *create_fdt(BostonState *s,
 qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
 qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
 
+qemu_fdt_add_subnode(fdt, "/cpus/cpu-map");
 for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
+char *map_path;
+
 name = g_strdup_printf("/cpus/cpu@%d", cpu);
 qemu_fdt_add_subnode(fdt, name);
 qemu_fdt_setprop_string(fdt, name, "compatible", "img,mips");
@@ -550,6 +553,27 @@ static const void *create_fdt(BostonState *s,
 qemu_fdt_setprop_cell(fdt, name, "reg", cpu);
 qemu_fdt_setprop_string(fdt, name, "device_type", "cpu");
 qemu_fdt_setprop_cells(fdt, name, "clocks", clk_ph, 
FDT_BOSTON_CLK_CPU);
+qemu_fdt_setprop_cell(fdt, name, "phandle", 
qemu_fdt_alloc_phandle(fdt));
+
+if (ms->smp.threads > 1) {
+map_path = g_strdup_printf(
+"/cpus/cpu-map/socket%d/cluster%d/core%d/thread%d",
+cpu / (ms->smp.clusters * ms->smp.cores * ms->smp.threads),
+(cpu / (ms->smp.cores * ms->smp.threads)) % ms->smp.clusters,
+(cpu / ms->smp.threads) % ms->smp.cores,
+cpu % ms->smp.threads);
+} else {
+map_path = g_strdup_printf(
+"/cpus/cpu-map/socket%d/cluster%d/core%d",
+cpu / (ms->smp.clusters * ms->smp.cores),
+(cpu / ms->smp.cores) % ms->smp.clusters,
+cpu % ms->smp.cores);
+}
+
+qemu_fdt_add_path(fdt, map_path);
+qemu_fdt_setprop_phandle(fdt, map_path, "cpu", name);
+
+g_free(map_path);
 g_free(name);
 }
 
@@ -591,6 +615,15 @@ static const void *create_fdt(BostonState *s,
 g_free(name);
 g_free(gic_name);
 
+/* CM node */
+name = g_strdup_printf("/soc/cm@%" HWADDR_PRIx, memmap[BOSTON_CM].base);
+qemu_fdt_add_subnode(fdt, name);
+qemu_fdt_setprop_string(fdt, name, "compatible", "mti,mips-cm");
+qemu_fdt_setprop_cells(fdt, name, "reg", memmap[BOSTON_CM].base,
+memmap[BOSTON_CM].size);
+g_free(name);
+
+
 /* CDMM node */
 name = g_strdup_printf("/soc/cdmm@%" HWADDR_PRIx, 
memmap[BOSTON_CDMM].base);
 qemu_fdt_add_subnode(fdt, name);
@@ -703,7 +736,9 @@ static void boston_mach_init(MachineState *machine)
 object_initialize_child(OBJECT(machine), "cps", >cps, TYPE_MIPS_CPS);
 object_property_set_str(OBJECT(>cps), "cpu-type", machine->cpu_type,
 _fatal);
-object_property_set_uint(OBJECT(>cps), "num-vp", machine->smp.cpus,
+object_property_set_uint(OBJECT(>cps), "num-pcore", machine->smp.cores,
+_fatal);
+object_property_set_uint(OBJECT(>cps), "num-vp", machine->smp.threads,
 _fatal);
 qdev_connect_clock_in(DEVICE(>cps), "clk-in",
   qdev_get_clock_out(dev, "cpu-refclk"));

-- 
2.34.1




[PATCH 2/5] hw/msic/mips_cmgcr: Implement multicore functions

2024-05-06 Thread Jiaxun Yang
We implemented following functions to allow software
to probe and control VPs on secondary core

- Reading out pcore count and coherence state
- Two scratch GCRs for firmware
- Semaphore GCR for register locking
- Redirect block to other cores

Signed-off-by: Jiaxun Yang 
---
 hw/misc/mips_cmgcr.c | 168 +++
 include/hw/misc/mips_cmgcr.h |  87 +++---
 2 files changed, 215 insertions(+), 40 deletions(-)

diff --git a/hw/misc/mips_cmgcr.c b/hw/misc/mips_cmgcr.c
index 2703040f45..8c2d184f2c 100644
--- a/hw/misc/mips_cmgcr.c
+++ b/hw/misc/mips_cmgcr.c
@@ -73,14 +73,19 @@ static inline void update_gic_base(MIPSGCRState *gcr, 
uint64_t val)
 static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size)
 {
 MIPSGCRState *gcr = (MIPSGCRState *) opaque;
-MIPSGCRVPState *current_vps = >vps[current_cpu->cpu_index];
-MIPSGCRVPState *other_vps = >vps[current_vps->other];
+int redirect_corenum = mips_gcr_get_redirect_corenum(gcr);
+int redirect_vpid = mips_gcr_get_redirect_vpid(gcr);
+int current_corenum = mips_gcr_get_current_corenum(gcr);
+int current_vpid = mips_gcr_get_current_vpid(gcr);
+MIPSGCRPCoreState *current_pcore = >pcs[current_corenum];
+MIPSGCRVPState *current_vps = _pcore->vps[current_vpid];
+MIPSGCRPCoreState *other_pcore = >pcs[redirect_corenum];
+MIPSGCRVPState *other_vps = _pcore->vps[redirect_vpid];
 
 switch (addr) {
 /* Global Control Block Register */
 case GCR_CONFIG_OFS:
-/* Set PCORES to 0 */
-return 0;
+return gcr->num_pcores - 1;
 case GCR_BASE_OFS:
 return gcr->gcr_base;
 case GCR_REV_OFS:
@@ -96,7 +101,19 @@ static uint64_t gcr_read(void *opaque, hwaddr addr, 
unsigned size)
 case GCR_L2_CONFIG_OFS:
 /* L2 BYPASS */
 return GCR_L2_CONFIG_BYPASS_MSK;
+case GCR_SYS_CONFIG2_OFS:
+return gcr->num_vps << GCR_SYS_CONFIG2_MAXVP_SHF;
+case GCR_SCRATCH0_OFS:
+return gcr->scratch[0];
+case GCR_SCRATCH1_OFS:
+return gcr->scratch[1];
+case GCR_SEM_OFS:
+return gcr->sem;
 /* Core-Local and Core-Other Control Blocks */
+case MIPS_CLCB_OFS + GCR_CL_COH_EN_OFS:
+return current_pcore->coh_en;
+case MIPS_COCB_OFS + GCR_CL_COH_EN_OFS:
+return other_pcore->coh_en;
 case MIPS_CLCB_OFS + GCR_CL_CONFIG_OFS:
 case MIPS_COCB_OFS + GCR_CL_CONFIG_OFS:
 /* Set PVP to # of VPs - 1 */
@@ -105,10 +122,18 @@ static uint64_t gcr_read(void *opaque, hwaddr addr, 
unsigned size)
 return current_vps->reset_base;
 case MIPS_COCB_OFS + GCR_CL_RESETBASE_OFS:
 return other_vps->reset_base;
-case MIPS_CLCB_OFS + GCR_CL_OTHER_OFS:
-return current_vps->other;
-case MIPS_COCB_OFS + GCR_CL_OTHER_OFS:
-return other_vps->other;
+case MIPS_CLCB_OFS + GCR_CL_REDIRECT_OFS:
+return current_vps->redirect;
+case MIPS_COCB_OFS + GCR_CL_REDIRECT_OFS:
+return other_vps->redirect;
+case MIPS_CLCB_OFS + GCR_CL_ID_OFS:
+return current_corenum;
+case MIPS_COCB_OFS + GCR_CL_ID_OFS:
+return redirect_corenum;
+case MIPS_CLCB_OFS + GCR_CL_SCRATCH_OFS:
+return current_vps->scratch;
+case MIPS_COCB_OFS + GCR_CL_SCRATCH_OFS:
+return other_vps->scratch;
 default:
 qemu_log_mask(LOG_UNIMP, "Read %d bytes at GCR offset 0x%" HWADDR_PRIx
   "\n", size, addr);
@@ -123,12 +148,36 @@ static inline target_ulong 
get_exception_base(MIPSGCRVPState *vps)
 return (int32_t)(vps->reset_base & GCR_CL_RESET_BASE_RESETBASE_MSK);
 }
 
+static inline void set_redirect(MIPSGCRState *gcr,
+MIPSGCRVPState *vps, target_ulong data)
+{
+int new_vpid = data & GCR_CL_REDIRECT_VP_MSK;
+int new_coreid = (data & GCR_CL_REDIRECT_CORE_MSK) >> 
GCR_CL_REDIRECT_CORE_SHF;
+
+if (new_vpid >= gcr->num_vps) {
+return;
+}
+
+if (new_coreid >= gcr->num_pcores) {
+return;
+}
+
+vps->redirect = data & (GCR_CL_REDIRECT_VP_MSK | GCR_CL_REDIRECT_CORE_MSK);
+}
+
 /* Write GCR registers */
 static void gcr_write(void *opaque, hwaddr addr, uint64_t data, unsigned size)
 {
-MIPSGCRState *gcr = (MIPSGCRState *)opaque;
-MIPSGCRVPState *current_vps = >vps[current_cpu->cpu_index];
-MIPSGCRVPState *other_vps = >vps[current_vps->other];
+MIPSGCRState *gcr = (MIPSGCRState *) opaque;
+int redirect_corenum = mips_gcr_get_redirect_corenum(gcr);
+int redirect_vpid = mips_gcr_get_redirect_vpid(gcr);
+int redirect_vpnum = mips_gcr_get_redirect_vpnum(gcr);
+int current_corenum = mips_gcr_get_current_corenum(gcr);
+int current_vpid = mips_gcr_get_current_vpid(gcr);
+MIPSGCRPCoreState *current_pcore = >pcs[current_corenum];
+

[PATCH 1/5] target/mips: Make globalnumber a CPU property

2024-05-06 Thread Jiaxun Yang
GlobalNumber marks topology information of a CPU instance.

Make it a CPU property to allow CPS to override topology information.

Signed-off-by: Jiaxun Yang 
---
 target/mips/cpu.c| 16 +++-
 target/mips/cpu.h| 10 +-
 target/mips/sysemu/machine.c |  5 ++---
 3 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index bbe01d07dd..762000d09b 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -296,7 +296,6 @@ static void mips_cpu_reset_hold(Object *obj, ResetType type)
 env->CP0_Random = env->tlb->nb_tlb - 1;
 env->tlb->tlb_in_use = env->tlb->nb_tlb;
 env->CP0_Wired = 0;
-env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
 env->CP0_EBase = KSEG0_BASE | (cs->cpu_index & 0x3FF);
 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
@@ -484,6 +483,12 @@ static void mips_cpu_realizefn(DeviceState *dev, Error 
**errp)
 
 env->exception_base = (int32_t)0xBFC0;
 
+#if !defined(CONFIG_USER_ONLY)
+if (env->CP0_GlobalNumber == -1) {
+env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
+}
+#endif
+
 #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
 mmu_init(env, env->cpu_model);
 #endif
@@ -563,6 +568,13 @@ static const TCGCPUOps mips_tcg_ops = {
 };
 #endif /* CONFIG_TCG */
 
+static Property mips_cpu_properties[] = {
+#if !defined(CONFIG_USER_ONLY)
+DEFINE_PROP_INT32("globalnumber", MIPSCPU, env.CP0_GlobalNumber, -1),
+#endif
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void mips_cpu_class_init(ObjectClass *c, void *data)
 {
 MIPSCPUClass *mcc = MIPS_CPU_CLASS(c);
@@ -592,6 +604,8 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
 #ifdef CONFIG_TCG
 cc->tcg_ops = _tcg_ops;
 #endif /* CONFIG_TCG */
+
+device_class_set_props(dc, mips_cpu_properties);
 }
 
 static const TypeInfo mips_cpu_type_info = {
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 3e906a175a..7499608678 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -612,8 +612,13 @@ typedef struct CPUArchState {
 # define CP0EnLo_RI 31
 # define CP0EnLo_XI 30
 #endif
-int32_t CP0_GlobalNumber;
+/* CP0_GlobalNumber is preserved across CPU reset. */
 #define CP0GN_VPId 0
+#define CP0GN_VPId_MASK (0xFFUL << CP0GN_VPId)
+#define CP0GN_CoreNum 8
+#define CP0GN_CoreNum_MASK (0xFUL << CP0GN_CoreNum)
+#define CP0GN_ClusterNum 16
+#define CP0GN_ClusterNum_MASK (0xFUL << CP0GN_ClusterNum)
 /*
  * CP0 Register 4
  */
@@ -1175,6 +1180,9 @@ typedef struct CPUArchState {
 struct {} end_reset_fields;
 
 /* Fields from here on are preserved across CPU reset. */
+#if !defined(CONFIG_USER_ONLY)
+int32_t CP0_GlobalNumber;
+#endif
 CPUMIPSMVPContext *mvp;
 #if !defined(CONFIG_USER_ONLY)
 CPUMIPSTLBContext *tlb;
diff --git a/target/mips/sysemu/machine.c b/target/mips/sysemu/machine.c
index 213fd637fc..235d640862 100644
--- a/target/mips/sysemu/machine.c
+++ b/target/mips/sysemu/machine.c
@@ -218,8 +218,8 @@ static const VMStateDescription vmstate_tlb = {
 
 const VMStateDescription vmstate_mips_cpu = {
 .name = "cpu",
-.version_id = 21,
-.minimum_version_id = 21,
+.version_id = 22,
+.minimum_version_id = 22,
 .post_load = cpu_post_load,
 .fields = (const VMStateField[]) {
 /* Active TC */
@@ -257,7 +257,6 @@ const VMStateDescription vmstate_mips_cpu = {
 VMSTATE_INT32(env.CP0_VPEOpt, MIPSCPU),
 VMSTATE_UINT64(env.CP0_EntryLo0, MIPSCPU),
 VMSTATE_UINT64(env.CP0_EntryLo1, MIPSCPU),
-VMSTATE_INT32(env.CP0_GlobalNumber, MIPSCPU),
 VMSTATE_UINTTL(env.CP0_Context, MIPSCPU),
 VMSTATE_INT32(env.CP0_MemoryMapID, MIPSCPU),
 VMSTATE_INT32(env.CP0_PageMask, MIPSCPU),

-- 
2.34.1




[PATCH 0/5] hw/mips: Proper multi core support

2024-05-06 Thread Jiaxun Yang
Hi all,

This series implemented propper multiple core support for MIPS
CPS systsm.

Previously all CPUs are being implemented as a smt thread in a
single core. Now it respects topology supplied in QEMU args.

To test:
Build a latest kernel with 64r6el_defconfig (tested on 6.6,
next-20240506).

Then run:
```
qemu-system-mips64el -M boston -cpu I6500 -kernel ~/linux-next/vmlinux -smp 
4,cores=2,threads=2 -append "console=ttyS0,115200" -nographic
```
In dmesg of guest kernel:
```
[0.00] VP topology {2,2} total 4
...
[0.085190] smp: Bringing up secondary CPUs ...
[0.090219] Primary instruction cache 64kB, VIPT, 4-way, linesize 64 bytes.
[0.095461] Primary data cache 64kB, 4-way, PIPT, no aliases, linesize 64 
bytes
[0.096658] CPU1 revision is: 0001b000 (MIPS I6500)
[0.096718] FPU revision is: 20f30300
[0.124711] Synchronize counters for CPU 1: done.
[0.940979] Primary instruction cache 64kB, VIPT, 4-way, linesize 64 bytes.
[0.941041] Primary data cache 64kB, 4-way, PIPT, no aliases, linesize 64 
bytes
[0.941256] CPU2 revision is: 0001b000 (MIPS I6500)
[0.941289] FPU revision is: 20f30300
[0.965322] Synchronize counters for CPU 2: done.
[1.260937] Primary instruction cache 64kB, VIPT, 4-way, linesize 64 bytes.
[1.261001] Primary data cache 64kB, 4-way, PIPT, no aliases, linesize 64 
bytes
[1.261172] CPU3 revision is: 0001b000 (MIPS I6500)
[1.261209] FPU revision is: 20f30300
[1.285390] Synchronize counters for CPU 3: done.
[1.346985] smp: Brought up 1 node, 4 CPUs
```

Please review.

Thanks

To: qemu-devel@nongnu.org
Cc: Philippe Mathieu-Daudé 

Signed-off-by: Jiaxun Yang 
---
Jiaxun Yang (5):
  target/mips: Make globalnumber a CPU property
  hw/msic/mips_cmgcr: Implement multicore functions
  hw/msic/mips_cpc: Implement multi core support
  hw/mips/cps: Implement multi core support
  hw/mips/boston: Implement multi core support

 hw/mips/boston.c |  37 +-
 hw/mips/cps.c|  66 ++---
 hw/misc/mips_cmgcr.c | 168 +++
 hw/misc/mips_cpc.c   |  97 ++---
 include/hw/mips/cps.h|   1 +
 include/hw/misc/mips_cmgcr.h |  87 +++---
 include/hw/misc/mips_cpc.h   |  15 +++-
 target/mips/cpu.c|  16 -
 target/mips/cpu.h|  10 ++-
 target/mips/sysemu/machine.c |   5 +-
 10 files changed, 403 insertions(+), 99 deletions(-)
---
base-commit: 248f6f62df073a3b4158fd0093863ab885feabb5
change-id: 20240506-mips-smp-9af9e71ad8c2

Best regards,
-- 
Jiaxun Yang 




[PATCH 4/5] hw/mips/cps: Implement multi core support

2024-05-06 Thread Jiaxun Yang
Implement multiple physical core support by creating
CPU devices accorading to the new topology and passing
pcore/vp information to CPC and CMGCR sub-devices.

Signed-off-by: Jiaxun Yang 
---
 hw/mips/cps.c | 66 +++
 include/hw/mips/cps.h |  1 +
 2 files changed, 41 insertions(+), 26 deletions(-)

diff --git a/hw/mips/cps.c b/hw/mips/cps.c
index 07b73b0a1f..6cf02379a9 100644
--- a/hw/mips/cps.c
+++ b/hw/mips/cps.c
@@ -73,31 +73,43 @@ static void mips_cps_realize(DeviceState *dev, Error **errp)
 return;
 }
 
-for (int i = 0; i < s->num_vp; i++) {
-MIPSCPU *cpu = MIPS_CPU(object_new(s->cpu_type));
-CPUMIPSState *env = >env;
+object_initialize_child(OBJECT(dev), "gcr", >gcr, TYPE_MIPS_GCR);
 
-/* All VPs are halted on reset. Leave powering up to CPC. */
-object_property_set_bool(OBJECT(cpu), "start-powered-off", true,
- _abort);
+for (int corenum = 0; corenum < s->num_pcore; corenum++) {
+for (int vpid = 0; vpid < s->num_vp; vpid++) {
+int vpnum = corenum * s->num_vp + vpid;
+int32_t globalnumber = (corenum << CP0GN_CoreNum) | vpid;
 
-/* All cores use the same clock tree */
-qdev_connect_clock_in(DEVICE(cpu), "clk-in", s->clock);
+MIPSCPU *cpu = MIPS_CPU(object_new(s->cpu_type));
+CPUMIPSState *env = >env;
 
-if (!qdev_realize_and_unref(DEVICE(cpu), NULL, errp)) {
-return;
-}
+/* All VPs are halted on reset. Leave powering up to CPC. */
+object_property_set_bool(OBJECT(cpu), "start-powered-off", true,
+_abort);
+
+object_property_set_int(OBJECT(cpu), "globalnumber", globalnumber,
+_abort);
+
+/* All cores use the same clock tree */
+qdev_connect_clock_in(DEVICE(cpu), "clk-in", s->clock);
+
+if (!qdev_realize_and_unref(DEVICE(cpu), NULL, errp)) {
+return;
+}
+
+g_assert(vpnum == CPU(cpu)->cpu_index);
 
-/* Init internal devices */
-cpu_mips_irq_init_cpu(cpu);
-cpu_mips_clock_init(cpu);
+/* Init internal devices */
+cpu_mips_irq_init_cpu(cpu);
+cpu_mips_clock_init(cpu);
 
-if (cpu_mips_itu_supported(env)) {
-itu_present = true;
-/* Attach ITC Tag to the VP */
-env->itc_tag = mips_itu_get_tag_region(>itu);
+if (cpu_mips_itu_supported(env)) {
+itu_present = true;
+/* Attach ITC Tag to the VP */
+env->itc_tag = mips_itu_get_tag_region(>itu);
+}
+qemu_register_reset(main_cpu_reset, cpu);
 }
-qemu_register_reset(main_cpu_reset, cpu);
 }
 
 /* Inter-Thread Communication Unit */
@@ -119,8 +131,12 @@ static void mips_cps_realize(DeviceState *dev, Error 
**errp)
 object_initialize_child(OBJECT(dev), "cpc", >cpc, TYPE_MIPS_CPC);
 object_property_set_uint(OBJECT(>cpc), "num-vp", s->num_vp,
 _abort);
+object_property_set_uint(OBJECT(>cpc), "num-pcore", s->num_pcore,
+_abort);
 object_property_set_int(OBJECT(>cpc), "vp-start-running", 1,
 _abort);
+object_property_set_link(OBJECT(>cpc), "gcr", OBJECT(>gcr),
+_abort);
 if (!sysbus_realize(SYS_BUS_DEVICE(>cpc), errp)) {
 return;
 }
@@ -130,7 +146,7 @@ static void mips_cps_realize(DeviceState *dev, Error **errp)
 
 /* Global Interrupt Controller */
 object_initialize_child(OBJECT(dev), "gic", >gic, TYPE_MIPS_GIC);
-object_property_set_uint(OBJECT(>gic), "num-vp", s->num_vp,
+object_property_set_uint(OBJECT(>gic), "num-vp", s->num_vp * 
s->num_pcore,
 _abort);
 object_property_set_uint(OBJECT(>gic), "num-irq", 128,
 _abort);
@@ -141,16 +157,13 @@ static void mips_cps_realize(DeviceState *dev, Error 
**errp)
 memory_region_add_subregion(>container, 0,
 sysbus_mmio_get_region(SYS_BUS_DEVICE(>gic), 
0));
 
-/* Global Configuration Registers */
-gcr_base = MIPS_CPU(first_cpu)->env.CP0_CMGCRBase << 4;
-
-object_initialize_child(OBJECT(dev), "gcr", >gcr, TYPE_MIPS_GCR);
+gcr_base = GCR_BASE_ADDR;
+object_property_set_uint(OBJECT(>gcr), "num-pcores", s->num_pcore,
+_abort);
 object_property_set_uint(OBJECT(>gcr), "num-vp"

[PATCH 3/5] hw/msic/mips_cpc: Implement multi core support

2024-05-06 Thread Jiaxun Yang
Implement multiple physical core support for MIPS CPC
controller. Including some R/O configuration registers
and VP bring up support on multiple cores.

Signed-off-by: Jiaxun Yang 
---
 hw/misc/mips_cpc.c | 97 ++
 include/hw/misc/mips_cpc.h | 15 ++-
 2 files changed, 85 insertions(+), 27 deletions(-)

diff --git a/hw/misc/mips_cpc.c b/hw/misc/mips_cpc.c
index 1e8fd2e699..f6a2f29088 100644
--- a/hw/misc/mips_cpc.c
+++ b/hw/misc/mips_cpc.c
@@ -25,9 +25,25 @@
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
 
+#include "hw/misc/mips_cmgcr.h"
 #include "hw/misc/mips_cpc.h"
 #include "hw/qdev-properties.h"
 
+static inline int cpc_vpnum_to_corenum(MIPSCPCState *cpc, int vpnum)
+{
+return vpnum / cpc->num_vp;
+}
+
+static inline int cpc_vpnum_to_vpid(MIPSCPCState *cpc, int vpnum)
+{
+return vpnum % cpc->num_vp;
+}
+
+static inline MIPSCPCPCoreState *cpc_vpnum_to_pcs(MIPSCPCState *cpc, int vpnum)
+{
+return >pcs[cpc_vpnum_to_corenum(cpc, vpnum)];
+}
+
 static inline uint64_t cpc_vp_run_mask(MIPSCPCState *cpc)
 {
 return (1ULL << cpc->num_vp) - 1;
@@ -39,36 +55,41 @@ static void mips_cpu_reset_async_work(CPUState *cs, 
run_on_cpu_data data)
 
 cpu_reset(cs);
 cs->halted = 0;
-cpc->vp_running |= 1ULL << cs->cpu_index;
+cpc_vpnum_to_pcs(cpc, cs->cpu_index)->vp_running |=
+1 << cpc_vpnum_to_vpid(cpc, cs->cpu_index);
 }
 
-static void cpc_run_vp(MIPSCPCState *cpc, uint64_t vp_run)
+static void cpc_run_vp(MIPSCPCState *cpc, int pcore, uint64_t vp_run)
 {
-CPUState *cs = first_cpu;
+MIPSCPCPCoreState *pcs = >pcs[pcore];
 
-CPU_FOREACH(cs) {
-uint64_t i = 1ULL << cs->cpu_index;
-if (i & vp_run & ~cpc->vp_running) {
+for (int vpid = 0; vpid < cpc->num_vp; vpid++) {
+if ((1 << vpid) & vp_run & ~pcs->vp_running) {
+int vpnum = pcore * cpc->num_vp + vpid;
 /*
  * To avoid racing with a CPU we are just kicking off.
  * We do the final bit of preparation for the work in
  * the target CPUs context.
  */
-async_safe_run_on_cpu(cs, mips_cpu_reset_async_work,
-  RUN_ON_CPU_HOST_PTR(cpc));
+async_safe_run_on_cpu(qemu_get_cpu(vpnum),
+mips_cpu_reset_async_work,
+RUN_ON_CPU_HOST_PTR(cpc));
+pcs->vp_running |= 1 << vpid;
 }
 }
 }
 
-static void cpc_stop_vp(MIPSCPCState *cpc, uint64_t vp_stop)
+static void cpc_stop_vp(MIPSCPCState *cpc, int pcore, uint64_t vp_stop)
 {
-CPUState *cs = first_cpu;
+MIPSCPCPCoreState *pcs = >pcs[pcore];
+
+for (int vpid = 0; vpid < cpc->num_vp; vpid++) {
+if ((1 << vpid) & vp_stop & pcs->vp_running) {
+int vpnum = pcore * cpc->num_vp + vpid;
+CPUState *cs = qemu_get_cpu(vpnum);
 
-CPU_FOREACH(cs) {
-uint64_t i = 1ULL << cs->cpu_index;
-if (i & vp_stop & cpc->vp_running) {
 cpu_interrupt(cs, CPU_INTERRUPT_HALT);
-cpc->vp_running &= ~i;
+pcs->vp_running &= ~(1 << vpid);
 }
 }
 }
@@ -77,15 +98,20 @@ static void cpc_write(void *opaque, hwaddr offset, uint64_t 
data,
   unsigned size)
 {
 MIPSCPCState *s = opaque;
+int current_corenum = cpc_vpnum_to_corenum(s, current_cpu->cpu_index);
 
 switch (offset) {
 case CPC_CL_BASE_OFS + CPC_VP_RUN_OFS:
+cpc_run_vp(s, current_corenum, data);
+break;
 case CPC_CO_BASE_OFS + CPC_VP_RUN_OFS:
-cpc_run_vp(s, data & cpc_vp_run_mask(s));
+cpc_run_vp(s, mips_gcr_get_redirect_corenum(s->gcr), data);
 break;
 case CPC_CL_BASE_OFS + CPC_VP_STOP_OFS:
+cpc_stop_vp(s, current_corenum, data);
+break;
 case CPC_CO_BASE_OFS + CPC_VP_STOP_OFS:
-cpc_stop_vp(s, data & cpc_vp_run_mask(s));
+cpc_stop_vp(s, mips_gcr_get_redirect_corenum(s->gcr), data);
 break;
 default:
 qemu_log_mask(LOG_UNIMP,
@@ -101,9 +127,13 @@ static uint64_t cpc_read(void *opaque, hwaddr offset, 
unsigned size)
 MIPSCPCState *s = opaque;
 
 switch (offset) {
+case CPC_CL_BASE_OFS + CPC_CL_STAT_CONF_OFS:
+case CPC_CO_BASE_OFS + CPC_CL_STAT_CONF_OFS:
+return CPC_CL_STAT_CONF_SEQ_STATE_U6 << CPC_CL_STAT_CONF_SEQ_STATE_SHF;
 case CPC_CL_BASE_OFS + CPC_VP_RUNNING_OFS:
+return cpc_vpnum_to_pcs(s, current_cpu->cpu_index)->vp_running;
 case CPC_CO_BASE_OFS + CPC_VP_RUNNING_OFS:
-return s->vp_running;
+return s->pcs[mips_gcr_get_redirect_corenum(s->gcr)].vp_running;
 default:

Re: [RFC PATCH 00/11] target/mips: Remove I6500 CPU definition

2024-02-09 Thread Jiaxun Yang




在 2024/2/9 09:05, Philippe Mathieu-Daudé 写道:

Alternative to:
https://lore.kernel.org/qemu-devel/20240209085347.8446-1-phi...@linaro.org/
If the I6500 can not be tested or its support is incomplete,
there is no point in wasting energy maintaining it.


Actually all SAAR and ITU stuff are optional for I6500 in real world so 
it's fine

to just leave I6500 defined without SAAR support.

The main difference between I6400 and I6500 is multi-cluster support, I do
have some patch for bringing proper multi-cluster support to QEMU, but
it can't work with boston due to address space limitations.

Should I give mips-virt stuff another go?

Thanks
- Jiaxun



Philippe Mathieu-Daudé (11):
   target/mips: Remove helpers accessing SAAR registers
   hw/misc/mips: Reduce itc_reconfigure() scope
   target/mips: Remove MIPSITUState::itu field
   target/mips: Remove CPUMIPSState::saarp field
   hw/misc/mips_itu: Remove MIPSITUState::cpu0 field
   hw/misc/mips_itu: Remove MIPSITUState::saar field
   target/mips: Remove CPUMIPSState::CP0_SAAR[2] field
   target/mips: Remove helpers accessing SAARI register
   target/mips: Remove CPUMIPSState::CP0_SAARI field
   target/mips: Remove the unused DisasContext::saar field
   target/mips: Remove I6500 CPU definition

  docs/about/removed-features.rst |  5 +++
  include/hw/misc/mips_itu.h  |  6 ---
  target/mips/cpu.h   |  4 --
  target/mips/tcg/translate.h |  1 -
  target/mips/tcg/sysemu_helper.h.inc |  6 ---
  hw/mips/cps.c   |  3 --
  hw/misc/mips_itu.c  | 35 ++--
  target/mips/sysemu/machine.c|  4 +-
  target/mips/tcg/sysemu/cp0_helper.c | 63 -
  target/mips/tcg/translate.c | 62 
  tests/qtest/machine-none-test.c |  2 +-
  target/mips/cpu-defs.c.inc  | 40 --
  12 files changed, 12 insertions(+), 219 deletions(-)



--
---
Jiaxun Yang




Re: why various devices are loading x86 roms on non-x86 architectures?

2024-01-31 Thread Jiaxun Yang




在 2024/1/31 10:28, Michael Tokarev 写道:

Hi!

qemu-system-aarch64 -device virtio-vga

this one loads vgabios-virtio.bin.  Why?
Does this bios work on aarch64 (or any other non-x86 arch)?
Should there may be some conditional in this and similar places?
The same is true for x86 pxe roms and other x86-only roms.


FYI on some systems they use x86emu (or biosemu) to run x86 only
OpROMs, this is at least true for u-boot (u-boot/drivers/bios_emulator),
PMON (MIPS/Loongson) and coreboot.

Thanks
- Jiaxun



Thanks,

/mjt



--
---
Jiaxun Yang




Re: [PATCH] target/mips: enable GINVx support for I6400 and I6500

2023-07-10 Thread Jiaxun Yang




在 2023/6/30 15:28, Marcin Nowakowski 写道:

GINVI and GINVT operations are supported on MIPS I6400 and I6500 cores,
so indicate that properly in CP0.Config5 register bits [16:15].

Signed-off-by: Marcin Nowakowski 


VZ is unimplemented in TCG so perhaps we should leave them as not supported?

Thanks
- Jiaxun


---
  target/mips/cpu-defs.c.inc | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/mips/cpu-defs.c.inc b/target/mips/cpu-defs.c.inc
index d45f245a67..da122e72d7 100644
--- a/target/mips/cpu-defs.c.inc
+++ b/target/mips/cpu-defs.c.inc
@@ -709,7 +709,7 @@ const mips_def_t mips_defs[] =
  .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (3 << CP0C4_IE) |
 (1 << CP0C4_AE) | (0xfc << CP0C4_KScrExist),
  .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_XNP) | (1 << CP0C5_VP) |
-   (1 << CP0C5_LLB) | (1 << CP0C5_MRP),
+   (1 << CP0C5_LLB) | (1 << CP0C5_MRP) | (3 << CP0C5_GI),
  .CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn) | (1 << CP0C5_SBRI) |
(1 << CP0C5_FRE) | (1 << CP0C5_UFE),
  .CP0_LLAddr_rw_bitmask = 0,
@@ -749,7 +749,7 @@ const mips_def_t mips_defs[] =
  .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (3 << CP0C4_IE) |
 (1 << CP0C4_AE) | (0xfc << CP0C4_KScrExist),
  .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_XNP) | (1 << CP0C5_VP) |
-   (1 << CP0C5_LLB) | (1 << CP0C5_MRP),
+   (1 << CP0C5_LLB) | (1 << CP0C5_MRP) | (3 << CP0C5_GI),
  .CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn) | (1 << CP0C5_SBRI) |
(1 << CP0C5_FRE) | (1 << CP0C5_UFE),
  .CP0_LLAddr_rw_bitmask = 0,





Re: [PATCH 1/4] hw/intc/loongarch_ipi: Bring back all 4 IPI mailboxes

2023-06-03 Thread Jiaxun Yang



> 2023年6月3日 01:28,Peter Maydell  写道:
> 
> On Sun, 21 May 2023 at 11:24, Jiaxun Yang  wrote:
>> 
>> As per "Loongson 3A5000/3B5000 Processor Reference Manual",
>> Loongson 3A5000's IPI implementation have 4 mailboxes per
>> core.
>> 
>> However, in 78464f023b54 ("hw/loongarch/virt: Modify ipi as
>> percpu device"), the number of IPI mailboxes was reduced to
>> one, which mismatches actual hardware.
>> 
>> It won't affect LoongArch based system as LoongArch boot code
>> only uses the first mailbox, however MIPS based Loongson boot
>> code uses all 4 mailboxes.
>> 
>> Fixes: 78464f023b54 ("hw/loongarch/virt: Modify ipi as percpu device")
>> Signed-off-by: Jiaxun Yang 
>> ---
>> hw/intc/loongarch_ipi.c | 6 +++---
>> include/hw/intc/loongarch_ipi.h | 4 +++-
>> 2 files changed, 6 insertions(+), 4 deletions(-)
>> 
>> diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
>> index d6ab91721ea1..3e453816524e 100644
>> --- a/hw/intc/loongarch_ipi.c
>> +++ b/hw/intc/loongarch_ipi.c
>> @@ -238,14 +238,14 @@ static void loongarch_ipi_init(Object *obj)
>> 
>> static const VMStateDescription vmstate_ipi_core = {
>> .name = "ipi-single",
>> -.version_id = 1,
>> -.minimum_version_id = 1,
>> +.version_id = 2,
>> +.minimum_version_id = 2,
>> .fields = (VMStateField[]) {
>> VMSTATE_UINT32(status, IPICore),
>> VMSTATE_UINT32(en, IPICore),
>> VMSTATE_UINT32(set, IPICore),
>> VMSTATE_UINT32(clear, IPICore),
>> -VMSTATE_UINT32_ARRAY(buf, IPICore, 2),
>> +VMSTATE_UINT32_ARRAY(buf, IPICore, IPI_MBX_NUM * 2),
>> VMSTATE_END_OF_LIST()
>> }
>> };
>> diff --git a/include/hw/intc/loongarch_ipi.h 
>> b/include/hw/intc/loongarch_ipi.h
>> index 664e050b926e..6c6194786e80 100644
>> --- a/include/hw/intc/loongarch_ipi.h
>> +++ b/include/hw/intc/loongarch_ipi.h
>> @@ -28,6 +28,8 @@
>> #define MAIL_SEND_OFFSET  0
>> #define ANY_SEND_OFFSET   (IOCSR_ANY_SEND - IOCSR_MAIL_SEND)
>> 
>> +#define IPI_MBX_NUM   4
>> +
>> #define TYPE_LOONGARCH_IPI "loongarch_ipi"
>> OBJECT_DECLARE_SIMPLE_TYPE(LoongArchIPI, LOONGARCH_IPI)
>> 
>> @@ -37,7 +39,7 @@ typedef struct IPICore {
>> uint32_t set;
>> uint32_t clear;
>> /* 64bit buf divide into 2 32bit buf */
>> -uint32_t buf[2];
>> +uint32_t buf[IPI_MBX_NUM * 2];
>> qemu_irq irq;
>> } IPICore;
> 
> In particular, this fixes Coverity issues CID 1512452 and 1512453,
> where Coverity notices that the code in loongarch_ipi_writel() and
> loongarch_ipi_readl() reads off the end of the too-short buf[].

LoongArch maintainers, do you mind to take this patch while I’m refactoring
rest of the series?

Thanks
Jiaxun

> 
> thanks
> -- PMM





Re: [PATCH 1/4] hw/intc/loongarch_ipi: Bring back all 4 IPI mailboxes

2023-05-23 Thread Jiaxun Yang



> 2023年5月23日 11:01,Song Gao  写道:
> 
> 
> 
> 在 2023/5/23 上午11:22, Jiaxun Yang 写道:
[...]
>> 
>>> 
>> Is totally the same on MIPS and LoongArch. I’m guarding them out because
>> We have different way to get IOCSR address space on MIPS, which is due
>> to be implemented.
>> 
>> I can further abstract out a function to get IOCSR address space. But still,
>> I think the best way to differ those two architecture is using TARGET_* 
>> macros,
>> as it doesn’t make much sense to have unused code for another architecture
>> compiled.
> Most of the code in hw/intc or hw/ uses property to distinguish between 
> different devices,  not TARGE_* macro.

They are the *same* device, with different way to handle IOCSR address space.

Another problem is casting CPUState with LOONGARCH_CPU() is something invalid on
MIPS, vice-versa. We are potentially introducing a security issue here.

I know nobody have done something like this before, but not necessarily to be a 
bad idea.

I’ll introduce something like:

+#ifdef TARGET_LOONGARCH64
+static inline void *AddressSpace get_iocsr_as(int cpuid)
+{
+CPUState *cs = qemu_get_cpu(cpuid);
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+
+return >env.address_space_iocsr;
+}
+#endif
+
+#ifdef TARGET_MIPS64
+static inline void *AddressSpace get_iocsr_as(int cpuid)
+{
+CPUState *cs = qemu_get_cpu(cpuid);
+MIPSCPU *cpu = MIPS_CPU(cs);
+
+return >env.iocsr.as;
+}
+#endif

Thanks
- Jiaxun

> 
> I still think it is better to use property.
> 
> Thanks.
> Song Gao
>>> All references to loongarch_ipi should also be changed.
>> Sure.
>> 
>> Thanks
>> - Jiaxun
> 




Re: [PATCH 1/4] hw/intc/loongarch_ipi: Bring back all 4 IPI mailboxes

2023-05-22 Thread Jiaxun Yang



> 2023年5月23日 02:25,Song Gao  写道:
> 
> 
> 
> 在 2023/5/22 下午9:44, Philippe Mathieu-Daudé 写道:
>> On 22/5/23 13:47, Jiaxun Yang wrote:
>>> 
>>> 
>>>> 2023年5月22日 04:52,Huacai Chen  写道:
>>>> 
>>>> Hi, Jiaxun,
>>>> 
>>>> Rename loongarch_ipi to loongson_ipi? It will be shared by both MIPS
>>>> and LoongArch in your series.
>>> 
>>> Hi Huacai,
>>> 
>>> Thanks for the point, what’s the opinion from LoongArch mainatiners?
>>> 
>>> Or perhaps rename it as loong_ipi to reflect the nature that it’s shared
>>> by MIPS based Loongson and LoongArch based Loongson?
>> 
>> I'm not a LoongArch maintainer, but a model named "loong_ipi" makes
>> sense to me.
>> 
>> Please add it to the two Virt machine sections in MAINTAINERS.

Hi Song,

>> 
> 'loonggson_ipi' is better, qemu doesn't have naming with 'loong' as prefix.

Thanks, I’ll take looongson_ipi then.

> 
> And  patch2 should not use macros. Some attributes should be added to 
> distinguish between MIPS and LongArch.

By attribute do you mean property? If so I don’t see any necessity, the IP block
Is totally the same on MIPS and LoongArch. I’m guarding them out because
We have different way to get IOCSR address space on MIPS, which is due
to be implemented.

I can further abstract out a function to get IOCSR address space. But still,
I think the best way to differ those two architecture is using TARGET_* macros,
as it doesn’t make much sense to have unused code for another architecture
compiled.

> 
> All references to loongarch_ipi should also be changed.
Sure.

Thanks
- Jiaxun

> 
> Thanks.
> Song Gao





Re: [PATCH 2/2] hw/mips/loongson3_virt: Remove CPU restrictions for TCG

2023-05-22 Thread Jiaxun Yang



> 2023年5月22日 13:08,Philippe Mathieu-Daudé  写道:
> 
> On 21/5/23 23:48, Jiaxun Yang wrote:
>> After implemented CPUCFG and CSR, we are now able to boot Linux
>> kernel with Loongson-3A4000 CPU, so there is no point to restrict
>> CPU type for TCG.
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1639
> ?

Potentially yes, although I think the issue itself is just a question on usage
of the board.

Thanks
- Jiaxun

> 
>> Signed-off-by: Jiaxun Yang 
>> ---
>>  hw/mips/loongson3_virt.c | 4 
>>  1 file changed, 4 deletions(-)
> 
> 




Re: [PATCH 1/4] hw/intc/loongarch_ipi: Bring back all 4 IPI mailboxes

2023-05-22 Thread Jiaxun Yang



> 2023年5月22日 04:52,Huacai Chen  写道:
> 
> Hi, Jiaxun,
> 
> Rename loongarch_ipi to loongson_ipi? It will be shared by both MIPS
> and LoongArch in your series.

Hi Huacai,

Thanks for the point, what’s the opinion from LoongArch mainatiners?

Or perhaps rename it as loong_ipi to reflect the nature that it’s shared
by MIPS based Loongson and LoongArch based Loongson?

Thanks
- Jiaxun

> 
> 
> Huacai
> 
> On Sun, May 21, 2023 at 6:24 PM Jiaxun Yang  wrote:
>> 
>> As per "Loongson 3A5000/3B5000 Processor Reference Manual",
>> Loongson 3A5000's IPI implementation have 4 mailboxes per
>> core.
>> 
>> However, in 78464f023b54 ("hw/loongarch/virt: Modify ipi as
>> percpu device"), the number of IPI mailboxes was reduced to
>> one, which mismatches actual hardware.
>> 
>> It won't affect LoongArch based system as LoongArch boot code
>> only uses the first mailbox, however MIPS based Loongson boot
>> code uses all 4 mailboxes.
>> 
>> Fixes: 78464f023b54 ("hw/loongarch/virt: Modify ipi as percpu device")
>> Signed-off-by: Jiaxun Yang 
>> ---
>> hw/intc/loongarch_ipi.c | 6 +++---
>> include/hw/intc/loongarch_ipi.h | 4 +++-
>> 2 files changed, 6 insertions(+), 4 deletions(-)
>> 
>> diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
>> index d6ab91721ea1..3e453816524e 100644
>> --- a/hw/intc/loongarch_ipi.c
>> +++ b/hw/intc/loongarch_ipi.c
>> @@ -238,14 +238,14 @@ static void loongarch_ipi_init(Object *obj)
>> 
>> static const VMStateDescription vmstate_ipi_core = {
>> .name = "ipi-single",
>> -.version_id = 1,
>> -.minimum_version_id = 1,
>> +.version_id = 2,
>> +.minimum_version_id = 2,
>> .fields = (VMStateField[]) {
>> VMSTATE_UINT32(status, IPICore),
>> VMSTATE_UINT32(en, IPICore),
>> VMSTATE_UINT32(set, IPICore),
>> VMSTATE_UINT32(clear, IPICore),
>> -VMSTATE_UINT32_ARRAY(buf, IPICore, 2),
>> +VMSTATE_UINT32_ARRAY(buf, IPICore, IPI_MBX_NUM * 2),
>> VMSTATE_END_OF_LIST()
>> }
>> };
>> diff --git a/include/hw/intc/loongarch_ipi.h 
>> b/include/hw/intc/loongarch_ipi.h
>> index 664e050b926e..6c6194786e80 100644
>> --- a/include/hw/intc/loongarch_ipi.h
>> +++ b/include/hw/intc/loongarch_ipi.h
>> @@ -28,6 +28,8 @@
>> #define MAIL_SEND_OFFSET  0
>> #define ANY_SEND_OFFSET   (IOCSR_ANY_SEND - IOCSR_MAIL_SEND)
>> 
>> +#define IPI_MBX_NUM   4
>> +
>> #define TYPE_LOONGARCH_IPI "loongarch_ipi"
>> OBJECT_DECLARE_SIMPLE_TYPE(LoongArchIPI, LOONGARCH_IPI)
>> 
>> @@ -37,7 +39,7 @@ typedef struct IPICore {
>> uint32_t set;
>> uint32_t clear;
>> /* 64bit buf divide into 2 32bit buf */
>> -uint32_t buf[2];
>> +uint32_t buf[IPI_MBX_NUM * 2];
>> qemu_irq irq;
>> } IPICore;
>> 
>> --
>> 2.39.2 (Apple Git-143)
>> 




[PATCH 0/2] MIPS: Enable Loongson-3A4000 TCG for system emulation

2023-05-21 Thread Jiaxun Yang
Hi there,

This series enables Loongson-3A4000 TCG for system emulation.
It Implemented Loongson CSR insertions which is required for
Linux Kernel to probe CPU features and removed CPU type restrictions
for loongson3_virt board.

This series is based on two of my previous series[1] [2]. However it's
just a soft dependency for me to do boot test, feel free to apply this
series without them.

Note that loongarch_ipi is still not hooked up in IOCSR. I've sucessfully
done it locally but I just want to confirm some details on hardware.

Thanks
- Jiaxun

[1]: 
https://lore.kernel.org/qemu-devel/20230521102307.87081-1-jiaxun.y...@flygoat.com/T/#t
[2]: 
https://lore.kernel.org/qemu-devel/0bb0cded-8450-536e-b90f-1a9d33311...@linaro.org/T/#t

Jiaxun Yang (2):
  target/mips: Implement Loongson CSR instructions
  hw/mips/loongson3_virt: Remove CPU restrictions for TCG

 hw/mips/loongson3_virt.c |  4 --
 target/mips/cpu-defs.c.inc   |  9 
 target/mips/cpu.c|  8 
 target/mips/cpu.h| 40 
 target/mips/helper.h |  4 ++
 target/mips/internal.h   |  2 +
 target/mips/tcg/lcsr.decode  | 17 +++
 target/mips/tcg/lcsr_translate.c | 69 
 target/mips/tcg/meson.build  |  2 +
 target/mips/tcg/op_helper.c  | 16 +++
 target/mips/tcg/sysemu/lcsr_helper.c | 45 ++
 target/mips/tcg/sysemu/meson.build   |  4 ++
 target/mips/tcg/sysemu_helper.h.inc  |  8 
 target/mips/tcg/translate.c  |  3 ++
 target/mips/tcg/translate.h  |  7 +++
 15 files changed, 234 insertions(+), 4 deletions(-)
 create mode 100644 target/mips/tcg/lcsr.decode
 create mode 100644 target/mips/tcg/lcsr_translate.c
 create mode 100644 target/mips/tcg/sysemu/lcsr_helper.c

-- 
2.39.2 (Apple Git-143)




[PATCH 2/2] hw/mips/loongson3_virt: Remove CPU restrictions for TCG

2023-05-21 Thread Jiaxun Yang
After implemented CPUCFG and CSR, we are now able to boot Linux
kernel with Loongson-3A4000 CPU, so there is no point to restrict
CPU type for TCG.

Signed-off-by: Jiaxun Yang 
---
 hw/mips/loongson3_virt.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index a57245012598..47289fb6bf85 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -488,10 +488,6 @@ static void mips_loongson3_virt_init(MachineState *machine)
 if (!machine->cpu_type) {
 machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A1000");
 }
-if (!strstr(machine->cpu_type, "Loongson-3A1000")) {
-error_report("Loongson-3/TCG needs cpu type Loongson-3A1000");
-exit(1);
-}
 } else {
 if (!machine->cpu_type) {
 machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A4000");
-- 
2.39.2 (Apple Git-143)




[PATCH 1/2] target/mips: Implement Loongson CSR instructions

2023-05-21 Thread Jiaxun Yang
Loongson introduced CSR instructions since 3A4000, which looks
similar to IOCSR and CPUCFG instructions we seen in LoongArch.

Unfortunately we don't have much document about those instructions,
bit fields of CPUCFG instructions and IOCSR registers can be found
at 3A4000's user manual, while instruction encodings can be found
at arch/mips/include/asm/mach-loongson64/loongson_regs.h from
Linux Kernel.

Our predefined CPUCFG bits are differ from actual 3A4000, since
we can't emulate all CPUCFG features present in 3A4000 for now,
we just enable bits for what we have in TCG.

Signed-off-by: Jiaxun Yang 
---
 target/mips/cpu-defs.c.inc   |  9 
 target/mips/cpu.c|  8 
 target/mips/cpu.h| 40 
 target/mips/helper.h |  4 ++
 target/mips/internal.h   |  2 +
 target/mips/tcg/lcsr.decode  | 17 +++
 target/mips/tcg/lcsr_translate.c | 69 
 target/mips/tcg/meson.build  |  2 +
 target/mips/tcg/op_helper.c  | 16 +++
 target/mips/tcg/sysemu/lcsr_helper.c | 45 ++
 target/mips/tcg/sysemu/meson.build   |  4 ++
 target/mips/tcg/sysemu_helper.h.inc  |  8 
 target/mips/tcg/translate.c  |  3 ++
 target/mips/tcg/translate.h  |  7 +++
 14 files changed, 234 insertions(+)
 create mode 100644 target/mips/tcg/lcsr.decode
 create mode 100644 target/mips/tcg/lcsr_translate.c
 create mode 100644 target/mips/tcg/sysemu/lcsr_helper.c

diff --git a/target/mips/cpu-defs.c.inc b/target/mips/cpu-defs.c.inc
index d45f245a6718..167c96cb2748 100644
--- a/target/mips/cpu-defs.c.inc
+++ b/target/mips/cpu-defs.c.inc
@@ -895,6 +895,15 @@ const mips_def_t mips_defs[] =
 .CP1_fcr31 = 0,
 .CP1_fcr31_rw_bitmask = 0xFF83,
 .MSAIR = (0x01 << MSAIR_ProcID) | (0x40 << MSAIR_Rev),
+.lcsr_cpucfg1 = (1 << CPUCFG1_FP) | (2 << CPUCFG1_FPREV) |
+(1 << CPUCFG1_MSA1) | (1 << CPUCFG1_LSLDR0) |
+(1 << CPUCFG1_LSPERF) | (1 << CPUCFG1_LSPERFX) |
+(1 << CPUCFG1_LSSYNCI) | (1 << CPUCFG1_LLEXC) |
+(1 << CPUCFG1_SCRAND) | (1 << CPUCFG1_MUALP) |
+(1 << CPUCFG1_KMUALEN) | (1 << CPUCFG1_ITLBT) |
+(1 << CPUCFG1_SFBP) | (1 << CPUCFG1_CDMAP),
+.lcsr_cpucfg2 = (1 << CPUCFG2_LEXT1) | (1 << CPUCFG2_LCSRP) |
+(1 << CPUCFG2_LDISBLIKELY),
 .SEGBITS = 48,
 .PABITS = 48,
 .insn_flags = CPU_MIPS64R2 | INSN_LOONGSON3A |
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index b7119cbbb459..e675b9178192 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -244,6 +244,8 @@ static void mips_cpu_reset_hold(Object *obj)
 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
+env->lcsr_cpucfg1 = env->cpu_model->lcsr_cpucfg1;
+env->lcsr_cpucfg2 = env->cpu_model->lcsr_cpucfg2;
 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
@@ -507,6 +509,12 @@ static void mips_cpu_initfn(Object *obj)
 cpu->count_div = clock_new(OBJECT(obj), "clk-div-count");
 env->count_clock = clock_new(OBJECT(obj), "clk-count");
 env->cpu_model = mcc->cpu_def;
+if (mcc->cpu_def->lcsr_cpucfg2 & (1 << CPUCFG2_LCSRP)) {
+memory_region_init_io(>system_iocsr, OBJECT(cpu), NULL,
+env, "iocsr", UINT64_MAX);
+address_space_init(>address_space_iocsr,
+>system_iocsr, "IOCSR");
+}
 }
 
 static char *mips_cpu_type_name(const char *cpu_model)
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 1b8107b0af86..f63b128ff3d3 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -3,6 +3,9 @@
 
 #include "cpu-qom.h"
 #include "exec/cpu-defs.h"
+#ifndef CONFIG_USER_ONLY
+#include "exec/memory.h"
+#endif
 #include "fpu/softfloat-types.h"
 #include "hw/clock.h"
 #include "mips-defs.h"
@@ -1068,6 +1071,33 @@ typedef struct CPUArchState {
  */
 int32_t CP0_DESAVE;
 target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
+/*
+ * Loongson CSR CPUCFG registers
+ */
+uint32_t lcsr_cpucfg1;
+#define CPUCFG1_FP 0
+#define CPUCFG1_FPREV  1
+#define CPUCFG1_MMI4
+#define CPUCFG1_MSA1   5
+#define CPUCFG1_MSA2   6
+#define CPUCFG1_LSLDR0 16
+#define CPUCFG1_LSPERF 17
+#define CPUCFG1_LSPERFX 18
+#define CPUCFG1_LSSYNCI 19
+#d

[PATCH] target/mips: Rework cp0_timer with clock API

2023-05-21 Thread Jiaxun Yang
Previous implementation of MIPS cp0_timer computes a
cp0_count_ns based on input clock. However rounding
error of cp0_count_ns can affect precision of cp0_timer.

Using clock API and a divider for cp0_timer, so we can
use clock_ns_to_ticks/clock_ns_to_ticks to avoid rounding
issue.

Also workaround the situation that in such handler flow:

count = read_c0_count()
write_c0_compare(count)

If timer had not progressed when compare was written, the
interrupt would trigger again.

Signed-off-by: Jiaxun Yang 
---
This seems fixed MTTCG booting issue on malta 5kEc with SMP.
I'm going to do more test and see if we can enable MTTCG for
mips64el.
---
 target/mips/cpu.c  |  8 +---
 target/mips/cpu.h  |  3 ++-
 target/mips/sysemu/cp0_timer.c | 35 ++
 3 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index 01e0fbe10db2..b7119cbbb459 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -449,9 +449,9 @@ static void mips_cp0_period_set(MIPSCPU *cpu)
 {
 CPUMIPSState *env = >env;
 
-env->cp0_count_ns = clock_ticks_to_ns(MIPS_CPU(cpu)->clock,
-  env->cpu_model->CCRes);
-assert(env->cp0_count_ns);
+clock_set_mul_div(cpu->count_div, env->cpu_model->CCRes, 1);
+clock_set_source(cpu->count_div, cpu->clock);
+clock_set_source(env->count_clock, cpu->count_div);
 }
 
 static void mips_cpu_realizefn(DeviceState *dev, Error **errp)
@@ -504,6 +504,8 @@ static void mips_cpu_initfn(Object *obj)
 
 cpu_set_cpustate_pointers(cpu);
 cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu, 0);
+cpu->count_div = clock_new(OBJECT(obj), "clk-div-count");
+env->count_clock = clock_new(OBJECT(obj), "clk-count");
 env->cpu_model = mcc->cpu_def;
 }
 
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 142c55af478b..1b8107b0af86 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -1160,8 +1160,8 @@ typedef struct CPUArchState {
 
 const mips_def_t *cpu_model;
 QEMUTimer *timer; /* Internal timer */
+Clock *count_clock; /* CP0_Count clock */
 target_ulong exception_base; /* ExceptionBase input to the core */
-uint64_t cp0_count_ns; /* CP0_Count clock period (in nanoseconds) */
 } CPUMIPSState;
 
 /**
@@ -1178,6 +1178,7 @@ struct ArchCPU {
 /*< public >*/
 
 Clock *clock;
+Clock *count_div; /* Divider for CP0_Count clock */
 CPUNegativeOffsetState neg;
 CPUMIPSState env;
 };
diff --git a/target/mips/sysemu/cp0_timer.c b/target/mips/sysemu/cp0_timer.c
index 70de95d338f8..9d2bcb0dea21 100644
--- a/target/mips/sysemu/cp0_timer.c
+++ b/target/mips/sysemu/cp0_timer.c
@@ -28,15 +28,26 @@
 #include "internal.h"
 
 /* MIPS R4K timer */
+static uint32_t cpu_mips_get_count_val(CPUMIPSState *env)
+{
+int64_t now_ns;
+now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+return env->CP0_Count +
+(uint32_t)clock_ns_to_ticks(env->count_clock, now_ns);
+}
+
 static void cpu_mips_timer_update(CPUMIPSState *env)
 {
 uint64_t now_ns, next_ns;
 uint32_t wait;
 
 now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-wait = env->CP0_Compare - env->CP0_Count -
-   (uint32_t)(now_ns / env->cp0_count_ns);
-next_ns = now_ns + (uint64_t)wait * env->cp0_count_ns;
+wait = env->CP0_Compare - cpu_mips_get_count_val(env);
+/* Clamp interval to overflow if virtual time had not progressed */
+if (!wait) {
+wait = UINT32_MAX;
+}
+next_ns = now_ns + clock_ticks_to_ns(env->count_clock, wait);
 timer_mod(env->timer, next_ns);
 }
 
@@ -64,7 +75,7 @@ uint32_t cpu_mips_get_count(CPUMIPSState *env)
 cpu_mips_timer_expire(env);
 }
 
-return env->CP0_Count + (uint32_t)(now_ns / env->cp0_count_ns);
+return cpu_mips_get_count_val(env);
 }
 }
 
@@ -79,9 +90,8 @@ void cpu_mips_store_count(CPUMIPSState *env, uint32_t count)
 env->CP0_Count = count;
 } else {
 /* Store new count register */
-env->CP0_Count = count -
-   (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) /
-  env->cp0_count_ns);
+env->CP0_Count = count - (uint32_t)clock_ns_to_ticks(env->count_clock,
+qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
 /* Update timer timer */
 cpu_mips_timer_update(env);
 }
@@ -107,8 +117,8 @@ void cpu_mips_start_count(CPUMIPSState *env)
 void cpu_mips_stop_count(CPUMIPSState *env)
 {
 /* Store the current value */
-env->CP0_Count += (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) /
- env->cp0_count_ns);
+env->CP0_Count += (uint32_t)clock_ns_to_ticks(env->count_clock,
+qe

[PATCH 4/4] tests/avocado: Add boot_linux_console test for loongson3-virt

2023-05-21 Thread Jiaxun Yang
Test loongson3-virt machine againt debian kernel and cpio rootfs.

Signed-off-by: Jiaxun Yang 
---
 tests/avocado/boot_linux_console.py | 46 +
 1 file changed, 46 insertions(+)

diff --git a/tests/avocado/boot_linux_console.py 
b/tests/avocado/boot_linux_console.py
index c0675809e641..fdb479448e47 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -191,6 +191,52 @@ def test_mips64el_fuloong2e(self):
 console_pattern = 'Kernel command line: %s' % kernel_command_line
 self.wait_for_console_pattern(console_pattern)
 
+def test_mips64el_loongson3_virt_cpio(self):
+"""
+:avocado: tags=arch:mips64el
+:avocado: tags=endian:little
+:avocado: tags=machine:loongson3-virt
+:avocado: tags=cpu:Loongson-3A1000
+:avocado: tags=device:liointc
+:avocado: tags=device:loongarch_ipi
+:avocado: tags=device:goldfish_rtc
+"""
+deb_url = ('http://snapshot.debian.org/archive/debian/'
+   '20230501T024743Z/pool/main/l/linux/'
+   'linux-image-5.10.0-22-loongson-3_5.10.178-3_mips64el.deb')
+deb_hash = 'af4fcc721b727df0bef31057325e4cc02725ae0c'
+deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+kernel_path = self.extract_from_deb(deb_path,
+'/boot/vmlinuz-5.10.0-22-loongson-3')
+initrd_url = ('https://github.com/groeck/linux-build-test/'
+  'raw/8584a59e/rootfs/'
+  'mipsel64/rootfs.mipsel64r1.cpio.gz')
+initrd_hash = '1dbb8a396e916847325284dbe2151167'
+initrd_path_gz = self.fetch_asset(initrd_url, algorithm='md5',
+  asset_hash=initrd_hash)
+initrd_path = self.workdir + "rootfs.cpio"
+archive.gzip_uncompress(initrd_path_gz, initrd_path)
+
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE
+   + 'console=ttyS0,115200 '
+   + 'rdinit=/sbin/init noreboot')
+self.vm.add_args('-kernel', kernel_path,
+ '-initrd', initrd_path,
+ '-append', kernel_command_line,
+ '-no-reboot')
+self.vm.launch()
+wait_for_console_pattern(self, 'Boot successful.')
+
+exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
+'ICT Loongson-3')
+exec_command_and_wait_for_pattern(self, 'uname -a',
+'5.10.0-22-loongson-3')
+exec_command_and_wait_for_pattern(self, 'reboot',
+'reboot: Restarting system')
+# Wait for VM to shut down gracefully
+self.vm.wait()
+
 def test_mips_malta_cpio(self):
 """
 :avocado: tags=arch:mips
-- 
2.39.2 (Apple Git-143)




[PATCH 2/4] hw/intc/loongarch_ipi: Guard LoongArch only features with ifdef

2023-05-21 Thread Jiaxun Yang
IOCSR based send features are tied to LoongArch's CPU implmentation,
ifdef them for LoongArch only so we can build loongarch_ipi on MIPS.

Note that Loongson-3A4000 have IOCSR as well, so we may implement
those features for MIPS in future.

Signed-off-by: Jiaxun Yang 
---
 hw/intc/loongarch_ipi.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
index 3e453816524e..895a2ee96e1e 100644
--- a/hw/intc/loongarch_ipi.c
+++ b/hw/intc/loongarch_ipi.c
@@ -50,6 +50,7 @@ static uint64_t loongarch_ipi_readl(void *opaque, hwaddr 
addr, unsigned size)
 return ret;
 }
 
+#ifdef TARGET_LOONGARCH64
 static void send_ipi_data(CPULoongArchState *env, uint64_t val, hwaddr addr)
 {
 int i, mask = 0, data = 0;
@@ -140,6 +141,25 @@ static void any_send(uint64_t val)
 env = >env;
 send_ipi_data(env, val, addr);
 }
+#else
+static void ipi_send(uint64_t val)
+{
+qemu_log_mask(LOG_UNIMP, "%s: Unimplemented send 0x%" PRIx64 "\n",
+__func__, val);
+}
+
+static void mail_send(uint64_t val)
+{
+qemu_log_mask(LOG_UNIMP, "%s: Unimplemented send 0x%" PRIx64 "\n",
+__func__, val);
+}
+
+static void any_send(uint64_t val)
+{
+qemu_log_mask(LOG_UNIMP, "%s: Unimplemented send 0x%" PRIx64 "\n",
+__func__, val);
+}
+#endif
 
 static void loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
  unsigned size)
-- 
2.39.2 (Apple Git-143)




[PATCH 0/4] hw/mips/loongson3_virt: Wire up loongarch_ipi device

2023-05-21 Thread Jiaxun Yang
Hi all,

This series wires up loongarch_ipi device for loongson3-virt,
which is required for SMP support.

We also add a new test for loongson3-virt for acceptance harness.

Thanks
- Jiaxun

Jiaxun Yang (4):
  hw/intc/loongarch_ipi: Bring back all 4 IPI mailboxes
  hw/intc/loongarch_ipi: Guard LoongArch only features with ifdef
  hw/mips/loongson3_virt: Wire up loongarch_ipi device
  tests/avocado: Add boot_linux_console test for loongson3-virt

 hw/intc/loongarch_ipi.c | 26 ++--
 hw/mips/Kconfig |  1 +
 hw/mips/loongson3_bootp.c   |  2 --
 hw/mips/loongson3_bootp.h   |  3 ++
 hw/mips/loongson3_virt.c| 20 +++--
 include/hw/intc/loongarch_ipi.h |  4 ++-
 tests/avocado/boot_linux_console.py | 46 +
 7 files changed, 94 insertions(+), 8 deletions(-)

-- 
2.39.2 (Apple Git-143)




[PATCH 3/4] hw/mips/loongson3_virt: Wire up loongarch_ipi device

2023-05-21 Thread Jiaxun Yang
Wire up loongarch_ipi device for loongson3_virt machine, so we
can have SMP support for TCG backend as well.

Signed-off-by: Jiaxun Yang 
---
 hw/mips/Kconfig   |  1 +
 hw/mips/loongson3_bootp.c |  2 --
 hw/mips/loongson3_bootp.h |  3 +++
 hw/mips/loongson3_virt.c  | 20 ++--
 4 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index da3a37e215ec..7cb6c1def16c 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -40,6 +40,7 @@ config LOONGSON3V
 imply QXL if SPICE
 select SERIAL
 select GOLDFISH_RTC
+select LOONGARCH_IPI
 select LOONGSON_LIOINTC
 select PCI_DEVICES
 select PCI_EXPRESS_GENERIC_BRIDGE
diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
index f99af229327a..474d3556b2e5 100644
--- a/hw/mips/loongson3_bootp.c
+++ b/hw/mips/loongson3_bootp.c
@@ -25,8 +25,6 @@
 #include "hw/boards.h"
 #include "hw/mips/loongson3_bootp.h"
 
-#define LOONGSON3_CORE_PER_NODE 4
-
 static void init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
 {
 struct efi_cpuinfo_loongson *c = g_cpuinfo;
diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h
index d525ab745a69..55f98858a5f4 100644
--- a/hw/mips/loongson3_bootp.h
+++ b/hw/mips/loongson3_bootp.h
@@ -200,6 +200,8 @@ struct boot_params {
 struct efi_reset_system_t reset_system;
 };
 
+#define LOONGSON3_CORE_PER_NODE 4
+
 /* Overall MMIO & Memory layout */
 enum {
 VIRT_LOWMEM,
@@ -211,6 +213,7 @@ enum {
 VIRT_BIOS_ROM,
 VIRT_UART,
 VIRT_LIOINTC,
+VIRT_IPI,
 VIRT_PCIE_MMIO,
 VIRT_HIGHMEM
 };
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index 25534288dd81..a57245012598 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -38,6 +38,7 @@
 #include "hw/mips/loongson3_bootp.h"
 #include "hw/misc/unimp.h"
 #include "hw/intc/i8259.h"
+#include "hw/intc/loongarch_ipi.h"
 #include "hw/loader.h"
 #include "hw/isa/superio.h"
 #include "hw/pci/msi.h"
@@ -76,6 +77,7 @@ const MemMapEntry virt_memmap[] = {
 [VIRT_PCIE_ECAM] =   { 0x1a00, 0x200 },
 [VIRT_BIOS_ROM] ={ 0x1fc0,  0x20 },
 [VIRT_UART] ={ 0x1fe001e0,   0x8 },
+[VIRT_IPI] = { 0x3ff01000, 0x400 },
 [VIRT_LIOINTC] = { 0x3ff01400,  0x64 },
 [VIRT_PCIE_MMIO] =   { 0x4000,0x4000 },
 [VIRT_HIGHMEM] = { 0x8000,   0x0 }, /* Variable */
@@ -529,6 +531,8 @@ static void mips_loongson3_virt_init(MachineState *machine)
 clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ);
 
 for (i = 0; i < machine->smp.cpus; i++) {
+int node = i / LOONGSON3_CORE_PER_NODE;
+int core = i % LOONGSON3_CORE_PER_NODE;
 int ip;
 
 /* init CPUs */
@@ -539,12 +543,24 @@ static void mips_loongson3_virt_init(MachineState 
*machine)
 cpu_mips_clock_init(cpu);
 qemu_register_reset(main_cpu_reset, cpu);
 
-if (i >= 4) {
+/* IPI controller is in kernel for KVM */
+if (!kvm_enabled()) {
+DeviceState *ipi;
+
+hwaddr base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base;
+base += core * 0x100;
+ipi = qdev_new(TYPE_LOONGARCH_IPI);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), _fatal);
+qdev_connect_gpio_out(ipi, 0, cpu->env.irq[6]);
+sysbus_mmio_map(SYS_BUS_DEVICE(ipi), 0, base);
+}
+
+if (node > 0) {
 continue; /* Only node-0 can be connected to LIOINTC */
 }
 
 for (ip = 0; ip < 4 ; ip++) {
-int pin = i * 4 + ip;
+int pin = core * LOONGSON3_CORE_PER_NODE + ip;
 sysbus_connect_irq(SYS_BUS_DEVICE(liointc),
pin, cpu->env.irq[ip + 2]);
 }
-- 
2.39.2 (Apple Git-143)




[PATCH 1/4] hw/intc/loongarch_ipi: Bring back all 4 IPI mailboxes

2023-05-21 Thread Jiaxun Yang
As per "Loongson 3A5000/3B5000 Processor Reference Manual",
Loongson 3A5000's IPI implementation have 4 mailboxes per
core.

However, in 78464f023b54 ("hw/loongarch/virt: Modify ipi as
percpu device"), the number of IPI mailboxes was reduced to
one, which mismatches actual hardware.

It won't affect LoongArch based system as LoongArch boot code
only uses the first mailbox, however MIPS based Loongson boot
code uses all 4 mailboxes.

Fixes: 78464f023b54 ("hw/loongarch/virt: Modify ipi as percpu device")
Signed-off-by: Jiaxun Yang 
---
 hw/intc/loongarch_ipi.c | 6 +++---
 include/hw/intc/loongarch_ipi.h | 4 +++-
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
index d6ab91721ea1..3e453816524e 100644
--- a/hw/intc/loongarch_ipi.c
+++ b/hw/intc/loongarch_ipi.c
@@ -238,14 +238,14 @@ static void loongarch_ipi_init(Object *obj)
 
 static const VMStateDescription vmstate_ipi_core = {
 .name = "ipi-single",
-.version_id = 1,
-.minimum_version_id = 1,
+.version_id = 2,
+.minimum_version_id = 2,
 .fields = (VMStateField[]) {
 VMSTATE_UINT32(status, IPICore),
 VMSTATE_UINT32(en, IPICore),
 VMSTATE_UINT32(set, IPICore),
 VMSTATE_UINT32(clear, IPICore),
-VMSTATE_UINT32_ARRAY(buf, IPICore, 2),
+VMSTATE_UINT32_ARRAY(buf, IPICore, IPI_MBX_NUM * 2),
 VMSTATE_END_OF_LIST()
 }
 };
diff --git a/include/hw/intc/loongarch_ipi.h b/include/hw/intc/loongarch_ipi.h
index 664e050b926e..6c6194786e80 100644
--- a/include/hw/intc/loongarch_ipi.h
+++ b/include/hw/intc/loongarch_ipi.h
@@ -28,6 +28,8 @@
 #define MAIL_SEND_OFFSET  0
 #define ANY_SEND_OFFSET   (IOCSR_ANY_SEND - IOCSR_MAIL_SEND)
 
+#define IPI_MBX_NUM   4
+
 #define TYPE_LOONGARCH_IPI "loongarch_ipi"
 OBJECT_DECLARE_SIMPLE_TYPE(LoongArchIPI, LOONGARCH_IPI)
 
@@ -37,7 +39,7 @@ typedef struct IPICore {
 uint32_t set;
 uint32_t clear;
 /* 64bit buf divide into 2 32bit buf */
-uint32_t buf[2];
+uint32_t buf[IPI_MBX_NUM * 2];
 qemu_irq irq;
 } IPICore;
 
-- 
2.39.2 (Apple Git-143)




Re: [PATCH 21/22] tests/avocado: use http for mipsdistros.mips.com

2023-05-10 Thread Jiaxun Yang



> 2023年5月3日 10:12,Alex Bennée  写道:
> 
> As the cached assets have fallen out of our cache new attempts to
> fetch these binaries fail hard due to certificate expirty. It's hard
> to find a contact email for the domain as the root page of mipsdistros
> throws up some random XML. I suspect Amazon are merely the hosts.
> 
> Signed-off-by: Alex Bennée 
> Cc: Philippe Mathieu-Daudé 

Hi  all,

Just reached MIPS to get certification fixed.

Thanks
- Jiaxun


Re: [PATCH] linux-user: Fix mips fp64 executables loading

2023-04-05 Thread Jiaxun Yang



> 2023年4月4日 06:21,Daniil Kovalev  写道:
> 
> If a program requires fr1, we should set the FR bit of CP0 control status
> register and add F64 hardware flag. The corresponding `else if` branch
> statement is copied from the linux kernel sources (see `arch_check_elf` 
> function
> in linux/arch/mips/kernel/elf.c).
> 
> Signed-off-by: Daniil Kovalev 

Reviewed-by: Jiaxun Yang 

Thanks!

> ---
> linux-user/mips/cpu_loop.c | 5 -
> 1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c
> index d5c1c7941d..8735e58bad 100644
> --- a/linux-user/mips/cpu_loop.c
> +++ b/linux-user/mips/cpu_loop.c
> @@ -290,7 +290,10 @@ void target_cpu_copy_regs(CPUArchState *env, struct 
> target_pt_regs *regs)
> env->CP0_Status |= (1 << CP0St_FR);
> env->hflags |= MIPS_HFLAG_F64;
> }
> -} else  if (!prog_req.fre && !prog_req.frdefault &&
> +} else if (prog_req.fr1) {
> +env->CP0_Status |= (1 << CP0St_FR);
> +env->hflags |= MIPS_HFLAG_F64;
> +} else if (!prog_req.fre && !prog_req.frdefault &&
>   !prog_req.fr1 && !prog_req.single && !prog_req.soft) {
> fprintf(stderr, "qemu: Can't find a matching FPU mode\n");
> exit(1);
> -- 
> 2.40.0
> 




Re: [PATCH] linux-user/mips: Low down switchable NaN2008 requirement

2023-03-21 Thread Jiaxun Yang



> 2023年3月15日 08:18,Philippe Mathieu-Daudé  写道:
> 
> On 11/3/23 13:39, Jiaxun Yang wrote:
>>> 2023年3月9日 12:32,Philippe Mathieu-Daudé  写道:
>>> 
>>> Hi Jiaxun,
>>> 
>>> On 11/2/23 18:34, Jiaxun Yang wrote:
>>>> Previously switchable NaN2008 requires fcsr31.nan2008 to be writable
>>>> for guest. However as per MIPS arch spec this bit can never be writable.
>>>> This cause NaN2008 ELF to be rejected by QEMU.
>>>> NaN2008 can be enabled on R2~R5 processors, just make it available
>>>> unconditionally.
>>>> Signed-off-by: Jiaxun Yang 
>>>> ---
>>>>  linux-user/mips/cpu_loop.c | 3 +--
>>>>  1 file changed, 1 insertion(+), 2 deletions(-)
>>>> diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c
>>>> index d5c1c7941d..b5c2ca4a3e 100644
>>>> --- a/linux-user/mips/cpu_loop.c
>>>> +++ b/linux-user/mips/cpu_loop.c
>>>> @@ -301,8 +301,7 @@ void target_cpu_copy_regs(CPUArchState *env, struct 
>>>> target_pt_regs *regs)
>>>>  }
>>>>  if (((info->elf_flags & EF_MIPS_NAN2008) != 0) !=
>>>>  ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) {
>>>> -if ((env->active_fpu.fcr31_rw_bitmask &
>>>> -  (1 << FCR31_NAN2008)) == 0) {
>>>> +if (!(env->insn_flags & ISA_MIPS_R2)) {
>>>>  fprintf(stderr, "ELF binary's NaN mode not supported by 
>>>> CPU\n");
>>>>  exit(1);
>>>>  }
>>> 
>>> Looking at R6.06 revision history:
>>> 
>>>  5.03 August 21, 2013
>>> 
>>>  • ABS2008 and NAN2008 fields of Table 5.7 “FCSR RegisterField
>>>Descriptions” were optional in release 3 and could be R/W,
>>>but as of release 5 are required, read-only, and preset by
>>>hardware.
>>> So I tried with this change:
>>> 
>>> -- >8 --
>>> diff --git a/target/mips/cpu.c b/target/mips/cpu.c
>>> index 05caf54999..5f1364ffaf 100644
>>> --- a/target/mips/cpu.c
>>> +++ b/target/mips/cpu.c
>>> @@ -243,6 +243,13 @@ static void mips_cpu_reset_hold(Object *obj)
>>> env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
>>> env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
>>> env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
>>> +if (env->insn_flags & ISA_MIPS_R5) {
>>> +assert(!(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << 
>>> FCR31_ABS2008)));
>>> +assert(!(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << 
>>> FCR31_NAN2008)));
>>> +} else if (env->insn_flags & ISA_MIPS_R3) {
>>> +assert(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << 
>>> FCR31_ABS2008));
>>> +assert(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << 
>>> FCR31_NAN2008));
>>> +}
>>> env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
>>> env->msair = env->cpu_model->MSAIR;
>>> env->insn_flags = env->cpu_model->insn_flags;
>>> ---
>>> 
>>> and got:
>>> 
>>> $ for cpu in $(./qemu-system-mips64el -cpu help | cut -d\' -f2); do \
>>>  echo -n ${cpu}...;echo q \
>>>  | ./qemu-system-mips64el -accel tcg -cpu ${cpu} \
>>>   -S -monitor stdio 1> /dev/null || break; \
>>>  echo OK; done
>>> 4Kc...OK
>>> 4Km...OK
>>> 4KEcR1...OK
>>> 4KEmR1...OK
>>> 4KEc...OK
>>> 4KEm...OK
>>> 24Kc...OK
>>> 24KEc...OK
>>> 24Kf...OK
>>> 34Kf...OK
>>> 74Kf...OK
>>> M14K...OK
>>> M14Kc...OK
>>> P5600...OK
>>> mips32r6-generic...OK
>>> I7200...OK
>>> R4000...OK
>>> VR5432...OK
>>> 5Kc...OK
>>> 5Kf...OK
>>> 20Kc...OK
>>> MIPS64R2-generic...OK
>>> 5KEc...OK
>>> 5KEf...OK
>>> I6400...OK
>>> I6500...OK
>>> Loongson-2E...OK
>>> Loongson-2F...OK
>>> Loongson-3A1000...OK
>>> Loongson-3A4000...OK
>>> mips64dspr2...OK
>>> Octeon68XX...OK
>>> $
>> Well that’s because there is no CPU being marked as MIPS Release 3 in QEMU, 
>> and only
>> P5600 is marked as MIPS Release 5.
>> In reality R3 implementations are all advertising themself as R2, and later 
>> RCs of microAptiv
>> and interaptiv can all be configured as NaN2008 only. So for those CPUs we 
>> have binary compiled
>> with -march=mips32r2 -mnan=2008.
>> Given that default CPU of mips32r2 in QEMU is 24Kf, I think the best 
>> approach to deal with such
>> situation is to allow NaN2008 to be enabled for early processors for 
>> linux-user.
>> There is a NAN2008 Debian port for test:
>> http://repo.oss.cipunited.com/mipsel-nan2008/tarball/sid-mipsel-nan2008-20230309-1.tar.xz
> 
> $ qemu-mipsel -L sid-mipsel-nan2008-20230313-1/usr -cpu P5600 usr/bin/uname  
> -ms
> Linux mips
> 
> What about something like:

That would lost capability of testing NaN2008 binaries again other CPU models.

Thanks
- Jiaxun

> 
> -- >8 --
> --- a/linux-user/mips/target_elf.h
> +++ b/linux-user/mips/target_elf.h
> @@ -15,6 +15,9 @@ static inline const char *cpu_get_model(uint32_t eflags)
> if ((eflags & EF_MIPS_MACH) == EF_MIPS_MACH_5900) {
> return "R5900";
> }
> +if (eflags & EF_MIPS_NAN2008) {
> +return "P5600";
> +}
> return "24Kf";
> }
> #endif
> ---





Re: [PATCH] linux-user/mips: Low down switchable NaN2008 requirement

2023-03-11 Thread Jiaxun Yang



> 2023年3月9日 12:32,Philippe Mathieu-Daudé  写道:
> 
> Hi Jiaxun,
> 
> On 11/2/23 18:34, Jiaxun Yang wrote:
>> Previously switchable NaN2008 requires fcsr31.nan2008 to be writable
>> for guest. However as per MIPS arch spec this bit can never be writable.
>> This cause NaN2008 ELF to be rejected by QEMU.
>> NaN2008 can be enabled on R2~R5 processors, just make it available
>> unconditionally.
>> Signed-off-by: Jiaxun Yang 
>> ---
>>  linux-user/mips/cpu_loop.c | 3 +--
>>  1 file changed, 1 insertion(+), 2 deletions(-)
>> diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c
>> index d5c1c7941d..b5c2ca4a3e 100644
>> --- a/linux-user/mips/cpu_loop.c
>> +++ b/linux-user/mips/cpu_loop.c
>> @@ -301,8 +301,7 @@ void target_cpu_copy_regs(CPUArchState *env, struct 
>> target_pt_regs *regs)
>>  }
>>  if (((info->elf_flags & EF_MIPS_NAN2008) != 0) !=
>>  ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) {
>> -if ((env->active_fpu.fcr31_rw_bitmask &
>> -  (1 << FCR31_NAN2008)) == 0) {
>> +if (!(env->insn_flags & ISA_MIPS_R2)) {
>>  fprintf(stderr, "ELF binary's NaN mode not supported by CPU\n");
>>  exit(1);
>>  }
> 
> Looking at R6.06 revision history:
> 
>  5.03 August 21, 2013
> 
>  • ABS2008 and NAN2008 fields of Table 5.7 “FCSR RegisterField
>Descriptions” were optional in release 3 and could be R/W,
>but as of release 5 are required, read-only, and preset by
>hardware.
> So I tried with this change:
> 
> -- >8 --
> diff --git a/target/mips/cpu.c b/target/mips/cpu.c
> index 05caf54999..5f1364ffaf 100644
> --- a/target/mips/cpu.c
> +++ b/target/mips/cpu.c
> @@ -243,6 +243,13 @@ static void mips_cpu_reset_hold(Object *obj)
> env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
> env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
> env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
> +if (env->insn_flags & ISA_MIPS_R5) {
> +assert(!(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << 
> FCR31_ABS2008)));
> +assert(!(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << 
> FCR31_NAN2008)));
> +} else if (env->insn_flags & ISA_MIPS_R3) {
> +assert(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << FCR31_ABS2008));
> +assert(env->cpu_model->CP1_fcr31_rw_bitmask & (1 << FCR31_NAN2008));
> +}
> env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
> env->msair = env->cpu_model->MSAIR;
> env->insn_flags = env->cpu_model->insn_flags;
> ---
> 
> and got:
> 
> $ for cpu in $(./qemu-system-mips64el -cpu help | cut -d\' -f2); do \
>  echo -n ${cpu}...;echo q \
>  | ./qemu-system-mips64el -accel tcg -cpu ${cpu} \
>   -S -monitor stdio 1> /dev/null || break; \
>  echo OK; done
> 4Kc...OK
> 4Km...OK
> 4KEcR1...OK
> 4KEmR1...OK
> 4KEc...OK
> 4KEm...OK
> 24Kc...OK
> 24KEc...OK
> 24Kf...OK
> 34Kf...OK
> 74Kf...OK
> M14K...OK
> M14Kc...OK
> P5600...OK
> mips32r6-generic...OK
> I7200...OK
> R4000...OK
> VR5432...OK
> 5Kc...OK
> 5Kf...OK
> 20Kc...OK
> MIPS64R2-generic...OK
> 5KEc...OK
> 5KEf...OK
> I6400...OK
> I6500...OK
> Loongson-2E...OK
> Loongson-2F...OK
> Loongson-3A1000...OK
> Loongson-3A4000...OK
> mips64dspr2...OK
> Octeon68XX...OK
> $

Well that’s because there is no CPU being marked as MIPS Release 3 in QEMU, and 
only
P5600 is marked as MIPS Release 5.

In reality R3 implementations are all advertising themself as R2, and later RCs 
of microAptiv
and interaptiv can all be configured as NaN2008 only. So for those CPUs we have 
binary compiled
with -march=mips32r2 -mnan=2008.

Given that default CPU of mips32r2 in QEMU is 24Kf, I think the best approach 
to deal with such
situation is to allow NaN2008 to be enabled for early processors for linux-user.

There is a NAN2008 Debian port for test: 

http://repo.oss.cipunited.com/mipsel-nan2008/tarball/sid-mipsel-nan2008-20230309-1.tar.xz

Thanks

> 
> Which CPU are you testing? Where can I get such ELF binary for testing?
> 
> Thanks,
> 
> Phil.





Re: [PATCH v2 0/2] MIPS Virt machine

2023-03-07 Thread Jiaxun Yang



> 2023年3月7日 21:07,Philippe Mathieu-Daudé  写道:
> 
> On 7/3/23 21:14, Philippe Mathieu-Daudé wrote:
>> On 7/3/23 21:07, Jiaxun Yang wrote:
>>> 
>>> 
>>>> 2023年3月7日 15:01,Philippe Mathieu-Daudé  写道:
>>>> 
>>>> On 4/3/23 23:38, Jiaxun Yang wrote:
>>>>> Hi there,
>>>>> This patchset is to add a new machine type for MIPS architecture, which
>>>>> is purely a VirtIO machine.
>>>> 
>>>>> Jiaxun Yang (2):
>>>>>   hw/misc: Add MIPS Trickbox device
>>>>>   hw/mips: Add MIPS virt board
>>>> Thanks, applied with following changes:
>>> 
>>> Thanks for those clean-ups!
> 
> Unfortunately I have to drop this due to the libfdt
> dependency, which fails the --disable-fdt job:
> https://gitlab.com/philmd/qemu/-/jobs/3890587748

Perhaps we should just select TARGET_NEED_FDT for all MIPS variants?

Thanks
- Jiaxun


Re: [PATCH v2 2/2] hw/mips: Add MIPS virt board

2023-03-07 Thread Jiaxun Yang



> 2023年3月7日 20:10,Philippe Mathieu-Daudé  写道:
> 
> On 4/3/23 23:38, Jiaxun Yang wrote:
>> MIPS virt board is design to utilize existing VirtIO infrastures
>> but also comptitable with MIPS's existing internal simulation tools.
>> It includes virtio-pci, virtio-mmio, pcie gpex, flash rom, fw_cfg,
>> goldfish-rtc and MIPS CPS system.
>> It should be able to cooperate with any MIPS CPU cores.
>> Signed-off-by: Jiaxun Yang 
>> ---
>> v1:
>>  - Rename to virt board
>>  - Convert BIOS flash to ROM
>>  - Cleanups
>> v2:
>>  - Fix fdt flash
>>  - Remove UP variant
>> ---
>>  MAINTAINERS |   7 +
>>  configs/devices/mips-softmmu/common.mak |   1 +
>>  docs/system/target-mips.rst |  22 +
>>  hw/mips/Kconfig |  17 +
>>  hw/mips/meson.build |   1 +
>>  hw/mips/virt.c  | 916 
>>  6 files changed, 964 insertions(+)
>>  create mode 100644 hw/mips/virt.c
> 
> 
>> +static void virt_machine_init(MachineState *machine)
>> +{
>> +MIPSVirtState *s = MIPS_VIRT_MACHINE(machine);
>> +MemoryRegion *system_memory = get_system_memory();
>> +const MemMapEntry *memmap = virt_memmap;
>> +int i;
>> +
>> +s->cpuclk = clock_new(OBJECT(machine), "cpu-refclk");
>> +clock_set_hz(s->cpuclk, VIRT_CPU_REF_CLK_FREQ);
>> +
>> +s->cps = MIPS_CPS(qdev_new(TYPE_MIPS_CPS));
>> +object_property_set_str(OBJECT(s->cps), "cpu-type", machine->cpu_type,
>> +_fatal);
>> +object_property_set_int(OBJECT(s->cps), "num-core", machine->smp.cpus,
>> +_fatal);
>> +qdev_connect_clock_in(DEVICE(s->cps), "clk-in", s->cpuclk);
>> +sysbus_realize(SYS_BUS_DEVICE(s->cps), _fatal);
> 
> qemu-system-mips64el: Property 'mips-cps.num-core' not found
> 
> I'm worried. I suppose you want this property:
> 
>  DEFINE_PROP_UINT32("num-vp", MIPSCPSState, num_vp, 1),

Yes

> 
> Is your series based on mainstream QEMU?


Whoops, rebasing issue not caught by CI…

Accidentally leaked part of following patch into this one, was trying to fix SMP
support for earlier CPUs.

Apologise for this.

Thanks
- Jiaxun








Re: [PATCH v2 0/2] MIPS Virt machine

2023-03-07 Thread Jiaxun Yang



> 2023年3月7日 15:01,Philippe Mathieu-Daudé  写道:
> 
> On 4/3/23 23:38, Jiaxun Yang wrote:
>> Hi there,
>> This patchset is to add a new machine type for MIPS architecture, which
>> is purely a VirtIO machine.
> 
>> Jiaxun Yang (2):
>>  hw/misc: Add MIPS Trickbox device
>>  hw/mips: Add MIPS virt board
> Thanks, applied with following changes:

Thanks for those clean-ups!

> 
> - remove pointless mask in mips_trickbox_write(),
> - declare QOM macros using OBJECT_DECLARE_SIMPLE_TYPE(),
> - declare machine type using DEFINE_TYPES(),
> - do not select PCI in Kconfig,

Hmm, PCI is sort of mandatory for this machine, any reason not to select it?

> - compile virt.o using fdt flags in meson.build,
> - use HWADDR_PRIx,
> - name MachineState variable 'ms',
> - fix conflict in docs/system/target-mips.rst,
> - fix style

Thanks.
- Jiaxun


[PATCH v2 0/2] MIPS Virt machine

2023-03-04 Thread Jiaxun Yang
Hi there,

This patchset is to add a new machine type for MIPS architecture, which
is purely a VirtIO machine.

It is design to utilize existing VirtIO infrastures but also comptitable
with MIPS's existing internal simulation tools.

It should be able to cooperate with any MIPS core and boot Generic MIPS
kernel.

Kernel patch available at: 
https://lore.kernel.org/linux-mips/20230304221524.47160-1-jiaxun.y...@flygoat.com/

Thanks

Jiaxun Yang (2):
  hw/misc: Add MIPS Trickbox device
  hw/mips: Add MIPS virt board

 MAINTAINERS |   7 +
 configs/devices/mips-softmmu/common.mak |   1 +
 docs/system/target-mips.rst |  22 +
 hw/mips/Kconfig |  17 +
 hw/mips/meson.build |   1 +
 hw/mips/virt.c  | 916 
 hw/misc/Kconfig |   3 +
 hw/misc/meson.build |   1 +
 hw/misc/mips_trickbox.c |  97 +++
 hw/misc/trace-events|   4 +
 include/hw/misc/mips_trickbox.h |  41 ++
 11 files changed, 1110 insertions(+)
 create mode 100644 hw/mips/virt.c
 create mode 100644 hw/misc/mips_trickbox.c
 create mode 100644 include/hw/misc/mips_trickbox.h

-- 
2.37.1 (Apple Git-137.1)




[PATCH v2 2/2] hw/mips: Add MIPS virt board

2023-03-04 Thread Jiaxun Yang
MIPS virt board is design to utilize existing VirtIO infrastures
but also comptitable with MIPS's existing internal simulation tools.

It includes virtio-pci, virtio-mmio, pcie gpex, flash rom, fw_cfg,
goldfish-rtc and MIPS CPS system.

It should be able to cooperate with any MIPS CPU cores.

Signed-off-by: Jiaxun Yang 
---
v1:
 - Rename to virt board
 - Convert BIOS flash to ROM
 - Cleanups
v2:
 - Fix fdt flash
 - Remove UP variant
---
 MAINTAINERS |   7 +
 configs/devices/mips-softmmu/common.mak |   1 +
 docs/system/target-mips.rst |  22 +
 hw/mips/Kconfig |  17 +
 hw/mips/meson.build |   1 +
 hw/mips/virt.c  | 916 
 6 files changed, 964 insertions(+)
 create mode 100644 hw/mips/virt.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 9adb6286279d..6884eaa78a76 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1296,6 +1296,13 @@ F: hw/mips/boston.c
 F: hw/pci-host/xilinx-pcie.c
 F: include/hw/pci-host/xilinx-pcie.h
 
+Virt
+M: Jiaxun Yang 
+S: Maintained
+F: hw/mips/virt.c
+F: hw/misc/mips_trickbox.c
+F: include/hw/misc/mips_trickbox.h
+
 OpenRISC Machines
 -
 or1k-sim
diff --git a/configs/devices/mips-softmmu/common.mak 
b/configs/devices/mips-softmmu/common.mak
index 7da99327a779..eb2c32b7c175 100644
--- a/configs/devices/mips-softmmu/common.mak
+++ b/configs/devices/mips-softmmu/common.mak
@@ -24,6 +24,7 @@ CONFIG_I8259=y
 CONFIG_MC146818RTC=y
 CONFIG_MIPS_CPS=y
 CONFIG_MIPS_ITU=y
+CONFIG_MIPS_VIRT=y
 CONFIG_MALTA=y
 CONFIG_PCNET_PCI=y
 CONFIG_MIPSSIM=y
diff --git a/docs/system/target-mips.rst b/docs/system/target-mips.rst
index 138441bdec1c..a11f08ab00a3 100644
--- a/docs/system/target-mips.rst
+++ b/docs/system/target-mips.rst
@@ -10,6 +10,8 @@ machine types are emulated:
 
 -  A generic ISA PC-like machine \"mips\"
 
+-  Generic Virtual Platform \"virt\"
+
 -  The MIPS Malta prototype board \"malta\"
 
 -  An ACER Pica \"pica61\". This machine needs the 64-bit emulator.
@@ -31,6 +33,26 @@ emulated:
 
 -  NE2000 network card
 
+The virt machine supports the following devices:
+
+- A range of MIPS CPUs, default is the P5600 (32-bit) or I6400 (64-bit)
+
+- MIPS CM (Coherence Manager)
+
+- CFI parallel NOR flash memory
+
+- 1 NS16550 compatible UART
+
+- 1 Google Goldfish RTC
+
+- 1 MIPS Trickbox device
+
+- 8 virtio-mmio transport devices
+
+- 1 generic PCIe host bridge
+
+- The fw_cfg device that allows a guest to obtain data from QEMU
+
 The Malta emulation supports the following devices:
 
 -  Core board with MIPS 24Kf CPU and Galileo system controller
diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index da3a37e215ec..8a753ec2aee2 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -59,5 +59,22 @@ config MIPS_BOSTON
 select AHCI_ICH9
 select SERIAL
 
+config MIPS_VIRT
+bool
+imply PCI_DEVICES
+imply VIRTIO_VGA
+imply TEST_DEVICES
+select MIPS_CPS
+select MIPS_TRICKBOX
+select SERIAL
+select FW_CFG_MIPS
+select GOLDFISH_RTC
+select PCI
+select PCI_EXPRESS_GENERIC_BRIDGE
+select PFLASH_CFI01
+select VIRTIO_MMIO
+select FW_CFG_DMA
+select PLATFORM_BUS
+
 config FW_CFG_MIPS
 bool
diff --git a/hw/mips/meson.build b/hw/mips/meson.build
index 900613fc087f..5670c939fa7b 100644
--- a/hw/mips/meson.build
+++ b/hw/mips/meson.build
@@ -1,6 +1,7 @@
 mips_ss = ss.source_set()
 mips_ss.add(files('bootloader.c', 'mips_int.c'))
 mips_ss.add(when: 'CONFIG_FW_CFG_MIPS', if_true: files('fw_cfg.c'))
+mips_ss.add(when: 'CONFIG_MIPS_VIRT', if_true: files('virt.c'))
 mips_ss.add(when: 'CONFIG_LOONGSON3V', if_true: files('loongson3_bootp.c', 
'loongson3_virt.c'))
 mips_ss.add(when: 'CONFIG_MALTA', if_true: files('malta.c'))
 mips_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('cps.c'))
diff --git a/hw/mips/virt.c b/hw/mips/virt.c
new file mode 100644
index ..e4359f930104
--- /dev/null
+++ b/hw/mips/virt.c
@@ -0,0 +1,916 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * QEMU MIPS Virt Board
+ * Copyright (C) 2022 Jiaxun Yang 
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qemu/datadir.h"
+
+#include "chardev/char.h"
+#include "hw/block/flash.h"
+#include "hw/boards.h"
+#include "hw/char/serial.h"
+#include "hw/core/sysbus-fdt.h"
+#include "hw/display/ramfb.h"
+#include "hw/intc/goldfish_pic.h"
+#include "hw/loader-fit.h"
+#include "hw/loader.h"
+#include "hw/mips/bootloader.h"
+#include "hw/mips/cps.h"
+#include "hw/mips/cpudevs.h"
+#include "hw/mips/mips.h"
+#include "hw/misc/mips_trickbox.h"
+#include "hw/pci-host/gpex.h"
+#include "hw/pci/pci.h"
+#include "hw/platform-bus.h"
+#include "hw/qdev-clock.h"
+#include "hw/q

[PATCH v2 1/2] hw/misc: Add MIPS Trickbox device

2023-03-04 Thread Jiaxun Yang
MIPS Trickbox is a emulated device present in MIPS's IASIM simulator
for decades. It's capable of managing simulator status, signaling
interrupts, doing DMA and EJTAG signal stimulations.

For now we just use definition of this device and implement power
management related functions.

Signed-off-by: Jiaxun Yang 
---
v1: Rewording commit message
---
 hw/misc/Kconfig |  3 +
 hw/misc/meson.build |  1 +
 hw/misc/mips_trickbox.c | 97 +
 hw/misc/trace-events|  4 ++
 include/hw/misc/mips_trickbox.h | 41 ++
 5 files changed, 146 insertions(+)
 create mode 100644 hw/misc/mips_trickbox.c
 create mode 100644 include/hw/misc/mips_trickbox.h

diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 2ef5781ef87b..9f09da23c191 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -85,6 +85,9 @@ config STM32F4XX_EXTI
 config MIPS_ITU
 bool
 
+config MIPS_TRICKBOX
+bool
+
 config MPS2_FPGAIO
 bool
 select LED
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index fe869b98ca4d..1b58fd7df7b2 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -134,6 +134,7 @@ specific_ss.add(when: 'CONFIG_MAC_VIA', if_true: 
files('mac_via.c'))
 
 specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_cmgcr.c', 
'mips_cpc.c'))
 specific_ss.add(when: 'CONFIG_MIPS_ITU', if_true: files('mips_itu.c'))
+specific_ss.add(when: 'CONFIG_MIPS_TRICKBOX', if_true: 
files('mips_trickbox.c'))
 
 softmmu_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa_ec.c'))
 
diff --git a/hw/misc/mips_trickbox.c b/hw/misc/mips_trickbox.c
new file mode 100644
index ..20349b774b2f
--- /dev/null
+++ b/hw/misc/mips_trickbox.c
@@ -0,0 +1,97 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ *
+ * MIPS Trickbox
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "trace.h"
+#include "sysemu/runstate.h"
+#include "hw/misc/mips_trickbox.h"
+
+static uint64_t mips_trickbox_read(void *opaque, hwaddr addr, unsigned int 
size)
+{
+uint64_t value = 0;
+
+qemu_log_mask(LOG_UNIMP,
+"%s: unimplemented register read 0x%02"HWADDR_PRIx"\n",
+__func__, addr);
+trace_mips_trickbox_read(size, value);
+
+return 0;
+}
+
+static void mips_trickbox_write(void *opaque, hwaddr addr,
+   uint64_t val64, unsigned int size)
+{
+trace_mips_trickbox_write(size, val64);
+
+switch (addr) {
+case REG_SIM_CMD:
+switch (val64 & 0x) {
+case TRICK_PANIC:
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
+break;
+case TRICK_HALT:
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+break;
+case TRICK_SUSPEND:
+qemu_system_suspend_request();
+break;
+case TRICK_RESET:
+qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+break;
+case TRICK_PASS_MIPS:
+case TRICK_PASS_NANOMIPS:
+exit(EXIT_SUCCESS);
+break;
+case TRICK_FAIL_MIPS:
+case TRICK_FAIL_NANOMIPS:
+exit(EXIT_FAILURE);
+break;
+}
+break;
+default:
+qemu_log_mask(LOG_UNIMP,
+  "%s: unimplemented register write 0x%02"HWADDR_PRIx"\n",
+  __func__, addr);
+break;
+}
+}
+
+static const MemoryRegionOps mips_trickbox_ops = {
+.read = mips_trickbox_read,
+.write = mips_trickbox_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid = {
+.min_access_size = 2,
+.max_access_size = 4
+}
+};
+
+static void mips_trickbox_init(Object *obj)
+{
+MIPSTrickboxState *s = MIPS_TRICKBOX(obj);
+
+memory_region_init_io(>mmio, obj, _trickbox_ops, s,
+  TYPE_MIPS_TRICKBOX, 0x100);
+sysbus_init_mmio(SYS_BUS_DEVICE(obj), >mmio);
+}
+
+static const TypeInfo mips_trickbox_info = {
+.name  = TYPE_MIPS_TRICKBOX,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(MIPSTrickboxState),
+.instance_init = mips_trickbox_init,
+};
+
+static void mips_trickbox_register_types(void)
+{
+type_register_static(_trickbox_info);
+}
+
+type_init(mips_trickbox_register_types)
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index c47876a90262..8603cf0d5ad2 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -279,3 +279,7 @@ virt_ctrl_instance_init(void *dev) "ctrl: %p"
 lasi_chip_mem_valid(uint64_t addr, uint32_t val) "access to addr 0x%"PRIx64" 
is %d"
 lasi_chip_read(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"
 lasi_chip_write(uint64_t addr, uint32_t val

Re: [PATCH v3 03/20] target/mips: Drop tcg_temp_free from mips16e_translate.c.inc

2023-03-04 Thread Jiaxun Yang



> 2023年3月4日 18:18,Richard Henderson  写道:
> 
> Translators are no longer required to free tcg temporaries.
> 
> Signed-off-by: Richard Henderson 

Reviewed-by: Jiaxun Yang 

Thanks.

> ---
> 2.34.1
> 




[PATCH] hw/mips/gt64xxx_pci: Don't endian-swap GT_PCI0_CFGADDR

2023-02-23 Thread Jiaxun Yang
145e2198d749 ("hw/mips/gt64xxx_pci: Endian-swap using PCI_HOST_BRIDGE
MemoryRegionOps") converted CFGADDR/CFGDATA registers to use PCI_HOST_BRIDGE's
accessor facility and enabled byte swap for both CFGADDR/CFGDATA register.

However CFGADDR as a ISD internal register is not controled by MByteSwap
bit, it follows endian of all other ISD register, which means it ties to
little endian.

Move mapping of CFGADDR out of gt64120_update_pci_cfgdata_mapping to disable
endian-swapping.

This should fix some recent reports about poweroff hang.

Fixes: 145e2198d749 ("hw/mips/gt64xxx_pci: Endian-swap using PCI_HOST_BRIDGE 
MemoryRegionOps")
Signed-off-by: Jiaxun Yang 
---
 hw/pci-host/gt64120.c | 18 ++
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/hw/pci-host/gt64120.c b/hw/pci-host/gt64120.c
index f226d0342039..82c15edb4698 100644
--- a/hw/pci-host/gt64120.c
+++ b/hw/pci-host/gt64120.c
@@ -321,9 +321,6 @@ static void gt64120_isd_mapping(GT64120State *s)
 static void gt64120_update_pci_cfgdata_mapping(GT64120State *s)
 {
 /* Indexed on MByteSwap bit, see Table 158: PCI_0 Command, Offset: 0xc00 */
-static const MemoryRegionOps *pci_host_conf_ops[] = {
-_host_conf_be_ops, _host_conf_le_ops
-};
 static const MemoryRegionOps *pci_host_data_ops[] = {
 _host_data_be_ops, _host_data_le_ops
 };
@@ -339,15 +336,6 @@ static void 
gt64120_update_pci_cfgdata_mapping(GT64120State *s)
  * - Table 16: 32-bit PCI Transaction Endianess
  * - Table 158: PCI_0 Command, Offset: 0xc00
  */
-if (memory_region_is_mapped(>conf_mem)) {
-memory_region_del_subregion(>ISD_mem, >conf_mem);
-object_unparent(OBJECT(>conf_mem));
-}
-memory_region_init_io(>conf_mem, OBJECT(phb),
-  pci_host_conf_ops[s->regs[GT_PCI0_CMD] & 1],
-  s, "pci-conf-idx", 4);
-memory_region_add_subregion_overlap(>ISD_mem, GT_PCI0_CFGADDR << 2,
->conf_mem, 1);
 
 if (memory_region_is_mapped(>data_mem)) {
 memory_region_del_subregion(>ISD_mem, >data_mem);
@@ -1208,6 +1196,12 @@ static void gt64120_realize(DeviceState *dev, Error 
**errp)
 PCI_DEVFN(18, 0), TYPE_PCI_BUS);
 
 pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci");
+memory_region_init_io(>conf_mem, OBJECT(phb),
+  _host_conf_le_ops,
+  s, "pci-conf-idx", 4);
+memory_region_add_subregion_overlap(>ISD_mem, GT_PCI0_CFGADDR << 2,
+>conf_mem, 1);
+
 
 /*
  * The whole address space decoded by the GT-64120A doesn't generate
-- 
2.37.1 (Apple Git-137.1)




Re: [PATCH 3/3] hw/mips: Add MIPS virt board

2023-02-22 Thread Jiaxun Yang
Ping?

> 2023年2月6日 01:08,Jiaxun Yang  写道:
> 
> 
> 
>> 2023年2月5日 11:48,Philippe Mathieu-Daudé  写道:
>> 
>> Hi Jiaxun,
>> 
>> On 2/2/23 14:21, Jiaxun Yang wrote:
>>> MIPS virt board is design to utilize existing VirtIO infrastures
>>> but also comptitable with MIPS's existing internal simulation tools.
>>> It includes virtio-mmio, pcie gpex, flash rom, fw_cfg, goldfish-rtc,
>>> and optional goldfish_pic in case MIPS GIC is not present.
>> 
>> Is it worth using the CPS/GIC? Can't we using the goldfish PIC
>> regardless CPS availability? Did you run performance comparison?
> 
> goldfish_pic don’t have IPI infra so we must reinvent another SMP mechanism 
> :-(
> 
> The interrupt performance should be close as the interrupt handling flow is 
> almost
> the same.
> 
> Also it can help us prepare for I6400 vGIC support.
> 
> Thanks.
> - Jiaxun
> 
> 
>> 
>>> It should be able to cooperate with any MIPS CPU cores.
>>> Signed-off-by: Jiaxun Yang 
>>> ---
>>> v1:
>>> - Rename to virt board
>>> - Convert BIOS flash to ROM
>>> - Cleanups
>>> ---
>>> MAINTAINERS |7 +
>>> configs/devices/mips-softmmu/common.mak |1 +
>>> docs/system/target-mips.rst |   24 +
>>> hw/mips/Kconfig |   18 +
>>> hw/mips/meson.build |1 +
>>> hw/mips/virt.c  | 1015 +++
>>> 6 files changed, 1066 insertions(+)
>>> create mode 100644 hw/mips/virt.c
>> 
> 
> 




Re: [PATCH] linux-user/mips: Low down switchable NaN2008 requirement

2023-02-22 Thread Jiaxun Yang
Ping?

> 2023年2月11日 17:34,Jiaxun Yang  写道:
> 
> Previously switchable NaN2008 requires fcsr31.nan2008 to be writable
> for guest. However as per MIPS arch spec this bit can never be writable.
> This cause NaN2008 ELF to be rejected by QEMU.
> 
> NaN2008 can be enabled on R2~R5 processors, just make it available
> unconditionally.
> 
> Signed-off-by: Jiaxun Yang 
> ---
> linux-user/mips/cpu_loop.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c
> index d5c1c7941d..b5c2ca4a3e 100644
> --- a/linux-user/mips/cpu_loop.c
> +++ b/linux-user/mips/cpu_loop.c
> @@ -301,8 +301,7 @@ void target_cpu_copy_regs(CPUArchState *env, struct 
> target_pt_regs *regs)
> }
> if (((info->elf_flags & EF_MIPS_NAN2008) != 0) !=
> ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) {
> -if ((env->active_fpu.fcr31_rw_bitmask &
> -  (1 << FCR31_NAN2008)) == 0) {
> +if (!(env->insn_flags & ISA_MIPS_R2)) {
> fprintf(stderr, "ELF binary's NaN mode not supported by CPU\n");
> exit(1);
> }
> -- 
> 2.37.1 (Apple Git-137.1)
> 




Re: [RFC PATCH] docs/about/deprecated: Deprecate 32-bit host systems

2023-02-18 Thread Jiaxun Yang



在2023年2月17日二月 下午6:57,Thomas Huth写道:
> On 17/02/2023 18.43, Philippe Mathieu-Daudé wrote:
>> (Cc'ing Huacai & Jiaxun).
>> 
>> On 17/2/23 17:38, Paolo Bonzini wrote:
>>> On 2/17/23 11:47, Daniel P. Berrangé wrote:
 On Fri, Feb 17, 2023 at 11:36:41AM +0100, Markus Armbruster wrote:
> I feel the discussion petered out without a conclusion.
>
> I don't think letting the status quo win by inertia is a good outcome
> here.
>
> Which 32-bit hosts are still useful, and why?

 Which 32-bit hosts does Linux still provide KVM  support for.
>>>
>>> All except ARM: MIPS, x86, PPC and RISC-V.
>>>
>>> I would like to remove x86, but encountered some objections.
>>>
>>> MIPS, nobody is really using it I think.
>> 
>> 32-bit was added in 2014, commit 222e7d11e7 ("target-mips: Enable KVM
>> support in build system"). I'm not aware of anybody using it (even
>> testing it). I don't have hardware to test it (neither time).
>
> Could you maybe suggest a kernel patch to remove it, to see what happens? 
> ... if nobody objects to the removal of the 32-bit MIPS KVM kernel support 
> and the patch gets merged, that would help us in the long run, I think.

I’m still occasionally testing 32-bit MIPS KVM support with MIPS P5600.

It works just fine so there is no need for further maintenance work.

I’d be sad to see the support go but I can live with it.

There are commercial users for MIPS 32 KVM but they’re all running customized 
downstream QEMU so I guess it’s fine.

Thanks
- Jiaxun

>
>   Thanks,
>Thomas

-- 
- Jiaxun



Re: [PATCH 1/3] target/mips: fix JALS32/J32 instruction handling for microMIPS

2023-02-15 Thread Jiaxun Yang



在2023年2月15日二月 下午8:50,Philippe Mathieu-Daudé写道:
> On 15/2/23 21:21, Richard Henderson wrote:
>> On 2/14/23 22:47, Marcin Nowakowski wrote:
>>> @@ -4860,6 +4860,7 @@ static void gen_compute_branch(DisasContext 
>>> *ctx, uint32_t opc,
>>>   target_ulong btgt = -1;
>>>   int blink = 0;
>>>   int bcond_compute = 0;
>>> +    int jal_mask = 0;
>> 
>> Better to limit the scope of the variable to the block below.
>> 
>>> @@ -4917,6 +4918,11 @@ static void gen_compute_branch(DisasContext 
>>> *ctx, uint32_t opc,
>>>   break;
>>>   case OPC_J:
>>>   case OPC_JAL:
>>> +    /* Jump to immediate */
>>> +    jal_mask = ctx->hflags & MIPS_HFLAG_M16 ? 0xF800 : 
>>> 0xF000;
>>> +    btgt = ((ctx->base.pc_next + insn_bytes) & jal_mask) |
>>> +    (uint32_t)offset;
>> 
>> Ideally we wouldn't have one huge helper function, and could pass down 
>> the mask from the translator.  But that's on-going cleanup.
>
> Yes, this is the approach taken in decodetree conversion.
>
> I hope to rebase / respin incorporating Jiaxun patches some day...

Which series are you referring?
Just caught some time so I might able to help.

>
>> Reviewed-by: Richard Henderson 
>> 
>> 
>> r~

-- 
- Jiaxun



Re: [RFC PATCH 9/9] hw/mips/itu: Pass SAAR using QOM link property

2023-02-13 Thread Jiaxun Yang



> 2023年2月3日 11:36,Philippe Mathieu-Daudé  写道:
> 
> QOM objects shouldn't access each other internals fields
> except using the QOM API.
> 
> mips_cps_realize() instantiates a TYPE_MIPS_ITU object, and
> directly sets the 'saar' pointer:
> 
>   if (saar_present) {
>   s->itu.saar = >CP0_SAAR;
>   }
> 
> In order to avoid that, pass the MIPS_CPU object via a QOM
> link property, and set the 'saar' pointer in mips_itu_realize().
> 
> Signed-off-by: Philippe Mathieu-Daudé 

Tested-by: Jiaxun Yang 
Reviewed-by: Jiaxun Yang 

Tested with ITU cases.

> ---
> RFC because not tested.
> ---
> hw/mips/cps.c  | 23 ++-
> hw/misc/mips_itu.c | 26 ++
> include/hw/misc/mips_itu.h |  5 ++---
> 3 files changed, 26 insertions(+), 28 deletions(-)
> 
> diff --git a/hw/mips/cps.c b/hw/mips/cps.c
> index 38acc57468..2b5269ebf1 100644
> --- a/hw/mips/cps.c
> +++ b/hw/mips/cps.c
> @@ -66,20 +66,17 @@ static bool cpu_mips_itu_supported(CPUMIPSState *env)
> static void mips_cps_realize(DeviceState *dev, Error **errp)
> {
> MIPSCPSState *s = MIPS_CPS(dev);
> -CPUMIPSState *env;
> -MIPSCPU *cpu;
> -int i;
> target_ulong gcr_base;
> bool itu_present = false;
> -bool saar_present = false;
> 
> if (!clock_get(s->clock)) {
> error_setg(errp, "CPS input clock is not connected to an output 
> clock");
> return;
> }
> 
> -for (i = 0; i < s->num_vp; i++) {
> -cpu = MIPS_CPU(object_new(s->cpu_type));
> +for (int i = 0; i < s->num_vp; i++) {
> +MIPSCPU *cpu = MIPS_CPU(object_new(s->cpu_type));
> +CPUMIPSState *env = >env;
> 
> /* All VPs are halted on reset. Leave powering up to CPC. */
> if (!object_property_set_bool(OBJECT(cpu), "start-powered-off", true,
> @@ -97,7 +94,6 @@ static void mips_cps_realize(DeviceState *dev, Error **errp)
> cpu_mips_irq_init_cpu(cpu);
> cpu_mips_clock_init(cpu);
> 
> -env = >env;
> if (cpu_mips_itu_supported(env)) {
> itu_present = true;
> /* Attach ITC Tag to the VP */
> @@ -107,22 +103,15 @@ static void mips_cps_realize(DeviceState *dev, Error 
> **errp)
> qemu_register_reset(main_cpu_reset, cpu);
> }
> 
> -cpu = MIPS_CPU(first_cpu);
> -env = >env;
> -saar_present = (bool)env->saarp;
> -
> /* Inter-Thread Communication Unit */
> if (itu_present) {
> object_initialize_child(OBJECT(dev), "itu", >itu, TYPE_MIPS_ITU);
> +object_property_set_link(OBJECT(>itu), "cpu[0]",
> + OBJECT(first_cpu), _abort);
> object_property_set_uint(OBJECT(>itu), "num-fifo", 16,
> _abort);
> object_property_set_uint(OBJECT(>itu), "num-semaphores", 16,
> _abort);
> -object_property_set_bool(OBJECT(>itu), "saar-present", 
> saar_present,
> - _abort);
> -if (saar_present) {
> -s->itu.saar = >CP0_SAAR;
> -}
> if (!sysbus_realize(SYS_BUS_DEVICE(>itu), errp)) {
> return;
> }
> @@ -158,7 +147,7 @@ static void mips_cps_realize(DeviceState *dev, Error 
> **errp)
> sysbus_mmio_get_region(SYS_BUS_DEVICE(>gic), 
> 0));
> 
> /* Global Configuration Registers */
> -gcr_base = env->CP0_CMGCRBase << 4;
> +gcr_base = MIPS_CPU(first_cpu)->env.CP0_CMGCRBase << 4;
> 
> object_initialize_child(OBJECT(dev), "gcr", >gcr, TYPE_MIPS_GCR);
> object_property_set_uint(OBJECT(>gcr), "num-vp", s->num_vp,
> diff --git a/hw/misc/mips_itu.c b/hw/misc/mips_itu.c
> index a06cdd10ea..0eda302db4 100644
> --- a/hw/misc/mips_itu.c
> +++ b/hw/misc/mips_itu.c
> @@ -93,10 +93,10 @@ void itc_reconfigure(MIPSITUState *tag)
> uint64_t size = (1 * KiB) + (am[1] & ITC_AM1_ADDR_MASK_MASK);
> bool is_enabled = (am[0] & ITC_AM0_EN_MASK) != 0;
> 
> -if (tag->saar_present) {
> -address = ((*(uint64_t *) tag->saar) & 0xE000ULL) << 4;
> -size = 1ULL << ((*(uint64_t *) tag->saar >> 1) & 0x1f);
> -is_enabled = *(uint64_t *) tag->saar & 1;
> +if (tag->saar) {
> +address = (tag->saar[0] & 0xE000ULL) << 4;
> +size = 1ULL << ((tag->saar[0] >> 1) & 0x1f);
> +is_enabled = tag->saar[0] 

[PATCH] linux-user/mips: Low down switchable NaN2008 requirement

2023-02-11 Thread Jiaxun Yang
Previously switchable NaN2008 requires fcsr31.nan2008 to be writable
for guest. However as per MIPS arch spec this bit can never be writable.
This cause NaN2008 ELF to be rejected by QEMU.

NaN2008 can be enabled on R2~R5 processors, just make it available
unconditionally.

Signed-off-by: Jiaxun Yang 
---
 linux-user/mips/cpu_loop.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c
index d5c1c7941d..b5c2ca4a3e 100644
--- a/linux-user/mips/cpu_loop.c
+++ b/linux-user/mips/cpu_loop.c
@@ -301,8 +301,7 @@ void target_cpu_copy_regs(CPUArchState *env, struct 
target_pt_regs *regs)
 }
 if (((info->elf_flags & EF_MIPS_NAN2008) != 0) !=
 ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) {
-if ((env->active_fpu.fcr31_rw_bitmask &
-  (1 << FCR31_NAN2008)) == 0) {
+if (!(env->insn_flags & ISA_MIPS_R2)) {
 fprintf(stderr, "ELF binary's NaN mode not supported by CPU\n");
 exit(1);
 }
-- 
2.37.1 (Apple Git-137.1)




Re: [PATCH 3/3] hw/mips: Add MIPS virt board

2023-02-05 Thread Jiaxun Yang



> 2023年2月5日 11:48,Philippe Mathieu-Daudé  写道:
> 
> Hi Jiaxun,
> 
> On 2/2/23 14:21, Jiaxun Yang wrote:
>> MIPS virt board is design to utilize existing VirtIO infrastures
>> but also comptitable with MIPS's existing internal simulation tools.
>> It includes virtio-mmio, pcie gpex, flash rom, fw_cfg, goldfish-rtc,
>> and optional goldfish_pic in case MIPS GIC is not present.
> 
> Is it worth using the CPS/GIC? Can't we using the goldfish PIC
> regardless CPS availability? Did you run performance comparison?

goldfish_pic don’t have IPI infra so we must reinvent another SMP mechanism :-(

The interrupt performance should be close as the interrupt handling flow is 
almost
the same.

Also it can help us prepare for I6400 vGIC support.

Thanks.
- Jiaxun


> 
>> It should be able to cooperate with any MIPS CPU cores.
>> Signed-off-by: Jiaxun Yang 
>> ---
>> v1:
>>  - Rename to virt board
>>  - Convert BIOS flash to ROM
>>  - Cleanups
>> ---
>>  MAINTAINERS |7 +
>>  configs/devices/mips-softmmu/common.mak |1 +
>>  docs/system/target-mips.rst |   24 +
>>  hw/mips/Kconfig |   18 +
>>  hw/mips/meson.build |1 +
>>  hw/mips/virt.c  | 1015 +++
>>  6 files changed, 1066 insertions(+)
>>  create mode 100644 hw/mips/virt.c
> 




[PATCH 1/3] docs/system: Remove "mips" board from target-mips.rst

2023-02-02 Thread Jiaxun Yang
This board had been deprecated long ago.

Signed-off-by: Jiaxun Yang 
---
 docs/system/target-mips.rst | 14 --
 1 file changed, 14 deletions(-)

diff --git a/docs/system/target-mips.rst b/docs/system/target-mips.rst
index 138441bdec..83239fb9df 100644
--- a/docs/system/target-mips.rst
+++ b/docs/system/target-mips.rst
@@ -8,8 +8,6 @@ endian options, ``qemu-system-mips``, ``qemu-system-mipsel``
 ``qemu-system-mips64`` and ``qemu-system-mips64el``. Five different
 machine types are emulated:
 
--  A generic ISA PC-like machine \"mips\"
-
 -  The MIPS Malta prototype board \"malta\"
 
 -  An ACER Pica \"pica61\". This machine needs the 64-bit emulator.
@@ -19,18 +17,6 @@ machine types are emulated:
 -  A MIPS Magnum R4000 machine \"magnum\". This machine needs the
64-bit emulator.
 
-The generic emulation is supported by Debian 'Etch' and is able to
-install Debian into a virtual disk image. The following devices are
-emulated:
-
--  A range of MIPS CPUs, default is the 24Kf
-
--  PC style serial port
-
--  PC style IDE disk
-
--  NE2000 network card
-
 The Malta emulation supports the following devices:
 
 -  Core board with MIPS 24Kf CPU and Galileo system controller
-- 
2.37.1 (Apple Git-137.1)




[PATCH 3/3] hw/mips: Add MIPS virt board

2023-02-02 Thread Jiaxun Yang
MIPS virt board is design to utilize existing VirtIO infrastures
but also comptitable with MIPS's existing internal simulation tools.

It includes virtio-mmio, pcie gpex, flash rom, fw_cfg, goldfish-rtc,
and optional goldfish_pic in case MIPS GIC is not present.

It should be able to cooperate with any MIPS CPU cores.

Signed-off-by: Jiaxun Yang 
---
v1:
 - Rename to virt board
 - Convert BIOS flash to ROM
 - Cleanups
---
 MAINTAINERS |7 +
 configs/devices/mips-softmmu/common.mak |1 +
 docs/system/target-mips.rst |   24 +
 hw/mips/Kconfig |   18 +
 hw/mips/meson.build |1 +
 hw/mips/virt.c  | 1015 +++
 6 files changed, 1066 insertions(+)
 create mode 100644 hw/mips/virt.c

diff --git a/MAINTAINERS b/MAINTAINERS
index c581c11a64..eb6b748786 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1291,6 +1291,13 @@ F: hw/mips/boston.c
 F: hw/pci-host/xilinx-pcie.c
 F: include/hw/pci-host/xilinx-pcie.h
 
+Virt
+M: Jiaxun Yang 
+S: Maintained
+F: hw/mips/virt.c
+F: hw/misc/mips_trickbox.c
+F: include/hw/misc/mips_trickbox.h
+
 OpenRISC Machines
 -
 or1k-sim
diff --git a/configs/devices/mips-softmmu/common.mak 
b/configs/devices/mips-softmmu/common.mak
index 7da99327a7..eb2c32b7c1 100644
--- a/configs/devices/mips-softmmu/common.mak
+++ b/configs/devices/mips-softmmu/common.mak
@@ -24,6 +24,7 @@ CONFIG_I8259=y
 CONFIG_MC146818RTC=y
 CONFIG_MIPS_CPS=y
 CONFIG_MIPS_ITU=y
+CONFIG_MIPS_VIRT=y
 CONFIG_MALTA=y
 CONFIG_PCNET_PCI=y
 CONFIG_MIPSSIM=y
diff --git a/docs/system/target-mips.rst b/docs/system/target-mips.rst
index 83239fb9df..8755a21bf4 100644
--- a/docs/system/target-mips.rst
+++ b/docs/system/target-mips.rst
@@ -8,6 +8,8 @@ endian options, ``qemu-system-mips``, ``qemu-system-mipsel``
 ``qemu-system-mips64`` and ``qemu-system-mips64el``. Five different
 machine types are emulated:
 
+- Generic Virtual Platform \"virt\"
+
 -  The MIPS Malta prototype board \"malta\"
 
 -  An ACER Pica \"pica61\". This machine needs the 64-bit emulator.
@@ -17,6 +19,28 @@ machine types are emulated:
 -  A MIPS Magnum R4000 machine \"magnum\". This machine needs the
64-bit emulator.
 
+The virt machine supports the following devices:
+
+- A range of MIPS CPUs, default is the P5600 (32-bit) or I6400 (64-bit)
+
+- MIPS CM (Coherence Manager) for SMP system with supported CPU
+
+- Google Goldfish PIC Interrupt Controller for system without CM
+
+- CFI parallel NOR flash memory
+
+- 1 NS16550 compatible UART
+
+- 1 Google Goldfish RTC
+
+- 1 MIPS Trickbox device
+
+- 8 virtio-mmio transport devices
+
+- 1 generic PCIe host bridge
+
+- The fw_cfg device that allows a guest to obtain data from QEMU
+
 The Malta emulation supports the following devices:
 
 -  Core board with MIPS 24Kf CPU and Galileo system controller
diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index da3a37e215..0790ec55c3 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -59,5 +59,23 @@ config MIPS_BOSTON
 select AHCI_ICH9
 select SERIAL
 
+config MIPS_VIRT
+bool
+imply PCI_DEVICES
+imply VIRTIO_VGA
+imply TEST_DEVICES
+select MIPS_CPS
+select MIPS_TRICKBOX
+select SERIAL
+select FW_CFG_MIPS
+select GOLDFISH_RTC
+select GOLDFISH_PIC
+select PCI
+select PCI_EXPRESS_GENERIC_BRIDGE
+select PFLASH_CFI01
+select VIRTIO_MMIO
+select FW_CFG_DMA
+select PLATFORM_BUS
+
 config FW_CFG_MIPS
 bool
diff --git a/hw/mips/meson.build b/hw/mips/meson.build
index 900613fc08..5670c939fa 100644
--- a/hw/mips/meson.build
+++ b/hw/mips/meson.build
@@ -1,6 +1,7 @@
 mips_ss = ss.source_set()
 mips_ss.add(files('bootloader.c', 'mips_int.c'))
 mips_ss.add(when: 'CONFIG_FW_CFG_MIPS', if_true: files('fw_cfg.c'))
+mips_ss.add(when: 'CONFIG_MIPS_VIRT', if_true: files('virt.c'))
 mips_ss.add(when: 'CONFIG_LOONGSON3V', if_true: files('loongson3_bootp.c', 
'loongson3_virt.c'))
 mips_ss.add(when: 'CONFIG_MALTA', if_true: files('malta.c'))
 mips_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('cps.c'))
diff --git a/hw/mips/virt.c b/hw/mips/virt.c
new file mode 100644
index 00..e13b2c731b
--- /dev/null
+++ b/hw/mips/virt.c
@@ -0,0 +1,1015 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * QEMU MIPS Virt Board
+ * Copyright (C) 2022 Jiaxun Yang 
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qemu/datadir.h"
+
+#include "chardev/char.h"
+#include "hw/block/flash.h"
+#include "hw/boards.h"
+#include "hw/char/serial.h"
+#include "hw/core/sysbus-fdt.h"
+#include "hw/display/ramfb.h"
+#include "hw/intc/goldfish_pic.h"
+#include "hw/loader-fit.h"
+#include "hw/loader.h"
+#include "hw/mips/bootloader.h"
+#include "hw/mips/cps.h"
+#include "hw/mips/cpudevs.h"

[PATCH 2/3] hw/misc: Add MIPS Trickbox device

2023-02-02 Thread Jiaxun Yang
MIPS Trickbox is a emulated device present in MIPS's IASIM simulator
for decades. It's capable of managing simulator status, signaling
interrupts, doing DMA and EJTAG signal stimulations.

For now we just use definition of this device and implement power
management related functions.

Signed-off-by: Jiaxun Yang 
---
v1: Rewording commit message
---
 hw/misc/Kconfig |  3 +
 hw/misc/meson.build |  1 +
 hw/misc/mips_trickbox.c | 97 +
 hw/misc/trace-events|  4 ++
 include/hw/misc/mips_trickbox.h | 41 ++
 5 files changed, 146 insertions(+)
 create mode 100644 hw/misc/mips_trickbox.c
 create mode 100644 include/hw/misc/mips_trickbox.h

diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index eaeddca277..a9637e6494 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -89,6 +89,9 @@ config STM32F4XX_EXTI
 config MIPS_ITU
 bool
 
+config MIPS_TRICKBOX
+bool
+
 config MPS2_FPGAIO
 bool
 select LED
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 448e14b531..1ea92b266d 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -135,6 +135,7 @@ specific_ss.add(when: 'CONFIG_MAC_VIA', if_true: 
files('mac_via.c'))
 
 specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_cmgcr.c', 
'mips_cpc.c'))
 specific_ss.add(when: 'CONFIG_MIPS_ITU', if_true: files('mips_itu.c'))
+specific_ss.add(when: 'CONFIG_MIPS_TRICKBOX', if_true: 
files('mips_trickbox.c'))
 
 softmmu_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa_ec.c'))
 
diff --git a/hw/misc/mips_trickbox.c b/hw/misc/mips_trickbox.c
new file mode 100644
index 00..20349b774b
--- /dev/null
+++ b/hw/misc/mips_trickbox.c
@@ -0,0 +1,97 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ *
+ * MIPS Trickbox
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "trace.h"
+#include "sysemu/runstate.h"
+#include "hw/misc/mips_trickbox.h"
+
+static uint64_t mips_trickbox_read(void *opaque, hwaddr addr, unsigned int 
size)
+{
+uint64_t value = 0;
+
+qemu_log_mask(LOG_UNIMP,
+"%s: unimplemented register read 0x%02"HWADDR_PRIx"\n",
+__func__, addr);
+trace_mips_trickbox_read(size, value);
+
+return 0;
+}
+
+static void mips_trickbox_write(void *opaque, hwaddr addr,
+   uint64_t val64, unsigned int size)
+{
+trace_mips_trickbox_write(size, val64);
+
+switch (addr) {
+case REG_SIM_CMD:
+switch (val64 & 0x) {
+case TRICK_PANIC:
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
+break;
+case TRICK_HALT:
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+break;
+case TRICK_SUSPEND:
+qemu_system_suspend_request();
+break;
+case TRICK_RESET:
+qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+break;
+case TRICK_PASS_MIPS:
+case TRICK_PASS_NANOMIPS:
+exit(EXIT_SUCCESS);
+break;
+case TRICK_FAIL_MIPS:
+case TRICK_FAIL_NANOMIPS:
+exit(EXIT_FAILURE);
+break;
+}
+break;
+default:
+qemu_log_mask(LOG_UNIMP,
+  "%s: unimplemented register write 0x%02"HWADDR_PRIx"\n",
+  __func__, addr);
+break;
+}
+}
+
+static const MemoryRegionOps mips_trickbox_ops = {
+.read = mips_trickbox_read,
+.write = mips_trickbox_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid = {
+.min_access_size = 2,
+.max_access_size = 4
+}
+};
+
+static void mips_trickbox_init(Object *obj)
+{
+MIPSTrickboxState *s = MIPS_TRICKBOX(obj);
+
+memory_region_init_io(>mmio, obj, _trickbox_ops, s,
+  TYPE_MIPS_TRICKBOX, 0x100);
+sysbus_init_mmio(SYS_BUS_DEVICE(obj), >mmio);
+}
+
+static const TypeInfo mips_trickbox_info = {
+.name  = TYPE_MIPS_TRICKBOX,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(MIPSTrickboxState),
+.instance_init = mips_trickbox_init,
+};
+
+static void mips_trickbox_register_types(void)
+{
+type_register_static(_trickbox_info);
+}
+
+type_init(mips_trickbox_register_types)
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index c47876a902..8603cf0d5a 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -279,3 +279,7 @@ virt_ctrl_instance_init(void *dev) "ctrl: %p"
 lasi_chip_mem_valid(uint64_t addr, uint32_t val) "access to addr 0x%"PRIx64" 
is %d"
 lasi_chip_read(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"
 lasi_chip_write(uint64_t addr, uint32_t val) "addr 0x%&q

[PATCH 0/3] MIPS Virt machine

2023-02-02 Thread Jiaxun Yang
Hi there,

This patchset is to add a new machine type for MIPS architecture, which
is purely a VirtIO machine.

It is design to utilize existing VirtIO infrastures but also comptitable
with MIPS's existing internal simulation tools.

It should be able to cooperate with any MIPS core and boot Generic MIPS
kernel.

For testing purpose I've built little endian kernel[1] to work with this
machine with R4X00, loongson2f, octeon, mips32r2, mips64r2 and mips64r6. 

TODO:
- Documentation
- Test against big endian kernel
- nanoMIPS options

Thanks

Jiaxun Yang (3):
  docs/system: Remove "mips" board from target-mips.rst
  hw/misc: Add MIPS Trickbox device
  hw/mips: Add MIPS virt board

 MAINTAINERS |7 +
 configs/devices/mips-softmmu/common.mak |1 +
 docs/system/target-mips.rst |   26 +-
 hw/mips/Kconfig |   18 +
 hw/mips/meson.build |1 +
 hw/mips/virt.c  | 1015 +++
 hw/misc/Kconfig |3 +
 hw/misc/meson.build |1 +
 hw/misc/mips_trickbox.c |   97 +++
 hw/misc/trace-events|4 +
 include/hw/misc/mips_trickbox.h |   41 +
 11 files changed, 1206 insertions(+), 8 deletions(-)
 create mode 100644 hw/mips/virt.c
 create mode 100644 hw/misc/mips_trickbox.c
 create mode 100644 include/hw/misc/mips_trickbox.h

-- 
2.37.1 (Apple Git-137.1)




Re: [PATCH-for-8.0 6/7] hw/mips/bootloader: Implement nanoMIPS SW opcode

2022-12-11 Thread Jiaxun Yang



> 2022年12月10日 15:55,Philippe Mathieu-Daudé  写道:
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
> hw/mips/bootloader.c | 25 -
> 1 file changed, 24 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/mips/bootloader.c b/hw/mips/bootloader.c
> index cc3df385df..541b59bf84 100644
> --- a/hw/mips/bootloader.c
> +++ b/hw/mips/bootloader.c
> @@ -177,9 +177,32 @@ static void bl_gen_ori(void **p, bl_reg rt, bl_reg rs, 
> uint16_t imm)
> }
> }
> 
> +static void bl_gen_sw_nm(void **ptr, bl_reg rt, uint8_t rs, uint16_t offset)
> +{
> +uint16_t *p = (uint16_t *)*ptr;
> +uint32_t insn = 0;
> +
> +insn = deposit32(insn, 26, 6, 0b11);
> +insn = deposit32(insn, 21, 5, rt);
> +insn = deposit32(insn, 16, 5, rs);
> +insn = deposit32(insn, 12, 4, 0b1001);
> +insn = deposit32(insn, 0, 12, offset);
> +
> +stw_p(p, insn >> 16);
> +p++;
> +stw_p(p, insn >> 0);
> +p++;

Think we can have a helper function like st_nm32_p.

Thanks
- Jiaxun

> +
> +*ptr = p;
> +}
> +
> static void bl_gen_sw(void **p, bl_reg rt, uint8_t base, uint16_t offset)
> {
> -bl_gen_i_type(p, 0x2b, base, rt, offset);
> +if (bootcpu_supports_isa(ISA_NANOMIPS32)) {
> +bl_gen_sw_nm(p, rt, base, offset);
> +} else {
> +bl_gen_i_type(p, 0x2b, base, rt, offset);
> +}
> }
> 
> static void bl_gen_sd(void **p, bl_reg rt, uint8_t base, uint16_t offset)
> -- 
> 2.38.1
> 




Re: [PATCH-for-8.0 4/7] hw/mips/bootloader: Implement nanoMIPS LUI opcode

2022-12-11 Thread Jiaxun Yang



> 2022年12月10日 16:01,Philippe Mathieu-Daudé  写道:
> 
> On 10/12/22 16:54, Philippe Mathieu-Daudé wrote:
>> Signed-off-by: Philippe Mathieu-Daudé 
>> ---
>>  hw/mips/bootloader.c | 29 ++---
>>  1 file changed, 26 insertions(+), 3 deletions(-)
>> diff --git a/hw/mips/bootloader.c b/hw/mips/bootloader.c
>> index 7f7d938f2e..997e74ee52 100644
>> --- a/hw/mips/bootloader.c
>> +++ b/hw/mips/bootloader.c
>> @@ -120,11 +120,34 @@ static void bl_gen_jalr(void **p, bl_reg rs)
>>  bl_gen_r_type(p, 0, rs, 0, BL_REG_RA, 0, 0x09);
>>  }
>>  +static void bl_gen_lui_nm(void **ptr, bl_reg rt, uint32_t imm20)
>> +{
>> +uint16_t *p = (uint16_t *)*ptr;
>> +uint32_t insn = 0;
> 
> Hmm we should check if imm20 fits in 20-bit.

Perhaps it will be easier to use 48bit addiu instruction to generate LI?

Thanks
- Jiaxun

> 
>> +insn = deposit32(insn, 26, 6, 0b111000);
>> +insn = deposit32(insn, 21, 5, rt);
>> +insn = deposit32(insn, 12, 9, extract32(imm20, 12, 9));
>> +insn = deposit32(insn, 2, 10, extract32(imm20, 21, 10));
>> +insn = deposit32(insn, 0, 1, sextract32(imm20, 31, 1));
>> +
>> +stw_p(p, insn >> 16);
>> +p++;
>> +stw_p(p, insn >> 0);
>> +p++;
>> +
>> +*ptr = p;
>> +}





Re: CVMSEG Emulation

2022-12-09 Thread Jiaxun Yang



> 2022年12月9日 17:44,Christopher Wrogg  写道:
> 
> I tried both.
> 
> Option 1 
> What I did:
> #undef TARGET_VIRT_ADDR_SPACE_BITS and #define 
> TARGET_VIRT_ADDR_SPACE_BITS 64
> The Result:
> perror reports "Cannot allocate memory"
> Option 2: 
> What I did:
> TARGET_VIRT_ADDR_SPACE_BITS for me is 30 so I masked by 0x3FFF
> The Result:
> The segfault persists and gdb reports the memory as inaccessible.

Hmm this looks wired for me, by no chance TARGET_VIRT_ADDR_SPACE_BITS for MIPS
can be 30, on N64 ABI build it should be 48 and 32 for N32 or O32 build.

It is defined in target/mips/cpu-param.h .

Thanks.

> 
> On Thu, Dec 8, 2022 at 4:55 PM Jiaxun Yang  wrote:
> 
> Hi,
> 
> This address range is located in KSEG3… Doesn’t seems to be a good location
> for userspace program.
> 
> I think you have two options to make target_mmap work, the first would be 
> rising
> TARGET_VIRT_ADDR_SPACE_BITS to 64 bit. That may break some user space
> applications storing pointer tags on higher bits.
> 
> The second would be mask CVMSEG base with TARGET_VIRT_ADDR_SPACE_BITS
> before mmap, As higher VM address bits will be dropped when addressing guest 
> VM,
> that should provide a similar behaviour. Though you’ll have multiple alias 
> for CVMSEG in
> memory and application will be able to access CVMSEG with bits higher than
> TARGET_VIRT_ADDR_SPACE_BITS set to any value. Don’t know if it will break 
> anything,
> AFAIK normal applications won't use this range.
> 
> Thanks
> - Jiaxun 
> 
> 
> > 2022年12月8日 15:08,Christopher Wrogg  写道:
> > 
> > In userspace emulation how do I make a set of addresses always valid and 
> > initialized to 0 even though the process does not map it in? In particular 
> > I want to map the CVMSEG for Cavium qemu-mips64 and qemu-mipsn32. The 
> > addresses would be 0x8000 - 0xBFFF. I've looked at 
> > target_mmap but it can't handle addresses that large. The lack of an 
> > emulated mmu for 64 bit guests is going to be a problem.
> 




Re: CVMSEG Emulation

2022-12-08 Thread Jiaxun Yang


Hi,

This address range is located in KSEG3… Doesn’t seems to be a good location
for userspace program.

I think you have two options to make target_mmap work, the first would be rising
TARGET_VIRT_ADDR_SPACE_BITS to 64 bit. That may break some user space
applications storing pointer tags on higher bits.

The second would be mask CVMSEG base with TARGET_VIRT_ADDR_SPACE_BITS
before mmap, As higher VM address bits will be dropped when addressing guest VM,
that should provide a similar behaviour. Though you’ll have multiple alias for 
CVMSEG in
memory and application will be able to access CVMSEG with bits higher than
TARGET_VIRT_ADDR_SPACE_BITS set to any value. Don’t know if it will break 
anything,
AFAIK normal applications won't use this range.

Thanks
- Jiaxun 


> 2022年12月8日 15:08,Christopher Wrogg  写道:
> 
> In userspace emulation how do I make a set of addresses always valid and 
> initialized to 0 even though the process does not map it in? In particular I 
> want to map the CVMSEG for Cavium qemu-mips64 and qemu-mipsn32. The addresses 
> would be 0x8000 - 0xBFFF. I've looked at target_mmap 
> but it can't handle addresses that large. The lack of an emulated mmu for 64 
> bit guests is going to be a problem.




Re: [RFC PATCH 3/3] hw/mips: Add MIPS VirtIO board

2022-11-25 Thread Jiaxun Yang



> 2022年11月25日 13:25,Philippe Mathieu-Daudé  写道:
> 
> On 24/11/22 22:29, Jiaxun Yang wrote:
>> MIPS VirtIO board is design to utilize existing VirtIO infrastures
>> but also comptitable with MIPS's existing internal simulation tools.
>> It includes virtio-mmio, pcie gpex, flash rom, fw_cfg, goldfish-rtc,
>> and optional goldfish_pic in case MIPS GIC is not present.
>> It should be able to cooperate with any MIPS CPU cores.
>> Signed-off-by: Jiaxun Yang 
>> ---
>>  configs/devices/mips-softmmu/common.mak |1 +
>>  hw/mips/Kconfig |   18 +
>>  hw/mips/meson.build |1 +
>>  hw/mips/virt.c  | 1039 +++
>>  4 files changed, 1059 insertions(+)
>>  create mode 100644 hw/mips/virt.c
>> diff --git a/configs/devices/mips-softmmu/common.mak 
>> b/configs/devices/mips-softmmu/common.mak
>> index 416161f833..534b7843eb 100644
>> --- a/configs/devices/mips-softmmu/common.mak
>> +++ b/configs/devices/mips-softmmu/common.mak
>> @@ -29,6 +29,7 @@ CONFIG_MC146818RTC=y
>>  CONFIG_EMPTY_SLOT=y
>>  CONFIG_MIPS_CPS=y
>>  CONFIG_MIPS_ITU=y
>> +CONFIG_MIPS_VIRT=y
> 
> Is there any value adding the 32-bit machine, or can we just add it as 64-bit?

Well because it can boot with generic kernel so people can still test it again 
various
32bit cores like old 4K / 24K / and newer P5600 / Ingenic XBurst / I7200.

There will be some new 32-bit nanoMIPS products,  though they will run highly 
customised
software instead of Linux stuff :-(

> 
>> +struct MIPSVirtState {
>> +MachineState parent;
>> +
>> +Notifier machine_done;
>> +Clock *cpuclk;
>> +DeviceState *platform_bus_dev;
>> +MIPSCPSState *cps;
>> +DeviceState *pic;
>> +PFlashCFI01 *flash[2];
> 
> We should be fine with 1 ROM for CODE and 1 flash for VARS,
> see my previous comments on the LoongArch virt machine:
> 
> https://lore.kernel.org/qemu-devel/2f381d06-842f-ac8b-085c-0419675a4...@linaro.org/
> https://lore.kernel.org/qemu-devel/b62401b2-3a12-e89d-6953-b40dd170b...@linaro.org/

Will use use this scheme, thanks.
Any recommendation on size of those two regions?

Thanks
- Jiaxun

> 
>> +FWCfgState *fw_cfg;
>> +
>> +MIPSVirtPlatType plat_type;
>> +int fdt_size;
>> +};





[RFC PATCH 3/3] hw/mips: Add MIPS VirtIO board

2022-11-24 Thread Jiaxun Yang
MIPS VirtIO board is design to utilize existing VirtIO infrastures
but also comptitable with MIPS's existing internal simulation tools.

It includes virtio-mmio, pcie gpex, flash rom, fw_cfg, goldfish-rtc,
and optional goldfish_pic in case MIPS GIC is not present.

It should be able to cooperate with any MIPS CPU cores.

Signed-off-by: Jiaxun Yang 
---
 configs/devices/mips-softmmu/common.mak |1 +
 hw/mips/Kconfig |   18 +
 hw/mips/meson.build |1 +
 hw/mips/virt.c  | 1039 +++
 4 files changed, 1059 insertions(+)
 create mode 100644 hw/mips/virt.c

diff --git a/configs/devices/mips-softmmu/common.mak 
b/configs/devices/mips-softmmu/common.mak
index 416161f833..534b7843eb 100644
--- a/configs/devices/mips-softmmu/common.mak
+++ b/configs/devices/mips-softmmu/common.mak
@@ -29,6 +29,7 @@ CONFIG_MC146818RTC=y
 CONFIG_EMPTY_SLOT=y
 CONFIG_MIPS_CPS=y
 CONFIG_MIPS_ITU=y
+CONFIG_MIPS_VIRT=y
 CONFIG_MALTA=y
 CONFIG_PCNET_PCI=y
 CONFIG_MIPSSIM=y
diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index 725525358d..419a729479 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -57,5 +57,23 @@ config MIPS_BOSTON
 select AHCI_ICH9
 select SERIAL
 
+config MIPS_VIRT
+bool
+imply PCI_DEVICES
+imply VIRTIO_VGA
+imply TEST_DEVICES
+select MIPS_CPS
+select MIPS_TRICKBOX
+select SERIAL
+select FW_CFG_MIPS
+select GOLDFISH_RTC
+select GOLDFISH_PIC
+select PCI
+select PCI_EXPRESS_GENERIC_BRIDGE
+select PFLASH_CFI01
+select VIRTIO_MMIO
+select FW_CFG_DMA
+select PLATFORM_BUS
+
 config FW_CFG_MIPS
 bool
diff --git a/hw/mips/meson.build b/hw/mips/meson.build
index dd0101ad4d..287425cb10 100644
--- a/hw/mips/meson.build
+++ b/hw/mips/meson.build
@@ -1,6 +1,7 @@
 mips_ss = ss.source_set()
 mips_ss.add(files('bootloader.c', 'mips_int.c'))
 mips_ss.add(when: 'CONFIG_FW_CFG_MIPS', if_true: files('fw_cfg.c'))
+mips_ss.add(when: 'CONFIG_MIPS_VIRT', if_true: files('virt.c'))
 mips_ss.add(when: 'CONFIG_LOONGSON3V', if_true: files('loongson3_bootp.c', 
'loongson3_virt.c'))
 mips_ss.add(when: 'CONFIG_MALTA', if_true: files('gt64xxx_pci.c', 'malta.c'))
 mips_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('cps.c'))
diff --git a/hw/mips/virt.c b/hw/mips/virt.c
new file mode 100644
index 00..d7a1d211ac
--- /dev/null
+++ b/hw/mips/virt.c
@@ -0,0 +1,1039 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * QEMU MIPS VirtIO Board
+ * Copyright (C) 2022 Jiaxun Yang 
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qemu/datadir.h"
+
+#include "chardev/char.h"
+#include "hw/block/flash.h"
+#include "hw/boards.h"
+#include "hw/char/serial.h"
+#include "hw/core/sysbus-fdt.h"
+#include "hw/display/ramfb.h"
+#include "hw/intc/goldfish_pic.h"
+#include "hw/loader-fit.h"
+#include "hw/loader.h"
+#include "hw/mips/bootloader.h"
+#include "hw/mips/cps.h"
+#include "hw/mips/cpudevs.h"
+#include "hw/mips/mips.h"
+#include "hw/misc/mips_trickbox.h"
+#include "hw/pci-host/gpex.h"
+#include "hw/pci/pci.h"
+#include "hw/platform-bus.h"
+#include "hw/qdev-clock.h"
+#include "hw/qdev-properties.h"
+#include "hw/rtc/goldfish_rtc.h"
+#include "hw/sysbus.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "qemu/guest-random.h"
+#include "qemu/log.h"
+#include "sysemu/device_tree.h"
+#include "sysemu/qtest.h"
+#include "sysemu/reset.h"
+#include "sysemu/runstate.h"
+#include "sysemu/sysemu.h"
+#include "elf.h"
+
+#include "qom/object.h"
+#include 
+
+#define TYPE_MIPS_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
+typedef struct MIPSVirtState MIPSVirtState;
+DECLARE_INSTANCE_CHECKER(MIPSVirtState, MIPS_VIRT_MACHINE,
+ TYPE_MIPS_VIRT_MACHINE)
+
+#define FDT_IRQ_TYPE_NONE 0
+#define FDT_IRQ_TYPE_LEVEL_HIGH 4
+#define FDT_GIC_SHARED 0
+#define FDT_GIC_LOCAL 1
+#define FDT_VIRT_CLK_SYS 1
+#define FDT_VIRT_CLK_CPU 2
+#define FDT_PCI_IRQ_MAP_PINS 4
+#define FDT_PCI_IRQ_MAP_DESCS 6
+
+#define FDT_PCI_ADDR_CELLS 3
+#define FDT_PCI_INT_CELLS 1
+#define FDT_MAX_INT_CELLS 3
+#define FDT_MAX_INT_MAP_WIDTH \
+(FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + 1 + FDT_MAX_INT_CELLS)
+
+#define VIRT_CPU_REF_CLK_FREQ 1
+
+typedef enum MIPSVirtPlatType {
+VIRT_PLAT_UP = 0,
+VIRT_PLAT_CPS = 1
+} MIPSVirtPlatType;
+
+struct MIPSVirtState {
+MachineState parent;
+
+Notifier machine_done;
+Clock *cpuclk;
+DeviceState *platform_bus_dev;
+MIPSCPSState *cps;
+DeviceState *pic;
+PFlashCFI01 *flash[2];
+FWCfgState *fw_cfg;
+
+MIPSVirtPlatType plat_type;
+int 

[RFC PATCH 0/3] MIPS VirtIO Machine

2022-11-24 Thread Jiaxun Yang
Hi there,

This patchset is to add a new machine type for MIPS architecture, which
is purely a VirtIO machine.

It is design to utilize existing VirtIO infrastures but also comptitable
with MIPS's existing internal simulation tools.

It should be able to cooperate with any MIPS core and boot Generic MIPS
kernel.

For testing purpose I've built little endian kernel[1] to work with this
machine with R4X00, loongson2f, octeon, mips32r2, mips64r2 and mips64r6. 

TODO:
- Documentation
- Test against big endian kernel
- nanoMIPS options

Thanks

[1]: https://github.com/FlyGoat/qemu-testing-blob/tree/main/kernel

Jiaxun Yang (3):
  hw/intc: Add missing include for goldfish_pic.h
  hw/misc: Add MIPS Trickbox device
  hw/mips: Add MIPS VirtIO board

 configs/devices/mips-softmmu/common.mak |1 +
 hw/mips/Kconfig |   18 +
 hw/mips/meson.build |1 +
 hw/mips/virt.c  | 1039 +++
 hw/misc/Kconfig |3 +
 hw/misc/meson.build |1 +
 hw/misc/mips_trickbox.c |   97 +++
 hw/misc/trace-events|4 +
 include/hw/intc/goldfish_pic.h  |2 +
 include/hw/misc/mips_trickbox.h |   41 +
 10 files changed, 1207 insertions(+)
 create mode 100644 hw/mips/virt.c
 create mode 100644 hw/misc/mips_trickbox.c
 create mode 100644 include/hw/misc/mips_trickbox.h

-- 
2.37.1 (Apple Git-137.1)




[RFC PATCH 1/3] hw/intc: Add missing include for goldfish_pic.h

2022-11-24 Thread Jiaxun Yang
hw/sysbus.h is missed in goldfish_pic.h.

Signed-off-by: Jiaxun Yang 
---
 include/hw/intc/goldfish_pic.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/hw/intc/goldfish_pic.h b/include/hw/intc/goldfish_pic.h
index e9d552f796..3e79580367 100644
--- a/include/hw/intc/goldfish_pic.h
+++ b/include/hw/intc/goldfish_pic.h
@@ -10,6 +10,8 @@
 #ifndef HW_INTC_GOLDFISH_PIC_H
 #define HW_INTC_GOLDFISH_PIC_H
 
+#include "hw/sysbus.h"
+
 #define TYPE_GOLDFISH_PIC "goldfish_pic"
 OBJECT_DECLARE_SIMPLE_TYPE(GoldfishPICState, GOLDFISH_PIC)
 
-- 
2.37.1 (Apple Git-137.1)




[RFC PATCH 2/3] hw/misc: Add MIPS Trickbox device

2022-11-24 Thread Jiaxun Yang
MIPS Trickbox is a emulated device present in MIPS's proprietary
simulators for decadeds. It's capable for managing simulator status,
signaling interrupts, doing DMA and EJTAG stimulations.

For now we just borrow this device and implement power management
related functions.

Signed-off-by: Jiaxun Yang 
---
 hw/misc/Kconfig |  3 +
 hw/misc/meson.build |  1 +
 hw/misc/mips_trickbox.c | 97 +
 hw/misc/trace-events|  4 ++
 include/hw/misc/mips_trickbox.h | 41 ++
 5 files changed, 146 insertions(+)
 create mode 100644 hw/misc/mips_trickbox.c
 create mode 100644 include/hw/misc/mips_trickbox.h

diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index cbabe9f78c..fa92c439ec 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -89,6 +89,9 @@ config STM32F4XX_EXTI
 config MIPS_ITU
 bool
 
+config MIPS_TRICKBOX
+bool
+
 config MPS2_FPGAIO
 bool
 select LED
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 95268eddc0..116eff8890 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -133,6 +133,7 @@ specific_ss.add(when: 'CONFIG_MAC_VIA', if_true: 
files('mac_via.c'))
 
 specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_cmgcr.c', 
'mips_cpc.c'))
 specific_ss.add(when: 'CONFIG_MIPS_ITU', if_true: files('mips_itu.c'))
+specific_ss.add(when: 'CONFIG_MIPS_TRICKBOX', if_true: 
files('mips_trickbox.c'))
 
 specific_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa_ec.c'))
 
diff --git a/hw/misc/mips_trickbox.c b/hw/misc/mips_trickbox.c
new file mode 100644
index 00..20349b774b
--- /dev/null
+++ b/hw/misc/mips_trickbox.c
@@ -0,0 +1,97 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.0-or-later
+ *
+ * MIPS Trickbox
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "trace.h"
+#include "sysemu/runstate.h"
+#include "hw/misc/mips_trickbox.h"
+
+static uint64_t mips_trickbox_read(void *opaque, hwaddr addr, unsigned int 
size)
+{
+uint64_t value = 0;
+
+qemu_log_mask(LOG_UNIMP,
+"%s: unimplemented register read 0x%02"HWADDR_PRIx"\n",
+__func__, addr);
+trace_mips_trickbox_read(size, value);
+
+return 0;
+}
+
+static void mips_trickbox_write(void *opaque, hwaddr addr,
+   uint64_t val64, unsigned int size)
+{
+trace_mips_trickbox_write(size, val64);
+
+switch (addr) {
+case REG_SIM_CMD:
+switch (val64 & 0x) {
+case TRICK_PANIC:
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
+break;
+case TRICK_HALT:
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+break;
+case TRICK_SUSPEND:
+qemu_system_suspend_request();
+break;
+case TRICK_RESET:
+qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+break;
+case TRICK_PASS_MIPS:
+case TRICK_PASS_NANOMIPS:
+exit(EXIT_SUCCESS);
+break;
+case TRICK_FAIL_MIPS:
+case TRICK_FAIL_NANOMIPS:
+exit(EXIT_FAILURE);
+break;
+}
+break;
+default:
+qemu_log_mask(LOG_UNIMP,
+  "%s: unimplemented register write 0x%02"HWADDR_PRIx"\n",
+  __func__, addr);
+break;
+}
+}
+
+static const MemoryRegionOps mips_trickbox_ops = {
+.read = mips_trickbox_read,
+.write = mips_trickbox_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid = {
+.min_access_size = 2,
+.max_access_size = 4
+}
+};
+
+static void mips_trickbox_init(Object *obj)
+{
+MIPSTrickboxState *s = MIPS_TRICKBOX(obj);
+
+memory_region_init_io(>mmio, obj, _trickbox_ops, s,
+  TYPE_MIPS_TRICKBOX, 0x100);
+sysbus_init_mmio(SYS_BUS_DEVICE(obj), >mmio);
+}
+
+static const TypeInfo mips_trickbox_info = {
+.name  = TYPE_MIPS_TRICKBOX,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(MIPSTrickboxState),
+.instance_init = mips_trickbox_init,
+};
+
+static void mips_trickbox_register_types(void)
+{
+type_register_static(_trickbox_info);
+}
+
+type_init(mips_trickbox_register_types)
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index c18bc0605e..6df0e42450 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -274,3 +274,7 @@ virt_ctrl_instance_init(void *dev) "ctrl: %p"
 lasi_chip_mem_valid(uint64_t addr, uint32_t val) "access to addr 0x%"PRIx64" 
is %d"
 lasi_chip_read(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"
 lasi_chip_write(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"
+
+# mip

Re: [PATCH v2 2/3] hw/mips/malta: Set PIIX4 IRQ routes in embedded bootloader

2022-11-23 Thread Jiaxun Yang



> 2022年11月22日 12:37,BALATON Zoltan  写道:
> 
> Hello,
> 
> On Mon, 21 Nov 2022, Bernhard Beschow wrote:
>> Am 21. November 2022 22:43:50 UTC schrieb "Philippe Mathieu-Daudé" 
>> :
>>> On 21/11/22 16:34, Bernhard Beschow wrote:
 Am 27. Oktober 2022 20:47:19 UTC schrieb "Philippe Mathieu-Daudé" 
 :
> Linux kernel expects the northbridge & southbridge chipsets
> configured by the BIOS firmware. We emulate that by writing
> a tiny bootloader code in write_bootloader().
> 
> Upon introduction in commit 5c2b87e34d ("PIIX4 support"),
> the PIIX4 configuration space included values specific to
> the Malta board.
> 
> Set the Malta-specific IRQ routing values in the embedded
> bootloader, so the next commit can remove the Malta specific
> bits from the PIIX4 PCI-ISA bridge and make it generic
> (matching the real hardware).
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
> FIXME: Missing the nanoMIPS counter-part!
 
 Who will be taking care of this? I have absolutely no clue how the 
 write_bootloader functions work, so I don't see how to fix it.
>>> 
>>> Oh actually I wrote that and tested it but context switched and forgot
>>> about it... I'll look back when I get some time, probably around the
>>> release.

I can try to adopt existing boot loader helper functions, just a matter of 
opcodes I think.

> 
> Unrelated to this but found it while looking at malta.c now: another possible 
> clean up is to replace the local generate_eeprom_spd() func with 
> spd_data_generate() from hw/i2c/smbus_eeprom.c that other boards use already 
> but I did not change malta because I could not test it. If you can test malta 
> then it should be an easy change and simplify malta.c a bit.
> 
 Couldn't we just do it like in pegasos2_init() where the registers are 
 initialized by QEMU directly if there is no bootloader binary configured? 
 I could do that.
>>> I rather mimic bootloaders... maybe a matter of taste?
> 
> Is that a bootloader or a replacement firmware? To me bootloader is some OS 
> specific binary that is loaded by firware to boot an OS. But there are OS 
> independent bootloaders like grub so maybe you could emulate something like 
> that, I don't know what malta does.

YAMON is a OS-dependent and HW-dependent firmware like u-boot.

> 
> If there's no firmware binary QEMU should provide something to replace it to 
> give the expected environment for the binary loaded by -kernel. In case of 
> pegasos2 the init method sets up regs to init devices as done by the firmware 
> and the rest is implemented by VOF (loaded from pc-bios) that provices the 
> OpenFirmware client interface. The device setup in init is needed because VOF 
> does not do that.
> 
>> I don't mind either way. I meant that I could help with the second approach 
>> but not with the current one since I have no clue whatsoever how it works. 
>> There are just too many magic constants that don't make any sense to me, and 
>> too many layers of indirection, for example.
> 
> If malta has a replacement firmware for this case maybe it could be stored in 
> a binary in pc-bios and loaded from there instead of writing it in hex to 
> guest memory. That binary could even be assembled from source which should 
> make it simpler to write and change. Or is YAMON open source? According to 
> this page it is: https://www.mips.com/develop/tools/boot-loaders/ so maybe it 
> could be included as a firmware binary instead of being emulated?

Hmm, YAMON was a open source software but I’m unable to find a copy of source 
for Malta board comes with GT chipset that QEMU emulated.
So nowadays we mainly use -kernel feature to do direct kernel boot.

Direct kernel boot is really a brilliant function that I don’t want to lose :-)

Thanks
- Jiaxun


> 
> Regards,
> BALATON Zoltan
> 
>> Anyway, I'm asking for the current state because I'm pretty much ready for 
>> posting a v3 of my PIIX consolidation series which now depends on this 
>> series.
>> 
>> Best regards,
>> Bernhard
>> 
>>> 
>>> Regards,
>>> 
>>> Phil.
>> 




Re: [PATCH] target/mips: Properly set C0_CMGCRBase after CPU reset

2022-11-23 Thread Jiaxun Yang



> 2022年11月14日 16:25,Jiaxun Yang  写道:
> 
> Value of C0_CMGCRBase will be reseted to default when cpu reset
> happens. In some cases software may move GCR base and then initiate
> a CPU reset, this will leave C0_CMGCRBase of reseted core incorrect.
> 
> Implement a callback in CMGCR device to allow C0_CMGCRBase and other
> global states to be overriden after CPU reset.
> 
> Signed-off-by: Jiaxun Yang 
> ---
> This fixes SMP boot for Boston board.
> I'm not sure if it's the best palce to make such a callback,
> but we can add more global states such as BEV here in future.

Ping :-)

Any comments?

> ---
> hw/mips/cps.c| 3 ++-
> hw/misc/mips_cmgcr.c | 5 +
> target/mips/cpu.c| 4 +++-
> target/mips/cpu.h| 4 
> 4 files changed, 14 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/mips/cps.c b/hw/mips/cps.c
> index 2b436700ce..29b10ff8d0 100644
> --- a/hw/mips/cps.c
> +++ b/hw/mips/cps.c
> @@ -98,6 +98,7 @@ static void mips_cps_realize(DeviceState *dev, Error **errp)
> cpu_mips_clock_init(cpu);
> 
> env = >env;
> +env->gcr = >gcr;
> if (cpu_mips_itu_supported(env)) {
> itu_present = true;
> /* Attach ITC Tag to the VP */
> @@ -158,7 +159,7 @@ static void mips_cps_realize(DeviceState *dev, Error 
> **errp)
> sysbus_mmio_get_region(SYS_BUS_DEVICE(>gic), 
> 0));
> 
> /* Global Configuration Registers */
> -gcr_base = env->CP0_CMGCRBase << 4;
> +gcr_base = GCR_BASE_ADDR;
> 
> object_initialize_child(OBJECT(dev), "gcr", >gcr, TYPE_MIPS_GCR);
> object_property_set_int(OBJECT(>gcr), "num-vp", s->num_vp,
> diff --git a/hw/misc/mips_cmgcr.c b/hw/misc/mips_cmgcr.c
> index 3c8b37f700..f2108b7d32 100644
> --- a/hw/misc/mips_cmgcr.c
> +++ b/hw/misc/mips_cmgcr.c
> @@ -19,6 +19,11 @@
> #include "hw/qdev-properties.h"
> #include "hw/intc/mips_gic.h"
> 
> +void gcr_cpu_reset(struct MIPSGCRState *s, CPUMIPSState *env)
> +{
> +env->CP0_CMGCRBase = s->gcr_base >> 4;
> +}
> +
> static inline bool is_cpc_connected(MIPSGCRState *s)
> {
> return s->cpc_mr != NULL;
> diff --git a/target/mips/cpu.c b/target/mips/cpu.c
> index e997c1b9cb..d0a76b95f7 100644
> --- a/target/mips/cpu.c
> +++ b/target/mips/cpu.c
> @@ -297,7 +297,9 @@ static void mips_cpu_reset(DeviceState *dev)
> env->CP0_EBase |= (int32_t)0x8000;
> }
> if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
> -env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
> +if (env->gcr) {
> +gcr_cpu_reset(env->gcr, env);
> +}
> }
> env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ?
> 0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff;
> diff --git a/target/mips/cpu.h b/target/mips/cpu.h
> index 0a085643a3..c345e6b1c7 100644
> --- a/target/mips/cpu.h
> +++ b/target/mips/cpu.h
> @@ -1154,6 +1154,7 @@ typedef struct CPUArchState {
> CPUMIPSTLBContext *tlb;
> void *irq[8];
> struct MIPSITUState *itu;
> +struct MIPSGCRState *gcr;
> MemoryRegion *itc_tag; /* ITC Configuration Tags */
> #endif
> 
> @@ -1310,6 +1311,9 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int 
> level);
> /* mips_itu.c */
> void itc_reconfigure(struct MIPSITUState *tag);
> 
> +/* mips_cmgcr.c */
> +void gcr_cpu_reset(struct MIPSGCRState *s, CPUMIPSState *env);
> +
> #endif /* !CONFIG_USER_ONLY */
> 
> /* helper.c */
> -- 
> 2.37.4
> 




[PATCH] target/mips: Properly set C0_CMGCRBase after CPU reset

2022-11-14 Thread Jiaxun Yang
Value of C0_CMGCRBase will be reseted to default when cpu reset
happens. In some cases software may move GCR base and then initiate
a CPU reset, this will leave C0_CMGCRBase of reseted core incorrect.

Implement a callback in CMGCR device to allow C0_CMGCRBase and other
global states to be overriden after CPU reset.

Signed-off-by: Jiaxun Yang 
---
This fixes SMP boot for Boston board.
I'm not sure if it's the best palce to make such a callback,
but we can add more global states such as BEV here in future.
---
 hw/mips/cps.c| 3 ++-
 hw/misc/mips_cmgcr.c | 5 +
 target/mips/cpu.c| 4 +++-
 target/mips/cpu.h| 4 
 4 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/hw/mips/cps.c b/hw/mips/cps.c
index 2b436700ce..29b10ff8d0 100644
--- a/hw/mips/cps.c
+++ b/hw/mips/cps.c
@@ -98,6 +98,7 @@ static void mips_cps_realize(DeviceState *dev, Error **errp)
 cpu_mips_clock_init(cpu);
 
 env = >env;
+env->gcr = >gcr;
 if (cpu_mips_itu_supported(env)) {
 itu_present = true;
 /* Attach ITC Tag to the VP */
@@ -158,7 +159,7 @@ static void mips_cps_realize(DeviceState *dev, Error **errp)
 sysbus_mmio_get_region(SYS_BUS_DEVICE(>gic), 
0));
 
 /* Global Configuration Registers */
-gcr_base = env->CP0_CMGCRBase << 4;
+gcr_base = GCR_BASE_ADDR;
 
 object_initialize_child(OBJECT(dev), "gcr", >gcr, TYPE_MIPS_GCR);
 object_property_set_int(OBJECT(>gcr), "num-vp", s->num_vp,
diff --git a/hw/misc/mips_cmgcr.c b/hw/misc/mips_cmgcr.c
index 3c8b37f700..f2108b7d32 100644
--- a/hw/misc/mips_cmgcr.c
+++ b/hw/misc/mips_cmgcr.c
@@ -19,6 +19,11 @@
 #include "hw/qdev-properties.h"
 #include "hw/intc/mips_gic.h"
 
+void gcr_cpu_reset(struct MIPSGCRState *s, CPUMIPSState *env)
+{
+env->CP0_CMGCRBase = s->gcr_base >> 4;
+}
+
 static inline bool is_cpc_connected(MIPSGCRState *s)
 {
 return s->cpc_mr != NULL;
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index e997c1b9cb..d0a76b95f7 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -297,7 +297,9 @@ static void mips_cpu_reset(DeviceState *dev)
 env->CP0_EBase |= (int32_t)0x8000;
 }
 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
-env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
+if (env->gcr) {
+gcr_cpu_reset(env->gcr, env);
+}
 }
 env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ?
 0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff;
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 0a085643a3..c345e6b1c7 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -1154,6 +1154,7 @@ typedef struct CPUArchState {
 CPUMIPSTLBContext *tlb;
 void *irq[8];
 struct MIPSITUState *itu;
+struct MIPSGCRState *gcr;
 MemoryRegion *itc_tag; /* ITC Configuration Tags */
 #endif
 
@@ -1310,6 +1311,9 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int 
level);
 /* mips_itu.c */
 void itc_reconfigure(struct MIPSITUState *tag);
 
+/* mips_cmgcr.c */
+void gcr_cpu_reset(struct MIPSGCRState *s, CPUMIPSState *env);
+
 #endif /* !CONFIG_USER_ONLY */
 
 /* helper.c */
-- 
2.37.4




Re: [PATCH 1/2] target/mips: Don't check COP1X for 64 bit FP mode

2022-11-08 Thread Jiaxun Yang




在 2022/11/7 23:29, Philippe Mathieu-Daudé 写道:

On 7/11/22 23:47, Philippe Mathieu-Daudé wrote:

On 2/11/22 17:57, Jiaxun Yang wrote:
Some implementations (i.e. Loongson-2F) may decide to implement a 64 
bit

FPU without implmenting COP1X instructions.

As the eligibility of 64 bit FP instructions is already determined by
CP0St_FR, there is no need to check for COP1X again.

Signed-off-by: Jiaxun Yang 
---
  target/mips/tcg/translate.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 2f2d707a12..e49d2a25a8 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -1545,7 +1545,7 @@ void check_cop1x(DisasContext *ctx)
   */
  void check_cp1_64bitmode(DisasContext *ctx)
  {
-    if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | 
MIPS_HFLAG_COP1X))) {

+    if (unlikely(~ctx->hflags & MIPS_HFLAG_F64) {
  gen_reserved_instruction(ctx);
  }
  }


Did you test your patch? I'm getting:

../../target/mips/tcg/translate.c:1548:49: error: expected ')'
    if (unlikely(~ctx->hflags & MIPS_HFLAG_F64) {
    ^
../../target/mips/tcg/translate.c:1548:8: note: to match this '('
    if (unlikely(~ctx->hflags & MIPS_HFLAG_F64) {
   ^
../../target/mips/tcg/translate.c:1551:1: error: expected statement
}


Woah, typo when copy changes back from test machine...
Will use git publish next time.

Thanks
- Jiaxun



^






Re: [PATCH 2/2] target/mips: Correct check for CABS instructions

2022-11-08 Thread Jiaxun Yang




在 2022/11/7 22:35, Philippe Mathieu-Daudé 写道:

On 2/11/22 17:57, Jiaxun Yang wrote:

Accroading to "MIPS Architecture for Programmers Volume IV-c:
The MIPS-3D Application-Specific Extension to the MIPS64 Architecture"
(MD00099). CABS.cond.fmt belongs to MIPS-3D ASE, and it has nothing 
to do

with COP1X opcode.

Remove all unnecessary COP1X checks and check for MIPS3D availability
in decoding code path.

Signed-off-by: Jiaxun Yang 
---
  target/mips/tcg/translate.c | 9 +
  1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index e49d2a25a8..23e575ad95 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -1788,16 +1788,8 @@ static inline void gen_cmp ## type ## _ ## 
fmt(DisasContext *ctx, int n,  \

check_ps(ctx); \
break; \
  case FMT_D: \
-    if (abs) 
{    \

- check_cop1x(ctx); \
- } \
  check_cp1_registers(ctx, fs | 
ft);    \

break; \
-    case FMT_S: \
-    if (abs) 
{    \

- check_cop1x(ctx); \
- } \
- break; \


I'm not sure we want to remove this check on all opcodes handled by
the FOP_CONDS() macro, and for all architecture variants. Maybe we
need to special-case CABS.cond.fmt?


Hmm if I read the code correctly COP1X check is only ran when abs is
set, and the only case abs is set is for CABS.cond.fmt.




} \
  gen_ldcmp_fpr##bits(ctx, fp0, 
fs);    \
  gen_ldcmp_fpr##bits(ctx, fp1, 
ft);    \
@@ -10424,6 +10416,7 @@ static void gen_farith(DisasContext *ctx, 
enum fopcode op1,

  case OPC_CMP_NGT_S:
  check_insn_opc_removed(ctx, ISA_MIPS_R6);
  if (ctx->opcode & (1 << 6)) {
+    check_insn(ctx, ASE_MIPS3D);


You somehow revert commit b8aa4598e2 ("MIPS COP1X (and related)
instructions") which is in use since 15 years.


Still no idea about why it is here in first place
CABS.cond.fmt is even not mentioned in MIPS IV manual. So it's unlikely 
to have

anything to do with COP1X.

Thanks
- Jiaxun




  gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
  } else {
  gen_cmp_s(ctx, func - 48, ft, fs, cc);







[PATCH 1/2] target/mips: Don't check COP1X for 64 bit FP mode

2022-11-02 Thread Jiaxun Yang
Some implementations (i.e. Loongson-2F) may decide to implement a 64 bit
FPU without implmenting COP1X instructions.

As the eligibility of 64 bit FP instructions is already determined by
CP0St_FR, there is no need to check for COP1X again.

Signed-off-by: Jiaxun Yang 
---
 target/mips/tcg/translate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 2f2d707a12..e49d2a25a8 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -1545,7 +1545,7 @@ void check_cop1x(DisasContext *ctx)
  */
 void check_cp1_64bitmode(DisasContext *ctx)
 {
-if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
+if (unlikely(~ctx->hflags & MIPS_HFLAG_F64) {
 gen_reserved_instruction(ctx);
 }
 }
-- 
2.34.1




[PATCH 2/2] target/mips: Correct check for CABS instructions

2022-11-02 Thread Jiaxun Yang
Accroading to "MIPS Architecture for Programmers Volume IV-c:
The MIPS-3D Application-Specific Extension to the MIPS64 Architecture"
(MD00099). CABS.cond.fmt belongs to MIPS-3D ASE, and it has nothing to do
with COP1X opcode.

Remove all unnecessary COP1X checks and check for MIPS3D availability
in decoding code path.

Signed-off-by: Jiaxun Yang 
---
 target/mips/tcg/translate.c | 9 +
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index e49d2a25a8..23e575ad95 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -1788,16 +1788,8 @@ static inline void gen_cmp ## type ## _ ## 
fmt(DisasContext *ctx, int n,  \
 check_ps(ctx);\
 break;\
 case FMT_D:   \
-if (abs) {\
-check_cop1x(ctx); \
-} \
 check_cp1_registers(ctx, fs | ft);\
 break;\
-case FMT_S:   \
-if (abs) {\
-check_cop1x(ctx); \
-} \
-break;\
 } \
 gen_ldcmp_fpr##bits(ctx, fp0, fs);\
 gen_ldcmp_fpr##bits(ctx, fp1, ft);\
@@ -10424,6 +10416,7 @@ static void gen_farith(DisasContext *ctx, enum fopcode 
op1,
 case OPC_CMP_NGT_S:
 check_insn_opc_removed(ctx, ISA_MIPS_R6);
 if (ctx->opcode & (1 << 6)) {
+check_insn(ctx, ASE_MIPS3D);
 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
 } else {
 gen_cmp_s(ctx, func - 48, ft, fs, cc);
-- 
2.34.1




[PATCH v2 3/3] target/mips: Disable DSP ASE for Octeon68XX

2022-10-31 Thread Jiaxun Yang
I don't have access to Octeon68XX hardware but accroading to
my investigation Octeon never had DSP ASE support.

As per "Cavium Networks OCTEON Plus CN50XX Hardware Reference
Manual" CP0C3_DSPP is reserved bit and read as 0. Also I do have
access to a Ubiquiti Edgerouter 4 which has Octeon CN7130 processor
and I can confirm CP0C3_DSPP is read as 0 on that processor.

Further more, in linux kernel:
arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
cpu_has_dsp is overridden as 0.

So I believe we shouldn't emulate DSP in QEMU as well.

Signed-off-by: Jiaxun Yang 
Acked-by: Richard Henderson 
---
 target/mips/cpu-defs.c.inc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/mips/cpu-defs.c.inc b/target/mips/cpu-defs.c.inc
index 7f53c94ec8..480e60aeec 100644
--- a/target/mips/cpu-defs.c.inc
+++ b/target/mips/cpu-defs.c.inc
@@ -934,7 +934,7 @@ const mips_def_t mips_defs[] =
(1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
 .CP0_Config2 = MIPS_CONFIG2,
-.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_LPA) | (1 << CP0C3_DSPP) ,
+.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_LPA),
 .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) |
(0x3c << CP0C4_KScrExist) | (1U << CP0C4_MMUExtDef) |
(3U << CP0C4_MMUSizeExt),
@@ -946,7 +946,7 @@ const mips_def_t mips_defs[] =
 .CP0_Status_rw_bitmask = 0x12F8,
 .SEGBITS = 42,
 .PABITS = 49,
-.insn_flags = CPU_MIPS64R2 | INSN_OCTEON | ASE_DSP,
+.insn_flags = CPU_MIPS64R2 | INSN_OCTEON,
 .mmu_type = MMU_TYPE_R4000,
 },
 
-- 
2.34.1




[PATCH v2 2/3] target/mips: Cast offset field of Octeon BBIT to int16_t

2022-10-31 Thread Jiaxun Yang
As per "Cavium Networks OCTEON Plus CN50XX Hardware Reference
Manual" offset field is signed 16 bit value. However arg_BBIT.offset
is unsigned. We need to cast it as signed to do address calculation.

Signed-off-by: Jiaxun Yang 
---
v2:
Do casting in decodetree. (philmd)
---
 target/mips/tcg/octeon.decode | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/mips/tcg/octeon.decode b/target/mips/tcg/octeon.decode
index 8929ad088e..0c787cb498 100644
--- a/target/mips/tcg/octeon.decode
+++ b/target/mips/tcg/octeon.decode
@@ -12,7 +12,7 @@
 # BBIT13210 . . 
 
 %bbit_p  28:1 16:5
-BBIT 11 set:1 . 10 rs:5 . offset:16 p=%bbit_p
+BBIT 11 set:1 . 10 rs:5 . offset:s16 p=%bbit_p
 
 # Arithmetic
 # BADDU rd, rs, rt
-- 
2.34.1




  1   2   3   4   >