aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/alpha/dp264.c4
-rw-r--r--hw/arm/armv7m.c2
-rw-r--r--hw/arm/boot.c93
-rw-r--r--hw/arm/virt.c168
-rw-r--r--hw/core/loader.c99
-rw-r--r--hw/cpu/a15mpcore.c2
-rw-r--r--hw/cris/boot.c2
-rw-r--r--hw/i386/multiboot.c3
-rw-r--r--hw/intc/arm_gic.c45
-rw-r--r--hw/intc/arm_gic_common.c2
-rw-r--r--hw/lm32/lm32_boards.c4
-rw-r--r--hw/lm32/milkymist.c2
-rw-r--r--hw/m68k/an5206.c2
-rw-r--r--hw/m68k/dummy_m68k.c2
-rw-r--r--hw/m68k/mcf5208.c2
-rw-r--r--hw/microblaze/boot.c4
-rw-r--r--hw/mips/mips_fulong2e.c2
-rw-r--r--hw/mips/mips_malta.c2
-rw-r--r--hw/mips/mips_mipssim.c2
-rw-r--r--hw/mips/mips_r4k.c2
-rw-r--r--hw/misc/bcm2835_mbox.c6
-rw-r--r--hw/misc/bcm2835_property.c38
-rw-r--r--hw/moxie/moxiesim.c3
-rw-r--r--hw/openrisc/openrisc_sim.c3
-rw-r--r--hw/pci-host/prep.c2
-rw-r--r--hw/ppc/e500.c2
-rw-r--r--hw/ppc/mac_newworld.c5
-rw-r--r--hw/ppc/mac_oldworld.c5
-rw-r--r--hw/ppc/ppc440_bamboo.c3
-rw-r--r--hw/ppc/spapr.c6
-rw-r--r--hw/ppc/virtex_ml507.c3
-rw-r--r--hw/s390x/ipl.c4
-rw-r--r--hw/sd/sd.c2
-rw-r--r--hw/sd/sdhci.c21
-rw-r--r--hw/sparc/leon3.c2
-rw-r--r--hw/sparc/sun4m.c4
-rw-r--r--hw/sparc64/sun4u.c4
-rw-r--r--hw/tricore/tricore_testboard.c2
-rw-r--r--hw/xtensa/sim.c4
-rw-r--r--hw/xtensa/xtfpga.c2
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 {