Merge tag 'pull-riscv-to-apply-20250519' of https://github.com/alistair23/qemu into staging

First RISC-V PR for 10.1

* Add support for RIMT to virt machine ACPI
* Don't allow PMP RLB to bypass rule privileges
* Fix checks on writes to pmpcfg in Smepmp MML mode
* Generate strided vector loads/stores with tcg nodes
* Improve Microchip Polarfire SoC customization
* Use tcg ops generation to emulate whole reg rvv loads/stores
* Expand the probe_pages helper function to handle probe flags
* Fix type conflict of GLib function pointers
* Fix endless translation loop on big endian systems
* Use tail pseudoinstruction for calling tail
* Fix some RISC-V vector instruction corner cases
* MAINTAINERS: Add common-user/host/riscv to RISC-V section
* Fix write_misa vs aligned next_pc
* KVM CSR fixes
* Virt machine memmap usage cleanup

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCgAdFiEEaukCtqfKh31tZZKWr3yVEwxTgBMFAmgqreUACgkQr3yVEwxT
# gBMurA//WAX4X+aNi6keCr20Ffv3gUnkPPeVewLLKOrZZ7h5oyWtRcSQvwDBSr8C
# vzs4Rf492iNljnbRj09KYkLB8Qq/QH2Ixl+IgG8ueJAHJ8WdG6HYrrDxcONwgL1K
# lQrRaDrMCFjU35uDlejfuvWWEmb4GKDMfj/wxs5wgNvnHgNhThmVaWQysx8KHYU+
# tevPQj5s4mvVGztGRSHIZQ8bth7oVUQR5CsKngGEmVLS2L6yVYTUN5ZhB5g6Ikrq
# jKn44cROLfvv+0zPB9Lgu7eKauA/h8SckjCV+dGoMDB5J5M/TvwS118VHOjNVEQZ
# yLx6/BdLp3SRPwbvu9jn6vjms95iZSJXXdnY+Cg4MqAbuIRQK66n6Zoa3LjbEk2U
# zsf03uYUla9CBs6VQJmF7yjks3AbWokpZ9WSsGIcHJgXe8pEUeEsWOgiBhifJ5bD
# Hljlkiw1gHCjhtc2aWEH0aBwM7896lmdct70JmkjQ4uZKkFSqJ8y5l0Gm3lvgvdO
# OEPyMbZ6hSO4UZovcpeFtOoXteCUVthvqz0mADoQAtG+2qoX0k+9h8v305fhlti+
# bXJfu1QPsQqCYMrv4ZSTbRg0uC8m7CHnA+coC0XnCcMwEk9ZBl373/cnQYWsmqo8
# lxZmXLvpaN9CEzjOmZhXUsOvIqAJdM1sYPWnoXJ71t7mn4QEOPA=
# =dFjk
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 19 May 2025 00:04:53 EDT
# gpg:                using RSA key 6AE902B6A7CA877D6D659296AF7C95130C538013
# gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 6AE9 02B6 A7CA 877D 6D65  9296 AF7C 9513 0C53 8013

* tag 'pull-riscv-to-apply-20250519' of https://github.com/alistair23/qemu: (56 commits)
  hw/riscv/virt.c: remove 'long' casts in fmt strings
  hw/riscv/virt.c: use s->memmap in finalize_fdt() functions
  hw/riscv/virt.c: use s->memmap in create_fdt_virtio()
  hw/riscv/virt.c: use s->memmap in create_fdt_sockets() path
  hw/riscv/virt.c: use s->memmap in create_fdt() path
  hw/riscv/virt.c: add 'base' arg in create_fw_cfg()
  hw/riscv/virt.c: use s->memmap in virt_machine_done()
  hw/riscv/virt.c: remove trivial virt_memmap references
  hw/riscv/virt.c: enforce s->memmap use in machine_init()
  target/riscv/kvm: add scounteren CSR
  target/riscv/kvm: read/write KVM regs via env size
  target/riscv/kvm: add senvcfg CSR
  target/riscv/kvm: do not read unavailable CSRs
  target/riscv/kvm: add kvm_csr_cfgs[]
  target/riscv/kvm: turn kvm_riscv_reg_id_ulong() into a macro
  target/riscv/kvm: turn u32/u64 reg functions into macros
  target/riscv/kvm: fix leak in kvm_riscv_init_multiext_cfg()
  target/riscv/kvm: minor fixes/tweaks
  target/riscv: Fix write_misa vs aligned next_pc
  target/riscv: Move insn_len to internals.h
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi
2025-05-19 14:00:54 -04:00
22 changed files with 1573 additions and 758 deletions
+1
View File
@@ -328,6 +328,7 @@ F: include/hw/char/riscv_htif.h
F: include/hw/riscv/
F: linux-user/host/riscv32/
F: linux-user/host/riscv64/
F: common-user/host/riscv*
F: tests/functional/test_riscv*
F: tests/tcg/riscv64/
+2 -2
View File
@@ -69,11 +69,11 @@ safe_syscall_end:
/* code path setting errno */
0: neg a0, a0
j safe_syscall_set_errno_tail
tail safe_syscall_set_errno_tail
/* code path when we didn't execute the syscall */
2: li a0, QEMU_ERESTARTSYS
j safe_syscall_set_errno_tail
tail safe_syscall_set_errno_tail
.cfi_endproc
.size safe_syscall_base, .-safe_syscall_base
+44 -82
View File
@@ -5,10 +5,10 @@ Microchip PolarFire SoC Icicle Kit integrates a PolarFire SoC, with one
SiFive's E51 plus four U54 cores and many on-chip peripherals and an FPGA.
For more details about Microchip PolarFire SoC, please see:
https://www.microsemi.com/product-directory/soc-fpgas/5498-polarfire-soc-fpga
https://www.microchip.com/en-us/products/fpgas-and-plds/system-on-chip-fpgas/polarfire-soc-fpgas
The Icicle Kit board information can be found here:
https://www.microsemi.com/existing-parts/parts/152514
https://www.microchip.com/en-us/development-tool/mpfs-icicle-kit-es
Supported devices
-----------------
@@ -26,95 +26,48 @@ The ``microchip-icicle-kit`` machine supports the following devices:
* 2 GEM Ethernet controllers
* 1 SDHC storage controller
The memory is set to 1537 MiB by default. A sanity check on RAM size is
performed in the machine init routine to prompt user to increase the RAM size
to > 1537 MiB when less than 1537 MiB RAM is detected.
Boot options
------------
The ``microchip-icicle-kit`` machine can start using the standard -bios
functionality for loading its BIOS image, aka Hart Software Services (HSS_).
HSS loads the second stage bootloader U-Boot from an SD card. Then a kernel
can be loaded from U-Boot. It also supports direct kernel booting via the
-kernel option along with the device tree blob via -dtb. When direct kernel
boot is used, the OpenSBI fw_dynamic BIOS image is used to boot a payload
like U-Boot or OS kernel directly.
The ``microchip-icicle-kit`` machine provides some options to run a firmware
(BIOS) or a kernel image. QEMU follows below truth table to select the
firmware:
The user provided DTB should have the following requirements:
* The /cpus node should contain at least one subnode for E51 and the number
of subnodes should match QEMU's ``-smp`` option
* The /memory reg size should match QEMUs selected ram_size via ``-m``
* Should contain a node for the CLINT device with a compatible string
"riscv,clint0"
QEMU follows below truth table to select which payload to execute:
===== ========== ========== =======
-bios -kernel -dtb payload
===== ========== ========== =======
N N don't care HSS
Y don't care don't care HSS
N Y Y kernel
===== ========== ========== =======
The memory is set to 1537 MiB by default which is the minimum required high
memory size by HSS. A sanity check on ram size is performed in the machine
init routine to prompt user to increase the RAM size to > 1537 MiB when less
than 1537 MiB ram is detected.
Running HSS
-----------
HSS 2020.12 release is tested at the time of writing. To build an HSS image
that can be booted by the ``microchip-icicle-kit`` machine, type the following
in the HSS source tree:
.. code-block:: bash
$ export CROSS_COMPILE=riscv64-linux-
$ cp boards/mpfs-icicle-kit-es/def_config .config
$ make BOARD=mpfs-icicle-kit-es
Download the official SD card image released by Microchip and prepare it for
QEMU usage:
.. code-block:: bash
$ wget ftp://ftpsoc.microsemi.com/outgoing/core-image-minimal-dev-icicle-kit-es-sd-20201009141623.rootfs.wic.gz
$ gunzip core-image-minimal-dev-icicle-kit-es-sd-20201009141623.rootfs.wic.gz
$ qemu-img resize core-image-minimal-dev-icicle-kit-es-sd-20201009141623.rootfs.wic 4G
Then we can boot the machine by:
.. code-block:: bash
$ qemu-system-riscv64 -M microchip-icicle-kit -smp 5 \
-bios path/to/hss.bin -sd path/to/sdcard.img \
-nic user,model=cadence_gem \
-nic tap,ifname=tap,model=cadence_gem,script=no \
-display none -serial stdio \
-chardev socket,id=serial1,path=serial1.sock,server=on,wait=on \
-serial chardev:serial1
With above command line, current terminal session will be used for the first
serial port. Open another terminal window, and use ``minicom`` to connect the
second serial port.
.. code-block:: bash
$ minicom -D unix\#serial1.sock
HSS output is on the first serial port (stdio) and U-Boot outputs on the
second serial port. U-Boot will automatically load the Linux kernel from
the SD card image.
============= =========== ======================================
-bios -kernel firmware
============= =========== ======================================
none N this is an error
none Y the kernel image
NULL, default N hss.bin
NULL, default Y opensbi-riscv64-generic-fw_dynamic.bin
other don't care the BIOS image
============= =========== ======================================
Direct Kernel Boot
------------------
Sometimes we just want to test booting a new kernel, and transforming the
kernel image to the format required by the HSS bootflow is tedious. We can
use '-kernel' for direct kernel booting just like other RISC-V machines do.
Use the ``-kernel`` option to directly run a kernel image. When a direct
kernel boot is requested, a device tree blob may be specified via the ``-dtb``
option. Unlike other QEMU machines, this machine does not generate a device
tree for the kernel. It shall be provided by the user. The user provided DTB
should meet the following requirements:
In this mode, the OpenSBI fw_dynamic BIOS image for 'generic' platform is
used to boot an S-mode payload like U-Boot or OS kernel directly.
* The ``/cpus`` node should contain at least one subnode for E51 and the number
of subnodes should match QEMU's ``-smp`` option.
* The ``/memory`` reg size should match QEMUs selected RAM size via the ``-m``
option.
* It should contain a node for the CLINT device with a compatible string
"riscv,clint0".
When ``-bios`` is not specified or set to ``default``, the OpenSBI
``fw_dynamic`` BIOS image for the ``generic`` platform is used to boot an
S-mode payload like U-Boot or OS kernel directly.
For example, the following commands show building a U-Boot image from U-Boot
mainline v2021.07 for the Microchip Icicle Kit board:
@@ -146,4 +99,13 @@ CAVEATS:
``u-boot.bin`` has to be used which does contain one. To use the ELF image,
we need to change to CONFIG_OF_EMBED or CONFIG_OF_PRIOR_STAGE.
Running HSS
-----------
The machine ``microchip-icicle-kit`` used to run the Hart Software Services
(HSS_), however, the HSS development progressed and the QEMU machine
implementation lacks behind. Currently, running the HSS no longer works.
There is missing support in the clock and memory controller devices. In
particular, reading from the SD card does not work.
.. _HSS: https://github.com/polarfire-soc/hart-software-services
+7
View File
@@ -27,7 +27,9 @@
#include "hw/irq.h"
#include "hw/sysbus.h"
#include "hw/misc/mchp_pfsoc_sysreg.h"
#include "system/runstate.h"
#define MSS_RESET_CR 0x18
#define ENVM_CR 0xb8
#define MESSAGE_INT 0x118c
@@ -56,6 +58,11 @@ static void mchp_pfsoc_sysreg_write(void *opaque, hwaddr offset,
{
MchpPfSoCSysregState *s = opaque;
switch (offset) {
case MSS_RESET_CR:
if (value == 0xdead) {
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
}
break;
case MESSAGE_INT:
qemu_irq_lower(s->irq);
break;
+113 -40
View File
@@ -39,6 +39,7 @@
#include "qemu/units.h"
#include "qemu/cutils.h"
#include "qapi/error.h"
#include "qapi/visitor.h"
#include "hw/boards.h"
#include "hw/loader.h"
#include "hw/sysbus.h"
@@ -61,9 +62,6 @@
#define BIOS_FILENAME "hss.bin"
#define RESET_VECTOR 0x20220000
/* CLINT timebase frequency */
#define CLINT_TIMEBASE_FREQ 1000000
/* GEM version */
#define GEM_REVISION 0x0107010c
@@ -193,6 +191,7 @@ static void microchip_pfsoc_soc_instance_init(Object *obj)
static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
{
MachineState *ms = MACHINE(qdev_get_machine());
MicrochipIcicleKitState *iks = MICROCHIP_ICICLE_KIT_MACHINE(ms);
MicrochipPFSoCState *s = MICROCHIP_PFSOC(dev);
const MemMapEntry *memmap = microchip_pfsoc_memmap;
MemoryRegion *system_memory = get_system_memory();
@@ -253,7 +252,7 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp)
memmap[MICROCHIP_PFSOC_CLINT].base + RISCV_ACLINT_SWI_SIZE,
RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus,
RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
CLINT_TIMEBASE_FREQ, false);
iks->clint_timebase_freq, false);
/* L2 cache controller */
create_unimplemented_device("microchip.pfsoc.l2cc",
@@ -516,7 +515,6 @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
uint64_t mem_low_size, mem_high_size;
hwaddr firmware_load_addr;
const char *firmware_name;
bool kernel_as_payload = false;
target_ulong firmware_end_addr, kernel_start_addr;
uint64_t kernel_entry;
uint64_t fdt_load_addr;
@@ -579,45 +577,50 @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
}
/*
* We follow the following table to select which payload we execute.
* We follow the following table to select which firmware we use.
*
* -bios | -kernel | payload
* -------+------------+--------
* N | N | HSS
* Y | don't care | HSS
* N | Y | kernel
*
* This ensures backwards compatibility with how we used to expose -bios
* to users but allows them to run through direct kernel booting as well.
*
* When -kernel is used for direct boot, -dtb must be present to provide
* a valid device tree for the board, as we don't generate device tree.
* -bios | -kernel | firmware
* --------------+------------+--------
* none | N | error
* none | Y | kernel
* NULL, default | N | BIOS_FILENAME
* NULL, default | Y | RISCV64_BIOS_BIN
* other | don't care | other
*/
if (machine->kernel_filename && machine->dtb) {
int fdt_size;
machine->fdt = load_device_tree(machine->dtb, &fdt_size);
if (!machine->fdt) {
error_report("load_device_tree() failed");
if (machine->firmware && !strcmp(machine->firmware, "none")) {
if (!machine->kernel_filename) {
error_report("for -bios none, a kernel is required");
exit(1);
}
firmware_name = RISCV64_BIOS_BIN;
firmware_load_addr = memmap[MICROCHIP_PFSOC_DRAM_LO].base;
kernel_as_payload = true;
}
if (!kernel_as_payload) {
firmware_name = BIOS_FILENAME;
firmware_name = NULL;
firmware_load_addr = RESET_VECTOR;
} else if (!machine->firmware || !strcmp(machine->firmware, "default")) {
if (machine->kernel_filename) {
firmware_name = RISCV64_BIOS_BIN;
firmware_load_addr = memmap[MICROCHIP_PFSOC_DRAM_LO].base;
} else {
firmware_name = BIOS_FILENAME;
firmware_load_addr = RESET_VECTOR;
}
} else {
firmware_name = machine->firmware;
firmware_load_addr = RESET_VECTOR;
}
/* Load the firmware */
firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
&firmware_load_addr, NULL);
/* Load the firmware if necessary */
firmware_end_addr = firmware_load_addr;
if (firmware_name) {
char *filename = riscv_find_firmware(firmware_name, NULL);
if (filename) {
firmware_end_addr = riscv_load_firmware(filename,
&firmware_load_addr, NULL);
g_free(filename);
}
}
riscv_boot_info_init(&boot_info, &s->soc.u_cpus);
if (kernel_as_payload) {
if (machine->kernel_filename) {
kernel_start_addr = riscv_calc_kernel_start_addr(&boot_info,
firmware_end_addr);
@@ -625,20 +628,82 @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
true, NULL);
kernel_entry = boot_info.image_low_addr;
/* Compute the fdt load address in dram */
fdt_load_addr = riscv_compute_fdt_addr(memmap[MICROCHIP_PFSOC_DRAM_LO].base,
memmap[MICROCHIP_PFSOC_DRAM_LO].size,
machine, &boot_info);
riscv_load_fdt(fdt_load_addr, machine->fdt);
if (machine->dtb) {
int fdt_size;
machine->fdt = load_device_tree(machine->dtb, &fdt_size);
if (!machine->fdt) {
error_report("load_device_tree() failed");
exit(1);
}
/* Compute the FDT load address in DRAM */
hwaddr kernel_ram_base = memmap[MICROCHIP_PFSOC_DRAM_LO].base;
hwaddr kernel_ram_size = memmap[MICROCHIP_PFSOC_DRAM_LO].size;
if (kernel_entry - kernel_ram_base >= kernel_ram_size) {
kernel_ram_base = memmap[MICROCHIP_PFSOC_DRAM_HI].base;
kernel_ram_size = mem_high_size;
}
fdt_load_addr = riscv_compute_fdt_addr(kernel_ram_base, kernel_ram_size,
machine, &boot_info);
riscv_load_fdt(fdt_load_addr, machine->fdt);
} else {
warn_report_once("The QEMU microchip-icicle-kit machine does not "
"generate a device tree, so no device tree is "
"being provided to the guest.");
fdt_load_addr = 0;
}
hwaddr start_addr;
if (firmware_name) {
start_addr = firmware_load_addr;
} else {
start_addr = kernel_entry;
}
/* Load the reset vector */
riscv_setup_rom_reset_vec(machine, &s->soc.u_cpus, firmware_load_addr,
riscv_setup_rom_reset_vec(machine, &s->soc.u_cpus, start_addr,
memmap[MICROCHIP_PFSOC_ENVM_DATA].base,
memmap[MICROCHIP_PFSOC_ENVM_DATA].size,
kernel_entry, fdt_load_addr);
}
}
static void microchip_icicle_kit_set_clint_timebase_freq(Object *obj,
Visitor *v,
const char *name,
void *opaque,
Error **errp)
{
MicrochipIcicleKitState *s = MICROCHIP_ICICLE_KIT_MACHINE(obj);
uint32_t value;
if (!visit_type_uint32(v, name, &value, errp)) {
return;
}
s->clint_timebase_freq = value;
}
static void microchip_icicle_kit_get_clint_timebase_freq(Object *obj,
Visitor *v,
const char *name,
void *opaque,
Error **errp)
{
MicrochipIcicleKitState *s = MICROCHIP_ICICLE_KIT_MACHINE(obj);
uint32_t value = s->clint_timebase_freq;
visit_type_uint32(v, name, &value, errp);
}
static void microchip_icicle_kit_machine_instance_init(Object *obj)
{
MicrochipIcicleKitState *m = MICROCHIP_ICICLE_KIT_MACHINE(obj);
m->clint_timebase_freq = 1000000;
}
static void microchip_icicle_kit_machine_class_init(ObjectClass *oc,
const void *data)
{
@@ -661,12 +726,20 @@ static void microchip_icicle_kit_machine_class_init(ObjectClass *oc,
* See memory_tests() in mss_ddr.c in the HSS source code.
*/
mc->default_ram_size = 1537 * MiB;
object_class_property_add(oc, "clint-timebase-frequency", "uint32_t",
microchip_icicle_kit_get_clint_timebase_freq,
microchip_icicle_kit_set_clint_timebase_freq,
NULL, NULL);
object_class_property_set_description(oc, "clint-timebase-frequency",
"Set CLINT timebase frequency in Hz.");
}
static const TypeInfo microchip_icicle_kit_machine_typeinfo = {
.name = MACHINE_TYPE_NAME("microchip-icicle-kit"),
.parent = TYPE_MACHINE,
.class_init = microchip_icicle_kit_machine_class_init,
.instance_init = microchip_icicle_kit_machine_instance_init,
.instance_size = sizeof(MicrochipIcicleKitState),
};
+6 -3
View File
@@ -72,7 +72,7 @@ static void csr_call(char *cmd, uint64_t cpu_num, int csrno, uint64_t *val)
ret = riscv_csrr(env, csrno, (target_ulong *)val);
} else if (strcmp(cmd, "set_csr") == 0) {
ret = riscv_csrrw(env, csrno, NULL, *(target_ulong *)val,
MAKE_64BIT_MASK(0, TARGET_LONG_BITS));
MAKE_64BIT_MASK(0, TARGET_LONG_BITS), 0);
}
g_assert(ret == RISCV_EXCP_NONE);
@@ -104,8 +104,11 @@ static bool csr_qtest_callback(CharBackend *chr, gchar **words)
static void riscv_cpu_register_csr_qtest_callback(void)
{
static GOnce once;
g_once(&once, (GThreadFunc)qtest_set_command_cb, csr_qtest_callback);
static bool first = true;
if (first) {
first = false;
qtest_set_command_cb(csr_qtest_callback);
}
}
#endif
+215
View File
@@ -198,6 +198,32 @@ acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap,
aml_append(scope, dev);
}
/*
* Add DSDT entry for the IOMMU platform device.
* ACPI ID for IOMMU is defined in the section 6.2 of RISC-V BRS spec.
* https://github.com/riscv-non-isa/riscv-brs/releases/download/v0.8/riscv-brs-spec.pdf
*/
static void acpi_dsdt_add_iommu_sys(Aml *scope, const MemMapEntry *iommu_memmap,
uint32_t iommu_irq)
{
uint32_t i;
Aml *dev = aml_device("IMU0");
aml_append(dev, aml_name_decl("_HID", aml_string("RSCV0004")));
aml_append(dev, aml_name_decl("_UID", aml_int(0)));
Aml *crs = aml_resource_template();
aml_append(crs, aml_memory32_fixed(iommu_memmap->base,
iommu_memmap->size, AML_READ_WRITE));
for (i = iommu_irq; i < iommu_irq + 4; i++) {
aml_append(crs, aml_interrupt(AML_CONSUMER, AML_EDGE, AML_ACTIVE_LOW,
AML_EXCLUSIVE, &i, 1));
}
aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(scope, dev);
}
/*
* Serial Port Console Redirection Table (SPCR)
* Rev: 1.10
@@ -450,6 +476,9 @@ static void build_dsdt(GArray *table_data,
}
acpi_dsdt_add_uart(scope, &memmap[VIRT_UART0], UART0_IRQ);
if (virt_is_iommu_sys_enabled(s)) {
acpi_dsdt_add_iommu_sys(scope, &memmap[VIRT_IOMMU_SYS], IOMMU_SYS_IRQ);
}
if (socket_count == 1) {
virtio_acpi_dsdt_add(scope, memmap[VIRT_VIRTIO].base,
@@ -602,6 +631,187 @@ static void build_madt(GArray *table_data,
acpi_table_end(linker, &table);
}
#define ID_MAPPING_ENTRY_SIZE 20
#define IOMMU_ENTRY_SIZE 40
#define RISCV_INTERRUPT_WIRE_OFFSSET 40
#define ROOT_COMPLEX_ENTRY_SIZE 20
#define RIMT_NODE_OFFSET 48
/*
* ID Mapping Structure
*/
static void build_rimt_id_mapping(GArray *table_data, uint32_t source_id_base,
uint32_t num_ids, uint32_t dest_id_base)
{
/* Source ID Base */
build_append_int_noprefix(table_data, source_id_base, 4);
/* Number of IDs */
build_append_int_noprefix(table_data, num_ids, 4);
/* Destination Device ID Base */
build_append_int_noprefix(table_data, source_id_base, 4);
/* Destination IOMMU Offset */
build_append_int_noprefix(table_data, dest_id_base, 4);
/* Flags */
build_append_int_noprefix(table_data, 0, 4);
}
struct AcpiRimtIdMapping {
uint32_t source_id_base;
uint32_t num_ids;
};
typedef struct AcpiRimtIdMapping AcpiRimtIdMapping;
/* Build the rimt ID mapping to IOMMU for a given PCI host bridge */
static int rimt_host_bridges(Object *obj, void *opaque)
{
GArray *idmap_blob = opaque;
if (object_dynamic_cast(obj, TYPE_PCI_HOST_BRIDGE)) {
PCIBus *bus = PCI_HOST_BRIDGE(obj)->bus;
if (bus && !pci_bus_bypass_iommu(bus)) {
int min_bus, max_bus;
pci_bus_range(bus, &min_bus, &max_bus);
AcpiRimtIdMapping idmap = {
.source_id_base = min_bus << 8,
.num_ids = (max_bus - min_bus + 1) << 8,
};
g_array_append_val(idmap_blob, idmap);
}
}
return 0;
}
static int rimt_idmap_compare(gconstpointer a, gconstpointer b)
{
AcpiRimtIdMapping *idmap_a = (AcpiRimtIdMapping *)a;
AcpiRimtIdMapping *idmap_b = (AcpiRimtIdMapping *)b;
return idmap_a->source_id_base - idmap_b->source_id_base;
}
/*
* RISC-V IO Mapping Table (RIMT)
* https://github.com/riscv-non-isa/riscv-acpi-rimt/releases/download/v0.99/rimt-spec.pdf
*/
static void build_rimt(GArray *table_data, BIOSLinker *linker,
RISCVVirtState *s)
{
int i, nb_nodes, rc_mapping_count;
size_t node_size, iommu_offset = 0;
uint32_t id = 0;
g_autoptr(GArray) iommu_idmaps = g_array_new(false, true,
sizeof(AcpiRimtIdMapping));
AcpiTable table = { .sig = "RIMT", .rev = 1, .oem_id = s->oem_id,
.oem_table_id = s->oem_table_id };
acpi_table_begin(&table, table_data);
object_child_foreach_recursive(object_get_root(),
rimt_host_bridges, iommu_idmaps);
/* Sort the ID mapping by Source ID Base*/
g_array_sort(iommu_idmaps, rimt_idmap_compare);
nb_nodes = 2; /* RC, IOMMU */
rc_mapping_count = iommu_idmaps->len;
/* Number of RIMT Nodes */
build_append_int_noprefix(table_data, nb_nodes, 4);
/* Offset to Array of RIMT Nodes */
build_append_int_noprefix(table_data, RIMT_NODE_OFFSET, 4);
build_append_int_noprefix(table_data, 0, 4); /* Reserved */
iommu_offset = table_data->len - table.table_offset;
/* IOMMU Device Structure */
build_append_int_noprefix(table_data, 0, 1); /* Type - IOMMU*/
build_append_int_noprefix(table_data, 1, 1); /* Revision */
node_size = IOMMU_ENTRY_SIZE;
build_append_int_noprefix(table_data, node_size, 2); /* Length */
build_append_int_noprefix(table_data, 0, 2); /* Reserved */
build_append_int_noprefix(table_data, id++, 2); /* ID */
if (virt_is_iommu_sys_enabled(s)) {
/* Hardware ID */
build_append_int_noprefix(table_data, 'R', 1);
build_append_int_noprefix(table_data, 'S', 1);
build_append_int_noprefix(table_data, 'C', 1);
build_append_int_noprefix(table_data, 'V', 1);
build_append_int_noprefix(table_data, '0', 1);
build_append_int_noprefix(table_data, '0', 1);
build_append_int_noprefix(table_data, '0', 1);
build_append_int_noprefix(table_data, '4', 1);
/* Base Address */
build_append_int_noprefix(table_data,
s->memmap[VIRT_IOMMU_SYS].base, 8);
build_append_int_noprefix(table_data, 0, 4); /* Flags */
} else {
/* Hardware ID */
build_append_int_noprefix(table_data, '0', 1);
build_append_int_noprefix(table_data, '0', 1);
build_append_int_noprefix(table_data, '1', 1);
build_append_int_noprefix(table_data, '0', 1);
build_append_int_noprefix(table_data, '0', 1);
build_append_int_noprefix(table_data, '0', 1);
build_append_int_noprefix(table_data, '1', 1);
build_append_int_noprefix(table_data, '4', 1);
build_append_int_noprefix(table_data, 0, 8); /* Base Address */
build_append_int_noprefix(table_data, 1, 4); /* Flags */
}
build_append_int_noprefix(table_data, 0, 4); /* Proximity Domain */
build_append_int_noprefix(table_data, 0, 2); /* PCI Segment number */
/* PCIe B/D/F */
if (virt_is_iommu_sys_enabled(s)) {
build_append_int_noprefix(table_data, 0, 2);
} else {
build_append_int_noprefix(table_data, s->pci_iommu_bdf, 2);
}
/* Number of interrupt wires */
build_append_int_noprefix(table_data, 0, 2);
/* Interrupt wire array offset */
build_append_int_noprefix(table_data, RISCV_INTERRUPT_WIRE_OFFSSET, 2);
/* PCIe Root Complex Node */
build_append_int_noprefix(table_data, 1, 1); /* Type */
build_append_int_noprefix(table_data, 1, 1); /* Revision */
node_size = ROOT_COMPLEX_ENTRY_SIZE +
ID_MAPPING_ENTRY_SIZE * rc_mapping_count;
build_append_int_noprefix(table_data, node_size, 2); /* Length */
build_append_int_noprefix(table_data, 0, 2); /* Reserved */
build_append_int_noprefix(table_data, id++, 2); /* ID */
build_append_int_noprefix(table_data, 0, 4); /* Flags */
build_append_int_noprefix(table_data, 0, 2); /* Reserved */
/* PCI Segment number */
build_append_int_noprefix(table_data, 0, 2);
/* ID mapping array offset */
build_append_int_noprefix(table_data, ROOT_COMPLEX_ENTRY_SIZE, 2);
/* Number of ID mappings */
build_append_int_noprefix(table_data, rc_mapping_count, 2);
/* Output Reference */
AcpiRimtIdMapping *range;
/* ID mapping array */
for (i = 0; i < iommu_idmaps->len; i++) {
range = &g_array_index(iommu_idmaps, AcpiRimtIdMapping, i);
if (virt_is_iommu_sys_enabled(s)) {
range->source_id_base = 0;
} else {
range->source_id_base = s->pci_iommu_bdf + 1;
}
range->num_ids = 0xffff - s->pci_iommu_bdf;
build_rimt_id_mapping(table_data, range->source_id_base,
range->num_ids, iommu_offset);
}
acpi_table_end(linker, &table);
}
/*
* ACPI spec, Revision 6.5+
* 5.2.16 System Resource Affinity Table (SRAT)
@@ -679,6 +889,11 @@ static void virt_acpi_build(RISCVVirtState *s, AcpiBuildTables *tables)
acpi_add_table(table_offsets, tables_blob);
build_rhct(tables_blob, tables->linker, s);
if (virt_is_iommu_sys_enabled(s) || s->pci_iommu_bdf) {
acpi_add_table(table_offsets, tables_blob);
build_rimt(tables_blob, tables->linker, s);
}
acpi_add_table(table_offsets, tables_blob);
spcr_setup(tables_blob, tables->linker, s);
+141 -132
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -67,6 +67,7 @@ typedef struct MicrochipIcicleKitState {
MachineState parent_obj;
/*< public >*/
uint32_t clint_timebase_freq;
MicrochipPFSoCState soc;
} MicrochipIcicleKitState;
+1
View File
@@ -63,6 +63,7 @@ struct RISCVVirtState {
const MemMapEntry *memmap;
struct GPEXHost *gpex_host;
OnOffAuto iommu_sys;
uint16_t pci_iommu_bdf;
};
enum {
+9 -7
View File
@@ -75,6 +75,7 @@ const char *riscv_get_misa_ext_name(uint32_t bit);
const char *riscv_get_misa_ext_description(uint32_t bit);
#define CPU_CFG_OFFSET(_prop) offsetof(struct RISCVCPUConfig, _prop)
#define ENV_CSR_OFFSET(_csr) offsetof(CPURISCVState, _csr)
typedef struct riscv_cpu_profile {
struct riscv_cpu_profile *u_parent;
@@ -813,8 +814,8 @@ RISCVException riscv_csrr(CPURISCVState *env, int csrno,
target_ulong *ret_value);
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask);
target_ulong *ret_value, target_ulong new_value,
target_ulong write_mask, uintptr_t ra);
RISCVException riscv_csrrw_debug(CPURISCVState *env, int csrno,
target_ulong *ret_value,
target_ulong new_value,
@@ -823,13 +824,13 @@ RISCVException riscv_csrrw_debug(CPURISCVState *env, int csrno,
static inline void riscv_csr_write(CPURISCVState *env, int csrno,
target_ulong val)
{
riscv_csrrw(env, csrno, NULL, val, MAKE_64BIT_MASK(0, TARGET_LONG_BITS));
riscv_csrrw(env, csrno, NULL, val, MAKE_64BIT_MASK(0, TARGET_LONG_BITS), 0);
}
static inline target_ulong riscv_csr_read(CPURISCVState *env, int csrno)
{
target_ulong val = 0;
riscv_csrrw(env, csrno, &val, 0, 0);
riscv_csrrw(env, csrno, &val, 0, 0, 0);
return val;
}
@@ -838,7 +839,8 @@ typedef RISCVException (*riscv_csr_predicate_fn)(CPURISCVState *env,
typedef RISCVException (*riscv_csr_read_fn)(CPURISCVState *env, int csrno,
target_ulong *ret_value);
typedef RISCVException (*riscv_csr_write_fn)(CPURISCVState *env, int csrno,
target_ulong new_value);
target_ulong new_value,
uintptr_t ra);
typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
target_ulong *ret_value,
target_ulong new_value,
@@ -847,8 +849,8 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
Int128 *ret_value);
RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
Int128 *ret_value,
Int128 new_value, Int128 write_mask);
Int128 *ret_value, Int128 new_value,
Int128 write_mask, uintptr_t ra);
typedef RISCVException (*riscv_csr_read128_fn)(CPURISCVState *env, int csrno,
Int128 *ret_value);
+4 -2
View File
@@ -1566,9 +1566,11 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
target_ulong *pte_pa = qemu_map_ram_ptr(mr->ram_block, addr1);
target_ulong old_pte;
if (riscv_cpu_sxl(env) == MXL_RV32) {
old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, pte, updated_pte);
old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, cpu_to_le32(pte), cpu_to_le32(updated_pte));
old_pte = le32_to_cpu(old_pte);
} else {
old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
old_pte = qatomic_cmpxchg(pte_pa, cpu_to_le64(pte), cpu_to_le64(updated_pte));
old_pte = le64_to_cpu(old_pte);
}
if (old_pte != pte) {
goto restart;
+148 -130
View File
File diff suppressed because it is too large Load Diff
+9 -9
View File
@@ -703,14 +703,14 @@ vfredmax_vs 000111 . ..... ..... 001 ..... 1010111 @r_vm
# Vector widening ordered and unordered float reduction sum
vfwredusum_vs 110001 . ..... ..... 001 ..... 1010111 @r_vm
vfwredosum_vs 110011 . ..... ..... 001 ..... 1010111 @r_vm
vmand_mm 011001 - ..... ..... 010 ..... 1010111 @r
vmnand_mm 011101 - ..... ..... 010 ..... 1010111 @r
vmandn_mm 011000 - ..... ..... 010 ..... 1010111 @r
vmxor_mm 011011 - ..... ..... 010 ..... 1010111 @r
vmor_mm 011010 - ..... ..... 010 ..... 1010111 @r
vmnor_mm 011110 - ..... ..... 010 ..... 1010111 @r
vmorn_mm 011100 - ..... ..... 010 ..... 1010111 @r
vmxnor_mm 011111 - ..... ..... 010 ..... 1010111 @r
vmand_mm 011001 1 ..... ..... 010 ..... 1010111 @r
vmnand_mm 011101 1 ..... ..... 010 ..... 1010111 @r
vmandn_mm 011000 1 ..... ..... 010 ..... 1010111 @r
vmxor_mm 011011 1 ..... ..... 010 ..... 1010111 @r
vmor_mm 011010 1 ..... ..... 010 ..... 1010111 @r
vmnor_mm 011110 1 ..... ..... 010 ..... 1010111 @r
vmorn_mm 011100 1 ..... ..... 010 ..... 1010111 @r
vmxnor_mm 011111 1 ..... ..... 010 ..... 1010111 @r
vcpop_m 010000 . ..... 10000 010 ..... 1010111 @r2_vm
vfirst_m 010000 . ..... 10001 010 ..... 1010111 @r2_vm
vmsbf_m 010100 . ..... 00001 010 ..... 1010111 @r2_vm
@@ -732,7 +732,7 @@ vrgather_vv 001100 . ..... ..... 000 ..... 1010111 @r_vm
vrgatherei16_vv 001110 . ..... ..... 000 ..... 1010111 @r_vm
vrgather_vx 001100 . ..... ..... 100 ..... 1010111 @r_vm
vrgather_vi 001100 . ..... ..... 011 ..... 1010111 @r_vm
vcompress_vm 010111 - ..... ..... 010 ..... 1010111 @r
vcompress_vm 010111 1 ..... ..... 010 ..... 1010111 @r
vmv1r_v 100111 1 ..... 00000 011 ..... 1010111 @r2rd
vmv2r_v 100111 1 ..... 00001 011 ..... 1010111 @r2rd
vmv4r_v 100111 1 ..... 00011 011 ..... 1010111 @r2rd
+7 -2
View File
@@ -119,8 +119,11 @@ static bool trans_vfwmaccbf16_vv(DisasContext *ctx, arg_vfwmaccbf16_vv *a)
REQUIRE_FPU;
REQUIRE_ZVFBFWMA(ctx);
uint8_t sew = ctx->sew;
if (require_rvv(ctx) && vext_check_isa_ill(ctx) && (ctx->sew == MO_16) &&
vext_check_dss(ctx, a->rd, a->rs1, a->rs2, a->vm)) {
vext_check_dss(ctx, a->rd, a->rs1, a->rs2, a->vm) &&
vext_check_input_eew(ctx, a->rd, sew + 1, a->rs1, sew, a->vm) &&
vext_check_input_eew(ctx, a->rd, sew + 1, a->rs2, sew, a->vm)) {
uint32_t data = 0;
gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
@@ -146,8 +149,10 @@ static bool trans_vfwmaccbf16_vf(DisasContext *ctx, arg_vfwmaccbf16_vf *a)
REQUIRE_FPU;
REQUIRE_ZVFBFWMA(ctx);
uint8_t sew = ctx->sew;
if (require_rvv(ctx) && (ctx->sew == MO_16) && vext_check_isa_ill(ctx) &&
vext_check_ds(ctx, a->rd, a->rs2, a->vm)) {
vext_check_ds(ctx, a->rd, a->rs2, a->vm) &&
vext_check_input_eew(ctx, a->rd, sew + 1, a->rs2, sew, a->vm)) {
uint32_t data = 0;
gen_set_rm(ctx, RISCV_FRM_DYN);
File diff suppressed because it is too large Load Diff
+5
View File
@@ -201,4 +201,9 @@ static inline target_ulong adjust_addr_virt(CPURISCVState *env,
return adjust_addr_body(env, addr, true);
}
static inline int insn_len(uint16_t first_word)
{
return (first_word & 3) == 3 ? 4 : 2;
}
#endif
+212 -123
View File
File diff suppressed because it is too large Load Diff
+7 -6
View File
@@ -71,7 +71,7 @@ target_ulong helper_csrr(CPURISCVState *env, int csr)
void helper_csrw(CPURISCVState *env, int csr, target_ulong src)
{
target_ulong mask = env->xl == MXL_RV32 ? UINT32_MAX : (target_ulong)-1;
RISCVException ret = riscv_csrrw(env, csr, NULL, src, mask);
RISCVException ret = riscv_csrrw(env, csr, NULL, src, mask, GETPC());
if (ret != RISCV_EXCP_NONE) {
riscv_raise_exception(env, ret, GETPC());
@@ -82,7 +82,7 @@ target_ulong helper_csrrw(CPURISCVState *env, int csr,
target_ulong src, target_ulong write_mask)
{
target_ulong val = 0;
RISCVException ret = riscv_csrrw(env, csr, &val, src, write_mask);
RISCVException ret = riscv_csrrw(env, csr, &val, src, write_mask, GETPC());
if (ret != RISCV_EXCP_NONE) {
riscv_raise_exception(env, ret, GETPC());
@@ -108,7 +108,7 @@ void helper_csrw_i128(CPURISCVState *env, int csr,
{
RISCVException ret = riscv_csrrw_i128(env, csr, NULL,
int128_make128(srcl, srch),
UINT128_MAX);
UINT128_MAX, GETPC());
if (ret != RISCV_EXCP_NONE) {
riscv_raise_exception(env, ret, GETPC());
@@ -116,13 +116,14 @@ void helper_csrw_i128(CPURISCVState *env, int csr,
}
target_ulong helper_csrrw_i128(CPURISCVState *env, int csr,
target_ulong srcl, target_ulong srch,
target_ulong maskl, target_ulong maskh)
target_ulong srcl, target_ulong srch,
target_ulong maskl, target_ulong maskh)
{
Int128 rv = int128_zero();
RISCVException ret = riscv_csrrw_i128(env, csr, &rv,
int128_make128(srcl, srch),
int128_make128(maskl, maskh));
int128_make128(maskl, maskh),
GETPC());
if (ret != RISCV_EXCP_NONE) {
riscv_raise_exception(env, ret, GETPC());
+81 -66
View File
@@ -32,6 +32,15 @@ static bool pmp_write_cfg(CPURISCVState *env, uint32_t addr_index,
uint8_t val);
static uint8_t pmp_read_cfg(CPURISCVState *env, uint32_t addr_index);
/*
* Convert the PMP permissions to match the truth table in the Smepmp spec.
*/
static inline uint8_t pmp_get_smepmp_operation(uint8_t cfg)
{
return ((cfg & PMP_LOCK) >> 4) | ((cfg & PMP_READ) << 2) |
(cfg & PMP_WRITE) | ((cfg & PMP_EXEC) >> 2);
}
/*
* Accessor method to extract address matching type 'a field' from cfg reg
*/
@@ -46,21 +55,58 @@ static inline uint8_t pmp_get_a_field(uint8_t cfg)
*/
static inline int pmp_is_locked(CPURISCVState *env, uint32_t pmp_index)
{
/* mseccfg.RLB is set */
if (MSECCFG_RLB_ISSET(env)) {
return 0;
}
if (env->pmp_state.pmp[pmp_index].cfg_reg & PMP_LOCK) {
return 1;
}
/* Top PMP has no 'next' to check */
if ((pmp_index + 1u) >= MAX_RISCV_PMPS) {
return 0;
}
/*
* Check whether a PMP is locked for writing or not.
* (i.e. has LOCK flag and mseccfg.RLB is unset)
*/
static int pmp_is_readonly(CPURISCVState *env, uint32_t pmp_index)
{
return pmp_is_locked(env, pmp_index) && !MSECCFG_RLB_ISSET(env);
}
/*
* Check whether `val` is an invalid Smepmp config value
*/
static int pmp_is_invalid_smepmp_cfg(CPURISCVState *env, uint8_t val)
{
/* No check if mseccfg.MML is not set or if mseccfg.RLB is set */
if (!MSECCFG_MML_ISSET(env) || MSECCFG_RLB_ISSET(env)) {
return 0;
}
return 0;
/*
* Adding a rule with executable privileges that either is M-mode-only
* or a locked Shared-Region is not possible
*/
switch (pmp_get_smepmp_operation(val)) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 12:
case 14:
case 15:
return 0;
case 9:
case 10:
case 11:
case 13:
return 1;
default:
g_assert_not_reached();
}
}
/*
@@ -91,45 +137,18 @@ static inline uint8_t pmp_read_cfg(CPURISCVState *env, uint32_t pmp_index)
static bool pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val)
{
if (pmp_index < MAX_RISCV_PMPS) {
bool locked = true;
if (riscv_cpu_cfg(env)->ext_smepmp) {
/* mseccfg.RLB is set */
if (MSECCFG_RLB_ISSET(env)) {
locked = false;
}
/* mseccfg.MML is not set */
if (!MSECCFG_MML_ISSET(env) && !pmp_is_locked(env, pmp_index)) {
locked = false;
}
/* mseccfg.MML is set */
if (MSECCFG_MML_ISSET(env)) {
/* not adding execute bit */
if ((val & PMP_LOCK) != 0 && (val & PMP_EXEC) != PMP_EXEC) {
locked = false;
}
/* shared region and not adding X bit */
if ((val & PMP_LOCK) != PMP_LOCK &&
(val & 0x7) != (PMP_WRITE | PMP_EXEC)) {
locked = false;
}
}
} else {
if (!pmp_is_locked(env, pmp_index)) {
locked = false;
}
if (env->pmp_state.pmp[pmp_index].cfg_reg == val) {
/* no change */
return false;
}
if (locked) {
qemu_log_mask(LOG_GUEST_ERROR, "ignoring pmpcfg write - locked\n");
} else if (env->pmp_state.pmp[pmp_index].cfg_reg != val) {
/* If !mseccfg.MML then ignore writes with encoding RW=01 */
if ((val & PMP_WRITE) && !(val & PMP_READ) &&
!MSECCFG_MML_ISSET(env)) {
return false;
}
if (pmp_is_readonly(env, pmp_index)) {
qemu_log_mask(LOG_GUEST_ERROR,
"ignoring pmpcfg write - read only\n");
} else if (pmp_is_invalid_smepmp_cfg(env, val)) {
qemu_log_mask(LOG_GUEST_ERROR,
"ignoring pmpcfg write - invalid\n");
} else {
env->pmp_state.pmp[pmp_index].cfg_reg = val;
pmp_update_rule_addr(env, pmp_index);
return true;
@@ -353,16 +372,6 @@ bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr,
const uint8_t a_field =
pmp_get_a_field(env->pmp_state.pmp[i].cfg_reg);
/*
* Convert the PMP permissions to match the truth table in the
* Smepmp spec.
*/
const uint8_t smepmp_operation =
((env->pmp_state.pmp[i].cfg_reg & PMP_LOCK) >> 4) |
((env->pmp_state.pmp[i].cfg_reg & PMP_READ) << 2) |
(env->pmp_state.pmp[i].cfg_reg & PMP_WRITE) |
((env->pmp_state.pmp[i].cfg_reg & PMP_EXEC) >> 2);
if (((s + e) == 2) && (PMP_AMATCH_OFF != a_field)) {
/*
* If the PMP entry is not off and the address is in range,
@@ -381,6 +390,9 @@ bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr,
/*
* If mseccfg.MML Bit set, do the enhanced pmp priv check
*/
const uint8_t smepmp_operation =
pmp_get_smepmp_operation(env->pmp_state.pmp[i].cfg_reg);
if (mode == PRV_M) {
switch (smepmp_operation) {
case 0:
@@ -517,6 +529,11 @@ void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index,
bool is_next_cfg_tor = false;
if (addr_index < MAX_RISCV_PMPS) {
if (env->pmp_state.pmp[addr_index].addr_reg == val) {
/* no change */
return;
}
/*
* In TOR mode, need to check the lock bit of the next pmp
* (if there is a next).
@@ -525,25 +542,23 @@ void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index,
uint8_t pmp_cfg = env->pmp_state.pmp[addr_index + 1].cfg_reg;
is_next_cfg_tor = PMP_AMATCH_TOR == pmp_get_a_field(pmp_cfg);
if (pmp_is_locked(env, addr_index + 1) && is_next_cfg_tor) {
if (pmp_is_readonly(env, addr_index + 1) && is_next_cfg_tor) {
qemu_log_mask(LOG_GUEST_ERROR,
"ignoring pmpaddr write - pmpcfg + 1 locked\n");
"ignoring pmpaddr write - pmpcfg+1 read only\n");
return;
}
}
if (!pmp_is_locked(env, addr_index)) {
if (env->pmp_state.pmp[addr_index].addr_reg != val) {
env->pmp_state.pmp[addr_index].addr_reg = val;
pmp_update_rule_addr(env, addr_index);
if (is_next_cfg_tor) {
pmp_update_rule_addr(env, addr_index + 1);
}
tlb_flush(env_cpu(env));
if (!pmp_is_readonly(env, addr_index)) {
env->pmp_state.pmp[addr_index].addr_reg = val;
pmp_update_rule_addr(env, addr_index);
if (is_next_cfg_tor) {
pmp_update_rule_addr(env, addr_index + 1);
}
tlb_flush(env_cpu(env));
} else {
qemu_log_mask(LOG_GUEST_ERROR,
"ignoring pmpaddr write - locked\n");
"ignoring pmpaddr write - read only\n");
}
} else {
qemu_log_mask(LOG_GUEST_ERROR,

Some files were not shown because too many files have changed in this diff Show More