mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-09-06 18:05:37 +00:00
target-arm queue:
* add virtio-mmio transport base address to device path (avoid an assertion failure with multiple virtio-scsi-devices) * revert hw/ptimer commit5a50307
which causes regressions on SPARC guests * use Neon to accelerate zero-page checking on AArch64 hosts * set the MPIDR for TCG to match how KVM does it (and fit with GICv2/GICv3 restrictions on SGI target lists) * add some missing AArch32 TLBI hypervisor TLB operations * m25p80: Fix QIOR/DIOR handling for Winbond * hw/misc: fix typo in Aspeed SCU hw-strap2 property name * ast2400: pretend DMAs are done for U-boot * ast2400: some minor code cleanups -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJXh7wKAAoJEDwlJe0UNgzeTKUQAJFbi+fyN5m4ubkrgtVHUbpl H8msZTYt1Ce7k4uYmUan18fBDAqJgDOYupzU7inAlAVo32h0+iYQNRmedyXvaxA3 ihL5GWGWTKm9t/ZP0Od2xo4VlSIGl3sI+WLFTJBtPdVUw7ZMT8/j3NiE3hgayTBd xn4N+bcV0ODf1vUhEJc5lma6eWDPjclZGReN3yyaAzhD43pyG+ScR4Kz8vLlEYhj KoGdD39RdO+Ya+B6fYHEAFCeXyJOtbIuS3dD+g9qkWwRx0sdeWnokK8H0eixuD4G lriFjit6GxIyPQ1lGhVhVQxeP72ghyNJxStRqgvjKDEEs5jJc4XZUgoUwlpk+Bno GQHG4KVtS+PZrDnEhM9nq5zZ0HuOv3asS08g/y1fEBqPg1z5eFJ4B+4lVDY9PcxZ 0vPgMiClqNz5d+4RK/QfX0ebKG8gJJql1AK/DAw0pGh5/AoAah8gC1thHs7LUxOn f3hrglN75WZwkLnqQ7qdP+d1iJ6VbmMDhXrsL6Ar8ASx1V/AGGUsoXtSEZGEePFV 4gh8CRGV5X/g2wTrdpsQWtCWcHC7oUBspB156aNNyqR+cUWnHBRKBDXv/CWgMmc+ 2zhim8sGVECoD7NYj826bps60ZHyFf83j9WZ5uod2jdAqooLba5Had8eYq7UAFnG irmYuzZrCooaIvYow10b =+HaT -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20160714' into staging target-arm queue: * add virtio-mmio transport base address to device path (avoid an assertion failure with multiple virtio-scsi-devices) * revert hw/ptimer commit5a50307
which causes regressions on SPARC guests * use Neon to accelerate zero-page checking on AArch64 hosts * set the MPIDR for TCG to match how KVM does it (and fit with GICv2/GICv3 restrictions on SGI target lists) * add some missing AArch32 TLBI hypervisor TLB operations * m25p80: Fix QIOR/DIOR handling for Winbond * hw/misc: fix typo in Aspeed SCU hw-strap2 property name * ast2400: pretend DMAs are done for U-boot * ast2400: some minor code cleanups # gpg: Signature made Thu 14 Jul 2016 17:21:30 BST # gpg: using RSA key 0x3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20160714: ast2400: externalize revision numbers ast2400: pretend DMAs are done for U-boot ast2400: replace aspeed_smc_is_implemented() hw/misc: fix typo in Aspeed SCU hw-strap2 property name m25p80: Fix QIOR/DIOR handling for Winbond target-arm: Add missed AArch32 TLBI sytem registers hw/arm/virt: tcg: adjust MPIDR like KVM gic: provide defines for v2/v3 targetlist sizes target-arm: Use Neon for zero checking Revert "hw/ptimer: Perform counter wrap around if timer already expired" virtio-mmio: format transport base address in BusClass.get_dev_path Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
14c7d99333
|
@ -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, };
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(),
|
||||
};
|
||||
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 \
|
||||
{\
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in a new issue