summaryrefslogtreecommitdiffstats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/arm/armsse.c35
-rw-r--r--hw/arm/mps2-tz.c39
-rw-r--r--hw/arm/smmuv3.c50
-rw-r--r--hw/intc/arm_gicv3_cpuif.c48
4 files changed, 107 insertions, 65 deletions
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
index 2e5d0679e7..a1456cb0f4 100644
--- a/hw/arm/armsse.c
+++ b/hw/arm/armsse.c
@@ -13,6 +13,7 @@
#include "qemu/log.h"
#include "qemu/module.h"
#include "qemu/bitops.h"
+#include "qemu/units.h"
#include "qapi/error.h"
#include "trace.h"
#include "hw/sysbus.h"
@@ -59,6 +60,7 @@ struct ARMSSEInfo {
const char *cpu_type;
uint32_t sse_version;
int sram_banks;
+ uint32_t sram_bank_base;
int num_cpus;
uint32_t sys_version;
uint32_t iidr;
@@ -69,6 +71,7 @@ struct ARMSSEInfo {
bool has_cpuid;
bool has_cpu_pwrctrl;
bool has_sse_counter;
+ bool has_tcms;
Property *props;
const ARMSSEDeviceInfo *devinfo;
const bool *irq_is_common;
@@ -102,7 +105,7 @@ static Property sse300_properties[] = {
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
MemoryRegion *),
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
- DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
+ DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 18),
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE, cpu_dsp[0], true),
@@ -504,6 +507,7 @@ static const ARMSSEInfo armsse_variants[] = {
.sse_version = ARMSSE_IOTKIT,
.cpu_type = ARM_CPU_TYPE_NAME("cortex-m33"),
.sram_banks = 1,
+ .sram_bank_base = 0x20000000,
.num_cpus = 1,
.sys_version = 0x41743,
.iidr = 0,
@@ -514,6 +518,7 @@ static const ARMSSEInfo armsse_variants[] = {
.has_cpuid = false,
.has_cpu_pwrctrl = false,
.has_sse_counter = false,
+ .has_tcms = false,
.props = iotkit_properties,
.devinfo = iotkit_devices,
.irq_is_common = sse200_irq_is_common,
@@ -523,6 +528,7 @@ static const ARMSSEInfo armsse_variants[] = {
.sse_version = ARMSSE_SSE200,
.cpu_type = ARM_CPU_TYPE_NAME("cortex-m33"),
.sram_banks = 4,
+ .sram_bank_base = 0x20000000,
.num_cpus = 2,
.sys_version = 0x22041743,
.iidr = 0,
@@ -533,6 +539,7 @@ static const ARMSSEInfo armsse_variants[] = {
.has_cpuid = true,
.has_cpu_pwrctrl = false,
.has_sse_counter = false,
+ .has_tcms = false,
.props = sse200_properties,
.devinfo = sse200_devices,
.irq_is_common = sse200_irq_is_common,
@@ -542,6 +549,7 @@ static const ARMSSEInfo armsse_variants[] = {
.sse_version = ARMSSE_SSE300,
.cpu_type = ARM_CPU_TYPE_NAME("cortex-m55"),
.sram_banks = 2,
+ .sram_bank_base = 0x21000000,
.num_cpus = 1,
.sys_version = 0x7e00043b,
.iidr = 0x74a0043b,
@@ -552,6 +560,7 @@ static const ARMSSEInfo armsse_variants[] = {
.has_cpuid = true,
.has_cpu_pwrctrl = true,
.has_sse_counter = true,
+ .has_tcms = true,
.props = sse300_properties,
.devinfo = sse300_devices,
.irq_is_common = sse300_irq_is_common,
@@ -909,7 +918,6 @@ static void armsse_realize(DeviceState *dev, Error **errp)
const ARMSSEDeviceInfo *devinfo;
int i;
MemoryRegion *mr;
- Error *err = NULL;
SysBusDevice *sbd_apb_ppc0;
SysBusDevice *sbd_secctl;
DeviceState *dev_apb_ppc0;
@@ -918,6 +926,8 @@ static void armsse_realize(DeviceState *dev, Error **errp)
DeviceState *dev_splitter;
uint32_t addr_width_max;
+ ERRP_GUARD();
+
if (!s->board_memory) {
error_setg(errp, "memory property was not set");
return;
@@ -1147,10 +1157,9 @@ static void armsse_realize(DeviceState *dev, Error **errp)
uint32_t sram_bank_size = 1 << s->sram_addr_width;
memory_region_init_ram(&s->sram[i], NULL, ramname,
- sram_bank_size, &err);
+ sram_bank_size, errp);
g_free(ramname);
- if (err) {
- error_propagate(errp, err);
+ if (*errp) {
return;
}
object_property_set_link(OBJECT(&s->mpc[i]), "downstream",
@@ -1161,7 +1170,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
/* Map the upstream end of the MPC into the right place... */
sbd_mpc = SYS_BUS_DEVICE(&s->mpc[i]);
memory_region_add_subregion(&s->container,
- 0x20000000 + i * sram_bank_size,
+ info->sram_bank_base + i * sram_bank_size,
sysbus_mmio_get_region(sbd_mpc, 1));
/* ...and its register interface */
memory_region_add_subregion(&s->container, 0x50083000 + i * 0x1000,
@@ -1210,6 +1219,20 @@ static void armsse_realize(DeviceState *dev, Error **errp)
sysbus_mmio_get_region(sbd, 1));
}
+ if (info->has_tcms) {
+ /* The SSE-300 has an ITCM at 0x0000_0000 and a DTCM at 0x2000_0000 */
+ memory_region_init_ram(&s->itcm, NULL, "sse300-itcm", 512 * KiB, errp);
+ if (*errp) {
+ return;
+ }
+ memory_region_init_ram(&s->dtcm, NULL, "sse300-dtcm", 512 * KiB, errp);
+ if (*errp) {
+ return;
+ }
+ memory_region_add_subregion(&s->container, 0x00000000, &s->itcm);
+ memory_region_add_subregion(&s->container, 0x20000000, &s->dtcm);
+ }
+
/* Devices behind APB PPC0:
* 0x40000000: timer0
* 0x40001000: timer1
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index 70aa31a7f6..e23830f4b7 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -123,8 +123,10 @@ struct MPS2TZMachineClass {
int numirq; /* Number of external interrupts */
int uart_overflow_irq; /* number of the combined UART overflow IRQ */
uint32_t init_svtor; /* init-svtor setting for SSE */
+ uint32_t sram_addr_width; /* SRAM_ADDR_WIDTH setting for SSE */
const RAMInfo *raminfo;
const char *armsse_type;
+ uint32_t boot_ram_size; /* size of ram at address 0; 0 == find in raminfo */
};
struct MPS2TZMachineState {
@@ -244,18 +246,12 @@ static const RAMInfo an524_raminfo[] = { {
.mpc = 0,
.mrindex = 0,
}, {
- .name = "sram",
- .base = 0x20000000,
- .size = 32 * 4 * KiB,
- .mpc = -1,
- .mrindex = 1,
- }, {
/* We don't model QSPI flash yet; for now expose it as simple ROM */
.name = "QSPI",
.base = 0x28000000,
.size = 8 * MiB,
.mpc = 1,
- .mrindex = 2,
+ .mrindex = 1,
.flags = IS_ROM,
}, {
.name = "DDR",
@@ -269,24 +265,12 @@ static const RAMInfo an524_raminfo[] = { {
};
static const RAMInfo an547_raminfo[] = { {
- .name = "itcm",
- .base = 0x00000000,
- .size = 512 * KiB,
- .mpc = -1,
- .mrindex = 0,
- }, {
.name = "sram",
.base = 0x01000000,
.size = 2 * MiB,
.mpc = 0,
.mrindex = 1,
}, {
- .name = "dtcm",
- .base = 0x20000000,
- .size = 4 * 128 * KiB,
- .mpc = -1,
- .mrindex = 2,
- }, {
.name = "sram 2",
.base = 0x21000000,
.size = 4 * MiB,
@@ -766,6 +750,14 @@ static uint32_t boot_ram_size(MPS2TZMachineState *mms)
const RAMInfo *p;
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
+ /*
+ * Use a per-board specification (for when the boot RAM is in
+ * the SSE and so doesn't have a RAMInfo list entry)
+ */
+ if (mmc->boot_ram_size) {
+ return mmc->boot_ram_size;
+ }
+
for (p = mmc->raminfo; p->name; p++) {
if (p->base == boot_mem_base(mms)) {
return p->size;
@@ -812,6 +804,7 @@ static void mps2tz_common_init(MachineState *machine)
OBJECT(system_memory), &error_abort);
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", mmc->numirq);
qdev_prop_set_uint32(iotkitdev, "init-svtor", mmc->init_svtor);
+ qdev_prop_set_uint32(iotkitdev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
@@ -1269,8 +1262,10 @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
mmc->numirq = 92;
mmc->uart_overflow_irq = 47;
mmc->init_svtor = 0x10000000;
+ mmc->sram_addr_width = 15;
mmc->raminfo = an505_raminfo;
mmc->armsse_type = TYPE_IOTKIT;
+ mmc->boot_ram_size = 0;
mps2tz_set_default_ram_info(mmc);
}
@@ -1296,8 +1291,10 @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
mmc->numirq = 92;
mmc->uart_overflow_irq = 47;
mmc->init_svtor = 0x10000000;
+ mmc->sram_addr_width = 15;
mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
mmc->armsse_type = TYPE_SSE200;
+ mmc->boot_ram_size = 0;
mps2tz_set_default_ram_info(mmc);
}
@@ -1323,8 +1320,10 @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
mmc->numirq = 95;
mmc->uart_overflow_irq = 47;
mmc->init_svtor = 0x10000000;
+ mmc->sram_addr_width = 15;
mmc->raminfo = an524_raminfo;
mmc->armsse_type = TYPE_SSE200;
+ mmc->boot_ram_size = 0;
mps2tz_set_default_ram_info(mmc);
object_class_property_add_str(oc, "remap", mps2_get_remap, mps2_set_remap);
@@ -1355,8 +1354,10 @@ static void mps3tz_an547_class_init(ObjectClass *oc, void *data)
mmc->numirq = 96;
mmc->uart_overflow_irq = 48;
mmc->init_svtor = 0x00000000;
+ mmc->sram_addr_width = 21;
mmc->raminfo = an547_raminfo;
mmc->armsse_type = TYPE_SSE300;
+ mmc->boot_ram_size = 512 * KiB;
mps2tz_set_default_ram_info(mmc);
}
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 7bed2ac520..01b60bee49 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -857,43 +857,45 @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova,
static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
{
- uint8_t scale = 0, num = 0, ttl = 0;
- dma_addr_t addr = CMD_ADDR(cmd);
+ dma_addr_t end, addr = CMD_ADDR(cmd);
uint8_t type = CMD_TYPE(cmd);
uint16_t vmid = CMD_VMID(cmd);
+ uint8_t scale = CMD_SCALE(cmd);
+ uint8_t num = CMD_NUM(cmd);
+ uint8_t ttl = CMD_TTL(cmd);
bool leaf = CMD_LEAF(cmd);
uint8_t tg = CMD_TG(cmd);
- uint64_t first_page = 0, last_page;
- uint64_t num_pages = 1;
+ uint64_t num_pages;
+ uint8_t granule;
int asid = -1;
- if (tg) {
- scale = CMD_SCALE(cmd);
- num = CMD_NUM(cmd);
- ttl = CMD_TTL(cmd);
- num_pages = (num + 1) * BIT_ULL(scale);
- }
-
if (type == SMMU_CMD_TLBI_NH_VA) {
asid = CMD_ASID(cmd);
}
- /* Split invalidations into ^2 range invalidations */
- last_page = num_pages - 1;
- while (num_pages) {
- uint8_t granule = tg * 2 + 10;
- uint64_t mask, count;
+ if (!tg) {
+ trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, 1, ttl, leaf);
+ smmuv3_inv_notifiers_iova(s, asid, addr, tg, 1);
+ smmu_iotlb_inv_iova(s, asid, addr, tg, 1, ttl);
+ return;
+ }
+
+ /* RIL in use */
- mask = dma_aligned_pow2_mask(first_page, last_page, 64 - granule);
- count = mask + 1;
+ num_pages = (num + 1) * BIT_ULL(scale);
+ granule = tg * 2 + 10;
+
+ /* Split invalidations into ^2 range invalidations */
+ end = addr + (num_pages << granule) - 1;
- trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, count, ttl, leaf);
- smmuv3_inv_notifiers_iova(s, asid, addr, tg, count);
- smmu_iotlb_inv_iova(s, asid, addr, tg, count, ttl);
+ while (addr != end + 1) {
+ uint64_t mask = dma_aligned_pow2_mask(addr, end, 64);
- num_pages -= count;
- first_page += count;
- addr += count * BIT_ULL(granule);
+ num_pages = (mask + 1) >> granule;
+ trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf);
+ smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages);
+ smmu_iotlb_inv_iova(s, asid, addr, tg, num_pages, ttl);
+ addr += mask + 1;
}
}
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index 43ef1d7a84..81f94c7f4a 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -1307,27 +1307,16 @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
GICv3CPUState *cs = icc_cs_from_env(env);
int irq = value & 0xffffff;
int grp;
+ bool is_eoir0 = ri->crm == 8;
- if (icv_access(env, ri->crm == 8 ? HCR_FMO : HCR_IMO)) {
+ if (icv_access(env, is_eoir0 ? HCR_FMO : HCR_IMO)) {
icv_eoir_write(env, ri, value);
return;
}
- trace_gicv3_icc_eoir_write(ri->crm == 8 ? 0 : 1,
+ trace_gicv3_icc_eoir_write(is_eoir0 ? 0 : 1,
gicv3_redist_affid(cs), value);
- if (ri->crm == 8) {
- /* EOIR0 */
- grp = GICV3_G0;
- } else {
- /* EOIR1 */
- if (arm_is_secure(env)) {
- grp = GICV3_G1;
- } else {
- grp = GICV3_G1NS;
- }
- }
-
if (irq >= cs->gic->num_irq) {
/* This handles two cases:
* 1. If software writes the ID of a spurious interrupt [ie 1020-1023]
@@ -1340,8 +1329,35 @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
return;
}
- if (icc_highest_active_group(cs) != grp) {
- return;
+ grp = icc_highest_active_group(cs);
+ switch (grp) {
+ case GICV3_G0:
+ if (!is_eoir0) {
+ return;
+ }
+ if (!(cs->gic->gicd_ctlr & GICD_CTLR_DS)
+ && arm_feature(env, ARM_FEATURE_EL3) && !arm_is_secure(env)) {
+ return;
+ }
+ break;
+ case GICV3_G1:
+ if (is_eoir0) {
+ return;
+ }
+ if (!arm_is_secure(env)) {
+ return;
+ }
+ break;
+ case GICV3_G1NS:
+ if (is_eoir0) {
+ return;
+ }
+ if (!arm_is_el3_or_mon(env) && arm_is_secure(env)) {
+ return;
+ }
+ break;
+ default:
+ g_assert_not_reached();
}
icc_drop_prio(cs, grp);