summaryrefslogtreecommitdiffstats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/arm/xlnx-zynqmp.c2
-rw-r--r--hw/intc/armv7m_nvic.c158
-rw-r--r--hw/sd/sd.c12
3 files changed, 165 insertions, 7 deletions
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 2b27daf51d..d4b6560194 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -440,6 +440,8 @@ static void xlnx_zynqmp_class_init(ObjectClass *oc, void *data)
dc->props = xlnx_zynqmp_props;
dc->realize = xlnx_zynqmp_realize;
+ /* Reason: Uses serial_hds in realize function, thus can't be used twice */
+ dc->user_creatable = false;
}
static const TypeInfo xlnx_zynqmp_type_info = {
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index d90d8d0784..22d5e6e6af 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -616,7 +616,7 @@ bool armv7m_nvic_acknowledge_irq(void *opaque)
vec->active = 1;
vec->pending = 0;
- env->v7m.exception = s->vectpending;
+ write_v7m_exception(env, s->vectpending);
nvic_irq_update(s);
@@ -1017,6 +1017,76 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
goto bad_offset;
}
return cpu->env.pmsav8.mair1[attrs.secure];
+ case 0xdd0: /* SAU_CTRL */
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
+ goto bad_offset;
+ }
+ if (!attrs.secure) {
+ return 0;
+ }
+ return cpu->env.sau.ctrl;
+ case 0xdd4: /* SAU_TYPE */
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
+ goto bad_offset;
+ }
+ if (!attrs.secure) {
+ return 0;
+ }
+ return cpu->sau_sregion;
+ case 0xdd8: /* SAU_RNR */
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
+ goto bad_offset;
+ }
+ if (!attrs.secure) {
+ return 0;
+ }
+ return cpu->env.sau.rnr;
+ case 0xddc: /* SAU_RBAR */
+ {
+ int region = cpu->env.sau.rnr;
+
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
+ goto bad_offset;
+ }
+ if (!attrs.secure) {
+ return 0;
+ }
+ if (region >= cpu->sau_sregion) {
+ return 0;
+ }
+ return cpu->env.sau.rbar[region];
+ }
+ case 0xde0: /* SAU_RLAR */
+ {
+ int region = cpu->env.sau.rnr;
+
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
+ goto bad_offset;
+ }
+ if (!attrs.secure) {
+ return 0;
+ }
+ if (region >= cpu->sau_sregion) {
+ return 0;
+ }
+ return cpu->env.sau.rlar[region];
+ }
+ case 0xde4: /* SFSR */
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
+ goto bad_offset;
+ }
+ if (!attrs.secure) {
+ return 0;
+ }
+ return cpu->env.v7m.sfsr;
+ case 0xde8: /* SFAR */
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
+ goto bad_offset;
+ }
+ if (!attrs.secure) {
+ return 0;
+ }
+ return cpu->env.v7m.sfar;
default:
bad_offset:
qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset);
@@ -1160,6 +1230,7 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
s->sec_vectors[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
s->sec_vectors[ARMV7M_EXCP_USAGE].enabled =
(value & (1 << 18)) != 0;
+ s->sec_vectors[ARMV7M_EXCP_HARD].pending = (value & (1 << 21)) != 0;
/* SecureFault not banked, but RAZ/WI to NS */
s->vectors[ARMV7M_EXCP_SECURE].active = (value & (1 << 4)) != 0;
s->vectors[ARMV7M_EXCP_SECURE].enabled = (value & (1 << 19)) != 0;
@@ -1368,6 +1439,86 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
* only affect cacheability, and we don't implement caching.
*/
break;
+ case 0xdd0: /* SAU_CTRL */
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
+ goto bad_offset;
+ }
+ if (!attrs.secure) {
+ return;
+ }
+ cpu->env.sau.ctrl = value & 3;
+ case 0xdd4: /* SAU_TYPE */
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
+ goto bad_offset;
+ }
+ break;
+ case 0xdd8: /* SAU_RNR */
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
+ goto bad_offset;
+ }
+ if (!attrs.secure) {
+ return;
+ }
+ if (value >= cpu->sau_sregion) {
+ qemu_log_mask(LOG_GUEST_ERROR, "SAU region out of range %"
+ PRIu32 "/%" PRIu32 "\n",
+ value, cpu->sau_sregion);
+ } else {
+ cpu->env.sau.rnr = value;
+ }
+ break;
+ case 0xddc: /* SAU_RBAR */
+ {
+ int region = cpu->env.sau.rnr;
+
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
+ goto bad_offset;
+ }
+ if (!attrs.secure) {
+ return;
+ }
+ if (region >= cpu->sau_sregion) {
+ return;
+ }
+ cpu->env.sau.rbar[region] = value & ~0x1f;
+ tlb_flush(CPU(cpu));
+ break;
+ }
+ case 0xde0: /* SAU_RLAR */
+ {
+ int region = cpu->env.sau.rnr;
+
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
+ goto bad_offset;
+ }
+ if (!attrs.secure) {
+ return;
+ }
+ if (region >= cpu->sau_sregion) {
+ return;
+ }
+ cpu->env.sau.rlar[region] = value & ~0x1c;
+ tlb_flush(CPU(cpu));
+ break;
+ }
+ case 0xde4: /* SFSR */
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
+ goto bad_offset;
+ }
+ if (!attrs.secure) {
+ return;
+ }
+ cpu->env.v7m.sfsr &= ~value; /* W1C */
+ break;
+ case 0xde8: /* SFAR */
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
+ goto bad_offset;
+ }
+ if (!attrs.secure) {
+ return;
+ }
+ cpu->env.v7m.sfsr = value;
+ break;
case 0xf00: /* Software Triggered Interrupt Register */
{
int excnum = (value & 0x1ff) + NVIC_FIRST_IRQ;
@@ -1782,6 +1933,11 @@ static void armv7m_nvic_reset(DeviceState *dev)
int resetprio;
NVICState *s = NVIC(dev);
+ memset(s->vectors, 0, sizeof(s->vectors));
+ memset(s->sec_vectors, 0, sizeof(s->sec_vectors));
+ s->prigroup[M_REG_NS] = 0;
+ s->prigroup[M_REG_S] = 0;
+
s->vectors[ARMV7M_EXCP_NMI].enabled = 1;
/* MEM, BUS, and USAGE are enabled through
* the System Handler Control register
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index ba47bff4db..35347a5bbc 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1797,8 +1797,13 @@ uint8_t sd_read_data(SDState *sd)
break;
case 18: /* CMD18: READ_MULTIPLE_BLOCK */
- if (sd->data_offset == 0)
+ if (sd->data_offset == 0) {
+ if (sd->data_start + io_len > sd->size) {
+ sd->card_status |= ADDRESS_ERROR;
+ return 0x00;
+ }
BLK_READ_BLOCK(sd->data_start, io_len);
+ }
ret = sd->data[sd->data_offset ++];
if (sd->data_offset >= io_len) {
@@ -1812,11 +1817,6 @@ uint8_t sd_read_data(SDState *sd)
break;
}
}
-
- if (sd->data_start + io_len > sd->size) {
- sd->card_status |= ADDRESS_ERROR;
- break;
- }
}
break;