aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bsd-user/syscall.c6
-rwxr-xr-xconfigure4
-rw-r--r--exec.c23
-rw-r--r--hw/arm/aspeed_ast2600.c23
-rw-r--r--hw/arm/aspeed_soc.c25
-rw-r--r--hw/arm/fsl-imx6.c21
-rw-r--r--hw/arm/raspi.c190
-rw-r--r--hw/arm/virt-acpi-build.c25
-rw-r--r--hw/char/exynos4210_uart.c5
-rw-r--r--hw/core/machine.c2
-rw-r--r--hw/display/qxl.c7
-rw-r--r--hw/display/qxl.h2
-rw-r--r--hw/misc/imx2_wdt.c2
-rw-r--r--hw/usb/dev-uas.c2
-rw-r--r--hw/usb/host-libusb.c17
-rw-r--r--include/exec/helper-gen.h13
-rw-r--r--include/exec/helper-head.h2
-rw-r--r--include/exec/helper-proto.h6
-rw-r--r--include/exec/helper-tcg.h7
-rw-r--r--include/hw/arm/aspeed_soc.h6
-rw-r--r--include/hw/arm/fsl-imx6.h3
-rw-r--r--include/qemu/seqlock.h4
-rw-r--r--include/qemu/timer.h5
-rw-r--r--include/sysemu/sysemu.h1
-rw-r--r--include/tcg/tcg-op-gvec.h7
-rw-r--r--linux-user/exit.c4
-rw-r--r--linux-user/hppa/target_signal.h1
-rw-r--r--linux-user/signal.c136
-rw-r--r--linux-user/syscall.c22
-rw-r--r--linux-user/trace-events3
-rw-r--r--qapi/ui.json3
-rw-r--r--qemu-deprecated.texi5
-rwxr-xr-xscripts/minikconf.py2
-rw-r--r--target/arm/cpu-param.h2
-rw-r--r--target/arm/cpu.c4
-rw-r--r--target/arm/cpu.h95
-rw-r--r--target/arm/cpu64.c10
-rw-r--r--target/arm/helper-a64.c6
-rw-r--r--target/arm/helper.c327
-rw-r--r--target/arm/internals.h85
-rw-r--r--target/arm/kvm64.c2
-rw-r--r--target/arm/op_helper.c14
-rw-r--r--target/arm/translate-a64.c31
-rw-r--r--target/arm/translate.c42
-rw-r--r--target/i386/cpu.c2
-rw-r--r--target/i386/kvm.c7
-rw-r--r--target/i386/misc_helper.c8
-rw-r--r--tcg/tcg-op-gvec.c32
-rwxr-xr-xtests/check-block.sh2
-rw-r--r--tests/data/acpi/virt/DSDTbin18462 -> 5307 bytes
-rw-r--r--tests/data/acpi/virt/DSDT.memhpbin19799 -> 6644 bytes
-rw-r--r--tests/data/acpi/virt/DSDT.numamembin18462 -> 5307 bytes
-rw-r--r--ui/cocoa.m63
-rw-r--r--ui/gtk.c27
-rw-r--r--ui/sdl2.c16
-rw-r--r--util/qemu-timer-common.c11
-rw-r--r--vl.c18
57 files changed, 1037 insertions, 351 deletions
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index 0d45b654bb..d38ec7a162 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -330,7 +330,7 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
switch(num) {
case TARGET_FREEBSD_NR_exit:
-#ifdef TARGET_GPROF
+#ifdef CONFIG_GPROF
_mcleanup();
#endif
gdb_exit(cpu_env, arg1);
@@ -432,7 +432,7 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
switch(num) {
case TARGET_NETBSD_NR_exit:
-#ifdef TARGET_GPROF
+#ifdef CONFIG_GPROF
_mcleanup();
#endif
gdb_exit(cpu_env, arg1);
@@ -511,7 +511,7 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
switch(num) {
case TARGET_OPENBSD_NR_exit:
-#ifdef TARGET_GPROF
+#ifdef CONFIG_GPROF
_mcleanup();
#endif
gdb_exit(cpu_env, arg1);
diff --git a/configure b/configure
index 115dc38085..16f94cd96b 100755
--- a/configure
+++ b/configure
@@ -6771,6 +6771,9 @@ fi
if test "$l2tpv3" = "yes" ; then
echo "CONFIG_L2TPV3=y" >> $config_host_mak
fi
+if test "$gprof" = "yes" ; then
+ echo "CONFIG_GPROF=y" >> $config_host_mak
+fi
if test "$cap_ng" = "yes" ; then
echo "CONFIG_LIBCAP_NG=y" >> $config_host_mak
fi
@@ -7951,7 +7954,6 @@ alpha)
esac
if test "$gprof" = "yes" ; then
- echo "TARGET_GPROF=y" >> $config_target_mak
if test "$target_linux_user" = "yes" ; then
cflags="-p $cflags"
ldflags="-p $ldflags"
diff --git a/exec.c b/exec.c
index 67e520d18e..8e9cc3b47c 100644
--- a/exec.c
+++ b/exec.c
@@ -98,15 +98,15 @@ CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus);
/* current CPU in the current thread. It is only valid inside
cpu_exec() */
__thread CPUState *current_cpu;
-/* 0 = Do not count executed instructions.
- 1 = Precise instruction counting.
- 2 = Adaptive rate instruction counting. */
-int use_icount;
uintptr_t qemu_host_page_size;
intptr_t qemu_host_page_mask;
#if !defined(CONFIG_USER_ONLY)
+/* 0 = Do not count executed instructions.
+ 1 = Precise instruction counting.
+ 2 = Adaptive rate instruction counting. */
+int use_icount;
typedef struct PhysPageEntry PhysPageEntry;
@@ -1019,14 +1019,13 @@ void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs)
static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
{
- MemTxAttrs attrs;
- hwaddr phys = cpu_get_phys_page_attrs_debug(cpu, pc, &attrs);
- int asidx = cpu_asidx_from_attrs(cpu, attrs);
- if (phys != -1) {
- /* Locks grabbed by tb_invalidate_phys_addr */
- tb_invalidate_phys_addr(cpu->cpu_ases[asidx].as,
- phys | (pc & ~TARGET_PAGE_MASK), attrs);
- }
+ /*
+ * There may not be a virtual to physical translation for the pc
+ * right now, but there may exist cached TB for this pc.
+ * Flush the whole TB cache to force re-translation of such TBs.
+ * This is heavyweight, but we're debugging anyway.
+ */
+ tb_flush(cpu);
}
#endif
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 90cf1c755d..446b44d31c 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -31,6 +31,8 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
[ASPEED_FMC] = 0x1E620000,
[ASPEED_SPI1] = 0x1E630000,
[ASPEED_SPI2] = 0x1E641000,
+ [ASPEED_EHCI1] = 0x1E6A1000,
+ [ASPEED_EHCI2] = 0x1E6A3000,
[ASPEED_MII1] = 0x1E650000,
[ASPEED_MII2] = 0x1E650008,
[ASPEED_MII3] = 0x1E650010,
@@ -79,6 +81,8 @@ static const int aspeed_soc_ast2600_irqmap[] = {
[ASPEED_ADC] = 78,
[ASPEED_XDMA] = 6,
[ASPEED_SDHCI] = 43,
+ [ASPEED_EHCI1] = 5,
+ [ASPEED_EHCI2] = 9,
[ASPEED_EMMC] = 15,
[ASPEED_GPIO] = 40,
[ASPEED_GPIO_1_8V] = 11,
@@ -166,6 +170,11 @@ static void aspeed_soc_ast2600_init(Object *obj)
sizeof(s->spi[i]), typename);
}
+ for (i = 0; i < sc->ehcis_num; i++) {
+ sysbus_init_child_obj(obj, "ehci[*]", OBJECT(&s->ehci[i]),
+ sizeof(s->ehci[i]), TYPE_PLATFORM_EHCI);
+ }
+
snprintf(typename, sizeof(typename), "aspeed.sdmc-%s", socname);
sysbus_init_child_obj(obj, "sdmc", OBJECT(&s->sdmc), sizeof(s->sdmc),
typename);
@@ -416,6 +425,19 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
s->spi[i].ctrl->flash_window_base);
}
+ /* EHCI */
+ for (i = 0; i < sc->ehcis_num; i++) {
+ object_property_set_bool(OBJECT(&s->ehci[i]), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci[i]), 0,
+ sc->memmap[ASPEED_EHCI1 + i]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci[i]), 0,
+ aspeed_soc_get_irq(s, ASPEED_EHCI1 + i));
+ }
+
/* SDMC - SDRAM Memory Controller */
object_property_set_bool(OBJECT(&s->sdmc), true, "realized", &err);
if (err) {
@@ -534,6 +556,7 @@ static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data)
sc->silicon_rev = AST2600_A0_SILICON_REV;
sc->sram_size = 0x10000;
sc->spis_num = 2;
+ sc->ehcis_num = 2;
sc->wdts_num = 4;
sc->macs_num = 4;
sc->irqmap = aspeed_soc_ast2600_irqmap;
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index b5e809a1d3..696c7fda14 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -30,6 +30,7 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = {
[ASPEED_IOMEM] = 0x1E600000,
[ASPEED_FMC] = 0x1E620000,
[ASPEED_SPI1] = 0x1E630000,
+ [ASPEED_EHCI1] = 0x1E6A1000,
[ASPEED_VIC] = 0x1E6C0000,
[ASPEED_SDMC] = 0x1E6E0000,
[ASPEED_SCU] = 0x1E6E2000,
@@ -59,6 +60,8 @@ static const hwaddr aspeed_soc_ast2500_memmap[] = {
[ASPEED_FMC] = 0x1E620000,
[ASPEED_SPI1] = 0x1E630000,
[ASPEED_SPI2] = 0x1E631000,
+ [ASPEED_EHCI1] = 0x1E6A1000,
+ [ASPEED_EHCI2] = 0x1E6A3000,
[ASPEED_VIC] = 0x1E6C0000,
[ASPEED_SDMC] = 0x1E6E0000,
[ASPEED_SCU] = 0x1E6E2000,
@@ -91,6 +94,8 @@ static const int aspeed_soc_ast2400_irqmap[] = {
[ASPEED_UART5] = 10,
[ASPEED_VUART] = 8,
[ASPEED_FMC] = 19,
+ [ASPEED_EHCI1] = 5,
+ [ASPEED_EHCI2] = 13,
[ASPEED_SDMC] = 0,
[ASPEED_SCU] = 21,
[ASPEED_ADC] = 31,
@@ -180,6 +185,11 @@ static void aspeed_soc_init(Object *obj)
sizeof(s->spi[i]), typename);
}
+ for (i = 0; i < sc->ehcis_num; i++) {
+ sysbus_init_child_obj(obj, "ehci[*]", OBJECT(&s->ehci[i]),
+ sizeof(s->ehci[i]), TYPE_PLATFORM_EHCI);
+ }
+
snprintf(typename, sizeof(typename), "aspeed.sdmc-%s", socname);
sysbus_init_child_obj(obj, "sdmc", OBJECT(&s->sdmc), sizeof(s->sdmc),
typename);
@@ -364,6 +374,19 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
s->spi[i].ctrl->flash_window_base);
}
+ /* EHCI */
+ for (i = 0; i < sc->ehcis_num; i++) {
+ object_property_set_bool(OBJECT(&s->ehci[i]), true, "realized", &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci[i]), 0,
+ sc->memmap[ASPEED_EHCI1 + i]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci[i]), 0,
+ aspeed_soc_get_irq(s, ASPEED_EHCI1 + i));
+ }
+
/* SDMC - SDRAM Memory Controller */
object_property_set_bool(OBJECT(&s->sdmc), true, "realized", &err);
if (err) {
@@ -472,6 +495,7 @@ static void aspeed_soc_ast2400_class_init(ObjectClass *oc, void *data)
sc->silicon_rev = AST2400_A1_SILICON_REV;
sc->sram_size = 0x8000;
sc->spis_num = 1;
+ sc->ehcis_num = 1;
sc->wdts_num = 2;
sc->macs_num = 2;
sc->irqmap = aspeed_soc_ast2400_irqmap;
@@ -496,6 +520,7 @@ static void aspeed_soc_ast2500_class_init(ObjectClass *oc, void *data)
sc->silicon_rev = AST2500_A1_SILICON_REV;
sc->sram_size = 0x9000;
sc->spis_num = 2;
+ sc->ehcis_num = 2;
sc->wdts_num = 3;
sc->macs_num = 2;
sc->irqmap = aspeed_soc_ast2500_irqmap;
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index 552145b24e..ecc62855f2 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -91,6 +91,12 @@ static void fsl_imx6_init(Object *obj)
sysbus_init_child_obj(obj, name, &s->spi[i], sizeof(s->spi[i]),
TYPE_IMX_SPI);
}
+ for (i = 0; i < FSL_IMX6_NUM_WDTS; i++) {
+ snprintf(name, NAME_SIZE, "wdt%d", i);
+ sysbus_init_child_obj(obj, name, &s->wdt[i], sizeof(s->wdt[i]),
+ TYPE_IMX2_WDT);
+ }
+
sysbus_init_child_obj(obj, "eth", &s->eth, sizeof(s->eth), TYPE_IMX_ENET);
}
@@ -383,6 +389,21 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(DEVICE(&s->a9mpcore),
FSL_IMX6_ENET_MAC_1588_IRQ));
+ /*
+ * Watchdog
+ */
+ for (i = 0; i < FSL_IMX6_NUM_WDTS; i++) {
+ static const hwaddr FSL_IMX6_WDOGn_ADDR[FSL_IMX6_NUM_WDTS] = {
+ FSL_IMX6_WDOG1_ADDR,
+ FSL_IMX6_WDOG2_ADDR,
+ };
+
+ object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized",
+ &error_abort);
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, FSL_IMX6_WDOGn_ADDR[i]);
+ }
+
/* ROM memory */
memory_region_init_rom(&s->rom, NULL, "imx6.rom",
FSL_IMX6_ROM_SIZE, &err);
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index 3996f6c63a..90ad9b8115 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -13,9 +13,11 @@
#include "qemu/osdep.h"
#include "qemu/units.h"
+#include "qemu/cutils.h"
#include "qapi/error.h"
#include "cpu.h"
#include "hw/arm/bcm2836.h"
+#include "hw/registerfields.h"
#include "qemu/error-report.h"
#include "hw/boards.h"
#include "hw/loader.h"
@@ -29,13 +31,104 @@
#define FIRMWARE_ADDR_3 0x80000 /* Pi 3 loads kernel.img here by default */
#define SPINTABLE_ADDR 0xd8 /* Pi 3 bootloader spintable */
-/* Table of Linux board IDs for different Pi versions */
-static const int raspi_boardid[] = {[1] = 0xc42, [2] = 0xc43, [3] = 0xc44};
+/* Registered machine type (matches RPi Foundation bootloader and U-Boot) */
+#define MACH_TYPE_BCM2708 3138
-typedef struct RasPiState {
+typedef struct RaspiMachineState {
+ /*< private >*/
+ MachineState parent_obj;
+ /*< public >*/
BCM283XState soc;
MemoryRegion ram;
-} RasPiState;
+} RaspiMachineState;
+
+typedef struct RaspiMachineClass {
+ /*< private >*/
+ MachineClass parent_obj;
+ /*< public >*/
+ uint32_t board_rev;
+} RaspiMachineClass;
+
+#define TYPE_RASPI_MACHINE MACHINE_TYPE_NAME("raspi-common")
+#define RASPI_MACHINE(obj) \
+ OBJECT_CHECK(RaspiMachineState, (obj), TYPE_RASPI_MACHINE)
+
+#define RASPI_MACHINE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(RaspiMachineClass, (klass), TYPE_RASPI_MACHINE)
+#define RASPI_MACHINE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(RaspiMachineClass, (obj), TYPE_RASPI_MACHINE)
+
+/*
+ * Board revision codes:
+ * www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/
+ */
+FIELD(REV_CODE, REVISION, 0, 4);
+FIELD(REV_CODE, TYPE, 4, 8);
+FIELD(REV_CODE, PROCESSOR, 12, 4);
+FIELD(REV_CODE, MANUFACTURER, 16, 4);
+FIELD(REV_CODE, MEMORY_SIZE, 20, 3);
+FIELD(REV_CODE, STYLE, 23, 1);
+
+static uint64_t board_ram_size(uint32_t board_rev)
+{
+ assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); /* Only new style */
+ return 256 * MiB << FIELD_EX32(board_rev, REV_CODE, MEMORY_SIZE);
+}
+
+static int board_processor_id(uint32_t board_rev)
+{
+ assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); /* Only new style */
+ return FIELD_EX32(board_rev, REV_CODE, PROCESSOR);
+}
+
+static int board_version(uint32_t board_rev)
+{
+ return board_processor_id(board_rev) + 1;
+}
+
+static const char *board_soc_type(uint32_t board_rev)
+{
+ static const char *soc_types[] = {
+ NULL, TYPE_BCM2836, TYPE_BCM2837,
+ };
+ int proc_id = board_processor_id(board_rev);
+
+ if (proc_id >= ARRAY_SIZE(soc_types) || !soc_types[proc_id]) {
+ error_report("Unsupported processor id '%d' (board revision: 0x%x)",
+ proc_id, board_rev);
+ exit(1);
+ }
+ return soc_types[proc_id];
+}
+
+static int cores_count(uint32_t board_rev)
+{
+ static const int soc_cores_count[] = {
+ 0, BCM283X_NCPUS, BCM283X_NCPUS,
+ };
+ int proc_id = board_processor_id(board_rev);
+
+ if (proc_id >= ARRAY_SIZE(soc_cores_count) || !soc_cores_count[proc_id]) {
+ error_report("Unsupported processor id '%d' (board revision: 0x%x)",
+ proc_id, board_rev);
+ exit(1);
+ }
+ return soc_cores_count[proc_id];
+}
+
+static const char *board_type(uint32_t board_rev)
+{
+ static const char *types[] = {
+ "A", "B", "A+", "B+", "2B", "Alpha", "CM1", NULL, "3B", "Zero",
+ "CM3", NULL, "Zero W", "3B+", "3A+", NULL, "CM3+", "4B",
+ };
+ assert(FIELD_EX32(board_rev, REV_CODE, STYLE)); /* Only new style */
+ int bt = FIELD_EX32(board_rev, REV_CODE, TYPE);
+ if (bt >= ARRAY_SIZE(types) || !types[bt]) {
+ return "Unknown";
+ }
+ return types[bt];
+}
static void write_smpboot(ARMCPU *cpu, const struct arm_boot_info *info)
{
@@ -116,7 +209,7 @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
static struct arm_boot_info binfo;
int r;
- binfo.board_id = raspi_boardid[version];
+ binfo.board_id = MACH_TYPE_BCM2708;
binfo.ram_size = ram_size;
binfo.nb_cpus = machine->smp.cpus;
@@ -164,25 +257,26 @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
arm_load_kernel(ARM_CPU(first_cpu), machine, &binfo);
}
-static void raspi_init(MachineState *machine, int version)
+static void raspi_machine_init(MachineState *machine)
{
- RasPiState *s = g_new0(RasPiState, 1);
+ RaspiMachineClass *mc = RASPI_MACHINE_GET_CLASS(machine);
+ RaspiMachineState *s = RASPI_MACHINE(machine);
+ uint32_t board_rev = mc->board_rev;
+ int version = board_version(board_rev);
+ uint64_t ram_size = board_ram_size(board_rev);
uint32_t vcram_size;
DriveInfo *di;
BlockBackend *blk;
BusState *bus;
DeviceState *carddev;
- if (machine->ram_size > 1 * GiB) {
- error_report("Requested ram size is too large for this machine: "
- "maximum is 1GB");
+ if (machine->ram_size != ram_size) {
+ char *size_str = size_to_str(ram_size);
+ error_report("Invalid RAM size, should be %s", size_str);
+ g_free(size_str);
exit(1);
}
- object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc),
- version == 3 ? TYPE_BCM2837 : TYPE_BCM2836,
- &error_abort, NULL);
-
/* Allocate and map RAM */
memory_region_allocate_system_memory(&s->ram, OBJECT(machine), "ram",
machine->ram_size);
@@ -190,9 +284,10 @@ static void raspi_init(MachineState *machine, int version)
memory_region_add_subregion_overlap(get_system_memory(), 0, &s->ram, 0);
/* Setup the SOC */
+ object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc),
+ board_soc_type(board_rev), &error_abort, NULL);
object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(&s->ram),
&error_abort);
- int board_rev = version == 3 ? 0xa02082 : 0xa21041;
object_property_set_int(OBJECT(&s->soc), board_rev, "board-rev",
&error_abort);
object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_abort);
@@ -214,45 +309,46 @@ static void raspi_init(MachineState *machine, int version)
setup_boot(machine, version, machine->ram_size - vcram_size);
}
-static void raspi2_init(MachineState *machine)
+static void raspi_machine_class_init(ObjectClass *oc, void *data)
{
- raspi_init(machine, 2);
-}
+ MachineClass *mc = MACHINE_CLASS(oc);
+ RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc);
+ uint32_t board_rev = (uint32_t)(uintptr_t)data;
-static void raspi2_machine_init(MachineClass *mc)
-{
- mc->desc = "Raspberry Pi 2";
- mc->init = raspi2_init;
+ rmc->board_rev = board_rev;
+ mc->desc = g_strdup_printf("Raspberry Pi %s", board_type(board_rev));
+ mc->init = raspi_machine_init;
mc->block_default_type = IF_SD;
mc->no_parallel = 1;
mc->no_floppy = 1;
mc->no_cdrom = 1;
- mc->max_cpus = BCM283X_NCPUS;
- mc->min_cpus = BCM283X_NCPUS;
- mc->default_cpus = BCM283X_NCPUS;
- mc->default_ram_size = 1 * GiB;
- mc->ignore_memory_transaction_failures = true;
+ mc->default_cpus = mc->min_cpus = mc->max_cpus = cores_count(board_rev);
+ mc->default_ram_size = board_ram_size(board_rev);
+ if (board_version(board_rev) == 2) {
+ mc->ignore_memory_transaction_failures = true;
+ }
};
-DEFINE_MACHINE("raspi2", raspi2_machine_init)
+static const TypeInfo raspi_machine_types[] = {
+ {
+ .name = MACHINE_TYPE_NAME("raspi2"),
+ .parent = TYPE_RASPI_MACHINE,
+ .class_init = raspi_machine_class_init,
+ .class_data = (void *)0xa21041,
#ifdef TARGET_AARCH64
-static void raspi3_init(MachineState *machine)
-{
- raspi_init(machine, 3);
-}
-
-static void raspi3_machine_init(MachineClass *mc)
-{
- mc->desc = "Raspberry Pi 3";
- mc->init = raspi3_init;
- mc->block_default_type = IF_SD;
- mc->no_parallel = 1;
- mc->no_floppy = 1;
- mc->no_cdrom = 1;
- mc->max_cpus = BCM283X_NCPUS;
- mc->min_cpus = BCM283X_NCPUS;
- mc->default_cpus = BCM283X_NCPUS;
- mc->default_ram_size = 1 * GiB;
-}
-DEFINE_MACHINE("raspi3", raspi3_machine_init)
+ }, {
+ .name = MACHINE_TYPE_NAME("raspi3"),
+ .parent = TYPE_RASPI_MACHINE,
+ .class_init = raspi_machine_class_init,
+ .class_data = (void *)0xa02082,
#endif
+ }, {
+ .name = TYPE_RASPI_MACHINE,
+ .parent = TYPE_MACHINE,
+ .instance_size = sizeof(RaspiMachineState),
+ .class_size = sizeof(RaspiMachineClass),
+ .abstract = true,
+ }
+};
+
+DEFINE_TYPES(raspi_machine_types)
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index bd5f771e9b..fb4b166f82 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -78,11 +78,6 @@ static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap,
AML_EXCLUSIVE, &uart_irq, 1));
aml_append(dev, aml_name_decl("_CRS", crs));
- /* The _ADR entry is used to link this device to the UART described
- * in the SPCR table, i.e. SPCR.base_address.address == _ADR.
- */
- aml_append(dev, aml_name_decl("_ADR", aml_int(uart_memmap->base)));
-
aml_append(scope, dev);
}
@@ -156,7 +151,7 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
{
int ecam_id = VIRT_ECAM_ID(highmem_ecam);
Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
- int i, bus_no;
+ int i, slot_no;
hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
@@ -170,18 +165,17 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
aml_append(dev, aml_name_decl("_BBN", aml_int(0)));
- aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
aml_append(dev, aml_name_decl("_UID", aml_string("PCI0")));
aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device")));
aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
/* Declare the PCI Routing Table. */
- Aml *rt_pkg = aml_varpackage(nr_pcie_buses * PCI_NUM_PINS);
- for (bus_no = 0; bus_no < nr_pcie_buses; bus_no++) {
+ Aml *rt_pkg = aml_varpackage(PCI_SLOT_MAX * PCI_NUM_PINS);
+ for (slot_no = 0; slot_no < PCI_SLOT_MAX; slot_no++) {
for (i = 0; i < PCI_NUM_PINS; i++) {
- int gsi = (i + bus_no) % PCI_NUM_PINS;
+ int gsi = (i + slot_no) % PCI_NUM_PINS;
Aml *pkg = aml_package(4);
- aml_append(pkg, aml_int((bus_no << 16) | 0xFFFF));
+ aml_append(pkg, aml_int((slot_no << 16) | 0xFFFF));
aml_append(pkg, aml_int(i));
aml_append(pkg, aml_name("GSI%d", gsi));
aml_append(pkg, aml_int(0));
@@ -195,7 +189,7 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
uint32_t irqs = irq + i;
Aml *dev_gsi = aml_device("GSI%d", i);
aml_append(dev_gsi, aml_name_decl("_HID", aml_string("PNP0C0F")));
- aml_append(dev_gsi, aml_name_decl("_UID", aml_int(0)));
+ aml_append(dev_gsi, aml_name_decl("_UID", aml_int(i)));
crs = aml_resource_template();
aml_append(crs,
aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
@@ -242,7 +236,6 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
size_mmio_high));
}
- aml_append(method, aml_name_decl("RBUF", rbuf));
aml_append(method, aml_return(rbuf));
aml_append(dev, method);
@@ -317,10 +310,6 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
aml_append(method, aml_return(buf));
aml_append(dev, method);
- Aml *dev_rp0 = aml_device("%s", "RP0");
- aml_append(dev_rp0, aml_name_decl("_ADR", aml_int(0)));
- aml_append(dev, dev_rp0);
-
Aml *dev_res0 = aml_device("%s", "RES0");
aml_append(dev_res0, aml_name_decl("_HID", aml_string("PNP0C02")));
crs = aml_resource_template();
@@ -338,7 +327,6 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
{
Aml *dev = aml_device("GPO0");
aml_append(dev, aml_name_decl("_HID", aml_string("ARMH0061")));
- aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
aml_append(dev, aml_name_decl("_UID", aml_int(0)));
Aml *crs = aml_resource_template();
@@ -368,7 +356,6 @@ static void acpi_dsdt_add_power_button(Aml *scope)
{
Aml *dev = aml_device(ACPI_POWER_BUTTON_DEVICE);
aml_append(dev, aml_name_decl("_HID", aml_string("PNP0C0C")));
- aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
aml_append(dev, aml_name_decl("_UID", aml_int(0)));
aml_append(scope, dev);
}
diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c
index 25d6588e41..96d5180e3e 100644
--- a/hw/char/exynos4210_uart.c
+++ b/hw/char/exynos4210_uart.c
@@ -674,8 +674,6 @@ static void exynos4210_uart_init(Object *obj)
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
Exynos4210UartState *s = EXYNOS4210_UART(dev);
- s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
- exynos4210_uart_timeout_int, s);
s->wordtime = NANOSECONDS_PER_SECOND * 10 / 9600;
/* memory mapping */
@@ -691,6 +689,9 @@ static void exynos4210_uart_realize(DeviceState *dev, Error **errp)
{
Exynos4210UartState *s = EXYNOS4210_UART(dev);
+ s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+ exynos4210_uart_timeout_int, s);
+
qemu_chr_fe_set_handlers(&s->chr, exynos4210_uart_can_receive,
exynos4210_uart_receive, exynos4210_uart_event,
NULL, s, NULL, true);
diff --git a/hw/core/machine.c b/hw/core/machine.c
index d8e30e4895..84812a1d1c 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -34,6 +34,8 @@ GlobalProperty hw_compat_4_2[] = {
{ "vhost-blk-device", "seg_max_adjust", "off"},
{ "usb-host", "suppress-remote-wake", "off" },
{ "usb-redir", "suppress-remote-wake", "off" },
+ { "qxl", "revision", "4" },
+ { "qxl-vga", "revision", "4" },
};
const size_t hw_compat_4_2_len = G_N_ELEMENTS(hw_compat_4_2);
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index c33b1915a5..64884da708 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -1309,7 +1309,8 @@ static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
PCIQXLDevice *qxl = container_of(vga, PCIQXLDevice, vga);
trace_qxl_io_write_vga(qxl->id, qxl_mode_to_string(qxl->mode), addr, val);
- if (qxl->mode != QXL_MODE_VGA) {
+ if (qxl->mode != QXL_MODE_VGA &&
+ qxl->revision <= QXL_REVISION_STABLE_V12) {
qxl_destroy_primary(qxl, QXL_SYNC);
qxl_soft_reset(qxl);
}
@@ -2121,6 +2122,10 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp)
pci_device_rev = QXL_REVISION_STABLE_V12;
io_size = pow2ceil(QXL_IO_RANGE_SIZE);
break;
+ case 5: /* qxl-5 */
+ pci_device_rev = QXL_REVISION_STABLE_V12 + 1;
+ io_size = pow2ceil(QXL_IO_RANGE_SIZE);
+ break;
default:
error_setg(errp, "Invalid revision %d for qxl device (max %d)",
qxl->revision, QXL_DEFAULT_REVISION);
diff --git a/hw/display/qxl.h b/hw/display/qxl.h
index 80eb0d2672..707631a1f5 100644
--- a/hw/display/qxl.h
+++ b/hw/display/qxl.h
@@ -144,7 +144,7 @@ typedef struct PCIQXLDevice {
} \
} while (0)
-#define QXL_DEFAULT_REVISION QXL_REVISION_STABLE_V12
+#define QXL_DEFAULT_REVISION (QXL_REVISION_STABLE_V12 + 1)
/* qxl.c */
void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
diff --git a/hw/misc/imx2_wdt.c b/hw/misc/imx2_wdt.c
index 5576778a32..2aedfe803a 100644
--- a/hw/misc/imx2_wdt.c
+++ b/hw/misc/imx2_wdt.c
@@ -29,7 +29,7 @@ static void imx2_wdt_write(void *opaque, hwaddr addr,
uint64_t value, unsigned int size)
{
if (addr == IMX2_WDT_WCR &&
- (value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS))) {
+ (~value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS))) {
watchdog_perform_action();
}
}
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index 9825ec37d0..11a8684cc2 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -303,7 +303,7 @@ static const USBDescDevice desc_device_high = {
static const USBDescDevice desc_device_super = {
.bcdUSB = 0x0300,
- .bMaxPacketSize0 = 64,
+ .bMaxPacketSize0 = 9,
.bNumConfigurations = 1,
.confs = (USBDescConfig[]) {
{
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index 2594700901..2ac7a936fb 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -354,9 +354,7 @@ static USBHostRequest *usb_host_req_alloc(USBHostDevice *s, USBPacket *p,
static void usb_host_req_free(USBHostRequest *r)
{
- if (r->host) {
- QTAILQ_REMOVE(&r->host->requests, r, next);
- }
+ QTAILQ_REMOVE(&r->host->requests, r, next);
libusb_free_transfer(r->xfer);
g_free(r->buffer);
g_free(r);
@@ -468,12 +466,7 @@ static void usb_host_req_abort(USBHostRequest *r)
usb_packet_complete(USB_DEVICE(s), r->p);
}
r->p = NULL;
- }
-
- QTAILQ_REMOVE(&r->host->requests, r, next);
- r->host = NULL;
- if (inflight) {
libusb_cancel_transfer(r->xfer);
}
}
@@ -962,6 +955,13 @@ static void usb_host_abort_xfers(USBHostDevice *s)
QTAILQ_FOREACH_SAFE(r, &s->requests, next, rtmp) {
usb_host_req_abort(r);
}
+
+ while (QTAILQ_FIRST(&s->requests) != NULL) {
+ struct timeval tv;
+ memset(&tv, 0, sizeof(tv));
+ tv.tv_usec = 2500;
+ libusb_handle_events_timeout(ctx, &tv);
+ }
}
static int usb_host_close(USBHostDevice *s)
@@ -1011,6 +1011,7 @@ static void usb_host_exit_notifier(struct Notifier *n, void *data)
USBHostDevice *s = container_of(n, USBHostDevice, exit);
if (s->dh) {
+ usb_host_abort_xfers(s);
usb_host_release_interfaces(s);
libusb_reset_device(s->dh);
usb_host_attach_kernel(s);
diff --git a/include/exec/helper-gen.h b/include/exec/helper-gen.h
index 236ff40524..29c02f85dc 100644
--- a/include/exec/helper-gen.h
+++ b/include/exec/helper-gen.h
@@ -66,6 +66,18 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
tcg_gen_callN(HELPER(name), dh_retvar(ret), 6, args); \
}
+#define DEF_HELPER_FLAGS_7(name, flags, ret, t1, t2, t3, t4, t5, t6, t7)\
+static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
+ dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
+ dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6), \
+ dh_arg_decl(t7, 7)) \
+{ \
+ TCGTemp *args[7] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
+ dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6), \
+ dh_arg(t7, 7) }; \
+ tcg_gen_callN(HELPER(name), dh_retvar(ret), 7, args); \
+}
+
#include "helper.h"
#include "trace/generated-helpers.h"
#include "trace/generated-helpers-wrappers.h"
@@ -79,6 +91,7 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
#undef DEF_HELPER_FLAGS_4
#undef DEF_HELPER_FLAGS_5
#undef DEF_HELPER_FLAGS_6
+#undef DEF_HELPER_FLAGS_7
#undef GEN_HELPER
#endif /* HELPER_GEN_H */
diff --git a/include/exec/helper-head.h b/include/exec/helper-head.h
index f2519c9741..3094c7946d 100644
--- a/include/exec/helper-head.h
+++ b/include/exec/helper-head.h
@@ -148,6 +148,8 @@
DEF_HELPER_FLAGS_5(name, 0, ret, t1, t2, t3, t4, t5)
#define DEF_HELPER_6(name, ret, t1, t2, t3, t4, t5, t6) \
DEF_HELPER_FLAGS_6(name, 0, ret, t1, t2, t3, t4, t5, t6)
+#define DEF_HELPER_7(name, ret, t1, t2, t3, t4, t5, t6, t7) \
+ DEF_HELPER_FLAGS_7(name, 0, ret, t1, t2, t3, t4, t5, t6, t7)
/* MAX_OPC_PARAM_IARGS must be set to n if last entry is DEF_HELPER_FLAGS_n. */
diff --git a/include/exec/helper-proto.h b/include/exec/helper-proto.h
index 1c4ba9bc78..a0a8d9aa46 100644
--- a/include/exec/helper-proto.h
+++ b/include/exec/helper-proto.h
@@ -30,6 +30,11 @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
dh_ctype(t4), dh_ctype(t5), dh_ctype(t6));
+#define DEF_HELPER_FLAGS_7(name, flags, ret, t1, t2, t3, t4, t5, t6, t7) \
+dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
+ dh_ctype(t4), dh_ctype(t5), dh_ctype(t6), \
+ dh_ctype(t7));
+
#include "helper.h"
#include "trace/generated-helpers.h"
#include "tcg-runtime.h"
@@ -42,5 +47,6 @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
#undef DEF_HELPER_FLAGS_4
#undef DEF_HELPER_FLAGS_5
#undef DEF_HELPER_FLAGS_6
+#undef DEF_HELPER_FLAGS_7
#endif /* HELPER_PROTO_H */
diff --git a/include/exec/helper-tcg.h b/include/exec/helper-tcg.h
index 573c2ce2e9..27870509a2 100644
--- a/include/exec/helper-tcg.h
+++ b/include/exec/helper-tcg.h
@@ -52,6 +52,12 @@
| dh_sizemask(t2, 2) | dh_sizemask(t3, 3) | dh_sizemask(t4, 4) \
| dh_sizemask(t5, 5) | dh_sizemask(t6, 6) },
+#define DEF_HELPER_FLAGS_7(NAME, FLAGS, ret, t1, t2, t3, t4, t5, t6, t7) \
+ { .func = HELPER(NAME), .name = str(NAME), .flags = FLAGS, \
+ .sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) \
+ | dh_sizemask(t2, 2) | dh_sizemask(t3, 3) | dh_sizemask(t4, 4) \
+ | dh_sizemask(t5, 5) | dh_sizemask(t6, 6) | dh_sizemask(t7, 7) },
+
#include "helper.h"
#include "trace/generated-helpers.h"
#include "tcg-runtime.h"
@@ -65,5 +71,6 @@
#undef DEF_HELPER_FLAGS_4
#undef DEF_HELPER_FLAGS_5
#undef DEF_HELPER_FLAGS_6
+#undef DEF_HELPER_FLAGS_7
#endif /* HELPER_TCG_H */
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 90ac7f7ffa..78b9f6ae53 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -26,8 +26,10 @@
#include "target/arm/cpu.h"
#include "hw/gpio/aspeed_gpio.h"
#include "hw/sd/aspeed_sdhci.h"
+#include "hw/usb/hcd-ehci.h"
#define ASPEED_SPIS_NUM 2
+#define ASPEED_EHCIS_NUM 2
#define ASPEED_WDTS_NUM 4
#define ASPEED_CPUS_NUM 2
#define ASPEED_MACS_NUM 4
@@ -50,6 +52,7 @@ typedef struct AspeedSoCState {
AspeedXDMAState xdma;
AspeedSMCState fmc;
AspeedSMCState spi[ASPEED_SPIS_NUM];
+ EHCISysBusState ehci[ASPEED_EHCIS_NUM];
AspeedSDMCState sdmc;
AspeedWDTState wdt[ASPEED_WDTS_NUM];
FTGMAC100State ftgmac100[ASPEED_MACS_NUM];
@@ -71,6 +74,7 @@ typedef struct AspeedSoCClass {
uint32_t silicon_rev;
uint64_t sram_size;
int spis_num;
+ int ehcis_num;
int wdts_num;
int macs_num;
const int *irqmap;
@@ -94,6 +98,8 @@ enum {
ASPEED_FMC,
ASPEED_SPI1,
ASPEED_SPI2,
+ ASPEED_EHCI1,
+ ASPEED_EHCI2,
ASPEED_VIC,
ASPEED_SDMC,
ASPEED_SCU,
diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h
index 1265a55c3b..60eadccb42 100644
--- a/include/hw/arm/fsl-imx6.h
+++ b/include/hw/arm/fsl-imx6.h
@@ -21,6 +21,7 @@
#include "hw/cpu/a9mpcore.h"
#include "hw/misc/imx6_ccm.h"
#include "hw/misc/imx6_src.h"
+#include "hw/misc/imx2_wdt.h"
#include "hw/char/imx_serial.h"
#include "hw/timer/imx_gpt.h"
#include "hw/timer/imx_epit.h"
@@ -42,6 +43,7 @@
#define FSL_IMX6_NUM_GPIOS 7
#define FSL_IMX6_NUM_ESDHCS 4
#define FSL_IMX6_NUM_ECSPIS 5
+#define FSL_IMX6_NUM_WDTS 2
typedef struct FslIMX6State {
/*< private >*/
@@ -59,6 +61,7 @@ typedef struct FslIMX6State {
IMXGPIOState gpio[FSL_IMX6_NUM_GPIOS];
SDHCIState esdhc[FSL_IMX6_NUM_ESDHCS];
IMXSPIState spi[FSL_IMX6_NUM_ECSPIS];
+ IMX2WdtState wdt[FSL_IMX6_NUM_WDTS];
IMXFECState eth;
MemoryRegion rom;
MemoryRegion caam;
diff --git a/include/qemu/seqlock.h b/include/qemu/seqlock.h
index fd408b7ec5..8b6b4ee4bb 100644
--- a/include/qemu/seqlock.h
+++ b/include/qemu/seqlock.h
@@ -55,11 +55,11 @@ static inline void seqlock_write_lock_impl(QemuSeqLock *sl, QemuLockable *lock)
#define seqlock_write_lock(sl, lock) \
seqlock_write_lock_impl(sl, QEMU_MAKE_LOCKABLE(lock))
-/* Lock out other writers and update the count. */
+/* Update the count and release the lock. */
static inline void seqlock_write_unlock_impl(QemuSeqLock *sl, QemuLockable *lock)
{
+ seqlock_write_end(sl);
qemu_lockable_unlock(lock);
- seqlock_write_begin(sl);
}
#define seqlock_write_unlock(sl, lock) \
seqlock_write_unlock_impl(sl, QEMU_MAKE_LOCKABLE(lock))
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 85bc6eb00b..6a8b48b5a9 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -838,14 +838,11 @@ extern int use_rt_clock;
static inline int64_t get_clock(void)
{
-#ifdef CLOCK_MONOTONIC
if (use_rt_clock) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec * 1000000000LL + ts.tv_nsec;
- } else
-#endif
- {
+ } else {
/* XXX: using gettimeofday leads to problems if the date
changes, so it should be avoided. */
return get_clock_realtime();
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 6358a324a7..7956e9054a 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -41,7 +41,6 @@ extern const char *keyboard_layout;
extern int win2k_install_hack;
extern int alt_grab;
extern int ctrl_grab;
-extern int cursor_hide;
extern int graphic_rotate;
extern int no_shutdown;
extern int old_param;
diff --git a/include/tcg/tcg-op-gvec.h b/include/tcg/tcg-op-gvec.h
index 830d68f697..74534e2480 100644
--- a/include/tcg/tcg-op-gvec.h
+++ b/include/tcg/tcg-op-gvec.h
@@ -83,6 +83,13 @@ void tcg_gen_gvec_4_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
uint32_t maxsz, int32_t data,
gen_helper_gvec_4_ptr *fn);
+typedef void gen_helper_gvec_5_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr,
+ TCGv_ptr, TCGv_ptr, TCGv_i32);
+void tcg_gen_gvec_5_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
+ uint32_t cofs, uint32_t eofs, TCGv_ptr ptr,
+ uint32_t oprsz, uint32_t maxsz, int32_t data,
+ gen_helper_gvec_5_ptr *fn);
+
/* Expand a gvec operation. Either inline or out-of-line depending on
the actual vector size and the operations supported by the host. */
typedef struct {
diff --git a/linux-user/exit.c b/linux-user/exit.c
index a362ef67d2..1594015444 100644
--- a/linux-user/exit.c
+++ b/linux-user/exit.c
@@ -18,7 +18,7 @@
*/
#include "qemu/osdep.h"
#include "qemu.h"
-#ifdef TARGET_GPROF
+#ifdef CONFIG_GPROF
#include <sys/gmon.h>
#endif
@@ -28,7 +28,7 @@ extern void __gcov_dump(void);
void preexit_cleanup(CPUArchState *env, int code)
{
-#ifdef TARGET_GPROF
+#ifdef CONFIG_GPROF
_mcleanup();
#endif
#ifdef CONFIG_GCOV
diff --git a/linux-user/hppa/target_signal.h b/linux-user/hppa/target_signal.h
index ba159ff8d0..c2a0102ed7 100644
--- a/linux-user/hppa/target_signal.h
+++ b/linux-user/hppa/target_signal.h
@@ -34,6 +34,7 @@
#define TARGET_SIGURG 29
#define TARGET_SIGXFSZ 30
#define TARGET_SIGSYS 31
+#define TARGET_SIGRTMIN 32
#define TARGET_SIG_BLOCK 0
#define TARGET_SIG_UNBLOCK 1
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 5ca6d62b15..94259dd070 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -30,6 +30,15 @@ static struct target_sigaction sigact_table[TARGET_NSIG];
static void host_signal_handler(int host_signum, siginfo_t *info,
void *puc);
+
+/*
+ * System includes define _NSIG as SIGRTMAX + 1,
+ * but qemu (like the kernel) defines TARGET_NSIG as TARGET_SIGRTMAX
+ * and the first signal is SIGHUP defined as 1
+ * Signal number 0 is reserved for use as kill(pid, 0), to test whether
+ * a process exists without sending it a signal.
+ */
+QEMU_BUILD_BUG_ON(__SIGRTMAX + 1 != _NSIG);
static uint8_t host_to_target_signal_table[_NSIG] = {
[SIGHUP] = TARGET_SIGHUP,
[SIGINT] = TARGET_SIGINT,
@@ -66,26 +75,25 @@ static uint8_t host_to_target_signal_table[_NSIG] = {
[SIGPWR] = TARGET_SIGPWR,
[SIGSYS] = TARGET_SIGSYS,
/* next signals stay the same */
- /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
- host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
- To fix this properly we need to do manual signal delivery multiplexed
- over a single host signal. */
- [__SIGRTMIN] = __SIGRTMAX,
- [__SIGRTMAX] = __SIGRTMIN,
};
-static uint8_t target_to_host_signal_table[_NSIG];
+static uint8_t target_to_host_signal_table[TARGET_NSIG + 1];
+
+/* valid sig is between 1 and _NSIG - 1 */
int host_to_target_signal(int sig)
{
- if (sig < 0 || sig >= _NSIG)
+ if (sig < 1 || sig >= _NSIG) {
return sig;
+ }
return host_to_target_signal_table[sig];
}
+/* valid sig is between 1 and TARGET_NSIG */
int target_to_host_signal(int sig)
{
- if (sig < 0 || sig >= _NSIG)
+ if (sig < 1 || sig > TARGET_NSIG) {
return sig;
+ }
return target_to_host_signal_table[sig];
}
@@ -106,11 +114,15 @@ static inline int target_sigismember(const target_sigset_t *set, int signum)
void host_to_target_sigset_internal(target_sigset_t *d,
const sigset_t *s)
{
- int i;
+ int host_sig, target_sig;
target_sigemptyset(d);
- for (i = 1; i <= TARGET_NSIG; i++) {
- if (sigismember(s, i)) {
- target_sigaddset(d, host_to_target_signal(i));
+ for (host_sig = 1; host_sig < _NSIG; host_sig++) {
+ target_sig = host_to_target_signal(host_sig);
+ if (target_sig < 1 || target_sig > TARGET_NSIG) {
+ continue;
+ }
+ if (sigismember(s, host_sig)) {
+ target_sigaddset(d, target_sig);
}
}
}
@@ -128,11 +140,15 @@ void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
void target_to_host_sigset_internal(sigset_t *d,
const target_sigset_t *s)
{
- int i;
+ int host_sig, target_sig;
sigemptyset(d);
- for (i = 1; i <= TARGET_NSIG; i++) {
- if (target_sigismember(s, i)) {
- sigaddset(d, target_to_host_signal(i));
+ for (target_sig = 1; target_sig <= TARGET_NSIG; target_sig++) {
+ host_sig = target_to_host_signal(target_sig);
+ if (host_sig < 1 || host_sig >= _NSIG) {
+ continue;
+ }
+ if (target_sigismember(s, target_sig)) {
+ sigaddset(d, host_sig);
}
}
}
@@ -480,37 +496,72 @@ static int core_dump_signal(int sig)
}
}
+static void signal_table_init(void)
+{
+ int host_sig, target_sig, count;
+
+ /*
+ * Signals are supported starting from TARGET_SIGRTMIN and going up
+ * until we run out of host realtime signals.
+ * glibc at least uses only the lower 2 rt signals and probably
+ * nobody's using the upper ones.
+ * it's why SIGRTMIN (34) is generally greater than __SIGRTMIN (32)
+ * To fix this properly we need to do manual signal delivery multiplexed
+ * over a single host signal.
+ * Attempts for configure "missing" signals via sigaction will be
+ * silently ignored.
+ */
+ for (host_sig = SIGRTMIN; host_sig <= SIGRTMAX; host_sig++) {
+ target_sig = host_sig - SIGRTMIN + TARGET_SIGRTMIN;
+ if (target_sig <= TARGET_NSIG) {
+ host_to_target_signal_table[host_sig] = target_sig;
+ }
+ }
+
+ /* generate signal conversion tables */
+ for (target_sig = 1; target_sig <= TARGET_NSIG; target_sig++) {
+ target_to_host_signal_table[target_sig] = _NSIG; /* poison */
+ }
+ for (host_sig = 1; host_sig < _NSIG; host_sig++) {
+ if (host_to_target_signal_table[host_sig] == 0) {
+ host_to_target_signal_table[host_sig] = host_sig;
+ }
+ target_sig = host_to_target_signal_table[host_sig];
+ if (target_sig <= TARGET_NSIG) {
+ target_to_host_signal_table[target_sig] = host_sig;
+ }
+ }
+
+ if (trace_event_get_state_backends(TRACE_SIGNAL_TABLE_INIT)) {
+ for (target_sig = 1, count = 0; target_sig <= TARGET_NSIG; target_sig++) {
+ if (target_to_host_signal_table[target_sig] == _NSIG) {
+ count++;
+ }
+ }
+ trace_signal_table_init(count);
+ }
+}
+
void signal_init(void)
{
TaskState *ts = (TaskState *)thread_cpu->opaque;
struct sigaction act;
struct sigaction oact;
- int i, j;
+ int i;
int host_sig;
- /* generate signal conversion tables */
- for(i = 1; i < _NSIG; i++) {
- if (host_to_target_signal_table[i] == 0)
- host_to_target_signal_table[i] = i;
- }
- for(i = 1; i < _NSIG; i++) {
- j = host_to_target_signal_table[i];
- target_to_host_signal_table[j] = i;
- }
+ /* initialize signal conversion tables */
+ signal_table_init();
/* Set the signal mask from the host mask. */
sigprocmask(0, 0, &ts->signal_mask);
- /* set all host signal handlers. ALL signals are blocked during
- the handlers to serialize them. */
- memset(sigact_table, 0, sizeof(sigact_table));
-
sigfillset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = host_signal_handler;
for(i = 1; i <= TARGET_NSIG; i++) {
-#ifdef TARGET_GPROF
- if (i == SIGPROF) {
+#ifdef CONFIG_GPROF
+ if (i == TARGET_SIGPROF) {
continue;
}
#endif
@@ -787,6 +838,8 @@ int do_sigaction(int sig, const struct target_sigaction *act,
int host_sig;
int ret = 0;
+ trace_signal_do_sigaction_guest(sig, TARGET_NSIG);
+
if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) {
return -TARGET_EINVAL;
}
@@ -817,6 +870,23 @@ int do_sigaction(int sig, const struct target_sigaction *act,
/* we update the host linux signal state */
host_sig = target_to_host_signal(sig);
+ trace_signal_do_sigaction_host(host_sig, TARGET_NSIG);
+ if (host_sig > SIGRTMAX) {
+ /* we don't have enough host signals to map all target signals */
+ qemu_log_mask(LOG_UNIMP, "Unsupported target signal #%d, ignored\n",
+ sig);
+ /*
+ * we don't return an error here because some programs try to
+ * register an handler for all possible rt signals even if they
+ * don't need it.
+ * An error here can abort them whereas there can be no problem
+ * to not have the signal available later.
+ * This is the case for golang,
+ * See https://github.com/golang/go/issues/33746
+ * So we silently ignore the error.
+ */
+ return 0;
+ }
if (host_sig != SIGSEGV && host_sig != SIGBUS) {
sigfillset(&act1.sa_mask);
act1.sa_flags = SA_SIGINFO;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d60142f069..c930577686 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2344,6 +2344,28 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
}
break;
}
+ case TARGET_SO_PEERSEC: {
+ char *name;
+
+ if (get_user_u32(len, optlen)) {
+ return -TARGET_EFAULT;
+ }
+ if (len < 0) {
+ return -TARGET_EINVAL;
+ }
+ name = lock_user(VERIFY_WRITE, optval_addr, len, 0);
+ if (!name) {
+ return -TARGET_EFAULT;
+ }
+ lv = len;
+ ret = get_errno(getsockopt(sockfd, level, SO_PEERSEC,
+ name, &lv));
+ if (put_user_u32(lv, optlen)) {
+ ret = -TARGET_EFAULT;
+ }
+ unlock_user(name, optval_addr, lv);
+ break;
+ }
case TARGET_SO_LINGER:
{
struct linger lg;
diff --git a/linux-user/trace-events b/linux-user/trace-events
index f6de1b8bef..0296133dae 100644
--- a/linux-user/trace-events
+++ b/linux-user/trace-events
@@ -1,6 +1,9 @@
# See docs/devel/tracing.txt for syntax documentation.
# signal.c
+signal_table_init(int i) "number of unavailable signals: %d"
+signal_do_sigaction_guest(int sig, int max) "target signal %d (MAX %d)"
+signal_do_sigaction_host(int sig, int max) "host signal %d (MAX %d)"
# */signal.c
user_setup_frame(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64
user_setup_rt_frame(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64
diff --git a/qapi/ui.json b/qapi/ui.json
index e04525d8b4..f8c803fe43 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -1144,6 +1144,8 @@
# @type: Which DisplayType qemu should use.
# @full-screen: Start user interface in fullscreen mode (default: off).
# @window-close: Allow to quit qemu with window close button (default: on).
+# @show-cursor: Force showing the mouse cursor (default: off).
+# (since: 5.0)
# @gl: Enable OpenGL support (default: off).
#
# Since: 2.12
@@ -1153,6 +1155,7 @@
'base' : { 'type' : 'DisplayType',
'*full-screen' : 'bool',
'*window-close' : 'bool',
+ '*show-cursor' : 'bool',
'*gl' : 'DisplayGLMode' },
'discriminator' : 'type',
'data' : { 'gtk' : 'DisplayGTK',
diff --git a/qemu-deprecated.texi b/qemu-deprecated.texi
index 017b750ca8..0671c26c80 100644
--- a/qemu-deprecated.texi
+++ b/qemu-deprecated.texi
@@ -148,6 +148,11 @@ QEMU 5.0 introduced an alternative syntax to specify the size of the translation
block cache, @option{-accel tcg,tb-size=}. The new syntax deprecates the
previously available @option{-tb-size} option.
+@subsection -show-cursor option (since 5.0)
+
+Use @option{-display sdl,show-cursor=on} or
+ @option{-display gtk,show-cursor=on} instead.
+
@section QEMU Machine Protocol (QMP) commands
@subsection change (since 2.5.0)
diff --git a/scripts/minikconf.py b/scripts/minikconf.py
index 2f9647d0fa..90b99517c1 100755
--- a/scripts/minikconf.py
+++ b/scripts/minikconf.py
@@ -645,7 +645,7 @@ class KconfigParser:
self.cursor = self.src.find('\n', self.cursor)
self.val = self.src[start:self.cursor]
return TOK_SOURCE
- elif self.tok.isalpha():
+ elif self.tok.isalnum():
# identifier
while self.src[self.cursor].isalnum() or self.src[self.cursor] == '_':
self.cursor += 1
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
index 18ac562346..d593b60b28 100644
--- a/target/arm/cpu-param.h
+++ b/target/arm/cpu-param.h
@@ -29,6 +29,6 @@
# define TARGET_PAGE_BITS_MIN 10
#endif
-#define NB_MMU_MODES 9
+#define NB_MMU_MODES 12
#endif
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index b0762a76c4..de733aceeb 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2709,6 +2709,10 @@ static void arm_max_initfn(Object *obj)
t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
cpu->isar.mvfr2 = t;
+ t = cpu->id_mmfr3;
+ t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
+ cpu->id_mmfr3 = t;
+
t = cpu->id_mmfr4;
t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
cpu->id_mmfr4 = t;
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 0b3036c484..e943ffe8a9 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -871,6 +871,7 @@ struct ARMCPU {
uint64_t id_aa64pfr1;
uint64_t id_aa64mmfr0;
uint64_t id_aa64mmfr1;
+ uint64_t id_aa64mmfr2;
} isar;
uint32_t midr;
uint32_t revidr;
@@ -1186,12 +1187,7 @@ void pmu_init(ARMCPU *cpu);
#define CPSR_IT_2_7 (0xfc00U)
#define CPSR_GE (0xfU << 16)
#define CPSR_IL (1U << 20)
-/* Note that the RESERVED bits include bit 21, which is PSTATE_SS in
- * an AArch64 SPSR but RES0 in AArch32 SPSR and CPSR. In QEMU we use
- * env->uncached_cpsr bit 21 to store PSTATE.SS when executing in AArch32,
- * where it is live state but not accessible to the AArch32 code.
- */
-#define CPSR_RESERVED (0x7U << 21)
+#define CPSR_PAN (1U << 22)
#define CPSR_J (1U << 24)
#define CPSR_IT_0_1 (3U << 25)
#define CPSR_Q (1U << 27)
@@ -1209,8 +1205,6 @@ void pmu_init(ARMCPU *cpu);
#define CPSR_USER (CPSR_NZCV | CPSR_Q | CPSR_GE)
/* Execution state bits. MRS read as zero, MSR writes ignored. */
#define CPSR_EXEC (CPSR_T | CPSR_IT | CPSR_J | CPSR_IL)
-/* Mask of bits which may be set by exception return copying them from SPSR */
-#define CPSR_ERET_MASK (~CPSR_RESERVED)
/* Bit definitions for M profile XPSR. Most are the same as CPSR. */
#define XPSR_EXCP 0x1ffU
@@ -1258,6 +1252,8 @@ void pmu_init(ARMCPU *cpu);
#define PSTATE_BTYPE (3U << 10)
#define PSTATE_IL (1U << 20)
#define PSTATE_SS (1U << 21)
+#define PSTATE_PAN (1U << 22)
+#define PSTATE_UAO (1U << 23)
#define PSTATE_V (1U << 28)
#define PSTATE_C (1U << 29)
#define PSTATE_Z (1U << 30)
@@ -1727,6 +1723,15 @@ FIELD(ID_ISAR6, FHM, 8, 4)
FIELD(ID_ISAR6, SB, 12, 4)
FIELD(ID_ISAR6, SPECRES, 16, 4)
+FIELD(ID_MMFR3, CMAINTVA, 0, 4)
+FIELD(ID_MMFR3, CMAINTSW, 4, 4)
+FIELD(ID_MMFR3, BPMAINT, 8, 4)
+FIELD(ID_MMFR3, MAINTBCST, 12, 4)
+FIELD(ID_MMFR3, PAN, 16, 4)
+FIELD(ID_MMFR3, COHWALK, 20, 4)
+FIELD(ID_MMFR3, CMEMSZ, 24, 4)
+FIELD(ID_MMFR3, SUPERSEC, 28, 4)
+
FIELD(ID_MMFR4, SPECSEI, 0, 4)
FIELD(ID_MMFR4, AC2, 4, 4)
FIELD(ID_MMFR4, XNX, 8, 4)
@@ -1800,6 +1805,22 @@ FIELD(ID_AA64MMFR1, PAN, 20, 4)
FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
FIELD(ID_AA64MMFR1, XNX, 28, 4)
+FIELD(ID_AA64MMFR2, CNP, 0, 4)
+FIELD(ID_AA64MMFR2, UAO, 4, 4)
+FIELD(ID_AA64MMFR2, LSM, 8, 4)
+FIELD(ID_AA64MMFR2, IESB, 12, 4)
+FIELD(ID_AA64MMFR2, VARANGE, 16, 4)
+FIELD(ID_AA64MMFR2, CCIDX, 20, 4)
+FIELD(ID_AA64MMFR2, NV, 24, 4)
+FIELD(ID_AA64MMFR2, ST, 28, 4)
+FIELD(ID_AA64MMFR2, AT, 32, 4)
+FIELD(ID_AA64MMFR2, IDS, 36, 4)
+FIELD(ID_AA64MMFR2, FWB, 40, 4)
+FIELD(ID_AA64MMFR2, TTL, 48, 4)
+FIELD(ID_AA64MMFR2, BBM, 52, 4)
+FIELD(ID_AA64MMFR2, EVT, 56, 4)
+FIELD(ID_AA64MMFR2, E0PD, 60, 4)
+
FIELD(ID_DFR0, COPDBG, 0, 4)
FIELD(ID_DFR0, COPSDBG, 4, 4)
FIELD(ID_DFR0, MMAPDBG, 8, 4)
@@ -2751,20 +2772,24 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
* 5. we want to be able to use the TLB for accesses done as part of a
* stage1 page table walk, rather than having to walk the stage2 page
* table over and over.
+ * 6. we need separate EL1/EL2 mmu_idx for handling the Privileged Access
+ * Never (PAN) bit within PSTATE.
*
* This gives us the following list of cases:
*
* NS EL0 EL1&0 stage 1+2 (aka NS PL0)
* NS EL1 EL1&0 stage 1+2 (aka NS PL1)
+ * NS EL1 EL1&0 stage 1+2 +PAN
* NS EL0 EL2&0
- * NS EL2 EL2&0
+ * NS EL2 EL2&0 +PAN
* NS EL2 (aka NS PL2)
* S EL0 EL1&0 (aka S PL0)
* S EL1 EL1&0 (not used if EL3 is 32 bit)
+ * S EL1 EL1&0 +PAN
* S EL3 (aka S PL1)
* NS EL1&0 stage 2
*
- * for a total of 9 different mmu_idx.
+ * for a total of 12 different mmu_idx.
*
* R profile CPUs have an MPU, but can use the same set of MMU indexes
* as A profile. They only need to distinguish NS EL0 and NS EL1 (and
@@ -2819,19 +2844,22 @@ typedef enum ARMMMUIdx {
/*
* A-profile.
*/
- ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
- ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A,
- ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E10_1_PAN = 3 | ARM_MMU_IDX_A,
- ARMMMUIdx_E2 = 3 | ARM_MMU_IDX_A,
- ARMMMUIdx_E20_2 = 4 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E2 = 4 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E20_2 = 5 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E20_2_PAN = 6 | ARM_MMU_IDX_A,
- ARMMMUIdx_SE10_0 = 5 | ARM_MMU_IDX_A,
- ARMMMUIdx_SE10_1 = 6 | ARM_MMU_IDX_A,
- ARMMMUIdx_SE3 = 7 | ARM_MMU_IDX_A,
+ ARMMMUIdx_SE10_0 = 7 | ARM_MMU_IDX_A,
+ ARMMMUIdx_SE10_1 = 8 | ARM_MMU_IDX_A,
+ ARMMMUIdx_SE10_1_PAN = 9 | ARM_MMU_IDX_A,
+ ARMMMUIdx_SE3 = 10 | ARM_MMU_IDX_A,
- ARMMMUIdx_Stage2 = 8 | ARM_MMU_IDX_A,
+ ARMMMUIdx_Stage2 = 11 | ARM_MMU_IDX_A,
/*
* These are not allocated TLBs and are used only for AT system
@@ -2839,6 +2867,7 @@ typedef enum ARMMMUIdx {
*/
ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
+ ARMMMUIdx_Stage1_E1_PAN = 2 | ARM_MMU_IDX_NOTLB,
/*
* M-profile.
@@ -2864,10 +2893,13 @@ typedef enum ARMMMUIdxBit {
TO_CORE_BIT(E10_0),
TO_CORE_BIT(E20_0),
TO_CORE_BIT(E10_1),
+ TO_CORE_BIT(E10_1_PAN),
TO_CORE_BIT(E2),
TO_CORE_BIT(E20_2),
+ TO_CORE_BIT(E20_2_PAN),
TO_CORE_BIT(SE10_0),
TO_CORE_BIT(SE10_1),
+ TO_CORE_BIT(SE10_1_PAN),
TO_CORE_BIT(SE3),
TO_CORE_BIT(Stage2),
@@ -3432,6 +3464,16 @@ static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 4;
}
+static inline bool isar_feature_aa32_pan(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) != 0;
+}
+
+static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) >= 2;
+}
+
/*
* 64-bit feature tests via id registers.
*/
@@ -3591,6 +3633,21 @@ static inline bool isar_feature_aa64_lor(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0;
}
+static inline bool isar_feature_aa64_pan(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) != 0;
+}
+
+static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2;
+}
+
+static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
+}
+
static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index c80fb5fd43..f0d98bc79d 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -673,8 +673,14 @@ static void aarch64_max_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */
t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1);
t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1);
+ t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */
+ t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* VMID16 */
cpu->isar.id_aa64mmfr1 = t;
+ t = cpu->isar.id_aa64mmfr2;
+ t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
+ cpu->isar.id_aa64mmfr2 = t;
+
/* Replicate the same data to the 32-bit id registers. */
u = cpu->isar.id_isar5;
u = FIELD_DP32(u, ID_ISAR5, AES, 2); /* AES + PMULL */
@@ -693,6 +699,10 @@ static void aarch64_max_initfn(Object *obj)
u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1);
cpu->isar.id_isar6 = u;
+ u = cpu->id_mmfr3;
+ u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
+ cpu->id_mmfr3 = u;
+
/*
* FIXME: We do not yet support ARMv8.2-fp16 for AArch32 yet,
* so do not set MVFR1.FPHP. Strictly speaking this is not legal,
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index bf45f8a785..509ae93069 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -959,7 +959,7 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
{
int cur_el = arm_current_el(env);
unsigned int spsr_idx = aarch64_banked_spsr_index(cur_el);
- uint32_t spsr = env->banked_spsr[spsr_idx];
+ uint32_t mask, spsr = env->banked_spsr[spsr_idx];
int new_el;
bool return_to_aa64 = (spsr & PSTATE_nRW) == 0;
@@ -1014,7 +1014,8 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
* will sort the register banks out for us, and we've already
* caught all the bad-mode cases in el_from_spsr().
*/
- cpsr_write(env, spsr, ~0, CPSRWriteRaw);
+ mask = aarch32_cpsr_valid_mask(env->features, &env_archcpu(env)->isar);
+ cpsr_write(env, spsr, mask, CPSRWriteRaw);
if (!arm_singlestep_active(env)) {
env->uncached_cpsr &= ~PSTATE_SS;
}
@@ -1031,6 +1032,7 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
cur_el, new_el, env->regs[15]);
} else {
env->aarch64 = 1;
+ spsr &= aarch64_pstate_valid_mask(&env_archcpu(env)->isar);
pstate_write(env, spsr);
if (!arm_singlestep_active(env)) {
env->pstate &= ~PSTATE_SS;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 7d15d5c933..366dbcf460 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -671,6 +671,7 @@ static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
tlb_flush_by_mmuidx(cs,
ARMMMUIdxBit_E10_1 |
+ ARMMMUIdxBit_E10_1_PAN |
ARMMMUIdxBit_E10_0 |
ARMMMUIdxBit_Stage2);
}
@@ -682,6 +683,7 @@ static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
tlb_flush_by_mmuidx_all_cpus_synced(cs,
ARMMMUIdxBit_E10_1 |
+ ARMMMUIdxBit_E10_1_PAN |
ARMMMUIdxBit_E10_0 |
ARMMMUIdxBit_Stage2);
}
@@ -2700,6 +2702,7 @@ static int gt_phys_redir_timeridx(CPUARMState *env)
switch (arm_mmu_idx(env)) {
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
return GTIMER_HYP;
default:
return GTIMER_PHYS;
@@ -2711,6 +2714,7 @@ static int gt_virt_redir_timeridx(CPUARMState *env)
switch (arm_mmu_idx(env)) {
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
return GTIMER_HYPVIRT;
default:
return GTIMER_VIRT;
@@ -3261,8 +3265,7 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
bool take_exc = false;
if (fi.s1ptw && current_el == 1 && !arm_is_secure(env)
- && (mmu_idx == ARMMMUIdx_Stage1_E1 ||
- mmu_idx == ARMMMUIdx_Stage1_E0)) {
+ && arm_mmu_idx_is_stage1_of_2(mmu_idx)) {
/*
* Synchronous stage 2 fault on an access made as part of the
* translation table walk for AT S1E0* or AT S1E1* insn
@@ -3338,7 +3341,9 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
format64 = arm_s1_regime_using_lpae_format(env, mmu_idx);
if (arm_feature(env, ARM_FEATURE_EL2)) {
- if (mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
+ if (mmu_idx == ARMMMUIdx_E10_0 ||
+ mmu_idx == ARMMMUIdx_E10_1 ||
+ mmu_idx == ARMMMUIdx_E10_1_PAN) {
format64 |= env->cp15.hcr_el2 & (HCR_VM | HCR_DC);
} else {
format64 |= arm_current_el(env) == 2;
@@ -3404,16 +3409,21 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
switch (ri->opc2 & 6) {
case 0:
- /* stage 1 current state PL1: ATS1CPR, ATS1CPW */
+ /* stage 1 current state PL1: ATS1CPR, ATS1CPW, ATS1CPRP, ATS1CPWP */
switch (el) {
case 3:
mmu_idx = ARMMMUIdx_SE3;
break;
case 2:
- mmu_idx = ARMMMUIdx_Stage1_E1;
- break;
+ g_assert(!secure); /* TODO: ARMv8.4-SecEL2 */
+ /* fall through */
case 1:
- mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E1;
+ if (ri->crm == 9 && (env->uncached_cpsr & CPSR_PAN)) {
+ mmu_idx = (secure ? ARMMMUIdx_SE10_1_PAN
+ : ARMMMUIdx_Stage1_E1_PAN);
+ } else {
+ mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E1;
+ }
break;
default:
g_assert_not_reached();
@@ -3482,8 +3492,13 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
switch (ri->opc2 & 6) {
case 0:
switch (ri->opc1) {
- case 0: /* AT S1E1R, AT S1E1W */
- mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E1;
+ case 0: /* AT S1E1R, AT S1E1W, AT S1E1RP, AT S1E1WP */
+ if (ri->crm == 9 && (env->pstate & PSTATE_PAN)) {
+ mmu_idx = (secure ? ARMMMUIdx_SE10_1_PAN
+ : ARMMMUIdx_Stage1_E1_PAN);
+ } else {
+ mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E1;
+ }
break;
case 4: /* AT S1E2R, AT S1E2W */
mmu_idx = ARMMMUIdx_E2;
@@ -3798,7 +3813,9 @@ static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
if (extract64(raw_read(env, ri) ^ value, 48, 16) &&
(arm_hcr_el2_eff(env) & HCR_E2H)) {
tlb_flush_by_mmuidx(env_cpu(env),
- ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E20_0);
+ ARMMMUIdxBit_E20_2 |
+ ARMMMUIdxBit_E20_2_PAN |
+ ARMMMUIdxBit_E20_0);
}
raw_write(env, ri, value);
}
@@ -3816,6 +3833,7 @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
if (raw_read(env, ri) != value) {
tlb_flush_by_mmuidx(cs,
ARMMMUIdxBit_E10_1 |
+ ARMMMUIdxBit_E10_1_PAN |
ARMMMUIdxBit_E10_0 |
ARMMMUIdxBit_Stage2);
raw_write(env, ri, value);
@@ -4155,6 +4173,42 @@ static void aa64_daif_write(CPUARMState *env, const ARMCPRegInfo *ri,
env->daif = value & PSTATE_DAIF;
}
+static uint64_t aa64_pan_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ return env->pstate & PSTATE_PAN;
+}
+
+static void aa64_pan_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ env->pstate = (env->pstate & ~PSTATE_PAN) | (value & PSTATE_PAN);
+}
+
+static const ARMCPRegInfo pan_reginfo = {
+ .name = "PAN", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 3,
+ .type = ARM_CP_NO_RAW, .access = PL1_RW,
+ .readfn = aa64_pan_read, .writefn = aa64_pan_write
+};
+
+static uint64_t aa64_uao_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ return env->pstate & PSTATE_UAO;
+}
+
+static void aa64_uao_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ env->pstate = (env->pstate & ~PSTATE_UAO) | (value & PSTATE_UAO);
+}
+
+static const ARMCPRegInfo uao_reginfo = {
+ .name = "UAO", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 4,
+ .type = ARM_CP_NO_RAW, .access = PL1_RW,
+ .readfn = aa64_uao_read, .writefn = aa64_uao_write
+};
+
static CPAccessResult aa64_cacheop_access(CPUARMState *env,
const ARMCPRegInfo *ri,
bool isread)
@@ -4176,12 +4230,18 @@ static int vae1_tlbmask(CPUARMState *env)
{
/* Since we exclude secure first, we may read HCR_EL2 directly. */
if (arm_is_secure_below_el3(env)) {
- return ARMMMUIdxBit_SE10_1 | ARMMMUIdxBit_SE10_0;
+ return ARMMMUIdxBit_SE10_1 |
+ ARMMMUIdxBit_SE10_1_PAN |
+ ARMMMUIdxBit_SE10_0;
} else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
== (HCR_E2H | HCR_TGE)) {
- return ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E20_0;
+ return ARMMMUIdxBit_E20_2 |
+ ARMMMUIdxBit_E20_2_PAN |
+ ARMMMUIdxBit_E20_0;
} else {
- return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
+ return ARMMMUIdxBit_E10_1 |
+ ARMMMUIdxBit_E10_1_PAN |
+ ARMMMUIdxBit_E10_0;
}
}
@@ -4215,18 +4275,28 @@ static int alle1_tlbmask(CPUARMState *env)
* stage 1 translations.
*/
if (arm_is_secure_below_el3(env)) {
- return ARMMMUIdxBit_SE10_1 | ARMMMUIdxBit_SE10_0;
+ return ARMMMUIdxBit_SE10_1 |
+ ARMMMUIdxBit_SE10_1_PAN |
+ ARMMMUIdxBit_SE10_0;
} else if (arm_feature(env, ARM_FEATURE_EL2)) {
- return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0 | ARMMMUIdxBit_Stage2;
+ return ARMMMUIdxBit_E10_1 |
+ ARMMMUIdxBit_E10_1_PAN |
+ ARMMMUIdxBit_E10_0 |
+ ARMMMUIdxBit_Stage2;
} else {
- return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
+ return ARMMMUIdxBit_E10_1 |
+ ARMMMUIdxBit_E10_1_PAN |
+ ARMMMUIdxBit_E10_0;
}
}
static int e2_tlbmask(CPUARMState *env)
{
/* TODO: ARMv8.4-SecEL2 */
- return ARMMMUIdxBit_E20_0 | ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E2;
+ return ARMMMUIdxBit_E20_0 |
+ ARMMMUIdxBit_E20_2 |
+ ARMMMUIdxBit_E20_2_PAN |
+ ARMMMUIdxBit_E2;
}
static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -6310,6 +6380,35 @@ static CPAccessResult access_lor_other(CPUARMState *env,
return access_lor_ns(env);
}
+/*
+ * A trivial implementation of ARMv8.1-LOR leaves all of these
+ * registers fixed at 0, which indicates that there are zero
+ * supported Limited Ordering regions.
+ */
+static const ARMCPRegInfo lor_reginfo[] = {
+ { .name = "LORSA_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 0,
+ .access = PL1_RW, .accessfn = access_lor_other,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "LOREA_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 1,
+ .access = PL1_RW, .accessfn = access_lor_other,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "LORN_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 2,
+ .access = PL1_RW, .accessfn = access_lor_other,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "LORC_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 3,
+ .access = PL1_RW, .accessfn = access_lor_other,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "LORID_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
+ .access = PL1_R, .accessfn = access_lorid,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ REGINFO_SENTINEL
+};
+
#ifdef TARGET_AARCH64
static CPAccessResult access_pauth(CPUARMState *env, const ARMCPRegInfo *ri,
bool isread)
@@ -6612,6 +6711,32 @@ static const ARMCPRegInfo vhe_reginfo[] = {
REGINFO_SENTINEL
};
+#ifndef CONFIG_USER_ONLY
+static const ARMCPRegInfo ats1e1_reginfo[] = {
+ { .name = "AT_S1E1R", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 0,
+ .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
+ .writefn = ats_write64 },
+ { .name = "AT_S1E1W", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
+ .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
+ .writefn = ats_write64 },
+ REGINFO_SENTINEL
+};
+
+static const ARMCPRegInfo ats1cp_reginfo[] = {
+ { .name = "ATS1CPRP",
+ .cp = 15, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 0,
+ .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
+ .writefn = ats_write },
+ { .name = "ATS1CPWP",
+ .cp = 15, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
+ .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
+ .writefn = ats_write },
+ REGINFO_SENTINEL
+};
+#endif
+
void register_cp_regs_for_features(ARMCPU *cpu)
{
/* Register all the coprocessor registers based on feature bits */
@@ -6966,11 +7091,11 @@ void register_cp_regs_for_features(ARMCPU *cpu)
.access = PL1_R, .type = ARM_CP_CONST,
.accessfn = access_aa64_tid3,
.resetvalue = cpu->isar.id_aa64mmfr1 },
- { .name = "ID_AA64MMFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
+ { .name = "ID_AA64MMFR2_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 2,
.access = PL1_R, .type = ARM_CP_CONST,
.accessfn = access_aa64_tid3,
- .resetvalue = 0 },
+ .resetvalue = cpu->isar.id_aa64mmfr2 },
{ .name = "ID_AA64MMFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 3,
.access = PL1_R, .type = ARM_CP_CONST,
@@ -7544,36 +7669,22 @@ void register_cp_regs_for_features(ARMCPU *cpu)
}
if (cpu_isar_feature(aa64_lor, cpu)) {
- /*
- * A trivial implementation of ARMv8.1-LOR leaves all of these
- * registers fixed at 0, which indicates that there are zero
- * supported Limited Ordering regions.
- */
- static const ARMCPRegInfo lor_reginfo[] = {
- { .name = "LORSA_EL1", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 0,
- .access = PL1_RW, .accessfn = access_lor_other,
- .type = ARM_CP_CONST, .resetvalue = 0 },
- { .name = "LOREA_EL1", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 1,
- .access = PL1_RW, .accessfn = access_lor_other,
- .type = ARM_CP_CONST, .resetvalue = 0 },
- { .name = "LORN_EL1", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 2,
- .access = PL1_RW, .accessfn = access_lor_other,
- .type = ARM_CP_CONST, .resetvalue = 0 },
- { .name = "LORC_EL1", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 3,
- .access = PL1_RW, .accessfn = access_lor_other,
- .type = ARM_CP_CONST, .resetvalue = 0 },
- { .name = "LORID_EL1", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
- .access = PL1_R, .accessfn = access_lorid,
- .type = ARM_CP_CONST, .resetvalue = 0 },
- REGINFO_SENTINEL
- };
define_arm_cp_regs(cpu, lor_reginfo);
}
+ if (cpu_isar_feature(aa64_pan, cpu)) {
+ define_one_arm_cp_reg(cpu, &pan_reginfo);
+ }
+#ifndef CONFIG_USER_ONLY
+ if (cpu_isar_feature(aa64_ats1e1, cpu)) {
+ define_arm_cp_regs(cpu, ats1e1_reginfo);
+ }
+ if (cpu_isar_feature(aa32_ats1e1, cpu)) {
+ define_arm_cp_regs(cpu, ats1cp_reginfo);
+ }
+#endif
+ if (cpu_isar_feature(aa64_uao, cpu)) {
+ define_one_arm_cp_reg(cpu, &uao_reginfo);
+ }
if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
define_arm_cp_regs(cpu, vhe_reginfo);
@@ -8717,8 +8828,12 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
uint32_t mask, uint32_t offset,
uint32_t newpc)
{
+ int new_el;
+
/* Change the CPU state so as to actually take the exception. */
switch_mode(env, new_mode);
+ new_el = arm_current_el(env);
+
/*
* For exceptions taken to AArch32 we must clear the SS bit in both
* PSTATE and in the old-state value we save to SPSR_<mode>, so zero it now.
@@ -8731,7 +8846,7 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
/* Set new mode endianness */
env->uncached_cpsr &= ~CPSR_E;
- if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
+ if (env->cp15.sctlr_el[new_el] & SCTLR_EE) {
env->uncached_cpsr |= CPSR_E;
}
/* J and IL must always be cleared for exception entry */
@@ -8742,6 +8857,25 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
env->thumb = (env->cp15.sctlr_el[2] & SCTLR_TE) != 0;
env->elr_el[2] = env->regs[15];
} else {
+ /* CPSR.PAN is normally preserved preserved unless... */
+ if (cpu_isar_feature(aa64_pan, env_archcpu(env))) {
+ switch (new_el) {
+ case 3:
+ if (!arm_is_secure_below_el3(env)) {
+ /* ... the target is EL3, from non-secure state. */
+ env->uncached_cpsr &= ~CPSR_PAN;
+ break;
+ }
+ /* ... the target is EL3, from secure state ... */
+ /* fall through */
+ case 1:
+ /* ... the target is EL1 and SCTLR.SPAN is 0. */
+ if (!(env->cp15.sctlr_el[new_el] & SCTLR_SPAN)) {
+ env->uncached_cpsr |= CPSR_PAN;
+ }
+ break;
+ }
+ }
/*
* this is a lie, as there was no c1_sys on V4T/V5, but who cares
* and we should just guard the thumb mode on V4
@@ -9004,6 +9138,7 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
unsigned int new_el = env->exception.target_el;
target_ulong addr = env->cp15.vbar_el[new_el];
unsigned int new_mode = aarch64_pstate_mode(new_el, true);
+ unsigned int old_mode;
unsigned int cur_el = arm_current_el(env);
/*
@@ -9083,20 +9218,43 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
}
if (is_a64(env)) {
- env->banked_spsr[aarch64_banked_spsr_index(new_el)] = pstate_read(env);
+ old_mode = pstate_read(env);
aarch64_save_sp(env, arm_current_el(env));
env->elr_el[new_el] = env->pc;
} else {
- env->banked_spsr[aarch64_banked_spsr_index(new_el)] = cpsr_read(env);
+ old_mode = cpsr_read(env);
env->elr_el[new_el] = env->regs[15];
aarch64_sync_32_to_64(env);
env->condexec_bits = 0;
}
+ env->banked_spsr[aarch64_banked_spsr_index(new_el)] = old_mode;
+
qemu_log_mask(CPU_LOG_INT, "...with ELR 0x%" PRIx64 "\n",
env->elr_el[new_el]);
+ if (cpu_isar_feature(aa64_pan, cpu)) {
+ /* The value of PSTATE.PAN is normally preserved, except when ... */
+ new_mode |= old_mode & PSTATE_PAN;
+ switch (new_el) {
+ case 2:
+ /* ... the target is EL2 with HCR_EL2.{E2H,TGE} == '11' ... */
+ if ((arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE))
+ != (HCR_E2H | HCR_TGE)) {
+ break;
+ }
+ /* fall through */
+ case 1:
+ /* ... the target is EL1 ... */
+ /* ... and SCTLR_ELx.SPAN == 0, then set to 1. */
+ if ((env->cp15.sctlr_el[new_el] & SCTLR_SPAN) == 0) {
+ new_mode |= PSTATE_PAN;
+ }
+ break;
+ }
+ }
+
pstate_write(env, PSTATE_DAIF | new_mode);
env->aarch64 = 1;
aarch64_restore_sp(env, new_el);
@@ -9207,6 +9365,7 @@ static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
switch (mmu_idx) {
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
case ARMMMUIdx_Stage2:
case ARMMMUIdx_E2:
return 2;
@@ -9215,10 +9374,13 @@ static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
case ARMMMUIdx_SE10_0:
return arm_el_is_aa64(env, 3) ? 1 : 3;
case ARMMMUIdx_SE10_1:
+ case ARMMMUIdx_SE10_1_PAN:
case ARMMMUIdx_Stage1_E0:
case ARMMMUIdx_Stage1_E1:
+ case ARMMMUIdx_Stage1_E1_PAN:
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
case ARMMMUIdx_MPrivNegPri:
case ARMMMUIdx_MUserNegPri:
case ARMMMUIdx_MPriv:
@@ -9285,8 +9447,7 @@ static inline bool regime_translation_disabled(CPUARMState *env,
}
}
- if ((env->cp15.hcr_el2 & HCR_DC) &&
- (mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1)) {
+ if ((env->cp15.hcr_el2 & HCR_DC) && arm_mmu_idx_is_stage1_of_2(mmu_idx)) {
/* HCR.DC means SCTLR_EL1.M behaves as 0 */
return true;
}
@@ -9335,6 +9496,8 @@ static inline ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx)
return ARMMMUIdx_Stage1_E0;
case ARMMMUIdx_E10_1:
return ARMMMUIdx_Stage1_E1;
+ case ARMMMUIdx_E10_1_PAN:
+ return ARMMMUIdx_Stage1_E1_PAN;
default:
return mmu_idx;
}
@@ -9381,6 +9544,7 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
return false;
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
g_assert_not_reached();
}
}
@@ -9517,6 +9681,9 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
if (is_user) {
prot_rw = user_rw;
} else {
+ if (user_rw && regime_is_pan(env, mmu_idx)) {
+ return 0;
+ }
prot_rw = simple_ap_to_rw_prot_is_user(ap, false);
}
@@ -9595,7 +9762,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
hwaddr addr, MemTxAttrs txattrs,
ARMMMUFaultInfo *fi)
{
- if ((mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1) &&
+ if (arm_mmu_idx_is_stage1_of_2(mmu_idx) &&
!regime_translation_disabled(env, ARMMMUIdx_Stage2)) {
target_ulong s2size;
hwaddr s2pa;
@@ -11273,7 +11440,9 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
target_ulong *page_size,
ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs)
{
- if (mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
+ if (mmu_idx == ARMMMUIdx_E10_0 ||
+ mmu_idx == ARMMMUIdx_E10_1 ||
+ mmu_idx == ARMMMUIdx_E10_1_PAN) {
/* Call ourselves recursively to do the stage 1 and then stage 2
* translations.
*/
@@ -11800,10 +11969,13 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
case ARMMMUIdx_SE10_0:
return 0;
case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
case ARMMMUIdx_SE10_1:
+ case ARMMMUIdx_SE10_1_PAN:
return 1;
case ARMMMUIdx_E2:
case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
return 2;
case ARMMMUIdx_SE3:
return 3;
@@ -11838,13 +12010,22 @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
return ARMMMUIdx_E10_0;
case 1:
if (arm_is_secure_below_el3(env)) {
+ if (env->pstate & PSTATE_PAN) {
+ return ARMMMUIdx_SE10_1_PAN;
+ }
return ARMMMUIdx_SE10_1;
}
+ if (env->pstate & PSTATE_PAN) {
+ return ARMMMUIdx_E10_1_PAN;
+ }
return ARMMMUIdx_E10_1;
case 2:
/* TODO: ARMv8.4-SecEL2 */
/* Note that TGE does not apply at EL2. */
if ((env->cp15.hcr_el2 & HCR_E2H) && arm_el_is_aa64(env, 2)) {
+ if (env->pstate & PSTATE_PAN) {
+ return ARMMMUIdx_E20_2_PAN;
+ }
return ARMMMUIdx_E20_2;
}
return ARMMMUIdx_E2;
@@ -12017,25 +12198,29 @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
}
/* Compute the condition for using AccType_UNPRIV for LDTR et al. */
- /* TODO: ARMv8.2-UAO */
- switch (mmu_idx) {
- case ARMMMUIdx_E10_1:
- case ARMMMUIdx_SE10_1:
- /* TODO: ARMv8.3-NV */
- flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
- break;
- case ARMMMUIdx_E20_2:
- /* TODO: ARMv8.4-SecEL2 */
- /*
- * Note that E20_2 is gated by HCR_EL2.E2H == 1, but E20_0 is
- * gated by HCR_EL2.<E2H,TGE> == '11', and so is LDTR.
- */
- if (env->cp15.hcr_el2 & HCR_TGE) {
+ if (!(env->pstate & PSTATE_UAO)) {
+ switch (mmu_idx) {
+ case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
+ case ARMMMUIdx_SE10_1:
+ case ARMMMUIdx_SE10_1_PAN:
+ /* TODO: ARMv8.3-NV */
flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
+ break;
+ case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
+ /* TODO: ARMv8.4-SecEL2 */
+ /*
+ * Note that EL20_2 is gated by HCR_EL2.E2H == 1, but EL20_0 is
+ * gated by HCR_EL2.<E2H,TGE> == '11', and so is LDTR.
+ */
+ if (env->cp15.hcr_el2 & HCR_TGE) {
+ flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
+ }
+ break;
+ default:
+ break;
}
- break;
- default:
- break;
}
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 6d4a942bde..58c4d707c5 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -843,12 +843,16 @@ static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
switch (mmu_idx) {
case ARMMMUIdx_Stage1_E0:
case ARMMMUIdx_Stage1_E1:
+ case ARMMMUIdx_Stage1_E1_PAN:
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
case ARMMMUIdx_SE10_0:
case ARMMMUIdx_SE10_1:
+ case ARMMMUIdx_SE10_1_PAN:
return true;
default:
return false;
@@ -861,10 +865,13 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
switch (mmu_idx) {
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
case ARMMMUIdx_Stage1_E0:
case ARMMMUIdx_Stage1_E1:
+ case ARMMMUIdx_Stage1_E1_PAN:
case ARMMMUIdx_E2:
case ARMMMUIdx_Stage2:
case ARMMMUIdx_MPrivNegPri:
@@ -875,6 +882,7 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
case ARMMMUIdx_SE3:
case ARMMMUIdx_SE10_0:
case ARMMMUIdx_SE10_1:
+ case ARMMMUIdx_SE10_1_PAN:
case ARMMMUIdx_MSPrivNegPri:
case ARMMMUIdx_MSUserNegPri:
case ARMMMUIdx_MSPriv:
@@ -885,6 +893,19 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
}
}
+static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
+{
+ switch (mmu_idx) {
+ case ARMMMUIdx_Stage1_E1_PAN:
+ case ARMMMUIdx_E10_1_PAN:
+ case ARMMMUIdx_E20_2_PAN:
+ case ARMMMUIdx_SE10_1_PAN:
+ return true;
+ default:
+ return false;
+ }
+}
+
/* Return the FSR value for a debug exception (watchpoint, hardware
* breakpoint or BKPT insn) targeting the specified exception level.
*/
@@ -1034,6 +1055,70 @@ static inline ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env)
ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env);
#endif
+/**
+ * arm_mmu_idx_is_stage1_of_2:
+ * @mmu_idx: The ARMMMUIdx to test
+ *
+ * Return true if @mmu_idx is a NOTLB mmu_idx that is the
+ * first stage of a two stage regime.
+ */
+static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx mmu_idx)
+{
+ switch (mmu_idx) {
+ case ARMMMUIdx_Stage1_E0:
+ case ARMMMUIdx_Stage1_E1:
+ case ARMMMUIdx_Stage1_E1_PAN:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline uint32_t aarch32_cpsr_valid_mask(uint64_t features,
+ const ARMISARegisters *id)
+{
+ uint32_t valid = CPSR_M | CPSR_AIF | CPSR_IL | CPSR_NZCV;
+
+ if ((features >> ARM_FEATURE_V4T) & 1) {
+ valid |= CPSR_T;
+ }
+ if ((features >> ARM_FEATURE_V5) & 1) {
+ valid |= CPSR_Q; /* V5TE in reality*/
+ }
+ if ((features >> ARM_FEATURE_V6) & 1) {
+ valid |= CPSR_E | CPSR_GE;
+ }
+ if ((features >> ARM_FEATURE_THUMB2) & 1) {
+ valid |= CPSR_IT;
+ }
+ if (isar_feature_jazelle(id)) {
+ valid |= CPSR_J;
+ }
+ if (isar_feature_aa32_pan(id)) {
+ valid |= CPSR_PAN;
+ }
+
+ return valid;
+}
+
+static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id)
+{
+ uint32_t valid;
+
+ valid = PSTATE_M | PSTATE_DAIF | PSTATE_IL | PSTATE_SS | PSTATE_NZCV;
+ if (isar_feature_aa64_bti(id)) {
+ valid |= PSTATE_BTYPE;
+ }
+ if (isar_feature_aa64_pan(id)) {
+ valid |= PSTATE_PAN;
+ }
+ if (isar_feature_aa64_uao(id)) {
+ valid |= PSTATE_UAO;
+ }
+
+ return valid;
+}
+
/*
* Parameters of a given virtual address, as extracted from the
* translation control register (TCR) for a given regime.
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index fb21ab9e73..3bae9e4a66 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -549,6 +549,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
ARM64_SYS_REG(3, 0, 0, 7, 0));
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1,
ARM64_SYS_REG(3, 0, 0, 7, 1));
+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2,
+ ARM64_SYS_REG(3, 0, 0, 7, 2));
/*
* Note that if AArch32 support is not present in the host,
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 27d16ad9ad..af3020b78f 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -387,7 +387,14 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
uint32_t HELPER(cpsr_read)(CPUARMState *env)
{
- return cpsr_read(env) & ~(CPSR_EXEC | CPSR_RESERVED);
+ /*
+ * We store the ARMv8 PSTATE.SS bit in env->uncached_cpsr.
+ * This is convenient for populating SPSR_ELx, but must be
+ * hidden from aarch32 mode, where it is not visible.
+ *
+ * TODO: ARMv8.4-DIT -- need to move SS somewhere else.
+ */
+ return cpsr_read(env) & ~(CPSR_EXEC | PSTATE_SS);
}
void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask)
@@ -400,11 +407,14 @@ void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask)
/* Write the CPSR for a 32-bit exception return */
void HELPER(cpsr_write_eret)(CPUARMState *env, uint32_t val)
{
+ uint32_t mask;
+
qemu_mutex_lock_iothread();
arm_call_pre_el_change_hook(env_archcpu(env));
qemu_mutex_unlock_iothread();
- cpsr_write(env, val, CPSR_ERET_MASK, CPSRWriteExceptionReturn);
+ mask = aarch32_cpsr_valid_mask(env->features, &env_archcpu(env)->isar);
+ cpsr_write(env, val, mask, CPSRWriteExceptionReturn);
/* Generated code has already stored the new PC value, but
* without masking out its low bits, because which bits need
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 6e82486884..7c26c3bfeb 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -124,12 +124,15 @@ static int get_a64_user_mem_index(DisasContext *s)
*/
switch (useridx) {
case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
useridx = ARMMMUIdx_E10_0;
break;
case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
useridx = ARMMMUIdx_E20_0;
break;
case ARMMMUIdx_SE10_1:
+ case ARMMMUIdx_SE10_1_PAN:
useridx = ARMMMUIdx_SE10_0;
break;
default:
@@ -1599,6 +1602,34 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
s->base.is_jmp = DISAS_NEXT;
break;
+ case 0x03: /* UAO */
+ if (!dc_isar_feature(aa64_uao, s) || s->current_el == 0) {
+ goto do_unallocated;
+ }
+ if (crm & 1) {
+ set_pstate_bits(PSTATE_UAO);
+ } else {
+ clear_pstate_bits(PSTATE_UAO);
+ }
+ t1 = tcg_const_i32(s->current_el);
+ gen_helper_rebuild_hflags_a64(cpu_env, t1);
+ tcg_temp_free_i32(t1);
+ break;
+
+ case 0x04: /* PAN */
+ if (!dc_isar_feature(aa64_pan, s) || s->current_el == 0) {
+ goto do_unallocated;
+ }
+ if (crm & 1) {
+ set_pstate_bits(PSTATE_PAN);
+ } else {
+ clear_pstate_bits(PSTATE_PAN);
+ }
+ t1 = tcg_const_i32(s->current_el);
+ gen_helper_rebuild_hflags_a64(cpu_env, t1);
+ tcg_temp_free_i32(t1);
+ break;
+
case 0x05: /* SPSel */
if (s->current_el == 0) {
goto do_unallocated;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index e11a5871d0..20f89ace2f 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -155,10 +155,12 @@ static inline int get_a32_user_mem_index(DisasContext *s)
case ARMMMUIdx_E2: /* this one is UNPREDICTABLE */
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
case ARMMMUIdx_SE3:
case ARMMMUIdx_SE10_0:
case ARMMMUIdx_SE10_1:
+ case ARMMMUIdx_SE10_1_PAN:
return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0);
case ARMMMUIdx_MUser:
case ARMMMUIdx_MPriv:
@@ -2732,39 +2734,33 @@ static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
/* Return the mask of PSR bits set by a MSR instruction. */
static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
{
- uint32_t mask;
+ uint32_t mask = 0;
- mask = 0;
- if (flags & (1 << 0))
+ if (flags & (1 << 0)) {
mask |= 0xff;
- if (flags & (1 << 1))
- mask |= 0xff00;
- if (flags & (1 << 2))
- mask |= 0xff0000;
- if (flags & (1 << 3))
- mask |= 0xff000000;
-
- /* Mask out undefined bits. */
- mask &= ~CPSR_RESERVED;
- if (!arm_dc_feature(s, ARM_FEATURE_V4T)) {
- mask &= ~CPSR_T;
}
- if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
- mask &= ~CPSR_Q; /* V5TE in reality*/
+ if (flags & (1 << 1)) {
+ mask |= 0xff00;
}
- if (!arm_dc_feature(s, ARM_FEATURE_V6)) {
- mask &= ~(CPSR_E | CPSR_GE);
+ if (flags & (1 << 2)) {
+ mask |= 0xff0000;
}
- if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
- mask &= ~CPSR_IT;
+ if (flags & (1 << 3)) {
+ mask |= 0xff000000;
}
- /* Mask out execution state and reserved bits. */
+
+ /* Mask out undefined and reserved bits. */
+ mask &= aarch32_cpsr_valid_mask(s->features, s->isar);
+
+ /* Mask out execution state. */
if (!spsr) {
- mask &= ~(CPSR_EXEC | CPSR_RESERVED);
+ mask &= ~CPSR_EXEC;
}
+
/* Mask out privileged bits. */
- if (IS_USER(s))
+ if (IS_USER(s)) {
mask &= CPSR_USER;
+ }
return mask;
}
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 32efa46852..92fafa2659 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -6414,7 +6414,9 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
error_setg(&local_err, "CPU model '%s' requires KVM", name);
goto out;
}
+ }
+ if (cpu->max_features && accel_uses_host_cpuid()) {
if (enable_cpu_pm) {
host_cpuid(5, 0, &cpu->mwait.eax, &cpu->mwait.ebx,
&cpu->mwait.ecx, &cpu->mwait.edx);
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 6ef291d580..69eb43d796 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -105,6 +105,7 @@ static bool has_msr_smi_count;
static bool has_msr_arch_capabs;
static bool has_msr_core_capabs;
static bool has_msr_vmx_vmfunc;
+static bool has_msr_ucode_rev;
static uint32_t has_architectural_pmu_version;
static uint32_t num_architectural_pmu_gp_counters;
@@ -2056,6 +2057,9 @@ static int kvm_get_supported_msrs(KVMState *s)
case MSR_IA32_VMX_VMFUNC:
has_msr_vmx_vmfunc = true;
break;
+ case MSR_IA32_UCODE_REV:
+ has_msr_ucode_rev = true;
+ break;
}
}
}
@@ -2696,8 +2700,7 @@ static void kvm_init_msrs(X86CPU *cpu)
env->features[FEAT_CORE_CAPABILITY]);
}
- if (kvm_arch_get_supported_msr_feature(kvm_state,
- MSR_IA32_UCODE_REV)) {
+ if (has_msr_ucode_rev) {
kvm_msr_entry_add(cpu, MSR_IA32_UCODE_REV, cpu->ucode_rev);
}
diff --git a/target/i386/misc_helper.c b/target/i386/misc_helper.c
index aed16fe3f0..7d61221024 100644
--- a/target/i386/misc_helper.c
+++ b/target/i386/misc_helper.c
@@ -229,7 +229,6 @@ void helper_rdmsr(CPUX86State *env)
#else
void helper_wrmsr(CPUX86State *env)
{
- X86CPU *x86_cpu = env_archcpu(env);
uint64_t val;
cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC());
@@ -372,9 +371,6 @@ void helper_wrmsr(CPUX86State *env)
env->msr_bndcfgs = val;
cpu_sync_bndcs_hflags(env);
break;
- case MSR_IA32_UCODE_REV:
- val = x86_cpu->ucode_rev;
- break;
default:
if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
&& (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
@@ -393,6 +389,7 @@ void helper_wrmsr(CPUX86State *env)
void helper_rdmsr(CPUX86State *env)
{
+ X86CPU *x86_cpu = env_archcpu(env);
uint64_t val;
cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC());
@@ -526,6 +523,9 @@ void helper_rdmsr(CPUX86State *env)
case MSR_IA32_BNDCFGS:
val = env->msr_bndcfgs;
break;
+ case MSR_IA32_UCODE_REV:
+ val = x86_cpu->ucode_rev;
+ break;
default:
if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL
&& (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL +
diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
index 41b4a3c661..327d9588e0 100644
--- a/tcg/tcg-op-gvec.c
+++ b/tcg/tcg-op-gvec.c
@@ -290,6 +290,38 @@ void tcg_gen_gvec_4_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
tcg_temp_free_i32(desc);
}
+/* Generate a call to a gvec-style helper with five vector operands
+ and an extra pointer operand. */
+void tcg_gen_gvec_5_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
+ uint32_t cofs, uint32_t eofs, TCGv_ptr ptr,
+ uint32_t oprsz, uint32_t maxsz, int32_t data,
+ gen_helper_gvec_5_ptr *fn)
+{
+ TCGv_ptr a0, a1, a2, a3, a4;
+ TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+
+ a0 = tcg_temp_new_ptr();
+ a1 = tcg_temp_new_ptr();
+ a2 = tcg_temp_new_ptr();
+ a3 = tcg_temp_new_ptr();
+ a4 = tcg_temp_new_ptr();
+
+ tcg_gen_addi_ptr(a0, cpu_env, dofs);
+ tcg_gen_addi_ptr(a1, cpu_env, aofs);
+ tcg_gen_addi_ptr(a2, cpu_env, bofs);
+ tcg_gen_addi_ptr(a3, cpu_env, cofs);
+ tcg_gen_addi_ptr(a4, cpu_env, eofs);
+
+ fn(a0, a1, a2, a3, a4, ptr, desc);
+
+ tcg_temp_free_ptr(a0);
+ tcg_temp_free_ptr(a1);
+ tcg_temp_free_ptr(a2);
+ tcg_temp_free_ptr(a3);
+ tcg_temp_free_ptr(a4);
+ tcg_temp_free_i32(desc);
+}
+
/* Return true if we want to implement something of OPRSZ bytes
in units of LNSZ. This limits the expansion of inline code. */
static inline bool check_size_impl(uint32_t oprsz, uint32_t lnsz)
diff --git a/tests/check-block.sh b/tests/check-block.sh
index 679aedec50..ad320c21ba 100755
--- a/tests/check-block.sh
+++ b/tests/check-block.sh
@@ -16,7 +16,7 @@ if [ "$#" -ne 0 ]; then
format_list="$@"
fi
-if grep -q "TARGET_GPROF=y" *-softmmu/config-target.mak 2>/dev/null ; then
+if grep -q "CONFIG_GPROF=y" config-host.mak 2>/dev/null ; then
echo "GPROF is enabled ==> Not running the qemu-iotests."
exit 0
fi
diff --git a/tests/data/acpi/virt/DSDT b/tests/data/acpi/virt/DSDT
index d0f3afeb13..d6f5c61788 100644
--- a/tests/data/acpi/virt/DSDT
+++ b/tests/data/acpi/virt/DSDT
Binary files differ
diff --git a/tests/data/acpi/virt/DSDT.memhp b/tests/data/acpi/virt/DSDT.memhp
index 41ccc6431b..c527ac4739 100644
--- a/tests/data/acpi/virt/DSDT.memhp
+++ b/tests/data/acpi/virt/DSDT.memhp
Binary files differ
diff --git a/tests/data/acpi/virt/DSDT.numamem b/tests/data/acpi/virt/DSDT.numamem
index d0f3afeb13..d6f5c61788 100644
--- a/tests/data/acpi/virt/DSDT.numamem
+++ b/tests/data/acpi/virt/DSDT.numamem
Binary files differ
diff --git a/ui/cocoa.m b/ui/cocoa.m
index fbb5b1b45f..747a70839a 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -42,60 +42,10 @@
#include <Carbon/Carbon.h>
#include "hw/core/cpu.h"
-#ifndef MAC_OS_X_VERSION_10_5
-#define MAC_OS_X_VERSION_10_5 1050
-#endif
-#ifndef MAC_OS_X_VERSION_10_6
-#define MAC_OS_X_VERSION_10_6 1060
-#endif
-#ifndef MAC_OS_X_VERSION_10_9
-#define MAC_OS_X_VERSION_10_9 1090
-#endif
-#ifndef MAC_OS_X_VERSION_10_10
-#define MAC_OS_X_VERSION_10_10 101000
-#endif
-#ifndef MAC_OS_X_VERSION_10_12
-#define MAC_OS_X_VERSION_10_12 101200
-#endif
#ifndef MAC_OS_X_VERSION_10_13
#define MAC_OS_X_VERSION_10_13 101300
#endif
-/* macOS 10.12 deprecated many constants, #define the new names for older SDKs */
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
-#define NSEventMaskAny NSAnyEventMask
-#define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask
-#define NSEventModifierFlagShift NSShiftKeyMask
-#define NSEventModifierFlagCommand NSCommandKeyMask
-#define NSEventModifierFlagControl NSControlKeyMask
-#define NSEventModifierFlagOption NSAlternateKeyMask
-#define NSEventTypeFlagsChanged NSFlagsChanged
-#define NSEventTypeKeyUp NSKeyUp
-#define NSEventTypeKeyDown NSKeyDown
-#define NSEventTypeMouseMoved NSMouseMoved
-#define NSEventTypeLeftMouseDown NSLeftMouseDown
-#define NSEventTypeRightMouseDown NSRightMouseDown
-#define NSEventTypeOtherMouseDown NSOtherMouseDown
-#define NSEventTypeLeftMouseDragged NSLeftMouseDragged
-#define NSEventTypeRightMouseDragged NSRightMouseDragged
-#define NSEventTypeOtherMouseDragged NSOtherMouseDragged
-#define NSEventTypeLeftMouseUp NSLeftMouseUp
-#define NSEventTypeRightMouseUp NSRightMouseUp
-#define NSEventTypeOtherMouseUp NSOtherMouseUp
-#define NSEventTypeScrollWheel NSScrollWheel
-#define NSTextAlignmentCenter NSCenterTextAlignment
-#define NSWindowStyleMaskBorderless NSBorderlessWindowMask
-#define NSWindowStyleMaskClosable NSClosableWindowMask
-#define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask
-#define NSWindowStyleMaskTitled NSTitledWindowMask
-#endif
-/* 10.13 deprecates NSFileHandlingPanelOKButton in favour of
- * NSModalResponseOK, which was introduced in 10.9. Define
- * it for older versions.
- */
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_9
-#define NSModalResponseOK NSFileHandlingPanelOKButton
-#endif
/* 10.14 deprecates NSOnState and NSOffState in favor of
* NSControlStateValueOn/Off, which were introduced in 10.13.
* Define for older versions
@@ -125,6 +75,7 @@ typedef struct {
NSWindow *normalWindow, *about_window;
static DisplayChangeListener *dcl;
static int last_buttons;
+static int cursor_hide = 1;
int gArgc;
char **gArgv;
@@ -465,11 +416,7 @@ QemuCocoaView *cocoaView;
COCOA_DEBUG("QemuCocoaView: drawRect\n");
// get CoreGraphic context
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10
- CGContextRef viewContextRef = [[NSGraphicsContext currentContext] graphicsPort];
-#else
CGContextRef viewContextRef = [[NSGraphicsContext currentContext] CGContext];
-#endif
CGContextSetInterpolationQuality (viewContextRef, kCGInterpolationNone);
CGContextSetShouldAntialias (viewContextRef, NO);
@@ -1075,9 +1022,7 @@ QemuCocoaView *cocoaView;
------------------------------------------------------
*/
@interface QemuCocoaAppController : NSObject
-#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
<NSWindowDelegate, NSApplicationDelegate>
-#endif
{
}
- (void)doToggleFullScreen:(id)sender;
@@ -1126,9 +1071,6 @@ QemuCocoaView *cocoaView;
[normalWindow setAcceptsMouseMovedEvents:YES];
[normalWindow setTitle:@"QEMU"];
[normalWindow setContentView:cocoaView];
-#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10)
- [normalWindow useOptimizedDrawing:YES];
-#endif
[normalWindow makeKeyAndOrderFront:self];
[normalWindow center];
[normalWindow setDelegate: self];
@@ -1918,6 +1860,9 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts)
[(QemuCocoaAppController *)[[NSApplication sharedApplication] delegate] toggleFullScreen: nil];
});
}
+ if (opts->has_show_cursor && opts->show_cursor) {
+ cursor_hide = 0;
+ }
dcl = g_malloc0(sizeof(DisplayChangeListener));
diff --git a/ui/gtk.c b/ui/gtk.c
index d18892d1de..f3f0af8921 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1965,17 +1965,19 @@ static GtkWidget *gd_create_menu_machine(GtkDisplayState *s)
* If available, return the refresh rate of the display in milli-Hertz,
* else return 0.
*/
-static int gd_refresh_rate_millihz(GtkDisplayState *s)
+static int gd_refresh_rate_millihz(GtkWidget *window)
{
#ifdef GDK_VERSION_3_22
- GdkDisplay *dpy = gtk_widget_get_display(s->window);
- GdkWindow *win = gtk_widget_get_window(s->window);
- GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win);
+ GdkWindow *win = gtk_widget_get_window(window);
- return gdk_monitor_get_refresh_rate(monitor);
-#else
- return 0;
+ if (win) {
+ GdkDisplay *dpy = gtk_widget_get_display(window);
+ GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win);
+
+ return gdk_monitor_get_refresh_rate(monitor);
+ }
#endif
+ return 0;
}
static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
@@ -2045,7 +2047,8 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
vc->gfx.kbd = qkbd_state_init(con);
vc->gfx.dcl.con = con;
- refresh_rate_millihz = gd_refresh_rate_millihz(s);
+ refresh_rate_millihz = gd_refresh_rate_millihz(vc->window ?
+ vc->window : s->window);
if (refresh_rate_millihz) {
vc->gfx.dcl.update_interval = MILLISEC_PER_SEC / refresh_rate_millihz;
}
@@ -2243,8 +2246,12 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts)
textdomain("qemu");
window_display = gtk_widget_get_display(s->window);
- s->null_cursor = gdk_cursor_new_for_display(window_display,
- GDK_BLANK_CURSOR);
+ if (s->opts->has_show_cursor && s->opts->show_cursor) {
+ s->null_cursor = NULL; /* default pointer */
+ } else {
+ s->null_cursor = gdk_cursor_new_for_display(window_display,
+ GDK_BLANK_CURSOR);
+ }
s->mouse_mode_notifier.notify = gd_mouse_mode_change;
qemu_add_mouse_mode_change_notifier(&s->mouse_mode_notifier);
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 9030f1c42e..3c9424eb42 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -161,9 +161,9 @@ static void sdl_update_caption(struct sdl2_console *scon)
}
}
-static void sdl_hide_cursor(void)
+static void sdl_hide_cursor(struct sdl2_console *scon)
{
- if (!cursor_hide) {
+ if (scon->opts->has_show_cursor && scon->opts->show_cursor) {
return;
}
@@ -175,9 +175,9 @@ static void sdl_hide_cursor(void)
}
}
-static void sdl_show_cursor(void)
+static void sdl_show_cursor(struct sdl2_console *scon)
{
- if (!cursor_hide) {
+ if (scon->opts->has_show_cursor && scon->opts->show_cursor) {
return;
}
@@ -216,7 +216,7 @@ static void sdl_grab_start(struct sdl2_console *scon)
SDL_WarpMouseInWindow(scon->real_window, guest_x, guest_y);
}
} else {
- sdl_hide_cursor();
+ sdl_hide_cursor(scon);
}
SDL_SetWindowGrab(scon->real_window, SDL_TRUE);
gui_grab = 1;
@@ -227,7 +227,7 @@ static void sdl_grab_end(struct sdl2_console *scon)
{
SDL_SetWindowGrab(scon->real_window, SDL_FALSE);
gui_grab = 0;
- sdl_show_cursor();
+ sdl_show_cursor(scon);
sdl_update_caption(scon);
}
@@ -658,7 +658,7 @@ static void sdl_mouse_warp(DisplayChangeListener *dcl,
if (on) {
if (!guest_cursor) {
- sdl_show_cursor();
+ sdl_show_cursor(scon);
}
if (gui_grab || qemu_input_is_absolute() || absolute_enabled) {
SDL_SetCursor(guest_sprite);
@@ -667,7 +667,7 @@ static void sdl_mouse_warp(DisplayChangeListener *dcl,
}
}
} else if (gui_grab) {
- sdl_hide_cursor();
+ sdl_hide_cursor(scon);
}
guest_cursor = on;
guest_x = x, guest_y = y;
diff --git a/util/qemu-timer-common.c b/util/qemu-timer-common.c
index 06d084d364..baf3317f74 100644
--- a/util/qemu-timer-common.c
+++ b/util/qemu-timer-common.c
@@ -49,14 +49,11 @@ int use_rt_clock;
static void __attribute__((constructor)) init_get_clock(void)
{
+ struct timespec ts;
+
use_rt_clock = 0;
-#ifdef CLOCK_MONOTONIC
- {
- struct timespec ts;
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
- use_rt_clock = 1;
- }
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
+ use_rt_clock = 1;
}
-#endif
}
#endif
diff --git a/vl.c b/vl.c
index 7dcb0879c4..b0ee318f99 100644
--- a/vl.c
+++ b/vl.c
@@ -168,7 +168,6 @@ int no_hpet = 0;
int fd_bootchk = 1;
static int no_reboot;
int no_shutdown = 0;
-int cursor_hide = 1;
int graphic_rotate = 0;
const char *watchdog;
QEMUOptionRom option_rom[MAX_OPTION_ROMS];
@@ -1931,6 +1930,16 @@ static void parse_display(const char *p)
} else {
goto invalid_sdl_args;
}
+ } else if (strstart(opts, ",show-cursor=", &nextopt)) {
+ opts = nextopt;
+ dpy.has_show_cursor = true;
+ if (strstart(opts, "on", &nextopt)) {
+ dpy.show_cursor = true;
+ } else if (strstart(opts, "off", &nextopt)) {
+ dpy.show_cursor = false;
+ } else {
+ goto invalid_sdl_args;
+ }
} else if (strstart(opts, ",gl=", &nextopt)) {
opts = nextopt;
dpy.has_gl = true;
@@ -3501,7 +3510,7 @@ int main(int argc, char **argv, char **envp)
gchar **optname = g_strsplit(typename,
ACCEL_CLASS_SUFFIX, 0);
printf("%s\n", optname[0]);
- g_free(optname);
+ g_strfreev(optname);
}
g_free(typename);
}
@@ -3553,7 +3562,10 @@ int main(int argc, char **argv, char **envp)
no_shutdown = 1;
break;
case QEMU_OPTION_show_cursor:
- cursor_hide = 0;
+ warn_report("The -show-cursor option is deprecated, "
+ "use -display {sdl,gtk},show-cursor=on instead");
+ dpy.has_show_cursor = true;
+ dpy.show_cursor = true;
break;
case QEMU_OPTION_uuid:
if (qemu_uuid_parse(optarg, &qemu_uuid) < 0) {