From dd291171740871a84c183d886f70b8d2e6a68d09 Mon Sep 17 00:00:00 2001 From: Miao Hao Date: Tue, 14 Jan 2025 17:54:44 +0800 Subject: [PATCH 1/8] target/loongarch: Add page table walker support for debugger usage When dump memory content with gva address, software page table walker is necessary to get responding gpa address. Here page table walker is added for debugger usage. Signed-off-by: Miao Hao Signed-off-by: Bibo Mao Reviewed-by: Bibo Mao --- target/loongarch/cpu_helper.c | 94 +++++++++++++++++++++++++++++-- target/loongarch/internals.h | 4 +- target/loongarch/tcg/tlb_helper.c | 4 +- 3 files changed, 94 insertions(+), 8 deletions(-) diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c index 580362ac3e..930466ca48 100644 --- a/target/loongarch/cpu_helper.c +++ b/target/loongarch/cpu_helper.c @@ -141,9 +141,85 @@ bool loongarch_tlb_search(CPULoongArchState *env, target_ulong vaddr, return false; } +static int loongarch_page_table_walker(CPULoongArchState *env, hwaddr *physical, + int *prot, target_ulong address) +{ + CPUState *cs = env_cpu(env); + target_ulong index, phys; + uint64_t dir_base, dir_width; + uint64_t base; + int level; + + if ((address >> 63) & 0x1) { + base = env->CSR_PGDH; + } else { + base = env->CSR_PGDL; + } + base &= TARGET_PHYS_MASK; + + for (level = 4; level > 0; level--) { + get_dir_base_width(env, &dir_base, &dir_width, level); + + if (dir_width == 0) { + continue; + } + + /* get next level page directory */ + index = (address >> dir_base) & ((1 << dir_width) - 1); + phys = base | index << 3; + base = ldq_phys(cs->as, phys) & TARGET_PHYS_MASK; + if (FIELD_EX64(base, TLBENTRY, HUGE)) { + /* base is a huge pte */ + break; + } + } + + /* pte */ + if (FIELD_EX64(base, TLBENTRY, HUGE)) { + /* Huge Page. base is pte */ + base = FIELD_DP64(base, TLBENTRY, LEVEL, 0); + base = FIELD_DP64(base, TLBENTRY, HUGE, 0); + if (FIELD_EX64(base, TLBENTRY, HGLOBAL)) { + base = FIELD_DP64(base, TLBENTRY, HGLOBAL, 0); + base = FIELD_DP64(base, TLBENTRY, G, 1); + } + } else { + /* Normal Page. base points to pte */ + get_dir_base_width(env, &dir_base, &dir_width, 0); + index = (address >> dir_base) & ((1 << dir_width) - 1); + phys = base | index << 3; + base = ldq_phys(cs->as, phys); + } + + /* TODO: check plv and other bits? */ + + /* base is pte, in normal pte format */ + if (!FIELD_EX64(base, TLBENTRY, V)) { + return TLBRET_NOMATCH; + } + + if (!FIELD_EX64(base, TLBENTRY, D)) { + *prot = PAGE_READ; + } else { + *prot = PAGE_READ | PAGE_WRITE; + } + + /* get TARGET_PAGE_SIZE aligned physical address */ + base += (address & TARGET_PHYS_MASK) & ((1 << dir_base) - 1); + /* mask RPLV, NX, NR bits */ + base = FIELD_DP64(base, TLBENTRY_64, RPLV, 0); + base = FIELD_DP64(base, TLBENTRY_64, NX, 0); + base = FIELD_DP64(base, TLBENTRY_64, NR, 0); + /* mask other attribute bits */ + *physical = base & TARGET_PAGE_MASK; + + return 0; +} + static int loongarch_map_address(CPULoongArchState *env, hwaddr *physical, int *prot, target_ulong address, - MMUAccessType access_type, int mmu_idx) + MMUAccessType access_type, int mmu_idx, + int is_debug) { int index, match; @@ -151,6 +227,13 @@ static int loongarch_map_address(CPULoongArchState *env, hwaddr *physical, if (match) { return loongarch_map_tlb_entry(env, physical, prot, address, access_type, index, mmu_idx); + } else if (is_debug) { + /* + * For debugger memory access, we want to do the map when there is a + * legal mapping, even if the mapping is not yet in TLB. return 0 if + * there is a valid map, else none zero. + */ + return loongarch_page_table_walker(env, physical, prot, address); } return TLBRET_NOMATCH; @@ -158,7 +241,8 @@ static int loongarch_map_address(CPULoongArchState *env, hwaddr *physical, #else static int loongarch_map_address(CPULoongArchState *env, hwaddr *physical, int *prot, target_ulong address, - MMUAccessType access_type, int mmu_idx) + MMUAccessType access_type, int mmu_idx, + int is_debug) { return TLBRET_NOMATCH; } @@ -178,7 +262,7 @@ static hwaddr dmw_va2pa(CPULoongArchState *env, target_ulong va, int get_physical_address(CPULoongArchState *env, hwaddr *physical, int *prot, target_ulong address, - MMUAccessType access_type, int mmu_idx) + MMUAccessType access_type, int mmu_idx, int is_debug) { int user_mode = mmu_idx == MMU_USER_IDX; int kernel_mode = mmu_idx == MMU_KERNEL_IDX; @@ -222,7 +306,7 @@ int get_physical_address(CPULoongArchState *env, hwaddr *physical, /* Mapped address */ return loongarch_map_address(env, physical, prot, address, - access_type, mmu_idx); + access_type, mmu_idx, is_debug); } hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) @@ -232,7 +316,7 @@ hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) int prot; if (get_physical_address(env, &phys_addr, &prot, addr, MMU_DATA_LOAD, - cpu_mmu_index(cs, false)) != 0) { + cpu_mmu_index(cs, false), 1) != 0) { return -1; } return phys_addr; diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h index ad9cf4fc7a..7b254c5f49 100644 --- a/target/loongarch/internals.h +++ b/target/loongarch/internals.h @@ -56,7 +56,9 @@ bool loongarch_tlb_search(CPULoongArchState *env, target_ulong vaddr, int *index); int get_physical_address(CPULoongArchState *env, hwaddr *physical, int *prot, target_ulong address, - MMUAccessType access_type, int mmu_idx); + MMUAccessType access_type, int mmu_idx, int is_debug); +void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base, + uint64_t *dir_width, target_ulong level); hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); #ifdef CONFIG_TCG diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c index 8c61fe728c..a323606e5a 100644 --- a/target/loongarch/tcg/tlb_helper.c +++ b/target/loongarch/tcg/tlb_helper.c @@ -18,7 +18,7 @@ #include "exec/log.h" #include "cpu-csr.h" -static void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base, +void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base, uint64_t *dir_width, target_ulong level) { switch (level) { @@ -485,7 +485,7 @@ bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, /* Data access */ ret = get_physical_address(env, &physical, &prot, address, - access_type, mmu_idx); + access_type, mmu_idx, 0); if (ret == TLBRET_MATCH) { tlb_set_page(cs, address & TARGET_PAGE_MASK, From 59c54c1ceb1d84cb48d27a5b26d6f21cb76ee9e1 Mon Sep 17 00:00:00 2001 From: Bibo Mao Date: Tue, 7 Jan 2025 11:08:13 +0800 Subject: [PATCH 2/8] hw/intc/loongarch_ipi: Implement realize interface Add realize interface for loongarch ipi device. Signed-off-by: Bibo Mao Reviewed-by: Bibo Mao --- hw/intc/loongarch_ipi.c | 19 +++++++++++++++++++ include/hw/intc/loongarch_ipi.h | 1 + 2 files changed, 20 insertions(+) diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c index 2ae1a42c46..4e2f9acddf 100644 --- a/hw/intc/loongarch_ipi.c +++ b/hw/intc/loongarch_ipi.c @@ -7,6 +7,7 @@ #include "qemu/osdep.h" #include "hw/boards.h" +#include "qapi/error.h" #include "hw/intc/loongarch_ipi.h" #include "target/loongarch/cpu.h" @@ -49,10 +50,26 @@ static CPUState *loongarch_cpu_by_arch_id(int64_t arch_id) return NULL; } +static void loongarch_ipi_realize(DeviceState *dev, Error **errp) +{ + LoongarchIPIClass *lic = LOONGARCH_IPI_GET_CLASS(dev); + Error *local_err = NULL; + + lic->parent_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } +} + static void loongarch_ipi_class_init(ObjectClass *klass, void *data) { LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_CLASS(klass); + LoongarchIPIClass *lic = LOONGARCH_IPI_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + device_class_set_parent_realize(dc, loongarch_ipi_realize, + &lic->parent_realize); licc->get_iocsr_as = get_iocsr_as; licc->cpu_by_arch_id = loongarch_cpu_by_arch_id; } @@ -61,6 +78,8 @@ static const TypeInfo loongarch_ipi_types[] = { { .name = TYPE_LOONGARCH_IPI, .parent = TYPE_LOONGSON_IPI_COMMON, + .instance_size = sizeof(LoongarchIPIState), + .class_size = sizeof(LoongarchIPIClass), .class_init = loongarch_ipi_class_init, } }; diff --git a/include/hw/intc/loongarch_ipi.h b/include/hw/intc/loongarch_ipi.h index 276b3040a3..923bf21ecb 100644 --- a/include/hw/intc/loongarch_ipi.h +++ b/include/hw/intc/loongarch_ipi.h @@ -20,6 +20,7 @@ struct LoongarchIPIState { struct LoongarchIPIClass { LoongsonIPICommonClass parent_class; + DeviceRealize parent_realize; }; #endif From 5b82177addba2487c3c0e1b1974c0076a5a36342 Mon Sep 17 00:00:00 2001 From: Bibo Mao Date: Tue, 7 Jan 2025 11:08:14 +0800 Subject: [PATCH 3/8] hw/intc/loongson_ipi: Remove num_cpu from loongson_ipi_common With mips64 loongson ipi, num_cpu property is used. With loongarch ipi, num_cpu can be acquired from possible_cpu_arch_ids. Here remove num_cpu setting from loongson_ipi_common, and this piece of code is put into loongson and loongarch ipi separately. Signed-off-by: Bibo Mao Reviewed-by: Bibo Mao --- hw/intc/loongarch_ipi.c | 13 +++++++++++++ hw/intc/loongson_ipi.c | 14 +++++++++++++- hw/intc/loongson_ipi_common.c | 14 -------------- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c index 4e2f9acddf..e6126e4fbc 100644 --- a/hw/intc/loongarch_ipi.c +++ b/hw/intc/loongarch_ipi.c @@ -52,14 +52,27 @@ static CPUState *loongarch_cpu_by_arch_id(int64_t arch_id) static void loongarch_ipi_realize(DeviceState *dev, Error **errp) { + LoongsonIPICommonState *lics = LOONGSON_IPI_COMMON(dev); LoongarchIPIClass *lic = LOONGARCH_IPI_GET_CLASS(dev); Error *local_err = NULL; + int i; lic->parent_realize(dev, &local_err); if (local_err) { error_propagate(errp, local_err); return; } + + if (lics->num_cpu == 0) { + error_setg(errp, "num-cpu must be at least 1"); + return; + } + + lics->cpu = g_new0(IPICore, lics->num_cpu); + for (i = 0; i < lics->num_cpu; i++) { + lics->cpu[i].ipi = lics; + qdev_init_gpio_out(dev, &lics->cpu[i].irq, 1); + } } static void loongarch_ipi_class_init(ObjectClass *klass, void *data) diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c index 4e08f03510..1ed39b90ea 100644 --- a/hw/intc/loongson_ipi.c +++ b/hw/intc/loongson_ipi.c @@ -36,6 +36,7 @@ static void loongson_ipi_realize(DeviceState *dev, Error **errp) LoongsonIPIClass *lic = LOONGSON_IPI_GET_CLASS(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); Error *local_err = NULL; + int i; lic->parent_realize(dev, &local_err); if (local_err) { @@ -43,8 +44,19 @@ static void loongson_ipi_realize(DeviceState *dev, Error **errp) return; } + if (sc->num_cpu == 0) { + error_setg(errp, "num-cpu must be at least 1"); + return; + } + + sc->cpu = g_new0(IPICore, sc->num_cpu); + for (i = 0; i < sc->num_cpu; i++) { + sc->cpu[i].ipi = sc; + qdev_init_gpio_out(dev, &sc->cpu[i].irq, 1); + } + s->ipi_mmio_mem = g_new0(MemoryRegion, sc->num_cpu); - for (unsigned i = 0; i < sc->num_cpu; i++) { + for (i = 0; i < sc->num_cpu; i++) { g_autofree char *name = g_strdup_printf("loongson_ipi_cpu%d_mmio", i); memory_region_init_io(&s->ipi_mmio_mem[i], OBJECT(dev), diff --git a/hw/intc/loongson_ipi_common.c b/hw/intc/loongson_ipi_common.c index 9a081565f5..5d46679ea1 100644 --- a/hw/intc/loongson_ipi_common.c +++ b/hw/intc/loongson_ipi_common.c @@ -10,7 +10,6 @@ #include "hw/intc/loongson_ipi_common.h" #include "hw/irq.h" #include "hw/qdev-properties.h" -#include "qapi/error.h" #include "qemu/log.h" #include "migration/vmstate.h" #include "trace.h" @@ -253,12 +252,6 @@ static void loongson_ipi_common_realize(DeviceState *dev, Error **errp) { LoongsonIPICommonState *s = LOONGSON_IPI_COMMON(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - int i; - - if (s->num_cpu == 0) { - error_setg(errp, "num-cpu must be at least 1"); - return; - } memory_region_init_io(&s->ipi_iocsr_mem, OBJECT(dev), &loongson_ipi_iocsr_ops, @@ -273,13 +266,6 @@ static void loongson_ipi_common_realize(DeviceState *dev, Error **errp) &loongson_ipi64_ops, s, "loongson_ipi64_iocsr", 0x118); sysbus_init_mmio(sbd, &s->ipi64_iocsr_mem); - - s->cpu = g_new0(IPICore, s->num_cpu); - for (i = 0; i < s->num_cpu; i++) { - s->cpu[i].ipi = s; - - qdev_init_gpio_out(dev, &s->cpu[i].irq, 1); - } } static void loongson_ipi_common_unrealize(DeviceState *dev) From ce78dacf7e9b22dcc121dca17b1a3bcd93751680 Mon Sep 17 00:00:00 2001 From: Bibo Mao Date: Tue, 7 Jan 2025 11:08:15 +0800 Subject: [PATCH 4/8] hw/intc/loongson_ipi: Remove property num_cpu from loongson_ipi_common With mips64 loongson ipi, num_cpu property is used. With loongarch ipi, num_cpu can be acquired from possible_cpu_arch_ids. Here remove property num_cpu from loongson_ipi_common, and put it into loongson and loongarch ipi separately. Signed-off-by: Bibo Mao Reviewed-by: Bibo Mao --- hw/intc/loongarch_ipi.c | 6 ++++++ hw/intc/loongson_ipi.c | 6 ++++++ hw/intc/loongson_ipi_common.c | 6 ------ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c index e6126e4fbc..9c7636c4d6 100644 --- a/hw/intc/loongarch_ipi.c +++ b/hw/intc/loongarch_ipi.c @@ -9,6 +9,7 @@ #include "hw/boards.h" #include "qapi/error.h" #include "hw/intc/loongarch_ipi.h" +#include "hw/qdev-properties.h" #include "target/loongarch/cpu.h" static AddressSpace *get_iocsr_as(CPUState *cpu) @@ -75,6 +76,10 @@ static void loongarch_ipi_realize(DeviceState *dev, Error **errp) } } +static const Property loongarch_ipi_properties[] = { + DEFINE_PROP_UINT32("num-cpu", LoongsonIPICommonState, num_cpu, 1), +}; + static void loongarch_ipi_class_init(ObjectClass *klass, void *data) { LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_CLASS(klass); @@ -83,6 +88,7 @@ static void loongarch_ipi_class_init(ObjectClass *klass, void *data) device_class_set_parent_realize(dc, loongarch_ipi_realize, &lic->parent_realize); + device_class_set_props(dc, loongarch_ipi_properties); licc->get_iocsr_as = get_iocsr_as; licc->cpu_by_arch_id = loongarch_cpu_by_arch_id; } diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c index 1ed39b90ea..29e92d48fd 100644 --- a/hw/intc/loongson_ipi.c +++ b/hw/intc/loongson_ipi.c @@ -7,6 +7,7 @@ #include "qemu/osdep.h" #include "hw/intc/loongson_ipi.h" +#include "hw/qdev-properties.h" #include "qapi/error.h" #include "target/mips/cpu.h" @@ -75,6 +76,10 @@ static void loongson_ipi_unrealize(DeviceState *dev) k->parent_unrealize(dev); } +static const Property loongson_ipi_properties[] = { + DEFINE_PROP_UINT32("num-cpu", LoongsonIPICommonState, num_cpu, 1), +}; + static void loongson_ipi_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -85,6 +90,7 @@ static void loongson_ipi_class_init(ObjectClass *klass, void *data) &lic->parent_realize); device_class_set_parent_unrealize(dc, loongson_ipi_unrealize, &lic->parent_unrealize); + device_class_set_props(dc, loongson_ipi_properties); licc->get_iocsr_as = get_iocsr_as; licc->cpu_by_arch_id = cpu_by_arch_id; } diff --git a/hw/intc/loongson_ipi_common.c b/hw/intc/loongson_ipi_common.c index 5d46679ea1..363cddc54c 100644 --- a/hw/intc/loongson_ipi_common.c +++ b/hw/intc/loongson_ipi_common.c @@ -9,7 +9,6 @@ #include "hw/sysbus.h" #include "hw/intc/loongson_ipi_common.h" #include "hw/irq.h" -#include "hw/qdev-properties.h" #include "qemu/log.h" #include "migration/vmstate.h" #include "trace.h" @@ -301,10 +300,6 @@ static const VMStateDescription vmstate_loongson_ipi_common = { } }; -static const Property ipi_common_properties[] = { - DEFINE_PROP_UINT32("num-cpu", LoongsonIPICommonState, num_cpu, 1), -}; - static void loongson_ipi_common_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -314,7 +309,6 @@ static void loongson_ipi_common_class_init(ObjectClass *klass, void *data) &licc->parent_realize); device_class_set_parent_unrealize(dc, loongson_ipi_common_unrealize, &licc->parent_unrealize); - device_class_set_props(dc, ipi_common_properties); dc->vmsd = &vmstate_loongson_ipi_common; } From 14dc02b56a3d4434401ad92415cbec3e30ff3fa5 Mon Sep 17 00:00:00 2001 From: Bibo Mao Date: Tue, 7 Jan 2025 11:08:16 +0800 Subject: [PATCH 5/8] hw/intc/loongarch_ipi: Get cpu number from possible_cpu_arch_ids Supported CPU number can be acquired from function possible_cpu_arch_ids(), cpu-num property is not necessary and can be removed. Signed-off-by: Bibo Mao Reviewed-by: Bibo Mao --- hw/intc/loongarch_ipi.c | 13 ++++++++----- include/hw/intc/loongson_ipi_common.h | 2 ++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c index 9c7636c4d6..49b4595d90 100644 --- a/hw/intc/loongarch_ipi.c +++ b/hw/intc/loongarch_ipi.c @@ -55,6 +55,9 @@ static void loongarch_ipi_realize(DeviceState *dev, Error **errp) { LoongsonIPICommonState *lics = LOONGSON_IPI_COMMON(dev); LoongarchIPIClass *lic = LOONGARCH_IPI_GET_CLASS(dev); + MachineState *machine = MACHINE(qdev_get_machine()); + MachineClass *mc = MACHINE_GET_CLASS(machine); + const CPUArchIdList *id_list; Error *local_err = NULL; int i; @@ -64,13 +67,13 @@ static void loongarch_ipi_realize(DeviceState *dev, Error **errp) return; } - if (lics->num_cpu == 0) { - error_setg(errp, "num-cpu must be at least 1"); - return; - } - + assert(mc->possible_cpu_arch_ids); + id_list = mc->possible_cpu_arch_ids(machine); + lics->num_cpu = id_list->len; lics->cpu = g_new0(IPICore, lics->num_cpu); for (i = 0; i < lics->num_cpu; i++) { + lics->cpu[i].arch_id = id_list->cpus[i].arch_id; + lics->cpu[i].cpu = CPU(id_list->cpus[i].cpu); lics->cpu[i].ipi = lics; qdev_init_gpio_out(dev, &lics->cpu[i].irq, 1); } diff --git a/include/hw/intc/loongson_ipi_common.h b/include/hw/intc/loongson_ipi_common.h index df9d9c5168..4192f3d548 100644 --- a/include/hw/intc/loongson_ipi_common.h +++ b/include/hw/intc/loongson_ipi_common.h @@ -27,6 +27,8 @@ typedef struct IPICore { /* 64bit buf divide into 2 32-bit buf */ uint32_t buf[IPI_MBX_NUM * 2]; qemu_irq irq; + uint64_t arch_id; + CPUState *cpu; } IPICore; struct LoongsonIPICommonState { From 1b3aa347044966a69e16a821eb44fbc16d0d58c9 Mon Sep 17 00:00:00 2001 From: Bibo Mao Date: Tue, 7 Jan 2025 11:08:17 +0800 Subject: [PATCH 6/8] hw/intc/loongarch_ipi: Remove property num-cpu Since cpu number can be acquired from possible_cpu_arch_ids(), num-cpu property is not necessary. Here remove num-cpu property for object TYPE_LOONGARCH_IPI object. Signed-off-by: Bibo Mao Reviewed-by: Bibo Mao --- hw/intc/loongarch_ipi.c | 5 ----- hw/loongarch/virt.c | 1 - 2 files changed, 6 deletions(-) diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c index 49b4595d90..41d9625dcb 100644 --- a/hw/intc/loongarch_ipi.c +++ b/hw/intc/loongarch_ipi.c @@ -79,10 +79,6 @@ static void loongarch_ipi_realize(DeviceState *dev, Error **errp) } } -static const Property loongarch_ipi_properties[] = { - DEFINE_PROP_UINT32("num-cpu", LoongsonIPICommonState, num_cpu, 1), -}; - static void loongarch_ipi_class_init(ObjectClass *klass, void *data) { LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_CLASS(klass); @@ -91,7 +87,6 @@ static void loongarch_ipi_class_init(ObjectClass *klass, void *data) device_class_set_parent_realize(dc, loongarch_ipi_realize, &lic->parent_realize); - device_class_set_props(dc, loongarch_ipi_properties); licc->get_iocsr_as = get_iocsr_as; licc->cpu_by_arch_id = loongarch_cpu_by_arch_id; } diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index db37ed6a71..63fa0f4e32 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -899,7 +899,6 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms) /* Create IPI device */ ipi = qdev_new(TYPE_LOONGARCH_IPI); - qdev_prop_set_uint32(ipi, "num-cpu", ms->smp.cpus); sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal); /* IPI iocsr memory region */ From 999b112d90be8404547eec0793f8d7c0b5d2a547 Mon Sep 17 00:00:00 2001 From: Bibo Mao Date: Tue, 7 Jan 2025 11:08:18 +0800 Subject: [PATCH 7/8] hw/intc/loongson_ipi: Add more input parameter for cpu_by_arch_id Add logic cpu index input parameter for function cpu_by_arch_id, CPUState::cpu_index is logic cpu slot index for possible_cpus. At the same time it is logic index with LoongsonIPICommonState::IPICore, here hide access for CPUState::cpu_index directly, it comes from function cpu_by_arch_id(). Signed-off-by: Bibo Mao Reviewed-by: Bibo Mao --- hw/intc/loongarch_ipi.c | 19 +++++++++++++++---- hw/intc/loongson_ipi.c | 23 ++++++++++++++++++++++- hw/intc/loongson_ipi_common.c | 21 ++++++++++++--------- include/hw/intc/loongson_ipi_common.h | 3 ++- 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c index 41d9625dcb..515549e8a5 100644 --- a/hw/intc/loongarch_ipi.c +++ b/hw/intc/loongarch_ipi.c @@ -38,17 +38,28 @@ static CPUArchId *find_cpu_by_archid(MachineState *ms, uint32_t id) return found_cpu; } -static CPUState *loongarch_cpu_by_arch_id(int64_t arch_id) +static int loongarch_cpu_by_arch_id(LoongsonIPICommonState *lics, + int64_t arch_id, int *index, CPUState **pcs) { MachineState *machine = MACHINE(qdev_get_machine()); CPUArchId *archid; + CPUState *cs; archid = find_cpu_by_archid(machine, arch_id); - if (archid) { - return CPU(archid->cpu); + if (archid && archid->cpu) { + cs = archid->cpu; + if (index) { + *index = cs->cpu_index; + } + + if (pcs) { + *pcs = cs; + } + + return MEMTX_OK; } - return NULL; + return MEMTX_ERROR; } static void loongarch_ipi_realize(DeviceState *dev, Error **errp) diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c index 29e92d48fd..d2268a27f8 100644 --- a/hw/intc/loongson_ipi.c +++ b/hw/intc/loongson_ipi.c @@ -20,6 +20,27 @@ static AddressSpace *get_iocsr_as(CPUState *cpu) return NULL; } +static int loongson_cpu_by_arch_id(LoongsonIPICommonState *lics, + int64_t arch_id, int *index, CPUState **pcs) +{ + CPUState *cs; + + cs = cpu_by_arch_id(arch_id); + if (cs == NULL) { + return MEMTX_ERROR; + } + + if (index) { + *index = cs->cpu_index; + } + + if (pcs) { + *pcs = cs; + } + + return MEMTX_OK; +} + static const MemoryRegionOps loongson_ipi_core_ops = { .read_with_attrs = loongson_ipi_core_readl, .write_with_attrs = loongson_ipi_core_writel, @@ -92,7 +113,7 @@ static void loongson_ipi_class_init(ObjectClass *klass, void *data) &lic->parent_unrealize); device_class_set_props(dc, loongson_ipi_properties); licc->get_iocsr_as = get_iocsr_as; - licc->cpu_by_arch_id = cpu_by_arch_id; + licc->cpu_by_arch_id = loongson_cpu_by_arch_id; } static const TypeInfo loongson_ipi_types[] = { diff --git a/hw/intc/loongson_ipi_common.c b/hw/intc/loongson_ipi_common.c index 363cddc54c..f5ab5024c0 100644 --- a/hw/intc/loongson_ipi_common.c +++ b/hw/intc/loongson_ipi_common.c @@ -103,16 +103,17 @@ static MemTxResult mail_send(LoongsonIPICommonState *ipi, uint32_t cpuid; hwaddr addr; CPUState *cs; + int cpu, ret; cpuid = extract32(val, 16, 10); - cs = licc->cpu_by_arch_id(cpuid); - if (cs == NULL) { + ret = licc->cpu_by_arch_id(ipi, cpuid, &cpu, &cs); + if (ret != MEMTX_OK) { return MEMTX_DECODE_ERROR; } /* override requester_id */ addr = SMP_IPI_MAILBOX + CORE_BUF_20 + (val & 0x1c); - attrs.requester_id = cs->cpu_index; + attrs.requester_id = cpu; return send_ipi_data(ipi, cs, val, addr, attrs); } @@ -123,16 +124,17 @@ static MemTxResult any_send(LoongsonIPICommonState *ipi, uint32_t cpuid; hwaddr addr; CPUState *cs; + int cpu, ret; cpuid = extract32(val, 16, 10); - cs = licc->cpu_by_arch_id(cpuid); - if (cs == NULL) { + ret = licc->cpu_by_arch_id(ipi, cpuid, &cpu, &cs); + if (ret != MEMTX_OK) { return MEMTX_DECODE_ERROR; } /* override requester_id */ addr = val & 0xffff; - attrs.requester_id = cs->cpu_index; + attrs.requester_id = cpu; return send_ipi_data(ipi, cs, val, addr, attrs); } @@ -146,6 +148,7 @@ MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr, uint64_t val, uint32_t cpuid; uint8_t vector; CPUState *cs; + int cpu, ret; addr &= 0xff; trace_loongson_ipi_write(size, (uint64_t)addr, val); @@ -176,11 +179,11 @@ MemTxResult loongson_ipi_core_writel(void *opaque, hwaddr addr, uint64_t val, cpuid = extract32(val, 16, 10); /* IPI status vector */ vector = extract8(val, 0, 5); - cs = licc->cpu_by_arch_id(cpuid); - if (cs == NULL || cs->cpu_index >= ipi->num_cpu) { + ret = licc->cpu_by_arch_id(ipi, cpuid, &cpu, &cs); + if (ret != MEMTX_OK || cpu >= ipi->num_cpu) { return MEMTX_DECODE_ERROR; } - loongson_ipi_core_writel(&ipi->cpu[cs->cpu_index], CORE_SET_OFF, + loongson_ipi_core_writel(&ipi->cpu[cpu], CORE_SET_OFF, BIT(vector), 4, attrs); break; default: diff --git a/include/hw/intc/loongson_ipi_common.h b/include/hw/intc/loongson_ipi_common.h index 4192f3d548..b587f9c571 100644 --- a/include/hw/intc/loongson_ipi_common.h +++ b/include/hw/intc/loongson_ipi_common.h @@ -46,7 +46,8 @@ struct LoongsonIPICommonClass { DeviceRealize parent_realize; DeviceUnrealize parent_unrealize; AddressSpace *(*get_iocsr_as)(CPUState *cpu); - CPUState *(*cpu_by_arch_id)(int64_t id); + int (*cpu_by_arch_id)(LoongsonIPICommonState *lics, int64_t id, + int *index, CPUState **pcs); }; MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr, uint64_t *data, From bb81f237401b5f89f6bba21d9d4f50e0073372a6 Mon Sep 17 00:00:00 2001 From: Bibo Mao Date: Tue, 7 Jan 2025 11:08:19 +0800 Subject: [PATCH 8/8] hw/intc/loongarch_ipi: Use alternative implemation for cpu_by_arch_id There is arch_id and CPUState pointer in IPICore object. With function cpu_by_arch_id() it can be implemented by parsing IPICore array inside, rather than possible_cpus array. Signed-off-by: Bibo Mao Reviewed-by: Bibo Mao --- hw/intc/loongarch_ipi.c | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c index 515549e8a5..5376f1e084 100644 --- a/hw/intc/loongarch_ipi.c +++ b/hw/intc/loongarch_ipi.c @@ -17,43 +17,29 @@ static AddressSpace *get_iocsr_as(CPUState *cpu) return LOONGARCH_CPU(cpu)->env.address_space_iocsr; } -static int archid_cmp(const void *a, const void *b) +static int loongarch_ipi_cmp(const void *a, const void *b) { - CPUArchId *archid_a = (CPUArchId *)a; - CPUArchId *archid_b = (CPUArchId *)b; + IPICore *ipi_a = (IPICore *)a; + IPICore *ipi_b = (IPICore *)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(&apic_id, ms->possible_cpus->cpus, - ms->possible_cpus->len, - sizeof(*ms->possible_cpus->cpus), - archid_cmp); - - return found_cpu; + return ipi_a->arch_id - ipi_b->arch_id; } static int loongarch_cpu_by_arch_id(LoongsonIPICommonState *lics, int64_t arch_id, int *index, CPUState **pcs) { - MachineState *machine = MACHINE(qdev_get_machine()); - CPUArchId *archid; - CPUState *cs; + IPICore ipi, *found; - archid = find_cpu_by_archid(machine, arch_id); - if (archid && archid->cpu) { - cs = archid->cpu; + ipi.arch_id = arch_id; + found = bsearch(&ipi, lics->cpu, lics->num_cpu, sizeof(IPICore), + loongarch_ipi_cmp); + if (found && found->cpu) { if (index) { - *index = cs->cpu_index; + *index = found - lics->cpu; } if (pcs) { - *pcs = cs; + *pcs = found->cpu; } return MEMTX_OK;