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-20200626' into staging
target-arm queue: * hw/arm/aspeed: improve QOM usage * hw/misc/pca9552: trace GPIO change events * target/arm: Implement ARMv8.5-MemTag for system emulation # gpg: Signature made Fri 26 Jun 2020 16:13:27 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-20200626: (57 commits) target/arm: Enable MTE target/arm: Add allocation tag storage for system mode target/arm: Create tagged ram when MTE is enabled target/arm: Cache the Tagged bit for a page in MemTxAttrs target/arm: Always pass cacheattr to get_phys_addr target/arm: Set PSTATE.TCO on exception entry target/arm: Implement data cache set allocation tags target/arm: Complete TBI clearing for user-only for SVE target/arm: Add mte helpers for sve scatter/gather memory ops target/arm: Handle TBI for sve scalar + int memory ops target/arm: Add mte helpers for sve scalar + int ff/nf loads target/arm: Add mte helpers for sve scalar + int stores target/arm: Add mte helpers for sve scalar + int loads target/arm: Add arm_tlb_bti_gp target/arm: Tidy trans_LD1R_zpri target/arm: Use mte_check1 for sve LD1R target/arm: Use mte_checkN for sve unpredicated stores target/arm: Use mte_checkN for sve unpredicated loads target/arm: Add helper_mte_check_zva target/arm: Implement helper_mte_checkN ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+27
-19
@@ -32,10 +32,15 @@ static struct arm_boot_info aspeed_board_binfo = {
|
||||
.board_id = -1, /* device-tree-only board */
|
||||
};
|
||||
|
||||
struct AspeedBoardState {
|
||||
struct AspeedMachineState {
|
||||
/* Private */
|
||||
MachineState parent_obj;
|
||||
/* Public */
|
||||
|
||||
AspeedSoCState soc;
|
||||
MemoryRegion ram_container;
|
||||
MemoryRegion max_ram;
|
||||
bool mmio_exec;
|
||||
};
|
||||
|
||||
/* Palmetto hardware value: 0x120CE416 */
|
||||
@@ -253,7 +258,7 @@ static void sdhci_attach_drive(SDHCIState *sdhci, DriveInfo *dinfo)
|
||||
|
||||
static void aspeed_machine_init(MachineState *machine)
|
||||
{
|
||||
AspeedBoardState *bmc;
|
||||
AspeedMachineState *bmc = ASPEED_MACHINE(machine);
|
||||
AspeedMachineClass *amc = ASPEED_MACHINE_GET_CLASS(machine);
|
||||
AspeedSoCClass *sc;
|
||||
DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
|
||||
@@ -261,8 +266,6 @@ static void aspeed_machine_init(MachineState *machine)
|
||||
int i;
|
||||
NICInfo *nd = &nd_table[0];
|
||||
|
||||
bmc = g_new0(AspeedBoardState, 1);
|
||||
|
||||
memory_region_init(&bmc->ram_container, NULL, "aspeed-ram-container",
|
||||
4 * GiB);
|
||||
memory_region_add_subregion(&bmc->ram_container, 0, machine->ram);
|
||||
@@ -329,12 +332,12 @@ static void aspeed_machine_init(MachineState *machine)
|
||||
* needed by the flash modules of the Aspeed machines.
|
||||
*/
|
||||
if (ASPEED_MACHINE(machine)->mmio_exec) {
|
||||
memory_region_init_alias(boot_rom, OBJECT(bmc), "aspeed.boot_rom",
|
||||
memory_region_init_alias(boot_rom, NULL, "aspeed.boot_rom",
|
||||
&fl->mmio, 0, fl->size);
|
||||
memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
|
||||
boot_rom);
|
||||
} else {
|
||||
memory_region_init_rom(boot_rom, OBJECT(bmc), "aspeed.boot_rom",
|
||||
memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom",
|
||||
fl->size, &error_abort);
|
||||
memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
|
||||
boot_rom);
|
||||
@@ -345,7 +348,7 @@ static void aspeed_machine_init(MachineState *machine)
|
||||
if (machine->kernel_filename && sc->num_cpus > 1) {
|
||||
/* With no u-boot we must set up a boot stub for the secondary CPU */
|
||||
MemoryRegion *smpboot = g_new(MemoryRegion, 1);
|
||||
memory_region_init_ram(smpboot, OBJECT(bmc), "aspeed.smpboot",
|
||||
memory_region_init_ram(smpboot, NULL, "aspeed.smpboot",
|
||||
0x80, &error_abort);
|
||||
memory_region_add_subregion(get_system_memory(),
|
||||
AST_SMP_MAILBOX_BASE, smpboot);
|
||||
@@ -374,7 +377,7 @@ static void aspeed_machine_init(MachineState *machine)
|
||||
arm_load_kernel(ARM_CPU(first_cpu), machine, &aspeed_board_binfo);
|
||||
}
|
||||
|
||||
static void palmetto_bmc_i2c_init(AspeedBoardState *bmc)
|
||||
static void palmetto_bmc_i2c_init(AspeedMachineState *bmc)
|
||||
{
|
||||
AspeedSoCState *soc = &bmc->soc;
|
||||
DeviceState *dev;
|
||||
@@ -396,7 +399,7 @@ static void palmetto_bmc_i2c_init(AspeedBoardState *bmc)
|
||||
object_property_set_int(OBJECT(dev), 110000, "temperature3", &error_abort);
|
||||
}
|
||||
|
||||
static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
|
||||
static void ast2500_evb_i2c_init(AspeedMachineState *bmc)
|
||||
{
|
||||
AspeedSoCState *soc = &bmc->soc;
|
||||
uint8_t *eeprom_buf = g_malloc0(8 * 1024);
|
||||
@@ -413,13 +416,13 @@ static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32);
|
||||
}
|
||||
|
||||
static void ast2600_evb_i2c_init(AspeedBoardState *bmc)
|
||||
static void ast2600_evb_i2c_init(AspeedMachineState *bmc)
|
||||
{
|
||||
/* Start with some devices on our I2C busses */
|
||||
ast2500_evb_i2c_init(bmc);
|
||||
}
|
||||
|
||||
static void romulus_bmc_i2c_init(AspeedBoardState *bmc)
|
||||
static void romulus_bmc_i2c_init(AspeedMachineState *bmc)
|
||||
{
|
||||
AspeedSoCState *soc = &bmc->soc;
|
||||
|
||||
@@ -428,7 +431,7 @@ static void romulus_bmc_i2c_init(AspeedBoardState *bmc)
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 0x32);
|
||||
}
|
||||
|
||||
static void swift_bmc_i2c_init(AspeedBoardState *bmc)
|
||||
static void swift_bmc_i2c_init(AspeedMachineState *bmc)
|
||||
{
|
||||
AspeedSoCState *soc = &bmc->soc;
|
||||
|
||||
@@ -457,7 +460,7 @@ static void swift_bmc_i2c_init(AspeedBoardState *bmc)
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 12), "tmp105", 0x4a);
|
||||
}
|
||||
|
||||
static void sonorapass_bmc_i2c_init(AspeedBoardState *bmc)
|
||||
static void sonorapass_bmc_i2c_init(AspeedMachineState *bmc)
|
||||
{
|
||||
AspeedSoCState *soc = &bmc->soc;
|
||||
|
||||
@@ -501,16 +504,19 @@ static void sonorapass_bmc_i2c_init(AspeedBoardState *bmc)
|
||||
|
||||
}
|
||||
|
||||
static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
|
||||
static void witherspoon_bmc_i2c_init(AspeedMachineState *bmc)
|
||||
{
|
||||
AspeedSoCState *soc = &bmc->soc;
|
||||
uint8_t *eeprom_buf = g_malloc0(8 * 1024);
|
||||
DeviceState *dev;
|
||||
|
||||
/* Bus 3: TODO bmp280@77 */
|
||||
/* Bus 3: TODO max31785@52 */
|
||||
/* Bus 3: TODO dps310@76 */
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), TYPE_PCA9552,
|
||||
0x60);
|
||||
dev = i2c_try_create_slave(TYPE_PCA9552, 0x60);
|
||||
qdev_prop_set_string(dev, "description", "pca1");
|
||||
i2c_realize_and_unref(dev, aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3),
|
||||
&error_fatal);
|
||||
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "tmp423", 0x4c);
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 5), "tmp423", 0x4c);
|
||||
@@ -525,8 +531,10 @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
|
||||
|
||||
smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), 0x51,
|
||||
eeprom_buf);
|
||||
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), TYPE_PCA9552,
|
||||
0x60);
|
||||
dev = i2c_try_create_slave(TYPE_PCA9552, 0x60);
|
||||
qdev_prop_set_string(dev, "description", "pca0");
|
||||
i2c_realize_and_unref(dev, aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11),
|
||||
&error_fatal);
|
||||
/* Bus 11: TODO ucd90160@64 */
|
||||
}
|
||||
|
||||
@@ -751,7 +759,7 @@ static const TypeInfo aspeed_machine_types[] = {
|
||||
}, {
|
||||
.name = TYPE_ASPEED_MACHINE,
|
||||
.parent = TYPE_MACHINE,
|
||||
.instance_size = sizeof(AspeedMachine),
|
||||
.instance_size = sizeof(AspeedMachineState),
|
||||
.instance_init = aspeed_machine_instance_init,
|
||||
.class_size = sizeof(AspeedMachineClass),
|
||||
.class_init = aspeed_machine_class_init,
|
||||
|
||||
+53
-2
@@ -1390,8 +1390,19 @@ static void create_platform_bus(VirtMachineState *vms)
|
||||
sysbus_mmio_get_region(s, 0));
|
||||
}
|
||||
|
||||
static void create_tag_ram(MemoryRegion *tag_sysmem,
|
||||
hwaddr base, hwaddr size,
|
||||
const char *name)
|
||||
{
|
||||
MemoryRegion *tagram = g_new(MemoryRegion, 1);
|
||||
|
||||
memory_region_init_ram(tagram, NULL, name, size / 32, &error_fatal);
|
||||
memory_region_add_subregion(tag_sysmem, base / 32, tagram);
|
||||
}
|
||||
|
||||
static void create_secure_ram(VirtMachineState *vms,
|
||||
MemoryRegion *secure_sysmem)
|
||||
MemoryRegion *secure_sysmem,
|
||||
MemoryRegion *secure_tag_sysmem)
|
||||
{
|
||||
MemoryRegion *secram = g_new(MemoryRegion, 1);
|
||||
char *nodename;
|
||||
@@ -1409,6 +1420,10 @@ static void create_secure_ram(VirtMachineState *vms,
|
||||
qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
|
||||
qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
|
||||
|
||||
if (secure_tag_sysmem) {
|
||||
create_tag_ram(secure_tag_sysmem, base, size, "mach-virt.secure-tag");
|
||||
}
|
||||
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
@@ -1665,6 +1680,8 @@ static void machvirt_init(MachineState *machine)
|
||||
const CPUArchIdList *possible_cpus;
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
MemoryRegion *secure_sysmem = NULL;
|
||||
MemoryRegion *tag_sysmem = NULL;
|
||||
MemoryRegion *secure_tag_sysmem = NULL;
|
||||
int n, virt_max_cpus;
|
||||
bool firmware_loaded;
|
||||
bool aarch64 = true;
|
||||
@@ -1819,6 +1836,35 @@ static void machvirt_init(MachineState *machine)
|
||||
"secure-memory", &error_abort);
|
||||
}
|
||||
|
||||
/*
|
||||
* The cpu adds the property if and only if MemTag is supported.
|
||||
* If it is, we must allocate the ram to back that up.
|
||||
*/
|
||||
if (object_property_find(cpuobj, "tag-memory", NULL)) {
|
||||
if (!tag_sysmem) {
|
||||
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, OBJECT(tag_sysmem),
|
||||
"tag-memory", &error_abort);
|
||||
if (vms->secure) {
|
||||
object_property_set_link(cpuobj, OBJECT(secure_tag_sysmem),
|
||||
"secure-tag-memory", &error_abort);
|
||||
}
|
||||
}
|
||||
|
||||
qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
|
||||
object_unref(cpuobj);
|
||||
}
|
||||
@@ -1857,10 +1903,15 @@ static void machvirt_init(MachineState *machine)
|
||||
create_uart(vms, VIRT_UART, sysmem, serial_hd(0));
|
||||
|
||||
if (vms->secure) {
|
||||
create_secure_ram(vms, secure_sysmem);
|
||||
create_secure_ram(vms, secure_sysmem, secure_tag_sysmem);
|
||||
create_uart(vms, VIRT_SECURE_UART, secure_sysmem, serial_hd(1));
|
||||
}
|
||||
|
||||
if (tag_sysmem) {
|
||||
create_tag_ram(tag_sysmem, vms->memmap[VIRT_MEM].base,
|
||||
machine->ram_size, "mach-virt.tag");
|
||||
}
|
||||
|
||||
vms->highmem_ecam &= vms->highmem && (!firmware_loaded || aarch64);
|
||||
|
||||
create_rtc(vms);
|
||||
|
||||
+16
-2
@@ -267,13 +267,27 @@ const VMStateDescription vmstate_i2c_slave = {
|
||||
}
|
||||
};
|
||||
|
||||
DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr)
|
||||
DeviceState *i2c_try_create_slave(const char *name, uint8_t addr)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
dev = qdev_new(name);
|
||||
qdev_prop_set_uint8(dev, "address", addr);
|
||||
qdev_realize_and_unref(dev, &bus->qbus, &error_fatal);
|
||||
return dev;
|
||||
}
|
||||
|
||||
bool i2c_realize_and_unref(DeviceState *dev, I2CBus *bus, Error **errp)
|
||||
{
|
||||
return qdev_realize_and_unref(dev, &bus->qbus, errp);
|
||||
}
|
||||
|
||||
DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
dev = i2c_try_create_slave(name, addr);
|
||||
i2c_realize_and_unref(dev, bus, &error_fatal);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
+162
-54
@@ -4,6 +4,7 @@
|
||||
* https://www.nxp.com/docs/en/application-note/AN264.pdf
|
||||
*
|
||||
* Copyright (c) 2017-2018, IBM Corporation.
|
||||
* Copyright (c) 2020 Philippe Mathieu-Daudé
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
* later. See the COPYING file in the top-level directory.
|
||||
@@ -12,11 +13,29 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/misc/pca9552.h"
|
||||
#include "hw/misc/pca9552_regs.h"
|
||||
#include "hw/irq.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "trace.h"
|
||||
|
||||
typedef struct PCA955xClass {
|
||||
/*< private >*/
|
||||
I2CSlaveClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
uint8_t pin_count;
|
||||
uint8_t max_reg;
|
||||
} PCA955xClass;
|
||||
|
||||
#define PCA955X_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(PCA955xClass, (klass), TYPE_PCA955X)
|
||||
#define PCA955X_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(PCA955xClass, (obj), TYPE_PCA955X)
|
||||
|
||||
#define PCA9552_LED_ON 0x0
|
||||
#define PCA9552_LED_OFF 0x1
|
||||
@@ -25,7 +44,7 @@
|
||||
|
||||
static const char *led_state[] = {"on", "off", "pwm0", "pwm1"};
|
||||
|
||||
static uint8_t pca9552_pin_get_config(PCA9552State *s, int pin)
|
||||
static uint8_t pca955x_pin_get_config(PCA955xState *s, int pin)
|
||||
{
|
||||
uint8_t reg = PCA9552_LS0 + (pin / 4);
|
||||
uint8_t shift = (pin % 4) << 1;
|
||||
@@ -33,20 +52,71 @@ static uint8_t pca9552_pin_get_config(PCA9552State *s, int pin)
|
||||
return extract32(s->regs[reg], shift, 2);
|
||||
}
|
||||
|
||||
static void pca9552_update_pin_input(PCA9552State *s)
|
||||
/* Return INPUT status (bit #N belongs to GPIO #N) */
|
||||
static uint16_t pca955x_pins_get_status(PCA955xState *s)
|
||||
{
|
||||
return (s->regs[PCA9552_INPUT1] << 8) | s->regs[PCA9552_INPUT0];
|
||||
}
|
||||
|
||||
static void pca955x_display_pins_status(PCA955xState *s,
|
||||
uint16_t previous_pins_status)
|
||||
{
|
||||
PCA955xClass *k = PCA955X_GET_CLASS(s);
|
||||
uint16_t pins_status, pins_changed;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < s->nr_leds; i++) {
|
||||
pins_status = pca955x_pins_get_status(s);
|
||||
pins_changed = previous_pins_status ^ pins_status;
|
||||
if (!pins_changed) {
|
||||
return;
|
||||
}
|
||||
if (trace_event_get_state_backends(TRACE_PCA955X_GPIO_STATUS)) {
|
||||
char *buf = g_newa(char, k->pin_count + 1);
|
||||
|
||||
for (i = 0; i < k->pin_count; i++) {
|
||||
if (extract32(pins_status, i, 1)) {
|
||||
buf[i] = '*';
|
||||
} else {
|
||||
buf[i] = '.';
|
||||
}
|
||||
}
|
||||
buf[i] = '\0';
|
||||
trace_pca955x_gpio_status(s->description, buf);
|
||||
}
|
||||
if (trace_event_get_state_backends(TRACE_PCA955X_GPIO_CHANGE)) {
|
||||
for (i = 0; i < k->pin_count; i++) {
|
||||
if (extract32(pins_changed, i, 1)) {
|
||||
unsigned new_state = extract32(pins_status, i, 1);
|
||||
|
||||
/*
|
||||
* We display the state using the PCA logic ("active-high").
|
||||
* This is not the state of the LED, which signal might be
|
||||
* wired "active-low" on the board.
|
||||
*/
|
||||
trace_pca955x_gpio_change(s->description, i,
|
||||
!new_state, new_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pca955x_update_pin_input(PCA955xState *s)
|
||||
{
|
||||
PCA955xClass *k = PCA955X_GET_CLASS(s);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < k->pin_count; i++) {
|
||||
uint8_t input_reg = PCA9552_INPUT0 + (i / 8);
|
||||
uint8_t input_shift = (i % 8);
|
||||
uint8_t config = pca9552_pin_get_config(s, i);
|
||||
uint8_t config = pca955x_pin_get_config(s, i);
|
||||
|
||||
switch (config) {
|
||||
case PCA9552_LED_ON:
|
||||
qemu_set_irq(s->gpio[i], 1);
|
||||
s->regs[input_reg] |= 1 << input_shift;
|
||||
break;
|
||||
case PCA9552_LED_OFF:
|
||||
qemu_set_irq(s->gpio[i], 0);
|
||||
s->regs[input_reg] &= ~(1 << input_shift);
|
||||
break;
|
||||
case PCA9552_LED_PWM0:
|
||||
@@ -58,7 +128,7 @@ static void pca9552_update_pin_input(PCA9552State *s)
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t pca9552_read(PCA9552State *s, uint8_t reg)
|
||||
static uint8_t pca955x_read(PCA955xState *s, uint8_t reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case PCA9552_INPUT0:
|
||||
@@ -79,8 +149,10 @@ static uint8_t pca9552_read(PCA9552State *s, uint8_t reg)
|
||||
}
|
||||
}
|
||||
|
||||
static void pca9552_write(PCA9552State *s, uint8_t reg, uint8_t data)
|
||||
static void pca955x_write(PCA955xState *s, uint8_t reg, uint8_t data)
|
||||
{
|
||||
uint16_t pins_status;
|
||||
|
||||
switch (reg) {
|
||||
case PCA9552_PSC0:
|
||||
case PCA9552_PWM0:
|
||||
@@ -93,8 +165,10 @@ static void pca9552_write(PCA9552State *s, uint8_t reg, uint8_t data)
|
||||
case PCA9552_LS1:
|
||||
case PCA9552_LS2:
|
||||
case PCA9552_LS3:
|
||||
pins_status = pca955x_pins_get_status(s);
|
||||
s->regs[reg] = data;
|
||||
pca9552_update_pin_input(s);
|
||||
pca955x_update_pin_input(s);
|
||||
pca955x_display_pins_status(s, pins_status);
|
||||
break;
|
||||
|
||||
case PCA9552_INPUT0:
|
||||
@@ -110,22 +184,24 @@ static void pca9552_write(PCA9552State *s, uint8_t reg, uint8_t data)
|
||||
* after each byte is sent to or received by the device. The index
|
||||
* rollovers to 0 when the maximum register address is reached.
|
||||
*/
|
||||
static void pca9552_autoinc(PCA9552State *s)
|
||||
static void pca955x_autoinc(PCA955xState *s)
|
||||
{
|
||||
PCA955xClass *k = PCA955X_GET_CLASS(s);
|
||||
|
||||
if (s->pointer != 0xFF && s->pointer & PCA9552_AUTOINC) {
|
||||
uint8_t reg = s->pointer & 0xf;
|
||||
|
||||
reg = (reg + 1) % (s->max_reg + 1);
|
||||
reg = (reg + 1) % (k->max_reg + 1);
|
||||
s->pointer = reg | PCA9552_AUTOINC;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t pca9552_recv(I2CSlave *i2c)
|
||||
static uint8_t pca955x_recv(I2CSlave *i2c)
|
||||
{
|
||||
PCA9552State *s = PCA9552(i2c);
|
||||
PCA955xState *s = PCA955X(i2c);
|
||||
uint8_t ret;
|
||||
|
||||
ret = pca9552_read(s, s->pointer & 0xf);
|
||||
ret = pca955x_read(s, s->pointer & 0xf);
|
||||
|
||||
/*
|
||||
* From the Specs:
|
||||
@@ -143,40 +219,41 @@ static uint8_t pca9552_recv(I2CSlave *i2c)
|
||||
__func__);
|
||||
}
|
||||
|
||||
pca9552_autoinc(s);
|
||||
pca955x_autoinc(s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pca9552_send(I2CSlave *i2c, uint8_t data)
|
||||
static int pca955x_send(I2CSlave *i2c, uint8_t data)
|
||||
{
|
||||
PCA9552State *s = PCA9552(i2c);
|
||||
PCA955xState *s = PCA955X(i2c);
|
||||
|
||||
/* First byte sent by is the register address */
|
||||
if (s->len == 0) {
|
||||
s->pointer = data;
|
||||
s->len++;
|
||||
} else {
|
||||
pca9552_write(s, s->pointer & 0xf, data);
|
||||
pca955x_write(s, s->pointer & 0xf, data);
|
||||
|
||||
pca9552_autoinc(s);
|
||||
pca955x_autoinc(s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pca9552_event(I2CSlave *i2c, enum i2c_event event)
|
||||
static int pca955x_event(I2CSlave *i2c, enum i2c_event event)
|
||||
{
|
||||
PCA9552State *s = PCA9552(i2c);
|
||||
PCA955xState *s = PCA955X(i2c);
|
||||
|
||||
s->len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pca9552_get_led(Object *obj, Visitor *v, const char *name,
|
||||
static void pca955x_get_led(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
PCA9552State *s = PCA9552(obj);
|
||||
PCA955xClass *k = PCA955X_GET_CLASS(obj);
|
||||
PCA955xState *s = PCA955X(obj);
|
||||
int led, rc, reg;
|
||||
uint8_t state;
|
||||
|
||||
@@ -185,7 +262,7 @@ static void pca9552_get_led(Object *obj, Visitor *v, const char *name,
|
||||
error_setg(errp, "%s: error reading %s", __func__, name);
|
||||
return;
|
||||
}
|
||||
if (led < 0 || led > s->nr_leds) {
|
||||
if (led < 0 || led > k->pin_count) {
|
||||
error_setg(errp, "%s invalid led %s", __func__, name);
|
||||
return;
|
||||
}
|
||||
@@ -195,7 +272,7 @@ static void pca9552_get_led(Object *obj, Visitor *v, const char *name,
|
||||
* reading the INPUTx reg
|
||||
*/
|
||||
reg = PCA9552_LS0 + led / 4;
|
||||
state = (pca9552_read(s, reg) >> (led % 8)) & 0x3;
|
||||
state = (pca955x_read(s, reg) >> (led % 8)) & 0x3;
|
||||
visit_type_str(v, name, (char **)&led_state[state], errp);
|
||||
}
|
||||
|
||||
@@ -209,10 +286,11 @@ static inline uint8_t pca955x_ledsel(uint8_t oldval, int led_num, int state)
|
||||
((state & 0x3) << (led_num << 1));
|
||||
}
|
||||
|
||||
static void pca9552_set_led(Object *obj, Visitor *v, const char *name,
|
||||
static void pca955x_set_led(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
PCA9552State *s = PCA9552(obj);
|
||||
PCA955xClass *k = PCA955X_GET_CLASS(obj);
|
||||
PCA955xState *s = PCA955X(obj);
|
||||
Error *local_err = NULL;
|
||||
int led, rc, reg, val;
|
||||
uint8_t state;
|
||||
@@ -228,7 +306,7 @@ static void pca9552_set_led(Object *obj, Visitor *v, const char *name,
|
||||
error_setg(errp, "%s: error reading %s", __func__, name);
|
||||
return;
|
||||
}
|
||||
if (led < 0 || led > s->nr_leds) {
|
||||
if (led < 0 || led > k->pin_count) {
|
||||
error_setg(errp, "%s invalid led %s", __func__, name);
|
||||
return;
|
||||
}
|
||||
@@ -244,9 +322,9 @@ static void pca9552_set_led(Object *obj, Visitor *v, const char *name,
|
||||
}
|
||||
|
||||
reg = PCA9552_LS0 + led / 4;
|
||||
val = pca9552_read(s, reg);
|
||||
val = pca955x_read(s, reg);
|
||||
val = pca955x_ledsel(val, led % 4, state);
|
||||
pca9552_write(s, reg, val);
|
||||
pca955x_write(s, reg, val);
|
||||
}
|
||||
|
||||
static const VMStateDescription pca9552_vmstate = {
|
||||
@@ -254,17 +332,17 @@ static const VMStateDescription pca9552_vmstate = {
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT8(len, PCA9552State),
|
||||
VMSTATE_UINT8(pointer, PCA9552State),
|
||||
VMSTATE_UINT8_ARRAY(regs, PCA9552State, PCA9552_NR_REGS),
|
||||
VMSTATE_I2C_SLAVE(i2c, PCA9552State),
|
||||
VMSTATE_UINT8(len, PCA955xState),
|
||||
VMSTATE_UINT8(pointer, PCA955xState),
|
||||
VMSTATE_UINT8_ARRAY(regs, PCA955xState, PCA955X_NR_REGS),
|
||||
VMSTATE_I2C_SLAVE(i2c, PCA955xState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void pca9552_reset(DeviceState *dev)
|
||||
{
|
||||
PCA9552State *s = PCA9552(dev);
|
||||
PCA955xState *s = PCA955X(dev);
|
||||
|
||||
s->regs[PCA9552_PSC0] = 0xFF;
|
||||
s->regs[PCA9552_PWM0] = 0x80;
|
||||
@@ -275,57 +353,87 @@ static void pca9552_reset(DeviceState *dev)
|
||||
s->regs[PCA9552_LS2] = 0x55;
|
||||
s->regs[PCA9552_LS3] = 0x55;
|
||||
|
||||
pca9552_update_pin_input(s);
|
||||
pca955x_update_pin_input(s);
|
||||
|
||||
s->pointer = 0xFF;
|
||||
s->len = 0;
|
||||
}
|
||||
|
||||
static void pca9552_initfn(Object *obj)
|
||||
static void pca955x_initfn(Object *obj)
|
||||
{
|
||||
PCA9552State *s = PCA9552(obj);
|
||||
PCA955xClass *k = PCA955X_GET_CLASS(obj);
|
||||
int led;
|
||||
|
||||
/* If support for the other PCA955X devices are implemented, these
|
||||
* constant values might be part of class structure describing the
|
||||
* PCA955X device
|
||||
*/
|
||||
s->max_reg = PCA9552_LS3;
|
||||
s->nr_leds = 16;
|
||||
|
||||
for (led = 0; led < s->nr_leds; led++) {
|
||||
assert(k->pin_count <= PCA955X_PIN_COUNT_MAX);
|
||||
for (led = 0; led < k->pin_count; led++) {
|
||||
char *name;
|
||||
|
||||
name = g_strdup_printf("led%d", led);
|
||||
object_property_add(obj, name, "bool", pca9552_get_led, pca9552_set_led,
|
||||
object_property_add(obj, name, "bool", pca955x_get_led, pca955x_set_led,
|
||||
NULL, NULL);
|
||||
g_free(name);
|
||||
}
|
||||
}
|
||||
|
||||
static void pca9552_class_init(ObjectClass *klass, void *data)
|
||||
static void pca955x_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PCA955xClass *k = PCA955X_GET_CLASS(dev);
|
||||
PCA955xState *s = PCA955X(dev);
|
||||
|
||||
if (!s->description) {
|
||||
s->description = g_strdup("pca-unspecified");
|
||||
}
|
||||
|
||||
qdev_init_gpio_out(dev, s->gpio, k->pin_count);
|
||||
}
|
||||
|
||||
static Property pca955x_properties[] = {
|
||||
DEFINE_PROP_STRING("description", PCA955xState, description),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void pca955x_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
|
||||
|
||||
k->event = pca9552_event;
|
||||
k->recv = pca9552_recv;
|
||||
k->send = pca9552_send;
|
||||
k->event = pca955x_event;
|
||||
k->recv = pca955x_recv;
|
||||
k->send = pca955x_send;
|
||||
dc->realize = pca955x_realize;
|
||||
device_class_set_props(dc, pca955x_properties);
|
||||
}
|
||||
|
||||
static const TypeInfo pca955x_info = {
|
||||
.name = TYPE_PCA955X,
|
||||
.parent = TYPE_I2C_SLAVE,
|
||||
.instance_init = pca955x_initfn,
|
||||
.instance_size = sizeof(PCA955xState),
|
||||
.class_init = pca955x_class_init,
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void pca9552_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
PCA955xClass *pc = PCA955X_CLASS(oc);
|
||||
|
||||
dc->reset = pca9552_reset;
|
||||
dc->vmsd = &pca9552_vmstate;
|
||||
pc->max_reg = PCA9552_LS3;
|
||||
pc->pin_count = 16;
|
||||
}
|
||||
|
||||
static const TypeInfo pca9552_info = {
|
||||
.name = TYPE_PCA9552,
|
||||
.parent = TYPE_I2C_SLAVE,
|
||||
.instance_init = pca9552_initfn,
|
||||
.instance_size = sizeof(PCA9552State),
|
||||
.parent = TYPE_PCA955X,
|
||||
.class_init = pca9552_class_init,
|
||||
};
|
||||
|
||||
static void pca9552_register_types(void)
|
||||
static void pca955x_register_types(void)
|
||||
{
|
||||
type_register_static(&pca955x_info);
|
||||
type_register_static(&pca9552_info);
|
||||
}
|
||||
|
||||
type_init(pca9552_register_types)
|
||||
type_init(pca955x_register_types)
|
||||
|
||||
@@ -209,3 +209,7 @@ via1_adb_poll(uint8_t data, const char *vadbint, int status, int index, int size
|
||||
# grlib_ahb_apb_pnp.c
|
||||
grlib_ahb_pnp_read(uint64_t addr, uint32_t value) "AHB PnP read addr:0x%03"PRIx64" data:0x%08x"
|
||||
grlib_apb_pnp_read(uint64_t addr, uint32_t value) "APB PnP read addr:0x%03"PRIx64" data:0x%08x"
|
||||
|
||||
# pca9552.c
|
||||
pca955x_gpio_status(const char *description, const char *buf) "%s GPIOs 0-15 [%s]"
|
||||
pca955x_gpio_change(const char *description, unsigned id, unsigned prev_state, unsigned current_state) "%s GPIO id:%u status: %u -> %u"
|
||||
|
||||
@@ -11,17 +11,11 @@
|
||||
|
||||
#include "hw/boards.h"
|
||||
|
||||
typedef struct AspeedBoardState AspeedBoardState;
|
||||
typedef struct AspeedMachineState AspeedMachineState;
|
||||
|
||||
#define TYPE_ASPEED_MACHINE MACHINE_TYPE_NAME("aspeed")
|
||||
#define ASPEED_MACHINE(obj) \
|
||||
OBJECT_CHECK(AspeedMachine, (obj), TYPE_ASPEED_MACHINE)
|
||||
|
||||
typedef struct AspeedMachine {
|
||||
MachineState parent_obj;
|
||||
|
||||
bool mmio_exec;
|
||||
} AspeedMachine;
|
||||
OBJECT_CHECK(AspeedMachineState, (obj), TYPE_ASPEED_MACHINE)
|
||||
|
||||
#define ASPEED_MAC0_ON (1 << 0)
|
||||
#define ASPEED_MAC1_ON (1 << 1)
|
||||
@@ -45,7 +39,7 @@ typedef struct AspeedMachineClass {
|
||||
const char *spi_model;
|
||||
uint32_t num_cs;
|
||||
uint32_t macs_mask;
|
||||
void (*i2c_init)(AspeedBoardState *bmc);
|
||||
void (*i2c_init)(AspeedMachineState *bmc);
|
||||
} AspeedMachineClass;
|
||||
|
||||
|
||||
|
||||
@@ -80,6 +80,8 @@ int i2c_send(I2CBus *bus, uint8_t data);
|
||||
uint8_t i2c_recv(I2CBus *bus);
|
||||
|
||||
DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr);
|
||||
DeviceState *i2c_try_create_slave(const char *name, uint8_t addr);
|
||||
bool i2c_realize_and_unref(DeviceState *dev, I2CBus *bus, Error **errp);
|
||||
|
||||
/* lm832x.c */
|
||||
void lm832x_key_event(DeviceState *dev, int key, int state);
|
||||
|
||||
@@ -12,11 +12,13 @@
|
||||
#include "hw/i2c/i2c.h"
|
||||
|
||||
#define TYPE_PCA9552 "pca9552"
|
||||
#define PCA9552(obj) OBJECT_CHECK(PCA9552State, (obj), TYPE_PCA9552)
|
||||
#define TYPE_PCA955X "pca955x"
|
||||
#define PCA955X(obj) OBJECT_CHECK(PCA955xState, (obj), TYPE_PCA955X)
|
||||
|
||||
#define PCA9552_NR_REGS 10
|
||||
#define PCA955X_NR_REGS 10
|
||||
#define PCA955X_PIN_COUNT_MAX 16
|
||||
|
||||
typedef struct PCA9552State {
|
||||
typedef struct PCA955xState {
|
||||
/*< private >*/
|
||||
I2CSlave i2c;
|
||||
/*< public >*/
|
||||
@@ -24,9 +26,9 @@ typedef struct PCA9552State {
|
||||
uint8_t len;
|
||||
uint8_t pointer;
|
||||
|
||||
uint8_t regs[PCA9552_NR_REGS];
|
||||
uint8_t max_reg;
|
||||
uint8_t nr_leds;
|
||||
} PCA9552State;
|
||||
uint8_t regs[PCA955X_NR_REGS];
|
||||
qemu_irq gpio[PCA955X_PIN_COUNT_MAX];
|
||||
char *description; /* For debugging purpose only */
|
||||
} PCA955xState;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -86,3 +86,4 @@ obj-$(CONFIG_SOFTMMU) += psci.o
|
||||
obj-$(TARGET_AARCH64) += translate-a64.o helper-a64.o
|
||||
obj-$(TARGET_AARCH64) += translate-sve.o sve_helper.o
|
||||
obj-$(TARGET_AARCH64) += pauth_helper.o
|
||||
obj-$(TARGET_AARCH64) += mte_helper.o
|
||||
|
||||
+76
-5
@@ -203,6 +203,9 @@ static void arm_cpu_reset(DeviceState *dev)
|
||||
* Enable TBI0 and TBI1. While the real kernel only enables TBI0,
|
||||
* turning on both here will produce smaller code and otherwise
|
||||
* make no difference to the user-level emulation.
|
||||
*
|
||||
* In sve_probe_page, we assume that this is set.
|
||||
* Do not modify this without other changes.
|
||||
*/
|
||||
env->cp15.tcr_el[1].raw_tcr = (3ULL << 37);
|
||||
#else
|
||||
@@ -1249,6 +1252,25 @@ void arm_cpu_post_init(Object *obj)
|
||||
if (kvm_enabled()) {
|
||||
kvm_arm_add_vcpu_properties(obj);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) &&
|
||||
cpu_isar_feature(aa64_mte, cpu)) {
|
||||
object_property_add_link(obj, "tag-memory",
|
||||
TYPE_MEMORY_REGION,
|
||||
(Object **)&cpu->tag_memory,
|
||||
qdev_prop_allow_set_link_before_realize,
|
||||
OBJ_PROP_LINK_STRONG);
|
||||
|
||||
if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) {
|
||||
object_property_add_link(obj, "secure-tag-memory",
|
||||
TYPE_MEMORY_REGION,
|
||||
(Object **)&cpu->secure_tag_memory,
|
||||
qdev_prop_allow_set_link_before_realize,
|
||||
OBJ_PROP_LINK_STRONG);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void arm_cpu_finalizefn(Object *obj)
|
||||
@@ -1738,18 +1760,43 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
unsigned int smp_cpus = ms->smp.cpus;
|
||||
bool has_secure = cpu->has_el3 || arm_feature(env, ARM_FEATURE_M_SECURITY);
|
||||
|
||||
if (cpu->has_el3 || arm_feature(env, ARM_FEATURE_M_SECURITY)) {
|
||||
cs->num_ases = 2;
|
||||
/*
|
||||
* We must set cs->num_ases to the final value before
|
||||
* the first call to cpu_address_space_init.
|
||||
*/
|
||||
if (cpu->tag_memory != NULL) {
|
||||
cs->num_ases = 3 + has_secure;
|
||||
} else {
|
||||
cs->num_ases = 1 + has_secure;
|
||||
}
|
||||
|
||||
if (has_secure) {
|
||||
if (!cpu->secure_memory) {
|
||||
cpu->secure_memory = cs->memory;
|
||||
}
|
||||
cpu_address_space_init(cs, ARMASIdx_S, "cpu-secure-memory",
|
||||
cpu->secure_memory);
|
||||
} else {
|
||||
cs->num_ases = 1;
|
||||
}
|
||||
|
||||
if (cpu->tag_memory != NULL) {
|
||||
cpu_address_space_init(cs, ARMASIdx_TagNS, "cpu-tag-memory",
|
||||
cpu->tag_memory);
|
||||
if (has_secure) {
|
||||
cpu_address_space_init(cs, ARMASIdx_TagS, "cpu-tag-memory",
|
||||
cpu->secure_tag_memory);
|
||||
}
|
||||
} else if (cpu_isar_feature(aa64_mte, cpu)) {
|
||||
/*
|
||||
* Since there is no tag memory, we can't meaningfully support MTE
|
||||
* to its fullest. To avoid problems later, when we would come to
|
||||
* use the tag memory, downgrade support to insns only.
|
||||
*/
|
||||
cpu->isar.id_aa64pfr1 =
|
||||
FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 1);
|
||||
}
|
||||
|
||||
cpu_address_space_init(cs, ARMASIdx_NS, "cpu-memory", cs->memory);
|
||||
|
||||
/* No core_count specified, default to smp_cpus. */
|
||||
@@ -1758,6 +1805,30 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tcg_enabled()) {
|
||||
int dcz_blocklen = 4 << cpu->dcz_blocksize;
|
||||
|
||||
/*
|
||||
* We only support DCZ blocklen that fits on one page.
|
||||
*
|
||||
* Architectually this is always true. However TARGET_PAGE_SIZE
|
||||
* is variable and, for compatibility with -machine virt-2.7,
|
||||
* is only 1KiB, as an artifact of legacy ARMv5 subpage support.
|
||||
* But even then, while the largest architectural DCZ blocklen
|
||||
* is 2KiB, no cpu actually uses such a large blocklen.
|
||||
*/
|
||||
assert(dcz_blocklen <= TARGET_PAGE_SIZE);
|
||||
|
||||
/*
|
||||
* We only support DCZ blocksize >= 2*TAG_GRANULE, which is to say
|
||||
* both nibbles of each byte storing tag data may be written at once.
|
||||
* Since TAG_GRANULE is 16, this means that blocklen must be >= 32.
|
||||
*/
|
||||
if (cpu_isar_feature(aa64_mte, cpu)) {
|
||||
assert(dcz_blocklen >= 2 * TAG_GRANULE);
|
||||
}
|
||||
}
|
||||
|
||||
qemu_init_vcpu(cs);
|
||||
cpu_reset(cs);
|
||||
|
||||
@@ -2169,8 +2240,8 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
|
||||
cc->tlb_fill = arm_cpu_tlb_fill;
|
||||
cc->debug_excp_handler = arm_debug_excp_handler;
|
||||
cc->debug_check_watchpoint = arm_debug_check_watchpoint;
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
cc->do_unaligned_access = arm_cpu_do_unaligned_access;
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
cc->do_transaction_failed = arm_cpu_do_transaction_failed;
|
||||
cc->adjust_watchpoint_address = arm_adjust_watchpoint_address;
|
||||
#endif /* CONFIG_TCG && !CONFIG_USER_ONLY */
|
||||
|
||||
+45
-5
@@ -502,6 +502,9 @@ typedef struct CPUARMState {
|
||||
uint64_t pmccfiltr_el0; /* Performance Monitor Filter Register */
|
||||
uint64_t vpidr_el2; /* Virtualization Processor ID Register */
|
||||
uint64_t vmpidr_el2; /* Virtualization Multiprocessor ID Register */
|
||||
uint64_t tfsr_el[4]; /* tfsre0_el1 is index 0. */
|
||||
uint64_t gcr_el1;
|
||||
uint64_t rgsr_el1;
|
||||
} cp15;
|
||||
|
||||
struct {
|
||||
@@ -789,6 +792,10 @@ struct ARMCPU {
|
||||
/* MemoryRegion to use for secure physical accesses */
|
||||
MemoryRegion *secure_memory;
|
||||
|
||||
/* MemoryRegion to use for allocation tag accesses */
|
||||
MemoryRegion *tag_memory;
|
||||
MemoryRegion *secure_tag_memory;
|
||||
|
||||
/* For v8M, pointer to the IDAU interface provided by board/SoC */
|
||||
Object *idau;
|
||||
|
||||
@@ -1282,6 +1289,7 @@ void pmu_init(ARMCPU *cpu);
|
||||
#define PSTATE_SS (1U << 21)
|
||||
#define PSTATE_PAN (1U << 22)
|
||||
#define PSTATE_UAO (1U << 23)
|
||||
#define PSTATE_TCO (1U << 25)
|
||||
#define PSTATE_V (1U << 28)
|
||||
#define PSTATE_C (1U << 29)
|
||||
#define PSTATE_Z (1U << 30)
|
||||
@@ -2356,7 +2364,9 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
|
||||
#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300)
|
||||
#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400)
|
||||
#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | 0x0500)
|
||||
#define ARM_LAST_SPECIAL ARM_CP_DC_ZVA
|
||||
#define ARM_CP_DC_GVA (ARM_CP_SPECIAL | 0x0600)
|
||||
#define ARM_CP_DC_GZVA (ARM_CP_SPECIAL | 0x0700)
|
||||
#define ARM_LAST_SPECIAL ARM_CP_DC_GZVA
|
||||
#define ARM_CP_FPU 0x1000
|
||||
#define ARM_CP_SVE 0x2000
|
||||
#define ARM_CP_NO_GDB 0x4000
|
||||
@@ -2979,6 +2989,8 @@ typedef enum ARMMMUIdxBit {
|
||||
typedef enum ARMASIdx {
|
||||
ARMASIdx_NS = 0,
|
||||
ARMASIdx_S = 1,
|
||||
ARMASIdx_TagNS = 2,
|
||||
ARMASIdx_TagS = 3,
|
||||
} ARMASIdx;
|
||||
|
||||
/* Return the Exception Level targeted by debug exceptions. */
|
||||
@@ -3183,10 +3195,10 @@ typedef ARMCPU ArchCPU;
|
||||
* | | | TBFLAG_A32 | |
|
||||
* | | +-----+----------+ TBFLAG_AM32 |
|
||||
* | TBFLAG_ANY | |TBFLAG_M32| |
|
||||
* | | +-+----------+--------------|
|
||||
* | | | TBFLAG_A64 |
|
||||
* +--------------+---------+---------------------------+
|
||||
* 31 20 15 0
|
||||
* | +-----------+----------+--------------|
|
||||
* | | TBFLAG_A64 |
|
||||
* +--------------+-------------------------------------+
|
||||
* 31 20 0
|
||||
*
|
||||
* Unless otherwise noted, these bits are cached in env->hflags.
|
||||
*/
|
||||
@@ -3253,6 +3265,10 @@ FIELD(TBFLAG_A64, BT, 9, 1)
|
||||
FIELD(TBFLAG_A64, BTYPE, 10, 2) /* Not cached. */
|
||||
FIELD(TBFLAG_A64, TBID, 12, 2)
|
||||
FIELD(TBFLAG_A64, UNPRIV, 14, 1)
|
||||
FIELD(TBFLAG_A64, ATA, 15, 1)
|
||||
FIELD(TBFLAG_A64, TCMA, 16, 2)
|
||||
FIELD(TBFLAG_A64, MTE_ACTIVE, 18, 1)
|
||||
FIELD(TBFLAG_A64, MTE0_ACTIVE, 19, 1)
|
||||
|
||||
/**
|
||||
* cpu_mmu_index:
|
||||
@@ -3385,6 +3401,20 @@ static inline uint64_t *aa64_vfp_qreg(CPUARMState *env, unsigned regno)
|
||||
/* Shared between translate-sve.c and sve_helper.c. */
|
||||
extern const uint64_t pred_esz_masks[4];
|
||||
|
||||
/* Helper for the macros below, validating the argument type. */
|
||||
static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lvalue macros for ARM TLB bits that we must cache in the TCG TLB.
|
||||
* Using these should be a bit more self-documenting than using the
|
||||
* generic target bits directly.
|
||||
*/
|
||||
#define arm_tlb_bti_gp(x) (typecheck_memtxattrs(x)->target_tlb_bit0)
|
||||
#define arm_tlb_mte_tagged(x) (typecheck_memtxattrs(x)->target_tlb_bit1)
|
||||
|
||||
/*
|
||||
* Naming convention for isar_feature functions:
|
||||
* Functions which test 32-bit ID registers should have _aa32_ in
|
||||
@@ -3814,6 +3844,16 @@ static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
|
||||
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_mte_insn_reg(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_mte(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 2;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_pmu_8_1(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 &&
|
||||
|
||||
@@ -654,6 +654,11 @@ static void aarch64_max_initfn(Object *obj)
|
||||
|
||||
t = cpu->isar.id_aa64pfr1;
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, BT, 1);
|
||||
/*
|
||||
* Begin with full support for MTE; will be downgraded to MTE=1
|
||||
* during realize if the board provides no tag memory.
|
||||
*/
|
||||
t = FIELD_DP64(t, ID_AA64PFR1, MTE, 2);
|
||||
cpu->isar.id_aa64pfr1 = t;
|
||||
|
||||
t = cpu->isar.id_aa64mmfr1;
|
||||
|
||||
+25
-69
@@ -1119,85 +1119,41 @@ void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in)
|
||||
* (which matches the usual QEMU behaviour of not implementing either
|
||||
* alignment faults or any memory attribute handling).
|
||||
*/
|
||||
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
uint64_t blocklen = 4 << cpu->dcz_blocksize;
|
||||
int blocklen = 4 << env_archcpu(env)->dcz_blocksize;
|
||||
uint64_t vaddr = vaddr_in & ~(blocklen - 1);
|
||||
int mmu_idx = cpu_mmu_index(env, false);
|
||||
void *mem;
|
||||
|
||||
/*
|
||||
* Trapless lookup. In addition to actual invalid page, may
|
||||
* return NULL for I/O, watchpoints, clean pages, etc.
|
||||
*/
|
||||
mem = tlb_vaddr_to_host(env, vaddr, MMU_DATA_STORE, mmu_idx);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
{
|
||||
if (unlikely(!mem)) {
|
||||
uintptr_t ra = GETPC();
|
||||
|
||||
/*
|
||||
* Slightly awkwardly, QEMU's TARGET_PAGE_SIZE may be less than
|
||||
* the block size so we might have to do more than one TLB lookup.
|
||||
* We know that in fact for any v8 CPU the page size is at least 4K
|
||||
* and the block size must be 2K or less, but TARGET_PAGE_SIZE is only
|
||||
* 1K as an artefact of legacy v5 subpage support being present in the
|
||||
* same QEMU executable. So in practice the hostaddr[] array has
|
||||
* two entries, given the current setting of TARGET_PAGE_BITS_MIN.
|
||||
* Trap if accessing an invalid page. DC_ZVA requires that we supply
|
||||
* the original pointer for an invalid page. But watchpoints require
|
||||
* that we probe the actual space. So do both.
|
||||
*/
|
||||
int maxidx = DIV_ROUND_UP(blocklen, TARGET_PAGE_SIZE);
|
||||
void *hostaddr[DIV_ROUND_UP(2 * KiB, 1 << TARGET_PAGE_BITS_MIN)];
|
||||
int try, i;
|
||||
unsigned mmu_idx = cpu_mmu_index(env, false);
|
||||
TCGMemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
|
||||
(void) probe_write(env, vaddr_in, 1, mmu_idx, ra);
|
||||
mem = probe_write(env, vaddr, blocklen, mmu_idx, ra);
|
||||
|
||||
assert(maxidx <= ARRAY_SIZE(hostaddr));
|
||||
|
||||
for (try = 0; try < 2; try++) {
|
||||
|
||||
for (i = 0; i < maxidx; i++) {
|
||||
hostaddr[i] = tlb_vaddr_to_host(env,
|
||||
vaddr + TARGET_PAGE_SIZE * i,
|
||||
1, mmu_idx);
|
||||
if (!hostaddr[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == maxidx) {
|
||||
/*
|
||||
* If it's all in the TLB it's fair game for just writing to;
|
||||
* we know we don't need to update dirty status, etc.
|
||||
*/
|
||||
for (i = 0; i < maxidx - 1; i++) {
|
||||
memset(hostaddr[i], 0, TARGET_PAGE_SIZE);
|
||||
}
|
||||
memset(hostaddr[i], 0, blocklen - (i * TARGET_PAGE_SIZE));
|
||||
return;
|
||||
}
|
||||
if (unlikely(!mem)) {
|
||||
/*
|
||||
* OK, try a store and see if we can populate the tlb. This
|
||||
* might cause an exception if the memory isn't writable,
|
||||
* in which case we will longjmp out of here. We must for
|
||||
* this purpose use the actual register value passed to us
|
||||
* so that we get the fault address right.
|
||||
* The only remaining reason for mem == NULL is I/O.
|
||||
* Just do a series of byte writes as the architecture demands.
|
||||
*/
|
||||
helper_ret_stb_mmu(env, vaddr_in, 0, oi, GETPC());
|
||||
/* Now we can populate the other TLB entries, if any */
|
||||
for (i = 0; i < maxidx; i++) {
|
||||
uint64_t va = vaddr + TARGET_PAGE_SIZE * i;
|
||||
if (va != (vaddr_in & TARGET_PAGE_MASK)) {
|
||||
helper_ret_stb_mmu(env, va, 0, oi, GETPC());
|
||||
}
|
||||
for (int i = 0; i < blocklen; i++) {
|
||||
cpu_stb_mmuidx_ra(env, vaddr + i, 0, mmu_idx, ra);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Slow path (probably attempt to do this to an I/O device or
|
||||
* similar, or clearing of a block of code we have translations
|
||||
* cached for). Just do a series of byte writes as the architecture
|
||||
* demands. It's not worth trying to use a cpu_physical_memory_map(),
|
||||
* memset(), unmap() sequence here because:
|
||||
* + we'd need to account for the blocksize being larger than a page
|
||||
* + the direct-RAM access case is almost always going to be dealt
|
||||
* with in the fastpath code above, so there's no speed benefit
|
||||
* + we would have to deal with the map returning NULL because the
|
||||
* bounce buffer was in use
|
||||
*/
|
||||
for (i = 0; i < blocklen; i++) {
|
||||
helper_ret_stb_mmu(env, vaddr + i, 0, oi, GETPC());
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
memset(g2h(vaddr), 0, blocklen);
|
||||
#endif
|
||||
|
||||
memset(mem, 0, blocklen);
|
||||
}
|
||||
|
||||
@@ -103,3 +103,19 @@ DEF_HELPER_FLAGS_3(autda, TCG_CALL_NO_WG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(autdb, TCG_CALL_NO_WG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(xpaci, TCG_CALL_NO_RWG_SE, i64, env, i64)
|
||||
DEF_HELPER_FLAGS_2(xpacd, TCG_CALL_NO_RWG_SE, i64, env, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_3(mte_check1, TCG_CALL_NO_WG, i64, env, i32, i64)
|
||||
DEF_HELPER_FLAGS_3(mte_checkN, TCG_CALL_NO_WG, i64, env, i32, i64)
|
||||
DEF_HELPER_FLAGS_3(mte_check_zva, TCG_CALL_NO_WG, i64, env, i32, i64)
|
||||
DEF_HELPER_FLAGS_3(irg, TCG_CALL_NO_RWG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_4(addsubg, TCG_CALL_NO_RWG_SE, i64, env, i64, s32, i32)
|
||||
DEF_HELPER_FLAGS_3(ldg, TCG_CALL_NO_WG, i64, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(stg, TCG_CALL_NO_WG, void, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(stg_parallel, TCG_CALL_NO_WG, void, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(stg_stub, TCG_CALL_NO_WG, void, env, i64)
|
||||
DEF_HELPER_FLAGS_3(st2g, TCG_CALL_NO_WG, void, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(st2g_parallel, TCG_CALL_NO_WG, void, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(st2g_stub, TCG_CALL_NO_WG, void, env, i64)
|
||||
DEF_HELPER_FLAGS_2(ldgm, TCG_CALL_NO_WG, i64, env, i64)
|
||||
DEF_HELPER_FLAGS_3(stgm, TCG_CALL_NO_WG, void, env, i64, i64)
|
||||
DEF_HELPER_FLAGS_3(stzgm_tags, TCG_CALL_NO_WG, void, env, i64, i64)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+329
-94
File diff suppressed because it is too large
Load Diff
@@ -96,6 +96,8 @@ DEF_HELPER_FLAGS_1(rebuild_hflags_a32_newel, TCG_CALL_NO_RWG, void, env)
|
||||
DEF_HELPER_FLAGS_2(rebuild_hflags_a32, TCG_CALL_NO_RWG, void, env, int)
|
||||
DEF_HELPER_FLAGS_2(rebuild_hflags_a64, TCG_CALL_NO_RWG, void, env, int)
|
||||
|
||||
DEF_HELPER_FLAGS_5(probe_access, TCG_CALL_NO_WG, void, env, tl, i32, i32, i32)
|
||||
|
||||
DEF_HELPER_1(vfp_get_fpscr, i32, env)
|
||||
DEF_HELPER_2(vfp_set_fpscr, void, env, i32)
|
||||
|
||||
|
||||
+152
-1
@@ -913,6 +913,51 @@ static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the exception level which controls this address translation regime */
|
||||
static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
|
||||
{
|
||||
switch (mmu_idx) {
|
||||
case ARMMMUIdx_E20_0:
|
||||
case ARMMMUIdx_E20_2:
|
||||
case ARMMMUIdx_E20_2_PAN:
|
||||
case ARMMMUIdx_Stage2:
|
||||
case ARMMMUIdx_E2:
|
||||
return 2;
|
||||
case ARMMMUIdx_SE3:
|
||||
return 3;
|
||||
case ARMMMUIdx_SE10_0:
|
||||
return arm_el_is_aa64(env, 3) ? 1 : 3;
|
||||
case ARMMMUIdx_SE10_1:
|
||||
case ARMMMUIdx_SE10_1_PAN:
|
||||
case ARMMMUIdx_Stage1_E0:
|
||||
case ARMMMUIdx_Stage1_E1:
|
||||
case ARMMMUIdx_Stage1_E1_PAN:
|
||||
case ARMMMUIdx_E10_0:
|
||||
case ARMMMUIdx_E10_1:
|
||||
case ARMMMUIdx_E10_1_PAN:
|
||||
case ARMMMUIdx_MPrivNegPri:
|
||||
case ARMMMUIdx_MUserNegPri:
|
||||
case ARMMMUIdx_MPriv:
|
||||
case ARMMMUIdx_MUser:
|
||||
case ARMMMUIdx_MSPrivNegPri:
|
||||
case ARMMMUIdx_MSUserNegPri:
|
||||
case ARMMMUIdx_MSPriv:
|
||||
case ARMMMUIdx_MSUser:
|
||||
return 1;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the TCR controlling this translation regime */
|
||||
static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
|
||||
{
|
||||
if (mmu_idx == ARMMMUIdx_Stage2) {
|
||||
return &env->cp15.vtcr_el2;
|
||||
}
|
||||
return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
|
||||
}
|
||||
|
||||
/* Return the FSR value for a debug exception (watchpoint, hardware
|
||||
* breakpoint or BKPT insn) targeting the specified exception level.
|
||||
*/
|
||||
@@ -1159,6 +1204,9 @@ static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id)
|
||||
if (isar_feature_aa64_uao(id)) {
|
||||
valid |= PSTATE_UAO;
|
||||
}
|
||||
if (isar_feature_aa64_mte(id)) {
|
||||
valid |= PSTATE_TCO;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
@@ -1195,6 +1243,24 @@ static inline int exception_target_el(CPUARMState *env)
|
||||
return target_el;
|
||||
}
|
||||
|
||||
/* Determine if allocation tags are available. */
|
||||
static inline bool allocation_tag_access_enabled(CPUARMState *env, int el,
|
||||
uint64_t sctlr)
|
||||
{
|
||||
if (el < 3
|
||||
&& arm_feature(env, ARM_FEATURE_EL3)
|
||||
&& !(env->cp15.scr_el3 & SCR_ATA)) {
|
||||
return false;
|
||||
}
|
||||
if (el < 2
|
||||
&& arm_feature(env, ARM_FEATURE_EL2)
|
||||
&& !(arm_hcr_el2_eff(env) & HCR_ATA)) {
|
||||
return false;
|
||||
}
|
||||
sctlr &= (el == 0 ? SCTLR_ATA0 : SCTLR_ATA);
|
||||
return sctlr != 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
/* Security attributes for an address, as returned by v8m_security_lookup. */
|
||||
@@ -1228,10 +1294,95 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
|
||||
MMUAccessType access_type, ARMMMUIdx mmu_idx,
|
||||
hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
|
||||
target_ulong *page_size,
|
||||
ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs);
|
||||
ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs)
|
||||
__attribute__((nonnull));
|
||||
|
||||
void arm_log_exception(int idx);
|
||||
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
/*
|
||||
* The log2 of the words in the tag block, for GMID_EL1.BS.
|
||||
* The is the maximum, 256 bytes, which manipulates 64-bits of tags.
|
||||
*/
|
||||
#define GMID_EL1_BS 6
|
||||
|
||||
/* We associate one allocation tag per 16 bytes, the minimum. */
|
||||
#define LOG2_TAG_GRANULE 4
|
||||
#define TAG_GRANULE (1 << LOG2_TAG_GRANULE)
|
||||
|
||||
/*
|
||||
* The SVE simd_data field, for memory ops, contains either
|
||||
* rd (5 bits) or a shift count (2 bits).
|
||||
*/
|
||||
#define SVE_MTEDESC_SHIFT 5
|
||||
|
||||
/* Bits within a descriptor passed to the helper_mte_check* functions. */
|
||||
FIELD(MTEDESC, MIDX, 0, 4)
|
||||
FIELD(MTEDESC, TBI, 4, 2)
|
||||
FIELD(MTEDESC, TCMA, 6, 2)
|
||||
FIELD(MTEDESC, WRITE, 8, 1)
|
||||
FIELD(MTEDESC, ESIZE, 9, 5)
|
||||
FIELD(MTEDESC, TSIZE, 14, 10) /* mte_checkN only */
|
||||
|
||||
bool mte_probe1(CPUARMState *env, uint32_t desc, uint64_t ptr);
|
||||
uint64_t mte_check1(CPUARMState *env, uint32_t desc,
|
||||
uint64_t ptr, uintptr_t ra);
|
||||
uint64_t mte_checkN(CPUARMState *env, uint32_t desc,
|
||||
uint64_t ptr, uintptr_t ra);
|
||||
|
||||
static inline int allocation_tag_from_addr(uint64_t ptr)
|
||||
{
|
||||
return extract64(ptr, 56, 4);
|
||||
}
|
||||
|
||||
static inline uint64_t address_with_allocation_tag(uint64_t ptr, int rtag)
|
||||
{
|
||||
return deposit64(ptr, 56, 4, rtag);
|
||||
}
|
||||
|
||||
/* Return true if tbi bits mean that the access is checked. */
|
||||
static inline bool tbi_check(uint32_t desc, int bit55)
|
||||
{
|
||||
return (desc >> (R_MTEDESC_TBI_SHIFT + bit55)) & 1;
|
||||
}
|
||||
|
||||
/* Return true if tcma bits mean that the access is unchecked. */
|
||||
static inline bool tcma_check(uint32_t desc, int bit55, int ptr_tag)
|
||||
{
|
||||
/*
|
||||
* We had extracted bit55 and ptr_tag for other reasons, so fold
|
||||
* (ptr<59:55> == 00000 || ptr<59:55> == 11111) into a single test.
|
||||
*/
|
||||
bool match = ((ptr_tag + bit55) & 0xf) == 0;
|
||||
bool tcma = (desc >> (R_MTEDESC_TCMA_SHIFT + bit55)) & 1;
|
||||
return tcma && match;
|
||||
}
|
||||
|
||||
/*
|
||||
* For TBI, ideally, we would do nothing. Proper behaviour on fault is
|
||||
* for the tag to be present in the FAR_ELx register. But for user-only
|
||||
* mode, we do not have a TLB with which to implement this, so we must
|
||||
* remove the top byte.
|
||||
*/
|
||||
static inline uint64_t useronly_clean_ptr(uint64_t ptr)
|
||||
{
|
||||
/* TBI is known to be enabled. */
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
ptr = sextract64(ptr, 0, 56);
|
||||
#endif
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static inline uint64_t useronly_maybe_clean_ptr(uint32_t desc, uint64_t ptr)
|
||||
{
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
int64_t clean_ptr = sextract64(ptr, 0, 56);
|
||||
if (tbi_check(desc, clean_ptr < 0)) {
|
||||
ptr = clean_ptr;
|
||||
}
|
||||
#endif
|
||||
return ptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -187,12 +187,13 @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
|
||||
hwaddr physaddr;
|
||||
int prot;
|
||||
ARMMMUFaultInfo fi = {};
|
||||
ARMCacheAttrs cacheattrs = {};
|
||||
bool secure = mmu_idx & ARM_MMU_IDX_M_S;
|
||||
int exc;
|
||||
bool exc_secure;
|
||||
|
||||
if (get_phys_addr(env, addr, MMU_DATA_STORE, mmu_idx, &physaddr,
|
||||
&attrs, &prot, &page_size, &fi, NULL)) {
|
||||
&attrs, &prot, &page_size, &fi, &cacheattrs)) {
|
||||
/* MPU/SAU lookup failed */
|
||||
if (fi.type == ARMFault_QEMU_SFault) {
|
||||
if (mode == STACK_LAZYFP) {
|
||||
@@ -279,13 +280,14 @@ static bool v7m_stack_read(ARMCPU *cpu, uint32_t *dest, uint32_t addr,
|
||||
hwaddr physaddr;
|
||||
int prot;
|
||||
ARMMMUFaultInfo fi = {};
|
||||
ARMCacheAttrs cacheattrs = {};
|
||||
bool secure = mmu_idx & ARM_MMU_IDX_M_S;
|
||||
int exc;
|
||||
bool exc_secure;
|
||||
uint32_t value;
|
||||
|
||||
if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &physaddr,
|
||||
&attrs, &prot, &page_size, &fi, NULL)) {
|
||||
&attrs, &prot, &page_size, &fi, &cacheattrs)) {
|
||||
/* MPU/SAU lookup failed */
|
||||
if (fi.type == ARMFault_QEMU_SFault) {
|
||||
qemu_log_mask(CPU_LOG_INT,
|
||||
@@ -1928,6 +1930,7 @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx,
|
||||
V8M_SAttributes sattrs = {};
|
||||
MemTxAttrs attrs = {};
|
||||
ARMMMUFaultInfo fi = {};
|
||||
ARMCacheAttrs cacheattrs = {};
|
||||
MemTxResult txres;
|
||||
target_ulong page_size;
|
||||
hwaddr physaddr;
|
||||
@@ -1945,8 +1948,8 @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx,
|
||||
"...really SecureFault with SFSR.INVEP\n");
|
||||
return false;
|
||||
}
|
||||
if (get_phys_addr(env, addr, MMU_INST_FETCH, mmu_idx,
|
||||
&physaddr, &attrs, &prot, &page_size, &fi, NULL)) {
|
||||
if (get_phys_addr(env, addr, MMU_INST_FETCH, mmu_idx, &physaddr,
|
||||
&attrs, &prot, &page_size, &fi, &cacheattrs)) {
|
||||
/* the MPU lookup failed */
|
||||
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_IACCVIOL_MASK;
|
||||
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM, env->v7m.secure);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user