diff options
Diffstat (limited to 'hw')
40 files changed, 441 insertions, 124 deletions
diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c index 992d1b234d..7c5989bdc7 100644 --- a/hw/alpha/dp264.c +++ b/hw/alpha/dp264.c @@ -111,7 +111,7 @@ static void clipper_init(MachineState *machine) } size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys, NULL, &palcode_entry, &palcode_low, &palcode_high, - 0, EM_ALPHA, 0); + 0, EM_ALPHA, 0, 0); if (size < 0) { error_report("could not load palcode '%s'", palcode_filename); exit(1); @@ -131,7 +131,7 @@ static void clipper_init(MachineState *machine) size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys, NULL, &kernel_entry, &kernel_low, &kernel_high, - 0, EM_ALPHA, 0); + 0, EM_ALPHA, 0, 0); if (size < 0) { error_report("could not load kernel '%s'", kernel_filename); exit(1); diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index f3973f721a..ed7d97fc21 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -211,7 +211,7 @@ DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, if (kernel_filename) { image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr, - NULL, big_endian, EM_ARM, 1); + NULL, big_endian, EM_ARM, 1, 0); if (image_size < 0) { image_size = load_image_targphys(kernel_filename, 0, mem_size); lowaddr = 0; diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 0a56d34cfe..8ba0e4272a 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -518,9 +518,34 @@ static void do_cpu_reset(void *opaque) cpu_reset(cs); if (info) { if (!info->is_linux) { + int i; /* Jump to the entry point. */ uint64_t entry = info->entry; + switch (info->endianness) { + case ARM_ENDIANNESS_LE: + env->cp15.sctlr_el[1] &= ~SCTLR_E0E; + for (i = 1; i < 4; ++i) { + env->cp15.sctlr_el[i] &= ~SCTLR_EE; + } + env->uncached_cpsr &= ~CPSR_E; + break; + case ARM_ENDIANNESS_BE8: + env->cp15.sctlr_el[1] |= SCTLR_E0E; + for (i = 1; i < 4; ++i) { + env->cp15.sctlr_el[i] |= SCTLR_EE; + } + env->uncached_cpsr |= CPSR_E; + break; + case ARM_ENDIANNESS_BE32: + env->cp15.sctlr_el[1] |= SCTLR_B; + break; + case ARM_ENDIANNESS_UNKNOWN: + break; /* Board's decision */ + default: + g_assert_not_reached(); + } + if (!env->aarch64) { env->thumb = info->entry & 1; entry &= 0xfffffffe; @@ -638,6 +663,62 @@ static int do_arm_linux_init(Object *obj, void *opaque) return 0; } +static uint64_t arm_load_elf(struct arm_boot_info *info, uint64_t *pentry, + uint64_t *lowaddr, uint64_t *highaddr, + int elf_machine) +{ + bool elf_is64; + union { + Elf32_Ehdr h32; + Elf64_Ehdr h64; + } elf_header; + int data_swab = 0; + bool big_endian; + uint64_t ret = -1; + Error *err = NULL; + + + load_elf_hdr(info->kernel_filename, &elf_header, &elf_is64, &err); + if (err) { + return ret; + } + + if (elf_is64) { + big_endian = elf_header.h64.e_ident[EI_DATA] == ELFDATA2MSB; + info->endianness = big_endian ? ARM_ENDIANNESS_BE8 + : ARM_ENDIANNESS_LE; + } else { + big_endian = elf_header.h32.e_ident[EI_DATA] == ELFDATA2MSB; + if (big_endian) { + if (bswap32(elf_header.h32.e_flags) & EF_ARM_BE8) { + info->endianness = ARM_ENDIANNESS_BE8; + } else { + info->endianness = ARM_ENDIANNESS_BE32; + /* In BE32, the CPU has a different view of the per-byte + * address map than the rest of the system. BE32 ELF files + * are organised such that they can be programmed through + * the CPU's per-word byte-reversed view of the world. QEMU + * however loads ELF files independently of the CPU. So + * tell the ELF loader to byte reverse the data for us. + */ + data_swab = 2; + } + } else { + info->endianness = ARM_ENDIANNESS_LE; + } + } + + ret = load_elf(info->kernel_filename, NULL, NULL, + pentry, lowaddr, highaddr, big_endian, elf_machine, + 1, data_swab); + if (ret <= 0) { + /* The header loaded but the image didn't */ + exit(1); + } + + return ret; +} + static void arm_load_kernel_notify(Notifier *notifier, void *data) { CPUState *cs; @@ -647,7 +728,6 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data) uint64_t elf_entry, elf_low_addr, elf_high_addr; int elf_machine; hwaddr entry, kernel_load_offset; - int big_endian; static const ARMInsnFixup *primary_loader; ArmLoadKernelNotifier *n = DO_UPCAST(ArmLoadKernelNotifier, notifier, notifier); @@ -733,12 +813,6 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data) if (info->nb_cpus == 0) info->nb_cpus = 1; -#ifdef TARGET_WORDS_BIGENDIAN - big_endian = 1; -#else - big_endian = 0; -#endif - /* We want to put the initrd far enough into RAM that when the * kernel is uncompressed it will not clobber the initrd. However * on boards without much RAM we must ensure that we still leave @@ -753,9 +827,8 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data) MIN(info->ram_size / 2, 128 * 1024 * 1024); /* Assume that raw images are linux kernels, and ELF images are not. */ - kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry, - &elf_low_addr, &elf_high_addr, big_endian, - elf_machine, 1); + kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr, + &elf_high_addr, elf_machine); if (kernel_size > 0 && have_dtb(info)) { /* If there is still some room left at the base of RAM, try and put * the DTB there like we do for images loaded with -bios or -pflash. diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 44bbbea92b..8c6c99625f 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -73,6 +73,7 @@ typedef struct VirtBoardInfo { uint32_t clock_phandle; uint32_t gic_phandle; uint32_t v2m_phandle; + bool using_psci; } VirtBoardInfo; typedef struct { @@ -95,6 +96,23 @@ typedef struct { #define VIRT_MACHINE_CLASS(klass) \ OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE) +/* RAM limit in GB. Since VIRT_MEM starts at the 1GB mark, this means + * RAM can go up to the 256GB mark, leaving 256GB of the physical + * address space unallocated and free for future use between 256G and 512G. + * If we need to provide more RAM to VMs in the future then we need to: + * * allocate a second bank of RAM starting at 2TB and working up + * * fix the DT and ACPI table generation code in QEMU to correctly + * report two split lumps of RAM to the guest + * * fix KVM in the host kernel to allow guests with >40 bit address spaces + * (We don't want to fill all the way up to 512GB with RAM because + * we might want it for non-RAM purposes later. Conversely it seems + * reasonable to assume that anybody configuring a VM with a quarter + * of a terabyte of RAM will be doing it on a host with more than a + * terabyte of physical address space.) + */ +#define RAMLIMIT_GB 255 +#define RAMLIMIT_BYTES (RAMLIMIT_GB * 1024ULL * 1024 * 1024) + /* Addresses and sizes of our components. * 0..128MB is space for a flash device so we can run bootrom code such as UEFI. * 128MB..256MB is used for miscellaneous device I/O. @@ -127,10 +145,11 @@ static const MemMapEntry a15memmap[] = { [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, + [VIRT_SECURE_MEM] = { 0x0e000000, 0x01000000 }, [VIRT_PCIE_MMIO] = { 0x10000000, 0x2eff0000 }, [VIRT_PCIE_PIO] = { 0x3eff0000, 0x00010000 }, [VIRT_PCIE_ECAM] = { 0x3f000000, 0x01000000 }, - [VIRT_MEM] = { 0x40000000, 30ULL * 1024 * 1024 * 1024 }, + [VIRT_MEM] = { 0x40000000, RAMLIMIT_BYTES }, /* Second PCIe window, 512GB wide at the 512GB boundary */ [VIRT_PCIE_MMIO_HIGH] = { 0x8000000000ULL, 0x8000000000ULL }, }; @@ -230,6 +249,10 @@ static void fdt_add_psci_node(const VirtBoardInfo *vbi) void *fdt = vbi->fdt; ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0)); + if (!vbi->using_psci) { + return; + } + qemu_fdt_add_subnode(fdt, "/psci"); if (armcpu->psci_version == 2) { const char comp[] = "arm,psci-0.2\0arm,psci"; @@ -341,7 +364,7 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi) qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", armcpu->dtb_compatible); - if (vbi->smp_cpus > 1) { + if (vbi->using_psci && vbi->smp_cpus > 1) { qemu_fdt_setprop_string(vbi->fdt, nodename, "enable-method", "psci"); } @@ -678,13 +701,15 @@ static void create_virtio_devices(const VirtBoardInfo *vbi, qemu_irq *pic) } static void create_one_flash(const char *name, hwaddr flashbase, - hwaddr flashsize) + hwaddr flashsize, const char *file, + MemoryRegion *sysmem) { /* Create and map a single flash device. We use the same * parameters as the flash devices on the Versatile Express board. */ DriveInfo *dinfo = drive_get_next(IF_PFLASH); DeviceState *dev = qdev_create(NULL, "cfi.pflash01"); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); const uint64_t sectorlength = 256 * 1024; if (dinfo) { @@ -704,19 +729,10 @@ static void create_one_flash(const char *name, hwaddr flashbase, qdev_prop_set_string(dev, "name", name); qdev_init_nofail(dev); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, flashbase); -} - -static void create_flash(const VirtBoardInfo *vbi) -{ - /* Create two flash devices to fill the VIRT_FLASH space in the memmap. - * Any file passed via -bios goes in the first of these. - */ - hwaddr flashsize = vbi->memmap[VIRT_FLASH].size / 2; - hwaddr flashbase = vbi->memmap[VIRT_FLASH].base; - char *nodename; + memory_region_add_subregion(sysmem, flashbase, + sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0)); - if (bios_name) { + if (file) { char *fn; int image_size; @@ -726,30 +742,73 @@ static void create_flash(const VirtBoardInfo *vbi) "but you cannot use both options at once"); exit(1); } - fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, file); if (!fn) { - error_report("Could not find ROM image '%s'", bios_name); + error_report("Could not find ROM image '%s'", file); exit(1); } - image_size = load_image_targphys(fn, flashbase, flashsize); + image_size = load_image_mr(fn, sysbus_mmio_get_region(sbd, 0)); g_free(fn); if (image_size < 0) { - error_report("Could not load ROM image '%s'", bios_name); + error_report("Could not load ROM image '%s'", file); exit(1); } } +} - create_one_flash("virt.flash0", flashbase, flashsize); - create_one_flash("virt.flash1", flashbase + flashsize, flashsize); +static void create_flash(const VirtBoardInfo *vbi, + MemoryRegion *sysmem, + MemoryRegion *secure_sysmem) +{ + /* Create two flash devices to fill the VIRT_FLASH space in the memmap. + * Any file passed via -bios goes in the first of these. + * sysmem is the system memory space. secure_sysmem is the secure view + * of the system, and the first flash device should be made visible only + * there. The second flash device is visible to both secure and nonsecure. + * If sysmem == secure_sysmem this means there is no separate Secure + * address space and both flash devices are generally visible. + */ + hwaddr flashsize = vbi->memmap[VIRT_FLASH].size / 2; + hwaddr flashbase = vbi->memmap[VIRT_FLASH].base; + char *nodename; - nodename = g_strdup_printf("/flash@%" PRIx64, flashbase); - qemu_fdt_add_subnode(vbi->fdt, nodename); - qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash"); - qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", - 2, flashbase, 2, flashsize, - 2, flashbase + flashsize, 2, flashsize); - qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4); - g_free(nodename); + create_one_flash("virt.flash0", flashbase, flashsize, + bios_name, secure_sysmem); + create_one_flash("virt.flash1", flashbase + flashsize, flashsize, + NULL, sysmem); + + if (sysmem == secure_sysmem) { + /* Report both flash devices as a single node in the DT */ + nodename = g_strdup_printf("/flash@%" PRIx64, flashbase); + qemu_fdt_add_subnode(vbi->fdt, nodename); + qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash"); + qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", + 2, flashbase, 2, flashsize, + 2, flashbase + flashsize, 2, flashsize); + qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4); + g_free(nodename); + } else { + /* Report the devices as separate nodes so we can mark one as + * only visible to the secure world. + */ + nodename = g_strdup_printf("/secflash@%" PRIx64, flashbase); + qemu_fdt_add_subnode(vbi->fdt, nodename); + qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash"); + qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", + 2, flashbase, 2, flashsize); + qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4); + qemu_fdt_setprop_string(vbi->fdt, nodename, "status", "disabled"); + qemu_fdt_setprop_string(vbi->fdt, nodename, "secure-status", "okay"); + g_free(nodename); + + nodename = g_strdup_printf("/flash@%" PRIx64, flashbase); + qemu_fdt_add_subnode(vbi->fdt, nodename); + qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash"); + qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", + 2, flashbase + flashsize, 2, flashsize); + qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4); + g_free(nodename); + } } static void create_fw_cfg(const VirtBoardInfo *vbi, AddressSpace *as) @@ -960,6 +1019,27 @@ static void create_platform_bus(VirtBoardInfo *vbi, qemu_irq *pic) sysbus_mmio_get_region(s, 0)); } +static void create_secure_ram(VirtBoardInfo *vbi, MemoryRegion *secure_sysmem) +{ + MemoryRegion *secram = g_new(MemoryRegion, 1); + char *nodename; + hwaddr base = vbi->memmap[VIRT_SECURE_MEM].base; + hwaddr size = vbi->memmap[VIRT_SECURE_MEM].size; + + memory_region_init_ram(secram, NULL, "virt.secure-ram", size, &error_fatal); + vmstate_register_ram_global(secram); + memory_region_add_subregion(secure_sysmem, base, secram); + + nodename = g_strdup_printf("/secram@%" PRIx64, base); + qemu_fdt_add_subnode(vbi->fdt, nodename); + qemu_fdt_setprop_string(vbi->fdt, nodename, "device_type", "memory"); + qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", 2, base, 2, size); + qemu_fdt_setprop_string(vbi->fdt, nodename, "status", "disabled"); + qemu_fdt_setprop_string(vbi->fdt, nodename, "secure-status", "okay"); + + g_free(nodename); +} + static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size) { const VirtBoardInfo *board = (const VirtBoardInfo *)binfo; @@ -1020,6 +1100,7 @@ static void machvirt_init(MachineState *machine) VirtGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state); VirtGuestInfo *guest_info = &guest_info_state->info; char **cpustr; + bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0); if (!cpu_model) { cpu_model = "cortex-a15"; @@ -1047,6 +1128,15 @@ static void machvirt_init(MachineState *machine) exit(1); } + /* If we have an EL3 boot ROM then the assumption is that it will + * implement PSCI itself, so disable QEMU's internal implementation + * so it doesn't get in the way. Instead of starting secondary + * CPUs in PSCI powerdown state we will start them all running and + * let the boot ROM sort them out. + * The usual case is that we do use QEMU's PSCI implementation. + */ + vbi->using_psci = !(vms->secure && firmware_loaded); + /* The maximum number of CPUs depends on the GIC version, or on how * many redistributors we can fit into the memory map. */ @@ -1066,7 +1156,7 @@ static void machvirt_init(MachineState *machine) vbi->smp_cpus = smp_cpus; if (machine->ram_size > vbi->memmap[VIRT_MEM].size) { - error_report("mach-virt: cannot model more than 30GB RAM"); + error_report("mach-virt: cannot model more than %dGB RAM", RAMLIMIT_GB); exit(1); } @@ -1114,12 +1204,15 @@ static void machvirt_init(MachineState *machine) object_property_set_bool(cpuobj, false, "has_el3", NULL); } - object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_HVC, "psci-conduit", - NULL); + if (vbi->using_psci) { + object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_HVC, + "psci-conduit", NULL); - /* Secondary CPUs start in PSCI powered-down state */ - if (n > 0) { - object_property_set_bool(cpuobj, true, "start-powered-off", NULL); + /* Secondary CPUs start in PSCI powered-down state */ + if (n > 0) { + object_property_set_bool(cpuobj, true, + "start-powered-off", NULL); + } } if (object_property_find(cpuobj, "reset-cbar", NULL)) { @@ -1145,13 +1238,14 @@ static void machvirt_init(MachineState *machine) machine->ram_size); memory_region_add_subregion(sysmem, vbi->memmap[VIRT_MEM].base, ram); - create_flash(vbi); + create_flash(vbi, sysmem, secure_sysmem ? secure_sysmem : sysmem); create_gic(vbi, pic, gic_version, vms->secure); create_uart(vbi, pic, VIRT_UART, sysmem); if (vms->secure) { + create_secure_ram(vbi, secure_sysmem); create_uart(vbi, pic, VIRT_SECURE_UART, secure_sysmem); } @@ -1187,7 +1281,7 @@ static void machvirt_init(MachineState *machine) vbi->bootinfo.board_id = -1; vbi->bootinfo.loader_start = vbi->memmap[VIRT_MEM].base; vbi->bootinfo.get_dtb = machvirt_dtb; - vbi->bootinfo.firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0); + vbi->bootinfo.firmware_loaded = firmware_loaded; arm_load_kernel(ARM_CPU(first_cpu), &vbi->bootinfo); /* diff --git a/hw/core/loader.c b/hw/core/loader.c index 3a57415bf8..8e8031ca3c 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -147,6 +147,28 @@ int load_image_targphys(const char *filename, return size; } +int load_image_mr(const char *filename, MemoryRegion *mr) +{ + int size; + + if (!memory_access_is_direct(mr, false)) { + /* Can only load an image into RAM or ROM */ + return -1; + } + + size = get_image_size(filename); + + if (size > memory_region_size(mr)) { + return -1; + } + if (size > 0) { + if (rom_add_file_mr(filename, mr, -1) < 0) { + return -1; + } + } + return size; +} + void pstrcpy_targphys(const char *name, hwaddr dest, int buf_size, const char *source) { @@ -332,10 +354,66 @@ const char *load_elf_strerror(int error) } } +void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp) +{ + int fd; + uint8_t e_ident_local[EI_NIDENT]; + uint8_t *e_ident; + size_t hdr_size, off; + bool is64l; + + if (!hdr) { + hdr = e_ident_local; + } + e_ident = hdr; + + fd = open(filename, O_RDONLY | O_BINARY); + if (fd < 0) { + error_setg_errno(errp, errno, "Failed to open file: %s", filename); + return; + } + if (read(fd, hdr, EI_NIDENT) != EI_NIDENT) { + error_setg_errno(errp, errno, "Failed to read file: %s", filename); + goto fail; + } + if (e_ident[0] != ELFMAG0 || + e_ident[1] != ELFMAG1 || + e_ident[2] != ELFMAG2 || + e_ident[3] != ELFMAG3) { + error_setg(errp, "Bad ELF magic"); + goto fail; + } + + is64l = e_ident[EI_CLASS] == ELFCLASS64; + hdr_size = is64l ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr); + if (is64) { + *is64 = is64l; + } + + off = EI_NIDENT; + while (hdr != e_ident_local && off < hdr_size) { + size_t br = read(fd, hdr + off, hdr_size - off); + switch (br) { + case 0: + error_setg(errp, "File too short: %s", filename); + goto fail; + case -1: + error_setg_errno(errp, errno, "Failed to read file: %s", + filename); + goto fail; + } + off += br; + } + +fail: + close(fd); +} + /* return < 0 if error, otherwise the number of bytes loaded in memory */ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t), void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, - uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb) + uint64_t *highaddr, int big_endian, int elf_machine, + int clear_lsb, int data_swab) { int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED; uint8_t e_ident[EI_NIDENT]; @@ -374,10 +452,12 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t), lseek(fd, 0, SEEK_SET); if (e_ident[EI_CLASS] == ELFCLASS64) { ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab, - pentry, lowaddr, highaddr, elf_machine, clear_lsb); + pentry, lowaddr, highaddr, elf_machine, clear_lsb, + data_swab); } else { ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab, - pentry, lowaddr, highaddr, elf_machine, clear_lsb); + pentry, lowaddr, highaddr, elf_machine, clear_lsb, + data_swab); } fail: @@ -751,7 +831,7 @@ static void *rom_set_mr(Rom *rom, Object *owner, const char *name) int rom_add_file(const char *file, const char *fw_dir, hwaddr addr, int32_t bootindex, - bool option_rom) + bool option_rom, MemoryRegion *mr) { MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); Rom *rom; @@ -818,7 +898,12 @@ int rom_add_file(const char *file, const char *fw_dir, fw_cfg_add_file(fw_cfg, fw_file_name, data, rom->romsize); } else { - snprintf(devpath, sizeof(devpath), "/rom@" TARGET_FMT_plx, addr); + if (mr) { + rom->mr = mr; + snprintf(devpath, sizeof(devpath), "/rom@%s", file); + } else { + snprintf(devpath, sizeof(devpath), "/rom@" TARGET_FMT_plx, addr); + } } add_boot_device_path(bootindex, NULL, devpath); @@ -892,12 +977,12 @@ int rom_add_elf_program(const char *name, void *data, size_t datasize, int rom_add_vga(const char *file) { - return rom_add_file(file, "vgaroms", 0, -1, true); + return rom_add_file(file, "vgaroms", 0, -1, true, NULL); } int rom_add_option(const char *file, int32_t bootindex) { - return rom_add_file(file, "genroms", 0, bootindex, true); + return rom_add_file(file, "genroms", 0, bootindex, true, NULL); } static void rom_reset(void *unused) diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c index e9063ad6d3..a221b8fe7b 100644 --- a/hw/cpu/a15mpcore.c +++ b/hw/cpu/a15mpcore.c @@ -109,7 +109,7 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp) /* Memory map (addresses are offsets from PERIPHBASE): * 0x0000-0x0fff -- reserved * 0x1000-0x1fff -- GIC Distributor - * 0x2000-0x2fff -- GIC CPU interface + * 0x2000-0x3fff -- GIC CPU interface * 0x4000-0x4fff -- GIC virtual interface control (not modelled) * 0x5000-0x5fff -- GIC virtual interface control (not modelled) * 0x6000-0x7fff -- GIC virtual CPU interface (not modelled) diff --git a/hw/cris/boot.c b/hw/cris/boot.c index 6608160e0d..42485a4ca0 100644 --- a/hw/cris/boot.c +++ b/hw/cris/boot.c @@ -73,7 +73,7 @@ void cris_load_image(CRISCPU *cpu, struct cris_load_info *li) /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis devboard SDK. */ image_size = load_elf(li->image_filename, translate_kernel_address, NULL, - &entry, NULL, &high, 0, EM_CRIS, 0); + &entry, NULL, &high, 0, EM_CRIS, 0, 0); li->entry = entry; if (image_size < 0) { /* Takes a kimage from the axis devboard SDK. */ diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c index c4d7d8328f..9e164e65d9 100644 --- a/hw/i386/multiboot.c +++ b/hw/i386/multiboot.c @@ -196,7 +196,8 @@ int load_multiboot(FWCfgState *fw_cfg, } kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry, - &elf_low, &elf_high, 0, I386_ELF_MACHINE, 0); + &elf_low, &elf_high, 0, I386_ELF_MACHINE, + 0, 0); if (kernel_size < 0) { fprintf(stderr, "Error while loading elf kernel\n"); exit(1); diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 60ab9b858b..0834c2f1a7 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -500,6 +500,41 @@ static uint8_t gic_get_running_priority(GICState *s, int cpu, MemTxAttrs attrs) } } +/* Return true if we should split priority drop and interrupt deactivation, + * ie whether the relevant EOIMode bit is set. + */ +static bool gic_eoi_split(GICState *s, int cpu, MemTxAttrs attrs) +{ + if (s->revision != 2) { + /* Before GICv2 prio-drop and deactivate are not separable */ + return false; + } + if (s->security_extn && !attrs.secure) { + return s->cpu_ctlr[cpu] & GICC_CTLR_EOIMODE_NS; + } + return s->cpu_ctlr[cpu] & GICC_CTLR_EOIMODE; +} + +static void gic_deactivate_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs) +{ + int cm = 1 << cpu; + int group = gic_has_groups(s) && GIC_TEST_GROUP(irq, cm); + + if (!gic_eoi_split(s, cpu, attrs)) { + /* This is UNPREDICTABLE; we choose to ignore it */ + qemu_log_mask(LOG_GUEST_ERROR, + "gic_deactivate_irq: GICC_DIR write when EOIMode clear"); + return; + } + + if (s->security_extn && !attrs.secure && !group) { + DPRINTF("Non-secure DI for Group0 interrupt %d ignored\n", irq); + return; + } + + GIC_CLEAR_ACTIVE(irq, cm); +} + void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs) { int cm = 1 << cpu; @@ -544,7 +579,11 @@ void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs) */ gic_drop_prio(s, cpu, group); - GIC_CLEAR_ACTIVE(irq, cm); + + /* In GICv2 the guest can choose to split priority-drop and deactivate */ + if (!gic_eoi_split(s, cpu, attrs)) { + GIC_CLEAR_ACTIVE(irq, cm); + } gic_update(s); } @@ -1210,6 +1249,10 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset, s->nsapr[regno][cpu] = value; break; } + case 0x1000: + /* GICC_DIR */ + gic_deactivate_irq(s, cpu, value & 0x3ff, attrs); + break; default: qemu_log_mask(LOG_GUEST_ERROR, "gic_cpu_write: Bad offset %x\n", (int)offset); diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index ac8cf42eb8..707d00ded4 100644 --- a/hw/intc/arm_gic_common.c +++ b/hw/intc/arm_gic_common.c @@ -121,7 +121,7 @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler, * neither it can use KVM. */ memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL, - s, "gic_cpu", s->revision == 2 ? 0x1000 : 0x100); + s, "gic_cpu", s->revision == 2 ? 0x2000 : 0x100); sysbus_init_mmio(sbd, &s->cpuiomem[0]); } } diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c index efa6f91fd2..c5a848b06c 100644 --- a/hw/lm32/lm32_boards.c +++ b/hw/lm32/lm32_boards.c @@ -143,7 +143,7 @@ static void lm32_evr_init(MachineState *machine) int kernel_size; kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL, - 1, EM_LATTICEMICO32, 0); + 1, EM_LATTICEMICO32, 0, 0); reset_info->bootstrap_pc = entry; if (kernel_size < 0) { @@ -245,7 +245,7 @@ static void lm32_uclinux_init(MachineState *machine) int kernel_size; kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL, - 1, EM_LATTICEMICO32, 0); + 1, EM_LATTICEMICO32, 0, 0); reset_info->bootstrap_pc = entry; if (kernel_size < 0) { diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c index 5a37b4a1c1..f71492ef7e 100644 --- a/hw/lm32/milkymist.c +++ b/hw/lm32/milkymist.c @@ -177,7 +177,7 @@ milkymist_init(MachineState *machine) /* Boots a kernel elf binary. */ kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL, - 1, EM_LATTICEMICO32, 0); + 1, EM_LATTICEMICO32, 0, 0); reset_info->bootstrap_pc = entry; if (kernel_size < 0) { diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c index d87b945f05..85f72770d7 100644 --- a/hw/m68k/an5206.c +++ b/hw/m68k/an5206.c @@ -73,7 +73,7 @@ static void an5206_init(MachineState *machine) } kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry, - NULL, NULL, 1, EM_68K, 0); + NULL, NULL, 1, EM_68K, 0, 0); entry = elf_entry; if (kernel_size < 0) { kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL, diff --git a/hw/m68k/dummy_m68k.c b/hw/m68k/dummy_m68k.c index a213bcf307..3c2174b505 100644 --- a/hw/m68k/dummy_m68k.c +++ b/hw/m68k/dummy_m68k.c @@ -50,7 +50,7 @@ static void dummy_m68k_init(MachineState *machine) /* Load kernel. */ if (kernel_filename) { kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry, - NULL, NULL, 1, EM_68K, 0); + NULL, NULL, 1, EM_68K, 0, 0); entry = elf_entry; if (kernel_size < 0) { kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL, diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c index 9597e861ab..4f49d34a8f 100644 --- a/hw/m68k/mcf5208.c +++ b/hw/m68k/mcf5208.c @@ -276,7 +276,7 @@ static void mcf5208evb_init(MachineState *machine) } kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry, - NULL, NULL, 1, EM_68K, 0); + NULL, NULL, 1, EM_68K, 0, 0); entry = elf_entry; if (kernel_size < 0) { kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL, diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c index 26cc3786f4..c24014a1f3 100644 --- a/hw/microblaze/boot.c +++ b/hw/microblaze/boot.c @@ -142,12 +142,12 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, /* Boots a kernel elf binary. */ kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, &low, &high, - big_endian, EM_MICROBLAZE, 0); + big_endian, EM_MICROBLAZE, 0, 0); base32 = entry; if (base32 == 0xc0000000) { kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, &entry, NULL, NULL, - big_endian, EM_MICROBLAZE, 0); + big_endian, EM_MICROBLAZE, 0, 0); } /* Always boot into physical ram. */ boot_info.bootstrap_pc = (uint32_t)entry; diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index 184c404454..4e5581b167 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -117,7 +117,7 @@ static int64_t load_kernel (CPUMIPSState *env) if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL, (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low, - (uint64_t *)&kernel_high, 0, EM_MIPS, 1) < 0) { + (uint64_t *)&kernel_high, 0, EM_MIPS, 1, 0) < 0) { fprintf(stderr, "qemu: could not load kernel '%s'\n", loaderparams.kernel_filename); exit(1); diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index c04aa2b8cc..f5173c42de 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -796,7 +796,7 @@ static int64_t load_kernel (void) if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL, (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high, - big_endian, EM_MIPS, 1) < 0) { + big_endian, EM_MIPS, 1, 0) < 0) { fprintf(stderr, "qemu: could not load kernel '%s'\n", loaderparams.kernel_filename); exit(1); diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c index 8951ae97d3..1ecff44a54 100644 --- a/hw/mips/mips_mipssim.c +++ b/hw/mips/mips_mipssim.c @@ -70,7 +70,7 @@ static int64_t load_kernel(void) kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL, (uint64_t *)&entry, NULL, (uint64_t *)&kernel_high, big_endian, - EM_MIPS, 1); + EM_MIPS, 1, 0); if (kernel_size >= 0) { if ((entry & ~0x7fffffffULL) == 0x80000000) entry = (int32_t)entry; diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c index b6625aeee4..724b1e9d51 100644 --- a/hw/mips/mips_r4k.c +++ b/hw/mips/mips_r4k.c @@ -88,7 +88,7 @@ static int64_t load_kernel(void) kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL, (uint64_t *)&entry, NULL, (uint64_t *)&kernel_high, big_endian, - EM_MIPS, 1); + EM_MIPS, 1, 0); if (kernel_size >= 0) { if ((entry & ~0x7fffffffULL) == 0x80000000) entry = (int32_t)entry; diff --git a/hw/misc/bcm2835_mbox.c b/hw/misc/bcm2835_mbox.c index 500baba7c0..106585a7bf 100644 --- a/hw/misc/bcm2835_mbox.c +++ b/hw/misc/bcm2835_mbox.c @@ -98,7 +98,7 @@ static void bcm2835_mbox_update(BCM2835MboxState *s) */ for (n = 0; n < MBOX_CHAN_COUNT; n++) { while (s->available[n] && !(s->mbox[0].status & ARM_MS_FULL)) { - value = ldl_phys(&s->mbox_as, n << MBOX_AS_CHAN_SHIFT); + value = ldl_le_phys(&s->mbox_as, n << MBOX_AS_CHAN_SHIFT); assert(value != MBOX_INVALID_DATA); /* Pending interrupt but no data */ mbox_push(&s->mbox[0], value); } @@ -207,12 +207,12 @@ static void bcm2835_mbox_write(void *opaque, hwaddr offset, ch = value & 0xf; if (ch < MBOX_CHAN_COUNT) { childaddr = ch << MBOX_AS_CHAN_SHIFT; - if (ldl_phys(&s->mbox_as, childaddr + MBOX_AS_PENDING)) { + if (ldl_le_phys(&s->mbox_as, childaddr + MBOX_AS_PENDING)) { /* Child busy, push delayed. Push it in the arm->vc mbox */ mbox_push(&s->mbox[1], value); } else { /* Push it directly to the child device */ - stl_phys(&s->mbox_as, childaddr, value); + stl_le_phys(&s->mbox_as, childaddr, value); } } else { /* Invalid channel number */ diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c index 581922abd7..41fbbe3e7f 100644 --- a/hw/misc/bcm2835_property.c +++ b/hw/misc/bcm2835_property.c @@ -22,20 +22,20 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) s->addr = value; - tot_len = ldl_phys(&s->dma_as, value); + tot_len = ldl_le_phys(&s->dma_as, value); /* @(addr + 4) : Buffer response code */ value = s->addr + 8; while (value + 8 <= s->addr + tot_len) { - tag = ldl_phys(&s->dma_as, value); - bufsize = ldl_phys(&s->dma_as, value + 4); + tag = ldl_le_phys(&s->dma_as, value); + bufsize = ldl_le_phys(&s->dma_as, value + 4); /* @(value + 8) : Request/response indicator */ resplen = 0; switch (tag) { case 0x00000000: /* End tag */ break; case 0x00000001: /* Get firmware revision */ - stl_phys(&s->dma_as, value + 12, 346337); + stl_le_phys(&s->dma_as, value + 12, 346337); resplen = 4; break; case 0x00010001: /* Get board model */ @@ -44,7 +44,7 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) resplen = 4; break; case 0x00010002: /* Get board revision */ - stl_phys(&s->dma_as, value + 12, s->board_rev); + stl_le_phys(&s->dma_as, value + 12, s->board_rev); resplen = 4; break; case 0x00010003: /* Get board MAC address */ @@ -58,24 +58,24 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) break; case 0x00010005: /* Get ARM memory */ /* base */ - stl_phys(&s->dma_as, value + 12, 0); + stl_le_phys(&s->dma_as, value + 12, 0); /* size */ - stl_phys(&s->dma_as, value + 16, s->ram_size); + stl_le_phys(&s->dma_as, value + 16, s->ram_size); resplen = 8; break; case 0x00028001: /* Set power state */ /* Assume that whatever device they asked for exists, * and we'll just claim we set it to the desired state */ - tmp = ldl_phys(&s->dma_as, value + 16); - stl_phys(&s->dma_as, value + 16, (tmp & 1)); + tmp = ldl_le_phys(&s->dma_as, value + 16); + stl_le_phys(&s->dma_as, value + 16, (tmp & 1)); resplen = 8; break; /* Clocks */ case 0x00030001: /* Get clock state */ - stl_phys(&s->dma_as, value + 16, 0x1); + stl_le_phys(&s->dma_as, value + 16, 0x1); resplen = 8; break; @@ -88,15 +88,15 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) case 0x00030002: /* Get clock rate */ case 0x00030004: /* Get max clock rate */ case 0x00030007: /* Get min clock rate */ - switch (ldl_phys(&s->dma_as, value + 12)) { + switch (ldl_le_phys(&s->dma_as, value + 12)) { case 1: /* EMMC */ - stl_phys(&s->dma_as, value + 16, 50000000); + stl_le_phys(&s->dma_as, value + 16, 50000000); break; case 2: /* UART */ - stl_phys(&s->dma_as, value + 16, 3000000); + stl_le_phys(&s->dma_as, value + 16, 3000000); break; default: - stl_phys(&s->dma_as, value + 16, 700000000); + stl_le_phys(&s->dma_as, value + 16, 700000000); break; } resplen = 8; @@ -113,19 +113,19 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) /* Temperature */ case 0x00030006: /* Get temperature */ - stl_phys(&s->dma_as, value + 16, 25000); + stl_le_phys(&s->dma_as, value + 16, 25000); resplen = 8; break; case 0x0003000A: /* Get max temperature */ - stl_phys(&s->dma_as, value + 16, 99000); + stl_le_phys(&s->dma_as, value + 16, 99000); resplen = 8; break; case 0x00060001: /* Get DMA channels */ /* channels 2-5 */ - stl_phys(&s->dma_as, value + 12, 0x003C); + stl_le_phys(&s->dma_as, value + 12, 0x003C); resplen = 4; break; @@ -143,12 +143,12 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) break; } - stl_phys(&s->dma_as, value + 8, (1 << 31) | resplen); + stl_le_phys(&s->dma_as, value + 8, (1 << 31) | resplen); value += bufsize + 12; } /* Buffer response code */ - stl_phys(&s->dma_as, s->addr + 4, (1 << 31)); + stl_le_phys(&s->dma_as, s->addr + 4, (1 << 31)); } static uint64_t bcm2835_property_read(void *opaque, hwaddr offset, diff --git a/hw/moxie/moxiesim.c b/hw/moxie/moxiesim.c index 9191ae9603..d88c9428e0 100644 --- a/hw/moxie/moxiesim.c +++ b/hw/moxie/moxiesim.c @@ -54,7 +54,8 @@ static void load_kernel(MoxieCPU *cpu, LoaderParams *loader_params) ram_addr_t initrd_offset; kernel_size = load_elf(loader_params->kernel_filename, NULL, NULL, - &entry, &kernel_low, &kernel_high, 1, EM_MOXIE, 0); + &entry, &kernel_low, &kernel_high, 1, EM_MOXIE, + 0, 0); if (kernel_size <= 0) { fprintf(stderr, "qemu: could not load kernel '%s'\n", diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c index 25c637aba7..46418c30f7 100644 --- a/hw/openrisc/openrisc_sim.c +++ b/hw/openrisc/openrisc_sim.c @@ -69,7 +69,8 @@ static void cpu_openrisc_load_kernel(ram_addr_t ram_size, if (kernel_filename && !qtest_enabled()) { kernel_size = load_elf(kernel_filename, NULL, NULL, - &elf_entry, NULL, NULL, 1, EM_OPENRISC, 1); + &elf_entry, NULL, NULL, 1, EM_OPENRISC, + 1, 0); entry = elf_entry; if (kernel_size < 0) { kernel_size = load_uimage(kernel_filename, diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c index 5dc550fe5e..49cdaab36b 100644 --- a/hw/pci-host/prep.c +++ b/hw/pci-host/prep.c @@ -313,7 +313,7 @@ static void raven_realize(PCIDevice *d, Error **errp) if (filename) { if (s->elf_machine != EM_NONE) { bios_size = load_elf(filename, NULL, NULL, NULL, - NULL, NULL, 1, s->elf_machine, 0); + NULL, NULL, 1, s->elf_machine, 0, 0); } if (bios_size < 0) { bios_size = get_image_size(filename); diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index bd84e9ac13..09154fa813 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -1017,7 +1017,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); bios_size = load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, NULL, - 1, PPC_ELF_MACHINE, 0); + 1, PPC_ELF_MACHINE, 0, 0); if (bios_size < 0) { /* * Hrm. No ELF image? Try a uImage, maybe someone is giving us an diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index f95086b787..f0a36b3133 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -221,7 +221,7 @@ static void ppc_core99_init(MachineState *machine) /* Load OpenBIOS (ELF) */ if (filename) { bios_size = load_elf(filename, NULL, NULL, NULL, - NULL, NULL, 1, PPC_ELF_MACHINE, 0); + NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0); g_free(filename); } else { @@ -244,7 +244,8 @@ static void ppc_core99_init(MachineState *machine) kernel_base = KERNEL_LOAD_ADDR; kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, - NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0); + NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, + 0, 0); if (kernel_size < 0) kernel_size = load_aout(kernel_filename, kernel_base, ram_size - kernel_base, bswap_needed, diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 898439860c..d952713313 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -149,7 +149,7 @@ static void ppc_heathrow_init(MachineState *machine) /* Load OpenBIOS (ELF) */ if (filename) { bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL, - 1, PPC_ELF_MACHINE, 0); + 1, PPC_ELF_MACHINE, 0, 0); g_free(filename); } else { bios_size = -1; @@ -170,7 +170,8 @@ static void ppc_heathrow_init(MachineState *machine) #endif kernel_base = KERNEL_LOAD_ADDR; kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, - NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0); + NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, + 0, 0); if (kernel_size < 0) kernel_size = load_aout(kernel_filename, kernel_base, ram_size - kernel_base, bswap_needed, diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c index e535a9f266..5c535b18a2 100644 --- a/hw/ppc/ppc440_bamboo.c +++ b/hw/ppc/ppc440_bamboo.c @@ -256,7 +256,8 @@ static void bamboo_init(MachineState *machine) NULL, NULL); if (success < 0) { success = load_elf(kernel_filename, NULL, NULL, &elf_entry, - &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, 0); + &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, + 0, 0); entry = elf_entry; loadaddr = elf_lowaddr; } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index e9d4abf06a..64c4acce06 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1942,11 +1942,13 @@ static void ppc_spapr_init(MachineState *machine) uint64_t lowaddr = 0; kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, - NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0); + NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, + 0, 0); if (kernel_size == ELF_LOAD_WRONG_ENDIAN) { kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, - NULL, &lowaddr, NULL, 0, PPC_ELF_MACHINE, 0); + NULL, &lowaddr, NULL, 0, PPC_ELF_MACHINE, + 0, 0); kernel_le = kernel_size > 0; } if (kernel_size < 0) { diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c index a902c88277..b807a08c28 100644 --- a/hw/ppc/virtex_ml507.c +++ b/hw/ppc/virtex_ml507.c @@ -258,7 +258,8 @@ static void virtex_init(MachineState *machine) /* Boots a kernel elf binary. */ kernel_size = load_elf(kernel_filename, NULL, NULL, - &entry, &low, &high, 1, PPC_ELF_MACHINE, 0); + &entry, &low, &high, 1, PPC_ELF_MACHINE, + 0, 0); boot_info.bootstrap_pc = entry & 0x00ffffff; if (kernel_size < 0) { diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index c9cf7cce64..41ff002069 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -101,7 +101,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) bios_size = load_elf(bios_filename, bios_translate_addr, &fwbase, &ipl->bios_start_addr, NULL, NULL, 1, - EM_S390, 0); + EM_S390, 0, 0); if (bios_size > 0) { /* Adjust ELF start address to final location */ ipl->bios_start_addr += fwbase; @@ -124,7 +124,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) if (ipl->kernel) { kernel_size = load_elf(ipl->kernel, NULL, NULL, &pentry, NULL, - NULL, 1, EM_S390, 0); + NULL, 1, EM_S390, 0, 0); if (kernel_size < 0) { kernel_size = load_image_targphys(ipl->kernel, 0, ram_size); } diff --git a/hw/sd/sd.c b/hw/sd/sd.c index edb6b32690..00c320d00b 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -449,7 +449,7 @@ static void sd_reset(DeviceState *dev) static bool sd_get_inserted(SDState *sd) { - return blk_is_inserted(sd->blk); + return sd->blk && blk_is_inserted(sd->blk); } static bool sd_get_readonly(SDState *sd) diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index e087c17ad7..d28b5871fc 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -207,6 +207,21 @@ static void sdhci_reset(SDHCIState *s) s->pending_insert_state = false; } +static void sdhci_poweron_reset(DeviceState *dev) +{ + /* QOM (ie power-on) reset. This is identical to reset + * commanded via device register apart from handling of the + * 'pending insert on powerup' quirk. + */ + SDHCIState *s = (SDHCIState *)dev; + + sdhci_reset(s); + + if (s->pending_insert_quirk) { + s->pending_insert_state = true; + } +} + static void sdhci_data_transfer(void *opaque); static void sdhci_send_command(SDHCIState *s) @@ -1290,6 +1305,7 @@ static void sdhci_pci_class_init(ObjectClass *klass, void *data) set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); dc->vmsd = &sdhci_vmstate; dc->props = sdhci_pci_properties; + dc->reset = sdhci_poweron_reset; } static const TypeInfo sdhci_pci_info = { @@ -1332,10 +1348,6 @@ static void sdhci_sysbus_realize(DeviceState *dev, Error ** errp) memory_region_init_io(&s->iomem, OBJECT(s), &sdhci_mmio_ops, s, "sdhci", SDHC_REGISTERS_MAP_SIZE); sysbus_init_mmio(sbd, &s->iomem); - - if (s->pending_insert_quirk) { - s->pending_insert_state = true; - } } static void sdhci_sysbus_class_init(ObjectClass *klass, void *data) @@ -1345,6 +1357,7 @@ static void sdhci_sysbus_class_init(ObjectClass *klass, void *data) dc->vmsd = &sdhci_vmstate; dc->props = sdhci_sysbus_properties; dc->realize = sdhci_sysbus_realize; + dc->reset = sdhci_poweron_reset; } static const TypeInfo sdhci_sysbus_info = { diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index 07c5c850ef..c579f5b9ea 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -194,7 +194,7 @@ static void leon3_generic_hw_init(MachineState *machine) uint64_t entry; kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL, - 1 /* big endian */, EM_SPARC, 0); + 1 /* big endian */, EM_SPARC, 0, 0); if (kernel_size < 0) { fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename); diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 20dc341710..eebef37897 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -279,7 +279,7 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename, bswap_needed = 0; #endif kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, - NULL, NULL, NULL, 1, EM_SPARC, 0); + NULL, NULL, NULL, 1, EM_SPARC, 0, 0); if (kernel_size < 0) kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR, RAM_size - KERNEL_LOAD_ADDR, bswap_needed, @@ -723,7 +723,7 @@ static void prom_init(hwaddr addr, const char *bios_name) filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { ret = load_elf(filename, translate_prom_address, &addr, NULL, - NULL, NULL, 1, EM_SPARC, 0); + NULL, NULL, 1, EM_SPARC, 0, 0); if (ret < 0 || ret > PROM_SIZE_MAX) { ret = load_image_targphys(filename, addr, PROM_SIZE_MAX); } diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index add1e752f3..0a6f453858 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -187,7 +187,7 @@ static uint64_t sun4u_load_kernel(const char *kernel_filename, bswap_needed = 0; #endif kernel_size = load_elf(kernel_filename, NULL, NULL, kernel_entry, - kernel_addr, &kernel_top, 1, EM_SPARCV9, 0); + kernel_addr, &kernel_top, 1, EM_SPARCV9, 0, 0); if (kernel_size < 0) { *kernel_addr = KERNEL_LOAD_ADDR; *kernel_entry = KERNEL_LOAD_ADDR; @@ -633,7 +633,7 @@ static void prom_init(hwaddr addr, const char *bios_name) filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { ret = load_elf(filename, translate_prom_address, &addr, - NULL, NULL, NULL, 1, EM_SPARCV9, 0); + NULL, NULL, NULL, 1, EM_SPARCV9, 0, 0); if (ret < 0 || ret > PROM_SIZE_MAX) { ret = load_image_targphys(filename, addr, PROM_SIZE_MAX); } diff --git a/hw/tricore/tricore_testboard.c b/hw/tricore/tricore_testboard.c index 9392571f1f..3cadb6521c 100644 --- a/hw/tricore/tricore_testboard.c +++ b/hw/tricore/tricore_testboard.c @@ -45,7 +45,7 @@ static void tricore_load_kernel(CPUTriCoreState *env) kernel_size = load_elf(tricoretb_binfo.kernel_filename, NULL, NULL, (uint64_t *)&entry, NULL, NULL, 0, - EM_TRICORE, 1); + EM_TRICORE, 1, 0); if (kernel_size <= 0) { error_report("qemu: no kernel file '%s'", tricoretb_binfo.kernel_filename); diff --git a/hw/xtensa/sim.c b/hw/xtensa/sim.c index 3a5060b03b..23050e8fb7 100644 --- a/hw/xtensa/sim.c +++ b/hw/xtensa/sim.c @@ -94,10 +94,10 @@ static void xtensa_sim_init(MachineState *machine) uint64_t elf_lowaddr; #ifdef TARGET_WORDS_BIGENDIAN int success = load_elf(kernel_filename, translate_phys_addr, cpu, - &elf_entry, &elf_lowaddr, NULL, 1, EM_XTENSA, 0); + &elf_entry, &elf_lowaddr, NULL, 1, EM_XTENSA, 0, 0); #else int success = load_elf(kernel_filename, translate_phys_addr, cpu, - &elf_entry, &elf_lowaddr, NULL, 0, EM_XTENSA, 0); + &elf_entry, &elf_lowaddr, NULL, 0, EM_XTENSA, 0, 0); #endif if (success > 0) { env->pc = elf_entry; diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index fe7684d41c..ed09b9d809 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -355,7 +355,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine) uint64_t elf_entry; uint64_t elf_lowaddr; int success = load_elf(kernel_filename, translate_phys_addr, cpu, - &elf_entry, &elf_lowaddr, NULL, be, EM_XTENSA, 0); + &elf_entry, &elf_lowaddr, NULL, be, EM_XTENSA, 0, 0); if (success > 0) { entry_point = elf_entry; } else { |