mirror of https://github.com/xemu-project/xemu.git
target-arm queue:
* ITS: error reporting cleanup * aspeed: improve documentation * Fix STM32F2XX USART data register readout * allow emulated GICv3 to be disabled in non-TCG builds * fix exception priority for singlestep, misaligned PC, bp, etc * Correct calculation of tlb range invalidate length * npcm7xx_emc: fix missing queue_flush * virt: Add VIOT ACPI table for virtio-iommu * target/i386: Use assert() to sanity-check b1 in SSE decode * Don't include qemu-common unnecessarily -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmG5xekZHHBldGVyLm1h eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3ramD/0WL8YV70sW5B/tHdb+/em1 xTBuABUUj5QDvKnxNoPIBwJI0vgmzwhAonYzcKKEUvlbL97crkgt6xSPvVxv2nf5 wnSYMKTDEC11AuYVdEyIMm5KLc88mq1w78pTYkFSUJmujCpfqLAsyXdEastIPHfN MdrwkpQ3wVmMeMcNBTq2yCxiGlz7x/myeJtDU9ihgPTcsgXa8BzziK6qCZHAOGCL 0/ljXDbVTJtLYUki9IqptPs8QUtlqOBt3rLplxHfKRKpmjiuD+xFlQ4GuIOBX+AL tQWgEyyiR9FnYpY1t3fWVtuKgjYXzlbh1A6cwdsK3Q68+qfi7Yr+lPryjwrmOkx7 /Yupq+QB/xgK4nxF4ydDXLvqI3h6GjaF2U9qujK3H9DyMOEYJDpaX1TZMphtWI89 9u7kLO6DNE00oUoiX+6Aty0qQtXv12SSaNpJmFON87/WLJJamHuiS6NiZp/r4ORU 51ds2LPGJAKAy9duqmZJ/81WlNjmHmurq1v+FIl29XInc4a2SpwEUM0rsTrrQTaD 16Qh2OZCnlYEg9nh6B54FQe8xP+pp69Gn/BRFhcwW9fPq4/pHSrwKEkI6lE+Yuiq +Fe8r0DbZczfhjcGdoUlIgMj+WSVY9Q8Opztsmv/kjZqxt0VvfdmAVp0odl5KdB4 cKAeYciNSgq2bGd+N4kuHA== =KuTi -----END PGP SIGNATURE----- Merge tag 'pull-target-arm-20211215' of https://git.linaro.org/people/pmaydell/qemu-arm into staging target-arm queue: * ITS: error reporting cleanup * aspeed: improve documentation * Fix STM32F2XX USART data register readout * allow emulated GICv3 to be disabled in non-TCG builds * fix exception priority for singlestep, misaligned PC, bp, etc * Correct calculation of tlb range invalidate length * npcm7xx_emc: fix missing queue_flush * virt: Add VIOT ACPI table for virtio-iommu * target/i386: Use assert() to sanity-check b1 in SSE decode * Don't include qemu-common unnecessarily # gpg: Signature made Wed 15 Dec 2021 02:39:37 AM PST # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [full] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [full] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [full] * tag 'pull-target-arm-20211215' of https://git.linaro.org/people/pmaydell/qemu-arm: (33 commits) tests/acpi: add expected blob for VIOT test on virt machine tests/acpi: add expected blobs for VIOT test on q35 machine tests/acpi: add test case for VIOT tests/acpi: allow updates of VIOT expected data files hw/arm/virt: Use object_property_set instead of qdev_prop_set hw/arm/virt: Reject instantiation of multiple IOMMUs hw/arm/virt: Remove device tree restriction for virtio-iommu hw/arm/virt-acpi-build: Add VIOT table for virtio-iommu hw/net: npcm7xx_emc fix missing queue_flush target/arm: Correct calculation of tlb range invalidate length hw/arm: Don't include qemu-common.h unnecessarily target/rx/cpu.h: Don't include qemu-common.h target/hexagon/cpu.h: don't include qemu-common.h include/hw/i386: Don't include qemu-common.h in .h files target/i386: Use assert() to sanity-check b1 in SSE decode tests/tcg: Add arm and aarch64 pc alignment tests target/arm: Suppress bp for exceptions with more priority target/arm: Assert thumb pc is aligned target/arm: Take an exception if PC is misaligned target/arm: Split compute_fsr_fsc out of arm_deliver_fault ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
aab8cfd4c3
|
@ -14,6 +14,7 @@ AST2400 SoC based machines :
|
||||||
|
|
||||||
- ``palmetto-bmc`` OpenPOWER Palmetto POWER8 BMC
|
- ``palmetto-bmc`` OpenPOWER Palmetto POWER8 BMC
|
||||||
- ``quanta-q71l-bmc`` OpenBMC Quanta BMC
|
- ``quanta-q71l-bmc`` OpenBMC Quanta BMC
|
||||||
|
- ``supermicrox11-bmc`` Supermicro X11 BMC
|
||||||
|
|
||||||
AST2500 SoC based machines :
|
AST2500 SoC based machines :
|
||||||
|
|
||||||
|
@ -21,12 +22,16 @@ AST2500 SoC based machines :
|
||||||
- ``romulus-bmc`` OpenPOWER Romulus POWER9 BMC
|
- ``romulus-bmc`` OpenPOWER Romulus POWER9 BMC
|
||||||
- ``witherspoon-bmc`` OpenPOWER Witherspoon POWER9 BMC
|
- ``witherspoon-bmc`` OpenPOWER Witherspoon POWER9 BMC
|
||||||
- ``sonorapass-bmc`` OCP SonoraPass BMC
|
- ``sonorapass-bmc`` OCP SonoraPass BMC
|
||||||
- ``swift-bmc`` OpenPOWER Swift BMC POWER9
|
- ``swift-bmc`` OpenPOWER Swift BMC POWER9 (to be removed in v7.0)
|
||||||
|
- ``fp5280g2-bmc`` Inspur FP5280G2 BMC
|
||||||
|
- ``g220a-bmc`` Bytedance G220A BMC
|
||||||
|
|
||||||
AST2600 SoC based machines :
|
AST2600 SoC based machines :
|
||||||
|
|
||||||
- ``ast2600-evb`` Aspeed AST2600 Evaluation board (Cortex-A7)
|
- ``ast2600-evb`` Aspeed AST2600 Evaluation board (Cortex-A7)
|
||||||
- ``tacoma-bmc`` OpenPOWER Witherspoon POWER9 AST2600 BMC
|
- ``tacoma-bmc`` OpenPOWER Witherspoon POWER9 AST2600 BMC
|
||||||
|
- ``rainier-bmc`` IBM Rainier POWER10 BMC
|
||||||
|
- ``fuji-bmc`` Facebook Fuji BMC
|
||||||
|
|
||||||
Supported devices
|
Supported devices
|
||||||
-----------------
|
-----------------
|
||||||
|
@ -51,13 +56,13 @@ Supported devices
|
||||||
* Front LEDs (PCA9552 on I2C bus)
|
* Front LEDs (PCA9552 on I2C bus)
|
||||||
* LPC Peripheral Controller (a subset of subdevices are supported)
|
* LPC Peripheral Controller (a subset of subdevices are supported)
|
||||||
* Hash/Crypto Engine (HACE) - Hash support only. TODO: HMAC and RSA
|
* Hash/Crypto Engine (HACE) - Hash support only. TODO: HMAC and RSA
|
||||||
|
* ADC
|
||||||
|
|
||||||
|
|
||||||
Missing devices
|
Missing devices
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
* Coprocessor support
|
* Coprocessor support
|
||||||
* ADC (out of tree implementation)
|
|
||||||
* PWM and Fan Controller
|
* PWM and Fan Controller
|
||||||
* Slave GPIO Controller
|
* Slave GPIO Controller
|
||||||
* Super I/O Controller
|
* Super I/O Controller
|
||||||
|
@ -73,16 +78,25 @@ Missing devices
|
||||||
Boot options
|
Boot options
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The Aspeed machines can be started using the ``-kernel`` option to
|
The Aspeed machines can be started using the ``-kernel`` and ``-dtb`` options
|
||||||
load a Linux kernel or from a firmware. Images can be downloaded from
|
to load a Linux kernel or from a firmware. Images can be downloaded from the
|
||||||
the OpenBMC jenkins :
|
OpenBMC jenkins :
|
||||||
|
|
||||||
https://jenkins.openbmc.org/job/ci-openbmc/lastSuccessfulBuild/distro=ubuntu,label=docker-builder
|
https://jenkins.openbmc.org/job/ci-openbmc/lastSuccessfulBuild/
|
||||||
|
|
||||||
or directly from the OpenBMC GitHub release repository :
|
or directly from the OpenBMC GitHub release repository :
|
||||||
|
|
||||||
https://github.com/openbmc/openbmc/releases
|
https://github.com/openbmc/openbmc/releases
|
||||||
|
|
||||||
|
To boot a kernel directly from a Linux build tree:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ qemu-system-arm -M ast2600-evb -nographic \
|
||||||
|
-kernel arch/arm/boot/zImage \
|
||||||
|
-dtb arch/arm/boot/dts/aspeed-ast2600-evb.dtb \
|
||||||
|
-initrd rootfs.cpio
|
||||||
|
|
||||||
The image should be attached as an MTD drive. Run :
|
The image should be attached as an MTD drive. Run :
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
|
@ -27,6 +27,7 @@ config ARM_VIRT
|
||||||
select DIMM
|
select DIMM
|
||||||
select ACPI_HW_REDUCED
|
select ACPI_HW_REDUCED
|
||||||
select ACPI_APEI
|
select ACPI_APEI
|
||||||
|
select ACPI_VIOT
|
||||||
|
|
||||||
config CHEETAH
|
config CHEETAH
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "qemu/datadir.h"
|
#include "qemu/datadir.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "qemu/datadir.h"
|
#include "qemu/datadir.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "qemu/datadir.h"
|
#include "qemu/datadir.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "hw/qdev-core.h"
|
#include "hw/qdev-core.h"
|
||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "qemu/datadir.h"
|
#include "qemu/datadir.h"
|
||||||
#include "qemu/units.h"
|
#include "qemu/units.h"
|
||||||
#include "sysemu/blockdev.h"
|
#include "sysemu/blockdev.h"
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "qemu/datadir.h"
|
#include "qemu/datadir.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "hw/arm/stm32f405_soc.h"
|
#include "hw/arm/stm32f405_soc.h"
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "qemu/datadir.h"
|
#include "qemu/datadir.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
#include "kvm_arm.h"
|
#include "kvm_arm.h"
|
||||||
#include "migration/vmstate.h"
|
#include "migration/vmstate.h"
|
||||||
#include "hw/acpi/ghes.h"
|
#include "hw/acpi/ghes.h"
|
||||||
|
#include "hw/acpi/viot.h"
|
||||||
|
|
||||||
#define ARM_SPI_BASE 32
|
#define ARM_SPI_BASE 32
|
||||||
|
|
||||||
|
@ -1011,6 +1012,12 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (vms->iommu == VIRT_IOMMU_VIRTIO) {
|
||||||
|
acpi_add_table(table_offsets, tables_blob);
|
||||||
|
build_viot(ms, tables_blob, tables->linker, vms->virtio_iommu_bdf,
|
||||||
|
vms->oem_id, vms->oem_table_id);
|
||||||
|
}
|
||||||
|
|
||||||
/* XSDT is pointed to by RSDP */
|
/* XSDT is pointed to by RSDP */
|
||||||
xsdt = tables_blob->len;
|
xsdt = tables_blob->len;
|
||||||
build_xsdt(tables_blob, tables->linker, table_offsets, vms->oem_id,
|
build_xsdt(tables_blob, tables->linker, table_offsets, vms->oem_id,
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "qemu/datadir.h"
|
#include "qemu/datadir.h"
|
||||||
#include "qemu/units.h"
|
#include "qemu/units.h"
|
||||||
#include "qemu/option.h"
|
#include "qemu/option.h"
|
||||||
|
@ -2494,6 +2493,11 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
||||||
hwaddr db_start = 0, db_end = 0;
|
hwaddr db_start = 0, db_end = 0;
|
||||||
char *resv_prop_str;
|
char *resv_prop_str;
|
||||||
|
|
||||||
|
if (vms->iommu != VIRT_IOMMU_NONE) {
|
||||||
|
error_setg(errp, "virt machine does not support multiple IOMMUs");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (vms->msi_controller) {
|
switch (vms->msi_controller) {
|
||||||
case VIRT_MSI_CTRL_NONE:
|
case VIRT_MSI_CTRL_NONE:
|
||||||
return;
|
return;
|
||||||
|
@ -2513,8 +2517,9 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
||||||
db_start, db_end,
|
db_start, db_end,
|
||||||
VIRTIO_IOMMU_RESV_MEM_T_MSI);
|
VIRTIO_IOMMU_RESV_MEM_T_MSI);
|
||||||
|
|
||||||
qdev_prop_set_uint32(dev, "len-reserved-regions", 1);
|
object_property_set_uint(OBJECT(dev), "len-reserved-regions", 1, errp);
|
||||||
qdev_prop_set_string(dev, "reserved-regions[0]", resv_prop_str);
|
object_property_set_str(OBJECT(dev), "reserved-regions[0]",
|
||||||
|
resv_prop_str, errp);
|
||||||
g_free(resv_prop_str);
|
g_free(resv_prop_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2614,16 +2619,10 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
|
||||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||||
|
|
||||||
if (device_is_dynamic_sysbus(mc, dev) ||
|
if (device_is_dynamic_sysbus(mc, dev) ||
|
||||||
(object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM))) {
|
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
|
||||||
|
object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
|
||||||
return HOTPLUG_HANDLER(machine);
|
return HOTPLUG_HANDLER(machine);
|
||||||
}
|
}
|
||||||
if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
|
|
||||||
VirtMachineState *vms = VIRT_MACHINE(machine);
|
|
||||||
|
|
||||||
if (!vms->bootinfo.firmware_loaded || !virt_is_acpi_enabled(vms)) {
|
|
||||||
return HOTPLUG_HANDLER(machine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,10 +103,11 @@ static uint64_t stm32f2xx_usart_read(void *opaque, hwaddr addr,
|
||||||
return retvalue;
|
return retvalue;
|
||||||
case USART_DR:
|
case USART_DR:
|
||||||
DB_PRINT("Value: 0x%" PRIx32 ", %c\n", s->usart_dr, (char) s->usart_dr);
|
DB_PRINT("Value: 0x%" PRIx32 ", %c\n", s->usart_dr, (char) s->usart_dr);
|
||||||
|
retvalue = s->usart_dr & 0x3FF;
|
||||||
s->usart_sr &= ~USART_SR_RXNE;
|
s->usart_sr &= ~USART_SR_RXNE;
|
||||||
qemu_chr_fe_accept_input(&s->chr);
|
qemu_chr_fe_accept_input(&s->chr);
|
||||||
qemu_set_irq(s->irq, 0);
|
qemu_set_irq(s->irq, 0);
|
||||||
return s->usart_dr & 0x3FF;
|
return retvalue;
|
||||||
case USART_BRR:
|
case USART_BRR:
|
||||||
return s->usart_brr;
|
return s->usart_brr;
|
||||||
case USART_CR1:
|
case USART_CR1:
|
||||||
|
|
|
@ -25,6 +25,11 @@ config APIC
|
||||||
select MSI_NONBROKEN
|
select MSI_NONBROKEN
|
||||||
select I8259
|
select I8259
|
||||||
|
|
||||||
|
config ARM_GIC_TCG
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
depends on ARM_GIC && TCG
|
||||||
|
|
||||||
config ARM_GIC_KVM
|
config ARM_GIC_KVM
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* ARM Generic Interrupt Controller v3
|
* ARM Generic Interrupt Controller v3 (emulation)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015 Huawei.
|
* Copyright (c) 2015 Huawei.
|
||||||
* Copyright (c) 2016 Linaro Limited
|
* Copyright (c) 2016 Linaro Limited
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* ARM Generic Interrupt Controller v3
|
* ARM Generic Interrupt Controller v3 (emulation)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016 Linaro Limited
|
* Copyright (c) 2016 Linaro Limited
|
||||||
* Written by Peter Maydell
|
* Written by Peter Maydell
|
||||||
|
@ -21,14 +21,6 @@
|
||||||
#include "hw/irq.h"
|
#include "hw/irq.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
|
||||||
void gicv3_set_gicv3state(CPUState *cpu, GICv3CPUState *s)
|
|
||||||
{
|
|
||||||
ARMCPU *arm_cpu = ARM_CPU(cpu);
|
|
||||||
CPUARMState *env = &arm_cpu->env;
|
|
||||||
|
|
||||||
env->gicv3state = (void *)s;
|
|
||||||
};
|
|
||||||
|
|
||||||
static GICv3CPUState *icc_cs_from_env(CPUARMState *env)
|
static GICv3CPUState *icc_cs_from_env(CPUARMState *env)
|
||||||
{
|
{
|
||||||
return env->gicv3state;
|
return env->gicv3state;
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
/*
|
||||||
|
* ARM Generic Interrupt Controller v3
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Linaro Limited
|
||||||
|
* Written by Peter Maydell
|
||||||
|
*
|
||||||
|
* This code is licensed under the GPL, version 2 or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "gicv3_internal.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
|
||||||
|
void gicv3_set_gicv3state(CPUState *cpu, GICv3CPUState *s)
|
||||||
|
{
|
||||||
|
ARMCPU *arm_cpu = ARM_CPU(cpu);
|
||||||
|
CPUARMState *env = &arm_cpu->env;
|
||||||
|
|
||||||
|
env->gicv3state = (void *)s;
|
||||||
|
};
|
|
@ -274,21 +274,36 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
|
||||||
if (res != MEMTX_OK) {
|
if (res != MEMTX_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
"%s: invalid command attributes: "
|
||||||
|
"invalid dte: %"PRIx64" for %d (MEM_TX: %d)\n",
|
||||||
|
__func__, dte, devid, res);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((devid > s->dt.maxids.max_devids) || !dte_valid || !ite_valid ||
|
|
||||||
!cte_valid || (eventid > max_eventid)) {
|
/*
|
||||||
|
* In this implementation, in case of guest errors we ignore the
|
||||||
|
* command and move onto the next command in the queue.
|
||||||
|
*/
|
||||||
|
if (devid > s->dt.maxids.max_devids) {
|
||||||
qemu_log_mask(LOG_GUEST_ERROR,
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
"%s: invalid command attributes "
|
"%s: invalid command attributes: devid %d>%d",
|
||||||
"devid %d or eventid %d or invalid dte %d or"
|
__func__, devid, s->dt.maxids.max_devids);
|
||||||
"invalid cte %d or invalid ite %d\n",
|
|
||||||
__func__, devid, eventid, dte_valid, cte_valid,
|
} else if (!dte_valid || !ite_valid || !cte_valid) {
|
||||||
ite_valid);
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
/*
|
"%s: invalid command attributes: "
|
||||||
* in this implementation, in case of error
|
"dte: %s, ite: %s, cte: %s\n",
|
||||||
* we ignore this command and move onto the next
|
__func__,
|
||||||
* command in the queue
|
dte_valid ? "valid" : "invalid",
|
||||||
*/
|
ite_valid ? "valid" : "invalid",
|
||||||
|
cte_valid ? "valid" : "invalid");
|
||||||
|
} else if (eventid > max_eventid) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
|
"%s: invalid command attributes: eventid %d > %d\n",
|
||||||
|
__func__, eventid, max_eventid);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Current implementation only supports rdbase == procnum
|
* Current implementation only supports rdbase == procnum
|
||||||
|
|
|
@ -3,12 +3,14 @@ softmmu_ss.add(when: 'CONFIG_ARM_GIC', if_true: files(
|
||||||
'arm_gic.c',
|
'arm_gic.c',
|
||||||
'arm_gic_common.c',
|
'arm_gic_common.c',
|
||||||
'arm_gicv2m.c',
|
'arm_gicv2m.c',
|
||||||
'arm_gicv3.c',
|
|
||||||
'arm_gicv3_common.c',
|
'arm_gicv3_common.c',
|
||||||
'arm_gicv3_dist.c',
|
|
||||||
'arm_gicv3_its_common.c',
|
'arm_gicv3_its_common.c',
|
||||||
'arm_gicv3_redist.c',
|
))
|
||||||
|
softmmu_ss.add(when: 'CONFIG_ARM_GIC_TCG', if_true: files(
|
||||||
|
'arm_gicv3.c',
|
||||||
|
'arm_gicv3_dist.c',
|
||||||
'arm_gicv3_its.c',
|
'arm_gicv3_its.c',
|
||||||
|
'arm_gicv3_redist.c',
|
||||||
))
|
))
|
||||||
softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_pic.c'))
|
softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_pic.c'))
|
||||||
softmmu_ss.add(when: 'CONFIG_HEATHROW_PIC', if_true: files('heathrow_pic.c'))
|
softmmu_ss.add(when: 'CONFIG_HEATHROW_PIC', if_true: files('heathrow_pic.c'))
|
||||||
|
@ -25,7 +27,8 @@ softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP_PMU', if_true: files('xlnx-pmu-iomod-in
|
||||||
|
|
||||||
specific_ss.add(when: 'CONFIG_ALLWINNER_A10_PIC', if_true: files('allwinner-a10-pic.c'))
|
specific_ss.add(when: 'CONFIG_ALLWINNER_A10_PIC', if_true: files('allwinner-a10-pic.c'))
|
||||||
specific_ss.add(when: 'CONFIG_APIC', if_true: files('apic.c', 'apic_common.c'))
|
specific_ss.add(when: 'CONFIG_APIC', if_true: files('apic.c', 'apic_common.c'))
|
||||||
specific_ss.add(when: 'CONFIG_ARM_GIC', if_true: files('arm_gicv3_cpuif.c'))
|
specific_ss.add(when: 'CONFIG_ARM_GIC', if_true: files('arm_gicv3_cpuif_common.c'))
|
||||||
|
specific_ss.add(when: 'CONFIG_ARM_GIC_TCG', if_true: files('arm_gicv3_cpuif.c'))
|
||||||
specific_ss.add(when: 'CONFIG_ARM_GIC_KVM', if_true: files('arm_gic_kvm.c'))
|
specific_ss.add(when: 'CONFIG_ARM_GIC_KVM', if_true: files('arm_gic_kvm.c'))
|
||||||
specific_ss.add(when: ['CONFIG_ARM_GIC_KVM', 'TARGET_AARCH64'], if_true: files('arm_gicv3_kvm.c', 'arm_gicv3_its_kvm.c'))
|
specific_ss.add(when: ['CONFIG_ARM_GIC_KVM', 'TARGET_AARCH64'], if_true: files('arm_gicv3_kvm.c', 'arm_gicv3_its_kvm.c'))
|
||||||
specific_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_nvic.c'))
|
specific_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_nvic.c'))
|
||||||
|
|
|
@ -284,6 +284,12 @@ static void emc_halt_rx(NPCM7xxEMCState *emc, uint32_t mista_flag)
|
||||||
emc_set_mista(emc, mista_flag);
|
emc_set_mista(emc, mista_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void emc_enable_rx_and_flush(NPCM7xxEMCState *emc)
|
||||||
|
{
|
||||||
|
emc->rx_active = true;
|
||||||
|
qemu_flush_queued_packets(qemu_get_queue(emc->nic));
|
||||||
|
}
|
||||||
|
|
||||||
static void emc_set_next_tx_descriptor(NPCM7xxEMCState *emc,
|
static void emc_set_next_tx_descriptor(NPCM7xxEMCState *emc,
|
||||||
const NPCM7xxEMCTxDesc *tx_desc,
|
const NPCM7xxEMCTxDesc *tx_desc,
|
||||||
uint32_t desc_addr)
|
uint32_t desc_addr)
|
||||||
|
@ -581,13 +587,6 @@ static ssize_t emc_receive(NetClientState *nc, const uint8_t *buf, size_t len1)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emc_try_receive_next_packet(NPCM7xxEMCState *emc)
|
|
||||||
{
|
|
||||||
if (emc_can_receive(qemu_get_queue(emc->nic))) {
|
|
||||||
qemu_flush_queued_packets(qemu_get_queue(emc->nic));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t npcm7xx_emc_read(void *opaque, hwaddr offset, unsigned size)
|
static uint64_t npcm7xx_emc_read(void *opaque, hwaddr offset, unsigned size)
|
||||||
{
|
{
|
||||||
NPCM7xxEMCState *emc = opaque;
|
NPCM7xxEMCState *emc = opaque;
|
||||||
|
@ -703,7 +702,7 @@ static void npcm7xx_emc_write(void *opaque, hwaddr offset,
|
||||||
emc->regs[REG_MGSTA] |= REG_MGSTA_RXHA;
|
emc->regs[REG_MGSTA] |= REG_MGSTA_RXHA;
|
||||||
}
|
}
|
||||||
if (value & REG_MCMDR_RXON) {
|
if (value & REG_MCMDR_RXON) {
|
||||||
emc->rx_active = true;
|
emc_enable_rx_and_flush(emc);
|
||||||
} else {
|
} else {
|
||||||
emc_halt_rx(emc, 0);
|
emc_halt_rx(emc, 0);
|
||||||
}
|
}
|
||||||
|
@ -739,8 +738,7 @@ static void npcm7xx_emc_write(void *opaque, hwaddr offset,
|
||||||
break;
|
break;
|
||||||
case REG_RSDR:
|
case REG_RSDR:
|
||||||
if (emc->regs[REG_MCMDR] & REG_MCMDR_RXON) {
|
if (emc->regs[REG_MCMDR] & REG_MCMDR_RXON) {
|
||||||
emc->rx_active = true;
|
emc_enable_rx_and_flush(emc);
|
||||||
emc_try_receive_next_packet(emc);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REG_MIIDA:
|
case REG_MIIDA:
|
||||||
|
|
|
@ -48,16 +48,8 @@ static void virtio_iommu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
|
||||||
VirtIOIOMMU *s = VIRTIO_IOMMU(vdev);
|
VirtIOIOMMU *s = VIRTIO_IOMMU(vdev);
|
||||||
|
|
||||||
if (!qdev_get_machine_hotplug_handler(DEVICE(vpci_dev))) {
|
if (!qdev_get_machine_hotplug_handler(DEVICE(vpci_dev))) {
|
||||||
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
|
error_setg(errp, "Check your machine implements a hotplug handler "
|
||||||
|
"for the virtio-iommu-pci device");
|
||||||
error_setg(errp,
|
|
||||||
"%s machine fails to create iommu-map device tree bindings",
|
|
||||||
mc->name);
|
|
||||||
error_append_hint(errp,
|
|
||||||
"Check your machine implements a hotplug handler "
|
|
||||||
"for the virtio-iommu-pci device\n");
|
|
||||||
error_append_hint(errp, "Check the guest is booted without FW or with "
|
|
||||||
"-no-acpi\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < s->nb_reserved_regions; i++) {
|
for (int i = 0; i < s->nb_reserved_regions; i++) {
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#ifndef HW_I386_MICROVM_H
|
#ifndef HW_I386_MICROVM_H
|
||||||
#define HW_I386_MICROVM_H
|
#define HW_I386_MICROVM_H
|
||||||
|
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "exec/hwaddr.h"
|
#include "exec/hwaddr.h"
|
||||||
#include "qemu/notify.h"
|
#include "qemu/notify.h"
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#ifndef HW_I386_X86_H
|
#ifndef HW_I386_X86_H
|
||||||
#define HW_I386_X86_H
|
#define HW_I386_X86_H
|
||||||
|
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "exec/hwaddr.h"
|
#include "exec/hwaddr.h"
|
||||||
#include "qemu/notify.h"
|
#include "qemu/notify.h"
|
||||||
|
|
||||||
|
|
|
@ -113,27 +113,35 @@ void cpu_loop(CPUARMState *env)
|
||||||
break;
|
break;
|
||||||
case EXCP_PREFETCH_ABORT:
|
case EXCP_PREFETCH_ABORT:
|
||||||
case EXCP_DATA_ABORT:
|
case EXCP_DATA_ABORT:
|
||||||
/* We should only arrive here with EC in {DATAABORT, INSNABORT}. */
|
|
||||||
ec = syn_get_ec(env->exception.syndrome);
|
ec = syn_get_ec(env->exception.syndrome);
|
||||||
assert(ec == EC_DATAABORT || ec == EC_INSNABORT);
|
switch (ec) {
|
||||||
|
case EC_DATAABORT:
|
||||||
/* Both EC have the same format for FSC, or close enough. */
|
case EC_INSNABORT:
|
||||||
fsc = extract32(env->exception.syndrome, 0, 6);
|
/* Both EC have the same format for FSC, or close enough. */
|
||||||
switch (fsc) {
|
fsc = extract32(env->exception.syndrome, 0, 6);
|
||||||
case 0x04 ... 0x07: /* Translation fault, level {0-3} */
|
switch (fsc) {
|
||||||
si_signo = TARGET_SIGSEGV;
|
case 0x04 ... 0x07: /* Translation fault, level {0-3} */
|
||||||
si_code = TARGET_SEGV_MAPERR;
|
si_signo = TARGET_SIGSEGV;
|
||||||
|
si_code = TARGET_SEGV_MAPERR;
|
||||||
|
break;
|
||||||
|
case 0x09 ... 0x0b: /* Access flag fault, level {1-3} */
|
||||||
|
case 0x0d ... 0x0f: /* Permission fault, level {1-3} */
|
||||||
|
si_signo = TARGET_SIGSEGV;
|
||||||
|
si_code = TARGET_SEGV_ACCERR;
|
||||||
|
break;
|
||||||
|
case 0x11: /* Synchronous Tag Check Fault */
|
||||||
|
si_signo = TARGET_SIGSEGV;
|
||||||
|
si_code = TARGET_SEGV_MTESERR;
|
||||||
|
break;
|
||||||
|
case 0x21: /* Alignment fault */
|
||||||
|
si_signo = TARGET_SIGBUS;
|
||||||
|
si_code = TARGET_BUS_ADRALN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x09 ... 0x0b: /* Access flag fault, level {1-3} */
|
case EC_PCALIGNMENT:
|
||||||
case 0x0d ... 0x0f: /* Permission fault, level {1-3} */
|
|
||||||
si_signo = TARGET_SIGSEGV;
|
|
||||||
si_code = TARGET_SEGV_ACCERR;
|
|
||||||
break;
|
|
||||||
case 0x11: /* Synchronous Tag Check Fault */
|
|
||||||
si_signo = TARGET_SIGSEGV;
|
|
||||||
si_code = TARGET_SEGV_MTESERR;
|
|
||||||
break;
|
|
||||||
case 0x21: /* Alignment fault */
|
|
||||||
si_signo = TARGET_SIGBUS;
|
si_signo = TARGET_SIGBUS;
|
||||||
si_code = TARGET_BUS_ADRALN;
|
si_code = TARGET_BUS_ADRALN;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu-common.h"
|
||||||
#include "qemu.h"
|
#include "qemu.h"
|
||||||
#include "user-internals.h"
|
#include "user-internals.h"
|
||||||
#include "cpu_loop-common.h"
|
#include "cpu_loop-common.h"
|
||||||
|
|
|
@ -220,6 +220,7 @@ bool arm_debug_check_breakpoint(CPUState *cs)
|
||||||
{
|
{
|
||||||
ARMCPU *cpu = ARM_CPU(cs);
|
ARMCPU *cpu = ARM_CPU(cs);
|
||||||
CPUARMState *env = &cpu->env;
|
CPUARMState *env = &cpu->env;
|
||||||
|
target_ulong pc;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -231,6 +232,28 @@ bool arm_debug_check_breakpoint(CPUState *cs)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Single-step exceptions have priority over breakpoint exceptions.
|
||||||
|
* If single-step state is active-pending, suppress the bp.
|
||||||
|
*/
|
||||||
|
if (arm_singlestep_active(env) && !(env->pstate & PSTATE_SS)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PC alignment faults have priority over breakpoint exceptions.
|
||||||
|
*/
|
||||||
|
pc = is_a64(env) ? env->pc : env->regs[15];
|
||||||
|
if ((is_a64(env) || !env->thumb) && (pc & 3) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Instruction aborts have priority over breakpoint exceptions.
|
||||||
|
* TODO: We would need to look up the page for PC and verify that
|
||||||
|
* it is present and executable.
|
||||||
|
*/
|
||||||
|
|
||||||
for (n = 0; n < ARRAY_SIZE(env->cpu_breakpoint); n++) {
|
for (n = 0; n < ARRAY_SIZE(env->cpu_breakpoint); n++) {
|
||||||
if (bp_wp_matches(cpu, n, false)) {
|
if (bp_wp_matches(cpu, n, false)) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -77,8 +77,13 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||||
|
|
||||||
tmp = ldl_p(mem_buf);
|
tmp = ldl_p(mem_buf);
|
||||||
|
|
||||||
/* Mask out low bit of PC to workaround gdb bugs. This will probably
|
/*
|
||||||
cause problems if we ever implement the Jazelle DBX extensions. */
|
* Mask out low bits of PC to workaround gdb bugs.
|
||||||
|
* This avoids an assert in thumb_tr_translate_insn, because it is
|
||||||
|
* architecturally impossible to misalign the pc.
|
||||||
|
* This will probably cause problems if we ever implement the
|
||||||
|
* Jazelle DBX extensions.
|
||||||
|
*/
|
||||||
if (n == 15) {
|
if (n == 15) {
|
||||||
tmp &= ~1;
|
tmp &= ~1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4519,18 +4519,18 @@ static uint64_t tlbi_aa64_range_get_length(CPUARMState *env,
|
||||||
uint64_t exponent;
|
uint64_t exponent;
|
||||||
uint64_t length;
|
uint64_t length;
|
||||||
|
|
||||||
num = extract64(value, 39, 4);
|
num = extract64(value, 39, 5);
|
||||||
scale = extract64(value, 44, 2);
|
scale = extract64(value, 44, 2);
|
||||||
page_size_granule = extract64(value, 46, 2);
|
page_size_granule = extract64(value, 46, 2);
|
||||||
|
|
||||||
page_shift = page_size_granule * 2 + 12;
|
|
||||||
|
|
||||||
if (page_size_granule == 0) {
|
if (page_size_granule == 0) {
|
||||||
qemu_log_mask(LOG_GUEST_ERROR, "Invalid page size granule %d\n",
|
qemu_log_mask(LOG_GUEST_ERROR, "Invalid page size granule %d\n",
|
||||||
page_size_granule);
|
page_size_granule);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
page_shift = (page_size_granule - 1) * 2 + 12;
|
||||||
|
|
||||||
exponent = (5 * scale) + 1;
|
exponent = (5 * scale) + 1;
|
||||||
length = (num + 1) << (exponent + page_shift);
|
length = (num + 1) << (exponent + page_shift);
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
|
||||||
DEF_HELPER_2(exception_internal, void, env, i32)
|
DEF_HELPER_2(exception_internal, void, env, i32)
|
||||||
DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
|
DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
|
||||||
DEF_HELPER_2(exception_bkpt_insn, void, env, i32)
|
DEF_HELPER_2(exception_bkpt_insn, void, env, i32)
|
||||||
|
DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl)
|
||||||
DEF_HELPER_1(setend, void, env)
|
DEF_HELPER_1(setend, void, env)
|
||||||
DEF_HELPER_2(wfi, void, env, i32)
|
DEF_HELPER_2(wfi, void, env, i32)
|
||||||
DEF_HELPER_1(wfe, void, env)
|
DEF_HELPER_1(wfe, void, env)
|
||||||
|
|
|
@ -794,6 +794,16 @@ static int cpu_post_load(void *opaque, int version_id)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Misaligned thumb pc is architecturally impossible.
|
||||||
|
* We have an assert in thumb_tr_translate_insn to verify this.
|
||||||
|
* Fail an incoming migrate to avoid this assert.
|
||||||
|
*/
|
||||||
|
if (!is_a64(env) && env->thumb && (env->regs[15] & 1)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!kvm_enabled()) {
|
if (!kvm_enabled()) {
|
||||||
pmu_op_finish(&cpu->env);
|
pmu_op_finish(&cpu->env);
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,4 +282,9 @@ static inline uint32_t syn_illegalstate(void)
|
||||||
return (EC_ILLEGALSTATE << ARM_EL_EC_SHIFT) | ARM_EL_IL;
|
return (EC_ILLEGALSTATE << ARM_EL_EC_SHIFT) | ARM_EL_IL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint32_t syn_pcalignment(void)
|
||||||
|
{
|
||||||
|
return (EC_PCALIGNMENT << ARM_EL_EC_SHIFT) | ARM_EL_IL;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* TARGET_ARM_SYNDROME_H */
|
#endif /* TARGET_ARM_SYNDROME_H */
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
|
#include "exec/helper-proto.h"
|
||||||
|
|
||||||
static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
|
static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
|
||||||
unsigned int target_el,
|
unsigned int target_el,
|
||||||
|
@ -49,25 +50,11 @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
|
||||||
return syn;
|
return syn;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void QEMU_NORETURN arm_deliver_fault(ARMCPU *cpu, vaddr addr,
|
static uint32_t compute_fsr_fsc(CPUARMState *env, ARMMMUFaultInfo *fi,
|
||||||
MMUAccessType access_type,
|
int target_el, int mmu_idx, uint32_t *ret_fsc)
|
||||||
int mmu_idx, ARMMMUFaultInfo *fi)
|
|
||||||
{
|
{
|
||||||
CPUARMState *env = &cpu->env;
|
|
||||||
int target_el;
|
|
||||||
bool same_el;
|
|
||||||
uint32_t syn, exc, fsr, fsc;
|
|
||||||
ARMMMUIdx arm_mmu_idx = core_to_arm_mmu_idx(env, mmu_idx);
|
ARMMMUIdx arm_mmu_idx = core_to_arm_mmu_idx(env, mmu_idx);
|
||||||
|
uint32_t fsr, fsc;
|
||||||
target_el = exception_target_el(env);
|
|
||||||
if (fi->stage2) {
|
|
||||||
target_el = 2;
|
|
||||||
env->cp15.hpfar_el2 = extract64(fi->s2addr, 12, 47) << 4;
|
|
||||||
if (arm_is_secure_below_el3(env) && fi->s1ns) {
|
|
||||||
env->cp15.hpfar_el2 |= HPFAR_NS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
same_el = (arm_current_el(env) == target_el);
|
|
||||||
|
|
||||||
if (target_el == 2 || arm_el_is_aa64(env, target_el) ||
|
if (target_el == 2 || arm_el_is_aa64(env, target_el) ||
|
||||||
arm_s1_regime_using_lpae_format(env, arm_mmu_idx)) {
|
arm_s1_regime_using_lpae_format(env, arm_mmu_idx)) {
|
||||||
|
@ -88,6 +75,31 @@ static void QEMU_NORETURN arm_deliver_fault(ARMCPU *cpu, vaddr addr,
|
||||||
fsc = 0x3f;
|
fsc = 0x3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*ret_fsc = fsc;
|
||||||
|
return fsr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void QEMU_NORETURN arm_deliver_fault(ARMCPU *cpu, vaddr addr,
|
||||||
|
MMUAccessType access_type,
|
||||||
|
int mmu_idx, ARMMMUFaultInfo *fi)
|
||||||
|
{
|
||||||
|
CPUARMState *env = &cpu->env;
|
||||||
|
int target_el;
|
||||||
|
bool same_el;
|
||||||
|
uint32_t syn, exc, fsr, fsc;
|
||||||
|
|
||||||
|
target_el = exception_target_el(env);
|
||||||
|
if (fi->stage2) {
|
||||||
|
target_el = 2;
|
||||||
|
env->cp15.hpfar_el2 = extract64(fi->s2addr, 12, 47) << 4;
|
||||||
|
if (arm_is_secure_below_el3(env) && fi->s1ns) {
|
||||||
|
env->cp15.hpfar_el2 |= HPFAR_NS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
same_el = (arm_current_el(env) == target_el);
|
||||||
|
|
||||||
|
fsr = compute_fsr_fsc(env, fi, target_el, mmu_idx, &fsc);
|
||||||
|
|
||||||
if (access_type == MMU_INST_FETCH) {
|
if (access_type == MMU_INST_FETCH) {
|
||||||
syn = syn_insn_abort(same_el, fi->ea, fi->s1ptw, fsc);
|
syn = syn_insn_abort(same_el, fi->ea, fi->s1ptw, fsc);
|
||||||
exc = EXCP_PREFETCH_ABORT;
|
exc = EXCP_PREFETCH_ABORT;
|
||||||
|
@ -123,6 +135,23 @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
|
||||||
arm_deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi);
|
arm_deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void helper_exception_pc_alignment(CPUARMState *env, target_ulong pc)
|
||||||
|
{
|
||||||
|
ARMMMUFaultInfo fi = { .type = ARMFault_Alignment };
|
||||||
|
int target_el = exception_target_el(env);
|
||||||
|
int mmu_idx = cpu_mmu_index(env, true);
|
||||||
|
uint32_t fsc;
|
||||||
|
|
||||||
|
env->exception.vaddress = pc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that the fsc is not applicable to this exception,
|
||||||
|
* since any syndrome is pcalignment not insn_abort.
|
||||||
|
*/
|
||||||
|
env->exception.fsr = compute_fsr_fsc(env, &fi, target_el, mmu_idx, &fsc);
|
||||||
|
raise_exception(env, EXCP_PREFETCH_ABORT, syn_pcalignment(), target_el);
|
||||||
|
}
|
||||||
|
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -14750,8 +14750,10 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
{
|
{
|
||||||
DisasContext *s = container_of(dcbase, DisasContext, base);
|
DisasContext *s = container_of(dcbase, DisasContext, base);
|
||||||
CPUARMState *env = cpu->env_ptr;
|
CPUARMState *env = cpu->env_ptr;
|
||||||
|
uint64_t pc = s->base.pc_next;
|
||||||
uint32_t insn;
|
uint32_t insn;
|
||||||
|
|
||||||
|
/* Singlestep exceptions have the highest priority. */
|
||||||
if (s->ss_active && !s->pstate_ss) {
|
if (s->ss_active && !s->pstate_ss) {
|
||||||
/* Singlestep state is Active-pending.
|
/* Singlestep state is Active-pending.
|
||||||
* If we're in this state at the start of a TB then either
|
* If we're in this state at the start of a TB then either
|
||||||
|
@ -14766,13 +14768,28 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
assert(s->base.num_insns == 1);
|
assert(s->base.num_insns == 1);
|
||||||
gen_swstep_exception(s, 0, 0);
|
gen_swstep_exception(s, 0, 0);
|
||||||
s->base.is_jmp = DISAS_NORETURN;
|
s->base.is_jmp = DISAS_NORETURN;
|
||||||
|
s->base.pc_next = pc + 4;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->pc_curr = s->base.pc_next;
|
if (pc & 3) {
|
||||||
insn = arm_ldl_code(env, &s->base, s->base.pc_next, s->sctlr_b);
|
/*
|
||||||
|
* PC alignment fault. This has priority over the instruction abort
|
||||||
|
* that we would receive from a translation fault via arm_ldl_code.
|
||||||
|
* This should only be possible after an indirect branch, at the
|
||||||
|
* start of the TB.
|
||||||
|
*/
|
||||||
|
assert(s->base.num_insns == 1);
|
||||||
|
gen_helper_exception_pc_alignment(cpu_env, tcg_constant_tl(pc));
|
||||||
|
s->base.is_jmp = DISAS_NORETURN;
|
||||||
|
s->base.pc_next = QEMU_ALIGN_UP(pc, 4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->pc_curr = pc;
|
||||||
|
insn = arm_ldl_code(env, &s->base, pc, s->sctlr_b);
|
||||||
s->insn = insn;
|
s->insn = insn;
|
||||||
s->base.pc_next += 4;
|
s->base.pc_next = pc + 4;
|
||||||
|
|
||||||
s->fp_access_checked = false;
|
s->fp_access_checked = false;
|
||||||
s->sve_access_checked = false;
|
s->sve_access_checked = false;
|
||||||
|
|
|
@ -9502,7 +9502,7 @@ static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
dc->insn_start = tcg_last_op();
|
dc->insn_start = tcg_last_op();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool arm_pre_translate_insn(DisasContext *dc)
|
static bool arm_check_kernelpage(DisasContext *dc)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
/* Intercept jump to the magic kernel page. */
|
/* Intercept jump to the magic kernel page. */
|
||||||
|
@ -9514,7 +9514,11 @@ static bool arm_pre_translate_insn(DisasContext *dc)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool arm_check_ss_active(DisasContext *dc)
|
||||||
|
{
|
||||||
if (dc->ss_active && !dc->pstate_ss) {
|
if (dc->ss_active && !dc->pstate_ss) {
|
||||||
/* Singlestep state is Active-pending.
|
/* Singlestep state is Active-pending.
|
||||||
* If we're in this state at the start of a TB then either
|
* If we're in this state at the start of a TB then either
|
||||||
|
@ -9548,17 +9552,38 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
{
|
{
|
||||||
DisasContext *dc = container_of(dcbase, DisasContext, base);
|
DisasContext *dc = container_of(dcbase, DisasContext, base);
|
||||||
CPUARMState *env = cpu->env_ptr;
|
CPUARMState *env = cpu->env_ptr;
|
||||||
|
uint32_t pc = dc->base.pc_next;
|
||||||
unsigned int insn;
|
unsigned int insn;
|
||||||
|
|
||||||
if (arm_pre_translate_insn(dc)) {
|
/* Singlestep exceptions have the highest priority. */
|
||||||
dc->base.pc_next += 4;
|
if (arm_check_ss_active(dc)) {
|
||||||
|
dc->base.pc_next = pc + 4;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dc->pc_curr = dc->base.pc_next;
|
if (pc & 3) {
|
||||||
insn = arm_ldl_code(env, &dc->base, dc->base.pc_next, dc->sctlr_b);
|
/*
|
||||||
|
* PC alignment fault. This has priority over the instruction abort
|
||||||
|
* that we would receive from a translation fault via arm_ldl_code
|
||||||
|
* (or the execution of the kernelpage entrypoint). This should only
|
||||||
|
* be possible after an indirect branch, at the start of the TB.
|
||||||
|
*/
|
||||||
|
assert(dc->base.num_insns == 1);
|
||||||
|
gen_helper_exception_pc_alignment(cpu_env, tcg_constant_tl(pc));
|
||||||
|
dc->base.is_jmp = DISAS_NORETURN;
|
||||||
|
dc->base.pc_next = QEMU_ALIGN_UP(pc, 4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arm_check_kernelpage(dc)) {
|
||||||
|
dc->base.pc_next = pc + 4;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dc->pc_curr = pc;
|
||||||
|
insn = arm_ldl_code(env, &dc->base, pc, dc->sctlr_b);
|
||||||
dc->insn = insn;
|
dc->insn = insn;
|
||||||
dc->base.pc_next += 4;
|
dc->base.pc_next = pc + 4;
|
||||||
disas_arm_insn(dc, insn);
|
disas_arm_insn(dc, insn);
|
||||||
|
|
||||||
arm_post_translate_insn(dc);
|
arm_post_translate_insn(dc);
|
||||||
|
@ -9617,25 +9642,28 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
{
|
{
|
||||||
DisasContext *dc = container_of(dcbase, DisasContext, base);
|
DisasContext *dc = container_of(dcbase, DisasContext, base);
|
||||||
CPUARMState *env = cpu->env_ptr;
|
CPUARMState *env = cpu->env_ptr;
|
||||||
|
uint32_t pc = dc->base.pc_next;
|
||||||
uint32_t insn;
|
uint32_t insn;
|
||||||
bool is_16bit;
|
bool is_16bit;
|
||||||
|
|
||||||
if (arm_pre_translate_insn(dc)) {
|
/* Misaligned thumb PC is architecturally impossible. */
|
||||||
dc->base.pc_next += 2;
|
assert((dc->base.pc_next & 1) == 0);
|
||||||
|
|
||||||
|
if (arm_check_ss_active(dc) || arm_check_kernelpage(dc)) {
|
||||||
|
dc->base.pc_next = pc + 2;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dc->pc_curr = dc->base.pc_next;
|
dc->pc_curr = pc;
|
||||||
insn = arm_lduw_code(env, &dc->base, dc->base.pc_next, dc->sctlr_b);
|
insn = arm_lduw_code(env, &dc->base, pc, dc->sctlr_b);
|
||||||
is_16bit = thumb_insn_is_16bit(dc, dc->base.pc_next, insn);
|
is_16bit = thumb_insn_is_16bit(dc, dc->base.pc_next, insn);
|
||||||
dc->base.pc_next += 2;
|
pc += 2;
|
||||||
if (!is_16bit) {
|
if (!is_16bit) {
|
||||||
uint32_t insn2 = arm_lduw_code(env, &dc->base, dc->base.pc_next,
|
uint32_t insn2 = arm_lduw_code(env, &dc->base, pc, dc->sctlr_b);
|
||||||
dc->sctlr_b);
|
|
||||||
|
|
||||||
insn = insn << 16 | insn2;
|
insn = insn << 16 | insn2;
|
||||||
dc->base.pc_next += 2;
|
pc += 2;
|
||||||
}
|
}
|
||||||
|
dc->base.pc_next = pc;
|
||||||
dc->insn = insn;
|
dc->insn = insn;
|
||||||
|
|
||||||
if (dc->pstate_il) {
|
if (dc->pstate_il) {
|
||||||
|
|
|
@ -23,7 +23,6 @@ typedef struct CPUHexagonState CPUHexagonState;
|
||||||
|
|
||||||
#include "fpu/softfloat-types.h"
|
#include "fpu/softfloat-types.h"
|
||||||
|
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "exec/cpu-defs.h"
|
#include "exec/cpu-defs.h"
|
||||||
#include "hex_regs.h"
|
#include "hex_regs.h"
|
||||||
#include "mmvec/mmvec.h"
|
#include "mmvec/mmvec.h"
|
||||||
|
|
|
@ -3519,9 +3519,6 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
|
||||||
case 0x171: /* shift xmm, im */
|
case 0x171: /* shift xmm, im */
|
||||||
case 0x172:
|
case 0x172:
|
||||||
case 0x173:
|
case 0x173:
|
||||||
if (b1 >= 2) {
|
|
||||||
goto unknown_op;
|
|
||||||
}
|
|
||||||
val = x86_ldub_code(env, s);
|
val = x86_ldub_code(env, s);
|
||||||
if (is_xmm) {
|
if (is_xmm) {
|
||||||
tcg_gen_movi_tl(s->T0, val);
|
tcg_gen_movi_tl(s->T0, val);
|
||||||
|
@ -3540,6 +3537,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
|
||||||
offsetof(CPUX86State, mmx_t0.MMX_L(1)));
|
offsetof(CPUX86State, mmx_t0.MMX_L(1)));
|
||||||
op1_offset = offsetof(CPUX86State,mmx_t0);
|
op1_offset = offsetof(CPUX86State,mmx_t0);
|
||||||
}
|
}
|
||||||
|
assert(b1 < 2);
|
||||||
sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
|
sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
|
||||||
(((modrm >> 3)) & 7)][b1];
|
(((modrm >> 3)) & 7)][b1];
|
||||||
if (!sse_fn_epp) {
|
if (!sse_fn_epp) {
|
||||||
|
@ -3770,10 +3768,8 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
reg = ((modrm >> 3) & 7) | REX_R(s);
|
reg = ((modrm >> 3) & 7) | REX_R(s);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
if (b1 >= 2) {
|
|
||||||
goto unknown_op;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
assert(b1 < 2);
|
||||||
sse_fn_epp = sse_op_table6[b].op[b1];
|
sse_fn_epp = sse_op_table6[b].op[b1];
|
||||||
if (!sse_fn_epp) {
|
if (!sse_fn_epp) {
|
||||||
goto unknown_op;
|
goto unknown_op;
|
||||||
|
@ -4200,10 +4196,8 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
|
||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
reg = ((modrm >> 3) & 7) | REX_R(s);
|
reg = ((modrm >> 3) & 7) | REX_R(s);
|
||||||
mod = (modrm >> 6) & 3;
|
mod = (modrm >> 6) & 3;
|
||||||
if (b1 >= 2) {
|
|
||||||
goto unknown_op;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
assert(b1 < 2);
|
||||||
sse_fn_eppi = sse_op_table7[b].op[b1];
|
sse_fn_eppi = sse_op_table7[b].op[b1];
|
||||||
if (!sse_fn_eppi) {
|
if (!sse_fn_eppi) {
|
||||||
goto unknown_op;
|
goto unknown_op;
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#define RX_CPU_H
|
#define RX_CPU_H
|
||||||
|
|
||||||
#include "qemu/bitops.h"
|
#include "qemu/bitops.h"
|
||||||
#include "qemu-common.h"
|
|
||||||
#include "hw/registerfields.h"
|
#include "hw/registerfields.h"
|
||||||
#include "cpu-qom.h"
|
#include "cpu-qom.h"
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1465,6 +1465,42 @@ static void test_acpi_virt_tcg(void)
|
||||||
free_test_data(&data);
|
free_test_data(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_acpi_q35_viot(void)
|
||||||
|
{
|
||||||
|
test_data data = {
|
||||||
|
.machine = MACHINE_Q35,
|
||||||
|
.variant = ".viot",
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To keep things interesting, two buses bypass the IOMMU.
|
||||||
|
* VIOT should only describes the other two buses.
|
||||||
|
*/
|
||||||
|
test_acpi_one("-machine default_bus_bypass_iommu=on "
|
||||||
|
"-device virtio-iommu-pci "
|
||||||
|
"-device pxb-pcie,bus_nr=0x10,id=pcie.100,bus=pcie.0 "
|
||||||
|
"-device pxb-pcie,bus_nr=0x20,id=pcie.200,bus=pcie.0,bypass_iommu=on "
|
||||||
|
"-device pxb-pcie,bus_nr=0x30,id=pcie.300,bus=pcie.0",
|
||||||
|
&data);
|
||||||
|
free_test_data(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_acpi_virt_viot(void)
|
||||||
|
{
|
||||||
|
test_data data = {
|
||||||
|
.machine = "virt",
|
||||||
|
.uefi_fl1 = "pc-bios/edk2-aarch64-code.fd",
|
||||||
|
.uefi_fl2 = "pc-bios/edk2-arm-vars.fd",
|
||||||
|
.cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2",
|
||||||
|
.ram_start = 0x40000000ULL,
|
||||||
|
.scan_len = 128ULL * 1024 * 1024,
|
||||||
|
};
|
||||||
|
|
||||||
|
test_acpi_one("-cpu cortex-a57 "
|
||||||
|
"-device virtio-iommu-pci", &data);
|
||||||
|
free_test_data(&data);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_oem_fields(test_data *data)
|
static void test_oem_fields(test_data *data)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -1639,6 +1675,7 @@ int main(int argc, char *argv[])
|
||||||
qtest_add_func("acpi/q35/kvm/xapic", test_acpi_q35_kvm_xapic);
|
qtest_add_func("acpi/q35/kvm/xapic", test_acpi_q35_kvm_xapic);
|
||||||
qtest_add_func("acpi/q35/kvm/dmar", test_acpi_q35_kvm_dmar);
|
qtest_add_func("acpi/q35/kvm/dmar", test_acpi_q35_kvm_dmar);
|
||||||
}
|
}
|
||||||
|
qtest_add_func("acpi/q35/viot", test_acpi_q35_viot);
|
||||||
} else if (strcmp(arch, "aarch64") == 0) {
|
} else if (strcmp(arch, "aarch64") == 0) {
|
||||||
if (has_tcg) {
|
if (has_tcg) {
|
||||||
qtest_add_func("acpi/virt", test_acpi_virt_tcg);
|
qtest_add_func("acpi/virt", test_acpi_virt_tcg);
|
||||||
|
@ -1646,6 +1683,7 @@ int main(int argc, char *argv[])
|
||||||
qtest_add_func("acpi/virt/memhp", test_acpi_virt_tcg_memhp);
|
qtest_add_func("acpi/virt/memhp", test_acpi_virt_tcg_memhp);
|
||||||
qtest_add_func("acpi/virt/pxb", test_acpi_virt_tcg_pxb);
|
qtest_add_func("acpi/virt/pxb", test_acpi_virt_tcg_pxb);
|
||||||
qtest_add_func("acpi/virt/oem-fields", test_acpi_oem_fields_virt);
|
qtest_add_func("acpi/virt/oem-fields", test_acpi_oem_fields_virt);
|
||||||
|
qtest_add_func("acpi/virt/viot", test_acpi_virt_viot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret = g_test_run();
|
ret = g_test_run();
|
||||||
|
|
|
@ -8,8 +8,8 @@ VPATH += $(ARM_SRC)
|
||||||
AARCH64_SRC=$(SRC_PATH)/tests/tcg/aarch64
|
AARCH64_SRC=$(SRC_PATH)/tests/tcg/aarch64
|
||||||
VPATH += $(AARCH64_SRC)
|
VPATH += $(AARCH64_SRC)
|
||||||
|
|
||||||
# Float-convert Tests
|
# Base architecture tests
|
||||||
AARCH64_TESTS=fcvt
|
AARCH64_TESTS=fcvt pcalign-a64
|
||||||
|
|
||||||
fcvt: LDFLAGS+=-lm
|
fcvt: LDFLAGS+=-lm
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/* Test PC misalignment exception */
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static void *expected;
|
||||||
|
|
||||||
|
static void sigbus(int sig, siginfo_t *info, void *vuc)
|
||||||
|
{
|
||||||
|
assert(info->si_code == BUS_ADRALN);
|
||||||
|
assert(info->si_addr == expected);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
void *tmp;
|
||||||
|
|
||||||
|
struct sigaction sa = {
|
||||||
|
.sa_sigaction = sigbus,
|
||||||
|
.sa_flags = SA_SIGINFO
|
||||||
|
};
|
||||||
|
|
||||||
|
if (sigaction(SIGBUS, &sa, NULL) < 0) {
|
||||||
|
perror("sigaction");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
asm volatile("adr %0, 1f + 1\n\t"
|
||||||
|
"str %0, %1\n\t"
|
||||||
|
"br %0\n"
|
||||||
|
"1:"
|
||||||
|
: "=&r"(tmp), "=m"(expected));
|
||||||
|
abort();
|
||||||
|
}
|
|
@ -29,6 +29,10 @@ run-fcvt: fcvt
|
||||||
$(call run-test,fcvt,$(QEMU) $<,"$< on $(TARGET_NAME)")
|
$(call run-test,fcvt,$(QEMU) $<,"$< on $(TARGET_NAME)")
|
||||||
$(call diff-out,fcvt,$(ARM_SRC)/fcvt.ref)
|
$(call diff-out,fcvt,$(ARM_SRC)/fcvt.ref)
|
||||||
|
|
||||||
|
# PC alignment test
|
||||||
|
ARM_TESTS += pcalign-a32
|
||||||
|
pcalign-a32: CFLAGS+=-marm
|
||||||
|
|
||||||
ifeq ($(CONFIG_ARM_COMPATIBLE_SEMIHOSTING),y)
|
ifeq ($(CONFIG_ARM_COMPATIBLE_SEMIHOSTING),y)
|
||||||
|
|
||||||
# Semihosting smoke test for linux-user
|
# Semihosting smoke test for linux-user
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/* Test PC misalignment exception */
|
||||||
|
|
||||||
|
#ifdef __thumb__
|
||||||
|
#error "This test must be compiled for ARM"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static void *expected;
|
||||||
|
|
||||||
|
static void sigbus(int sig, siginfo_t *info, void *vuc)
|
||||||
|
{
|
||||||
|
assert(info->si_code == BUS_ADRALN);
|
||||||
|
assert(info->si_addr == expected);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
void *tmp;
|
||||||
|
|
||||||
|
struct sigaction sa = {
|
||||||
|
.sa_sigaction = sigbus,
|
||||||
|
.sa_flags = SA_SIGINFO
|
||||||
|
};
|
||||||
|
|
||||||
|
if (sigaction(SIGBUS, &sa, NULL) < 0) {
|
||||||
|
perror("sigaction");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
asm volatile("adr %0, 1f + 2\n\t"
|
||||||
|
"str %0, %1\n\t"
|
||||||
|
"bx %0\n"
|
||||||
|
"1:"
|
||||||
|
: "=&r"(tmp), "=m"(expected));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From v8, it is CONSTRAINED UNPREDICTABLE whether BXWritePC aligns
|
||||||
|
* the address or not. If so, we can legitimately fall through.
|
||||||
|
*/
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
Loading…
Reference in New Issue