target-arm queue:
* Implement priority handling properly via GICC_APR
  * Enable TZ extensions on the GIC if we're using them
  * Minor preparatory patches for EL3 support
  * cadence_gem: Correct Marvell PHY SPCFC reset value
  * Support AHCI in ZynqMP
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCAAGBQJV7xFhAAoJEDwlJe0UNgzeobsP/iNDaNaLy/KDS2sErdPlHN6W
 1woHq4dP9Kv6DC55KE2lINDd/Y7XeFSz5A2hqVhOqLQMXysfW7gbT1KEWr7nw4Da
 c2fQgPPCsYd1XSB3PXHXJSYP0BgFNjRncvBgM4V/w4cPmETHPqaYBs2gQCm81Sg5
 FnjIKUJlr1DTE4jyJu4wu7lbJIeIS2bZnFqORd6uadoslyu+5yB0NKsEjqB88U+4
 +aRDFo3aSpUBqIy0KGIB73pxCwcHu6bqgmRXiORHt96OIzhMpgPLtwk/wjY3gvi8
 bD04ImGV5aQZpK+feIqj9AjJzL+Lq8hUQXrHT0q9tcBpXMrRjTcHZrdAy4/fJHEL
 sbO13KyVHAINSJAzNHWF+702iEvhc95EEV1mdftZ1EkNkSRnVpSS5mmjxriCLHB/
 t6b5d60Mqbou71LL1DCcbj2eMxRNwjhwfkGfqXxo7DVSORonV2DSRSDqIy+X24gV
 pEfphi3UGL7hDRJwx42nFtW3ezPB5tz0WgDT1eS32H5O2JSr0NRLS49mT6Jqbd4J
 2JWeEzgcRYcRymJMlZANNhL+7CORT7ZzjXRitTheq91pkkcf9SBkl55OI0MXH/JG
 vgqwwLKJiKZLxi1BJUJxvN828udH4EpIB6wc5RV9LAsTVoEftYdpc5O3Us4ae03+
 Dca5VcsBowY00cOIeYe5
 =hLY2
 -----END PGP SIGNATURE-----
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20150908' into staging
target-arm queue:
 * Implement priority handling properly via GICC_APR
 * Enable TZ extensions on the GIC if we're using them
 * Minor preparatory patches for EL3 support
 * cadence_gem: Correct Marvell PHY SPCFC reset value
 * Support AHCI in ZynqMP
# gpg: Signature made Tue 08 Sep 2015 17:48:33 BST using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
* remotes/pmaydell/tags/pull-target-arm-20150908:
  xlnx-zynqmp: Connect the sysbus AHCI to ZynqMP
  xlnx-zynqmp.c: Convert some of the error_propagate() calls to error_abort
  ahci.c: Don't assume AHCIState's parent is AHCIPCIState
  ahci: Separate the AHCI state structure into the header
  cadence_gem: Correct Marvell PHY SPCFC reset value
  target-arm: Add AArch64 access to PAR_EL1
  target-arm: Correct opc1 for AT_S12Exx
  target-arm: Log the target EL when taking exceptions
  target-arm: Fix default_exception_el() function for the case when EL3 is not supported
  hw/arm/virt: Enable TZ extensions on the GIC if we are using them
  hw/arm/virt: Default to not providing TrustZone support
  hw/cpu/{a15mpcore, a9mpcore}: enable TrustZone in GIC if it is enabled in CPUs
  hw/intc/arm_gic_common: Configure IRQs as NS if doing direct NS kernel boot
  hw/arm: new interface for devices which need to behave differently for kernel boot
  qom: Add recursive version of object_child_for_each
  hw/intc/arm_gic: Actually set the active bits for active interrupts
  hw/intc/arm_gic: Drop running_irq and last_active arrays
  hw/intc/arm_gic: Fix handling of GICC_APR<n>, GICC_NSAPR<n> registers
  hw/intc/arm_gic: Running priority is group priority, not full priority
  armv7m_nvic: Implement ICSR without using internal GIC state
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
			
			
This commit is contained in:
		
						commit
						fc04a730b7
					
				| 
						 | 
				
			
			@ -10,6 +10,7 @@
 | 
			
		|||
#include "config.h"
 | 
			
		||||
#include "hw/hw.h"
 | 
			
		||||
#include "hw/arm/arm.h"
 | 
			
		||||
#include "hw/arm/linux-boot-if.h"
 | 
			
		||||
#include "sysemu/sysemu.h"
 | 
			
		||||
#include "hw/boards.h"
 | 
			
		||||
#include "hw/loader.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -555,6 +556,20 @@ static void load_image_to_fw_cfg(FWCfgState *fw_cfg, uint16_t size_key,
 | 
			
		|||
    fw_cfg_add_bytes(fw_cfg, data_key, data, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int do_arm_linux_init(Object *obj, void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    if (object_dynamic_cast(obj, TYPE_ARM_LINUX_BOOT_IF)) {
 | 
			
		||||
        ARMLinuxBootIf *albif = ARM_LINUX_BOOT_IF(obj);
 | 
			
		||||
        ARMLinuxBootIfClass *albifc = ARM_LINUX_BOOT_IF_GET_CLASS(obj);
 | 
			
		||||
        struct arm_boot_info *info = opaque;
 | 
			
		||||
 | 
			
		||||
        if (albifc->arm_linux_init) {
 | 
			
		||||
            albifc->arm_linux_init(albif, info->secure_boot);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void arm_load_kernel_notify(Notifier *notifier, void *data)
 | 
			
		||||
{
 | 
			
		||||
    CPUState *cs;
 | 
			
		||||
| 
						 | 
				
			
			@ -778,6 +793,12 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
 | 
			
		|||
        if (info->nb_cpus > 1) {
 | 
			
		||||
            info->write_secondary_boot(cpu, info);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Notify devices which need to fake up firmware initialization
 | 
			
		||||
         * that we're doing a direct kernel boot.
 | 
			
		||||
         */
 | 
			
		||||
        object_child_foreach_recursive(object_get_root(),
 | 
			
		||||
                                       do_arm_linux_init, info);
 | 
			
		||||
    }
 | 
			
		||||
    info->is_linux = is_linux;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -803,3 +824,16 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
 | 
			
		|||
        qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo arm_linux_boot_if_info = {
 | 
			
		||||
    .name = TYPE_ARM_LINUX_BOOT_IF,
 | 
			
		||||
    .parent = TYPE_INTERFACE,
 | 
			
		||||
    .class_size = sizeof(ARMLinuxBootIfClass),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void arm_linux_boot_register_types(void)
 | 
			
		||||
{
 | 
			
		||||
    type_register_static(&arm_linux_boot_if_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type_init(arm_linux_boot_register_types)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -396,7 +396,7 @@ static void create_v2m(VirtBoardInfo *vbi, qemu_irq *pic)
 | 
			
		|||
    fdt_add_v2m_gic_node(vbi);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic)
 | 
			
		||||
static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, bool secure)
 | 
			
		||||
{
 | 
			
		||||
    /* We create a standalone GIC v2 */
 | 
			
		||||
    DeviceState *gicdev;
 | 
			
		||||
| 
						 | 
				
			
			@ -413,6 +413,9 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic)
 | 
			
		|||
     * interrupts; there are always 32 of the former (mandated by GIC spec).
 | 
			
		||||
     */
 | 
			
		||||
    qdev_prop_set_uint32(gicdev, "num-irq", NUM_IRQS + 32);
 | 
			
		||||
    if (!kvm_irqchip_in_kernel()) {
 | 
			
		||||
        qdev_prop_set_bit(gicdev, "has-security-extensions", secure);
 | 
			
		||||
    }
 | 
			
		||||
    qdev_init_nofail(gicdev);
 | 
			
		||||
    gicbusdev = SYS_BUS_DEVICE(gicdev);
 | 
			
		||||
    sysbus_mmio_map(gicbusdev, 0, vbi->memmap[VIRT_GIC_DIST].base);
 | 
			
		||||
| 
						 | 
				
			
			@ -967,7 +970,7 @@ static void machvirt_init(MachineState *machine)
 | 
			
		|||
 | 
			
		||||
    create_flash(vbi);
 | 
			
		||||
 | 
			
		||||
    create_gic(vbi, pic);
 | 
			
		||||
    create_gic(vbi, pic, vms->secure);
 | 
			
		||||
 | 
			
		||||
    create_uart(vbi, pic);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1044,8 +1047,11 @@ static void virt_instance_init(Object *obj)
 | 
			
		|||
{
 | 
			
		||||
    VirtMachineState *vms = VIRT_MACHINE(obj);
 | 
			
		||||
 | 
			
		||||
    /* EL3 is enabled by default on virt */
 | 
			
		||||
    vms->secure = true;
 | 
			
		||||
    /* EL3 is disabled by default on virt: this makes us consistent
 | 
			
		||||
     * between KVM and TCG for this board, and it also allows us to
 | 
			
		||||
     * boot UEFI blobs which assume no TrustZone support.
 | 
			
		||||
     */
 | 
			
		||||
    vms->secure = false;
 | 
			
		||||
    object_property_add_bool(obj, "secure", virt_get_secure,
 | 
			
		||||
                             virt_set_secure, NULL);
 | 
			
		||||
    object_property_set_description(obj, "secure",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,6 +28,10 @@
 | 
			
		|||
#define GIC_DIST_ADDR       0xf9010000
 | 
			
		||||
#define GIC_CPU_ADDR        0xf9020000
 | 
			
		||||
 | 
			
		||||
#define SATA_INTR           133
 | 
			
		||||
#define SATA_ADDR           0xFD0C0000
 | 
			
		||||
#define SATA_NUM_PORTS      2
 | 
			
		||||
 | 
			
		||||
static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
 | 
			
		||||
    0xFF0B0000, 0xFF0C0000, 0xFF0D0000, 0xFF0E0000,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -90,6 +94,9 @@ static void xlnx_zynqmp_init(Object *obj)
 | 
			
		|||
        object_initialize(&s->uart[i], sizeof(s->uart[i]), TYPE_CADENCE_UART);
 | 
			
		||||
        qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus_get_default());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    object_initialize(&s->sata, sizeof(s->sata), TYPE_SYSBUS_AHCI);
 | 
			
		||||
    qdev_set_parent_bus(DEVICE(&s->sata), sysbus_get_default());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
| 
						 | 
				
			
			@ -162,12 +169,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
 | 
			
		|||
        g_free(name);
 | 
			
		||||
 | 
			
		||||
        object_property_set_int(OBJECT(&s->apu_cpu[i]), GIC_BASE_ADDR,
 | 
			
		||||
                                "reset-cbar", &err);
 | 
			
		||||
        if (err) {
 | 
			
		||||
            error_propagate((errp), (err));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
                                "reset-cbar", &error_abort);
 | 
			
		||||
        object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, "realized",
 | 
			
		||||
                                 &err);
 | 
			
		||||
        if (err) {
 | 
			
		||||
| 
						 | 
				
			
			@ -200,12 +202,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
 | 
			
		|||
        g_free(name);
 | 
			
		||||
 | 
			
		||||
        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "reset-hivecs",
 | 
			
		||||
                                 &err);
 | 
			
		||||
        if (err != NULL) {
 | 
			
		||||
            error_propagate(errp, err);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
                                 &error_abort);
 | 
			
		||||
        object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "realized",
 | 
			
		||||
                                 &err);
 | 
			
		||||
        if (err) {
 | 
			
		||||
| 
						 | 
				
			
			@ -250,6 +247,17 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
 | 
			
		|||
        sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
 | 
			
		||||
                           gic_spi[uart_intr[i]]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    object_property_set_int(OBJECT(&s->sata), SATA_NUM_PORTS, "num-ports",
 | 
			
		||||
                            &error_abort);
 | 
			
		||||
    object_property_set_bool(OBJECT(&s->sata), true, "realized", &err);
 | 
			
		||||
    if (err) {
 | 
			
		||||
        error_propagate(errp, err);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->sata), 0, SATA_ADDR);
 | 
			
		||||
    sysbus_connect_irq(SYS_BUS_DEVICE(&s->sata), 0, gic_spi[SATA_INTR]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Property xlnx_zynqmp_props[] = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,10 +52,23 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
 | 
			
		|||
    SysBusDevice *busdev;
 | 
			
		||||
    int i;
 | 
			
		||||
    Error *err = NULL;
 | 
			
		||||
    bool has_el3;
 | 
			
		||||
    Object *cpuobj;
 | 
			
		||||
 | 
			
		||||
    gicdev = DEVICE(&s->gic);
 | 
			
		||||
    qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
 | 
			
		||||
    qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
 | 
			
		||||
 | 
			
		||||
    if (!kvm_irqchip_in_kernel()) {
 | 
			
		||||
        /* Make the GIC's TZ support match the CPUs. We assume that
 | 
			
		||||
         * either all the CPUs have TZ, or none do.
 | 
			
		||||
         */
 | 
			
		||||
        cpuobj = OBJECT(qemu_get_cpu(0));
 | 
			
		||||
        has_el3 = object_property_find(cpuobj, "has_el3", &error_abort) &&
 | 
			
		||||
            object_property_get_bool(cpuobj, "has_el3", &error_abort);
 | 
			
		||||
        qdev_prop_set_bit(gicdev, "has-security-extensions", has_el3);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
 | 
			
		||||
    if (err != NULL) {
 | 
			
		||||
        error_propagate(errp, err);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,6 +49,8 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp)
 | 
			
		|||
                 *wdtbusdev;
 | 
			
		||||
    Error *err = NULL;
 | 
			
		||||
    int i;
 | 
			
		||||
    bool has_el3;
 | 
			
		||||
    Object *cpuobj;
 | 
			
		||||
 | 
			
		||||
    scudev = DEVICE(&s->scu);
 | 
			
		||||
    qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
 | 
			
		||||
| 
						 | 
				
			
			@ -62,6 +64,15 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp)
 | 
			
		|||
    gicdev = DEVICE(&s->gic);
 | 
			
		||||
    qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
 | 
			
		||||
    qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
 | 
			
		||||
 | 
			
		||||
    /* Make the GIC's TZ support match the CPUs. We assume that
 | 
			
		||||
     * either all the CPUs have TZ, or none do.
 | 
			
		||||
     */
 | 
			
		||||
    cpuobj = OBJECT(qemu_get_cpu(0));
 | 
			
		||||
    has_el3 = object_property_find(cpuobj, "has_el3", &error_abort) &&
 | 
			
		||||
        object_property_get_bool(cpuobj, "has_el3", &error_abort);
 | 
			
		||||
    qdev_prop_set_bit(gicdev, "has-security-extensions", has_el3);
 | 
			
		||||
 | 
			
		||||
    object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
 | 
			
		||||
    if (err != NULL) {
 | 
			
		||||
        error_propagate(errp, err);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,6 @@
 | 
			
		|||
#include <hw/pci/msi.h>
 | 
			
		||||
#include <hw/i386/pc.h>
 | 
			
		||||
#include <hw/pci/pci.h>
 | 
			
		||||
#include <hw/sysbus.h>
 | 
			
		||||
 | 
			
		||||
#include "qemu/error-report.h"
 | 
			
		||||
#include "sysemu/block-backend.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -122,9 +121,9 @@ static uint32_t  ahci_port_read(AHCIState *s, int port, int offset)
 | 
			
		|||
 | 
			
		||||
static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
 | 
			
		||||
{
 | 
			
		||||
    AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
 | 
			
		||||
    PCIDevice *pci_dev =
 | 
			
		||||
        (PCIDevice *)object_dynamic_cast(OBJECT(d), TYPE_PCI_DEVICE);
 | 
			
		||||
    DeviceState *dev_state = s->container;
 | 
			
		||||
    PCIDevice *pci_dev = (PCIDevice *) object_dynamic_cast(OBJECT(dev_state),
 | 
			
		||||
                                                           TYPE_PCI_DEVICE);
 | 
			
		||||
 | 
			
		||||
    DPRINTF(0, "raise irq\n");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -137,9 +136,9 @@ static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
 | 
			
		|||
 | 
			
		||||
static void ahci_irq_lower(AHCIState *s, AHCIDevice *dev)
 | 
			
		||||
{
 | 
			
		||||
    AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
 | 
			
		||||
    PCIDevice *pci_dev =
 | 
			
		||||
        (PCIDevice *)object_dynamic_cast(OBJECT(d), TYPE_PCI_DEVICE);
 | 
			
		||||
    DeviceState *dev_state = s->container;
 | 
			
		||||
    PCIDevice *pci_dev = (PCIDevice *) object_dynamic_cast(OBJECT(dev_state),
 | 
			
		||||
                                                           TYPE_PCI_DEVICE);
 | 
			
		||||
 | 
			
		||||
    DPRINTF(0, "lower irq\n");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1437,6 +1436,7 @@ void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports)
 | 
			
		|||
    s->as = as;
 | 
			
		||||
    s->ports = ports;
 | 
			
		||||
    s->dev = g_new0(AHCIDevice, ports);
 | 
			
		||||
    s->container = qdev;
 | 
			
		||||
    ahci_reg_init(s);
 | 
			
		||||
    /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
 | 
			
		||||
    memory_region_init_io(&s->mem, OBJECT(qdev), &ahci_mem_ops, s,
 | 
			
		||||
| 
						 | 
				
			
			@ -1625,18 +1625,6 @@ const VMStateDescription vmstate_ahci = {
 | 
			
		|||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define TYPE_SYSBUS_AHCI "sysbus-ahci"
 | 
			
		||||
#define SYSBUS_AHCI(obj) OBJECT_CHECK(SysbusAHCIState, (obj), TYPE_SYSBUS_AHCI)
 | 
			
		||||
 | 
			
		||||
typedef struct SysbusAHCIState {
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    SysBusDevice parent_obj;
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
 | 
			
		||||
    AHCIState ahci;
 | 
			
		||||
    uint32_t num_ports;
 | 
			
		||||
} SysbusAHCIState;
 | 
			
		||||
 | 
			
		||||
static const VMStateDescription vmstate_sysbus_ahci = {
 | 
			
		||||
    .name = "sysbus-ahci",
 | 
			
		||||
    .fields = (VMStateField[]) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,8 @@
 | 
			
		|||
#ifndef HW_IDE_AHCI_H
 | 
			
		||||
#define HW_IDE_AHCI_H
 | 
			
		||||
 | 
			
		||||
#include <hw/sysbus.h>
 | 
			
		||||
 | 
			
		||||
#define AHCI_MEM_BAR_SIZE         0x1000
 | 
			
		||||
#define AHCI_MAX_PORTS            32
 | 
			
		||||
#define AHCI_MAX_SG               168 /* hardware max is 64K */
 | 
			
		||||
| 
						 | 
				
			
			@ -285,6 +287,8 @@ struct AHCIDevice {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
typedef struct AHCIState {
 | 
			
		||||
    DeviceState *container;
 | 
			
		||||
 | 
			
		||||
    AHCIDevice *dev;
 | 
			
		||||
    AHCIControlRegs control_regs;
 | 
			
		||||
    MemoryRegion mem;
 | 
			
		||||
| 
						 | 
				
			
			@ -369,4 +373,16 @@ void ahci_reset(AHCIState *s);
 | 
			
		|||
 | 
			
		||||
void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd);
 | 
			
		||||
 | 
			
		||||
#define TYPE_SYSBUS_AHCI "sysbus-ahci"
 | 
			
		||||
#define SYSBUS_AHCI(obj) OBJECT_CHECK(SysbusAHCIState, (obj), TYPE_SYSBUS_AHCI)
 | 
			
		||||
 | 
			
		||||
typedef struct SysbusAHCIState {
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    SysBusDevice parent_obj;
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
 | 
			
		||||
    AHCIState ahci;
 | 
			
		||||
    uint32_t num_ports;
 | 
			
		||||
} SysbusAHCIState;
 | 
			
		||||
 | 
			
		||||
#endif /* HW_IDE_AHCI_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -219,15 +219,99 @@ static uint16_t gic_get_current_pending_irq(GICState *s, int cpu,
 | 
			
		|||
    return pending_irq;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gic_set_running_irq(GICState *s, int cpu, int irq)
 | 
			
		||||
static int gic_get_group_priority(GICState *s, int cpu, int irq)
 | 
			
		||||
{
 | 
			
		||||
    s->running_irq[cpu] = irq;
 | 
			
		||||
    if (irq == 1023) {
 | 
			
		||||
        s->running_priority[cpu] = 0x100;
 | 
			
		||||
    /* Return the group priority of the specified interrupt
 | 
			
		||||
     * (which is the top bits of its priority, with the number
 | 
			
		||||
     * of bits masked determined by the applicable binary point register).
 | 
			
		||||
     */
 | 
			
		||||
    int bpr;
 | 
			
		||||
    uint32_t mask;
 | 
			
		||||
 | 
			
		||||
    if (gic_has_groups(s) &&
 | 
			
		||||
        !(s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) &&
 | 
			
		||||
        GIC_TEST_GROUP(irq, (1 << cpu))) {
 | 
			
		||||
        bpr = s->abpr[cpu];
 | 
			
		||||
    } else {
 | 
			
		||||
        s->running_priority[cpu] = GIC_GET_PRIORITY(irq, cpu);
 | 
			
		||||
        bpr = s->bpr[cpu];
 | 
			
		||||
    }
 | 
			
		||||
    gic_update(s);
 | 
			
		||||
 | 
			
		||||
    /* a BPR of 0 means the group priority bits are [7:1];
 | 
			
		||||
     * a BPR of 1 means they are [7:2], and so on down to
 | 
			
		||||
     * a BPR of 7 meaning no group priority bits at all.
 | 
			
		||||
     */
 | 
			
		||||
    mask = ~0U << ((bpr & 7) + 1);
 | 
			
		||||
 | 
			
		||||
    return GIC_GET_PRIORITY(irq, cpu) & mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gic_activate_irq(GICState *s, int cpu, int irq)
 | 
			
		||||
{
 | 
			
		||||
    /* Set the appropriate Active Priority Register bit for this IRQ,
 | 
			
		||||
     * and update the running priority.
 | 
			
		||||
     */
 | 
			
		||||
    int prio = gic_get_group_priority(s, cpu, irq);
 | 
			
		||||
    int preemption_level = prio >> (GIC_MIN_BPR + 1);
 | 
			
		||||
    int regno = preemption_level / 32;
 | 
			
		||||
    int bitno = preemption_level % 32;
 | 
			
		||||
 | 
			
		||||
    if (gic_has_groups(s) && GIC_TEST_GROUP(irq, (1 << cpu))) {
 | 
			
		||||
        s->nsapr[regno][cpu] &= (1 << bitno);
 | 
			
		||||
    } else {
 | 
			
		||||
        s->apr[regno][cpu] &= (1 << bitno);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s->running_priority[cpu] = prio;
 | 
			
		||||
    GIC_SET_ACTIVE(irq, 1 << cpu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int gic_get_prio_from_apr_bits(GICState *s, int cpu)
 | 
			
		||||
{
 | 
			
		||||
    /* Recalculate the current running priority for this CPU based
 | 
			
		||||
     * on the set bits in the Active Priority Registers.
 | 
			
		||||
     */
 | 
			
		||||
    int i;
 | 
			
		||||
    for (i = 0; i < GIC_NR_APRS; i++) {
 | 
			
		||||
        uint32_t apr = s->apr[i][cpu] | s->nsapr[i][cpu];
 | 
			
		||||
        if (!apr) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        return (i * 32 + ctz32(apr)) << (GIC_MIN_BPR + 1);
 | 
			
		||||
    }
 | 
			
		||||
    return 0x100;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gic_drop_prio(GICState *s, int cpu, int group)
 | 
			
		||||
{
 | 
			
		||||
    /* Drop the priority of the currently active interrupt in the
 | 
			
		||||
     * specified group.
 | 
			
		||||
     *
 | 
			
		||||
     * Note that we can guarantee (because of the requirement to nest
 | 
			
		||||
     * GICC_IAR reads [which activate an interrupt and raise priority]
 | 
			
		||||
     * with GICC_EOIR writes [which drop the priority for the interrupt])
 | 
			
		||||
     * that the interrupt we're being called for is the highest priority
 | 
			
		||||
     * active interrupt, meaning that it has the lowest set bit in the
 | 
			
		||||
     * APR registers.
 | 
			
		||||
     *
 | 
			
		||||
     * If the guest does not honour the ordering constraints then the
 | 
			
		||||
     * behaviour of the GIC is UNPREDICTABLE, which for us means that
 | 
			
		||||
     * the values of the APR registers might become incorrect and the
 | 
			
		||||
     * running priority will be wrong, so interrupts that should preempt
 | 
			
		||||
     * might not do so, and interrupts that should not preempt might do so.
 | 
			
		||||
     */
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < GIC_NR_APRS; i++) {
 | 
			
		||||
        uint32_t *papr = group ? &s->nsapr[i][cpu] : &s->apr[i][cpu];
 | 
			
		||||
        if (!*papr) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        /* Clear lowest set bit */
 | 
			
		||||
        *papr &= *papr - 1;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s->running_priority[cpu] = gic_get_prio_from_apr_bits(s, cpu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
 | 
			
		||||
| 
						 | 
				
			
			@ -250,7 +334,6 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
 | 
			
		|||
        DPRINTF("ACK, pending interrupt (%d) has insufficient priority\n", irq);
 | 
			
		||||
        return 1023;
 | 
			
		||||
    }
 | 
			
		||||
    s->last_active[irq][cpu] = s->running_irq[cpu];
 | 
			
		||||
 | 
			
		||||
    if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
 | 
			
		||||
        /* Clear pending flags for both level and edge triggered interrupts.
 | 
			
		||||
| 
						 | 
				
			
			@ -281,7 +364,8 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    gic_set_running_irq(s, cpu, irq);
 | 
			
		||||
    gic_activate_irq(s, cpu, irq);
 | 
			
		||||
    gic_update(s);
 | 
			
		||||
    DPRINTF("ACK %d\n", irq);
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -411,8 +495,9 @@ static uint8_t gic_get_running_priority(GICState *s, int cpu, MemTxAttrs attrs)
 | 
			
		|||
 | 
			
		||||
void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
 | 
			
		||||
{
 | 
			
		||||
    int update = 0;
 | 
			
		||||
    int cm = 1 << cpu;
 | 
			
		||||
    int group;
 | 
			
		||||
 | 
			
		||||
    DPRINTF("EOI %d\n", irq);
 | 
			
		||||
    if (irq >= s->num_irq) {
 | 
			
		||||
        /* This handles two cases:
 | 
			
		||||
| 
						 | 
				
			
			@ -425,8 +510,9 @@ void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
 | 
			
		|||
         */
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (s->running_irq[cpu] == 1023)
 | 
			
		||||
    if (s->running_priority[cpu] == 0x100) {
 | 
			
		||||
        return; /* No active IRQ.  */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
 | 
			
		||||
        /* Mark level triggered interrupts as pending if they are still
 | 
			
		||||
| 
						 | 
				
			
			@ -435,11 +521,12 @@ void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
 | 
			
		|||
            && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
 | 
			
		||||
            DPRINTF("Set %d pending mask %x\n", irq, cm);
 | 
			
		||||
            GIC_SET_PENDING(irq, cm);
 | 
			
		||||
            update = 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (s->security_extn && !attrs.secure && !GIC_TEST_GROUP(irq, cm)) {
 | 
			
		||||
    group = gic_has_groups(s) && GIC_TEST_GROUP(irq, cm);
 | 
			
		||||
 | 
			
		||||
    if (s->security_extn && !attrs.secure && !group) {
 | 
			
		||||
        DPRINTF("Non-secure EOI for Group0 interrupt %d ignored\n", irq);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -449,23 +536,9 @@ void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
 | 
			
		|||
     * i.e. go ahead and complete the irq anyway.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    if (irq != s->running_irq[cpu]) {
 | 
			
		||||
        /* Complete an IRQ that is not currently running.  */
 | 
			
		||||
        int tmp = s->running_irq[cpu];
 | 
			
		||||
        while (s->last_active[tmp][cpu] != 1023) {
 | 
			
		||||
            if (s->last_active[tmp][cpu] == irq) {
 | 
			
		||||
                s->last_active[tmp][cpu] = s->last_active[irq][cpu];
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            tmp = s->last_active[tmp][cpu];
 | 
			
		||||
        }
 | 
			
		||||
        if (update) {
 | 
			
		||||
            gic_update(s);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        /* Complete the current running IRQ.  */
 | 
			
		||||
        gic_set_running_irq(s, cpu, s->last_active[s->running_irq[cpu]][cpu]);
 | 
			
		||||
    }
 | 
			
		||||
    gic_drop_prio(s, cpu, group);
 | 
			
		||||
    GIC_CLEAR_ACTIVE(irq, cm);
 | 
			
		||||
    gic_update(s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
 | 
			
		||||
| 
						 | 
				
			
			@ -922,6 +995,68 @@ static MemTxResult gic_dist_write(void *opaque, hwaddr offset, uint64_t data,
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline uint32_t gic_apr_ns_view(GICState *s, int cpu, int regno)
 | 
			
		||||
{
 | 
			
		||||
    /* Return the Nonsecure view of GICC_APR<regno>. This is the
 | 
			
		||||
     * second half of GICC_NSAPR.
 | 
			
		||||
     */
 | 
			
		||||
    switch (GIC_MIN_BPR) {
 | 
			
		||||
    case 0:
 | 
			
		||||
        if (regno < 2) {
 | 
			
		||||
            return s->nsapr[regno + 2][cpu];
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 1:
 | 
			
		||||
        if (regno == 0) {
 | 
			
		||||
            return s->nsapr[regno + 1][cpu];
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 2:
 | 
			
		||||
        if (regno == 0) {
 | 
			
		||||
            return extract32(s->nsapr[0][cpu], 16, 16);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 3:
 | 
			
		||||
        if (regno == 0) {
 | 
			
		||||
            return extract32(s->nsapr[0][cpu], 8, 8);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        g_assert_not_reached();
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void gic_apr_write_ns_view(GICState *s, int cpu, int regno,
 | 
			
		||||
                                         uint32_t value)
 | 
			
		||||
{
 | 
			
		||||
    /* Write the Nonsecure view of GICC_APR<regno>. */
 | 
			
		||||
    switch (GIC_MIN_BPR) {
 | 
			
		||||
    case 0:
 | 
			
		||||
        if (regno < 2) {
 | 
			
		||||
            s->nsapr[regno + 2][cpu] = value;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 1:
 | 
			
		||||
        if (regno == 0) {
 | 
			
		||||
            s->nsapr[regno + 1][cpu] = value;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 2:
 | 
			
		||||
        if (regno == 0) {
 | 
			
		||||
            s->nsapr[0][cpu] = deposit32(s->nsapr[0][cpu], 16, 16, value);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 3:
 | 
			
		||||
        if (regno == 0) {
 | 
			
		||||
            s->nsapr[0][cpu] = deposit32(s->nsapr[0][cpu], 8, 8, value);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        g_assert_not_reached();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset,
 | 
			
		||||
                                uint64_t *data, MemTxAttrs attrs)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -962,8 +1097,31 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset,
 | 
			
		|||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 0xd0: case 0xd4: case 0xd8: case 0xdc:
 | 
			
		||||
        *data = s->apr[(offset - 0xd0) / 4][cpu];
 | 
			
		||||
    {
 | 
			
		||||
        int regno = (offset - 0xd0) / 4;
 | 
			
		||||
 | 
			
		||||
        if (regno >= GIC_NR_APRS || s->revision != 2) {
 | 
			
		||||
            *data = 0;
 | 
			
		||||
        } else if (s->security_extn && !attrs.secure) {
 | 
			
		||||
            /* NS view of GICC_APR<n> is the top half of GIC_NSAPR<n> */
 | 
			
		||||
            *data = gic_apr_ns_view(s, regno, cpu);
 | 
			
		||||
        } else {
 | 
			
		||||
            *data = s->apr[regno][cpu];
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    case 0xe0: case 0xe4: case 0xe8: case 0xec:
 | 
			
		||||
    {
 | 
			
		||||
        int regno = (offset - 0xe0) / 4;
 | 
			
		||||
 | 
			
		||||
        if (regno >= GIC_NR_APRS || s->revision != 2 || !gic_has_groups(s) ||
 | 
			
		||||
            (s->security_extn && !attrs.secure)) {
 | 
			
		||||
            *data = 0;
 | 
			
		||||
        } else {
 | 
			
		||||
            *data = s->nsapr[regno][cpu];
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    default:
 | 
			
		||||
        qemu_log_mask(LOG_GUEST_ERROR,
 | 
			
		||||
                      "gic_cpu_read: Bad offset %x\n", (int)offset);
 | 
			
		||||
| 
						 | 
				
			
			@ -1001,8 +1159,33 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset,
 | 
			
		|||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 0xd0: case 0xd4: case 0xd8: case 0xdc:
 | 
			
		||||
        qemu_log_mask(LOG_UNIMP, "Writing APR not implemented\n");
 | 
			
		||||
    {
 | 
			
		||||
        int regno = (offset - 0xd0) / 4;
 | 
			
		||||
 | 
			
		||||
        if (regno >= GIC_NR_APRS || s->revision != 2) {
 | 
			
		||||
            return MEMTX_OK;
 | 
			
		||||
        }
 | 
			
		||||
        if (s->security_extn && !attrs.secure) {
 | 
			
		||||
            /* NS view of GICC_APR<n> is the top half of GIC_NSAPR<n> */
 | 
			
		||||
            gic_apr_write_ns_view(s, regno, cpu, value);
 | 
			
		||||
        } else {
 | 
			
		||||
            s->apr[regno][cpu] = value;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    case 0xe0: case 0xe4: case 0xe8: case 0xec:
 | 
			
		||||
    {
 | 
			
		||||
        int regno = (offset - 0xe0) / 4;
 | 
			
		||||
 | 
			
		||||
        if (regno >= GIC_NR_APRS || s->revision != 2) {
 | 
			
		||||
            return MEMTX_OK;
 | 
			
		||||
        }
 | 
			
		||||
        if (!gic_has_groups(s) || (s->security_extn && !attrs.secure)) {
 | 
			
		||||
            return MEMTX_OK;
 | 
			
		||||
        }
 | 
			
		||||
        s->nsapr[regno][cpu] = value;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    default:
 | 
			
		||||
        qemu_log_mask(LOG_GUEST_ERROR,
 | 
			
		||||
                      "gic_cpu_write: Bad offset %x\n", (int)offset);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
#include "gic_internal.h"
 | 
			
		||||
#include "hw/arm/linux-boot-if.h"
 | 
			
		||||
 | 
			
		||||
static void gic_pre_save(void *opaque)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -59,8 +60,8 @@ static const VMStateDescription vmstate_gic_irq_state = {
 | 
			
		|||
 | 
			
		||||
static const VMStateDescription vmstate_gic = {
 | 
			
		||||
    .name = "arm_gic",
 | 
			
		||||
    .version_id = 10,
 | 
			
		||||
    .minimum_version_id = 10,
 | 
			
		||||
    .version_id = 12,
 | 
			
		||||
    .minimum_version_id = 12,
 | 
			
		||||
    .pre_save = gic_pre_save,
 | 
			
		||||
    .post_load = gic_post_load,
 | 
			
		||||
    .fields = (VMStateField[]) {
 | 
			
		||||
| 
						 | 
				
			
			@ -71,15 +72,14 @@ static const VMStateDescription vmstate_gic = {
 | 
			
		|||
        VMSTATE_UINT8_ARRAY(irq_target, GICState, GIC_MAXIRQ),
 | 
			
		||||
        VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, GIC_NCPU),
 | 
			
		||||
        VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL),
 | 
			
		||||
        VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, GIC_NCPU),
 | 
			
		||||
        VMSTATE_UINT8_2DARRAY(sgi_pending, GICState, GIC_NR_SGIS, GIC_NCPU),
 | 
			
		||||
        VMSTATE_UINT16_ARRAY(priority_mask, GICState, GIC_NCPU),
 | 
			
		||||
        VMSTATE_UINT16_ARRAY(running_irq, GICState, GIC_NCPU),
 | 
			
		||||
        VMSTATE_UINT16_ARRAY(running_priority, GICState, GIC_NCPU),
 | 
			
		||||
        VMSTATE_UINT16_ARRAY(current_pending, GICState, GIC_NCPU),
 | 
			
		||||
        VMSTATE_UINT8_ARRAY(bpr, GICState, GIC_NCPU),
 | 
			
		||||
        VMSTATE_UINT8_ARRAY(abpr, GICState, GIC_NCPU),
 | 
			
		||||
        VMSTATE_UINT32_2DARRAY(apr, GICState, GIC_NR_APRS, GIC_NCPU),
 | 
			
		||||
        VMSTATE_UINT32_2DARRAY(nsapr, GICState, GIC_NR_APRS, GIC_NCPU),
 | 
			
		||||
        VMSTATE_END_OF_LIST()
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -165,21 +165,35 @@ static void arm_gic_common_reset(DeviceState *dev)
 | 
			
		|||
{
 | 
			
		||||
    GICState *s = ARM_GIC_COMMON(dev);
 | 
			
		||||
    int i, j;
 | 
			
		||||
    int resetprio;
 | 
			
		||||
 | 
			
		||||
    /* If we're resetting a TZ-aware GIC as if secure firmware
 | 
			
		||||
     * had set it up ready to start a kernel in non-secure,
 | 
			
		||||
     * we need to set interrupt priorities to a "zero for the
 | 
			
		||||
     * NS view" value. This is particularly critical for the
 | 
			
		||||
     * priority_mask[] values, because if they are zero then NS
 | 
			
		||||
     * code cannot ever rewrite the priority to anything else.
 | 
			
		||||
     */
 | 
			
		||||
    if (s->security_extn && s->irq_reset_nonsecure) {
 | 
			
		||||
        resetprio = 0x80;
 | 
			
		||||
    } else {
 | 
			
		||||
        resetprio = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
 | 
			
		||||
    for (i = 0 ; i < s->num_cpu; i++) {
 | 
			
		||||
        if (s->revision == REV_11MPCORE) {
 | 
			
		||||
            s->priority_mask[i] = 0xf0;
 | 
			
		||||
        } else {
 | 
			
		||||
            s->priority_mask[i] = 0;
 | 
			
		||||
            s->priority_mask[i] = resetprio;
 | 
			
		||||
        }
 | 
			
		||||
        s->current_pending[i] = 1023;
 | 
			
		||||
        s->running_irq[i] = 1023;
 | 
			
		||||
        s->running_priority[i] = 0x100;
 | 
			
		||||
        s->cpu_ctlr[i] = 0;
 | 
			
		||||
        s->bpr[i] = GIC_MIN_BPR;
 | 
			
		||||
        s->abpr[i] = GIC_MIN_ABPR;
 | 
			
		||||
        for (j = 0; j < GIC_INTERNAL; j++) {
 | 
			
		||||
            s->priority1[j][i] = 0;
 | 
			
		||||
            s->priority1[j][i] = resetprio;
 | 
			
		||||
        }
 | 
			
		||||
        for (j = 0; j < GIC_NR_SGIS; j++) {
 | 
			
		||||
            s->sgi_pending[j][i] = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -191,7 +205,7 @@ static void arm_gic_common_reset(DeviceState *dev)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < ARRAY_SIZE(s->priority2); i++) {
 | 
			
		||||
        s->priority2[i] = 0;
 | 
			
		||||
        s->priority2[i] = resetprio;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < GIC_MAXIRQ; i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -202,9 +216,32 @@ static void arm_gic_common_reset(DeviceState *dev)
 | 
			
		|||
            s->irq_target[i] = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (s->security_extn && s->irq_reset_nonsecure) {
 | 
			
		||||
        for (i = 0; i < GIC_MAXIRQ; i++) {
 | 
			
		||||
            GIC_SET_GROUP(i, ALL_CPU_MASK);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s->ctlr = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void arm_gic_common_linux_init(ARMLinuxBootIf *obj,
 | 
			
		||||
                                      bool secure_boot)
 | 
			
		||||
{
 | 
			
		||||
    GICState *s = ARM_GIC_COMMON(obj);
 | 
			
		||||
 | 
			
		||||
    if (s->security_extn && !secure_boot) {
 | 
			
		||||
        /* We're directly booting a kernel into NonSecure. If this GIC
 | 
			
		||||
         * implements the security extensions then we must configure it
 | 
			
		||||
         * to have all the interrupts be NonSecure (this is a job that
 | 
			
		||||
         * is done by the Secure boot firmware in real hardware, and in
 | 
			
		||||
         * this mode QEMU is acting as a minimalist firmware-and-bootloader
 | 
			
		||||
         * equivalent).
 | 
			
		||||
         */
 | 
			
		||||
        s->irq_reset_nonsecure = true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Property arm_gic_common_properties[] = {
 | 
			
		||||
    DEFINE_PROP_UINT32("num-cpu", GICState, num_cpu, 1),
 | 
			
		||||
    DEFINE_PROP_UINT32("num-irq", GICState, num_irq, 32),
 | 
			
		||||
| 
						 | 
				
			
			@ -221,11 +258,13 @@ static Property arm_gic_common_properties[] = {
 | 
			
		|||
static void arm_gic_common_class_init(ObjectClass *klass, void *data)
 | 
			
		||||
{
 | 
			
		||||
    DeviceClass *dc = DEVICE_CLASS(klass);
 | 
			
		||||
    ARMLinuxBootIfClass *albifc = ARM_LINUX_BOOT_IF_CLASS(klass);
 | 
			
		||||
 | 
			
		||||
    dc->reset = arm_gic_common_reset;
 | 
			
		||||
    dc->realize = arm_gic_common_realize;
 | 
			
		||||
    dc->props = arm_gic_common_properties;
 | 
			
		||||
    dc->vmsd = &vmstate_gic;
 | 
			
		||||
    albifc->arm_linux_init = arm_gic_common_linux_init;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const TypeInfo arm_gic_common_type = {
 | 
			
		||||
| 
						 | 
				
			
			@ -235,6 +274,10 @@ static const TypeInfo arm_gic_common_type = {
 | 
			
		|||
    .class_size = sizeof(ARMGICCommonClass),
 | 
			
		||||
    .class_init = arm_gic_common_class_init,
 | 
			
		||||
    .abstract = true,
 | 
			
		||||
    .interfaces = (InterfaceInfo []) {
 | 
			
		||||
        { TYPE_ARM_LINUX_BOOT_IF },
 | 
			
		||||
        { },
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void register_types(void)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -185,26 +185,25 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
 | 
			
		|||
        return cpu->midr;
 | 
			
		||||
    case 0xd04: /* Interrupt Control State.  */
 | 
			
		||||
        /* VECTACTIVE */
 | 
			
		||||
        val = s->gic.running_irq[0];
 | 
			
		||||
        cpu = ARM_CPU(current_cpu);
 | 
			
		||||
        val = cpu->env.v7m.exception;
 | 
			
		||||
        if (val == 1023) {
 | 
			
		||||
            val = 0;
 | 
			
		||||
        } else if (val >= 32) {
 | 
			
		||||
            val -= 16;
 | 
			
		||||
        }
 | 
			
		||||
        /* RETTOBASE */
 | 
			
		||||
        if (s->gic.running_irq[0] == 1023
 | 
			
		||||
                || s->gic.last_active[s->gic.running_irq[0]][0] == 1023) {
 | 
			
		||||
            val |= (1 << 11);
 | 
			
		||||
        }
 | 
			
		||||
        /* VECTPENDING */
 | 
			
		||||
        if (s->gic.current_pending[0] != 1023)
 | 
			
		||||
            val |= (s->gic.current_pending[0] << 12);
 | 
			
		||||
        /* ISRPENDING */
 | 
			
		||||
        /* ISRPENDING and RETTOBASE */
 | 
			
		||||
        for (irq = 32; irq < s->num_irq; irq++) {
 | 
			
		||||
            if (s->gic.irq_state[irq].pending) {
 | 
			
		||||
                val |= (1 << 22);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            if (irq != cpu->env.v7m.exception && s->gic.irq_state[irq].active) {
 | 
			
		||||
                val |= (1 << 11);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        /* PENDSTSET */
 | 
			
		||||
        if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -951,7 +951,7 @@ static void gem_phy_reset(CadenceGEMState *s)
 | 
			
		|||
    s->phy_regs[PHY_REG_1000BTSTAT] = 0x7C00;
 | 
			
		||||
    s->phy_regs[PHY_REG_EXTSTAT] = 0x3000;
 | 
			
		||||
    s->phy_regs[PHY_REG_PHYSPCFC_CTL] = 0x0078;
 | 
			
		||||
    s->phy_regs[PHY_REG_PHYSPCFC_ST] = 0xBC00;
 | 
			
		||||
    s->phy_regs[PHY_REG_PHYSPCFC_ST] = 0x7C00;
 | 
			
		||||
    s->phy_regs[PHY_REG_EXT_PHYSPCFC_CTL] = 0x0C60;
 | 
			
		||||
    s->phy_regs[PHY_REG_LED] = 0x4100;
 | 
			
		||||
    s->phy_regs[PHY_REG_EXT_PHYSPCFC_CTL2] = 0x000A;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
/*
 | 
			
		||||
 * hw/arm/linux-boot-if.h : interface for devices which need to behave
 | 
			
		||||
 * specially for direct boot of an ARM Linux kernel
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef HW_ARM_LINUX_BOOT_IF_H
 | 
			
		||||
#define HW_ARM_LINUX_BOOT_IF_H
 | 
			
		||||
 | 
			
		||||
#include "qom/object.h"
 | 
			
		||||
 | 
			
		||||
#define TYPE_ARM_LINUX_BOOT_IF "arm-linux-boot-if"
 | 
			
		||||
#define ARM_LINUX_BOOT_IF_CLASS(klass) \
 | 
			
		||||
    OBJECT_CLASS_CHECK(ARMLinuxBootIfClass, (klass), TYPE_ARM_LINUX_BOOT_IF)
 | 
			
		||||
#define ARM_LINUX_BOOT_IF_GET_CLASS(obj) \
 | 
			
		||||
    OBJECT_GET_CLASS(ARMLinuxBootIfClass, (obj), TYPE_ARM_LINUX_BOOT_IF)
 | 
			
		||||
#define ARM_LINUX_BOOT_IF(obj) \
 | 
			
		||||
    INTERFACE_CHECK(ARMLinuxBootIf, (obj), TYPE_ARM_LINUX_BOOT_IF)
 | 
			
		||||
 | 
			
		||||
typedef struct ARMLinuxBootIf {
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    Object parent_obj;
 | 
			
		||||
} ARMLinuxBootIf;
 | 
			
		||||
 | 
			
		||||
typedef struct ARMLinuxBootIfClass {
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    InterfaceClass parent_class;
 | 
			
		||||
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
    /** arm_linux_init: configure the device for a direct boot
 | 
			
		||||
     * of an ARM Linux kernel (so that device reset puts it into
 | 
			
		||||
     * the state the kernel expects after firmware initialization,
 | 
			
		||||
     * rather than the true hardware reset state). This callback is
 | 
			
		||||
     * called once after machine construction is complete (before the
 | 
			
		||||
     * first system reset).
 | 
			
		||||
     *
 | 
			
		||||
     * @obj: the object implementing this interface
 | 
			
		||||
     * @secure_boot: true if we are booting Secure, false for NonSecure
 | 
			
		||||
     * (or for a CPU which doesn't support TrustZone)
 | 
			
		||||
     */
 | 
			
		||||
    void (*arm_linux_init)(ARMLinuxBootIf *obj, bool secure_boot);
 | 
			
		||||
} ARMLinuxBootIfClass;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -22,6 +22,8 @@
 | 
			
		|||
#include "hw/intc/arm_gic.h"
 | 
			
		||||
#include "hw/net/cadence_gem.h"
 | 
			
		||||
#include "hw/char/cadence_uart.h"
 | 
			
		||||
#include "hw/ide/pci.h"
 | 
			
		||||
#include "hw/ide/ahci.h"
 | 
			
		||||
 | 
			
		||||
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
 | 
			
		||||
#define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
 | 
			
		||||
| 
						 | 
				
			
			@ -60,6 +62,7 @@ typedef struct XlnxZynqMPState {
 | 
			
		|||
 | 
			
		||||
    CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
 | 
			
		||||
    CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
 | 
			
		||||
    SysbusAHCIState sata;
 | 
			
		||||
 | 
			
		||||
    char *boot_cpu;
 | 
			
		||||
    ARMCPU *boot_cpu_ptr;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,7 +68,6 @@ typedef struct GICState {
 | 
			
		|||
    uint8_t irq_target[GIC_MAXIRQ];
 | 
			
		||||
    uint8_t priority1[GIC_INTERNAL][GIC_NCPU];
 | 
			
		||||
    uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL];
 | 
			
		||||
    uint16_t last_active[GIC_MAXIRQ][GIC_NCPU];
 | 
			
		||||
    /* For each SGI on the target CPU, we store 8 bits
 | 
			
		||||
     * indicating which source CPUs have made this SGI
 | 
			
		||||
     * pending on the target CPU. These correspond to
 | 
			
		||||
| 
						 | 
				
			
			@ -78,7 +77,6 @@ typedef struct GICState {
 | 
			
		|||
    uint8_t sgi_pending[GIC_NR_SGIS][GIC_NCPU];
 | 
			
		||||
 | 
			
		||||
    uint16_t priority_mask[GIC_NCPU];
 | 
			
		||||
    uint16_t running_irq[GIC_NCPU];
 | 
			
		||||
    uint16_t running_priority[GIC_NCPU];
 | 
			
		||||
    uint16_t current_pending[GIC_NCPU];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -96,16 +94,9 @@ typedef struct GICState {
 | 
			
		|||
     * If an interrupt for preemption level X is active, then
 | 
			
		||||
     *   APRn[X mod 32] == 0b1,  where n = X / 32
 | 
			
		||||
     * otherwise the bit is clear.
 | 
			
		||||
     *
 | 
			
		||||
     * TODO: rewrite the interrupt acknowlege/complete routines to use
 | 
			
		||||
     * the APR registers to track the necessary information to update
 | 
			
		||||
     * s->running_priority[] on interrupt completion (ie completely remove
 | 
			
		||||
     * last_active[][] and running_irq[]). This will be necessary if we ever
 | 
			
		||||
     * want to support TCG<->KVM migration, or TCG guests which can
 | 
			
		||||
     * do power management involving powering down and restarting
 | 
			
		||||
     * the GIC.
 | 
			
		||||
     */
 | 
			
		||||
    uint32_t apr[GIC_NR_APRS][GIC_NCPU];
 | 
			
		||||
    uint32_t nsapr[GIC_NR_APRS][GIC_NCPU];
 | 
			
		||||
 | 
			
		||||
    uint32_t num_cpu;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -118,6 +109,7 @@ typedef struct GICState {
 | 
			
		|||
    uint32_t num_irq;
 | 
			
		||||
    uint32_t revision;
 | 
			
		||||
    bool security_extn;
 | 
			
		||||
    bool irq_reset_nonsecure; /* configure IRQs as group 1 (NS) on reset? */
 | 
			
		||||
    int dev_fd; /* kvm device fd if backed by kvm vgic support */
 | 
			
		||||
} GICState;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1493,6 +1493,21 @@ void object_property_set_description(Object *obj, const char *name,
 | 
			
		|||
int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
 | 
			
		||||
                         void *opaque);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * object_child_foreach_recursive:
 | 
			
		||||
 * @obj: the object whose children will be navigated
 | 
			
		||||
 * @fn: the iterator function to be called
 | 
			
		||||
 * @opaque: an opaque value that will be passed to the iterator
 | 
			
		||||
 *
 | 
			
		||||
 * Call @fn passing each child of @obj and @opaque to it, until @fn returns
 | 
			
		||||
 * non-zero. Calls recursively, all child nodes of @obj will also be passed
 | 
			
		||||
 * all the way down to the leaf nodes of the tree. Depth first ordering.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: The last value returned by @fn, or 0 if there is no child.
 | 
			
		||||
 */
 | 
			
		||||
int object_child_foreach_recursive(Object *obj,
 | 
			
		||||
                                   int (*fn)(Object *child, void *opaque),
 | 
			
		||||
                                   void *opaque);
 | 
			
		||||
/**
 | 
			
		||||
 * container_get:
 | 
			
		||||
 * @root: root of the #path, e.g., object_get_root()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										25
									
								
								qom/object.c
								
								
								
								
							
							
						
						
									
										25
									
								
								qom/object.c
								
								
								
								
							| 
						 | 
				
			
			@ -775,23 +775,42 @@ void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
 | 
			
		|||
    enumerating_types = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
 | 
			
		||||
                         void *opaque)
 | 
			
		||||
static int do_object_child_foreach(Object *obj,
 | 
			
		||||
                                   int (*fn)(Object *child, void *opaque),
 | 
			
		||||
                                   void *opaque, bool recurse)
 | 
			
		||||
{
 | 
			
		||||
    ObjectProperty *prop, *next;
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
 | 
			
		||||
    QTAILQ_FOREACH_SAFE(prop, &obj->properties, node, next) {
 | 
			
		||||
        if (object_property_is_child(prop)) {
 | 
			
		||||
            ret = fn(prop->opaque, opaque);
 | 
			
		||||
            Object *child = prop->opaque;
 | 
			
		||||
 | 
			
		||||
            ret = fn(child, opaque);
 | 
			
		||||
            if (ret != 0) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            if (recurse) {
 | 
			
		||||
                do_object_child_foreach(child, fn, opaque, true);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
 | 
			
		||||
                         void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    return do_object_child_foreach(obj, fn, opaque, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int object_child_foreach_recursive(Object *obj,
 | 
			
		||||
                                   int (*fn)(Object *child, void *opaque),
 | 
			
		||||
                                   void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    return do_object_child_foreach(obj, fn, opaque, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    GSList **list = opaque;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -478,7 +478,8 @@ void aarch64_cpu_do_interrupt(CPUState *cs)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    arm_log_exception(cs->exception_index);
 | 
			
		||||
    qemu_log_mask(CPU_LOG_INT, "...from EL%d\n", arm_current_el(env));
 | 
			
		||||
    qemu_log_mask(CPU_LOG_INT, "...from EL%d to EL%d\n", arm_current_el(env),
 | 
			
		||||
                  new_el);
 | 
			
		||||
    if (qemu_loglevel_mask(CPU_LOG_INT)
 | 
			
		||||
        && !excp_is_internal(cs->exception_index)) {
 | 
			
		||||
        qemu_log_mask(CPU_LOG_INT, "...with ESR 0x%" PRIx32 "\n",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2975,16 +2975,16 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
 | 
			
		|||
      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 3,
 | 
			
		||||
      .access = PL1_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
 | 
			
		||||
    { .name = "AT_S12E1R", .state = ARM_CP_STATE_AA64,
 | 
			
		||||
      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 4,
 | 
			
		||||
      .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 4,
 | 
			
		||||
      .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
 | 
			
		||||
    { .name = "AT_S12E1W", .state = ARM_CP_STATE_AA64,
 | 
			
		||||
      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 5,
 | 
			
		||||
      .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 5,
 | 
			
		||||
      .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
 | 
			
		||||
    { .name = "AT_S12E0R", .state = ARM_CP_STATE_AA64,
 | 
			
		||||
      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 6,
 | 
			
		||||
      .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 6,
 | 
			
		||||
      .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
 | 
			
		||||
    { .name = "AT_S12E0W", .state = ARM_CP_STATE_AA64,
 | 
			
		||||
      .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 7,
 | 
			
		||||
      .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 7,
 | 
			
		||||
      .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
 | 
			
		||||
    /* AT S1E2* are elsewhere as they UNDEF from EL3 if EL2 is not present */
 | 
			
		||||
    { .name = "AT_S1E3R", .state = ARM_CP_STATE_AA64,
 | 
			
		||||
| 
						 | 
				
			
			@ -2993,6 +2993,12 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
 | 
			
		|||
    { .name = "AT_S1E3W", .state = ARM_CP_STATE_AA64,
 | 
			
		||||
      .opc0 = 1, .opc1 = 6, .crn = 7, .crm = 8, .opc2 = 1,
 | 
			
		||||
      .access = PL3_W, .type = ARM_CP_NO_RAW, .writefn = ats_write64 },
 | 
			
		||||
    { .name = "PAR_EL1", .state = ARM_CP_STATE_AA64,
 | 
			
		||||
      .type = ARM_CP_ALIAS,
 | 
			
		||||
      .opc0 = 3, .opc1 = 0, .crn = 7, .crm = 4, .opc2 = 0,
 | 
			
		||||
      .access = PL1_RW, .resetvalue = 0,
 | 
			
		||||
      .fieldoffset = offsetof(CPUARMState, cp15.par_el[1]),
 | 
			
		||||
      .writefn = par_write },
 | 
			
		||||
#endif
 | 
			
		||||
    /* TLB invalidate last level of translation table walk */
 | 
			
		||||
    { .name = "TLBIMVALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10966,7 +10966,11 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
 | 
			
		|||
    dc->condjmp = 0;
 | 
			
		||||
 | 
			
		||||
    dc->aarch64 = 1;
 | 
			
		||||
    dc->el3_is_aa64 = arm_el_is_aa64(env, 3);
 | 
			
		||||
    /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
 | 
			
		||||
     * there is no secure EL1, so we route exceptions to EL3.
 | 
			
		||||
     */
 | 
			
		||||
    dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
 | 
			
		||||
                               !arm_el_is_aa64(env, 3);
 | 
			
		||||
    dc->thumb = 0;
 | 
			
		||||
    dc->bswap_code = 0;
 | 
			
		||||
    dc->condexec_mask = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11172,7 +11172,11 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
 | 
			
		|||
    dc->condjmp = 0;
 | 
			
		||||
 | 
			
		||||
    dc->aarch64 = 0;
 | 
			
		||||
    dc->el3_is_aa64 = arm_el_is_aa64(env, 3);
 | 
			
		||||
    /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
 | 
			
		||||
     * there is no secure EL1, so we route exceptions to EL3.
 | 
			
		||||
     */
 | 
			
		||||
    dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
 | 
			
		||||
                               !arm_el_is_aa64(env, 3);
 | 
			
		||||
    dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
 | 
			
		||||
    dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
 | 
			
		||||
    dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,7 +23,8 @@ typedef struct DisasContext {
 | 
			
		|||
    ARMMMUIdx mmu_idx; /* MMU index to use for normal loads/stores */
 | 
			
		||||
    bool ns;        /* Use non-secure CPREG bank on access */
 | 
			
		||||
    int fp_excp_el; /* FP exception EL or 0 if enabled */
 | 
			
		||||
    bool el3_is_aa64;  /* Flag indicating whether EL3 is AArch64 or not */
 | 
			
		||||
    /* Flag indicating that exceptions from secure mode are routed to EL3. */
 | 
			
		||||
    bool secure_routed_to_el3;
 | 
			
		||||
    bool vfp_enabled; /* FP enabled via FPSCR.EN */
 | 
			
		||||
    int vec_len;
 | 
			
		||||
    int vec_stride;
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +85,7 @@ static inline int default_exception_el(DisasContext *s)
 | 
			
		|||
     * exceptions can only be routed to ELs above 1, so we target the higher of
 | 
			
		||||
     * 1 or the current EL.
 | 
			
		||||
     */
 | 
			
		||||
    return (s->mmu_idx == ARMMMUIdx_S1SE0 && !s->el3_is_aa64)
 | 
			
		||||
    return (s->mmu_idx == ARMMMUIdx_S1SE0 && s->secure_routed_to_el3)
 | 
			
		||||
            ? 3 : MAX(1, s->current_el);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue