mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210510-1' into staging
target-arm queue: * docs: fix link in sbsa description * linux-user/aarch64: Enable hwcap for RND, BTI, and MTE * target/arm: Fix tlbbits calculation in tlbi_aa64_vae2is_write() * target/arm: Split neon and vfp translation to their own compilation units * target/arm: Make WFI a NOP for userspace emulators * hw/sd/omap_mmc: Use device_cold_reset() instead of device_legacy_reset() * include: More fixes for 'extern "C"' block use * hw/arm/imx25_pdk: Fix error message for invalid RAM size * hw/arm/mps2-tz: Implement AN524 memory remapping via machine property * hw/arm/xlnx: Fix PHY address for xilinx-zynq-a9 # gpg: Signature made Mon 10 May 2021 17:26:55 BST # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20210510-1: (26 commits) hw/arm/xlnx: Fix PHY address for xilinx-zynq-a9 hw/arm/mps2-tz: Implement AN524 memory remapping via machine property hw/misc/mps2-scc: Support using CFG0 bit 0 for remapping hw/misc/mps2-scc: Add "QEMU interface" comment hw/arm/imx25_pdk: Fix error message for invalid RAM size include/disas/dis-asm.h: Handle being included outside 'extern "C"' include/qemu/bswap.h: Handle being included outside extern "C" block osdep: Make os-win32.h and os-posix.h handle 'extern "C"' themselves hw/sd/omap_mmc: Use device_cold_reset() instead of device_legacy_reset() target/arm: Make WFI a NOP for userspace emulators target/arm: Make translate-neon.c.inc its own compilation unit target/arm: Make functions used by translate-neon global target/arm: Move NeonGenThreeOpEnvFn typedef to translate.h target/arm: Delete unused typedef target/arm: Move vfp_reg_ptr() to translate-neon.c.inc target/arm: Make translate-vfp.c.inc its own compilation unit target/arm: Make functions used by translate-vfp global target/arm: Move vfp_{load, store}_reg{32, 64} to translate-vfp.c.inc target/arm: Move gen_aa32 functions to translate-a32.h target/arm: Split m-nocp trans functions into their own file ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -18,9 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
extern "C" {
|
||||
#include "disas/dis-asm.h"
|
||||
}
|
||||
|
||||
#include "vixl/a64/disasm-a64.h"
|
||||
|
||||
|
||||
@@ -28,9 +28,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
extern "C" {
|
||||
#include "disas/dis-asm.h"
|
||||
}
|
||||
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
@@ -45,3 +45,13 @@ Differences between QEMU and real hardware:
|
||||
flash, but only as simple ROM, so attempting to rewrite the flash
|
||||
from the guest will fail
|
||||
- QEMU does not model the USB controller in MPS3 boards
|
||||
|
||||
Machine-specific options
|
||||
""""""""""""""""""""""""
|
||||
|
||||
The following machine-specific options are supported:
|
||||
|
||||
remap
|
||||
Supported for ``mps3-an524`` only.
|
||||
Set ``BRAM``/``QSPI`` to select the initial memory mapping. The
|
||||
default is ``BRAM``.
|
||||
|
||||
@@ -4,7 +4,7 @@ Arm Server Base System Architecture Reference board (``sbsa-ref``)
|
||||
While the `virt` board is a generic board platform that doesn't match
|
||||
any real hardware the `sbsa-ref` board intends to look like real
|
||||
hardware. The `Server Base System Architecture
|
||||
<https://developer.arm.com/documentation/den0029/latest>` defines a
|
||||
<https://developer.arm.com/documentation/den0029/latest>`_ defines a
|
||||
minimum base line of hardware support and importantly how the firmware
|
||||
reports that to any operating system. It is a static system that
|
||||
reports a very minimal DT to the firmware for non-discoverable
|
||||
|
||||
+2
-3
@@ -65,7 +65,6 @@ static struct arm_boot_info imx25_pdk_binfo;
|
||||
|
||||
static void imx25_pdk_init(MachineState *machine)
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
IMX25PDK *s = g_new0(IMX25PDK, 1);
|
||||
unsigned int ram_size;
|
||||
unsigned int alias_offset;
|
||||
@@ -77,8 +76,8 @@ static void imx25_pdk_init(MachineState *machine)
|
||||
|
||||
/* We need to initialize our memory */
|
||||
if (machine->ram_size > (FSL_IMX25_SDRAM0_SIZE + FSL_IMX25_SDRAM1_SIZE)) {
|
||||
char *sz = size_to_str(mc->default_ram_size);
|
||||
error_report("Invalid RAM size, should be %s", sz);
|
||||
char *sz = size_to_str(FSL_IMX25_SDRAM0_SIZE + FSL_IMX25_SDRAM1_SIZE);
|
||||
error_report("RAM size more than %s is not supported", sz);
|
||||
g_free(sz);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
+107
-1
@@ -55,6 +55,7 @@
|
||||
#include "hw/boards.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "hw/misc/unimp.h"
|
||||
#include "hw/char/cmsdk-apb-uart.h"
|
||||
#include "hw/timer/cmsdk-apb-timer.h"
|
||||
@@ -72,6 +73,7 @@
|
||||
#include "hw/core/split-irq.h"
|
||||
#include "hw/qdev-clock.h"
|
||||
#include "qom/object.h"
|
||||
#include "hw/irq.h"
|
||||
|
||||
#define MPS2TZ_NUMIRQ_MAX 96
|
||||
#define MPS2TZ_RAM_MAX 5
|
||||
@@ -153,6 +155,9 @@ struct MPS2TZMachineState {
|
||||
SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ_MAX];
|
||||
Clock *sysclk;
|
||||
Clock *s32kclk;
|
||||
|
||||
bool remap;
|
||||
qemu_irq remap_irq;
|
||||
};
|
||||
|
||||
#define TYPE_MPS2TZ_MACHINE "mps2tz"
|
||||
@@ -228,6 +233,10 @@ static const RAMInfo an505_raminfo[] = { {
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Note that the addresses and MPC numbering here should match up
|
||||
* with those used in remap_memory(), which can swap the BRAM and QSPI.
|
||||
*/
|
||||
static const RAMInfo an524_raminfo[] = { {
|
||||
.name = "bram",
|
||||
.base = 0x00000000,
|
||||
@@ -457,6 +466,7 @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
|
||||
|
||||
object_initialize_child(OBJECT(mms), "scc", scc, TYPE_MPS2_SCC);
|
||||
sccdev = DEVICE(scc);
|
||||
qdev_prop_set_uint32(sccdev, "scc-cfg0", mms->remap ? 1 : 0);
|
||||
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
|
||||
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
|
||||
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
|
||||
@@ -573,6 +583,52 @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
|
||||
return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
|
||||
}
|
||||
|
||||
static hwaddr boot_mem_base(MPS2TZMachineState *mms)
|
||||
{
|
||||
/*
|
||||
* Return the canonical address of the block which will be mapped
|
||||
* at address 0x0 (i.e. where the vector table is).
|
||||
* This is usually 0, but if the AN524 alternate memory map is
|
||||
* enabled it will be the base address of the QSPI block.
|
||||
*/
|
||||
return mms->remap ? 0x28000000 : 0;
|
||||
}
|
||||
|
||||
static void remap_memory(MPS2TZMachineState *mms, int map)
|
||||
{
|
||||
/*
|
||||
* Remap the memory for the AN524. 'map' is the value of
|
||||
* SCC CFG_REG0 bit 0, i.e. 0 for the default map and 1
|
||||
* for the "option 1" mapping where QSPI is at address 0.
|
||||
*
|
||||
* Effectively we need to swap around the "upstream" ends of
|
||||
* MPC 0 and MPC 1.
|
||||
*/
|
||||
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
|
||||
int i;
|
||||
|
||||
if (mmc->fpga_type != FPGA_AN524) {
|
||||
return;
|
||||
}
|
||||
|
||||
memory_region_transaction_begin();
|
||||
for (i = 0; i < 2; i++) {
|
||||
TZMPC *mpc = &mms->mpc[i];
|
||||
MemoryRegion *upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
|
||||
hwaddr addr = (i ^ map) ? 0x28000000 : 0;
|
||||
|
||||
memory_region_set_address(upstream, addr);
|
||||
}
|
||||
memory_region_transaction_commit();
|
||||
}
|
||||
|
||||
static void remap_irq_fn(void *opaque, int n, int level)
|
||||
{
|
||||
MPS2TZMachineState *mms = opaque;
|
||||
|
||||
remap_memory(mms, level);
|
||||
}
|
||||
|
||||
static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
|
||||
const char *name, hwaddr size,
|
||||
const int *irqs)
|
||||
@@ -711,7 +767,7 @@ static uint32_t boot_ram_size(MPS2TZMachineState *mms)
|
||||
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
|
||||
|
||||
for (p = mmc->raminfo; p->name; p++) {
|
||||
if (p->base == 0) {
|
||||
if (p->base == boot_mem_base(mms)) {
|
||||
return p->size;
|
||||
}
|
||||
}
|
||||
@@ -1095,6 +1151,16 @@ static void mps2tz_common_init(MachineState *machine)
|
||||
|
||||
create_non_mpc_ram(mms);
|
||||
|
||||
if (mmc->fpga_type == FPGA_AN524) {
|
||||
/*
|
||||
* Connect the line from the SCC so that we can remap when the
|
||||
* guest updates that register.
|
||||
*/
|
||||
mms->remap_irq = qemu_allocate_irq(remap_irq_fn, mms, 0);
|
||||
qdev_connect_gpio_out_named(DEVICE(&mms->scc), "remap", 0,
|
||||
mms->remap_irq);
|
||||
}
|
||||
|
||||
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
|
||||
boot_ram_size(mms));
|
||||
}
|
||||
@@ -1117,12 +1183,47 @@ static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address,
|
||||
*iregion = region;
|
||||
}
|
||||
|
||||
static char *mps2_get_remap(Object *obj, Error **errp)
|
||||
{
|
||||
MPS2TZMachineState *mms = MPS2TZ_MACHINE(obj);
|
||||
const char *val = mms->remap ? "QSPI" : "BRAM";
|
||||
return g_strdup(val);
|
||||
}
|
||||
|
||||
static void mps2_set_remap(Object *obj, const char *value, Error **errp)
|
||||
{
|
||||
MPS2TZMachineState *mms = MPS2TZ_MACHINE(obj);
|
||||
|
||||
if (!strcmp(value, "BRAM")) {
|
||||
mms->remap = false;
|
||||
} else if (!strcmp(value, "QSPI")) {
|
||||
mms->remap = true;
|
||||
} else {
|
||||
error_setg(errp, "Invalid remap value");
|
||||
error_append_hint(errp, "Valid values are BRAM and QSPI.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void mps2_machine_reset(MachineState *machine)
|
||||
{
|
||||
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
|
||||
|
||||
/*
|
||||
* Set the initial memory mapping before triggering the reset of
|
||||
* the rest of the system, so that the guest image loader and CPU
|
||||
* reset see the correct mapping.
|
||||
*/
|
||||
remap_memory(mms, mms->remap);
|
||||
qemu_devices_reset();
|
||||
}
|
||||
|
||||
static void mps2tz_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
IDAUInterfaceClass *iic = IDAU_INTERFACE_CLASS(oc);
|
||||
|
||||
mc->init = mps2tz_common_init;
|
||||
mc->reset = mps2_machine_reset;
|
||||
iic->check = mps2_tz_idau_check;
|
||||
}
|
||||
|
||||
@@ -1225,6 +1326,11 @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
|
||||
mmc->raminfo = an524_raminfo;
|
||||
mmc->armsse_type = TYPE_SSE200;
|
||||
mps2tz_set_default_ram_info(mmc);
|
||||
|
||||
object_class_property_add_str(oc, "remap", mps2_get_remap, mps2_set_remap);
|
||||
object_class_property_set_description(oc, "remap",
|
||||
"Set memory mapping. Valid values "
|
||||
"are BRAM (default) and QSPI.");
|
||||
}
|
||||
|
||||
static void mps3tz_an547_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
@@ -118,7 +118,7 @@ static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
|
||||
qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
|
||||
qdev_set_nic_properties(dev, nd);
|
||||
}
|
||||
object_property_set_int(OBJECT(dev), "phy-addr", 23, &error_abort);
|
||||
object_property_set_int(OBJECT(dev), "phy-addr", 7, &error_abort);
|
||||
s = SYS_BUS_DEVICE(dev);
|
||||
sysbus_realize_and_unref(s, &error_fatal);
|
||||
sysbus_mmio_map(s, 0, base);
|
||||
|
||||
+10
-3
@@ -23,6 +23,7 @@
|
||||
#include "qemu/bitops.h"
|
||||
#include "trace.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/irq.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/registerfields.h"
|
||||
#include "hw/misc/mps2-scc.h"
|
||||
@@ -186,10 +187,13 @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
|
||||
switch (offset) {
|
||||
case A_CFG0:
|
||||
/*
|
||||
* TODO on some boards bit 0 controls RAM remapping;
|
||||
* on others bit 1 is CPU_WAIT.
|
||||
* On some boards bit 0 controls board-specific remapping;
|
||||
* we always reflect bit 0 in the 'remap' GPIO output line,
|
||||
* and let the board wire it up or not as it chooses.
|
||||
* TODO on some boards bit 1 is CPU_WAIT.
|
||||
*/
|
||||
s->cfg0 = value;
|
||||
qemu_set_irq(s->remap, s->cfg0 & 1);
|
||||
break;
|
||||
case A_CFG1:
|
||||
s->cfg1 = value;
|
||||
@@ -283,7 +287,7 @@ static void mps2_scc_reset(DeviceState *dev)
|
||||
int i;
|
||||
|
||||
trace_mps2_scc_reset();
|
||||
s->cfg0 = 0;
|
||||
s->cfg0 = s->cfg0_reset;
|
||||
s->cfg1 = 0;
|
||||
s->cfg2 = 0;
|
||||
s->cfg5 = 0;
|
||||
@@ -308,6 +312,7 @@ static void mps2_scc_init(Object *obj)
|
||||
|
||||
memory_region_init_io(&s->iomem, obj, &mps2_scc_ops, s, "mps2-scc", 0x1000);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
qdev_init_gpio_out_named(DEVICE(obj), &s->remap, "remap", 1);
|
||||
}
|
||||
|
||||
static void mps2_scc_realize(DeviceState *dev, Error **errp)
|
||||
@@ -353,6 +358,8 @@ static Property mps2_scc_properties[] = {
|
||||
DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, cfg4, 0),
|
||||
DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0),
|
||||
DEFINE_PROP_UINT32("scc-id", MPS2SCC, id, 0),
|
||||
/* Reset value for CFG0 register */
|
||||
DEFINE_PROP_UINT32("scc-cfg0", MPS2SCC, cfg0_reset, 0),
|
||||
/*
|
||||
* These are the initial settings for the source clocks on the board.
|
||||
* In hardware they can be configured via a config file read by the
|
||||
|
||||
+1
-1
@@ -318,7 +318,7 @@ void omap_mmc_reset(struct omap_mmc_s *host)
|
||||
* into any bus, and we must reset it manually. When omap_mmc is
|
||||
* QOMified this must move into the QOM reset function.
|
||||
*/
|
||||
device_legacy_reset(DEVICE(host->card));
|
||||
device_cold_reset(DEVICE(host->card));
|
||||
}
|
||||
|
||||
static uint64_t omap_mmc_read(void *opaque, hwaddr offset,
|
||||
|
||||
+10
-2
@@ -9,6 +9,12 @@
|
||||
#ifndef DISAS_DIS_ASM_H
|
||||
#define DISAS_DIS_ASM_H
|
||||
|
||||
#include "qemu/bswap.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void *PTR;
|
||||
typedef uint64_t bfd_vma;
|
||||
typedef int64_t bfd_signed_vma;
|
||||
@@ -479,8 +485,6 @@ bool cap_disas_plugin(disassemble_info *info, uint64_t pc, size_t size);
|
||||
|
||||
/* from libbfd */
|
||||
|
||||
#include "qemu/bswap.h"
|
||||
|
||||
static inline bfd_vma bfd_getl64(const bfd_byte *addr)
|
||||
{
|
||||
return ldq_le_p(addr);
|
||||
@@ -508,4 +512,8 @@ static inline bfd_vma bfd_getb16(const bfd_byte *addr)
|
||||
|
||||
typedef bool bfd_boolean;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DISAS_DIS_ASM_H */
|
||||
|
||||
@@ -9,6 +9,24 @@
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a model of the Serial Communication Controller (SCC)
|
||||
* block found in most MPS FPGA images.
|
||||
*
|
||||
* QEMU interface:
|
||||
* + sysbus MMIO region 0: the register bank
|
||||
* + QOM property "scc-cfg4": value of the read-only CFG4 register
|
||||
* + QOM property "scc-aid": value of the read-only SCC_AID register
|
||||
* + QOM property "scc-id": value of the read-only SCC_ID register
|
||||
* + QOM property "scc-cfg0": reset value of the CFG0 register
|
||||
* + QOM property array "oscclk": reset values of the OSCCLK registers
|
||||
* (which are accessed via the SYS_CFG channel provided by this device)
|
||||
* + named GPIO output "remap": this tracks the value of CFG0 register
|
||||
* bit 0. Boards where this bit controls memory remapping should
|
||||
* connect this GPIO line to a function performing that mapping.
|
||||
* Boards where bit 0 has no special function should leave the GPIO
|
||||
* output disconnected.
|
||||
*/
|
||||
#ifndef MPS2_SCC_H
|
||||
#define MPS2_SCC_H
|
||||
|
||||
@@ -43,6 +61,9 @@ struct MPS2SCC {
|
||||
uint32_t num_oscclk;
|
||||
uint32_t *oscclk;
|
||||
uint32_t *oscclk_reset;
|
||||
uint32_t cfg0_reset;
|
||||
|
||||
qemu_irq remap;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+22
-4
@@ -1,8 +1,6 @@
|
||||
#ifndef BSWAP_H
|
||||
#define BSWAP_H
|
||||
|
||||
#include "fpu/softfloat-types.h"
|
||||
|
||||
#ifdef CONFIG_MACHINE_BSWAP_H
|
||||
# include <sys/endian.h>
|
||||
# include <machine/bswap.h>
|
||||
@@ -12,7 +10,18 @@
|
||||
# include <endian.h>
|
||||
#elif defined(CONFIG_BYTESWAP_H)
|
||||
# include <byteswap.h>
|
||||
#define BSWAP_FROM_BYTESWAP
|
||||
# else
|
||||
#define BSWAP_FROM_FALLBACKS
|
||||
#endif /* ! CONFIG_MACHINE_BSWAP_H */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "fpu/softfloat-types.h"
|
||||
|
||||
#ifdef BSWAP_FROM_BYTESWAP
|
||||
static inline uint16_t bswap16(uint16_t x)
|
||||
{
|
||||
return bswap_16(x);
|
||||
@@ -27,7 +36,9 @@ static inline uint64_t bswap64(uint64_t x)
|
||||
{
|
||||
return bswap_64(x);
|
||||
}
|
||||
# else
|
||||
#endif
|
||||
|
||||
#ifdef BSWAP_FROM_FALLBACKS
|
||||
static inline uint16_t bswap16(uint16_t x)
|
||||
{
|
||||
return (((x & 0x00ff) << 8) |
|
||||
@@ -53,7 +64,10 @@ static inline uint64_t bswap64(uint64_t x)
|
||||
((x & 0x00ff000000000000ULL) >> 40) |
|
||||
((x & 0xff00000000000000ULL) >> 56));
|
||||
}
|
||||
#endif /* ! CONFIG_MACHINE_BSWAP_H */
|
||||
#endif
|
||||
|
||||
#undef BSWAP_FROM_BYTESWAP
|
||||
#undef BSWAP_FROM_FALLBACKS
|
||||
|
||||
static inline void bswap16s(uint16_t *s)
|
||||
{
|
||||
@@ -494,4 +508,8 @@ DO_STN_LDN_P(be)
|
||||
#undef le_bswaps
|
||||
#undef be_bswaps
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BSWAP_H */
|
||||
|
||||
@@ -131,10 +131,6 @@ QEMU_EXTERN_C int daemon(int, int);
|
||||
*/
|
||||
#include "glib-compat.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "sysemu/os-win32.h"
|
||||
#endif
|
||||
@@ -143,6 +139,10 @@ extern "C" {
|
||||
#include "sysemu/os-posix.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "qemu/typedefs.h"
|
||||
|
||||
/*
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
#include <sys/sysmacros.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void os_set_line_buffering(void);
|
||||
void os_set_proc_name(const char *s);
|
||||
void os_setup_signal_handling(void);
|
||||
@@ -92,4 +96,8 @@ static inline void qemu_funlockfile(FILE *f)
|
||||
funlockfile(f);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,6 +30,10 @@
|
||||
#include <windows.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(_WIN64)
|
||||
/* On w64, setjmp is implemented by _setjmp which needs a second parameter.
|
||||
* If this parameter is NULL, longjump does no stack unwinding.
|
||||
@@ -194,4 +198,8 @@ ssize_t qemu_recv_wrap(int sockfd, void *buf, size_t len, int flags);
|
||||
ssize_t qemu_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags,
|
||||
struct sockaddr *addr, socklen_t *addrlen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -586,6 +586,16 @@ enum {
|
||||
ARM_HWCAP2_A64_SVESM4 = 1 << 6,
|
||||
ARM_HWCAP2_A64_FLAGM2 = 1 << 7,
|
||||
ARM_HWCAP2_A64_FRINT = 1 << 8,
|
||||
ARM_HWCAP2_A64_SVEI8MM = 1 << 9,
|
||||
ARM_HWCAP2_A64_SVEF32MM = 1 << 10,
|
||||
ARM_HWCAP2_A64_SVEF64MM = 1 << 11,
|
||||
ARM_HWCAP2_A64_SVEBF16 = 1 << 12,
|
||||
ARM_HWCAP2_A64_I8MM = 1 << 13,
|
||||
ARM_HWCAP2_A64_BF16 = 1 << 14,
|
||||
ARM_HWCAP2_A64_DGH = 1 << 15,
|
||||
ARM_HWCAP2_A64_RNG = 1 << 16,
|
||||
ARM_HWCAP2_A64_BTI = 1 << 17,
|
||||
ARM_HWCAP2_A64_MTE = 1 << 18,
|
||||
};
|
||||
|
||||
#define ELF_HWCAP get_elf_hwcap()
|
||||
@@ -640,6 +650,9 @@ static uint32_t get_elf_hwcap2(void)
|
||||
GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP);
|
||||
GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2);
|
||||
GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT);
|
||||
GET_FEATURE_ID(aa64_rndr, ARM_HWCAP2_A64_RNG);
|
||||
GET_FEATURE_ID(aa64_bti, ARM_HWCAP2_A64_BTI);
|
||||
GET_FEATURE_ID(aa64_mte, ARM_HWCAP2_A64_MTE);
|
||||
|
||||
return hwcaps;
|
||||
}
|
||||
|
||||
+1
-1
@@ -4742,7 +4742,7 @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
uint64_t pageaddr = sextract64(value << 12, 0, 56);
|
||||
bool secure = arm_is_secure_below_el3(env);
|
||||
int mask = secure ? ARMMMUIdxBit_SE2 : ARMMMUIdxBit_E2;
|
||||
int bits = tlbbits_for_regime(env, secure ? ARMMMUIdx_E2 : ARMMMUIdx_SE2,
|
||||
int bits = tlbbits_for_regime(env, secure ? ARMMMUIdx_SE2 : ARMMMUIdx_E2,
|
||||
pageaddr);
|
||||
|
||||
tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
gen = [
|
||||
decodetree.process('sve.decode', extra_args: '--decode=disas_sve'),
|
||||
decodetree.process('neon-shared.decode', extra_args: '--static-decode=disas_neon_shared'),
|
||||
decodetree.process('neon-dp.decode', extra_args: '--static-decode=disas_neon_dp'),
|
||||
decodetree.process('neon-ls.decode', extra_args: '--static-decode=disas_neon_ls'),
|
||||
decodetree.process('vfp.decode', extra_args: '--static-decode=disas_vfp'),
|
||||
decodetree.process('vfp-uncond.decode', extra_args: '--static-decode=disas_vfp_uncond'),
|
||||
decodetree.process('m-nocp.decode', extra_args: '--static-decode=disas_m_nocp'),
|
||||
decodetree.process('neon-shared.decode', extra_args: '--decode=disas_neon_shared'),
|
||||
decodetree.process('neon-dp.decode', extra_args: '--decode=disas_neon_dp'),
|
||||
decodetree.process('neon-ls.decode', extra_args: '--decode=disas_neon_ls'),
|
||||
decodetree.process('vfp.decode', extra_args: '--decode=disas_vfp'),
|
||||
decodetree.process('vfp-uncond.decode', extra_args: '--decode=disas_vfp_uncond'),
|
||||
decodetree.process('m-nocp.decode', extra_args: '--decode=disas_m_nocp'),
|
||||
decodetree.process('a32.decode', extra_args: '--static-decode=disas_a32'),
|
||||
decodetree.process('a32-uncond.decode', extra_args: '--static-decode=disas_a32_uncond'),
|
||||
decodetree.process('t32.decode', extra_args: '--static-decode=disas_t32'),
|
||||
@@ -26,6 +26,9 @@ arm_ss.add(files(
|
||||
'op_helper.c',
|
||||
'tlb_helper.c',
|
||||
'translate.c',
|
||||
'translate-m-nocp.c',
|
||||
'translate-neon.c',
|
||||
'translate-vfp.c',
|
||||
'vec_helper.c',
|
||||
'vfp_helper.c',
|
||||
'cpu_tcg.c',
|
||||
|
||||
@@ -228,6 +228,7 @@ void HELPER(setend)(CPUARMState *env)
|
||||
arm_rebuild_hflags(env);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped.
|
||||
* The function returns the target EL (1-3) if the instruction is to be trapped;
|
||||
* otherwise it returns 0 indicating it is not trapped.
|
||||
@@ -282,9 +283,21 @@ static inline int check_wfx_trap(CPUARMState *env, bool is_wfe)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void HELPER(wfi)(CPUARMState *env, uint32_t insn_len)
|
||||
{
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/*
|
||||
* WFI in the user-mode emulator is technically permitted but not
|
||||
* something any real-world code would do. AArch64 Linux kernels
|
||||
* trap it via SCTRL_EL1.nTWI and make it an (expensive) NOP;
|
||||
* AArch32 kernels don't trap it so it will delay a bit.
|
||||
* For QEMU, make it NOP here, because trying to raise EXCP_HLT
|
||||
* would trigger an abort.
|
||||
*/
|
||||
return;
|
||||
#else
|
||||
CPUState *cs = env_cpu(env);
|
||||
int target_el = check_wfx_trap(env, false);
|
||||
|
||||
@@ -309,6 +322,7 @@ void HELPER(wfi)(CPUARMState *env, uint32_t insn_len)
|
||||
cs->exception_index = EXCP_HLT;
|
||||
cs->halted = 1;
|
||||
cpu_loop_exit(cs);
|
||||
#endif
|
||||
}
|
||||
|
||||
void HELPER(wfe)(CPUARMState *env)
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* AArch32 translation, common definitions.
|
||||
*
|
||||
* Copyright (c) 2021 Linaro, Ltd.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TARGET_ARM_TRANSLATE_A64_H
|
||||
#define TARGET_ARM_TRANSLATE_A64_H
|
||||
|
||||
/* Prototypes for autogenerated disassembler functions */
|
||||
bool disas_m_nocp(DisasContext *dc, uint32_t insn);
|
||||
bool disas_vfp(DisasContext *s, uint32_t insn);
|
||||
bool disas_vfp_uncond(DisasContext *s, uint32_t insn);
|
||||
bool disas_neon_dp(DisasContext *s, uint32_t insn);
|
||||
bool disas_neon_ls(DisasContext *s, uint32_t insn);
|
||||
bool disas_neon_shared(DisasContext *s, uint32_t insn);
|
||||
|
||||
void load_reg_var(DisasContext *s, TCGv_i32 var, int reg);
|
||||
void arm_gen_condlabel(DisasContext *s);
|
||||
bool vfp_access_check(DisasContext *s);
|
||||
void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop);
|
||||
void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop);
|
||||
void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop);
|
||||
void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop);
|
||||
TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs);
|
||||
void gen_set_cpsr(TCGv_i32 var, uint32_t mask);
|
||||
void gen_set_condexec(DisasContext *s);
|
||||
void gen_set_pc_im(DisasContext *s, target_ulong val);
|
||||
void gen_lookup_tb(DisasContext *s);
|
||||
long vfp_reg_offset(bool dp, unsigned reg);
|
||||
long neon_full_reg_offset(unsigned reg);
|
||||
long neon_element_offset(int reg, int element, MemOp memop);
|
||||
void gen_rev16(TCGv_i32 dest, TCGv_i32 var);
|
||||
|
||||
static inline TCGv_i32 load_cpu_offset(int offset)
|
||||
{
|
||||
TCGv_i32 tmp = tcg_temp_new_i32();
|
||||
tcg_gen_ld_i32(tmp, cpu_env, offset);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
|
||||
|
||||
static inline void store_cpu_offset(TCGv_i32 var, int offset)
|
||||
{
|
||||
tcg_gen_st_i32(var, cpu_env, offset);
|
||||
tcg_temp_free_i32(var);
|
||||
}
|
||||
|
||||
#define store_cpu_field(var, name) \
|
||||
store_cpu_offset(var, offsetof(CPUARMState, name))
|
||||
|
||||
/* Create a new temporary and set it to the value of a CPU register. */
|
||||
static inline TCGv_i32 load_reg(DisasContext *s, int reg)
|
||||
{
|
||||
TCGv_i32 tmp = tcg_temp_new_i32();
|
||||
load_reg_var(s, tmp, reg);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void store_reg(DisasContext *s, int reg, TCGv_i32 var);
|
||||
|
||||
void gen_aa32_ld_internal_i32(DisasContext *s, TCGv_i32 val,
|
||||
TCGv_i32 a32, int index, MemOp opc);
|
||||
void gen_aa32_st_internal_i32(DisasContext *s, TCGv_i32 val,
|
||||
TCGv_i32 a32, int index, MemOp opc);
|
||||
void gen_aa32_ld_internal_i64(DisasContext *s, TCGv_i64 val,
|
||||
TCGv_i32 a32, int index, MemOp opc);
|
||||
void gen_aa32_st_internal_i64(DisasContext *s, TCGv_i64 val,
|
||||
TCGv_i32 a32, int index, MemOp opc);
|
||||
void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
|
||||
int index, MemOp opc);
|
||||
void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
|
||||
int index, MemOp opc);
|
||||
void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
|
||||
int index, MemOp opc);
|
||||
void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
|
||||
int index, MemOp opc);
|
||||
|
||||
#define DO_GEN_LD(SUFF, OPC) \
|
||||
static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
|
||||
TCGv_i32 a32, int index) \
|
||||
{ \
|
||||
gen_aa32_ld_i32(s, val, a32, index, OPC); \
|
||||
}
|
||||
|
||||
#define DO_GEN_ST(SUFF, OPC) \
|
||||
static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
|
||||
TCGv_i32 a32, int index) \
|
||||
{ \
|
||||
gen_aa32_st_i32(s, val, a32, index, OPC); \
|
||||
}
|
||||
|
||||
static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
|
||||
TCGv_i32 a32, int index)
|
||||
{
|
||||
gen_aa32_ld_i64(s, val, a32, index, MO_Q);
|
||||
}
|
||||
|
||||
static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
|
||||
TCGv_i32 a32, int index)
|
||||
{
|
||||
gen_aa32_st_i64(s, val, a32, index, MO_Q);
|
||||
}
|
||||
|
||||
DO_GEN_LD(8u, MO_UB)
|
||||
DO_GEN_LD(16u, MO_UW)
|
||||
DO_GEN_LD(32u, MO_UL)
|
||||
DO_GEN_ST(8, MO_UB)
|
||||
DO_GEN_ST(16, MO_UW)
|
||||
DO_GEN_ST(32, MO_UL)
|
||||
|
||||
#undef DO_GEN_LD
|
||||
#undef DO_GEN_ST
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
#define IS_USER(s) 1
|
||||
#else
|
||||
#define IS_USER(s) (s->user)
|
||||
#endif
|
||||
|
||||
/* Set NZCV flags from the high 4 bits of var. */
|
||||
#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
|
||||
|
||||
/* Swap low and high halfwords. */
|
||||
static inline void gen_swap_half(TCGv_i32 dest, TCGv_i32 var)
|
||||
{
|
||||
tcg_gen_rotri_i32(dest, var, 16);
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user