diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-08-20 09:55:42 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-08-20 09:55:42 +0100 |
commit | 2656eb7c599e306b95bad82b1372fc49ba3088f6 (patch) | |
tree | 571f2ba5ef8acf61eec2fdec5b9b7545b6ece0df /hw | |
parent | 302fa283789a2f9b1199c327047cfad2258a23a2 (diff) | |
parent | 14a906f755f77b325666d67e071c572478d06067 (diff) | |
download | qemu-2656eb7c599e306b95bad82b1372fc49ba3088f6.zip qemu-2656eb7c599e306b95bad82b1372fc49ba3088f6.tar.gz qemu-2656eb7c599e306b95bad82b1372fc49ba3088f6.tar.bz2 |
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20140819' into staging
target-arm:
* fix preferred return address for A64 BRK insn
* implement AArch64 single-stepping
* support loading gzip compressed AArch64 kernels
* use correct PSCI function IDs in the DT when KVM uses PSCI 0.2
* minor cleanups
# gpg: Signature made Tue 19 Aug 2014 19:04:09 BST using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
* remotes/pmaydell/tags/pull-target-arm-20140819:
arm: stellaris: Remove misleading address_space_mem var
arm: armv7m: Rename address_space_mem -> system_memory
aarch64: Allow -kernel option to take a gzip-compressed kernel.
loader: Add load_image_gzipped function.
arm: cortex-a9: Fix cache-line size and associativity
arm/virt: Use PSCI v0.2 function IDs in the DT when KVM uses PSCI v0.2
target-arm: Rename QEMU PSCI v0.1 definitions
target-arm: Implement MDSCR_EL1 as having state
target-arm: Implement ARMv8 single-stepping for AArch32 code
target-arm: Implement ARMv8 single-step handling for A64 code
target-arm: A64: Avoid duplicate exit_tb(0) in non-linked goto_tb
target-arm: Set PSTATE.SS correctly on exception return from AArch64
target-arm: Correctly handle PSTATE.SS when taking exception to AArch32
target-arm: Don't allow AArch32 to access RES0 CPSR bits
target-arm: Adjust debug ID registers per-CPU
target-arm: Provide both 32 and 64 bit versions of debug registers
target-arm: Allow STATE_BOTH reginfo descriptions for more than cp14
target-arm: Collect up the debug cp register definitions
target-arm: Fix return address for A64 BRK instructions
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/arm/armv7m.c | 8 | ||||
-rw-r--r-- | hw/arm/boot.c | 7 | ||||
-rw-r--r-- | hw/arm/stellaris.c | 3 | ||||
-rw-r--r-- | hw/arm/virt.c | 31 | ||||
-rw-r--r-- | hw/core/loader.c | 48 |
5 files changed, 86 insertions, 11 deletions
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index 397e8df..aedef13 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -166,7 +166,7 @@ static void armv7m_reset(void *opaque) flash_size and sram_size are in kb. Returns the NVIC array. */ -qemu_irq *armv7m_init(MemoryRegion *address_space_mem, +qemu_irq *armv7m_init(MemoryRegion *system_memory, int flash_size, int sram_size, const char *kernel_filename, const char *cpu_model) { @@ -213,10 +213,10 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem, memory_region_init_ram(flash, NULL, "armv7m.flash", flash_size); vmstate_register_ram_global(flash); memory_region_set_readonly(flash, true); - memory_region_add_subregion(address_space_mem, 0, flash); + memory_region_add_subregion(system_memory, 0, flash); memory_region_init_ram(sram, NULL, "armv7m.sram", sram_size); vmstate_register_ram_global(sram); - memory_region_add_subregion(address_space_mem, 0x20000000, sram); + memory_region_add_subregion(system_memory, 0x20000000, sram); armv7m_bitband_init(); nvic = qdev_create(NULL, "armv7m_nvic"); @@ -257,7 +257,7 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem, when returning from an exception. */ memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000); vmstate_register_ram_global(hack); - memory_region_add_subregion(address_space_mem, 0xfffff000, hack); + memory_region_add_subregion(system_memory, 0xfffff000, hack); qemu_register_reset(armv7m_reset, cpu); return pic; diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 1241761..e32f2f4 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -514,6 +514,13 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) kernel_size = load_uimage(info->kernel_filename, &entry, NULL, &is_linux); } + /* On aarch64, it's the bootloader's job to uncompress the kernel. */ + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && kernel_size < 0) { + entry = info->loader_start + kernel_load_offset; + kernel_size = load_image_gzipped(info->kernel_filename, entry, + info->ram_size - kernel_load_offset); + is_linux = 1; + } if (kernel_size < 0) { entry = info->loader_start + kernel_load_offset; kernel_size = load_image_targphys(info->kernel_filename, entry, diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index 80028e8..64bd4b4 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -1208,7 +1208,6 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, 0x40024000, 0x40025000, 0x40026000}; static const int gpio_irq[7] = {0, 1, 2, 3, 4, 30, 31}; - MemoryRegion *address_space_mem = get_system_memory(); qemu_irq *pic; DeviceState *gpio_dev[7]; qemu_irq gpio_in[7][8]; @@ -1223,7 +1222,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, flash_size = ((board->dc0 & 0xffff) + 1) << 1; sram_size = (board->dc0 >> 18) + 1; - pic = armv7m_init(address_space_mem, + pic = armv7m_init(get_system_memory(), flash_size, sram_size, kernel_filename, cpu_model); if (board->dc1 & (1 << 16)) { diff --git a/hw/arm/virt.c b/hw/arm/virt.c index ba94298..bd206a0 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -194,20 +194,41 @@ static void fdt_add_psci_node(const VirtBoardInfo *vbi) /* No PSCI for TCG yet */ if (kvm_enabled()) { + uint32_t cpu_suspend_fn; + uint32_t cpu_off_fn; + uint32_t cpu_on_fn; + uint32_t migrate_fn; + qemu_fdt_add_subnode(fdt, "/psci"); if (armcpu->psci_version == 2) { const char comp[] = "arm,psci-0.2\0arm,psci"; qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp)); + + cpu_off_fn = QEMU_PSCI_0_2_FN_CPU_OFF; + if (arm_feature(&armcpu->env, ARM_FEATURE_AARCH64)) { + cpu_suspend_fn = QEMU_PSCI_0_2_FN64_CPU_SUSPEND; + cpu_on_fn = QEMU_PSCI_0_2_FN64_CPU_ON; + migrate_fn = QEMU_PSCI_0_2_FN64_MIGRATE; + } else { + cpu_suspend_fn = QEMU_PSCI_0_2_FN_CPU_SUSPEND; + cpu_on_fn = QEMU_PSCI_0_2_FN_CPU_ON; + migrate_fn = QEMU_PSCI_0_2_FN_MIGRATE; + } } else { qemu_fdt_setprop_string(fdt, "/psci", "compatible", "arm,psci"); + + cpu_suspend_fn = QEMU_PSCI_0_1_FN_CPU_SUSPEND; + cpu_off_fn = QEMU_PSCI_0_1_FN_CPU_OFF; + cpu_on_fn = QEMU_PSCI_0_1_FN_CPU_ON; + migrate_fn = QEMU_PSCI_0_1_FN_MIGRATE; } qemu_fdt_setprop_string(fdt, "/psci", "method", "hvc"); - qemu_fdt_setprop_cell(fdt, "/psci", "cpu_suspend", - PSCI_FN_CPU_SUSPEND); - qemu_fdt_setprop_cell(fdt, "/psci", "cpu_off", PSCI_FN_CPU_OFF); - qemu_fdt_setprop_cell(fdt, "/psci", "cpu_on", PSCI_FN_CPU_ON); - qemu_fdt_setprop_cell(fdt, "/psci", "migrate", PSCI_FN_MIGRATE); + + qemu_fdt_setprop_cell(fdt, "/psci", "cpu_suspend", cpu_suspend_fn); + qemu_fdt_setprop_cell(fdt, "/psci", "cpu_off", cpu_off_fn); + qemu_fdt_setprop_cell(fdt, "/psci", "cpu_on", cpu_on_fn); + qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn); } } diff --git a/hw/core/loader.c b/hw/core/loader.c index 1a53f0f..193f0f8 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -577,6 +577,54 @@ int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz) return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK); } +/* This simply prevents g_malloc in the function below from allocating + * a huge amount of memory, by placing a limit on the maximum + * uncompressed image size that load_image_gzipped will read. + */ +#define LOAD_IMAGE_MAX_GUNZIP_BYTES (256 << 20) + +/* Load a gzip-compressed kernel. */ +int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz) +{ + uint8_t *compressed_data = NULL; + uint8_t *data = NULL; + gsize len; + ssize_t bytes; + int ret = -1; + + if (!g_file_get_contents(filename, (char **) &compressed_data, &len, + NULL)) { + goto out; + } + + /* Is it a gzip-compressed file? */ + if (len < 2 || + compressed_data[0] != 0x1f || + compressed_data[1] != 0x8b) { + goto out; + } + + if (max_sz > LOAD_IMAGE_MAX_GUNZIP_BYTES) { + max_sz = LOAD_IMAGE_MAX_GUNZIP_BYTES; + } + + data = g_malloc(max_sz); + bytes = gunzip(data, max_sz, compressed_data, len); + if (bytes < 0) { + fprintf(stderr, "%s: unable to decompress gzipped kernel file\n", + filename); + goto out; + } + + rom_add_blob_fixed(filename, data, bytes, addr); + ret = bytes; + + out: + g_free(compressed_data); + g_free(data); + return ret; +} + /* * Functions for reboot-persistent memory regions. * - used for vga bios and option roms. |