aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2025-01-09 08:34:01 -0500
committerStefan Hajnoczi <stefanha@redhat.com>2025-01-09 08:34:01 -0500
commitc10ed2fac295d77370c4c81091af5deb3859e35d (patch)
tree1852464e74e5d245124598f4237dd88b97dc768f /hw
parent3f8bcbba3b320c610689576fc47595f1076198dd (diff)
parentc3afa714bcea4c8b014fec99881bd0bdbe8262b8 (diff)
downloadqemu-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.c2
-rw-r--r--hw/core/loader.c4
-rw-r--r--hw/intc/loongarch_extioi.c36
-rw-r--r--hw/intc/loongarch_extioi_common.c18
-rw-r--r--hw/loongarch/boot.c69
-rw-r--r--hw/loongarch/virt.c1
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);
}