target-arm queue:
* Fix vd == vm overlap in sve_ldff1_z * Add support for MTE with KVM guests * Add RAZ/WI handling for DBGDTR[TX|RX] * Start of conversion of A64 decoder to decodetree * Saturate L2CTLR_EL1 core count field rather than overflowing * vexpress: Avoid trivial memory leak of 'flashalias' * sbsa-ref: switch default cpu core to Neoverse-N1 * sbsa-ref: use Bochs graphics card instead of VGA * MAINTAINERS: Add Marcin Juszkiewicz to sbsa-ref reviewer list * docs: Convert u2f.txt to rST -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmRmHvMZHHBldGVyLm1h eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3vqqEACFEcWq3E2gRjwnz8JAEk/0 jYuYg9jUG6Ev6xY5x31+M4DfK78eXgHYtCxhEcT6FSwpFg/ZXC+bPlZcRlM+8692 gkp+JJeBA4VRy9e7Uk6GvRWnpGzjnkHTHf4E9PZB8iIvbJY9nFTtMZydn1w0EnMW HsetnNLIxrtJaETwUa5mDWh0Bt4t6ZIEB2bJSr3O0fy7uiJ8xvpRMYxqfxvI0h+0 7xSaG7xb5Dy4LxohMK0CLdj1wy+8uWpYgD6ZneJ2hlqjknvNWa3zdR8bRLNT0aZL 8ubR1ioFvfi+uA26SNVrdRrGEhqMrTxD0XstFutz0zlOjn0wjo1Ny/ojmGYWuvcU aG09UvcecMP8hy+ygTXJ+2D04eH1VGmS1GEwRS3p+fdODsgHy0Ctln8IPK8SuG7q 67BG/F4GNdkbktHGbZlwduxh30furH8pSSlIJOeTq7d20+atqZ94MWaoW1iQ+t4B 9gDi3MsKoUKVNEhJPorHlDxvtlQppr0ziL0IVPeYUNJONlSza88hkx34ScA5Rl7+ 5vQYjLkhS1qZQqvd1fNSRNtHeGx2uBeE9eZF/ZCp7bA5rxcRn//LmG7hO7Octuii zIVaOektXeShALdJ7dMt4MZh0z1RjVVLf0ouC1HHCg9rlzvB+0I5AhXYacGkmCqW wf9S0hvNqdGmJRQhNRonGg== =ooCi -----END PGP SIGNATURE----- Merge tag 'pull-target-arm-20230518' of https://git.linaro.org/people/pmaydell/qemu-arm into staging target-arm queue: * Fix vd == vm overlap in sve_ldff1_z * Add support for MTE with KVM guests * Add RAZ/WI handling for DBGDTR[TX|RX] * Start of conversion of A64 decoder to decodetree * Saturate L2CTLR_EL1 core count field rather than overflowing * vexpress: Avoid trivial memory leak of 'flashalias' * sbsa-ref: switch default cpu core to Neoverse-N1 * sbsa-ref: use Bochs graphics card instead of VGA * MAINTAINERS: Add Marcin Juszkiewicz to sbsa-ref reviewer list * docs: Convert u2f.txt to rST # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmRmHvMZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3vqqEACFEcWq3E2gRjwnz8JAEk/0 # jYuYg9jUG6Ev6xY5x31+M4DfK78eXgHYtCxhEcT6FSwpFg/ZXC+bPlZcRlM+8692 # gkp+JJeBA4VRy9e7Uk6GvRWnpGzjnkHTHf4E9PZB8iIvbJY9nFTtMZydn1w0EnMW # HsetnNLIxrtJaETwUa5mDWh0Bt4t6ZIEB2bJSr3O0fy7uiJ8xvpRMYxqfxvI0h+0 # 7xSaG7xb5Dy4LxohMK0CLdj1wy+8uWpYgD6ZneJ2hlqjknvNWa3zdR8bRLNT0aZL # 8ubR1ioFvfi+uA26SNVrdRrGEhqMrTxD0XstFutz0zlOjn0wjo1Ny/ojmGYWuvcU # aG09UvcecMP8hy+ygTXJ+2D04eH1VGmS1GEwRS3p+fdODsgHy0Ctln8IPK8SuG7q # 67BG/F4GNdkbktHGbZlwduxh30furH8pSSlIJOeTq7d20+atqZ94MWaoW1iQ+t4B # 9gDi3MsKoUKVNEhJPorHlDxvtlQppr0ziL0IVPeYUNJONlSza88hkx34ScA5Rl7+ # 5vQYjLkhS1qZQqvd1fNSRNtHeGx2uBeE9eZF/ZCp7bA5rxcRn//LmG7hO7Octuii # zIVaOektXeShALdJ7dMt4MZh0z1RjVVLf0ouC1HHCg9rlzvB+0I5AhXYacGkmCqW # wf9S0hvNqdGmJRQhNRonGg== # =ooCi # -----END PGP SIGNATURE----- # gpg: Signature made Thu 18 May 2023 05:49:55 AM PDT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [full] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [full] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [full] * tag 'pull-target-arm-20230518' of https://git.linaro.org/people/pmaydell/qemu-arm: (29 commits) docs: Convert u2f.txt to rST hw/arm/vexpress: Avoid trivial memory leak of 'flashalias' target/arm: Saturate L2CTLR_EL1 core count field rather than overflowing target/arm: Convert ERET, ERETAA, ERETAB to decodetree target/arm: Convert BRAA, BRAB, BLRAA, BLRAB to decodetree target/arm: Convert BRA[AB]Z, BLR[AB]Z, RETA[AB] to decodetree target/arm: Convert BR, BLR, RET to decodetree target/arm: Convert conditional branch insns to decodetree target/arm: Convert TBZ, TBNZ to decodetree target/arm: Convert CBZ, CBNZ to decodetree target/arm: Convert unconditional branch immediate to decodetree target/arm: Convert Extract instructions to decodetree target/arm: Convert Bitfield to decodetree target/arm: Convert Move wide (immediate) to decodetree target/arm: Convert Logical (immediate) to decodetree target/arm: Replace bitmask64 with MAKE_64BIT_MASK target/arm: Convert Add/subtract (immediate with tags) to decodetree target/arm: Convert Add/subtract (immediate) to decodetree target/arm: Split gen_add_CC and gen_sub_CC target/arm: Convert PC-rel addressing to decodetree ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
266ccbb27b
@ -940,6 +940,7 @@ SBSA-REF
|
|||||||
M: Radoslaw Biernacki <rad@semihalf.com>
|
M: Radoslaw Biernacki <rad@semihalf.com>
|
||||||
M: Peter Maydell <peter.maydell@linaro.org>
|
M: Peter Maydell <peter.maydell@linaro.org>
|
||||||
R: Leif Lindholm <quic_llindhol@quicinc.com>
|
R: Leif Lindholm <quic_llindhol@quicinc.com>
|
||||||
|
R: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
|
||||||
L: qemu-arm@nongnu.org
|
L: qemu-arm@nongnu.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: hw/arm/sbsa-ref.c
|
F: hw/arm/sbsa-ref.c
|
||||||
|
@ -93,4 +93,5 @@ Emulated Devices
|
|||||||
devices/virtio-pmem.rst
|
devices/virtio-pmem.rst
|
||||||
devices/vhost-user-rng.rst
|
devices/vhost-user-rng.rst
|
||||||
devices/canokey.rst
|
devices/canokey.rst
|
||||||
|
devices/usb-u2f.rst
|
||||||
devices/igb.rst
|
devices/igb.rst
|
||||||
|
93
docs/system/devices/usb-u2f.rst
Normal file
93
docs/system/devices/usb-u2f.rst
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
Universal Second Factor (U2F) USB Key Device
|
||||||
|
============================================
|
||||||
|
|
||||||
|
U2F is an open authentication standard that enables relying parties
|
||||||
|
exposed to the internet to offer a strong second factor option for end
|
||||||
|
user authentication.
|
||||||
|
|
||||||
|
The second factor is provided by a device implementing the U2F
|
||||||
|
protocol. In case of a USB U2F security key, it is a USB HID device
|
||||||
|
that implements the U2F protocol.
|
||||||
|
|
||||||
|
QEMU supports both pass-through of a host U2F key device to a VM,
|
||||||
|
and software emulation of a U2F key.
|
||||||
|
|
||||||
|
``u2f-passthru``
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The ``u2f-passthru`` device allows you to connect a real hardware
|
||||||
|
U2F key on your host to a guest VM. All requests made from the guest
|
||||||
|
are passed through to the physical security key connected to the
|
||||||
|
host machine and vice versa.
|
||||||
|
|
||||||
|
In addition, the dedicated pass-through allows you to share a single
|
||||||
|
U2F security key with several guest VMs, which is not possible with a
|
||||||
|
simple host device assignment pass-through.
|
||||||
|
|
||||||
|
You can specify the host U2F key to use with the ``hidraw``
|
||||||
|
option, which takes the host path to a Linux ``/dev/hidrawN`` device:
|
||||||
|
|
||||||
|
.. parsed-literal::
|
||||||
|
|qemu_system| -usb -device u2f-passthru,hidraw=/dev/hidraw0
|
||||||
|
|
||||||
|
If you don't specify the device, the ``u2f-passthru`` device will
|
||||||
|
autoscan to take the first U2F device it finds on the host (this
|
||||||
|
requires a working libudev):
|
||||||
|
|
||||||
|
.. parsed-literal::
|
||||||
|
|qemu_system| -usb -device u2f-passthru
|
||||||
|
|
||||||
|
``u2f-emulated``
|
||||||
|
----------------
|
||||||
|
|
||||||
|
``u2f-emulated`` is a completely software emulated U2F device.
|
||||||
|
It uses `libu2f-emu <https://github.com/MattGorko/libu2f-emu>`__
|
||||||
|
for the U2F key emulation. libu2f-emu
|
||||||
|
provides a complete implementation of the U2F protocol device part for
|
||||||
|
all specified transports given by the FIDO Alliance.
|
||||||
|
|
||||||
|
To work, an emulated U2F device must have four elements:
|
||||||
|
|
||||||
|
* ec x509 certificate
|
||||||
|
* ec private key
|
||||||
|
* counter (four bytes value)
|
||||||
|
* 48 bytes of entropy (random bits)
|
||||||
|
|
||||||
|
To use this type of device, these have to be configured, and these
|
||||||
|
four elements must be passed one way or another.
|
||||||
|
|
||||||
|
Assuming that you have a working libu2f-emu installed on the host,
|
||||||
|
there are three possible ways to configure the ``u2f-emulated`` device:
|
||||||
|
|
||||||
|
* ephemeral
|
||||||
|
* setup directory
|
||||||
|
* manual
|
||||||
|
|
||||||
|
Ephemeral is the simplest way to configure; it lets the device generate
|
||||||
|
all the elements it needs for a single use of the lifetime of the device.
|
||||||
|
It is the default if you do not pass any other options to the device.
|
||||||
|
|
||||||
|
.. parsed-literal::
|
||||||
|
|qemu_system| -usb -device u2f-emulated
|
||||||
|
|
||||||
|
You can pass the device the path of a setup directory on the host
|
||||||
|
using the ``dir`` option; the directory must contain these four files:
|
||||||
|
|
||||||
|
* ``certificate.pem``: ec x509 certificate
|
||||||
|
* ``private-key.pem``: ec private key
|
||||||
|
* ``counter``: counter value
|
||||||
|
* ``entropy``: 48 bytes of entropy
|
||||||
|
|
||||||
|
.. parsed-literal::
|
||||||
|
|qemu_system| -usb -device u2f-emulated,dir=$dir
|
||||||
|
|
||||||
|
You can also manually pass the device the paths to each of these files,
|
||||||
|
if you don't want them all to be in the same directory, using the options
|
||||||
|
|
||||||
|
* ``cert``
|
||||||
|
* ``priv``
|
||||||
|
* ``counter``
|
||||||
|
* ``entropy``
|
||||||
|
|
||||||
|
.. parsed-literal::
|
||||||
|
|qemu_system| -usb -device u2f-emulated,cert=$DIR1/$FILE1,priv=$DIR2/$FILE2,counter=$DIR3/$FILE3,entropy=$DIR4/$FILE4
|
@ -207,7 +207,7 @@ option or the ``device_add`` monitor command. Available devices are:
|
|||||||
USB audio device
|
USB audio device
|
||||||
|
|
||||||
``u2f-{emulated,passthru}``
|
``u2f-{emulated,passthru}``
|
||||||
Universal Second Factor device
|
:doc:`usb-u2f`
|
||||||
|
|
||||||
``canokey``
|
``canokey``
|
||||||
An Open-source Secure Key implementing FIDO2, OpenPGP, PIV and more.
|
An Open-source Secure Key implementing FIDO2, OpenPGP, PIV and more.
|
||||||
|
110
docs/u2f.txt
110
docs/u2f.txt
@ -1,110 +0,0 @@
|
|||||||
QEMU U2F Key Device Documentation.
|
|
||||||
|
|
||||||
Contents
|
|
||||||
1. USB U2F key device
|
|
||||||
2. Building
|
|
||||||
3. Using u2f-emulated
|
|
||||||
4. Using u2f-passthru
|
|
||||||
5. Libu2f-emu
|
|
||||||
|
|
||||||
1. USB U2F key device
|
|
||||||
|
|
||||||
U2F is an open authentication standard that enables relying parties
|
|
||||||
exposed to the internet to offer a strong second factor option for end
|
|
||||||
user authentication.
|
|
||||||
|
|
||||||
The standard brings many advantages to both parties, client and server,
|
|
||||||
allowing to reduce over-reliance on passwords, it increases authentication
|
|
||||||
security and simplifies passwords.
|
|
||||||
|
|
||||||
The second factor is materialized by a device implementing the U2F
|
|
||||||
protocol. In case of a USB U2F security key, it is a USB HID device
|
|
||||||
that implements the U2F protocol.
|
|
||||||
|
|
||||||
In QEMU, the USB U2F key device offers a dedicated support of U2F, allowing
|
|
||||||
guest USB FIDO/U2F security keys operating in two possible modes:
|
|
||||||
pass-through and emulated.
|
|
||||||
|
|
||||||
The pass-through mode consists of passing all requests made from the guest
|
|
||||||
to the physical security key connected to the host machine and vice versa.
|
|
||||||
In addition, the dedicated pass-through allows to have a U2F security key
|
|
||||||
shared on several guests which is not possible with a simple host device
|
|
||||||
assignment pass-through.
|
|
||||||
|
|
||||||
The emulated mode consists of completely emulating the behavior of an
|
|
||||||
U2F device through software part. Libu2f-emu is used for that.
|
|
||||||
|
|
||||||
|
|
||||||
2. Building
|
|
||||||
|
|
||||||
To ensure the build of the u2f-emulated device variant which depends
|
|
||||||
on libu2f-emu: configuring and building:
|
|
||||||
|
|
||||||
./configure --enable-u2f && make
|
|
||||||
|
|
||||||
The pass-through mode is built by default on Linux. To take advantage
|
|
||||||
of the autoscan option it provides, make sure you have a working libudev
|
|
||||||
installed on the host.
|
|
||||||
|
|
||||||
|
|
||||||
3. Using u2f-emulated
|
|
||||||
|
|
||||||
To work, an emulated U2F device must have four elements:
|
|
||||||
* ec x509 certificate
|
|
||||||
* ec private key
|
|
||||||
* counter (four bytes value)
|
|
||||||
* 48 bytes of entropy (random bits)
|
|
||||||
|
|
||||||
To use this type of device, this one has to be configured, and these
|
|
||||||
four elements must be passed one way or another.
|
|
||||||
|
|
||||||
Assuming that you have a working libu2f-emu installed on the host.
|
|
||||||
There are three possible ways of configurations:
|
|
||||||
* ephemeral
|
|
||||||
* setup directory
|
|
||||||
* manual
|
|
||||||
|
|
||||||
Ephemeral is the simplest way to configure, it lets the device generate
|
|
||||||
all the elements it needs for a single use of the lifetime of the device.
|
|
||||||
|
|
||||||
qemu -usb -device u2f-emulated
|
|
||||||
|
|
||||||
Setup directory allows to configure the device from a directory containing
|
|
||||||
four files:
|
|
||||||
* certificate.pem: ec x509 certificate
|
|
||||||
* private-key.pem: ec private key
|
|
||||||
* counter: counter value
|
|
||||||
* entropy: 48 bytes of entropy
|
|
||||||
|
|
||||||
qemu -usb -device u2f-emulated,dir=$dir
|
|
||||||
|
|
||||||
Manual allows to configure the device more finely by specifying each
|
|
||||||
of the elements necessary for the device:
|
|
||||||
* cert
|
|
||||||
* priv
|
|
||||||
* counter
|
|
||||||
* entropy
|
|
||||||
|
|
||||||
qemu -usb -device u2f-emulated,cert=$DIR1/$FILE1,priv=$DIR2/$FILE2,counter=$DIR3/$FILE3,entropy=$DIR4/$FILE4
|
|
||||||
|
|
||||||
|
|
||||||
4. Using u2f-passthru
|
|
||||||
|
|
||||||
On the host specify the u2f-passthru device with a suitable hidraw:
|
|
||||||
|
|
||||||
qemu -usb -device u2f-passthru,hidraw=/dev/hidraw0
|
|
||||||
|
|
||||||
Alternately, the u2f-passthru device can autoscan to take the first
|
|
||||||
U2F device it finds on the host (this requires a working libudev):
|
|
||||||
|
|
||||||
qemu -usb -device u2f-passthru
|
|
||||||
|
|
||||||
|
|
||||||
5. Libu2f-emu
|
|
||||||
|
|
||||||
The u2f-emulated device uses libu2f-emu for the U2F key emulation. Libu2f-emu
|
|
||||||
implements completely the U2F protocol device part for all specified
|
|
||||||
transport given by the FIDO Alliance.
|
|
||||||
|
|
||||||
For more information about libu2f-emu see this page:
|
|
||||||
https://github.com/MattGorko/libu2f-emu.
|
|
@ -648,7 +648,7 @@ static void create_pcie(SBSAMachineState *sms)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_create_simple(pci->bus, -1, "VGA");
|
pci_create_simple(pci->bus, -1, "bochs-display");
|
||||||
|
|
||||||
create_smmu(sms, pci->bus);
|
create_smmu(sms, pci->bus);
|
||||||
}
|
}
|
||||||
@ -852,7 +852,7 @@ static void sbsa_ref_class_init(ObjectClass *oc, void *data)
|
|||||||
|
|
||||||
mc->init = sbsa_ref_init;
|
mc->init = sbsa_ref_init;
|
||||||
mc->desc = "QEMU 'SBSA Reference' ARM Virtual Machine";
|
mc->desc = "QEMU 'SBSA Reference' ARM Virtual Machine";
|
||||||
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a57");
|
mc->default_cpu_type = ARM_CPU_TYPE_NAME("neoverse-n1");
|
||||||
mc->max_cpus = 512;
|
mc->max_cpus = 512;
|
||||||
mc->pci_allow_0_address = true;
|
mc->pci_allow_0_address = true;
|
||||||
mc->minimum_page_bits = 12;
|
mc->minimum_page_bits = 12;
|
||||||
|
@ -173,6 +173,11 @@ struct VexpressMachineClass {
|
|||||||
|
|
||||||
struct VexpressMachineState {
|
struct VexpressMachineState {
|
||||||
MachineState parent;
|
MachineState parent;
|
||||||
|
MemoryRegion vram;
|
||||||
|
MemoryRegion sram;
|
||||||
|
MemoryRegion flashalias;
|
||||||
|
MemoryRegion lowram;
|
||||||
|
MemoryRegion a15sram;
|
||||||
bool secure;
|
bool secure;
|
||||||
bool virt;
|
bool virt;
|
||||||
};
|
};
|
||||||
@ -182,7 +187,7 @@ struct VexpressMachineState {
|
|||||||
#define TYPE_VEXPRESS_A15_MACHINE MACHINE_TYPE_NAME("vexpress-a15")
|
#define TYPE_VEXPRESS_A15_MACHINE MACHINE_TYPE_NAME("vexpress-a15")
|
||||||
OBJECT_DECLARE_TYPE(VexpressMachineState, VexpressMachineClass, VEXPRESS_MACHINE)
|
OBJECT_DECLARE_TYPE(VexpressMachineState, VexpressMachineClass, VEXPRESS_MACHINE)
|
||||||
|
|
||||||
typedef void DBoardInitFn(const VexpressMachineState *machine,
|
typedef void DBoardInitFn(VexpressMachineState *machine,
|
||||||
ram_addr_t ram_size,
|
ram_addr_t ram_size,
|
||||||
const char *cpu_type,
|
const char *cpu_type,
|
||||||
qemu_irq *pic);
|
qemu_irq *pic);
|
||||||
@ -263,14 +268,13 @@ static void init_cpus(MachineState *ms, const char *cpu_type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void a9_daughterboard_init(const VexpressMachineState *vms,
|
static void a9_daughterboard_init(VexpressMachineState *vms,
|
||||||
ram_addr_t ram_size,
|
ram_addr_t ram_size,
|
||||||
const char *cpu_type,
|
const char *cpu_type,
|
||||||
qemu_irq *pic)
|
qemu_irq *pic)
|
||||||
{
|
{
|
||||||
MachineState *machine = MACHINE(vms);
|
MachineState *machine = MACHINE(vms);
|
||||||
MemoryRegion *sysmem = get_system_memory();
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
MemoryRegion *lowram = g_new(MemoryRegion, 1);
|
|
||||||
ram_addr_t low_ram_size;
|
ram_addr_t low_ram_size;
|
||||||
|
|
||||||
if (ram_size > 0x40000000) {
|
if (ram_size > 0x40000000) {
|
||||||
@ -287,9 +291,9 @@ static void a9_daughterboard_init(const VexpressMachineState *vms,
|
|||||||
* address space should in theory be remappable to various
|
* address space should in theory be remappable to various
|
||||||
* things including ROM or RAM; we always map the RAM there.
|
* things including ROM or RAM; we always map the RAM there.
|
||||||
*/
|
*/
|
||||||
memory_region_init_alias(lowram, NULL, "vexpress.lowmem", machine->ram,
|
memory_region_init_alias(&vms->lowram, NULL, "vexpress.lowmem",
|
||||||
0, low_ram_size);
|
machine->ram, 0, low_ram_size);
|
||||||
memory_region_add_subregion(sysmem, 0x0, lowram);
|
memory_region_add_subregion(sysmem, 0x0, &vms->lowram);
|
||||||
memory_region_add_subregion(sysmem, 0x60000000, machine->ram);
|
memory_region_add_subregion(sysmem, 0x60000000, machine->ram);
|
||||||
|
|
||||||
/* 0x1e000000 A9MPCore (SCU) private memory region */
|
/* 0x1e000000 A9MPCore (SCU) private memory region */
|
||||||
@ -348,14 +352,13 @@ static VEDBoardInfo a9_daughterboard = {
|
|||||||
.init = a9_daughterboard_init,
|
.init = a9_daughterboard_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void a15_daughterboard_init(const VexpressMachineState *vms,
|
static void a15_daughterboard_init(VexpressMachineState *vms,
|
||||||
ram_addr_t ram_size,
|
ram_addr_t ram_size,
|
||||||
const char *cpu_type,
|
const char *cpu_type,
|
||||||
qemu_irq *pic)
|
qemu_irq *pic)
|
||||||
{
|
{
|
||||||
MachineState *machine = MACHINE(vms);
|
MachineState *machine = MACHINE(vms);
|
||||||
MemoryRegion *sysmem = get_system_memory();
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
MemoryRegion *sram = g_new(MemoryRegion, 1);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
/* We have to use a separate 64 bit variable here to avoid the gcc
|
/* We have to use a separate 64 bit variable here to avoid the gcc
|
||||||
@ -386,9 +389,9 @@ static void a15_daughterboard_init(const VexpressMachineState *vms,
|
|||||||
/* 0x2b060000: SP805 watchdog: not modelled */
|
/* 0x2b060000: SP805 watchdog: not modelled */
|
||||||
/* 0x2b0a0000: PL341 dynamic memory controller: not modelled */
|
/* 0x2b0a0000: PL341 dynamic memory controller: not modelled */
|
||||||
/* 0x2e000000: system SRAM */
|
/* 0x2e000000: system SRAM */
|
||||||
memory_region_init_ram(sram, NULL, "vexpress.a15sram", 0x10000,
|
memory_region_init_ram(&vms->a15sram, NULL, "vexpress.a15sram", 0x10000,
|
||||||
&error_fatal);
|
&error_fatal);
|
||||||
memory_region_add_subregion(sysmem, 0x2e000000, sram);
|
memory_region_add_subregion(sysmem, 0x2e000000, &vms->a15sram);
|
||||||
|
|
||||||
/* 0x7ffb0000: DMA330 DMA controller: not modelled */
|
/* 0x7ffb0000: DMA330 DMA controller: not modelled */
|
||||||
/* 0x7ffd0000: PL354 static memory controller: not modelled */
|
/* 0x7ffd0000: PL354 static memory controller: not modelled */
|
||||||
@ -547,10 +550,6 @@ static void vexpress_common_init(MachineState *machine)
|
|||||||
I2CBus *i2c;
|
I2CBus *i2c;
|
||||||
ram_addr_t vram_size, sram_size;
|
ram_addr_t vram_size, sram_size;
|
||||||
MemoryRegion *sysmem = get_system_memory();
|
MemoryRegion *sysmem = get_system_memory();
|
||||||
MemoryRegion *vram = g_new(MemoryRegion, 1);
|
|
||||||
MemoryRegion *sram = g_new(MemoryRegion, 1);
|
|
||||||
MemoryRegion *flashalias = g_new(MemoryRegion, 1);
|
|
||||||
MemoryRegion *flash0mem;
|
|
||||||
const hwaddr *map = daughterboard->motherboard_map;
|
const hwaddr *map = daughterboard->motherboard_map;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -662,24 +661,25 @@ static void vexpress_common_init(MachineState *machine)
|
|||||||
|
|
||||||
if (map[VE_NORFLASHALIAS] != -1) {
|
if (map[VE_NORFLASHALIAS] != -1) {
|
||||||
/* Map flash 0 as an alias into low memory */
|
/* Map flash 0 as an alias into low memory */
|
||||||
|
MemoryRegion *flash0mem;
|
||||||
flash0mem = sysbus_mmio_get_region(SYS_BUS_DEVICE(pflash0), 0);
|
flash0mem = sysbus_mmio_get_region(SYS_BUS_DEVICE(pflash0), 0);
|
||||||
memory_region_init_alias(flashalias, NULL, "vexpress.flashalias",
|
memory_region_init_alias(&vms->flashalias, NULL, "vexpress.flashalias",
|
||||||
flash0mem, 0, VEXPRESS_FLASH_SIZE);
|
flash0mem, 0, VEXPRESS_FLASH_SIZE);
|
||||||
memory_region_add_subregion(sysmem, map[VE_NORFLASHALIAS], flashalias);
|
memory_region_add_subregion(sysmem, map[VE_NORFLASHALIAS], &vms->flashalias);
|
||||||
}
|
}
|
||||||
|
|
||||||
dinfo = drive_get(IF_PFLASH, 0, 1);
|
dinfo = drive_get(IF_PFLASH, 0, 1);
|
||||||
ve_pflash_cfi01_register(map[VE_NORFLASH1], "vexpress.flash1", dinfo);
|
ve_pflash_cfi01_register(map[VE_NORFLASH1], "vexpress.flash1", dinfo);
|
||||||
|
|
||||||
sram_size = 0x2000000;
|
sram_size = 0x2000000;
|
||||||
memory_region_init_ram(sram, NULL, "vexpress.sram", sram_size,
|
memory_region_init_ram(&vms->sram, NULL, "vexpress.sram", sram_size,
|
||||||
&error_fatal);
|
&error_fatal);
|
||||||
memory_region_add_subregion(sysmem, map[VE_SRAM], sram);
|
memory_region_add_subregion(sysmem, map[VE_SRAM], &vms->sram);
|
||||||
|
|
||||||
vram_size = 0x800000;
|
vram_size = 0x800000;
|
||||||
memory_region_init_ram(vram, NULL, "vexpress.vram", vram_size,
|
memory_region_init_ram(&vms->vram, NULL, "vexpress.vram", vram_size,
|
||||||
&error_fatal);
|
&error_fatal);
|
||||||
memory_region_add_subregion(sysmem, map[VE_VIDEORAM], vram);
|
memory_region_add_subregion(sysmem, map[VE_VIDEORAM], &vms->vram);
|
||||||
|
|
||||||
/* 0x4e000000 LAN9118 Ethernet */
|
/* 0x4e000000 LAN9118 Ethernet */
|
||||||
if (nd_table[0].used) {
|
if (nd_table[0].used) {
|
||||||
|
@ -2146,7 +2146,7 @@ static void machvirt_init(MachineState *machine)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vms->mte && (kvm_enabled() || hvf_enabled())) {
|
if (vms->mte && hvf_enabled()) {
|
||||||
error_report("mach-virt: %s does not support providing "
|
error_report("mach-virt: %s does not support providing "
|
||||||
"MTE to the guest CPU",
|
"MTE to the guest CPU",
|
||||||
current_accel_name());
|
current_accel_name());
|
||||||
@ -2216,39 +2216,48 @@ static void machvirt_init(MachineState *machine)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (vms->mte) {
|
if (vms->mte) {
|
||||||
/* Create the memory region only once, but link to all cpus. */
|
if (tcg_enabled()) {
|
||||||
if (!tag_sysmem) {
|
/* Create the memory region only once, but link to all cpus. */
|
||||||
/*
|
if (!tag_sysmem) {
|
||||||
* The property exists only if MemTag is supported.
|
/*
|
||||||
* If it is, we must allocate the ram to back that up.
|
* The property exists only if MemTag is supported.
|
||||||
*/
|
* If it is, we must allocate the ram to back that up.
|
||||||
if (!object_property_find(cpuobj, "tag-memory")) {
|
*/
|
||||||
error_report("MTE requested, but not supported "
|
if (!object_property_find(cpuobj, "tag-memory")) {
|
||||||
"by the guest CPU");
|
error_report("MTE requested, but not supported "
|
||||||
|
"by the guest CPU");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
tag_sysmem = g_new(MemoryRegion, 1);
|
||||||
|
memory_region_init(tag_sysmem, OBJECT(machine),
|
||||||
|
"tag-memory", UINT64_MAX / 32);
|
||||||
|
|
||||||
|
if (vms->secure) {
|
||||||
|
secure_tag_sysmem = g_new(MemoryRegion, 1);
|
||||||
|
memory_region_init(secure_tag_sysmem, OBJECT(machine),
|
||||||
|
"secure-tag-memory",
|
||||||
|
UINT64_MAX / 32);
|
||||||
|
|
||||||
|
/* As with ram, secure-tag takes precedence over tag. */
|
||||||
|
memory_region_add_subregion_overlap(secure_tag_sysmem,
|
||||||
|
0, tag_sysmem, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object_property_set_link(cpuobj, "tag-memory",
|
||||||
|
OBJECT(tag_sysmem), &error_abort);
|
||||||
|
if (vms->secure) {
|
||||||
|
object_property_set_link(cpuobj, "secure-tag-memory",
|
||||||
|
OBJECT(secure_tag_sysmem),
|
||||||
|
&error_abort);
|
||||||
|
}
|
||||||
|
} else if (kvm_enabled()) {
|
||||||
|
if (!kvm_arm_mte_supported()) {
|
||||||
|
error_report("MTE requested, but not supported by KVM");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
kvm_arm_enable_mte(cpuobj, &error_abort);
|
||||||
tag_sysmem = g_new(MemoryRegion, 1);
|
|
||||||
memory_region_init(tag_sysmem, OBJECT(machine),
|
|
||||||
"tag-memory", UINT64_MAX / 32);
|
|
||||||
|
|
||||||
if (vms->secure) {
|
|
||||||
secure_tag_sysmem = g_new(MemoryRegion, 1);
|
|
||||||
memory_region_init(secure_tag_sysmem, OBJECT(machine),
|
|
||||||
"secure-tag-memory", UINT64_MAX / 32);
|
|
||||||
|
|
||||||
/* As with ram, secure-tag takes precedence over tag. */
|
|
||||||
memory_region_add_subregion_overlap(secure_tag_sysmem, 0,
|
|
||||||
tag_sysmem, -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object_property_set_link(cpuobj, "tag-memory", OBJECT(tag_sysmem),
|
|
||||||
&error_abort);
|
|
||||||
if (vms->secure) {
|
|
||||||
object_property_set_link(cpuobj, "secure-tag-memory",
|
|
||||||
OBJECT(secure_tag_sysmem),
|
|
||||||
&error_abort);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,8 +15,15 @@ static uint64_t l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
|||||||
{
|
{
|
||||||
ARMCPU *cpu = env_archcpu(env);
|
ARMCPU *cpu = env_archcpu(env);
|
||||||
|
|
||||||
/* Number of cores is in [25:24]; otherwise we RAZ */
|
/*
|
||||||
return (cpu->core_count - 1) << 24;
|
* Number of cores is in [25:24]; otherwise we RAZ.
|
||||||
|
* If the board didn't configure the CPUs into clusters,
|
||||||
|
* we default to "all CPUs in one cluster", which might be
|
||||||
|
* more than the 4 that the hardware permits and which is
|
||||||
|
* all you can report in this two-bit field. Saturate to
|
||||||
|
* 0b11 (== 4 CPUs) rather than overflowing the field.
|
||||||
|
*/
|
||||||
|
return MIN(cpu->core_count - 1, 3) << 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const ARMCPRegInfo cortex_a72_a57_a53_cp_reginfo[] = {
|
static const ARMCPRegInfo cortex_a72_a57_a53_cp_reginfo[] = {
|
||||||
|
@ -1480,6 +1480,7 @@ void arm_cpu_post_init(Object *obj)
|
|||||||
qdev_prop_allow_set_link_before_realize,
|
qdev_prop_allow_set_link_before_realize,
|
||||||
OBJ_PROP_LINK_STRONG);
|
OBJ_PROP_LINK_STRONG);
|
||||||
}
|
}
|
||||||
|
cpu->has_mte = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -1616,7 +1617,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
|||||||
}
|
}
|
||||||
if (cpu->tag_memory) {
|
if (cpu->tag_memory) {
|
||||||
error_setg(errp,
|
error_setg(errp,
|
||||||
"Cannot enable %s when guest CPUs has MTE enabled",
|
"Cannot enable %s when guest CPUs has tag memory enabled",
|
||||||
current_accel_name());
|
current_accel_name());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1996,10 +1997,10 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
if (cpu->tag_memory == NULL && cpu_isar_feature(aa64_mte, cpu)) {
|
if (!cpu->has_mte && cpu_isar_feature(aa64_mte, cpu)) {
|
||||||
/*
|
/*
|
||||||
* Disable the MTE feature bits if we do not have tag-memory
|
* Disable the MTE feature bits if we do not have the feature
|
||||||
* provided by the machine.
|
* setup by the machine.
|
||||||
*/
|
*/
|
||||||
cpu->isar.id_aa64pfr1 =
|
cpu->isar.id_aa64pfr1 =
|
||||||
FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 0);
|
FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 0);
|
||||||
|
@ -935,6 +935,9 @@ struct ArchCPU {
|
|||||||
*/
|
*/
|
||||||
uint32_t psci_conduit;
|
uint32_t psci_conduit;
|
||||||
|
|
||||||
|
/* CPU has Memory Tag Extension */
|
||||||
|
bool has_mte;
|
||||||
|
|
||||||
/* For v8M, initial value of the Secure VTOR */
|
/* For v8M, initial value of the Secure VTOR */
|
||||||
uint32_t init_svtor;
|
uint32_t init_svtor;
|
||||||
/* For v8M, initial value of the Non-secure VTOR */
|
/* For v8M, initial value of the Non-secure VTOR */
|
||||||
@ -1053,6 +1056,7 @@ struct ArchCPU {
|
|||||||
bool prop_pauth;
|
bool prop_pauth;
|
||||||
bool prop_pauth_impdef;
|
bool prop_pauth_impdef;
|
||||||
bool prop_lpa2;
|
bool prop_lpa2;
|
||||||
|
OnOffAuto prop_mte;
|
||||||
|
|
||||||
/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
|
/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
|
||||||
uint32_t dcz_blocksize;
|
uint32_t dcz_blocksize;
|
||||||
|
@ -949,8 +949,10 @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
|
|||||||
.access = PL0_R, .accessfn = access_tdcc,
|
.access = PL0_R, .accessfn = access_tdcc,
|
||||||
.type = ARM_CP_CONST, .resetvalue = 0 },
|
.type = ARM_CP_CONST, .resetvalue = 0 },
|
||||||
/*
|
/*
|
||||||
* OSDTRRX_EL1/OSDTRTX_EL1 are used for save and restore of DBGDTRRX_EL0.
|
* These registers belong to the Debug Communications Channel,
|
||||||
* It is a component of the Debug Communications Channel, which is not implemented.
|
* which is not implemented. However we implement RAZ/WI behaviour
|
||||||
|
* with trapping to prevent spurious SIGILLs if the guest OS does
|
||||||
|
* access them as the support cannot be probed for.
|
||||||
*/
|
*/
|
||||||
{ .name = "OSDTRRX_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14,
|
{ .name = "OSDTRRX_EL1", .state = ARM_CP_STATE_BOTH, .cp = 14,
|
||||||
.opc0 = 2, .opc1 = 0, .crn = 0, .crm = 0, .opc2 = 2,
|
.opc0 = 2, .opc1 = 0, .crn = 0, .crm = 0, .opc2 = 2,
|
||||||
@ -960,6 +962,11 @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
|
|||||||
.opc0 = 2, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2,
|
.opc0 = 2, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2,
|
||||||
.access = PL1_RW, .accessfn = access_tdcc,
|
.access = PL1_RW, .accessfn = access_tdcc,
|
||||||
.type = ARM_CP_CONST, .resetvalue = 0 },
|
.type = ARM_CP_CONST, .resetvalue = 0 },
|
||||||
|
/* DBGDTRTX_EL0/DBGDTRRX_EL0 depend on direction */
|
||||||
|
{ .name = "DBGDTR_EL0", .state = ARM_CP_STATE_BOTH, .cp = 14,
|
||||||
|
.opc0 = 2, .opc1 = 3, .crn = 0, .crm = 5, .opc2 = 0,
|
||||||
|
.access = PL0_RW, .accessfn = access_tdcc,
|
||||||
|
.type = ARM_CP_CONST, .resetvalue = 0 },
|
||||||
/*
|
/*
|
||||||
* OSECCR_EL1 provides a mechanism for an operating system
|
* OSECCR_EL1 provides a mechanism for an operating system
|
||||||
* to access the contents of EDECCR. EDECCR is not implemented though,
|
* to access the contents of EDECCR. EDECCR is not implemented though,
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "hw/irq.h"
|
#include "hw/irq.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
|
#include "migration/blocker.h"
|
||||||
|
|
||||||
const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
|
const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
|
||||||
KVM_CAP_LAST_INFO
|
KVM_CAP_LAST_INFO
|
||||||
@ -1064,3 +1065,37 @@ bool kvm_arch_cpu_check_are_resettable(void)
|
|||||||
void kvm_arch_accel_class_init(ObjectClass *oc)
|
void kvm_arch_accel_class_init(ObjectClass *oc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void kvm_arm_enable_mte(Object *cpuobj, Error **errp)
|
||||||
|
{
|
||||||
|
static bool tried_to_enable;
|
||||||
|
static bool succeeded_to_enable;
|
||||||
|
Error *mte_migration_blocker = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!tried_to_enable) {
|
||||||
|
/*
|
||||||
|
* MTE on KVM is enabled on a per-VM basis (and retrying doesn't make
|
||||||
|
* sense), and we only want a single migration blocker as well.
|
||||||
|
*/
|
||||||
|
tried_to_enable = true;
|
||||||
|
|
||||||
|
ret = kvm_vm_enable_cap(kvm_state, KVM_CAP_ARM_MTE, 0);
|
||||||
|
if (ret) {
|
||||||
|
error_setg_errno(errp, -ret, "Failed to enable KVM_CAP_ARM_MTE");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: add proper migration support with MTE enabled */
|
||||||
|
error_setg(&mte_migration_blocker,
|
||||||
|
"Live migration disabled due to MTE enabled");
|
||||||
|
if (migrate_add_blocker(mte_migration_blocker, errp)) {
|
||||||
|
error_free(mte_migration_blocker);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
succeeded_to_enable = true;
|
||||||
|
}
|
||||||
|
if (succeeded_to_enable) {
|
||||||
|
object_property_set_bool(cpuobj, "has_mte", true, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -756,6 +756,11 @@ bool kvm_arm_steal_time_supported(void)
|
|||||||
return kvm_check_extension(kvm_state, KVM_CAP_STEAL_TIME);
|
return kvm_check_extension(kvm_state, KVM_CAP_STEAL_TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool kvm_arm_mte_supported(void)
|
||||||
|
{
|
||||||
|
return kvm_check_extension(kvm_state, KVM_CAP_ARM_MTE);
|
||||||
|
}
|
||||||
|
|
||||||
QEMU_BUILD_BUG_ON(KVM_ARM64_SVE_VQ_MIN != 1);
|
QEMU_BUILD_BUG_ON(KVM_ARM64_SVE_VQ_MIN != 1);
|
||||||
|
|
||||||
uint32_t kvm_arm_sve_get_vls(CPUState *cs)
|
uint32_t kvm_arm_sve_get_vls(CPUState *cs)
|
||||||
|
@ -313,6 +313,13 @@ bool kvm_arm_pmu_supported(void);
|
|||||||
*/
|
*/
|
||||||
bool kvm_arm_sve_supported(void);
|
bool kvm_arm_sve_supported(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kvm_arm_mte_supported:
|
||||||
|
*
|
||||||
|
* Returns: true if KVM can enable MTE, and false otherwise.
|
||||||
|
*/
|
||||||
|
bool kvm_arm_mte_supported(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kvm_arm_get_max_vm_ipa_size:
|
* kvm_arm_get_max_vm_ipa_size:
|
||||||
* @ms: Machine state handle
|
* @ms: Machine state handle
|
||||||
@ -377,6 +384,8 @@ void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa);
|
|||||||
|
|
||||||
int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level);
|
int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level);
|
||||||
|
|
||||||
|
void kvm_arm_enable_mte(Object *cpuobj, Error **errp);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -403,6 +412,11 @@ static inline bool kvm_arm_steal_time_supported(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool kvm_arm_mte_supported(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These functions should never actually be called without KVM support.
|
* These functions should never actually be called without KVM support.
|
||||||
*/
|
*/
|
||||||
@ -451,6 +465,11 @@ static inline uint32_t kvm_arm_sve_get_vls(CPUState *cs)
|
|||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void kvm_arm_enable_mte(Object *cpuobj, Error **errp)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline const char *gic_class_name(void)
|
static inline const char *gic_class_name(void)
|
||||||
|
152
target/arm/tcg/a64.decode
Normal file
152
target/arm/tcg/a64.decode
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
# AArch64 A64 allowed instruction decoding
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 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/>.
|
||||||
|
|
||||||
|
#
|
||||||
|
# This file is processed by scripts/decodetree.py
|
||||||
|
#
|
||||||
|
|
||||||
|
&r rn
|
||||||
|
&ri rd imm
|
||||||
|
&rri_sf rd rn imm sf
|
||||||
|
&i imm
|
||||||
|
|
||||||
|
|
||||||
|
### Data Processing - Immediate
|
||||||
|
|
||||||
|
# PC-rel addressing
|
||||||
|
|
||||||
|
%imm_pcrel 5:s19 29:2
|
||||||
|
@pcrel . .. ..... ................... rd:5 &ri imm=%imm_pcrel
|
||||||
|
|
||||||
|
ADR 0 .. 10000 ................... ..... @pcrel
|
||||||
|
ADRP 1 .. 10000 ................... ..... @pcrel
|
||||||
|
|
||||||
|
# Add/subtract (immediate)
|
||||||
|
|
||||||
|
%imm12_sh12 10:12 !function=shl_12
|
||||||
|
@addsub_imm sf:1 .. ...... . imm:12 rn:5 rd:5
|
||||||
|
@addsub_imm12 sf:1 .. ...... . ............ rn:5 rd:5 imm=%imm12_sh12
|
||||||
|
|
||||||
|
ADD_i . 00 100010 0 ............ ..... ..... @addsub_imm
|
||||||
|
ADD_i . 00 100010 1 ............ ..... ..... @addsub_imm12
|
||||||
|
ADDS_i . 01 100010 0 ............ ..... ..... @addsub_imm
|
||||||
|
ADDS_i . 01 100010 1 ............ ..... ..... @addsub_imm12
|
||||||
|
|
||||||
|
SUB_i . 10 100010 0 ............ ..... ..... @addsub_imm
|
||||||
|
SUB_i . 10 100010 1 ............ ..... ..... @addsub_imm12
|
||||||
|
SUBS_i . 11 100010 0 ............ ..... ..... @addsub_imm
|
||||||
|
SUBS_i . 11 100010 1 ............ ..... ..... @addsub_imm12
|
||||||
|
|
||||||
|
# Add/subtract (immediate with tags)
|
||||||
|
|
||||||
|
&rri_tag rd rn uimm6 uimm4
|
||||||
|
@addsub_imm_tag . .. ...... . uimm6:6 .. uimm4:4 rn:5 rd:5 &rri_tag
|
||||||
|
|
||||||
|
ADDG_i 1 00 100011 0 ...... 00 .... ..... ..... @addsub_imm_tag
|
||||||
|
SUBG_i 1 10 100011 0 ...... 00 .... ..... ..... @addsub_imm_tag
|
||||||
|
|
||||||
|
# Logical (immediate)
|
||||||
|
|
||||||
|
&rri_log rd rn sf dbm
|
||||||
|
@logic_imm_64 1 .. ...... dbm:13 rn:5 rd:5 &rri_log sf=1
|
||||||
|
@logic_imm_32 0 .. ...... 0 dbm:12 rn:5 rd:5 &rri_log sf=0
|
||||||
|
|
||||||
|
AND_i . 00 100100 . ...... ...... ..... ..... @logic_imm_64
|
||||||
|
AND_i . 00 100100 . ...... ...... ..... ..... @logic_imm_32
|
||||||
|
ORR_i . 01 100100 . ...... ...... ..... ..... @logic_imm_64
|
||||||
|
ORR_i . 01 100100 . ...... ...... ..... ..... @logic_imm_32
|
||||||
|
EOR_i . 10 100100 . ...... ...... ..... ..... @logic_imm_64
|
||||||
|
EOR_i . 10 100100 . ...... ...... ..... ..... @logic_imm_32
|
||||||
|
ANDS_i . 11 100100 . ...... ...... ..... ..... @logic_imm_64
|
||||||
|
ANDS_i . 11 100100 . ...... ...... ..... ..... @logic_imm_32
|
||||||
|
|
||||||
|
# Move wide (immediate)
|
||||||
|
|
||||||
|
&movw rd sf imm hw
|
||||||
|
@movw_64 1 .. ...... hw:2 imm:16 rd:5 &movw sf=1
|
||||||
|
@movw_32 0 .. ...... 0 hw:1 imm:16 rd:5 &movw sf=0
|
||||||
|
|
||||||
|
MOVN . 00 100101 .. ................ ..... @movw_64
|
||||||
|
MOVN . 00 100101 .. ................ ..... @movw_32
|
||||||
|
MOVZ . 10 100101 .. ................ ..... @movw_64
|
||||||
|
MOVZ . 10 100101 .. ................ ..... @movw_32
|
||||||
|
MOVK . 11 100101 .. ................ ..... @movw_64
|
||||||
|
MOVK . 11 100101 .. ................ ..... @movw_32
|
||||||
|
|
||||||
|
# Bitfield
|
||||||
|
|
||||||
|
&bitfield rd rn sf immr imms
|
||||||
|
@bitfield_64 1 .. ...... 1 immr:6 imms:6 rn:5 rd:5 &bitfield sf=1
|
||||||
|
@bitfield_32 0 .. ...... 0 0 immr:5 0 imms:5 rn:5 rd:5 &bitfield sf=0
|
||||||
|
|
||||||
|
SBFM . 00 100110 . ...... ...... ..... ..... @bitfield_64
|
||||||
|
SBFM . 00 100110 . ...... ...... ..... ..... @bitfield_32
|
||||||
|
BFM . 01 100110 . ...... ...... ..... ..... @bitfield_64
|
||||||
|
BFM . 01 100110 . ...... ...... ..... ..... @bitfield_32
|
||||||
|
UBFM . 10 100110 . ...... ...... ..... ..... @bitfield_64
|
||||||
|
UBFM . 10 100110 . ...... ...... ..... ..... @bitfield_32
|
||||||
|
|
||||||
|
# Extract
|
||||||
|
|
||||||
|
&extract rd rn rm imm sf
|
||||||
|
|
||||||
|
EXTR 1 00 100111 1 0 rm:5 imm:6 rn:5 rd:5 &extract sf=1
|
||||||
|
EXTR 0 00 100111 0 0 rm:5 0 imm:5 rn:5 rd:5 &extract sf=0
|
||||||
|
|
||||||
|
# Branches
|
||||||
|
|
||||||
|
%imm26 0:s26 !function=times_4
|
||||||
|
@branch . ..... .......................... &i imm=%imm26
|
||||||
|
|
||||||
|
B 0 00101 .......................... @branch
|
||||||
|
BL 1 00101 .......................... @branch
|
||||||
|
|
||||||
|
%imm19 5:s19 !function=times_4
|
||||||
|
&cbz rt imm sf nz
|
||||||
|
|
||||||
|
CBZ sf:1 011010 nz:1 ................... rt:5 &cbz imm=%imm19
|
||||||
|
|
||||||
|
%imm14 5:s14 !function=times_4
|
||||||
|
%imm31_19 31:1 19:5
|
||||||
|
&tbz rt imm nz bitpos
|
||||||
|
|
||||||
|
TBZ . 011011 nz:1 ..... .............. rt:5 &tbz imm=%imm14 bitpos=%imm31_19
|
||||||
|
|
||||||
|
B_cond 0101010 0 ................... 0 cond:4 imm=%imm19
|
||||||
|
|
||||||
|
BR 1101011 0000 11111 000000 rn:5 00000 &r
|
||||||
|
BLR 1101011 0001 11111 000000 rn:5 00000 &r
|
||||||
|
RET 1101011 0010 11111 000000 rn:5 00000 &r
|
||||||
|
|
||||||
|
&braz rn m
|
||||||
|
BRAZ 1101011 0000 11111 00001 m:1 rn:5 11111 &braz # BRAAZ, BRABZ
|
||||||
|
BLRAZ 1101011 0001 11111 00001 m:1 rn:5 11111 &braz # BLRAAZ, BLRABZ
|
||||||
|
|
||||||
|
&reta m
|
||||||
|
RETA 1101011 0010 11111 00001 m:1 11111 11111 &reta # RETAA, RETAB
|
||||||
|
|
||||||
|
&bra rn rm m
|
||||||
|
BRA 1101011 1000 11111 00001 m:1 rn:5 rm:5 &bra # BRAA, BRAB
|
||||||
|
BLRA 1101011 1001 11111 00001 m:1 rn:5 rm:5 &bra # BLRAA, BLRAB
|
||||||
|
|
||||||
|
ERET 1101011 0100 11111 000000 11111 00000
|
||||||
|
ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
|
||||||
|
|
||||||
|
# We don't need to decode DRPS because it always UNDEFs except when
|
||||||
|
# the processor is in halting debug state (which we don't implement).
|
||||||
|
# The pattern is listed here as documentation.
|
||||||
|
# DRPS 1101011 0101 11111 000000 11111 00000
|
@ -13,6 +13,7 @@ gen = [
|
|||||||
decodetree.process('a32-uncond.decode', extra_args: '--static-decode=disas_a32_uncond'),
|
decodetree.process('a32-uncond.decode', extra_args: '--static-decode=disas_a32_uncond'),
|
||||||
decodetree.process('t32.decode', extra_args: '--static-decode=disas_t32'),
|
decodetree.process('t32.decode', extra_args: '--static-decode=disas_t32'),
|
||||||
decodetree.process('t16.decode', extra_args: ['-w', '16', '--static-decode=disas_t16']),
|
decodetree.process('t16.decode', extra_args: ['-w', '16', '--static-decode=disas_t16']),
|
||||||
|
decodetree.process('a64.decode', extra_args: ['--static-decode=disas_a64']),
|
||||||
]
|
]
|
||||||
|
|
||||||
arm_ss.add(gen)
|
arm_ss.add(gen)
|
||||||
|
@ -6727,6 +6727,7 @@ void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
|
|||||||
intptr_t reg_off;
|
intptr_t reg_off;
|
||||||
SVEHostPage info;
|
SVEHostPage info;
|
||||||
target_ulong addr, in_page;
|
target_ulong addr, in_page;
|
||||||
|
ARMVectorReg scratch;
|
||||||
|
|
||||||
/* Skip to the first true predicate. */
|
/* Skip to the first true predicate. */
|
||||||
reg_off = find_next_active(vg, 0, reg_max, esz);
|
reg_off = find_next_active(vg, 0, reg_max, esz);
|
||||||
@ -6736,6 +6737,11 @@ void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Protect against overlap between vd and vm. */
|
||||||
|
if (unlikely(vd == vm)) {
|
||||||
|
vm = memcpy(&scratch, vm, reg_max);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Probe the first element, allowing faults.
|
* Probe the first element, allowing faults.
|
||||||
*/
|
*/
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -220,6 +220,11 @@ static inline int rsub_8(DisasContext *s, int x)
|
|||||||
return 8 - x;
|
return 8 - x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int shl_12(DisasContext *s, int x)
|
||||||
|
{
|
||||||
|
return x << 12;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int neon_3same_fp_size(DisasContext *s, int x)
|
static inline int neon_3same_fp_size(DisasContext *s, int x)
|
||||||
{
|
{
|
||||||
/* Convert 0==fp32, 1==fp16 into a MO_* value */
|
/* Convert 0==fp32, 1==fp16 into a MO_* value */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user