From caab7ac83507e3e9a5fe2f37be5cfa759e766ba2 Mon Sep 17 00:00:00 2001 From: Bibo Mao Date: Mon, 14 Jul 2025 09:54:46 +0800 Subject: [PATCH 1/2] target/loongarch: Fix valid virtual address checking On LoongArch64 system, the high 32 bit of 64 bit virtual address should be 0x00000[0-7]yyy or 0xffff8yyy. The bit from 47 to 63 should be all 0 or all 1. Function get_physical_address() only checks bit 48 to 63, there will be problem with the following test case. On physical machine, there is bus error report and program exits abnormally. However on qemu TCG system emulation mode, the program runs normally. The virtual address 0xffff000000000000ULL + addr and addr are treated the same on TLB entry checking. This patch fixes this issue. void main() { void *addr, *addr1; int val; addr = malloc(100); *(int *)addr = 1; addr1 = 0xffff000000000000ULL + addr; val = *(int *)addr1; printf("val %d \n", val); } Cc: qemu-stable@nongnu.org Signed-off-by: Bibo Mao Acked-by: Song Gao Reviewed-by: Song Gao Message-ID: <20250714015446.746163-1-maobibo@loongson.cn> Signed-off-by: Song Gao --- target/loongarch/cpu_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c index e172b11ce1..b5f732f15b 100644 --- a/target/loongarch/cpu_helper.c +++ b/target/loongarch/cpu_helper.c @@ -196,8 +196,8 @@ int get_physical_address(CPULoongArchState *env, hwaddr *physical, } /* Check valid extension */ - addr_high = sextract64(address, TARGET_VIRT_ADDR_SPACE_BITS, 16); - if (!(addr_high == 0 || addr_high == -1)) { + addr_high = (int64_t)address >> (TARGET_VIRT_ADDR_SPACE_BITS - 1); + if (!(addr_high == 0 || addr_high == -1ULL)) { return TLBRET_BADADDR; } From 31995cc4087123a13e9345153e0c39ffb44b9277 Mon Sep 17 00:00:00 2001 From: Song Gao Date: Fri, 25 Jul 2025 16:12:13 +0800 Subject: [PATCH 2/2] hw/intc/loongarch_ipi: Fix start fail with smp cpu < smp maxcpus on KVM QEMU start failed when smp cpu < smp maxcpus , because qemu send a NULL cpu to KVM, this patch adds a check for kvm_ipi_access_regs() to fix it. run with '-smp 1,maxcpus=4,sockets=4,cores=1,threads=1' we got: Unexpected error in kvm_device_access() at ../accel/kvm/kvm-all.c:3477: qemu-system-loongarch64: KVM_SET_DEVICE_ATTR failed: Group 1073741825 attr 0x0000000000010000: Invalid argument Signed-off-by: Song Gao Reviewed-by: Bibo Mao Message-ID: <20250725081213.3867592-1-gaosong@loongson.cn> --- hw/intc/loongarch_ipi_kvm.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/hw/intc/loongarch_ipi_kvm.c b/hw/intc/loongarch_ipi_kvm.c index 4cb3acc921..dd4c367abf 100644 --- a/hw/intc/loongarch_ipi_kvm.c +++ b/hw/intc/loongarch_ipi_kvm.c @@ -23,36 +23,41 @@ static void kvm_ipi_access_regs(void *opaque, bool write) LoongarchIPIState *lis = LOONGARCH_IPI(opaque); IPICore *core; uint64_t attr; - int cpu, fd = lis->dev_fd; + int i, cpu_index, fd = lis->dev_fd; if (fd == 0) { return; } - for (cpu = 0; cpu < ipi->num_cpu; cpu++) { - core = &ipi->cpu[cpu]; - attr = (cpu << 16) | CORE_STATUS_OFF; + for (i = 0; i < ipi->num_cpu; i++) { + core = &ipi->cpu[i]; + if (core->cpu == NULL) { + continue; + } + cpu_index = i; + + attr = (cpu_index << 16) | CORE_STATUS_OFF; kvm_ipi_access_reg(fd, attr, &core->status, write); - attr = (cpu << 16) | CORE_EN_OFF; + attr = (cpu_index << 16) | CORE_EN_OFF; kvm_ipi_access_reg(fd, attr, &core->en, write); - attr = (cpu << 16) | CORE_SET_OFF; + attr = (cpu_index << 16) | CORE_SET_OFF; kvm_ipi_access_reg(fd, attr, &core->set, write); - attr = (cpu << 16) | CORE_CLEAR_OFF; + attr = (cpu_index << 16) | CORE_CLEAR_OFF; kvm_ipi_access_reg(fd, attr, &core->clear, write); - attr = (cpu << 16) | CORE_BUF_20; + attr = (cpu_index << 16) | CORE_BUF_20; kvm_ipi_access_reg(fd, attr, &core->buf[0], write); - attr = (cpu << 16) | CORE_BUF_28; + attr = (cpu_index << 16) | CORE_BUF_28; kvm_ipi_access_reg(fd, attr, &core->buf[2], write); - attr = (cpu << 16) | CORE_BUF_30; + attr = (cpu_index << 16) | CORE_BUF_30; kvm_ipi_access_reg(fd, attr, &core->buf[4], write); - attr = (cpu << 16) | CORE_BUF_38; + attr = (cpu_index << 16) | CORE_BUF_38; kvm_ipi_access_reg(fd, attr, &core->buf[6], write); } }