aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-07-14 17:32:53 +0100
committerPeter Maydell <peter.maydell@linaro.org>2016-07-14 17:32:53 +0100
commit14c7d99333e4a474c65bdae6f99aa8837e8078e6 (patch)
tree32c8874413f0ab109176d649557e1eb63c053805 /hw
parent1c8e93fb41c1ee37853ff7b85ebe1218a4a43780 (diff)
parent79a9f323a80b802ca98895d1c2d4aaf23cff815a (diff)
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20160714' into staging
target-arm queue: * add virtio-mmio transport base address to device path (avoid an assertion failure with multiple virtio-scsi-devices) * revert hw/ptimer commit 5a50307 which causes regressions on SPARC guests * use Neon to accelerate zero-page checking on AArch64 hosts * set the MPIDR for TCG to match how KVM does it (and fit with GICv2/GICv3 restrictions on SGI target lists) * add some missing AArch32 TLBI hypervisor TLB operations * m25p80: Fix QIOR/DIOR handling for Winbond * hw/misc: fix typo in Aspeed SCU hw-strap2 property name * ast2400: pretend DMAs are done for U-boot * ast2400: some minor code cleanups # gpg: Signature made Thu 14 Jul 2016 17:21:30 BST # gpg: using RSA key 0x3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20160714: ast2400: externalize revision numbers ast2400: pretend DMAs are done for U-boot ast2400: replace aspeed_smc_is_implemented() hw/misc: fix typo in Aspeed SCU hw-strap2 property name m25p80: Fix QIOR/DIOR handling for Winbond target-arm: Add missed AArch32 TLBI sytem registers hw/arm/virt: tcg: adjust MPIDR like KVM gic: provide defines for v2/v3 targetlist sizes target-arm: Use Neon for zero checking Revert "hw/ptimer: Perform counter wrap around if timer already expired" virtio-mmio: format transport base address in BusClass.get_dev_path Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/arm/ast2400.c2
-rw-r--r--hw/arm/virt.c25
-rw-r--r--hw/block/m25p80.c6
-rw-r--r--hw/core/ptimer.c9
-rw-r--r--hw/misc/aspeed_scu.c6
-rw-r--r--hw/ssi/aspeed_smc.c39
-rw-r--r--hw/virtio/virtio-mmio.c49
7 files changed, 100 insertions, 36 deletions
diff --git a/hw/arm/ast2400.c b/hw/arm/ast2400.c
index 0555843620..326fdb36ee 100644
--- a/hw/arm/ast2400.c
+++ b/hw/arm/ast2400.c
@@ -34,8 +34,6 @@
#define AST2400_FMC_FLASH_BASE 0x20000000
#define AST2400_SPI_FLASH_BASE 0x30000000
-#define AST2400_A0_SILICON_REV 0x02000303
-
static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
static const int timer_irqs[] = { 16, 17, 18, 35, 36, 37, 38, 39, };
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 4dafd42be8..a193b5a95b 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -52,7 +52,8 @@
#include "hw/arm/sysbus-fdt.h"
#include "hw/platform-bus.h"
#include "hw/arm/fdt.h"
-#include "hw/intc/arm_gic_common.h"
+#include "hw/intc/arm_gic.h"
+#include "hw/intc/arm_gicv3_common.h"
#include "kvm_arm.h"
#include "hw/smbios/smbios.h"
#include "qapi/visitor.h"
@@ -82,6 +83,7 @@ typedef struct VirtBoardInfo {
typedef struct {
MachineClass parent;
VirtBoardInfo *daughterboard;
+ bool disallow_affinity_adjustment;
} VirtMachineClass;
typedef struct {
@@ -1165,6 +1167,7 @@ void virt_guest_info_machine_done(Notifier *notifier, void *data)
static void machvirt_init(MachineState *machine)
{
VirtMachineState *vms = VIRT_MACHINE(machine);
+ VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine);
qemu_irq pic[NUM_IRQS];
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *secure_sysmem = NULL;
@@ -1181,6 +1184,7 @@ static void machvirt_init(MachineState *machine)
CPUClass *cc;
Error *err = NULL;
bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
+ uint8_t clustersz;
if (!cpu_model) {
cpu_model = "cortex-a15";
@@ -1226,8 +1230,10 @@ static void machvirt_init(MachineState *machine)
*/
if (gic_version == 3) {
virt_max_cpus = vbi->memmap[VIRT_GIC_REDIST].size / 0x20000;
+ clustersz = GICV3_TARGETLIST_BITS;
} else {
virt_max_cpus = GIC_NCPU;
+ clustersz = GIC_TARGETLIST_BITS;
}
if (max_cpus > virt_max_cpus) {
@@ -1281,6 +1287,20 @@ static void machvirt_init(MachineState *machine)
for (n = 0; n < smp_cpus; n++) {
Object *cpuobj = object_new(typename);
+ if (!vmc->disallow_affinity_adjustment) {
+ /* Adjust MPIDR like 64-bit KVM hosts, which incorporate the
+ * GIC's target-list limitations. 32-bit KVM hosts currently
+ * always create clusters of 4 CPUs, but that is expected to
+ * change when they gain support for gicv3. When KVM is enabled
+ * it will override the changes we make here, therefore our
+ * purposes are to make TCG consistent (with 64-bit KVM hosts)
+ * and to improve SGI efficiency.
+ */
+ uint8_t aff1 = n / clustersz;
+ uint8_t aff0 = n % clustersz;
+ object_property_set_int(cpuobj, (aff1 << ARM_AFF1_SHIFT) | aff0,
+ "mp-affinity", NULL);
+ }
if (!vms->secure) {
object_property_set_bool(cpuobj, false, "has_el3", NULL);
@@ -1507,7 +1527,10 @@ static void virt_2_6_instance_init(Object *obj)
static void virt_machine_2_6_options(MachineClass *mc)
{
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
+
virt_machine_2_7_options(mc);
SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_6);
+ vmc->disallow_affinity_adjustment = true;
}
DEFINE_VIRT_MACHINE(2, 6)
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index ca8c12c0f8..9828ee61d5 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -149,6 +149,7 @@ typedef struct FlashPartInfo {
*/
#define SPANSION_CONTINUOUS_READ_MODE_CMD_LEN 1
+#define WINBOND_CONTINUOUS_READ_MODE_CMD_LEN 1
static const FlashPartInfo known_devices[] = {
/* Atmel -- some are (confusingly) marketed as "DataFlash" */
@@ -777,7 +778,7 @@ static void decode_dio_read_cmd(Flash *s)
/* Dummy cycles modeled with bytes writes instead of bits */
switch (get_man(s)) {
case MAN_WINBOND:
- s->needed_bytes += 8;
+ s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN;
break;
case MAN_SPANSION:
s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN;
@@ -816,7 +817,8 @@ static void decode_qio_read_cmd(Flash *s)
/* Dummy cycles modeled with bytes writes instead of bits */
switch (get_man(s)) {
case MAN_WINBOND:
- s->needed_bytes += 8;
+ s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN;
+ s->needed_bytes += 4;
break;
case MAN_SPANSION:
s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN;
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
index 05b0c276eb..30829ee97b 100644
--- a/hw/core/ptimer.c
+++ b/hw/core/ptimer.c
@@ -93,7 +93,7 @@ uint64_t ptimer_get_count(ptimer_state *s)
bool oneshot = (s->enabled == 2);
/* Figure out the current counter value. */
- if (s->period == 0 || (expired && (oneshot || use_icount))) {
+ if (expired) {
/* Prevent timer underflowing if it should already have
triggered. */
counter = 0;
@@ -120,7 +120,7 @@ uint64_t ptimer_get_count(ptimer_state *s)
backwards.
*/
- rem = expired ? now - next : next - now;
+ rem = next - now;
div = period;
clz1 = clz64(rem);
@@ -140,11 +140,6 @@ uint64_t ptimer_get_count(ptimer_state *s)
div += 1;
}
counter = rem / div;
-
- if (expired && counter != 0) {
- /* Wrap around periodic counter. */
- counter = s->limit - (counter - 1) % s->limit;
- }
}
} else {
counter = s->delta;
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 23f51752b0..c7e2c8263f 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -88,8 +88,6 @@
#define PROT_KEY_UNLOCK 0x1688A8A8
#define SCU_IO_REGION_SIZE 0x20000
-#define AST2400_A0_SILICON_REV 0x02000303U
-
static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
[SYS_RST_CTRL] = 0xFFCFFEDCU,
[CLK_SEL] = 0xF3F40000U,
@@ -212,7 +210,7 @@ static void aspeed_scu_reset(DeviceState *dev)
static uint32_t aspeed_silicon_revs[] = { AST2400_A0_SILICON_REV, };
-static bool is_supported_silicon_rev(uint32_t silicon_rev)
+bool is_supported_silicon_rev(uint32_t silicon_rev)
{
int i;
@@ -255,7 +253,7 @@ static const VMStateDescription vmstate_aspeed_scu = {
static Property aspeed_scu_properties[] = {
DEFINE_PROP_UINT32("silicon-rev", AspeedSCUState, silicon_rev, 0),
DEFINE_PROP_UINT32("hw-strap1", AspeedSCUState, hw_strap1, 0),
- DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap1, 0),
+ DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap2, 0),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index a371e302d4..d319e04a27 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -273,6 +273,9 @@ static void aspeed_smc_reset(DeviceState *d)
memset(s->regs, 0, sizeof s->regs);
+ /* Pretend DMA is done (u-boot initialization) */
+ s->regs[R_INTR_CTRL] = INTR_CTRL_DMA_STATUS;
+
/* Unselect all slaves */
for (i = 0; i < s->num_cs; ++i) {
s->regs[s->r_ctrl0 + i] |= CTRL_CE_STOP_ACTIVE;
@@ -281,12 +284,6 @@ static void aspeed_smc_reset(DeviceState *d)
aspeed_smc_update_cs(s);
}
-static bool aspeed_smc_is_implemented(AspeedSMCState *s, hwaddr addr)
-{
- return (addr == s->r_conf || addr == s->r_timings || addr == s->r_ce_ctrl ||
- (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs));
-}
-
static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
{
AspeedSMCState *s = ASPEED_SMC(opaque);
@@ -300,13 +297,17 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
return 0;
}
- if (!aspeed_smc_is_implemented(s, addr)) {
+ if (addr == s->r_conf ||
+ addr == s->r_timings ||
+ addr == s->r_ce_ctrl ||
+ addr == R_INTR_CTRL ||
+ (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs)) {
+ return s->regs[addr];
+ } else {
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
- __func__, addr);
+ __func__, addr);
return 0;
}
-
- return s->regs[addr];
}
static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
@@ -324,20 +325,18 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
return;
}
- if (!aspeed_smc_is_implemented(s, addr)) {
+ if (addr == s->r_conf ||
+ addr == s->r_timings ||
+ addr == s->r_ce_ctrl) {
+ s->regs[addr] = value;
+ } else if (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs) {
+ s->regs[addr] = value;
+ aspeed_smc_update_cs(s);
+ } else {
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
__func__, addr);
return;
}
-
- /*
- * Not much to do apart from storing the value and set the cs
- * lines if the register is a controlling one.
- */
- s->regs[addr] = value;
- if (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs) {
- aspeed_smc_update_cs(s);
- }
}
static const MemoryRegionOps aspeed_smc_ops = {
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
index eb84b74532..13798b3cb8 100644
--- a/hw/virtio/virtio-mmio.c
+++ b/hw/virtio/virtio-mmio.c
@@ -91,6 +91,7 @@ typedef struct {
VirtioBusState bus;
bool ioeventfd_disabled;
bool ioeventfd_started;
+ bool format_transport_address;
} VirtIOMMIOProxy;
static bool virtio_mmio_ioeventfd_started(DeviceState *d)
@@ -469,6 +470,12 @@ assign_error:
/* virtio-mmio device */
+static Property virtio_mmio_properties[] = {
+ DEFINE_PROP_BOOL("format_transport_address", VirtIOMMIOProxy,
+ format_transport_address, true),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void virtio_mmio_realizefn(DeviceState *d, Error **errp)
{
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
@@ -489,6 +496,7 @@ static void virtio_mmio_class_init(ObjectClass *klass, void *data)
dc->realize = virtio_mmio_realizefn;
dc->reset = virtio_mmio_reset;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ dc->props = virtio_mmio_properties;
}
static const TypeInfo virtio_mmio_info = {
@@ -500,6 +508,46 @@ static const TypeInfo virtio_mmio_info = {
/* virtio-mmio-bus. */
+static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
+{
+ BusState *virtio_mmio_bus;
+ VirtIOMMIOProxy *virtio_mmio_proxy;
+ char *proxy_path;
+ SysBusDevice *proxy_sbd;
+ char *path;
+
+ virtio_mmio_bus = qdev_get_parent_bus(dev);
+ virtio_mmio_proxy = VIRTIO_MMIO(virtio_mmio_bus->parent);
+ proxy_path = qdev_get_dev_path(DEVICE(virtio_mmio_proxy));
+
+ /*
+ * If @format_transport_address is false, then we just perform the same as
+ * virtio_bus_get_dev_path(): we delegate the address formatting for the
+ * device on the virtio-mmio bus to the bus that the virtio-mmio proxy
+ * (i.e., the device that implements the virtio-mmio bus) resides on. In
+ * this case the base address of the virtio-mmio transport will be
+ * invisible.
+ */
+ if (!virtio_mmio_proxy->format_transport_address) {
+ return proxy_path;
+ }
+
+ /* Otherwise, we append the base address of the transport. */
+ proxy_sbd = SYS_BUS_DEVICE(virtio_mmio_proxy);
+ assert(proxy_sbd->num_mmio == 1);
+ assert(proxy_sbd->mmio[0].memory == &virtio_mmio_proxy->iomem);
+
+ if (proxy_path) {
+ path = g_strdup_printf("%s/virtio-mmio@" TARGET_FMT_plx, proxy_path,
+ proxy_sbd->mmio[0].addr);
+ } else {
+ path = g_strdup_printf("virtio-mmio@" TARGET_FMT_plx,
+ proxy_sbd->mmio[0].addr);
+ }
+ g_free(proxy_path);
+ return path;
+}
+
static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data)
{
BusClass *bus_class = BUS_CLASS(klass);
@@ -516,6 +564,7 @@ static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data)
k->ioeventfd_assign = virtio_mmio_ioeventfd_assign;
k->has_variable_vring_alignment = true;
bus_class->max_dev = 1;
+ bus_class->get_dev_path = virtio_mmio_bus_get_dev_path;
}
static const TypeInfo virtio_mmio_bus_info = {