target-arm queue:
* Stop using variable length array in dc_zva * Implement M-profile XPSR GE bits * Don't enable ARMV7M_EXCP_DEBUG from reset * armv7m_nvic: NS BFAR and BFSR are RAZ/WI if BFHFNMINS == 0 * armv7m_nvic: Check subpriority in nvic_recompute_state_secure() * fix various minor issues to allow building for Windows-on-ARM64 * aspeed: Set SDRAM size * Allow system registers for KVM guests to be changed by QEMU code * raspi: Diagnose requests for too much RAM * virt: Support firmware configuration with -blockdev -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAlzRcyIZHHBldGVyLm1h eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3lynD/0eOoNsA64b8GeY2OBgmYbc tNhgby30IhiiEiSdFK6cnKSq5MkqakGXwWQ5j7aYSjRV3frJD9unZO3yZ0FwlXmM PZ9qlvC3AW/TcFiV6nF0uJTh5EFdiV3iPsyRYC9b9Zm+tjAg79OchDp7qOH4vq0W rylkvQpbZrI/0poKDu/Efuq10fbT/aj9IwmO2EjWSGpt0R9rFYKFaaIKB0I1yrNQ V+JXMCYm39IUP0Zri9Hva67GvWotS6w1Z4J1v5epv2UNAS++LQlL16Mal7EHP9eI FWu7dfDUa9g78/ct1/ZEuG0myE9CiWEgpo1zzdLaokKgeZfsrvFYz3Y1zc14cMGh O1SuEQbsrrZX9CizYN8iPsFXP631mxk/Bz8jKklxa8L1JAW6RLpXtS8KZCMF+O6B PDzx7Tmxg08nG+PtMOD8jOV+cgMji2EFXeF5ojSCOpWyWKidnNUYRdubHDVU7yJR SRItNioTrEWQQOW7hiqhedi5QflObfdOUtrAi7i2NTuCaGqNIxkhSWaerCyJ0eli rlLctAXjqgU/APp66RdwtgrVnGyPs8hvgWsrHVC6yPLArkn0HpghH53VfijwGObZ e6iIRh4UvN94Vp3fGx1ADWkxAcZNi10zxzLFKjSCBpN0izIoNy3qLNEyD9QNK22c 8AcNj9nR7ZzhLRkpW7sv0A== =hcal -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20190507' into staging target-arm queue: * Stop using variable length array in dc_zva * Implement M-profile XPSR GE bits * Don't enable ARMV7M_EXCP_DEBUG from reset * armv7m_nvic: NS BFAR and BFSR are RAZ/WI if BFHFNMINS == 0 * armv7m_nvic: Check subpriority in nvic_recompute_state_secure() * fix various minor issues to allow building for Windows-on-ARM64 * aspeed: Set SDRAM size * Allow system registers for KVM guests to be changed by QEMU code * raspi: Diagnose requests for too much RAM * virt: Support firmware configuration with -blockdev # gpg: Signature made Tue 07 May 2019 12:59:30 BST # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20190507: target/arm: Stop using variable length array in dc_zva target/arm: Implement XPSR GE bits hw/intc/armv7m_nvic: Don't enable ARMV7M_EXCP_DEBUG from reset hw/intc/armv7m_nvic: NS BFAR and BFSR are RAZ/WI if BFHFNMINS == 0 hw/arm/armv7m_nvic: Check subpriority in nvic_recompute_state_secure() osdep: Fix mingw compilation regarding stdio formats util/cacheinfo: Use uint64_t on LLP64 model to satisfy Windows ARM64 qga: Fix mingw compilation warnings on enum conversion QEMU_PACKED: Remove gcc_struct attribute in Windows non x86 targets arm: aspeed: Set SDRAM size arm: Allow system registers for KVM guests to be changed by QEMU code hw/arm/raspi: Diagnose requests for too much RAM hw/arm/virt: Support firmware configuration with -blockdev pflash_cfi01: New pflash_cfi01_legacy_drive() pc: Rearrange pc_system_firmware_init()'s legacy -drive loop Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
629d166994
@ -148,7 +148,7 @@ typedef struct VhostUserInflight {
|
||||
uint16_t queue_size;
|
||||
} VhostUserInflight;
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32) && (defined(__x86_64__) || defined(__i386__))
|
||||
# define VU_PACKED __attribute__((gcc_struct, packed))
|
||||
#else
|
||||
# define VU_PACKED __attribute__((packed))
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "hw/loader.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/units.h"
|
||||
|
||||
static struct arm_boot_info aspeed_board_binfo = {
|
||||
.board_id = -1, /* device-tree-only board */
|
||||
@ -331,6 +332,9 @@ static void aspeed_machine_class_init(ObjectClass *oc, void *data)
|
||||
mc->no_floppy = 1;
|
||||
mc->no_cdrom = 1;
|
||||
mc->no_parallel = 1;
|
||||
if (board->ram) {
|
||||
mc->default_ram_size = board->ram;
|
||||
}
|
||||
amc->board = board;
|
||||
}
|
||||
|
||||
@ -352,6 +356,7 @@ static const AspeedBoardConfig aspeed_boards[] = {
|
||||
.spi_model = "mx25l25635e",
|
||||
.num_cs = 1,
|
||||
.i2c_init = palmetto_bmc_i2c_init,
|
||||
.ram = 256 * MiB,
|
||||
}, {
|
||||
.name = MACHINE_TYPE_NAME("ast2500-evb"),
|
||||
.desc = "Aspeed AST2500 EVB (ARM1176)",
|
||||
@ -361,6 +366,7 @@ static const AspeedBoardConfig aspeed_boards[] = {
|
||||
.spi_model = "mx25l25635e",
|
||||
.num_cs = 1,
|
||||
.i2c_init = ast2500_evb_i2c_init,
|
||||
.ram = 512 * MiB,
|
||||
}, {
|
||||
.name = MACHINE_TYPE_NAME("romulus-bmc"),
|
||||
.desc = "OpenPOWER Romulus BMC (ARM1176)",
|
||||
@ -370,6 +376,7 @@ static const AspeedBoardConfig aspeed_boards[] = {
|
||||
.spi_model = "mx66l1g45g",
|
||||
.num_cs = 2,
|
||||
.i2c_init = romulus_bmc_i2c_init,
|
||||
.ram = 512 * MiB,
|
||||
}, {
|
||||
.name = MACHINE_TYPE_NAME("witherspoon-bmc"),
|
||||
.desc = "OpenPOWER Witherspoon BMC (ARM1176)",
|
||||
@ -379,6 +386,7 @@ static const AspeedBoardConfig aspeed_boards[] = {
|
||||
.spi_model = "mx66l1g45g",
|
||||
.num_cs = 2,
|
||||
.i2c_init = witherspoon_bmc_i2c_init,
|
||||
.ram = 512 * MiB,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
@ -175,6 +176,12 @@ static void raspi_init(MachineState *machine, int version)
|
||||
BusState *bus;
|
||||
DeviceState *carddev;
|
||||
|
||||
if (machine->ram_size > 1 * GiB) {
|
||||
error_report("Requested ram size is too large for this machine: "
|
||||
"maximum is 1GB");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
object_initialize(&s->soc, sizeof(s->soc),
|
||||
version == 3 ? TYPE_BCM2837 : TYPE_BCM2836);
|
||||
object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
|
||||
|
202
hw/arm/virt.c
202
hw/arm/virt.c
@ -30,6 +30,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/arm/arm.h"
|
||||
@ -871,25 +872,19 @@ static void create_virtio_devices(const VirtMachineState *vms, qemu_irq *pic)
|
||||
}
|
||||
}
|
||||
|
||||
static void create_one_flash(const char *name, hwaddr flashbase,
|
||||
hwaddr flashsize, const char *file,
|
||||
MemoryRegion *sysmem)
|
||||
#define VIRT_FLASH_SECTOR_SIZE (256 * KiB)
|
||||
|
||||
static PFlashCFI01 *virt_flash_create1(VirtMachineState *vms,
|
||||
const char *name,
|
||||
const char *alias_prop_name)
|
||||
{
|
||||
/* Create and map a single flash device. We use the same
|
||||
* parameters as the flash devices on the Versatile Express board.
|
||||
/*
|
||||
* Create 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, TYPE_PFLASH_CFI01);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
const uint64_t sectorlength = 256 * 1024;
|
||||
|
||||
if (dinfo) {
|
||||
qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo),
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
qdev_prop_set_uint32(dev, "num-blocks", flashsize / sectorlength);
|
||||
qdev_prop_set_uint64(dev, "sector-length", sectorlength);
|
||||
qdev_prop_set_uint64(dev, "sector-length", VIRT_FLASH_SECTOR_SIZE);
|
||||
qdev_prop_set_uint8(dev, "width", 4);
|
||||
qdev_prop_set_uint8(dev, "device-width", 2);
|
||||
qdev_prop_set_bit(dev, "big-endian", false);
|
||||
@ -898,41 +893,41 @@ static void create_one_flash(const char *name, hwaddr flashbase,
|
||||
qdev_prop_set_uint16(dev, "id2", 0x00);
|
||||
qdev_prop_set_uint16(dev, "id3", 0x00);
|
||||
qdev_prop_set_string(dev, "name", name);
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
memory_region_add_subregion(sysmem, flashbase,
|
||||
sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0));
|
||||
|
||||
if (file) {
|
||||
char *fn;
|
||||
int image_size;
|
||||
|
||||
if (drive_get(IF_PFLASH, 0, 0)) {
|
||||
error_report("The contents of the first flash device may be "
|
||||
"specified with -bios or with -drive if=pflash... "
|
||||
"but you cannot use both options at once");
|
||||
exit(1);
|
||||
}
|
||||
fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, file);
|
||||
if (!fn) {
|
||||
error_report("Could not find ROM image '%s'", file);
|
||||
exit(1);
|
||||
}
|
||||
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'", file);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
object_property_add_child(OBJECT(vms), name, OBJECT(dev),
|
||||
&error_abort);
|
||||
object_property_add_alias(OBJECT(vms), alias_prop_name,
|
||||
OBJECT(dev), "drive", &error_abort);
|
||||
return PFLASH_CFI01(dev);
|
||||
}
|
||||
|
||||
static void create_flash(const VirtMachineState *vms,
|
||||
MemoryRegion *sysmem,
|
||||
MemoryRegion *secure_sysmem)
|
||||
static void virt_flash_create(VirtMachineState *vms)
|
||||
{
|
||||
/* Create two flash devices to fill the VIRT_FLASH space in the memmap.
|
||||
* Any file passed via -bios goes in the first of these.
|
||||
vms->flash[0] = virt_flash_create1(vms, "virt.flash0", "pflash0");
|
||||
vms->flash[1] = virt_flash_create1(vms, "virt.flash1", "pflash1");
|
||||
}
|
||||
|
||||
static void virt_flash_map1(PFlashCFI01 *flash,
|
||||
hwaddr base, hwaddr size,
|
||||
MemoryRegion *sysmem)
|
||||
{
|
||||
DeviceState *dev = DEVICE(flash);
|
||||
|
||||
assert(size % VIRT_FLASH_SECTOR_SIZE == 0);
|
||||
assert(size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX);
|
||||
qdev_prop_set_uint32(dev, "num-blocks", size / VIRT_FLASH_SECTOR_SIZE);
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
memory_region_add_subregion(sysmem, base,
|
||||
sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
|
||||
0));
|
||||
}
|
||||
|
||||
static void virt_flash_map(VirtMachineState *vms,
|
||||
MemoryRegion *sysmem,
|
||||
MemoryRegion *secure_sysmem)
|
||||
{
|
||||
/*
|
||||
* Map two flash devices to fill the VIRT_FLASH space in the memmap.
|
||||
* 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.
|
||||
@ -941,12 +936,20 @@ static void create_flash(const VirtMachineState *vms,
|
||||
*/
|
||||
hwaddr flashsize = vms->memmap[VIRT_FLASH].size / 2;
|
||||
hwaddr flashbase = vms->memmap[VIRT_FLASH].base;
|
||||
char *nodename;
|
||||
|
||||
create_one_flash("virt.flash0", flashbase, flashsize,
|
||||
bios_name, secure_sysmem);
|
||||
create_one_flash("virt.flash1", flashbase + flashsize, flashsize,
|
||||
NULL, sysmem);
|
||||
virt_flash_map1(vms->flash[0], flashbase, flashsize,
|
||||
secure_sysmem);
|
||||
virt_flash_map1(vms->flash[1], flashbase + flashsize, flashsize,
|
||||
sysmem);
|
||||
}
|
||||
|
||||
static void virt_flash_fdt(VirtMachineState *vms,
|
||||
MemoryRegion *sysmem,
|
||||
MemoryRegion *secure_sysmem)
|
||||
{
|
||||
hwaddr flashsize = vms->memmap[VIRT_FLASH].size / 2;
|
||||
hwaddr flashbase = vms->memmap[VIRT_FLASH].base;
|
||||
char *nodename;
|
||||
|
||||
if (sysmem == secure_sysmem) {
|
||||
/* Report both flash devices as a single node in the DT */
|
||||
@ -959,7 +962,8 @@ static void create_flash(const VirtMachineState *vms,
|
||||
qemu_fdt_setprop_cell(vms->fdt, nodename, "bank-width", 4);
|
||||
g_free(nodename);
|
||||
} else {
|
||||
/* Report the devices as separate nodes so we can mark one as
|
||||
/*
|
||||
* 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);
|
||||
@ -982,6 +986,54 @@ static void create_flash(const VirtMachineState *vms,
|
||||
}
|
||||
}
|
||||
|
||||
static bool virt_firmware_init(VirtMachineState *vms,
|
||||
MemoryRegion *sysmem,
|
||||
MemoryRegion *secure_sysmem)
|
||||
{
|
||||
int i;
|
||||
BlockBackend *pflash_blk0;
|
||||
|
||||
/* Map legacy -drive if=pflash to machine properties */
|
||||
for (i = 0; i < ARRAY_SIZE(vms->flash); i++) {
|
||||
pflash_cfi01_legacy_drive(vms->flash[i],
|
||||
drive_get(IF_PFLASH, 0, i));
|
||||
}
|
||||
|
||||
virt_flash_map(vms, sysmem, secure_sysmem);
|
||||
|
||||
pflash_blk0 = pflash_cfi01_get_blk(vms->flash[0]);
|
||||
|
||||
if (bios_name) {
|
||||
char *fname;
|
||||
MemoryRegion *mr;
|
||||
int image_size;
|
||||
|
||||
if (pflash_blk0) {
|
||||
error_report("The contents of the first flash device may be "
|
||||
"specified with -bios or with -drive if=pflash... "
|
||||
"but you cannot use both options at once");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Fall back to -bios */
|
||||
|
||||
fname = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
||||
if (!fname) {
|
||||
error_report("Could not find ROM image '%s'", bios_name);
|
||||
exit(1);
|
||||
}
|
||||
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(vms->flash[0]), 0);
|
||||
image_size = load_image_mr(fname, mr);
|
||||
g_free(fname);
|
||||
if (image_size < 0) {
|
||||
error_report("Could not load ROM image '%s'", bios_name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return pflash_blk0 || bios_name;
|
||||
}
|
||||
|
||||
static FWCfgState *create_fw_cfg(const VirtMachineState *vms, AddressSpace *as)
|
||||
{
|
||||
hwaddr base = vms->memmap[VIRT_FW_CFG].base;
|
||||
@ -1421,7 +1473,7 @@ static void machvirt_init(MachineState *machine)
|
||||
MemoryRegion *secure_sysmem = NULL;
|
||||
int n, virt_max_cpus;
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
|
||||
bool firmware_loaded;
|
||||
bool aarch64 = true;
|
||||
|
||||
/*
|
||||
@ -1460,6 +1512,27 @@ static void machvirt_init(MachineState *machine)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (vms->secure) {
|
||||
if (kvm_enabled()) {
|
||||
error_report("mach-virt: KVM does not support Security extensions");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* The Secure view of the world is the same as the NonSecure,
|
||||
* but with a few extra devices. Create it as a container region
|
||||
* containing the system memory at low priority; any secure-only
|
||||
* devices go in at higher priority and take precedence.
|
||||
*/
|
||||
secure_sysmem = g_new(MemoryRegion, 1);
|
||||
memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",
|
||||
UINT64_MAX);
|
||||
memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);
|
||||
}
|
||||
|
||||
firmware_loaded = virt_firmware_init(vms, sysmem,
|
||||
secure_sysmem ?: sysmem);
|
||||
|
||||
/* 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
|
||||
@ -1505,23 +1578,6 @@ static void machvirt_init(MachineState *machine)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (vms->secure) {
|
||||
if (kvm_enabled()) {
|
||||
error_report("mach-virt: KVM does not support Security extensions");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The Secure view of the world is the same as the NonSecure,
|
||||
* but with a few extra devices. Create it as a container region
|
||||
* containing the system memory at low priority; any secure-only
|
||||
* devices go in at higher priority and take precedence.
|
||||
*/
|
||||
secure_sysmem = g_new(MemoryRegion, 1);
|
||||
memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",
|
||||
UINT64_MAX);
|
||||
memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);
|
||||
}
|
||||
|
||||
create_fdt(vms);
|
||||
|
||||
possible_cpus = mc->possible_cpu_arch_ids(machine);
|
||||
@ -1610,7 +1666,7 @@ static void machvirt_init(MachineState *machine)
|
||||
&machine->device_memory->mr);
|
||||
}
|
||||
|
||||
create_flash(vms, sysmem, secure_sysmem ? secure_sysmem : sysmem);
|
||||
virt_flash_fdt(vms, sysmem, secure_sysmem);
|
||||
|
||||
create_gic(vms, pic);
|
||||
|
||||
@ -1956,6 +2012,8 @@ static void virt_instance_init(Object *obj)
|
||||
NULL);
|
||||
|
||||
vms->irqmap = a15irqmap;
|
||||
|
||||
virt_flash_create(vms);
|
||||
}
|
||||
|
||||
static const TypeInfo virt_machine_info = {
|
||||
|
@ -44,9 +44,12 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/option.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "trace.h"
|
||||
|
||||
@ -968,6 +971,31 @@ MemoryRegion *pflash_cfi01_get_memory(PFlashCFI01 *fl)
|
||||
return &fl->mem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle -drive if=pflash for machines that use properties.
|
||||
* If @dinfo is null, do nothing.
|
||||
* Else if @fl's property "drive" is already set, fatal error.
|
||||
* Else set it to the BlockBackend with @dinfo.
|
||||
*/
|
||||
void pflash_cfi01_legacy_drive(PFlashCFI01 *fl, DriveInfo *dinfo)
|
||||
{
|
||||
Location loc;
|
||||
|
||||
if (!dinfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
loc_push_none(&loc);
|
||||
qemu_opts_loc_restore(dinfo->opts);
|
||||
if (fl->blk) {
|
||||
error_report("clashes with -machine");
|
||||
exit(1);
|
||||
}
|
||||
qdev_prop_set_drive(DEVICE(fl), "drive",
|
||||
blk_by_legacy_dinfo(dinfo), &error_fatal);
|
||||
loc_pop(&loc);
|
||||
}
|
||||
|
||||
static void postload_update_cb(void *opaque, int running, RunState state)
|
||||
{
|
||||
PFlashCFI01 *pfl = opaque;
|
||||
|
@ -269,9 +269,7 @@ void pc_system_firmware_init(PCMachineState *pcms,
|
||||
{
|
||||
PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
|
||||
int i;
|
||||
DriveInfo *pflash_drv;
|
||||
BlockBackend *pflash_blk[ARRAY_SIZE(pcms->flash)];
|
||||
Location loc;
|
||||
|
||||
if (!pcmc->pci_enabled) {
|
||||
old_pc_system_rom_init(rom_memory, true);
|
||||
@ -280,21 +278,9 @@ void pc_system_firmware_init(PCMachineState *pcms,
|
||||
|
||||
/* Map legacy -drive if=pflash to machine properties */
|
||||
for (i = 0; i < ARRAY_SIZE(pcms->flash); i++) {
|
||||
pflash_cfi01_legacy_drive(pcms->flash[i],
|
||||
drive_get(IF_PFLASH, 0, i));
|
||||
pflash_blk[i] = pflash_cfi01_get_blk(pcms->flash[i]);
|
||||
pflash_drv = drive_get(IF_PFLASH, 0, i);
|
||||
if (!pflash_drv) {
|
||||
continue;
|
||||
}
|
||||
loc_push_none(&loc);
|
||||
qemu_opts_loc_restore(pflash_drv->opts);
|
||||
if (pflash_blk[i]) {
|
||||
error_report("clashes with -machine");
|
||||
exit(1);
|
||||
}
|
||||
pflash_blk[i] = blk_by_legacy_dinfo(pflash_drv);
|
||||
qdev_prop_set_drive(DEVICE(pcms->flash[i]),
|
||||
"drive", pflash_blk[i], &error_fatal);
|
||||
loc_pop(&loc);
|
||||
}
|
||||
|
||||
/* Reject gaps */
|
||||
|
@ -213,6 +213,7 @@ static void nvic_recompute_state_secure(NVICState *s)
|
||||
int active_prio = NVIC_NOEXC_PRIO;
|
||||
int pend_irq = 0;
|
||||
bool pending_is_s_banked = false;
|
||||
int pend_subprio = 0;
|
||||
|
||||
/* R_CQRV: precedence is by:
|
||||
* - lowest group priority; if both the same then
|
||||
@ -226,7 +227,7 @@ static void nvic_recompute_state_secure(NVICState *s)
|
||||
for (i = 1; i < s->num_irq; i++) {
|
||||
for (bank = M_REG_S; bank >= M_REG_NS; bank--) {
|
||||
VecInfo *vec;
|
||||
int prio;
|
||||
int prio, subprio;
|
||||
bool targets_secure;
|
||||
|
||||
if (bank == M_REG_S) {
|
||||
@ -241,8 +242,12 @@ static void nvic_recompute_state_secure(NVICState *s)
|
||||
}
|
||||
|
||||
prio = exc_group_prio(s, vec->prio, targets_secure);
|
||||
if (vec->enabled && vec->pending && prio < pend_prio) {
|
||||
subprio = vec->prio & ~nvic_gprio_mask(s, targets_secure);
|
||||
if (vec->enabled && vec->pending &&
|
||||
((prio < pend_prio) ||
|
||||
(prio == pend_prio && prio >= 0 && subprio < pend_subprio))) {
|
||||
pend_prio = prio;
|
||||
pend_subprio = subprio;
|
||||
pend_irq = i;
|
||||
pending_is_s_banked = (bank == M_REG_S);
|
||||
}
|
||||
@ -1162,6 +1167,10 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
}
|
||||
if (!attrs.secure &&
|
||||
!(s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
|
||||
return 0;
|
||||
}
|
||||
return cpu->env.v7m.bfar;
|
||||
case 0xd3c: /* Aux Fault Status. */
|
||||
/* TODO: Implement fault status registers. */
|
||||
@ -1641,6 +1650,10 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
|
||||
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
|
||||
goto bad_offset;
|
||||
}
|
||||
if (!attrs.secure &&
|
||||
!(s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
|
||||
return;
|
||||
}
|
||||
cpu->env.v7m.bfar = value;
|
||||
return;
|
||||
case 0xd3c: /* Aux Fault Status. */
|
||||
@ -2125,11 +2138,18 @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
|
||||
val = 0;
|
||||
break;
|
||||
};
|
||||
/* The BFSR bits [15:8] are shared between security states
|
||||
* and we store them in the NS copy
|
||||
/*
|
||||
* The BFSR bits [15:8] are shared between security states
|
||||
* and we store them in the NS copy. They are RAZ/WI for
|
||||
* NS code if AIRCR.BFHFNMINS is 0.
|
||||
*/
|
||||
val = s->cpu->env.v7m.cfsr[attrs.secure];
|
||||
val |= s->cpu->env.v7m.cfsr[M_REG_NS] & R_V7M_CFSR_BFSR_MASK;
|
||||
if (!attrs.secure &&
|
||||
!(s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
|
||||
val &= ~R_V7M_CFSR_BFSR_MASK;
|
||||
} else {
|
||||
val |= s->cpu->env.v7m.cfsr[M_REG_NS] & R_V7M_CFSR_BFSR_MASK;
|
||||
}
|
||||
val = extract32(val, (offset - 0xd28) * 8, size * 8);
|
||||
break;
|
||||
case 0xfe0 ... 0xfff: /* ID. */
|
||||
@ -2244,6 +2264,12 @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
|
||||
*/
|
||||
value <<= ((offset - 0xd28) * 8);
|
||||
|
||||
if (!attrs.secure &&
|
||||
!(s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
|
||||
/* BFSR bits are RAZ/WI for NS if BFHFNMINS is set */
|
||||
value &= ~R_V7M_CFSR_BFSR_MASK;
|
||||
}
|
||||
|
||||
s->cpu->env.v7m.cfsr[attrs.secure] &= ~value;
|
||||
if (attrs.secure) {
|
||||
/* The BFSR bits [15:8] are shared between security states
|
||||
@ -2465,10 +2491,12 @@ static void armv7m_nvic_reset(DeviceState *dev)
|
||||
* the System Handler Control register
|
||||
*/
|
||||
s->vectors[ARMV7M_EXCP_SVC].enabled = 1;
|
||||
s->vectors[ARMV7M_EXCP_DEBUG].enabled = 1;
|
||||
s->vectors[ARMV7M_EXCP_PENDSV].enabled = 1;
|
||||
s->vectors[ARMV7M_EXCP_SYSTICK].enabled = 1;
|
||||
|
||||
/* DebugMonitor is enabled via DEMCR.MON_EN */
|
||||
s->vectors[ARMV7M_EXCP_DEBUG].enabled = 0;
|
||||
|
||||
resetprio = arm_feature(&s->cpu->env, ARM_FEATURE_V8) ? -4 : -3;
|
||||
s->vectors[ARMV7M_EXCP_RESET].prio = resetprio;
|
||||
s->vectors[ARMV7M_EXCP_NMI].prio = -2;
|
||||
|
@ -22,6 +22,7 @@ typedef struct AspeedBoardConfig {
|
||||
const char *spi_model;
|
||||
uint32_t num_cs;
|
||||
void (*i2c_init)(AspeedBoardState *bmc);
|
||||
uint32_t ram;
|
||||
} AspeedBoardConfig;
|
||||
|
||||
#define TYPE_ASPEED_MACHINE MACHINE_TYPE_NAME("aspeed")
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "qemu/notify.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/arm/arm.h"
|
||||
#include "hw/block/flash.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "hw/intc/arm_gicv3_common.h"
|
||||
|
||||
@ -113,6 +114,7 @@ typedef struct {
|
||||
Notifier machine_done;
|
||||
DeviceState *platform_bus_dev;
|
||||
FWCfgState *fw_cfg;
|
||||
PFlashCFI01 *flash[2];
|
||||
bool secure;
|
||||
bool highmem;
|
||||
bool highmem_ecam;
|
||||
|
@ -24,6 +24,7 @@ PFlashCFI01 *pflash_cfi01_register(hwaddr base,
|
||||
int be);
|
||||
BlockBackend *pflash_cfi01_get_blk(PFlashCFI01 *fl);
|
||||
MemoryRegion *pflash_cfi01_get_memory(PFlashCFI01 *fl);
|
||||
void pflash_cfi01_legacy_drive(PFlashCFI01 *dev, DriveInfo *dinfo);
|
||||
|
||||
/* pflash_cfi02.c */
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
#define QEMU_SENTINEL __attribute__((sentinel))
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32) && (defined(__x86_64__) || defined(__i386__))
|
||||
# define QEMU_PACKED __attribute__((gcc_struct, packed))
|
||||
#else
|
||||
# define QEMU_PACKED __attribute__((packed))
|
||||
|
@ -85,17 +85,17 @@ extern int daemon(int, int);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later) */
|
||||
#ifdef __MINGW32__
|
||||
#define __USE_MINGW_ANSI_STDIO 1
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later) */
|
||||
#ifdef __MINGW32__
|
||||
#define __USE_MINGW_ANSI_STDIO 1
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string.h>
|
||||
|
@ -457,7 +457,7 @@ void qmp_guest_file_flush(int64_t handle, Error **errp)
|
||||
|
||||
#ifdef CONFIG_QGA_NTDDSCSI
|
||||
|
||||
static STORAGE_BUS_TYPE win2qemu[] = {
|
||||
static GuestDiskBusType win2qemu[] = {
|
||||
[BusTypeUnknown] = GUEST_DISK_BUS_TYPE_UNKNOWN,
|
||||
[BusTypeScsi] = GUEST_DISK_BUS_TYPE_SCSI,
|
||||
[BusTypeAtapi] = GUEST_DISK_BUS_TYPE_IDE,
|
||||
|
@ -23,7 +23,12 @@
|
||||
#define QEMU_NORETURN __attribute__ ((__noreturn__))
|
||||
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
#define QEMU_SENTINEL __attribute__((sentinel))
|
||||
#define QEMU_PACKED __attribute__((gcc_struct, packed))
|
||||
|
||||
#if defined(_WIN32) && (defined(__x86_64__) || defined(__i386__))
|
||||
# define QEMU_PACKED __attribute__((gcc_struct, packed))
|
||||
#else
|
||||
# define QEMU_PACKED __attribute__((packed))
|
||||
#endif
|
||||
|
||||
#define cat(x,y) x ## y
|
||||
#define cat2(x,y) cat(x,y)
|
||||
|
@ -1285,6 +1285,7 @@ static inline uint32_t xpsr_read(CPUARMState *env)
|
||||
| (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
|
||||
| (env->thumb << 24) | ((env->condexec_bits & 3) << 25)
|
||||
| ((env->condexec_bits & 0xfc) << 8)
|
||||
| (env->GE << 16)
|
||||
| env->v7m.exception;
|
||||
}
|
||||
|
||||
@ -1300,6 +1301,9 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
|
||||
if (mask & XPSR_Q) {
|
||||
env->QF = ((val & XPSR_Q) != 0);
|
||||
}
|
||||
if (mask & XPSR_GE) {
|
||||
env->GE = (val & XPSR_GE) >> 16;
|
||||
}
|
||||
if (mask & XPSR_T) {
|
||||
env->thumb = ((val & XPSR_T) != 0);
|
||||
}
|
||||
@ -2610,18 +2614,25 @@ bool write_list_to_cpustate(ARMCPU *cpu);
|
||||
/**
|
||||
* write_cpustate_to_list:
|
||||
* @cpu: ARMCPU
|
||||
* @kvm_sync: true if this is for syncing back to KVM
|
||||
*
|
||||
* For each register listed in the ARMCPU cpreg_indexes list, write
|
||||
* its value from the ARMCPUState structure into the cpreg_values list.
|
||||
* This is used to copy info from TCG's working data structures into
|
||||
* KVM or for outbound migration.
|
||||
*
|
||||
* @kvm_sync is true if we are doing this in order to sync the
|
||||
* register state back to KVM. In this case we will only update
|
||||
* values in the list if the previous list->cpustate sync actually
|
||||
* successfully wrote the CPU state. Otherwise we will keep the value
|
||||
* that is in the list.
|
||||
*
|
||||
* Returns: true if all register values were read correctly,
|
||||
* false if some register was unknown or could not be read.
|
||||
* Note that we do not stop early on failure -- we will attempt
|
||||
* reading all registers in the list.
|
||||
*/
|
||||
bool write_cpustate_to_list(ARMCPU *cpu);
|
||||
bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
|
||||
|
||||
#define ARM_CPUID_TI915T 0x54029152
|
||||
#define ARM_CPUID_TI925T 0x54029252
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/units.h"
|
||||
#include "target/arm/idau.h"
|
||||
#include "trace.h"
|
||||
#include "cpu.h"
|
||||
@ -266,7 +267,7 @@ static bool raw_accessors_invalid(const ARMCPRegInfo *ri)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool write_cpustate_to_list(ARMCPU *cpu)
|
||||
bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync)
|
||||
{
|
||||
/* Write the coprocessor state from cpu->env to the (index,value) list. */
|
||||
int i;
|
||||
@ -275,6 +276,7 @@ bool write_cpustate_to_list(ARMCPU *cpu)
|
||||
for (i = 0; i < cpu->cpreg_array_len; i++) {
|
||||
uint32_t regidx = kvm_to_cpreg_id(cpu->cpreg_indexes[i]);
|
||||
const ARMCPRegInfo *ri;
|
||||
uint64_t newval;
|
||||
|
||||
ri = get_arm_cp_reginfo(cpu->cp_regs, regidx);
|
||||
if (!ri) {
|
||||
@ -284,7 +286,29 @@ bool write_cpustate_to_list(ARMCPU *cpu)
|
||||
if (ri->type & ARM_CP_NO_RAW) {
|
||||
continue;
|
||||
}
|
||||
cpu->cpreg_values[i] = read_raw_cp_reg(&cpu->env, ri);
|
||||
|
||||
newval = read_raw_cp_reg(&cpu->env, ri);
|
||||
if (kvm_sync) {
|
||||
/*
|
||||
* Only sync if the previous list->cpustate sync succeeded.
|
||||
* Rather than tracking the success/failure state for every
|
||||
* item in the list, we just recheck "does the raw write we must
|
||||
* have made in write_list_to_cpustate() read back OK" here.
|
||||
*/
|
||||
uint64_t oldval = cpu->cpreg_values[i];
|
||||
|
||||
if (oldval == newval) {
|
||||
continue;
|
||||
}
|
||||
|
||||
write_raw_cp_reg(&cpu->env, ri, oldval);
|
||||
if (read_raw_cp_reg(&cpu->env, ri) != oldval) {
|
||||
continue;
|
||||
}
|
||||
|
||||
write_raw_cp_reg(&cpu->env, ri, newval);
|
||||
}
|
||||
cpu->cpreg_values[i] = newval;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
@ -8704,7 +8728,7 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
|
||||
{
|
||||
CPUARMState *env = &cpu->env;
|
||||
uint32_t excret;
|
||||
uint32_t xpsr;
|
||||
uint32_t xpsr, xpsr_mask;
|
||||
bool ufault = false;
|
||||
bool sfault = false;
|
||||
bool return_to_sp_process;
|
||||
@ -9156,8 +9180,13 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
|
||||
}
|
||||
*frame_sp_p = frameptr;
|
||||
}
|
||||
|
||||
xpsr_mask = ~(XPSR_SPREALIGN | XPSR_SFPA);
|
||||
if (!arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
|
||||
xpsr_mask &= ~XPSR_GE;
|
||||
}
|
||||
/* This xpsr_write() will invalidate frame_sp_p as it may switch stack */
|
||||
xpsr_write(env, xpsr, ~(XPSR_SPREALIGN | XPSR_SFPA));
|
||||
xpsr_write(env, xpsr, xpsr_mask);
|
||||
|
||||
if (env->v7m.secure) {
|
||||
bool sfpa = xpsr & XPSR_SFPA;
|
||||
@ -12642,6 +12671,9 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
|
||||
}
|
||||
if (!(reg & 4)) {
|
||||
mask |= XPSR_NZCV | XPSR_Q; /* APSR */
|
||||
if (arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
|
||||
mask |= XPSR_GE;
|
||||
}
|
||||
}
|
||||
/* EPSR reads as zero */
|
||||
return xpsr_read(env) & mask;
|
||||
@ -13099,14 +13131,17 @@ void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in)
|
||||
* We know that in fact for any v8 CPU the page size is at least 4K
|
||||
* and the block size must be 2K or less, but TARGET_PAGE_SIZE is only
|
||||
* 1K as an artefact of legacy v5 subpage support being present in the
|
||||
* same QEMU executable.
|
||||
* same QEMU executable. So in practice the hostaddr[] array has
|
||||
* two entries, given the current setting of TARGET_PAGE_BITS_MIN.
|
||||
*/
|
||||
int maxidx = DIV_ROUND_UP(blocklen, TARGET_PAGE_SIZE);
|
||||
void *hostaddr[maxidx];
|
||||
void *hostaddr[DIV_ROUND_UP(2 * KiB, 1 << TARGET_PAGE_BITS_MIN)];
|
||||
int try, i;
|
||||
unsigned mmu_idx = cpu_mmu_index(env, false);
|
||||
TCGMemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
|
||||
|
||||
assert(maxidx <= ARRAY_SIZE(hostaddr));
|
||||
|
||||
for (try = 0; try < 2; try++) {
|
||||
|
||||
for (i = 0; i < maxidx; i++) {
|
||||
|
@ -497,6 +497,14 @@ void kvm_arm_reset_vcpu(ARMCPU *cpu)
|
||||
fprintf(stderr, "write_kvmstate_to_list failed\n");
|
||||
abort();
|
||||
}
|
||||
/*
|
||||
* Sync the reset values also into the CPUState. This is necessary
|
||||
* because the next thing we do will be a kvm_arch_put_registers()
|
||||
* which will update the list values from the CPUState before copying
|
||||
* the list values back to KVM. It's OK to ignore failure returns here
|
||||
* for the same reason we do so in kvm_arch_get_registers().
|
||||
*/
|
||||
write_list_to_cpustate(cpu);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -384,24 +384,8 @@ int kvm_arch_put_registers(CPUState *cs, int level)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Note that we do not call write_cpustate_to_list()
|
||||
* here, so we are only writing the tuple list back to
|
||||
* KVM. This is safe because nothing can change the
|
||||
* CPUARMState cp15 fields (in particular gdb accesses cannot)
|
||||
* and so there are no changes to sync. In fact syncing would
|
||||
* be wrong at this point: for a constant register where TCG and
|
||||
* KVM disagree about its value, the preceding write_list_to_cpustate()
|
||||
* would not have had any effect on the CPUARMState value (since the
|
||||
* register is read-only), and a write_cpustate_to_list() here would
|
||||
* then try to write the TCG value back into KVM -- this would either
|
||||
* fail or incorrectly change the value the guest sees.
|
||||
*
|
||||
* If we ever want to allow the user to modify cp15 registers via
|
||||
* the gdb stub, we would need to be more clever here (for instance
|
||||
* tracking the set of registers kvm_arch_get_registers() successfully
|
||||
* managed to update the CPUARMState with, and only allowing those
|
||||
* to be written back up into the kernel).
|
||||
*/
|
||||
write_cpustate_to_list(cpu, true);
|
||||
|
||||
if (!write_list_to_kvmstate(cpu, level)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
@ -838,6 +838,8 @@ int kvm_arch_put_registers(CPUState *cs, int level)
|
||||
return ret;
|
||||
}
|
||||
|
||||
write_cpustate_to_list(cpu, true);
|
||||
|
||||
if (!write_list_to_kvmstate(cpu, level)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
@ -646,7 +646,7 @@ static int cpu_pre_save(void *opaque)
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
if (!write_cpustate_to_list(cpu)) {
|
||||
if (!write_cpustate_to_list(cpu, false)) {
|
||||
/* This should never fail. */
|
||||
abort();
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ static void sys_cache_info(int *isize, int *dsize)
|
||||
static void arch_cache_info(int *isize, int *dsize)
|
||||
{
|
||||
if (*isize == 0 || *dsize == 0) {
|
||||
unsigned long ctr;
|
||||
uint64_t ctr;
|
||||
|
||||
/* The real cache geometry is in CCSIDR_EL1/CLIDR_EL1/CSSELR_EL1,
|
||||
but (at least under Linux) these are marked protected by the
|
||||
|
Loading…
Reference in New Issue
Block a user