diff --git a/hw/arm/ast2400.c b/hw/arm/ast2400.c index 0555843620..326fdb36ee 100644 --- a/hw/arm/ast2400.c +++ b/hw/arm/ast2400.c @@ -34,8 +34,6 @@ #define AST2400_FMC_FLASH_BASE 0x20000000 #define AST2400_SPI_FLASH_BASE 0x30000000 -#define AST2400_A0_SILICON_REV 0x02000303 - static const int uart_irqs[] = { 9, 32, 33, 34, 10 }; static const int timer_irqs[] = { 16, 17, 18, 35, 36, 37, 38, 39, }; diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 4dafd42be8..a193b5a95b 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -52,7 +52,8 @@ #include "hw/arm/sysbus-fdt.h" #include "hw/platform-bus.h" #include "hw/arm/fdt.h" -#include "hw/intc/arm_gic_common.h" +#include "hw/intc/arm_gic.h" +#include "hw/intc/arm_gicv3_common.h" #include "kvm_arm.h" #include "hw/smbios/smbios.h" #include "qapi/visitor.h" @@ -82,6 +83,7 @@ typedef struct VirtBoardInfo { typedef struct { MachineClass parent; VirtBoardInfo *daughterboard; + bool disallow_affinity_adjustment; } VirtMachineClass; typedef struct { @@ -1165,6 +1167,7 @@ void virt_guest_info_machine_done(Notifier *notifier, void *data) static void machvirt_init(MachineState *machine) { VirtMachineState *vms = VIRT_MACHINE(machine); + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine); qemu_irq pic[NUM_IRQS]; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *secure_sysmem = NULL; @@ -1181,6 +1184,7 @@ static void machvirt_init(MachineState *machine) CPUClass *cc; Error *err = NULL; bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0); + uint8_t clustersz; if (!cpu_model) { cpu_model = "cortex-a15"; @@ -1226,8 +1230,10 @@ static void machvirt_init(MachineState *machine) */ if (gic_version == 3) { virt_max_cpus = vbi->memmap[VIRT_GIC_REDIST].size / 0x20000; + clustersz = GICV3_TARGETLIST_BITS; } else { virt_max_cpus = GIC_NCPU; + clustersz = GIC_TARGETLIST_BITS; } if (max_cpus > virt_max_cpus) { @@ -1281,6 +1287,20 @@ static void machvirt_init(MachineState *machine) for (n = 0; n < smp_cpus; n++) { Object *cpuobj = object_new(typename); + if (!vmc->disallow_affinity_adjustment) { + /* Adjust MPIDR like 64-bit KVM hosts, which incorporate the + * GIC's target-list limitations. 32-bit KVM hosts currently + * always create clusters of 4 CPUs, but that is expected to + * change when they gain support for gicv3. When KVM is enabled + * it will override the changes we make here, therefore our + * purposes are to make TCG consistent (with 64-bit KVM hosts) + * and to improve SGI efficiency. + */ + uint8_t aff1 = n / clustersz; + uint8_t aff0 = n % clustersz; + object_property_set_int(cpuobj, (aff1 << ARM_AFF1_SHIFT) | aff0, + "mp-affinity", NULL); + } if (!vms->secure) { object_property_set_bool(cpuobj, false, "has_el3", NULL); @@ -1507,7 +1527,10 @@ static void virt_2_6_instance_init(Object *obj) static void virt_machine_2_6_options(MachineClass *mc) { + VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); + virt_machine_2_7_options(mc); SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_6); + vmc->disallow_affinity_adjustment = true; } DEFINE_VIRT_MACHINE(2, 6) diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index ca8c12c0f8..9828ee61d5 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -149,6 +149,7 @@ typedef struct FlashPartInfo { */ #define SPANSION_CONTINUOUS_READ_MODE_CMD_LEN 1 +#define WINBOND_CONTINUOUS_READ_MODE_CMD_LEN 1 static const FlashPartInfo known_devices[] = { /* Atmel -- some are (confusingly) marketed as "DataFlash" */ @@ -777,7 +778,7 @@ static void decode_dio_read_cmd(Flash *s) /* Dummy cycles modeled with bytes writes instead of bits */ switch (get_man(s)) { case MAN_WINBOND: - s->needed_bytes += 8; + s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN; break; case MAN_SPANSION: s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN; @@ -816,7 +817,8 @@ static void decode_qio_read_cmd(Flash *s) /* Dummy cycles modeled with bytes writes instead of bits */ switch (get_man(s)) { case MAN_WINBOND: - s->needed_bytes += 8; + s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN; + s->needed_bytes += 4; break; case MAN_SPANSION: s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN; diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c index 05b0c276eb..30829ee97b 100644 --- a/hw/core/ptimer.c +++ b/hw/core/ptimer.c @@ -93,7 +93,7 @@ uint64_t ptimer_get_count(ptimer_state *s) bool oneshot = (s->enabled == 2); /* Figure out the current counter value. */ - if (s->period == 0 || (expired && (oneshot || use_icount))) { + if (expired) { /* Prevent timer underflowing if it should already have triggered. */ counter = 0; @@ -120,7 +120,7 @@ uint64_t ptimer_get_count(ptimer_state *s) backwards. */ - rem = expired ? now - next : next - now; + rem = next - now; div = period; clz1 = clz64(rem); @@ -140,11 +140,6 @@ uint64_t ptimer_get_count(ptimer_state *s) div += 1; } counter = rem / div; - - if (expired && counter != 0) { - /* Wrap around periodic counter. */ - counter = s->limit - (counter - 1) % s->limit; - } } } else { counter = s->delta; diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c index 23f51752b0..c7e2c8263f 100644 --- a/hw/misc/aspeed_scu.c +++ b/hw/misc/aspeed_scu.c @@ -88,8 +88,6 @@ #define PROT_KEY_UNLOCK 0x1688A8A8 #define SCU_IO_REGION_SIZE 0x20000 -#define AST2400_A0_SILICON_REV 0x02000303U - static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = { [SYS_RST_CTRL] = 0xFFCFFEDCU, [CLK_SEL] = 0xF3F40000U, @@ -212,7 +210,7 @@ static void aspeed_scu_reset(DeviceState *dev) static uint32_t aspeed_silicon_revs[] = { AST2400_A0_SILICON_REV, }; -static bool is_supported_silicon_rev(uint32_t silicon_rev) +bool is_supported_silicon_rev(uint32_t silicon_rev) { int i; @@ -255,7 +253,7 @@ static const VMStateDescription vmstate_aspeed_scu = { static Property aspeed_scu_properties[] = { DEFINE_PROP_UINT32("silicon-rev", AspeedSCUState, silicon_rev, 0), DEFINE_PROP_UINT32("hw-strap1", AspeedSCUState, hw_strap1, 0), - DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap1, 0), + DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap2, 0), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c index a371e302d4..d319e04a27 100644 --- a/hw/ssi/aspeed_smc.c +++ b/hw/ssi/aspeed_smc.c @@ -273,6 +273,9 @@ static void aspeed_smc_reset(DeviceState *d) memset(s->regs, 0, sizeof s->regs); + /* Pretend DMA is done (u-boot initialization) */ + s->regs[R_INTR_CTRL] = INTR_CTRL_DMA_STATUS; + /* Unselect all slaves */ for (i = 0; i < s->num_cs; ++i) { s->regs[s->r_ctrl0 + i] |= CTRL_CE_STOP_ACTIVE; @@ -281,12 +284,6 @@ static void aspeed_smc_reset(DeviceState *d) aspeed_smc_update_cs(s); } -static bool aspeed_smc_is_implemented(AspeedSMCState *s, hwaddr addr) -{ - return (addr == s->r_conf || addr == s->r_timings || addr == s->r_ce_ctrl || - (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs)); -} - static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size) { AspeedSMCState *s = ASPEED_SMC(opaque); @@ -300,13 +297,17 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size) return 0; } - if (!aspeed_smc_is_implemented(s, addr)) { + if (addr == s->r_conf || + addr == s->r_timings || + addr == s->r_ce_ctrl || + addr == R_INTR_CTRL || + (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs)) { + return s->regs[addr]; + } else { qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n", - __func__, addr); + __func__, addr); return 0; } - - return s->regs[addr]; } static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data, @@ -324,20 +325,18 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data, return; } - if (!aspeed_smc_is_implemented(s, addr)) { + if (addr == s->r_conf || + addr == s->r_timings || + addr == s->r_ce_ctrl) { + s->regs[addr] = value; + } else if (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs) { + s->regs[addr] = value; + aspeed_smc_update_cs(s); + } else { qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n", __func__, addr); return; } - - /* - * Not much to do apart from storing the value and set the cs - * lines if the register is a controlling one. - */ - s->regs[addr] = value; - if (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs) { - aspeed_smc_update_cs(s); - } } static const MemoryRegionOps aspeed_smc_ops = { diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index eb84b74532..13798b3cb8 100644 --- a/hw/virtio/virtio-mmio.c +++ b/hw/virtio/virtio-mmio.c @@ -91,6 +91,7 @@ typedef struct { VirtioBusState bus; bool ioeventfd_disabled; bool ioeventfd_started; + bool format_transport_address; } VirtIOMMIOProxy; static bool virtio_mmio_ioeventfd_started(DeviceState *d) @@ -469,6 +470,12 @@ assign_error: /* virtio-mmio device */ +static Property virtio_mmio_properties[] = { + DEFINE_PROP_BOOL("format_transport_address", VirtIOMMIOProxy, + format_transport_address, true), + DEFINE_PROP_END_OF_LIST(), +}; + static void virtio_mmio_realizefn(DeviceState *d, Error **errp) { VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d); @@ -489,6 +496,7 @@ static void virtio_mmio_class_init(ObjectClass *klass, void *data) dc->realize = virtio_mmio_realizefn; dc->reset = virtio_mmio_reset; set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->props = virtio_mmio_properties; } static const TypeInfo virtio_mmio_info = { @@ -500,6 +508,46 @@ static const TypeInfo virtio_mmio_info = { /* virtio-mmio-bus. */ +static char *virtio_mmio_bus_get_dev_path(DeviceState *dev) +{ + BusState *virtio_mmio_bus; + VirtIOMMIOProxy *virtio_mmio_proxy; + char *proxy_path; + SysBusDevice *proxy_sbd; + char *path; + + virtio_mmio_bus = qdev_get_parent_bus(dev); + virtio_mmio_proxy = VIRTIO_MMIO(virtio_mmio_bus->parent); + proxy_path = qdev_get_dev_path(DEVICE(virtio_mmio_proxy)); + + /* + * If @format_transport_address is false, then we just perform the same as + * virtio_bus_get_dev_path(): we delegate the address formatting for the + * device on the virtio-mmio bus to the bus that the virtio-mmio proxy + * (i.e., the device that implements the virtio-mmio bus) resides on. In + * this case the base address of the virtio-mmio transport will be + * invisible. + */ + if (!virtio_mmio_proxy->format_transport_address) { + return proxy_path; + } + + /* Otherwise, we append the base address of the transport. */ + proxy_sbd = SYS_BUS_DEVICE(virtio_mmio_proxy); + assert(proxy_sbd->num_mmio == 1); + assert(proxy_sbd->mmio[0].memory == &virtio_mmio_proxy->iomem); + + if (proxy_path) { + path = g_strdup_printf("%s/virtio-mmio@" TARGET_FMT_plx, proxy_path, + proxy_sbd->mmio[0].addr); + } else { + path = g_strdup_printf("virtio-mmio@" TARGET_FMT_plx, + proxy_sbd->mmio[0].addr); + } + g_free(proxy_path); + return path; +} + static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data) { BusClass *bus_class = BUS_CLASS(klass); @@ -516,6 +564,7 @@ static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data) k->ioeventfd_assign = virtio_mmio_ioeventfd_assign; k->has_variable_vring_alignment = true; bus_class->max_dev = 1; + bus_class->get_dev_path = virtio_mmio_bus_get_dev_path; } static const TypeInfo virtio_mmio_bus_info = { diff --git a/include/hw/compat.h b/include/hw/compat.h index 636befedb4..9914e7a59e 100644 --- a/include/hw/compat.h +++ b/include/hw/compat.h @@ -2,7 +2,11 @@ #define HW_COMPAT_H #define HW_COMPAT_2_6 \ - /* empty */ + {\ + .driver = "virtio-mmio",\ + .property = "format_transport_address",\ + .value = "off",\ + }, #define HW_COMPAT_2_5 \ {\ diff --git a/include/hw/intc/arm_gic.h b/include/hw/intc/arm_gic.h index 0971e37710..42bb535fd4 100644 --- a/include/hw/intc/arm_gic.h +++ b/include/hw/intc/arm_gic.h @@ -23,6 +23,9 @@ #include "arm_gic_common.h" +/* Number of SGI target-list bits */ +#define GIC_TARGETLIST_BITS 8 + #define TYPE_ARM_GIC "arm_gic" #define ARM_GIC(obj) \ OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC) diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h index f72e49922f..341a3118f0 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h @@ -35,6 +35,9 @@ #define GICV3_MAXIRQ 1020 #define GICV3_MAXSPI (GICV3_MAXIRQ - GIC_INTERNAL) +/* Number of SGI target-list bits */ +#define GICV3_TARGETLIST_BITS 16 + /* Minimum BPR for Secure, or when security not enabled */ #define GIC_MIN_BPR 0 /* Minimum BPR for Nonsecure when security is enabled */ diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h index 6b8e46f85f..fdfd982288 100644 --- a/include/hw/misc/aspeed_scu.h +++ b/include/hw/misc/aspeed_scu.h @@ -31,4 +31,9 @@ typedef struct AspeedSCUState { uint32_t hw_strap2; } AspeedSCUState; +#define AST2400_A0_SILICON_REV 0x02000303U +#define AST2500_A0_SILICON_REV 0x04000303U + +extern bool is_supported_silicon_rev(uint32_t silicon_rev); + #endif /* ASPEED_SCU_H */ diff --git a/target-arm/helper.c b/target-arm/helper.c index 1f9cdacc59..bdb842cc45 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -572,6 +572,102 @@ static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri, } } +static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs = ENV_GET_CPU(env); + + tlb_flush_by_mmuidx(cs, ARMMMUIdx_S12NSE1, ARMMMUIdx_S12NSE0, + ARMMMUIdx_S2NS, -1); +} + +static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *other_cs; + + CPU_FOREACH(other_cs) { + tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S12NSE1, + ARMMMUIdx_S12NSE0, ARMMMUIdx_S2NS, -1); + } +} + +static void tlbiipas2_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Invalidate by IPA. This has to invalidate any structures that + * contain only stage 2 translation information, but does not need + * to apply to structures that contain combined stage 1 and stage 2 + * translation information. + * This must NOP if EL2 isn't implemented or SCR_EL3.NS is zero. + */ + CPUState *cs = ENV_GET_CPU(env); + uint64_t pageaddr; + + if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) { + return; + } + + pageaddr = sextract64(value << 12, 0, 40); + + tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S2NS, -1); +} + +static void tlbiipas2_is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *other_cs; + uint64_t pageaddr; + + if (!arm_feature(env, ARM_FEATURE_EL2) || !(env->cp15.scr_el3 & SCR_NS)) { + return; + } + + pageaddr = sextract64(value << 12, 0, 40); + + CPU_FOREACH(other_cs) { + tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S2NS, -1); + } +} + +static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs = ENV_GET_CPU(env); + + tlb_flush_by_mmuidx(cs, ARMMMUIdx_S1E2, -1); +} + +static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *other_cs; + + CPU_FOREACH(other_cs) { + tlb_flush_by_mmuidx(other_cs, ARMMMUIdx_S1E2, -1); + } +} + +static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs = ENV_GET_CPU(env); + uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12); + + tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdx_S1E2, -1); +} + +static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *other_cs; + uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12); + + CPU_FOREACH(other_cs) { + tlb_flush_page_by_mmuidx(other_cs, pageaddr, ARMMMUIdx_S1E2, -1); + } +} + static const ARMCPRegInfo cp_reginfo[] = { /* Define the secure and non-secure FCSE identifier CP registers * separately because there is no secure bank in V8 (no _EL3). This allows @@ -3273,6 +3369,29 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { .type = ARM_CP_NO_RAW, .access = PL1_W, .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 }, + { .name = "TLBIMVALH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 5, + .type = ARM_CP_NO_RAW, .access = PL2_W, + .writefn = tlbimva_hyp_write }, + { .name = "TLBIMVALHIS", + .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 5, + .type = ARM_CP_NO_RAW, .access = PL2_W, + .writefn = tlbimva_hyp_is_write }, + { .name = "TLBIIPAS2", + .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 1, + .type = ARM_CP_NO_RAW, .access = PL2_W, + .writefn = tlbiipas2_write }, + { .name = "TLBIIPAS2IS", + .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 1, + .type = ARM_CP_NO_RAW, .access = PL2_W, + .writefn = tlbiipas2_is_write }, + { .name = "TLBIIPAS2L", + .cp = 15, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 5, + .type = ARM_CP_NO_RAW, .access = PL2_W, + .writefn = tlbiipas2_write }, + { .name = "TLBIIPAS2LIS", + .cp = 15, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 5, + .type = ARM_CP_NO_RAW, .access = PL2_W, + .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 }, @@ -3605,6 +3724,26 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { { .name = "HTTBR", .cp = 15, .opc1 = 4, .crm = 2, .access = PL2_RW, .type = ARM_CP_64BIT | ARM_CP_ALIAS, .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[2]) }, + { .name = "TLBIALLNSNH", + .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 4, + .type = ARM_CP_NO_RAW, .access = PL2_W, + .writefn = tlbiall_nsnh_write }, + { .name = "TLBIALLNSNHIS", + .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 4, + .type = ARM_CP_NO_RAW, .access = PL2_W, + .writefn = tlbiall_nsnh_is_write }, + { .name = "TLBIALLH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0, + .type = ARM_CP_NO_RAW, .access = PL2_W, + .writefn = tlbiall_hyp_write }, + { .name = "TLBIALLHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 0, + .type = ARM_CP_NO_RAW, .access = PL2_W, + .writefn = tlbiall_hyp_is_write }, + { .name = "TLBIMVAH", .cp = 15, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 1, + .type = ARM_CP_NO_RAW, .access = PL2_W, + .writefn = tlbimva_hyp_write }, + { .name = "TLBIMVAHIS", .cp = 15, .opc1 = 4, .crn = 8, .crm = 3, .opc2 = 1, + .type = ARM_CP_NO_RAW, .access = PL2_W, + .writefn = tlbimva_hyp_is_write }, { .name = "TLBI_ALLE2", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 7, .opc2 = 0, .type = ARM_CP_NO_RAW, .access = PL2_W, diff --git a/util/cutils.c b/util/cutils.c index 5830a688dc..7505fdaa81 100644 --- a/util/cutils.c +++ b/util/cutils.c @@ -184,6 +184,13 @@ int qemu_fdatasync(int fd) #define SPLAT(p) _mm_set1_epi8(*(p)) #define ALL_EQ(v1, v2) (_mm_movemask_epi8(_mm_cmpeq_epi8(v1, v2)) == 0xFFFF) #define VEC_OR(v1, v2) (_mm_or_si128(v1, v2)) +#elif defined(__aarch64__) +#include "arm_neon.h" +#define VECTYPE uint64x2_t +#define ALL_EQ(v1, v2) \ + ((vgetq_lane_u64(v1, 0) == vgetq_lane_u64(v2, 0)) && \ + (vgetq_lane_u64(v1, 1) == vgetq_lane_u64(v2, 1))) +#define VEC_OR(v1, v2) ((v1) | (v2)) #else #define VECTYPE unsigned long #define SPLAT(p) (*(p) * (~0UL / 255))