diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2025-01-09 08:34:01 -0500 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2025-01-09 08:34:01 -0500 |
commit | c10ed2fac295d77370c4c81091af5deb3859e35d (patch) | |
tree | 1852464e74e5d245124598f4237dd88b97dc768f /hw | |
parent | 3f8bcbba3b320c610689576fc47595f1076198dd (diff) | |
parent | c3afa714bcea4c8b014fec99881bd0bdbe8262b8 (diff) | |
download | qemu-c10ed2fac295d77370c4c81091af5deb3859e35d.zip qemu-c10ed2fac295d77370c4c81091af5deb3859e35d.tar.gz qemu-c10ed2fac295d77370c4c81091af5deb3859e35d.tar.bz2 |
Merge tag 'pull-loongarch-20250109' of https://gitlab.com/bibo-mao/qemu into staging
loongarch queue
# -----BEGIN PGP SIGNATURE-----
#
# iHUEABYKAB0WIQQNhkKjomWfgLCz0aQfewwSUazn0QUCZ39pJgAKCRAfewwSUazn
# 0YpMAQCNV9KJJ8f8EaXAw5a87mnmlcP0vRi5gZiyv1ZV9gRqPgEAhzCn/rnzpzd+
# H3B1fRlD1xmaQ8IqRugQ4vfDBd9CyQY=
# =OG4d
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 09 Jan 2025 01:13:58 EST
# gpg: using EDDSA key 0D8642A3A2659F80B0B3D1A41F7B0C1251ACE7D1
# gpg: Good signature from "bibo mao <maobibo@loongson.cn>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 7044 3A00 19C0 E97A 31C7 13C4 8E86 8FB7 A176 9D4C
# Subkey fingerprint: 0D86 42A3 A265 9F80 B0B3 D1A4 1F7B 0C12 51AC E7D1
* tag 'pull-loongarch-20250109' of https://gitlab.com/bibo-mao/qemu:
hw/intc/loongarch_extioi: Add irq routing support from physical id
hw/intc/loongarch_extioi: Remove num-cpu property
hw/intc/loongarch_extioi: Get cpu number from possible_cpu_arch_ids
target/loongarch: Only support 64bit pte width
hw/loongarch/boot: Support Linux raw boot image
hw/core/loader: Use ssize_t for efi zboot unpacker
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/arm/boot.c | 2 | ||||
-rw-r--r-- | hw/core/loader.c | 4 | ||||
-rw-r--r-- | hw/intc/loongarch_extioi.c | 36 | ||||
-rw-r--r-- | hw/intc/loongarch_extioi_common.c | 18 | ||||
-rw-r--r-- | hw/loongarch/boot.c | 69 | ||||
-rw-r--r-- | hw/loongarch/virt.c | 1 |
6 files changed, 113 insertions, 17 deletions
diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 68fe865..b44bea8 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -857,7 +857,7 @@ static uint64_t load_aarch64_image(const char *filename, hwaddr mem_base, hwaddr kernel_load_offset = KERNEL64_LOAD_ADDR; uint64_t kernel_size = 0; uint8_t *buffer; - int size; + ssize_t size; /* On aarch64, it's the bootloader's job to uncompress the kernel. */ size = load_image_gzipped_buffer(filename, LOAD_IMAGE_MAX_GUNZIP_BYTES, diff --git a/hw/core/loader.c b/hw/core/loader.c index c0407e2..4dfdb02 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -886,11 +886,11 @@ struct linux_efi_zboot_header { * * If the image is not a Linux EFI zboot image, do nothing and return success. */ -ssize_t unpack_efi_zboot_image(uint8_t **buffer, int *size) +ssize_t unpack_efi_zboot_image(uint8_t **buffer, ssize_t *size) { const struct linux_efi_zboot_header *header; uint8_t *data = NULL; - int ploff, plsize; + ssize_t ploff, plsize; ssize_t bytes; /* ignore if this is too small to be a EFI zboot image */ diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c index 4a1a7c3..f3055ec 100644 --- a/hw/intc/loongarch_extioi.c +++ b/hw/intc/loongarch_extioi.c @@ -15,6 +15,23 @@ #include "hw/intc/loongarch_extioi.h" #include "trace.h" +static int extioi_get_index_from_archid(LoongArchExtIOICommonState *s, + uint64_t arch_id) +{ + int i; + + for (i = 0; i < s->num_cpu; i++) { + if (s->cpu[i].arch_id == arch_id) { + break; + } + } + + if ((i < s->num_cpu) && s->cpu[i].cpu) { + return i; + } + + return -1; +} static void extioi_update_irq(LoongArchExtIOICommonState *s, int irq, int level) { @@ -125,7 +142,7 @@ static inline void extioi_enable_irq(LoongArchExtIOICommonState *s, int index,\ static inline void extioi_update_sw_coremap(LoongArchExtIOICommonState *s, int irq, uint64_t val, bool notify) { - int i, cpu; + int i, cpu, cpuid; /* * loongarch only support little endian, @@ -134,12 +151,17 @@ static inline void extioi_update_sw_coremap(LoongArchExtIOICommonState *s, val = cpu_to_le64(val); for (i = 0; i < 4; i++) { - cpu = val & 0xff; + cpuid = val & 0xff; val = val >> 8; if (!(s->status & BIT(EXTIOI_ENABLE_CPU_ENCODE))) { - cpu = ctz32(cpu); - cpu = (cpu >= 4) ? 0 : cpu; + cpuid = ctz32(cpuid); + cpuid = (cpuid >= 4) ? 0 : cpuid; + } + + cpu = extioi_get_index_from_archid(s, cpuid); + if (cpu < 0) { + continue; } if (s->sw_coremap[irq + i] == cpu) { @@ -347,12 +369,6 @@ static void loongarch_extioi_realize(DeviceState *dev, Error **errp) s->status |= BIT(EXTIOI_ENABLE); } - s->cpu = g_new0(ExtIOICore, s->num_cpu); - if (s->cpu == NULL) { - error_setg(errp, "Memory allocation for ExtIOICore faile"); - return; - } - for (i = 0; i < s->num_cpu; i++) { for (pin = 0; pin < LS3A_INTC_IP; pin++) { qdev_init_gpio_out(dev, &s->cpu[i].parent_irq[pin], 1); diff --git a/hw/intc/loongarch_extioi_common.c b/hw/intc/loongarch_extioi_common.c index e4c1cc3..fd56253 100644 --- a/hw/intc/loongarch_extioi_common.c +++ b/hw/intc/loongarch_extioi_common.c @@ -13,11 +13,24 @@ static void loongarch_extioi_common_realize(DeviceState *dev, Error **errp) { LoongArchExtIOICommonState *s = (LoongArchExtIOICommonState *)dev; + MachineState *machine = MACHINE(qdev_get_machine()); + MachineClass *mc = MACHINE_GET_CLASS(machine); + const CPUArchIdList *id_list; + int i; - if (s->num_cpu == 0) { - error_setg(errp, "num-cpu must be at least 1"); + assert(mc->possible_cpu_arch_ids); + id_list = mc->possible_cpu_arch_ids(machine); + s->num_cpu = id_list->len; + s->cpu = g_new0(ExtIOICore, s->num_cpu); + if (s->cpu == NULL) { + error_setg(errp, "Memory allocation for ExtIOICore faile"); return; } + + for (i = 0; i < s->num_cpu; i++) { + s->cpu[i].arch_id = id_list->cpus[i].arch_id; + s->cpu[i].cpu = CPU(id_list->cpus[i].cpu); + } } static int loongarch_extioi_common_pre_save(void *opaque) @@ -82,7 +95,6 @@ static const VMStateDescription vmstate_loongarch_extioi = { }; static const Property extioi_properties[] = { - DEFINE_PROP_UINT32("num-cpu", LoongArchExtIOICommonState, num_cpu, 1), DEFINE_PROP_BIT("has-virtualization-extension", LoongArchExtIOICommonState, features, EXTIOI_HAS_VIRT_EXTENSION, 0), }; diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c index 48154cd..241c0ee 100644 --- a/hw/loongarch/boot.c +++ b/hw/loongarch/boot.c @@ -15,6 +15,26 @@ #include "system/reset.h" #include "system/qtest.h" +/* + * Linux Image Format + * https://docs.kernel.org/arch/loongarch/booting.html + */ +#define LINUX_PE_MAGIC 0x818223cd +#define MZ_MAGIC 0x5a4d /* "MZ" */ + +struct loongarch_linux_hdr { + uint32_t mz_magic; + uint32_t res0; + uint64_t kernel_entry; + uint64_t kernel_size; + uint64_t load_offset; + uint64_t res1; + uint64_t res2; + uint64_t res3; + uint32_t linux_pe_magic; + uint32_t pe_header_offset; +} QEMU_PACKED; + struct memmap_entry *memmap_table; unsigned memmap_entries; @@ -171,6 +191,50 @@ static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr) return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS); } +static int64_t load_loongarch_linux_image(const char *filename, + uint64_t *kernel_entry, + uint64_t *kernel_low, + uint64_t *kernel_high) +{ + gsize len; + ssize_t size; + uint8_t *buffer; + struct loongarch_linux_hdr *hdr; + + /* Load as raw file otherwise */ + if (!g_file_get_contents(filename, (char **)&buffer, &len, NULL)) { + return -1; + } + size = len; + + /* Unpack the image if it is a EFI zboot image */ + if (unpack_efi_zboot_image(&buffer, &size) < 0) { + g_free(buffer); + return -1; + } + + hdr = (struct loongarch_linux_hdr *)buffer; + + if (extract32(le32_to_cpu(hdr->mz_magic), 0, 16) != MZ_MAGIC || + le32_to_cpu(hdr->linux_pe_magic) != LINUX_PE_MAGIC) { + g_free(buffer); + return -1; + } + + /* Early kernel versions may have those fields in virtual address */ + *kernel_entry = extract64(le64_to_cpu(hdr->kernel_entry), + 0, TARGET_PHYS_ADDR_SPACE_BITS); + *kernel_low = extract64(le64_to_cpu(hdr->load_offset), + 0, TARGET_PHYS_ADDR_SPACE_BITS); + *kernel_high = *kernel_low + size; + + rom_add_blob_fixed(filename, buffer, size, *kernel_low); + + g_free(buffer); + + return size; +} + static int64_t load_kernel_info(struct loongarch_boot_info *info) { uint64_t kernel_entry, kernel_low, kernel_high; @@ -181,6 +245,11 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info) &kernel_entry, &kernel_low, &kernel_high, NULL, 0, EM_LOONGARCH, 1, 0); + if (kernel_size < 0) { + kernel_size = load_loongarch_linux_image(info->kernel_filename, + &kernel_entry, &kernel_low, + &kernel_high); + } if (kernel_size < 0) { error_report("could not load kernel '%s': %s", diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 60bd4dc..df56d75 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -921,7 +921,6 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms) /* Create EXTIOI device */ extioi = qdev_new(TYPE_LOONGARCH_EXTIOI); - qdev_prop_set_uint32(extioi, "num-cpu", ms->smp.cpus); if (virt_is_veiointc_enabled(lvms)) { qdev_prop_set_bit(extioi, "has-virtualization-extension", true); } |