target-arm queue:

* report ARMv8-A FP support for AArch32 -cpu max
  * hw/ssi/xilinx_spips: Avoid AXI writes to the LQSPI linear memory
  * hw/ssi/xilinx_spips: Avoid out-of-bound access to lqspi_buf[]
  * hw/ssi/mss-spi: Avoid crash when reading empty RX FIFO
  * hw/display/xlnx_dp: Avoid crash when reading empty RX FIFO
  * hw/arm/virt: Fix non-secure flash mode
  * pl031: Correctly migrate state when using -rtc clock=host
  * fix regression that meant arm926 and arm1026 lost VFP
    double-precision support
  * v8M: NS BusFault on vector table fetch escalates to NS HardFault
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAl0sgoUZHHBldGVyLm1h
 eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3m8UEAClHrOpyfFdOdlkjh6QTvvE
 dxsKVVtQ7hy0pH98LA9QrFwLq5e8N+RpJQfPipKgoQ1l/I/l1/1KV41R38mubcdB
 CcJTOX/BZuC8I9IHOX1oA9UJh9WMrEL/52lhYuzFD03mWPS28nUO8jRsM9pqYJ/3
 KRNy20t0G13omq+BVPlj974J2SCHS2cJ67l3FPkxm1c+VR3MWPb2I3U30w9HRxCj
 9so+QSw4cJ6lU5uJU/zXcsyFWR0h8p0lNZ6yfKtsm8mxqgKdNSKnNa7yLP+ODEBe
 GFDkOrTLrZcTU9Dw9IocRYBOZeFoRJdlkVVPeOju7eX8W4CdvKf2MxLaJu7uT+Qj
 CB3+kBJ1cCMDWW+JSlXuDRl9Uvk/a28AAT8LdWbjjKKcVZvGlONKb7o6vhsPPcjY
 YKTrbwac+D287f2RKrUv5aVcNr/9bd+bEpkqFBayz+hoJU1xfji+wiSOL1hbzWeD
 isuFrBphscAKdM7i7+Pn/wiL8jy428ZwVh7+SaR1WBqtOyk8BaC3vBPOlwacun94
 US2WYVXuQRFfZPQSTf3ZWatcK4aelZJqlFZkGDtBfHyWRFOuG2HEKtA24BuU9mex
 U6e69gvNJfAKpaZ3bsNpAzW+1RGtn7ztVw0BkICPiiEMfc/ivGa9T0VJF9IEbMUY
 2rAh/QP0g5rwla4hSa3AwQ==
 =1077
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20190715' into staging

target-arm queue:
 * report ARMv8-A FP support for AArch32 -cpu max
 * hw/ssi/xilinx_spips: Avoid AXI writes to the LQSPI linear memory
 * hw/ssi/xilinx_spips: Avoid out-of-bound access to lqspi_buf[]
 * hw/ssi/mss-spi: Avoid crash when reading empty RX FIFO
 * hw/display/xlnx_dp: Avoid crash when reading empty RX FIFO
 * hw/arm/virt: Fix non-secure flash mode
 * pl031: Correctly migrate state when using -rtc clock=host
 * fix regression that meant arm926 and arm1026 lost VFP
   double-precision support
 * v8M: NS BusFault on vector table fetch escalates to NS HardFault

# gpg: Signature made Mon 15 Jul 2019 14:41:25 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-20190715:
  target/arm: NS BusFault on vector table fetch escalates to NS HardFault
  target/arm: Set VFP-related MVFR0 fields for arm926 and arm1026
  pl031: Correctly migrate state when using -rtc clock=host
  hw/arm/virt: Fix non-secure flash mode
  hw/display/xlnx_dp: Avoid crash when reading empty RX FIFO
  hw/ssi/mss-spi: Avoid crash when reading empty RX FIFO
  hw/ssi/xilinx_spips: Avoid out-of-bound access to lqspi_buf[]
  hw/ssi/xilinx_spips: Avoid AXI writes to the LQSPI linear memory
  hw/ssi/xilinx_spips: Convert lqspi_read() to read_with_attrs
  target/arm: report ARMv8-A FP support for AArch32 -cpu max

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-07-15 14:42:43 +01:00
commit 0dc6284710
9 changed files with 174 additions and 26 deletions

View File

@ -1674,7 +1674,7 @@ static void machvirt_init(MachineState *machine)
&machine->device_memory->mr);
}
virt_flash_fdt(vms, sysmem, secure_sysmem);
virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem);
create_gic(vms, pic);

View File

@ -35,6 +35,7 @@ GlobalProperty hw_compat_4_0[] = {
{ "virtio-gpu-pci", "edid", "false" },
{ "virtio-device", "use-started", "false" },
{ "virtio-balloon-device", "qemu-4-0-config-size", "true" },
{ "pl031", "migrate-tick-offset", "false" },
};
const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);

View File

@ -427,11 +427,18 @@ static uint8_t xlnx_dp_aux_pop_rx_fifo(XlnxDPState *s)
uint8_t ret;
if (fifo8_is_empty(&s->rx_fifo)) {
DPRINTF("rx_fifo underflow..\n");
abort();
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Reading empty RX_FIFO\n",
__func__);
/*
* The datasheet is not clear about the reset value, it seems
* to be unspecified. We choose to return '0'.
*/
ret = 0;
} else {
ret = fifo8_pop(&s->rx_fifo);
DPRINTF("pop 0x%" PRIX8 " from rx_fifo.\n", ret);
}
ret = fifo8_pop(&s->rx_fifo);
DPRINTF("pop 0x%" PRIX8 " from rx_fifo.\n", ret);
return ret;
}

View File

@ -165,7 +165,13 @@ spi_read(void *opaque, hwaddr addr, unsigned int size)
case R_SPI_RX:
s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL;
s->regs[R_SPI_STATUS] &= ~S_RXCHOVRF;
ret = fifo32_pop(&s->rx_fifo);
if (fifo32_is_empty(&s->rx_fifo)) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Reading empty RX_FIFO\n",
__func__);
} else {
ret = fifo32_pop(&s->rx_fifo);
}
if (fifo32_is_empty(&s->rx_fifo)) {
s->regs[R_SPI_STATUS] |= S_RXFIFOEMP;
}

View File

@ -1202,28 +1202,47 @@ static void lqspi_load_cache(void *opaque, hwaddr addr)
}
}
static uint64_t
lqspi_read(void *opaque, hwaddr addr, unsigned int size)
static MemTxResult lqspi_read(void *opaque, hwaddr addr, uint64_t *value,
unsigned size, MemTxAttrs attrs)
{
XilinxQSPIPS *q = opaque;
uint32_t ret;
XilinxQSPIPS *q = XILINX_QSPIPS(opaque);
if (addr >= q->lqspi_cached_addr &&
addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
uint8_t *retp = &q->lqspi_buf[addr - q->lqspi_cached_addr];
ret = cpu_to_le32(*(uint32_t *)retp);
DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr,
(unsigned)ret);
return ret;
} else {
lqspi_load_cache(opaque, addr);
return lqspi_read(opaque, addr, size);
*value = cpu_to_le32(*(uint32_t *)retp);
DB_PRINT_L(1, "addr: %08" HWADDR_PRIx ", data: %08" PRIx64 "\n",
addr, *value);
return MEMTX_OK;
}
lqspi_load_cache(opaque, addr);
return lqspi_read(opaque, addr, value, size, attrs);
}
static MemTxResult lqspi_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size, MemTxAttrs attrs)
{
/*
* From UG1085, Chapter 24 (Quad-SPI controllers):
* - Writes are ignored
* - AXI writes generate an external AXI slave error (SLVERR)
*/
qemu_log_mask(LOG_GUEST_ERROR, "%s Unexpected %u-bit access to 0x%" PRIx64
" (value: 0x%" PRIx64 "\n",
__func__, size << 3, offset, value);
return MEMTX_ERROR;
}
static const MemoryRegionOps lqspi_ops = {
.read = lqspi_read,
.read_with_attrs = lqspi_read,
.write_with_attrs = lqspi_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.impl = {
.min_access_size = 4,
.max_access_size = 4,
},
.valid = {
.min_access_size = 1,
.max_access_size = 4

View File

@ -199,29 +199,94 @@ static int pl031_pre_save(void *opaque)
{
PL031State *s = opaque;
/* tick_offset is base_time - rtc_clock base time. Instead, we want to
* store the base time relative to the QEMU_CLOCK_VIRTUAL for backwards-compatibility. */
/*
* The PL031 device model code uses the tick_offset field, which is
* the offset between what the guest RTC should read and what the
* QEMU rtc_clock reads:
* guest_rtc = rtc_clock + tick_offset
* and so
* tick_offset = guest_rtc - rtc_clock
*
* We want to migrate this offset, which sounds straightforward.
* Unfortunately older versions of QEMU migrated a conversion of this
* offset into an offset from the vm_clock. (This was in turn an
* attempt to be compatible with even older QEMU versions, but it
* has incorrect behaviour if the rtc_clock is not the same as the
* vm_clock.) So we put the actual tick_offset into a migration
* subsection, and the backwards-compatible time-relative-to-vm_clock
* in the main migration state.
*
* Calculate base time relative to QEMU_CLOCK_VIRTUAL:
*/
int64_t delta = qemu_clock_get_ns(rtc_clock) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->tick_offset_vmstate = s->tick_offset + delta / NANOSECONDS_PER_SECOND;
return 0;
}
static int pl031_pre_load(void *opaque)
{
PL031State *s = opaque;
s->tick_offset_migrated = false;
return 0;
}
static int pl031_post_load(void *opaque, int version_id)
{
PL031State *s = opaque;
int64_t delta = qemu_clock_get_ns(rtc_clock) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->tick_offset = s->tick_offset_vmstate - delta / NANOSECONDS_PER_SECOND;
/*
* If we got the tick_offset subsection, then we can just use
* the value in that. Otherwise the source is an older QEMU and
* has given us the offset from the vm_clock; convert it back to
* an offset from the rtc_clock. This will cause time to incorrectly
* go backwards compared to the host RTC, but this is unavoidable.
*/
if (!s->tick_offset_migrated) {
int64_t delta = qemu_clock_get_ns(rtc_clock) -
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->tick_offset = s->tick_offset_vmstate -
delta / NANOSECONDS_PER_SECOND;
}
pl031_set_alarm(s);
return 0;
}
static int pl031_tick_offset_post_load(void *opaque, int version_id)
{
PL031State *s = opaque;
s->tick_offset_migrated = true;
return 0;
}
static bool pl031_tick_offset_needed(void *opaque)
{
PL031State *s = opaque;
return s->migrate_tick_offset;
}
static const VMStateDescription vmstate_pl031_tick_offset = {
.name = "pl031/tick-offset",
.version_id = 1,
.minimum_version_id = 1,
.needed = pl031_tick_offset_needed,
.post_load = pl031_tick_offset_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT32(tick_offset, PL031State),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_pl031 = {
.name = "pl031",
.version_id = 1,
.minimum_version_id = 1,
.pre_save = pl031_pre_save,
.pre_load = pl031_pre_load,
.post_load = pl031_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT32(tick_offset_vmstate, PL031State),
@ -231,14 +296,33 @@ static const VMStateDescription vmstate_pl031 = {
VMSTATE_UINT32(im, PL031State),
VMSTATE_UINT32(is, PL031State),
VMSTATE_END_OF_LIST()
},
.subsections = (const VMStateDescription*[]) {
&vmstate_pl031_tick_offset,
NULL
}
};
static Property pl031_properties[] = {
/*
* True to correctly migrate the tick offset of the RTC. False to
* obtain backward migration compatibility with older QEMU versions,
* at the expense of the guest RTC going backwards compared with the
* host RTC when the VM is saved/restored if using -rtc host.
* (Even if set to 'true' older QEMU can migrate forward to newer QEMU;
* 'false' also permits newer QEMU to migrate to older QEMU.)
*/
DEFINE_PROP_BOOL("migrate-tick-offset",
PL031State, migrate_tick_offset, true),
DEFINE_PROP_END_OF_LIST()
};
static void pl031_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->vmsd = &vmstate_pl031;
dc->props = pl031_properties;
}
static const TypeInfo pl031_info = {

View File

@ -33,6 +33,8 @@ typedef struct PL031State {
*/
uint32_t tick_offset_vmstate;
uint32_t tick_offset;
bool tick_offset_migrated;
bool migrate_tick_offset;
uint32_t mr;
uint32_t lr;

View File

@ -1666,6 +1666,12 @@ static void arm926_initfn(Object *obj)
* set the field to indicate Jazelle support within QEMU.
*/
cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1);
/*
* Similarly, we need to set MVFR0 fields to enable double precision
* and short vector support even though ARMv5 doesn't have this register.
*/
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1);
}
static void arm946_initfn(Object *obj)
@ -1702,6 +1708,12 @@ static void arm1026_initfn(Object *obj)
* set the field to indicate Jazelle support within QEMU.
*/
cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1);
/*
* Similarly, we need to set MVFR0 fields to enable double precision
* and short vector support even though ARMv5 doesn't have this register.
*/
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1);
{
/* The 1026 had an IFAR at c6,c0,0,1 rather than the ARMv6 c6,c0,0,2 */
@ -2452,6 +2464,10 @@ static void arm_max_initfn(Object *obj)
t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
cpu->isar.id_isar6 = t;
t = cpu->isar.mvfr1;
t = FIELD_DP32(t, MVFR1, FPHP, 2); /* v8.0 FP support */
cpu->isar.mvfr1 = t;
t = cpu->isar.mvfr2;
t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */
t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */

View File

@ -624,7 +624,11 @@ static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure,
if (sattrs.ns) {
attrs.secure = false;
} else if (!targets_secure) {
/* NS access to S memory */
/*
* NS access to S memory: the underlying exception which we escalate
* to HardFault is SecureFault, which always targets Secure.
*/
exc_secure = true;
goto load_fail;
}
}
@ -632,6 +636,11 @@ static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure,
vector_entry = address_space_ldl(arm_addressspace(cs, attrs), addr,
attrs, &result);
if (result != MEMTX_OK) {
/*
* Underlying exception is BusFault: its target security state
* depends on BFHFNMINS.
*/
exc_secure = !(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK);
goto load_fail;
}
*pvec = vector_entry;
@ -641,13 +650,17 @@ load_fail:
/*
* All vector table fetch fails are reported as HardFault, with
* HFSR.VECTTBL and .FORCED set. (FORCED is set because
* technically the underlying exception is a MemManage or BusFault
* technically the underlying exception is a SecureFault or BusFault
* that is escalated to HardFault.) This is a terminal exception,
* so we will either take the HardFault immediately or else enter
* lockup (the latter case is handled in armv7m_nvic_set_pending_derived()).
* The HardFault is Secure if BFHFNMINS is 0 (meaning that all HFs are
* secure); otherwise it targets the same security state as the
* underlying exception.
*/
exc_secure = targets_secure ||
!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK);
if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
exc_secure = true;
}
env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK | R_V7M_HFSR_FORCED_MASK;
armv7m_nvic_set_pending_derived(env->nvic, ARMV7M_EXCP_HARD, exc_secure);
return false;