aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-03-05 16:47:37 +0000
committerPeter Maydell <peter.maydell@linaro.org>2020-03-05 16:47:37 +0000
commit55afdac3b29e672aad51e953412364127e54268b (patch)
treefbb209b6775c36491f15e597f5e80b0253d4ffb3
parentaf4378c39e54705d9b585089de80aae9526ac7e7 (diff)
parent597d61a3b1f94c53a3aaa77671697c0c5f797dbf (diff)
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20200305' into staging
* versal: Implement ADMA * Implement (trivially) ARMv8.2-TTCNP * hw/arm/smmu-common: a fix to smmu_find_smmu_pcibus * Remove unnecessary endianness-handling on some boards * Avoid minor memory leaks from timer_new in some devices * Honour more of the HCR_EL2 trap bits * Complain rather than ignoring bad command line options for cubieboard * Honour TBI for DC ZVA and exception return # gpg: Signature made Thu 05 Mar 2020 16:30:17 GMT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20200305: (37 commits) target/arm: Clean address for DC ZVA target/arm: Use DEF_HELPER_FLAGS for helper_dc_zva target/arm: Move helper_dc_zva to helper-a64.c target/arm: Apply TBI to ESR_ELx in helper_exception_return target/arm: Introduce core_to_aa64_mmu_idx target/arm: Optimize cpu_mmu_index target/arm: Replicate TBI/TBID bits for single range regimes hw/arm/cubieboard: report error when using unsupported -bios argument hw/arm/cubieboard: restrict allowed RAM size to 512MiB and 1GiB hw/arm/cubieboard: restrict allowed CPU type to ARM Cortex-A8 hw/arm/cubieboard: use ARM Cortex-A8 as the default CPU in machine definition tests/tcg/aarch64: Add newline in pauth-1 printf target/arm: Honor the HCR_EL2.TTLB bit target/arm: Honor the HCR_EL2.TPU bit target/arm: Honor the HCR_EL2.TPCP bit target/arm: Honor the HCR_EL2.TACR bit target/arm: Honor the HCR_EL2.TSW bit target/arm: Honor the HCR_EL2.{TVM,TRVM} bits target/arm: Improve masking in arm_hcr_el2_eff target/arm: Remove EL2 and EL3 setup from user-only ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/arm/cubieboard.c29
-rw-r--r--hw/arm/gumstix.c16
-rw-r--r--hw/arm/mainstone.c8
-rw-r--r--hw/arm/musicpal.c10
-rw-r--r--hw/arm/omap_sx1.c11
-rw-r--r--hw/arm/pxa2xx.c17
-rw-r--r--hw/arm/smmu-common.c20
-rw-r--r--hw/arm/spitz.c8
-rw-r--r--hw/arm/strongarm.c18
-rw-r--r--hw/arm/xlnx-versal-virt.c28
-rw-r--r--hw/arm/xlnx-versal.c24
-rw-r--r--hw/arm/z2.c8
-rw-r--r--hw/timer/cadence_ttc.c16
-rw-r--r--include/hw/arm/xlnx-versal.h6
-rw-r--r--target/arm/cpu.c13
-rw-r--r--target/arm/cpu.h30
-rw-r--r--target/arm/cpu64.c2
-rw-r--r--target/arm/helper-a64.c114
-rw-r--r--target/arm/helper-a64.h1
-rw-r--r--target/arm/helper.c373
-rw-r--r--target/arm/helper.h1
-rw-r--r--target/arm/internals.h6
-rw-r--r--target/arm/op_helper.c93
-rw-r--r--target/arm/translate-a64.c4
-rw-r--r--tests/tcg/aarch64/pauth-1.c2
25 files changed, 550 insertions, 308 deletions
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
index 089f9a30c1..871b1beef4 100644
--- a/hw/arm/cubieboard.c
+++ b/hw/arm/cubieboard.c
@@ -19,6 +19,7 @@
#include "exec/address-spaces.h"
#include "qapi/error.h"
#include "cpu.h"
+#include "sysemu/sysemu.h"
#include "hw/sysbus.h"
#include "hw/boards.h"
#include "hw/arm/allwinner-a10.h"
@@ -30,9 +31,30 @@ static struct arm_boot_info cubieboard_binfo = {
static void cubieboard_init(MachineState *machine)
{
- AwA10State *a10 = AW_A10(object_new(TYPE_AW_A10));
+ AwA10State *a10;
Error *err = NULL;
+ /* BIOS is not supported by this board */
+ if (bios_name) {
+ error_report("BIOS not supported for this machine");
+ exit(1);
+ }
+
+ /* This board has fixed size RAM (512MiB or 1GiB) */
+ if (machine->ram_size != 512 * MiB &&
+ machine->ram_size != 1 * GiB) {
+ error_report("This machine can only be used with 512MiB or 1GiB RAM");
+ exit(1);
+ }
+
+ /* Only allow Cortex-A8 for this board */
+ if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a8")) != 0) {
+ error_report("This board can only be used with cortex-a8 CPU");
+ exit(1);
+ }
+
+ a10 = AW_A10(object_new(TYPE_AW_A10));
+
object_property_set_int(OBJECT(&a10->emac), 1, "phy-addr", &err);
if (err != NULL) {
error_reportf_err(err, "Couldn't set phy address: ");
@@ -68,8 +90,9 @@ static void cubieboard_init(MachineState *machine)
static void cubieboard_machine_init(MachineClass *mc)
{
- mc->desc = "cubietech cubieboard (Cortex-A9)";
- mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a9");
+ mc->desc = "cubietech cubieboard (Cortex-A8)";
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a8");
+ mc->default_ram_size = 1 * GiB;
mc->init = cubieboard_init;
mc->block_default_type = IF_IDE;
mc->units_per_default_bus = 1;
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
index f26a0e8010..3a4bc332c4 100644
--- a/hw/arm/gumstix.c
+++ b/hw/arm/gumstix.c
@@ -51,7 +51,6 @@ static void connex_init(MachineState *machine)
{
PXA2xxState *cpu;
DriveInfo *dinfo;
- int be;
MemoryRegion *address_space_mem = get_system_memory();
uint32_t connex_rom = 0x01000000;
@@ -66,14 +65,9 @@ static void connex_init(MachineState *machine)
exit(1);
}
-#ifdef TARGET_WORDS_BIGENDIAN
- be = 1;
-#else
- be = 0;
-#endif
if (!pflash_cfi01_register(0x00000000, "connext.rom", connex_rom,
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
- sector_len, 2, 0, 0, 0, 0, be)) {
+ sector_len, 2, 0, 0, 0, 0, 0)) {
error_report("Error registering flash memory");
exit(1);
}
@@ -87,7 +81,6 @@ static void verdex_init(MachineState *machine)
{
PXA2xxState *cpu;
DriveInfo *dinfo;
- int be;
MemoryRegion *address_space_mem = get_system_memory();
uint32_t verdex_rom = 0x02000000;
@@ -102,14 +95,9 @@ static void verdex_init(MachineState *machine)
exit(1);
}
-#ifdef TARGET_WORDS_BIGENDIAN
- be = 1;
-#else
- be = 0;
-#endif
if (!pflash_cfi01_register(0x00000000, "verdex.rom", verdex_rom,
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
- sector_len, 2, 0, 0, 0, 0, be)) {
+ sector_len, 2, 0, 0, 0, 0, 0)) {
error_report("Error registering flash memory");
exit(1);
}
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
index 6e64dfab50..1042017086 100644
--- a/hw/arm/mainstone.c
+++ b/hw/arm/mainstone.c
@@ -119,7 +119,6 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
DeviceState *mst_irq;
DriveInfo *dinfo;
int i;
- int be;
MemoryRegion *rom = g_new(MemoryRegion, 1);
/* Setup CPU & memory */
@@ -130,11 +129,6 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
memory_region_set_readonly(rom, true);
memory_region_add_subregion(address_space_mem, 0, rom);
-#ifdef TARGET_WORDS_BIGENDIAN
- be = 1;
-#else
- be = 0;
-#endif
/* There are two 32MiB flash devices on the board */
for (i = 0; i < 2; i ++) {
dinfo = drive_get(IF_PFLASH, 0, i);
@@ -142,7 +136,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
i ? "mainstone.flash1" : "mainstone.flash0",
MAINSTONE_FLASH,
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
- sector_len, 4, 0, 0, 0, 0, be)) {
+ sector_len, 4, 0, 0, 0, 0, 0)) {
error_report("Error registering flash memory");
exit(1);
}
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index db8b03cb83..b2d0cfdac8 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -1645,22 +1645,12 @@ static void musicpal_init(MachineState *machine)
* 0xFF800000 (if there is 8 MB flash). So remap flash access if the
* image is smaller than 32 MB.
*/
-#ifdef TARGET_WORDS_BIGENDIAN
- pflash_cfi02_register(0x100000000ULL - MP_FLASH_SIZE_MAX,
- "musicpal.flash", flash_size,
- blk, 0x10000,
- MP_FLASH_SIZE_MAX / flash_size,
- 2, 0x00BF, 0x236D, 0x0000, 0x0000,
- 0x5555, 0x2AAA, 1);
-#else
pflash_cfi02_register(0x100000000ULL - MP_FLASH_SIZE_MAX,
"musicpal.flash", flash_size,
blk, 0x10000,
MP_FLASH_SIZE_MAX / flash_size,
2, 0x00BF, 0x236D, 0x0000, 0x0000,
0x5555, 0x2AAA, 0);
-#endif
-
}
sysbus_create_simple(TYPE_MV88W8618_FLASHCFG, MP_FLASHCFG_BASE, NULL);
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
index 2bebab4171..de5ff447dc 100644
--- a/hw/arm/omap_sx1.c
+++ b/hw/arm/omap_sx1.c
@@ -114,7 +114,6 @@ static void sx1_init(MachineState *machine, const int version)
DriveInfo *dinfo;
int fl_idx;
uint32_t flash_size = flash0_size;
- int be;
if (machine->ram_size != mc->default_ram_size) {
char *sz = size_to_str(mc->default_ram_size);
@@ -154,17 +153,11 @@ static void sx1_init(MachineState *machine, const int version)
OMAP_CS2_BASE, &cs[3]);
fl_idx = 0;
-#ifdef TARGET_WORDS_BIGENDIAN
- be = 1;
-#else
- be = 0;
-#endif
-
if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
if (!pflash_cfi01_register(OMAP_CS0_BASE,
"omap_sx1.flash0-1", flash_size,
blk_by_legacy_dinfo(dinfo),
- sector_size, 4, 0, 0, 0, 0, be)) {
+ sector_size, 4, 0, 0, 0, 0, 0)) {
fprintf(stderr, "qemu: Error registering flash memory %d.\n",
fl_idx);
}
@@ -187,7 +180,7 @@ static void sx1_init(MachineState *machine, const int version)
if (!pflash_cfi01_register(OMAP_CS1_BASE,
"omap_sx1.flash1-1", flash1_size,
blk_by_legacy_dinfo(dinfo),
- sector_size, 4, 0, 0, 0, 0, be)) {
+ sector_size, 4, 0, 0, 0, 0, 0)) {
fprintf(stderr, "qemu: Error registering flash memory %d.\n",
fl_idx);
}
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index b33f8f1351..56a36202d7 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -1134,18 +1134,22 @@ static void pxa2xx_rtc_init(Object *obj)
s->last_rtcpicr = 0;
s->last_hz = s->last_sw = s->last_pi = qemu_clock_get_ms(rtc_clock);
+ sysbus_init_irq(dev, &s->rtc_irq);
+
+ memory_region_init_io(&s->iomem, obj, &pxa2xx_rtc_ops, s,
+ "pxa2xx-rtc", 0x10000);
+ sysbus_init_mmio(dev, &s->iomem);
+}
+
+static void pxa2xx_rtc_realize(DeviceState *dev, Error **errp)
+{
+ PXA2xxRTCState *s = PXA2XX_RTC(dev);
s->rtc_hz = timer_new_ms(rtc_clock, pxa2xx_rtc_hz_tick, s);
s->rtc_rdal1 = timer_new_ms(rtc_clock, pxa2xx_rtc_rdal1_tick, s);
s->rtc_rdal2 = timer_new_ms(rtc_clock, pxa2xx_rtc_rdal2_tick, s);
s->rtc_swal1 = timer_new_ms(rtc_clock, pxa2xx_rtc_swal1_tick, s);
s->rtc_swal2 = timer_new_ms(rtc_clock, pxa2xx_rtc_swal2_tick, s);
s->rtc_pi = timer_new_ms(rtc_clock, pxa2xx_rtc_pi_tick, s);
-
- sysbus_init_irq(dev, &s->rtc_irq);
-
- memory_region_init_io(&s->iomem, obj, &pxa2xx_rtc_ops, s,
- "pxa2xx-rtc", 0x10000);
- sysbus_init_mmio(dev, &s->iomem);
}
static int pxa2xx_rtc_pre_save(void *opaque)
@@ -1203,6 +1207,7 @@ static void pxa2xx_rtc_sysbus_class_init(ObjectClass *klass, void *data)
dc->desc = "PXA2xx RTC Controller";
dc->vmsd = &vmstate_pxa2xx_rtc_regs;
+ dc->realize = pxa2xx_rtc_realize;
}
static const TypeInfo pxa2xx_rtc_sysbus_info = {
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
index 0f2573f004..e13a5f4a7c 100644
--- a/hw/arm/smmu-common.c
+++ b/hw/arm/smmu-common.c
@@ -290,19 +290,21 @@ inline int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num)
{
SMMUPciBus *smmu_pci_bus = s->smmu_pcibus_by_bus_num[bus_num];
+ GHashTableIter iter;
- if (!smmu_pci_bus) {
- GHashTableIter iter;
+ if (smmu_pci_bus) {
+ return smmu_pci_bus;
+ }
- g_hash_table_iter_init(&iter, s->smmu_pcibus_by_busptr);
- while (g_hash_table_iter_next(&iter, NULL, (void **)&smmu_pci_bus)) {
- if (pci_bus_num(smmu_pci_bus->bus) == bus_num) {
- s->smmu_pcibus_by_bus_num[bus_num] = smmu_pci_bus;
- return smmu_pci_bus;
- }
+ g_hash_table_iter_init(&iter, s->smmu_pcibus_by_busptr);
+ while (g_hash_table_iter_next(&iter, NULL, (void **)&smmu_pci_bus)) {
+ if (pci_bus_num(smmu_pci_bus->bus) == bus_num) {
+ s->smmu_pcibus_by_bus_num[bus_num] = smmu_pci_bus;
+ return smmu_pci_bus;
}
}
- return smmu_pci_bus;
+
+ return NULL;
}
static AddressSpace *smmu_find_add_as(PCIBus *bus, void *opaque, int devfn)
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index e001088103..cbfa6934cf 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -524,11 +524,16 @@ static void spitz_keyboard_init(Object *obj)
spitz_keyboard_pre_map(s);
- s->kbdtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, spitz_keyboard_tick, s);
qdev_init_gpio_in(dev, spitz_keyboard_strobe, SPITZ_KEY_STROBE_NUM);
qdev_init_gpio_out(dev, s->sense, SPITZ_KEY_SENSE_NUM);
}
+static void spitz_keyboard_realize(DeviceState *dev, Error **errp)
+{
+ SpitzKeyboardState *s = SPITZ_KEYBOARD(dev);
+ s->kbdtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, spitz_keyboard_tick, s);
+}
+
/* LCD backlight controller */
#define LCDTG_RESCTL 0x00
@@ -1115,6 +1120,7 @@ static void spitz_keyboard_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->vmsd = &vmstate_spitz_kbd;
+ dc->realize = spitz_keyboard_realize;
}
static const TypeInfo spitz_keyboard_info = {
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index cd8a99aaf2..3010d765bb 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -399,9 +399,6 @@ static void strongarm_rtc_init(Object *obj)
s->last_rcnr = (uint32_t) mktimegm(&tm);
s->last_hz = qemu_clock_get_ms(rtc_clock);
- s->rtc_alarm = timer_new_ms(rtc_clock, strongarm_rtc_alarm_tick, s);
- s->rtc_hz = timer_new_ms(rtc_clock, strongarm_rtc_hz_tick, s);
-
sysbus_init_irq(dev, &s->rtc_irq);
sysbus_init_irq(dev, &s->rtc_hz_irq);
@@ -410,6 +407,13 @@ static void strongarm_rtc_init(Object *obj)
sysbus_init_mmio(dev, &s->iomem);
}
+static void strongarm_rtc_realize(DeviceState *dev, Error **errp)
+{
+ StrongARMRTCState *s = STRONGARM_RTC(dev);
+ s->rtc_alarm = timer_new_ms(rtc_clock, strongarm_rtc_alarm_tick, s);
+ s->rtc_hz = timer_new_ms(rtc_clock, strongarm_rtc_hz_tick, s);
+}
+
static int strongarm_rtc_pre_save(void *opaque)
{
StrongARMRTCState *s = opaque;
@@ -451,6 +455,7 @@ static void strongarm_rtc_sysbus_class_init(ObjectClass *klass, void *data)
dc->desc = "StrongARM RTC Controller";
dc->vmsd = &vmstate_strongarm_rtc_regs;
+ dc->realize = strongarm_rtc_realize;
}
static const TypeInfo strongarm_rtc_sysbus_info = {
@@ -1240,15 +1245,16 @@ static void strongarm_uart_init(Object *obj)
"uart", 0x10000);
sysbus_init_mmio(dev, &s->iomem);
sysbus_init_irq(dev, &s->irq);
-
- s->rx_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, strongarm_uart_rx_to, s);
- s->tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, strongarm_uart_tx, s);
}
static void strongarm_uart_realize(DeviceState *dev, Error **errp)
{
StrongARMUARTState *s = STRONGARM_UART(dev);
+ s->rx_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+ strongarm_uart_rx_to,
+ s);
+ s->tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, strongarm_uart_tx, s);
qemu_chr_fe_set_handlers(&s->chr,
strongarm_uart_can_receive,
strongarm_uart_receive,
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index e7f4ca8bf9..878a275140 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -229,6 +229,33 @@ static void fdt_add_gem_nodes(VersalVirt *s)
}
}
+static void fdt_add_zdma_nodes(VersalVirt *s)
+{
+ const char clocknames[] = "clk_main\0clk_apb";
+ const char compat[] = "xlnx,zynqmp-dma-1.0";
+ int i;
+
+ for (i = XLNX_VERSAL_NR_ADMAS - 1; i >= 0; i--) {
+ uint64_t addr = MM_ADMA_CH0 + MM_ADMA_CH0_SIZE * i;
+ char *name = g_strdup_printf("/dma@%" PRIx64, addr);
+
+ qemu_fdt_add_subnode(s->fdt, name);
+
+ qemu_fdt_setprop_cell(s->fdt, name, "xlnx,bus-width", 64);
+ qemu_fdt_setprop_cells(s->fdt, name, "clocks",
+ s->phandle.clk_25Mhz, s->phandle.clk_25Mhz);
+ qemu_fdt_setprop(s->fdt, name, "clock-names",
+ clocknames, sizeof(clocknames));
+ qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
+ GIC_FDT_IRQ_TYPE_SPI, VERSAL_ADMA_IRQ_0 + i,
+ GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+ qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
+ 2, addr, 2, 0x1000);
+ qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
+ g_free(name);
+ }
+}
+
static void fdt_nop_memory_nodes(void *fdt, Error **errp)
{
Error *err = NULL;
@@ -427,6 +454,7 @@ static void versal_virt_init(MachineState *machine)
fdt_add_uart_nodes(s);
fdt_add_gic_nodes(s);
fdt_add_timer_nodes(s);
+ fdt_add_zdma_nodes(s);
fdt_add_cpu_nodes(s, psci_conduit);
fdt_add_clk_node(s, "/clk125", 125000000, s->phandle.clk_125Mhz);
fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 403fc7b881..cb0122a3a6 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -194,6 +194,29 @@ static void versal_create_gems(Versal *s, qemu_irq *pic)
}
}
+static void versal_create_admas(Versal *s, qemu_irq *pic)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
+ char *name = g_strdup_printf("adma%d", i);
+ DeviceState *dev;
+ MemoryRegion *mr;
+
+ dev = qdev_create(NULL, "xlnx.zdma");
+ s->lpd.iou.adma[i] = SYS_BUS_DEVICE(dev);
+ object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
+ qdev_init_nofail(dev);
+
+ mr = sysbus_mmio_get_region(s->lpd.iou.adma[i], 0);
+ memory_region_add_subregion(&s->mr_ps,
+ MM_ADMA_CH0 + i * MM_ADMA_CH0_SIZE, mr);
+
+ sysbus_connect_irq(s->lpd.iou.adma[i], 0, pic[VERSAL_ADMA_IRQ_0 + i]);
+ g_free(name);
+ }
+}
+
/* This takes the board allocated linear DDR memory and creates aliases
* for each split DDR range/aperture on the Versal address map.
*/
@@ -275,6 +298,7 @@ static void versal_realize(DeviceState *dev, Error **errp)
versal_create_apu_gic(s, pic);
versal_create_uarts(s, pic);
versal_create_gems(s, pic);
+ versal_create_admas(s, pic);
versal_map_ddr(s);
versal_unimp(s);
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
index 4bb237f22d..a0f4095990 100644
--- a/hw/arm/z2.c
+++ b/hw/arm/z2.c
@@ -300,7 +300,6 @@ static void z2_init(MachineState *machine)
uint32_t sector_len = 0x10000;
PXA2xxState *mpu;
DriveInfo *dinfo;
- int be;
void *z2_lcd;
I2CBus *bus;
DeviceState *wm;
@@ -308,15 +307,10 @@ static void z2_init(MachineState *machine)
/* Setup CPU & memory */
mpu = pxa270_init(address_space_mem, z2_binfo.ram_size, machine->cpu_type);
-#ifdef TARGET_WORDS_BIGENDIAN
- be = 1;
-#else
- be = 0;
-#endif
dinfo = drive_get(IF_PFLASH, 0, 0);
if (!pflash_cfi01_register(Z2_FLASH_BASE, "z2.flash0", Z2_FLASH_SIZE,
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
- sector_len, 4, 0, 0, 0, 0, be)) {
+ sector_len, 4, 0, 0, 0, 0, 0)) {
error_report("Error registering flash memory");
exit(1);
}
diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c
index 5e3128c1e3..b0ba6b2bba 100644
--- a/hw/timer/cadence_ttc.c
+++ b/hw/timer/cadence_ttc.c
@@ -412,16 +412,21 @@ static void cadence_timer_init(uint32_t freq, CadenceTimerState *s)
static void cadence_ttc_init(Object *obj)
{
CadenceTTCState *s = CADENCE_TTC(obj);
+
+ memory_region_init_io(&s->iomem, obj, &cadence_ttc_ops, s,
+ "timer", 0x1000);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
+}
+
+static void cadence_ttc_realize(DeviceState *dev, Error **errp)
+{
+ CadenceTTCState *s = CADENCE_TTC(dev);
int i;
for (i = 0; i < 3; ++i) {
cadence_timer_init(133000000, &s->timer[i]);
- sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->timer[i].irq);
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->timer[i].irq);
}
-
- memory_region_init_io(&s->iomem, obj, &cadence_ttc_ops, s,
- "timer", 0x1000);
- sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
}
static int cadence_timer_pre_save(void *opaque)
@@ -479,6 +484,7 @@ static void cadence_ttc_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->vmsd = &vmstate_cadence_ttc;
+ dc->realize = cadence_ttc_realize;
}
static const TypeInfo cadence_ttc_info = {
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index d844c4ffe4..6c0a692b2f 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -22,6 +22,7 @@
#define XLNX_VERSAL_NR_ACPUS 2
#define XLNX_VERSAL_NR_UARTS 2
#define XLNX_VERSAL_NR_GEMS 2
+#define XLNX_VERSAL_NR_ADMAS 8
#define XLNX_VERSAL_NR_IRQS 192
typedef struct Versal {
@@ -50,6 +51,7 @@ typedef struct Versal {
struct {
SysBusDevice *uart[XLNX_VERSAL_NR_UARTS];
SysBusDevice *gem[XLNX_VERSAL_NR_GEMS];
+ SysBusDevice *adma[XLNX_VERSAL_NR_ADMAS];
} iou;
} lpd;
@@ -74,6 +76,7 @@ typedef struct Versal {
#define VERSAL_GEM0_WAKE_IRQ_0 57
#define VERSAL_GEM1_IRQ_0 58
#define VERSAL_GEM1_WAKE_IRQ_0 59
+#define VERSAL_ADMA_IRQ_0 60
/* Architecturally reserved IRQs suitable for virtualization. */
#define VERSAL_RSVD_IRQ_FIRST 111
@@ -96,6 +99,9 @@ typedef struct Versal {
#define MM_GEM1 0xff0d0000U
#define MM_GEM1_SIZE 0x10000
+#define MM_ADMA_CH0 0xffa80000U
+#define MM_ADMA_CH0_SIZE 0x10000
+
#define MM_OCM 0xfffc0000U
#define MM_OCM_SIZE 0x40000
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index e6016e33ce..3623ecefbd 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -191,19 +191,13 @@ static void arm_cpu_reset(CPUState *s)
/* Enable all PAC keys. */
env->cp15.sctlr_el[1] |= (SCTLR_EnIA | SCTLR_EnIB |
SCTLR_EnDA | SCTLR_EnDB);
- /* Enable all PAC instructions */
- env->cp15.hcr_el2 |= HCR_API;
- env->cp15.scr_el3 |= SCR_API;
/* and to the FP/Neon instructions */
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 20, 2, 3);
/* and to the SVE instructions */
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 16, 2, 3);
- env->cp15.cptr_el[3] |= CPTR_EZ;
/* with maximum vector length */
env->vfp.zcr_el[1] = cpu_isar_feature(aa64_sve, cpu) ?
cpu->sve_max_vq - 1 : 0;
- env->vfp.zcr_el[2] = env->vfp.zcr_el[1];
- env->vfp.zcr_el[3] = env->vfp.zcr_el[1];
/*
* Enable TBI0 and TBI1. While the real kernel only enables TBI0,
* turning on both here will produce smaller code and otherwise
@@ -1103,11 +1097,13 @@ static Property arm_cpu_reset_hivecs_property =
static Property arm_cpu_rvbar_property =
DEFINE_PROP_UINT64("rvbar", ARMCPU, rvbar, 0);
+#ifndef CONFIG_USER_ONLY
static Property arm_cpu_has_el2_property =
DEFINE_PROP_BOOL("has_el2", ARMCPU, has_el2, true);
static Property arm_cpu_has_el3_property =
DEFINE_PROP_BOOL("has_el3", ARMCPU, has_el3, true);
+#endif
static Property arm_cpu_cfgend_property =
DEFINE_PROP_BOOL("cfgend", ARMCPU, cfgend, false);
@@ -1222,25 +1218,25 @@ void arm_cpu_post_init(Object *obj)
qdev_property_add_static(DEVICE(obj), &arm_cpu_rvbar_property);
}
+#ifndef CONFIG_USER_ONLY
if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) {
/* Add the has_el3 state CPU property only if EL3 is allowed. This will
* prevent "has_el3" from existing on CPUs which cannot support EL3.
*/
qdev_property_add_static(DEVICE(obj), &arm_cpu_has_el3_property);
-#ifndef CONFIG_USER_ONLY
object_property_add_link(obj, "secure-memory",
TYPE_MEMORY_REGION,
(Object **)&cpu->secure_memory,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_STRONG,
&error_abort);
-#endif
}
if (arm_feature(&cpu->env, ARM_FEATURE_EL2)) {
qdev_property_add_static(DEVICE(obj), &arm_cpu_has_el2_property);
}
+#endif
if (arm_feature(&cpu->env, ARM_FEATURE_PMU)) {
cpu->has_pmu = true;
@@ -2702,6 +2698,7 @@ static void arm_max_initfn(Object *obj)
t = cpu->isar.id_mmfr4;
t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
+ t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
cpu->isar.id_mmfr4 = t;
}
#endif
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 0b84742b66..4ffd991b6f 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1410,6 +1410,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
#define HCR_TERR (1ULL << 36)
#define HCR_TEA (1ULL << 37)
#define HCR_MIOCNCE (1ULL << 38)
+/* RES0 bit 39 */
#define HCR_APK (1ULL << 40)
#define HCR_API (1ULL << 41)
#define HCR_NV (1ULL << 42)
@@ -1418,13 +1419,19 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
#define HCR_NV2 (1ULL << 45)
#define HCR_FWB (1ULL << 46)
#define HCR_FIEN (1ULL << 47)
+/* RES0 bit 48 */
#define HCR_TID4 (1ULL << 49)
#define HCR_TICAB (1ULL << 50)
+#define HCR_AMVOFFEN (1ULL << 51)
#define HCR_TOCU (1ULL << 52)
+#define HCR_ENSCXT (1ULL << 53)
#define HCR_TTLBIS (1ULL << 54)
#define HCR_TTLBOS (1ULL << 55)
#define HCR_ATA (1ULL << 56)
#define HCR_DCT (1ULL << 57)
+#define HCR_TID5 (1ULL << 58)
+#define HCR_TWEDEN (1ULL << 59)
+#define HCR_TWEDEL MAKE_64BIT_MASK(60, 4)
#define SCR_NS (1U << 0)
#define SCR_IRQ (1U << 1)
@@ -2936,16 +2943,6 @@ typedef enum ARMMMUIdxBit {
#define MMU_USER_IDX 0
-/**
- * cpu_mmu_index:
- * @env: The cpu environment
- * @ifetch: True for code access, false for data access.
- *
- * Return the core mmu index for the current translation regime.
- * This function is used by generic TCG code paths.
- */
-int cpu_mmu_index(CPUARMState *env, bool ifetch);
-
/* Indexes used when registering address spaces with cpu_address_space_init */
typedef enum ARMASIdx {
ARMASIdx_NS = 0,
@@ -3225,6 +3222,19 @@ FIELD(TBFLAG_A64, BTYPE, 10, 2) /* Not cached. */
FIELD(TBFLAG_A64, TBID, 12, 2)
FIELD(TBFLAG_A64, UNPRIV, 14, 1)
+/**
+ * cpu_mmu_index:
+ * @env: The cpu environment
+ * @ifetch: True for code access, false for data access.
+ *
+ * Return the core mmu index for the current translation regime.
+ * This function is used by generic TCG code paths.
+ */
+static inline int cpu_mmu_index(CPUARMState *env, bool ifetch)
+{
+ return FIELD_EX32(env->hflags, TBFLAG_ANY, MMUIDX);
+}
+
static inline bool bswap_code(bool sctlr_b)
{
#ifdef CONFIG_USER_ONLY
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index b842e2b664..62d36f9e8d 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -677,6 +677,7 @@ static void aarch64_max_initfn(Object *obj)
t = cpu->isar.id_aa64mmfr2;
t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
+ t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */
cpu->isar.id_aa64mmfr2 = t;
/* Replicate the same data to the 32-bit id registers. */
@@ -704,6 +705,7 @@ static void aarch64_max_initfn(Object *obj)
u = cpu->isar.id_mmfr4;
u = FIELD_DP32(u, ID_MMFR4, HPDS, 1); /* AA32HPD */
u = FIELD_DP32(u, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */
+ u = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */
cpu->isar.id_mmfr4 = u;
u = cpu->isar.id_aa64dfr0;
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index 509ae93069..bc0649a44a 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -18,6 +18,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/units.h"
#include "cpu.h"
#include "exec/gdbstub.h"
#include "exec/helper-proto.h"
@@ -1031,6 +1032,8 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
"AArch32 EL%d PC 0x%" PRIx32 "\n",
cur_el, new_el, env->regs[15]);
} else {
+ int tbii;
+
env->aarch64 = 1;
spsr &= aarch64_pstate_valid_mask(&env_archcpu(env)->isar);
pstate_write(env, spsr);
@@ -1038,8 +1041,27 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
env->pstate &= ~PSTATE_SS;
}
aarch64_restore_sp(env, new_el);
- env->pc = new_pc;
helper_rebuild_hflags_a64(env, new_el);
+
+ /*
+ * Apply TBI to the exception return address. We had to delay this
+ * until after we selected the new EL, so that we could select the
+ * correct TBI+TBID bits. This is made easier by waiting until after
+ * the hflags rebuild, since we can pull the composite TBII field
+ * from there.
+ */
+ tbii = FIELD_EX32(env->hflags, TBFLAG_A64, TBII);
+ if ((tbii >> extract64(new_pc, 55, 1)) & 1) {
+ /* TBI is enabled. */
+ int core_mmu_idx = cpu_mmu_index(env, false);
+ if (regime_has_2_ranges(core_to_aa64_mmu_idx(core_mmu_idx))) {
+ new_pc = sextract64(new_pc, 0, 56);
+ } else {
+ new_pc = extract64(new_pc, 0, 56);
+ }
+ }
+ env->pc = new_pc;
+
qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
"AArch64 EL%d PC 0x%" PRIx64 "\n",
cur_el, new_el, env->pc);
@@ -1088,4 +1110,94 @@ uint32_t HELPER(sqrt_f16)(uint32_t a, void *fpstp)
return float16_sqrt(a, s);
}
+void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in)
+{
+ /*
+ * Implement DC ZVA, which zeroes a fixed-length block of memory.
+ * Note that we do not implement the (architecturally mandated)
+ * alignment fault for attempts to use this on Device memory
+ * (which matches the usual QEMU behaviour of not implementing either
+ * alignment faults or any memory attribute handling).
+ */
+
+ ARMCPU *cpu = env_archcpu(env);
+ uint64_t blocklen = 4 << cpu->dcz_blocksize;
+ uint64_t vaddr = vaddr_in & ~(blocklen - 1);
+
+#ifndef CONFIG_USER_ONLY
+ {
+ /*
+ * Slightly awkwardly, QEMU's TARGET_PAGE_SIZE may be less than
+ * the block size so we might have to do more than one TLB lookup.
+ * We know that in fact for any v8 CPU the page size is at least 4K
+ * and the block size must be 2K or less, but TARGET_PAGE_SIZE is only
+ * 1K as an artefact of legacy v5 subpage support being present in the
+ * same QEMU executable. So in practice the hostaddr[] array has
+ * two entries, given the current setting of TARGET_PAGE_BITS_MIN.
+ */
+ int maxidx = DIV_ROUND_UP(blocklen, TARGET_PAGE_SIZE);
+ void *hostaddr[DIV_ROUND_UP(2 * KiB, 1 << TARGET_PAGE_BITS_MIN)];
+ int try, i;
+ unsigned mmu_idx = cpu_mmu_index(env, false);
+ TCGMemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
+
+ assert(maxidx <= ARRAY_SIZE(hostaddr));
+
+ for (try = 0; try < 2; try++) {
+
+ for (i = 0; i < maxidx; i++) {
+ hostaddr[i] = tlb_vaddr_to_host(env,
+ vaddr + TARGET_PAGE_SIZE * i,
+ 1, mmu_idx);
+ if (!hostaddr[i]) {
+ break;
+ }
+ }
+ if (i == maxidx) {
+ /*
+ * If it's all in the TLB it's fair game for just writing to;
+ * we know we don't need to update dirty status, etc.
+ */
+ for (i = 0; i < maxidx - 1; i++) {
+ memset(hostaddr[i], 0, TARGET_PAGE_SIZE);
+ }
+ memset(hostaddr[i], 0, blocklen - (i * TARGET_PAGE_SIZE));
+ return;
+ }
+ /*
+ * OK, try a store and see if we can populate the tlb. This
+ * might cause an exception if the memory isn't writable,
+ * in which case we will longjmp out of here. We must for
+ * this purpose use the actual register value passed to us
+ * so that we get the fault address right.
+ */
+ helper_ret_stb_mmu(env, vaddr_in, 0, oi, GETPC());
+ /* Now we can populate the other TLB entries, if any */
+ for (i = 0; i < maxidx; i++) {
+ uint64_t va = vaddr + TARGET_PAGE_SIZE * i;
+ if (va != (vaddr_in & TARGET_PAGE_MASK)) {
+ helper_ret_stb_mmu(env, va, 0, oi, GETPC());
+ }
+ }
+ }
+ /*
+ * Slow path (probably attempt to do this to an I/O device or
+ * similar, or clearing of a block of code we have translations
+ * cached for). Just do a series of byte writes as the architecture
+ * demands. It's not worth trying to use a cpu_physical_memory_map(),
+ * memset(), unmap() sequence here because:
+ * + we'd need to account for the blocksize being larger than a page
+ * + the direct-RAM access case is almost always going to be dealt
+ * with in the fastpath code above, so there's no speed benefit
+ * + we would have to deal with the map returning NULL because the
+ * bounce buffer was in use
+ */
+ for (i = 0; i < blocklen; i++) {
+ helper_ret_stb_mmu(env, vaddr + i, 0, oi, GETPC());
+ }
+ }
+#else
+ memset(g2h(vaddr), 0, blocklen);
+#endif
+}
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
index a915c1247f..3df7c185aa 100644
--- a/target/arm/helper-a64.h
+++ b/target/arm/helper-a64.h
@@ -90,6 +90,7 @@ DEF_HELPER_2(advsimd_f16touinth, i32, f16, ptr)
DEF_HELPER_2(sqrt_f16, f16, f16, ptr)
DEF_HELPER_2(exception_return, void, env, i64)
+DEF_HELPER_FLAGS_2(dc_zva, TCG_CALL_NO_WG, void, env, i64)
DEF_HELPER_FLAGS_3(pacia, TCG_CALL_NO_WG, i64, env, i64, i64)
DEF_HELPER_FLAGS_3(pacib, TCG_CALL_NO_WG, i64, env, i64, i64)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 6be9ffa09e..f91e5d5345 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -530,6 +530,49 @@ static CPAccessResult access_tpm(CPUARMState *env, const ARMCPRegInfo *ri,
return CP_ACCESS_OK;
}
+/* Check for traps from EL1 due to HCR_EL2.TVM and HCR_EL2.TRVM. */
+static CPAccessResult access_tvm_trvm(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ if (arm_current_el(env) == 1) {
+ uint64_t trap = isread ? HCR_TRVM : HCR_TVM;
+ if (arm_hcr_el2_eff(env) & trap) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ }
+ return CP_ACCESS_OK;
+}
+
+/* Check for traps from EL1 due to HCR_EL2.TSW. */
+static CPAccessResult access_tsw(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ if (arm_current_el(env) == 1 && (arm_hcr_el2_eff(env) & HCR_TSW)) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ return CP_ACCESS_OK;
+}
+
+/* Check for traps from EL1 due to HCR_EL2.TACR. */
+static CPAccessResult access_tacr(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ if (arm_current_el(env) == 1 && (arm_hcr_el2_eff(env) & HCR_TACR)) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ return CP_ACCESS_OK;
+}
+
+/* Check for traps from EL1 due to HCR_EL2.TTLB. */
+static CPAccessResult access_ttlb(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ if (arm_current_el(env) == 1 && (arm_hcr_el2_eff(env) & HCR_TTLB)) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ return CP_ACCESS_OK;
+}
+
static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
{
ARMCPU *cpu = env_archcpu(env);
@@ -785,12 +828,14 @@ static const ARMCPRegInfo cp_reginfo[] = {
*/
{ .name = "CONTEXTIDR_EL1", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 1,
- .access = PL1_RW, .secure = ARM_CP_SECSTATE_NS,
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .secure = ARM_CP_SECSTATE_NS,
.fieldoffset = offsetof(CPUARMState, cp15.contextidr_el[1]),
.resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, },
{ .name = "CONTEXTIDR_S", .state = ARM_CP_STATE_AA32,
.cp = 15, .opc1 = 0, .crn = 13, .crm = 0, .opc2 = 1,
- .access = PL1_RW, .secure = ARM_CP_SECSTATE_S,
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .secure = ARM_CP_SECSTATE_S,
.fieldoffset = offsetof(CPUARMState, cp15.contextidr_s),
.resetvalue = 0, .writefn = contextidr_write, .raw_writefn = raw_write, },
REGINFO_SENTINEL
@@ -803,7 +848,7 @@ static const ARMCPRegInfo not_v8_cp_reginfo[] = {
/* MMU Domain access control / MPU write buffer control */
{ .name = "DACR",
.cp = 15, .opc1 = CP_ANY, .crn = 3, .crm = CP_ANY, .opc2 = CP_ANY,
- .access = PL1_RW, .resetvalue = 0,
+ .access = PL1_RW, .accessfn = access_tvm_trvm, .resetvalue = 0,
.writefn = dacr_write, .raw_writefn = raw_write,
.bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.dacr_s),
offsetoflow32(CPUARMState, cp15.dacr_ns) } },
@@ -996,7 +1041,7 @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
{ .name = "DMB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 5,
.access = PL0_W, .type = ARM_CP_NOP },
{ .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 2,
- .access = PL1_RW,
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.ifar_s),
offsetof(CPUARMState, cp15.ifar_ns) },
.resetvalue = 0, },
@@ -2208,16 +2253,19 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
*/
{ .name = "AFSR0_EL1", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 0, .crn = 5, .crm = 1, .opc2 = 0,
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "AFSR1_EL1", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 0, .crn = 5, .crm = 1, .opc2 = 1,
- .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
/* MAIR can just read-as-written because we don't implement caches
* and so don't need to care about memory attributes.
*/
{ .name = "MAIR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0,
- .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el[1]),
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .fieldoffset = offsetof(CPUARMState, cp15.mair_el[1]),
.resetvalue = 0 },
{ .name = "MAIR_EL3", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 6, .crn = 10, .crm = 2, .opc2 = 0,
@@ -2231,12 +2279,14 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
* handled in the field definitions.
*/
{ .name = "MAIR0", .state = ARM_CP_STATE_AA32,
- .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0, .access = PL1_RW,
+ .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0,
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.mair0_s),
offsetof(CPUARMState, cp15.mair0_ns) },
.resetfn = arm_cp_reset_ignore },
{ .name = "MAIR1", .state = ARM_CP_STATE_AA32,
- .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 1, .access = PL1_RW,
+ .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 1,
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.mair1_s),
offsetof(CPUARMState, cp15.mair1_ns) },
.resetfn = arm_cp_reset_ignore },
@@ -2245,41 +2295,53 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
.type = ARM_CP_NO_RAW, .access = PL1_R, .readfn = isr_read },
/* 32 bit ITLB invalidates */
{ .name = "ITLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 0,
- .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiall_write },
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
+ .writefn = tlbiall_write },
{ .name = "ITLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 1,
- .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimva_write },
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
+ .writefn = tlbimva_write },
{ .name = "ITLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 2,
- .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiasid_write },
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
+ .writefn = tlbiasid_write },
/* 32 bit DTLB invalidates */
{ .name = "DTLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 0,
- .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiall_write },
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
+ .writefn = tlbiall_write },
{ .name = "DTLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 1,
- .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimva_write },
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
+ .writefn = tlbimva_write },
{ .name = "DTLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 2,
- .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiasid_write },
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
+ .writefn = tlbiasid_write },
/* 32 bit TLB invalidates */
{ .name = "TLBIALL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0,
- .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiall_write },
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
+ .writefn = tlbiall_write },
{ .name = "TLBIMVA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1,
- .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimva_write },
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
+ .writefn = tlbimva_write },
{ .name = "TLBIASID", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2,
- .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiasid_write },
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
+ .writefn = tlbiasid_write },
{ .name = "TLBIMVAA", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
- .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimvaa_write },
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
+ .writefn = tlbimvaa_write },
REGINFO_SENTINEL
};
static const ARMCPRegInfo v7mp_cp_reginfo[] = {
/* 32 bit TLB invalidates, Inner Shareable */
{ .name = "TLBIALLIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0,
- .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbiall_is_write },
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
+ .writefn = tlbiall_is_write },
{ .name = "TLBIMVAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1,
- .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimva_is_write },
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
+ .writefn = tlbimva_is_write },
{ .name = "TLBIASIDIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2,
- .type = ARM_CP_NO_RAW, .access = PL1_W,
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
.writefn = tlbiasid_is_write },
{ .name = "TLBIMVAAIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3,
- .type = ARM_CP_NO_RAW, .access = PL1_W,
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
.writefn = tlbimvaa_is_write },
REGINFO_SENTINEL
};
@@ -3886,20 +3948,21 @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] = {
{ .name = "DFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0,
- .access = PL1_RW, .type = ARM_CP_ALIAS,
+ .access = PL1_RW, .accessfn = access_tvm_trvm, .type = ARM_CP_ALIAS,
.bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.dfsr_s),
offsetoflow32(CPUARMState, cp15.dfsr_ns) }, },
{ .name = "IFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1,
- .access = PL1_RW, .resetvalue = 0,
+ .access = PL1_RW, .accessfn = access_tvm_trvm, .resetvalue = 0,
.bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.ifsr_s),
offsetoflow32(CPUARMState, cp15.ifsr_ns) } },
{ .name = "DFAR", .cp = 15, .opc1 = 0, .crn = 6, .crm = 0, .opc2 = 0,
- .access = PL1_RW, .resetvalue = 0,
+ .access = PL1_RW, .accessfn = access_tvm_trvm, .resetvalue = 0,
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.dfar_s),
offsetof(CPUARMState, cp15.dfar_ns) } },
{ .name = "FAR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
- .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[1]),
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .fieldoffset = offsetof(CPUARMState, cp15.far_el[1]),
.resetvalue = 0, },
REGINFO_SENTINEL
};
@@ -3907,25 +3970,29 @@ static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] = {
static const ARMCPRegInfo vmsa_cp_reginfo[] = {
{ .name = "ESR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .crn = 5, .crm = 2, .opc1 = 0, .opc2 = 0,
- .access = PL1_RW,
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
.fieldoffset = offsetof(CPUARMState, cp15.esr_el[1]), .resetvalue = 0, },
{ .name = "TTBR0_EL1", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 0, .crn = 2, .crm = 0, .opc2 = 0,
- .access = PL1_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0,
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .writefn = vmsa_ttbr_write, .resetvalue = 0,
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s),
offsetof(CPUARMState, cp15.ttbr0_ns) } },
{ .name = "TTBR1_EL1", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 0, .crn = 2, .crm = 0, .opc2 = 1,
- .access = PL1_RW, .writefn = vmsa_ttbr_write, .resetvalue = 0,
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .writefn = vmsa_ttbr_write, .resetvalue = 0,
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
offsetof(CPUARMState, cp15.ttbr1_ns) } },
{ .name = "TCR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
- .access = PL1_RW, .writefn = vmsa_tcr_el12_write,
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .writefn = vmsa_tcr_el12_write,
.resetfn = vmsa_ttbcr_reset, .raw_writefn = raw_write,
.fieldoffset = offsetof(CPUARMState, cp15.tcr_el[1]) },
{ .name = "TTBCR", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
- .access = PL1_RW, .type = ARM_CP_ALIAS, .writefn = vmsa_ttbcr_write,
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .type = ARM_CP_ALIAS, .writefn = vmsa_ttbcr_write,
.raw_writefn = vmsa_ttbcr_raw_write,
.bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.tcr_el[3]),
offsetoflow32(CPUARMState, cp15.tcr_el[1])} },
@@ -3937,7 +4004,8 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
*/
static const ARMCPRegInfo ttbcr2_reginfo = {
.name = "TTBCR2", .cp = 15, .opc1 = 0, .crn = 2, .crm = 0, .opc2 = 3,
- .access = PL1_RW, .type = ARM_CP_ALIAS,
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .type = ARM_CP_ALIAS,
.bank_fieldoffsets = { offsetofhigh32(CPUARMState, cp15.tcr_el[3]),
offsetofhigh32(CPUARMState, cp15.tcr_el[1]) },
};
@@ -4157,23 +4225,25 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
/* NOP AMAIR0/1 */
{ .name = "AMAIR0", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 0,
- .access = PL1_RW, .type = ARM_CP_CONST,
- .resetvalue = 0 },
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
/* AMAIR1 is mapped to AMAIR_EL1[63:32] */
{ .name = "AMAIR1", .cp = 15, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 1,
- .access = PL1_RW, .type = ARM_CP_CONST,
- .resetvalue = 0 },
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "PAR", .cp = 15, .crm = 7, .opc1 = 0,
.access = PL1_RW, .type = ARM_CP_64BIT, .resetvalue = 0,
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.par_s),
offsetof(CPUARMState, cp15.par_ns)} },
{ .name = "TTBR0", .cp = 15, .crm = 2, .opc1 = 0,
- .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .type = ARM_CP_64BIT | ARM_CP_ALIAS,
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr0_s),
offsetof(CPUARMState, cp15.ttbr0_ns) },
.writefn = vmsa_ttbr_write, },
{ .name = "TTBR1", .cp = 15, .crm = 2, .opc1 = 1,
- .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS,
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
+ .type = ARM_CP_64BIT | ARM_CP_ALIAS,
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.ttbr1_s),
offsetof(CPUARMState, cp15.ttbr1_ns) },
.writefn = vmsa_ttbr_write, },
@@ -4253,15 +4323,46 @@ static const ARMCPRegInfo uao_reginfo = {
.readfn = aa64_uao_read, .writefn = aa64_uao_write
};
-static CPAccessResult aa64_cacheop_access(CPUARMState *env,
- const ARMCPRegInfo *ri,
- bool isread)
+static CPAccessResult aa64_cacheop_poc_access(CPUARMState *env,
+ const ARMCPRegInfo *ri,
+ bool isread)
{
- /* Cache invalidate/clean: NOP, but EL0 must UNDEF unless
- * SCTLR_EL1.UCI is set.
- */
- if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_UCI)) {
- return CP_ACCESS_TRAP;
+ /* Cache invalidate/clean to Point of Coherency or Persistence... */
+ switch (arm_current_el(env)) {
+ case 0:
+ /* ... EL0 must UNDEF unless SCTLR_EL1.UCI is set. */
+ if (!(arm_sctlr(env, 0) & SCTLR_UCI)) {
+ return CP_ACCESS_TRAP;
+ }
+ /* fall through */
+ case 1:
+ /* ... EL1 must trap to EL2 if HCR_EL2.TPCP is set. */
+ if (arm_hcr_el2_eff(env) & HCR_TPCP) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ break;
+ }
+ return CP_ACCESS_OK;
+}
+
+static CPAccessResult aa64_cacheop_pou_access(CPUARMState *env,
+ const ARMCPRegInfo *ri,
+ bool isread)
+{
+ /* Cache invalidate/clean to Point of Unification... */
+ switch (arm_current_el(env)) {
+ case 0:
+ /* ... EL0 must UNDEF unless SCTLR_EL1.UCI is set. */
+ if (!(arm_sctlr(env, 0) & SCTLR_UCI)) {
+ return CP_ACCESS_TRAP;
+ }
+ /* fall through */
+ case 1:
+ /* ... EL1 must trap to EL2 if HCR_EL2.TPU is set. */
+ if (arm_hcr_el2_eff(env) & HCR_TPU) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ break;
}
return CP_ACCESS_OK;
}
@@ -4663,86 +4764,89 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
/* Cache ops: all NOPs since we don't emulate caches */
{ .name = "IC_IALLUIS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
- .access = PL1_W, .type = ARM_CP_NOP },
+ .access = PL1_W, .type = ARM_CP_NOP,
+ .accessfn = aa64_cacheop_pou_access },
{ .name = "IC_IALLU", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 0,
- .access = PL1_W, .type = ARM_CP_NOP },
+ .access = PL1_W, .type = ARM_CP_NOP,
+ .accessfn = aa64_cacheop_pou_access },
{ .name = "IC_IVAU", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 5, .opc2 = 1,
.access = PL0_W, .type = ARM_CP_NOP,
- .accessfn = aa64_cacheop_access },
+ .accessfn = aa64_cacheop_pou_access },
{ .name = "DC_IVAC", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 1,
- .access = PL1_W, .type = ARM_CP_NOP },
+ .access = PL1_W, .accessfn = aa64_cacheop_poc_access,
+ .type = ARM_CP_NOP },
{ .name = "DC_ISW", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 2,
- .access = PL1_W, .type = ARM_CP_NOP },
+ .access = PL1_W, .accessfn = access_tsw, .type = ARM_CP_NOP },
{ .name = "DC_CVAC", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 10, .opc2 = 1,
.access = PL0_W, .type = ARM_CP_NOP,
- .accessfn = aa64_cacheop_access },
+ .accessfn = aa64_cacheop_poc_access },
{ .name = "DC_CSW", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 2,
- .access = PL1_W, .type = ARM_CP_NOP },
+ .access = PL1_W, .accessfn = access_tsw, .type = ARM_CP_NOP },
{ .name = "DC_CVAU", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 11, .opc2 = 1,
.access = PL0_W, .type = ARM_CP_NOP,
- .accessfn = aa64_cacheop_access },
+ .accessfn = aa64_cacheop_pou_access },
{ .name = "DC_CIVAC", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 14, .opc2 = 1,
.access = PL0_W, .type = ARM_CP_NOP,
- .accessfn = aa64_cacheop_access },
+ .accessfn = aa64_cacheop_poc_access },
{ .name = "DC_CISW", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,
- .access = PL1_W, .type = ARM_CP_NOP },
+ .access = PL1_W, .accessfn = access_tsw, .type = ARM_CP_NOP },
/* TLBI operations */
{ .name = "TLBI_VMALLE1IS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 0,
- .access = PL1_W, .type = ARM_CP_NO_RAW,
+ .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
.writefn = tlbi_aa64_vmalle1is_write },
{ .name = "TLBI_VAE1IS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 1,
- .access = PL1_W, .type = ARM_CP_NO_RAW,
+ .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
.writefn = tlbi_aa64_vae1is_write },
{ .name = "TLBI_ASIDE1IS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 2,
- .access = PL1_W, .type = ARM_CP_NO_RAW,
+ .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
.writefn = tlbi_aa64_vmalle1is_write },
{ .name = "TLBI_VAAE1IS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 3,
- .access = PL1_W, .type = ARM_CP_NO_RAW,
+ .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
.writefn = tlbi_aa64_vae1is_write },
{ .name = "TLBI_VALE1IS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5,
- .access = PL1_W, .type = ARM_CP_NO_RAW,
+ .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
.writefn = tlbi_aa64_vae1is_write },
{ .name = "TLBI_VAALE1IS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7,
- .access = PL1_W, .type = ARM_CP_NO_RAW,
+ .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
.writefn = tlbi_aa64_vae1is_write },
{ .name = "TLBI_VMALLE1", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 0,
- .access = PL1_W, .type = ARM_CP_NO_RAW,
+ .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
.writefn = tlbi_aa64_vmalle1_write },
{ .name = "TLBI_VAE1", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 1,
- .access = PL1_W, .type = ARM_CP_NO_RAW,
+ .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
.writefn = tlbi_aa64_vae1_write },
{ .name = "TLBI_ASIDE1", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 2,
- .access = PL1_W, .type = ARM_CP_NO_RAW,
+ .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
.writefn = tlbi_aa64_vmalle1_write },
{ .name = "TLBI_VAAE1", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 3,
- .access = PL1_W, .type = ARM_CP_NO_RAW,
+ .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
.writefn = tlbi_aa64_vae1_write },
{ .name = "TLBI_VALE1", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5,
- .access = PL1_W, .type = ARM_CP_NO_RAW,
+ .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
.writefn = tlbi_aa64_vae1_write },
{ .name = "TLBI_VAALE1", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7,
- .access = PL1_W, .type = ARM_CP_NO_RAW,
+ .access = PL1_W, .accessfn = access_ttlb, .type = ARM_CP_NO_RAW,
.writefn = tlbi_aa64_vae1_write },
{ .name = "TLBI_IPAS2E1IS", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1,
@@ -4828,14 +4932,17 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
#endif
/* TLB invalidate last level of translation table walk */
{ .name = "TLBIMVALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 5,
- .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimva_is_write },
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
+ .writefn = tlbimva_is_write },
{ .name = "TLBIMVAALIS", .cp = 15, .opc1 = 0, .crn = 8, .crm = 3, .opc2 = 7,
- .type = ARM_CP_NO_RAW, .access = PL1_W,
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
.writefn = tlbimvaa_is_write },
{ .name = "TLBIMVAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 5,
- .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimva_write },
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
+ .writefn = tlbimva_write },
{ .name = "TLBIMVAAL", .cp = 15, .opc1 = 0, .crn = 8, .crm = 7, .opc2 = 7,
- .type = ARM_CP_NO_RAW, .access = PL1_W, .writefn = tlbimvaa_write },
+ .type = ARM_CP_NO_RAW, .access = PL1_W, .accessfn = access_ttlb,
+ .writefn = tlbimvaa_write },
{ .name = "TLBIMVALH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5,
.type = ARM_CP_NO_RAW, .access = PL2_W,
.writefn = tlbimva_hyp_write },
@@ -4861,34 +4968,34 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
.writefn = tlbiipas2_is_write },
/* 32 bit cache operations */
{ .name = "ICIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
- .type = ARM_CP_NOP, .access = PL1_W },
+ .type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_pou_access },
{ .name = "BPIALLUIS", .cp = 15, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 6,
.type = ARM_CP_NOP, .access = PL1_W },
{ .name = "ICIALLU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 0,
- .type = ARM_CP_NOP, .access = PL1_W },
+ .type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_pou_access },
{ .name = "ICIMVAU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 1,
- .type = ARM_CP_NOP, .access = PL1_W },
+ .type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_pou_access },
{ .name = "BPIALL", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 6,
.type = ARM_CP_NOP, .access = PL1_W },
{ .name = "BPIMVA", .cp = 15, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 7,
.type = ARM_CP_NOP, .access = PL1_W },
{ .name = "DCIMVAC", .cp = 15, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 1,
- .type = ARM_CP_NOP, .access = PL1_W },
+ .type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_poc_access },
{ .name = "DCISW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 2,
- .type = ARM_CP_NOP, .access = PL1_W },
+ .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
{ .name = "DCCMVAC", .cp = 15, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 1,
- .type = ARM_CP_NOP, .access = PL1_W },
+ .type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_poc_access },
{ .name = "DCCSW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 2,
- .type = ARM_CP_NOP, .access = PL1_W },
+ .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
{ .name = "DCCMVAU", .cp = 15, .opc1 = 0, .crn = 7, .crm = 11, .opc2 = 1,
- .type = ARM_CP_NOP, .access = PL1_W },
+ .type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_pou_access },
{ .name = "DCCIMVAC", .cp = 15, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 1,
- .type = ARM_CP_NOP, .access = PL1_W },
+ .type = ARM_CP_NOP, .access = PL1_W, .accessfn = aa64_cacheop_poc_access },
{ .name = "DCCISW", .cp = 15, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,
- .type = ARM_CP_NOP, .access = PL1_W },
+ .type = ARM_CP_NOP, .access = PL1_W, .accessfn = access_tsw },
/* MMU Domain access control / MPU write buffer control */
{ .name = "DACR", .cp = 15, .opc1 = 0, .crn = 3, .crm = 0, .opc2 = 0,
- .access = PL1_RW, .resetvalue = 0,
+ .access = PL1_RW, .accessfn = access_tvm_trvm, .resetvalue = 0,
.writefn = dacr_write, .raw_writefn = raw_write,
.bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.dacr_s),
offsetoflow32(CPUARMState, cp15.dacr_ns) } },
@@ -5086,11 +5193,15 @@ static const ARMCPRegInfo el3_no_el2_v8_cp_reginfo[] = {
REGINFO_SENTINEL
};
-static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
{
ARMCPU *cpu = env_archcpu(env);
- /* Begin with bits defined in base ARMv8.0. */
- uint64_t valid_mask = MAKE_64BIT_MASK(0, 34);
+
+ if (arm_feature(env, ARM_FEATURE_V8)) {
+ valid_mask |= MAKE_64BIT_MASK(0, 34); /* ARMv8.0 */
+ } else {
+ valid_mask |= MAKE_64BIT_MASK(0, 28); /* ARMv7VE */
+ }
if (arm_feature(env, ARM_FEATURE_EL3)) {
valid_mask &= ~HCR_HCD;
@@ -5104,14 +5215,17 @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
*/
valid_mask &= ~HCR_TSC;
}
- if (cpu_isar_feature(aa64_vh, cpu)) {
- valid_mask |= HCR_E2H;
- }
- if (cpu_isar_feature(aa64_lor, cpu)) {
- valid_mask |= HCR_TLOR;
- }
- if (cpu_isar_feature(aa64_pauth, cpu)) {
- valid_mask |= HCR_API | HCR_APK;
+
+ if (arm_feature(env, ARM_FEATURE_AARCH64)) {
+ if (cpu_isar_feature(aa64_vh, cpu)) {
+ valid_mask |= HCR_E2H;
+ }
+ if (cpu_isar_feature(aa64_lor, cpu)) {
+ valid_mask |= HCR_TLOR;
+ }
+ if (cpu_isar_feature(aa64_pauth, cpu)) {
+ valid_mask |= HCR_API | HCR_APK;
+ }
}
/* Clear RES0 bits. */
@@ -5143,12 +5257,17 @@ static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
arm_cpu_update_vfiq(cpu);
}
+static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+{
+ do_hcr_write(env, value, 0);
+}
+
static void hcr_writehigh(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
/* Handle HCR2 write, i.e. write to high half of HCR_EL2 */
value = deposit64(env->cp15.hcr_el2, 32, 32, value);
- hcr_write(env, NULL, value);
+ do_hcr_write(env, value, MAKE_64BIT_MASK(0, 32));
}
static void hcr_writelow(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -5156,7 +5275,7 @@ static void hcr_writelow(CPUARMState *env, const ARMCPRegInfo *ri,
{
/* Handle HCR write, i.e. write to low half of HCR_EL2 */
value = deposit64(env->cp15.hcr_el2, 0, 32, value);
- hcr_write(env, NULL, value);
+ do_hcr_write(env, value, MAKE_64BIT_MASK(32, 32));
}
/*
@@ -5184,14 +5303,37 @@ uint64_t arm_hcr_el2_eff(CPUARMState *env)
* Since the v8.4 language applies to the entire register, and
* appears to be backward compatible, use that.
*/
- ret = 0;
- } else if (ret & HCR_TGE) {
- /* These bits are up-to-date as of ARMv8.4. */
+ return 0;
+ }
+
+ /*
+ * For a cpu that supports both aarch64 and aarch32, we can set bits
+ * in HCR_EL2 (e.g. via EL3) that are RES0 when we enter EL2 as aa32.
+ * Ignore all of the bits in HCR+HCR2 that are not valid for aarch32.
+ */
+ if (!arm_el_is_aa64(env, 2)) {
+ uint64_t aa32_valid;
+
+ /*
+ * These bits are up-to-date as of ARMv8.6.
+ * For HCR, it's easiest to list just the 2 bits that are invalid.
+ * For HCR2, list those that are valid.
+ */
+ aa32_valid = MAKE_64BIT_MASK(0, 32) & ~(HCR_RW | HCR_TDZ);
+ aa32_valid |= (HCR_CD | HCR_ID | HCR_TERR | HCR_TEA | HCR_MIOCNCE |
+ HCR_TID4 | HCR_TICAB | HCR_TOCU | HCR_TTLBIS);
+ ret &= aa32_valid;
+ }
+
+ if (ret & HCR_TGE) {
+ /* These bits are up-to-date as of ARMv8.6. */
if (ret & HCR_E2H) {
ret &= ~(HCR_VM | HCR_FMO | HCR_IMO | HCR_AMO |
HCR_BSU_MASK | HCR_DC | HCR_TWI | HCR_TWE |
HCR_TID0 | HCR_TID2 | HCR_TPCP | HCR_TPU |
- HCR_TDZ | HCR_CD | HCR_ID | HCR_MIOCNCE);
+ HCR_TDZ | HCR_CD | HCR_ID | HCR_MIOCNCE |
+ HCR_TID4 | HCR_TICAB | HCR_TOCU | HCR_ENSCXT |
+ HCR_TTLBIS | HCR_TTLBOS | HCR_TID5);
} else {
ret |= HCR_FMO | HCR_IMO | HCR_AMO;
}
@@ -6667,7 +6809,7 @@ static const ARMCPRegInfo dcpop_reg[] = {
{ .name = "DC_CVAP", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 12, .opc2 = 1,
.access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
- .accessfn = aa64_cacheop_access, .writefn = dccvap_writefn },
+ .accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn },
REGINFO_SENTINEL
};
@@ -6675,7 +6817,7 @@ static const ARMCPRegInfo dcpodp_reg[] = {
{ .name = "DC_CVADP", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 13, .opc2 = 1,
.access = PL0_W, .type = ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END,
- .accessfn = aa64_cacheop_access, .writefn = dccvap_writefn },
+ .accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn },
REGINFO_SENTINEL
};
#endif /*CONFIG_USER_ONLY*/
@@ -6888,8 +7030,8 @@ static const ARMCPRegInfo ats1cp_reginfo[] = {
static const ARMCPRegInfo actlr2_hactlr2_reginfo[] = {
{ .name = "ACTLR2", .state = ARM_CP_STATE_AA32,
.cp = 15, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 3,
- .access = PL1_RW, .type = ARM_CP_CONST,
- .resetvalue = 0 },
+ .access = PL1_RW, .accessfn = access_tacr,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
{ .name = "HACTLR2", .state = ARM_CP_STATE_AA32,
.cp = 15, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 3,
.access = PL2_RW, .type = ARM_CP_CONST,
@@ -7645,8 +7787,8 @@ void register_cp_regs_for_features(ARMCPU *cpu)
ARMCPRegInfo auxcr_reginfo[] = {
{ .name = "ACTLR_EL1", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 1,
- .access = PL1_RW, .type = ARM_CP_CONST,
- .resetvalue = cpu->reset_auxcr },
+ .access = PL1_RW, .accessfn = access_tacr,
+ .type = ARM_CP_CONST, .resetvalue = cpu->reset_auxcr },
{ .name = "ACTLR_EL2", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 1,
.access = PL2_RW, .type = ARM_CP_CONST,
@@ -7730,7 +7872,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
ARMCPRegInfo sctlr = {
.name = "SCTLR", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 0,
- .access = PL1_RW,
+ .access = PL1_RW, .accessfn = access_tvm_trvm,
.bank_fieldoffsets = { offsetof(CPUARMState, cp15.sctlr_s),
offsetof(CPUARMState, cp15.sctlr_ns) },
.writefn = sctlr_write, .resetvalue = cpu->reset_sctlr,
@@ -10316,7 +10458,8 @@ static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx)
} else if (mmu_idx == ARMMMUIdx_Stage2) {
return 0; /* VTCR_EL2 */
} else {
- return extract32(tcr, 20, 1);
+ /* Replicate the single TBI bit so we always have 2 bits. */
+ return extract32(tcr, 20, 1) * 3;
}
}
@@ -10327,7 +10470,8 @@ static int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx)
} else if (mmu_idx == ARMMMUIdx_Stage2) {
return 0; /* VTCR_EL2 */
} else {
- return extract32(tcr, 29, 1);
+ /* Replicate the single TBID bit so we always have 2 bits. */
+ return extract32(tcr, 29, 1) * 3;
}
}
@@ -10591,6 +10735,10 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
/* Now we can extract the actual base address from the TTBR */
descaddr = extract64(ttbr, 0, 48);
+ /*
+ * We rely on this masking to clear the RES0 bits at the bottom of the TTBR
+ * and also to mask out CnP (bit 0) which could validly be non-zero.
+ */
descaddr &= ~indexmask;
/* The address field in the descriptor goes up to bit 39 for ARMv7
@@ -12126,11 +12274,6 @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env)
return arm_mmu_idx_el(env, arm_current_el(env));
}
-int cpu_mmu_index(CPUARMState *env, bool ifetch)
-{
- return arm_to_core_mmu_idx(arm_mmu_idx(env));
-}
-
#ifndef CONFIG_USER_ONLY
ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env)
{
diff --git a/target/arm/helper.h b/target/arm/helper.h
index fcbf504121..72eb9e6a1a 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -559,7 +559,6 @@ DEF_HELPER_FLAGS_3(crypto_sm4ekey, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
-DEF_HELPER_2(dc_zva, void, env, i64)
DEF_HELPER_FLAGS_5(gvec_qrdmlah_s16, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, i32)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 9f96a2359f..e633aff36e 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -783,6 +783,12 @@ static inline ARMMMUIdx core_to_arm_mmu_idx(CPUARMState *env, int mmu_idx)
}
}
+static inline ARMMMUIdx core_to_aa64_mmu_idx(int mmu_idx)
+{
+ /* AArch64 is always a-profile. */
+ return mmu_idx | ARM_MMU_IDX_A;
+}
+
int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx);
/*
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index af3020b78f..eb0de080f1 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -17,7 +17,6 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
-#include "qemu/units.h"
#include "qemu/log.h"
#include "qemu/main-loop.h"
#include "cpu.h"
@@ -936,95 +935,3 @@ uint32_t HELPER(ror_cc)(CPUARMState *env, uint32_t x, uint32_t i)
return ((uint32_t)x >> shift) | (x << (32 - shift));
}
}
-
-void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in)
-{
- /*
- * Implement DC ZVA, which zeroes a fixed-length block of memory.
- * Note that we do not implement the (architecturally mandated)
- * alignment fault for attempts to use this on Device memory
- * (which matches the usual QEMU behaviour of not implementing either
- * alignment faults or any memory attribute handling).
- */
-
- ARMCPU *cpu = env_archcpu(env);
- uint64_t blocklen = 4 << cpu->dcz_blocksize;
- uint64_t vaddr = vaddr_in & ~(blocklen - 1);
-
-#ifndef CONFIG_USER_ONLY
- {
- /*
- * Slightly awkwardly, QEMU's TARGET_PAGE_SIZE may be less than
- * the block size so we might have to do more than one TLB lookup.
- * We know that in fact for any v8 CPU the page size is at least 4K
- * and the block size must be 2K or less, but TARGET_PAGE_SIZE is only
- * 1K as an artefact of legacy v5 subpage support being present in the
- * same QEMU executable. So in practice the hostaddr[] array has
- * two entries, given the current setting of TARGET_PAGE_BITS_MIN.
- */
- int maxidx = DIV_ROUND_UP(blocklen, TARGET_PAGE_SIZE);
- void *hostaddr[DIV_ROUND_UP(2 * KiB, 1 << TARGET_PAGE_BITS_MIN)];
- int try, i;
- unsigned mmu_idx = cpu_mmu_index(env, false);
- TCGMemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
-
- assert(maxidx <= ARRAY_SIZE(hostaddr));
-
- for (try = 0; try < 2; try++) {
-
- for (i = 0; i < maxidx; i++) {
- hostaddr[i] = tlb_vaddr_to_host(env,
- vaddr + TARGET_PAGE_SIZE * i,
- 1, mmu_idx);
- if (!hostaddr[i]) {
- break;
- }
- }
- if (i == maxidx) {
- /*
- * If it's all in the TLB it's fair game for just writing to;
- * we know we don't need to update dirty status, etc.
- */
- for (i = 0; i < maxidx - 1; i++) {
- memset(hostaddr[i], 0, TARGET_PAGE_SIZE);
- }
- memset(hostaddr[i], 0, blocklen - (i * TARGET_PAGE_SIZE));
- return;
- }
- /*
- * OK, try a store and see if we can populate the tlb. This
- * might cause an exception if the memory isn't writable,
- * in which case we will longjmp out of here. We must for
- * this purpose use the actual register value passed to us
- * so that we get the fault address right.
- */
- helper_ret_stb_mmu(env, vaddr_in, 0, oi, GETPC());
- /* Now we can populate the other TLB entries, if any */
- for (i = 0; i < maxidx; i++) {
- uint64_t va = vaddr + TARGET_PAGE_SIZE * i;
- if (va != (vaddr_in & TARGET_PAGE_MASK)) {
- helper_ret_stb_mmu(env, va, 0, oi, GETPC());
- }
- }
- }
-
- /*
- * Slow path (probably attempt to do this to an I/O device or
- * similar, or clearing of a block of code we have translations
- * cached for). Just do a series of byte writes as the architecture
- * demands. It's not worth trying to use a cpu_physical_memory_map(),
- * memset(), unmap() sequence here because:
- * + we'd need to account for the blocksize being larger than a page
- * + the direct-RAM access case is almost always going to be dealt
- * with in the fastpath code above, so there's no speed benefit
- * + we would have to deal with the map returning NULL because the
- * bounce buffer was in use
- */
- for (i = 0; i < blocklen; i++) {
- helper_ret_stb_mmu(env, vaddr + i, 0, oi, GETPC());
- }
- }
-#else
- memset(g2h(vaddr), 0, blocklen);
-#endif
-}
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 579180af0a..fefe8af7f5 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1784,7 +1784,7 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
return;
case ARM_CP_DC_ZVA:
/* Writes clear the aligned block of memory which rt points into. */
- tcg_rt = cpu_reg(s, rt);
+ tcg_rt = clean_data_tbi(s, cpu_reg(s, rt));
gen_helper_dc_zva(cpu_env, tcg_rt);
return;
default:
@@ -14300,7 +14300,7 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
dc->condexec_mask = 0;
dc->condexec_cond = 0;
core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
- dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
+ dc->mmu_idx = core_to_aa64_mmu_idx(core_mmu_idx);
dc->tbii = FIELD_EX32(tb_flags, TBFLAG_A64, TBII);
dc->tbid = FIELD_EX32(tb_flags, TBFLAG_A64, TBID);
dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
diff --git a/tests/tcg/aarch64/pauth-1.c b/tests/tcg/aarch64/pauth-1.c
index ea0984ea82..d3878cbeb6 100644
--- a/tests/tcg/aarch64/pauth-1.c
+++ b/tests/tcg/aarch64/pauth-1.c
@@ -29,7 +29,7 @@ int main()
}
perc = (float) count / (float) (TESTS * 2);
- printf("Ptr Check: %0.2f%%", perc * 100.0);
+ printf("Ptr Check: %0.2f%%\n", perc * 100.0);
assert(perc > 0.95);
return 0;
}