* [Qemu-devel] [PATCH 1/7] pseries: Convert VIO code to QOM style type safe(ish) casts
2013-04-08 5:08 [Qemu-devel] [0/7] Pending pseries updates David Gibson
@ 2013-04-08 5:08 ` David Gibson
2013-04-08 5:08 ` [Qemu-devel] [PATCH 2/7] pseries: Generate device paths for VIO devices David Gibson
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: David Gibson @ 2013-04-08 5:08 UTC (permalink / raw)
To: agraf; +Cc: qemu-ppc, qemu-devel, David Gibson
Curerntly the pseries VIO device code contains quite a few explicit
uses of DO_UPCAST and plain C casts. This is (obviously) type unsafe,
and not the conventional way of doing things in the QOM model. This
patch converts the code to use the QOM convention of per-type macros
to do verified casts with OBJECT_CHECK().
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
hw/ppc/spapr_vio.c | 4 ++--
hw/spapr_llan.c | 24 ++++++++++++++----------
hw/spapr_nvram.c | 10 +++++++---
hw/spapr_vscsi.c | 15 +++++++++------
hw/spapr_vty.c | 18 +++++++++++-------
5 files changed, 43 insertions(+), 28 deletions(-)
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 6eb3ab5..614b4a8 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -379,7 +379,7 @@ static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
* the given dev might already be in the list.
*/
QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
- other = DO_UPCAST(VIOsPAPRDevice, qdev, kid->child);
+ other = VIO_SPAPR_DEVICE(kid->child);
if (other != dev && other->reg == dev->reg) {
return other;
@@ -391,7 +391,7 @@ static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
static void spapr_vio_busdev_reset(DeviceState *qdev)
{
- VIOsPAPRDevice *dev = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
+ VIOsPAPRDevice *dev = VIO_SPAPR_DEVICE(qdev);
VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
/* Shut down the request queue and TCEs if necessary */
diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c
index 19701e7..e5d6f87 100644
--- a/hw/spapr_llan.c
+++ b/hw/spapr_llan.c
@@ -73,6 +73,10 @@ typedef uint64_t vlan_bd_t;
#define VLAN_RX_BDS_OFF 16
#define VLAN_MAX_BUFS ((SPAPR_TCE_PAGE_SIZE - VLAN_RX_BDS_OFF) / 8)
+#define TYPE_VIO_SPAPR_VLAN_DEVICE "spapr-vlan"
+#define VIO_SPAPR_VLAN_DEVICE(obj) \
+ OBJECT_CHECK(VIOsPAPRVLANDevice, (obj), TYPE_VIO_SPAPR_VLAN_DEVICE)
+
typedef struct VIOsPAPRVLANDevice {
VIOsPAPRDevice sdev;
NICConf nicconf;
@@ -93,8 +97,8 @@ static int spapr_vlan_can_receive(NetClientState *nc)
static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
size_t size)
{
- VIOsPAPRDevice *sdev = qemu_get_nic_opaque(nc);
- VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+ VIOsPAPRVLANDevice *dev = qemu_get_nic_opaque(nc);
+ VIOsPAPRDevice *sdev = VIO_SPAPR_DEVICE(dev);
vlan_bd_t rxq_bd = vio_ldq(sdev, dev->buf_list + VLAN_RXQ_BD_OFF);
vlan_bd_t bd;
int buf_ptr = dev->use_buf_ptr;
@@ -192,7 +196,7 @@ static NetClientInfo net_spapr_vlan_info = {
static void spapr_vlan_reset(VIOsPAPRDevice *sdev)
{
- VIOsPAPRVLANDevice *dev = DO_UPCAST(VIOsPAPRVLANDevice, sdev, sdev);
+ VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
dev->buf_list = 0;
dev->rx_bufs = 0;
@@ -201,7 +205,7 @@ static void spapr_vlan_reset(VIOsPAPRDevice *sdev)
static int spapr_vlan_init(VIOsPAPRDevice *sdev)
{
- VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+ VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
qemu_macaddr_default_if_unset(&dev->nicconf.macaddr);
@@ -225,7 +229,7 @@ void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd)
static int spapr_vlan_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
{
- VIOsPAPRVLANDevice *vdev = (VIOsPAPRVLANDevice *)dev;
+ VIOsPAPRVLANDevice *vdev = VIO_SPAPR_VLAN_DEVICE(dev);
uint8_t padded_mac[8] = {0, 0};
int ret;
@@ -282,7 +286,7 @@ static target_ulong h_register_logical_lan(PowerPCCPU *cpu,
target_ulong rec_queue = args[2];
target_ulong filter_list = args[3];
VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
- VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+ VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
vlan_bd_t filter_list_bd;
if (!dev) {
@@ -341,7 +345,7 @@ static target_ulong h_free_logical_lan(PowerPCCPU *cpu, sPAPREnvironment *spapr,
{
target_ulong reg = args[0];
VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
- VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+ VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
if (!dev) {
return H_PARAMETER;
@@ -365,7 +369,7 @@ static target_ulong h_add_logical_lan_buffer(PowerPCCPU *cpu,
target_ulong reg = args[0];
target_ulong buf = args[1];
VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
- VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+ VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
vlan_bd_t bd;
dprintf("H_ADD_LOGICAL_LAN_BUFFER(0x" TARGET_FMT_lx
@@ -413,7 +417,7 @@ static target_ulong h_send_logical_lan(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong *bufs = args + 1;
target_ulong continue_token = args[7];
VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
- VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
+ VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
unsigned total_len;
uint8_t *lbuf, *p;
int i, nbufs;
@@ -511,7 +515,7 @@ static void spapr_vlan_class_init(ObjectClass *klass, void *data)
}
static const TypeInfo spapr_vlan_info = {
- .name = "spapr-vlan",
+ .name = TYPE_VIO_SPAPR_VLAN_DEVICE,
.parent = TYPE_VIO_SPAPR_DEVICE,
.instance_size = sizeof(VIOsPAPRVLANDevice),
.class_init = spapr_vlan_class_init,
diff --git a/hw/spapr_nvram.c b/hw/spapr_nvram.c
index 680cdba..aebc110 100644
--- a/hw/spapr_nvram.c
+++ b/hw/spapr_nvram.c
@@ -36,6 +36,10 @@ typedef struct sPAPRNVRAM {
BlockDriverState *drive;
} sPAPRNVRAM;
+#define TYPE_VIO_SPAPR_NVRAM "spapr-nvram"
+#define VIO_SPAPR_NVRAM(obj) \
+ OBJECT_CHECK(sPAPRNVRAM, (obj), TYPE_VIO_SPAPR_NVRAM)
+
#define MIN_NVRAM_SIZE 8192
#define DEFAULT_NVRAM_SIZE 65536
#define MAX_NVRAM_SIZE (UINT16_MAX * 16)
@@ -134,7 +138,7 @@ static void rtas_nvram_store(sPAPREnvironment *spapr,
static int spapr_nvram_init(VIOsPAPRDevice *dev)
{
- sPAPRNVRAM *nvram = (sPAPRNVRAM *)dev;
+ sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(dev);
if (nvram->drive) {
nvram->size = bdrv_getlength(nvram->drive);
@@ -157,7 +161,7 @@ static int spapr_nvram_init(VIOsPAPRDevice *dev)
static int spapr_nvram_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
{
- sPAPRNVRAM *nvram = (sPAPRNVRAM *)dev;
+ sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(dev);
return fdt_setprop_cell(fdt, node_off, "#bytes", nvram->size);
}
@@ -182,7 +186,7 @@ static void spapr_nvram_class_init(ObjectClass *klass, void *data)
}
static const TypeInfo spapr_nvram_type_info = {
- .name = "spapr-nvram",
+ .name = TYPE_VIO_SPAPR_NVRAM,
.parent = TYPE_VIO_SPAPR_DEVICE,
.instance_size = sizeof(sPAPRNVRAM),
.class_init = spapr_nvram_class_init,
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 2794094..493e702 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -91,6 +91,9 @@ typedef struct vscsi_req {
int total_desc;
} vscsi_req;
+#define TYPE_VIO_SPAPR_VSCSI_DEVICE "spapr-vscsi"
+#define VIO_SPAPR_VSCSI_DEVICE(obj) \
+ OBJECT_CHECK(VSCSIState, (obj), TYPE_VIO_SPAPR_VSCSI_DEVICE)
typedef struct {
VIOsPAPRDevice vdev;
@@ -461,7 +464,7 @@ static int vscsi_preprocess_desc(vscsi_req *req)
/* Callback to indicate that the SCSI layer has completed a transfer. */
static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len)
{
- VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
+ VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(sreq->bus->qbus.parent);
vscsi_req *req = sreq->hba_private;
uint8_t *buf;
int rc = 0;
@@ -492,7 +495,7 @@ static void vscsi_transfer_data(SCSIRequest *sreq, uint32_t len)
/* Callback to indicate that the SCSI layer has completed a transfer. */
static void vscsi_command_complete(SCSIRequest *sreq, uint32_t status, size_t resid)
{
- VSCSIState *s = DO_UPCAST(VSCSIState, vdev.qdev, sreq->bus->qbus.parent);
+ VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(sreq->bus->qbus.parent);
vscsi_req *req = sreq->hba_private;
int32_t res_in = 0, res_out = 0;
@@ -827,7 +830,7 @@ static void vscsi_got_payload(VSCSIState *s, vscsi_crq *crq)
static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t *crq_data)
{
- VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev);
+ VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev);
vscsi_crq crq;
memcpy(crq.raw, crq_data, 16);
@@ -897,7 +900,7 @@ static const struct SCSIBusInfo vscsi_scsi_info = {
static void spapr_vscsi_reset(VIOsPAPRDevice *dev)
{
- VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev);
+ VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev);
int i;
memset(s->reqs, 0, sizeof(s->reqs));
@@ -908,7 +911,7 @@ static void spapr_vscsi_reset(VIOsPAPRDevice *dev)
static int spapr_vscsi_init(VIOsPAPRDevice *dev)
{
- VSCSIState *s = DO_UPCAST(VSCSIState, vdev, dev);
+ VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(dev);
dev->crq.SendFunc = vscsi_do_crq;
@@ -968,7 +971,7 @@ static void spapr_vscsi_class_init(ObjectClass *klass, void *data)
}
static const TypeInfo spapr_vscsi_info = {
- .name = "spapr-vscsi",
+ .name = TYPE_VIO_SPAPR_VSCSI_DEVICE,
.parent = TYPE_VIO_SPAPR_DEVICE,
.instance_size = sizeof(VSCSIState),
.class_init = spapr_vscsi_class_init,
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index be08571..764316e 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -12,16 +12,20 @@ typedef struct VIOsPAPRVTYDevice {
uint8_t buf[VTERM_BUFSIZE];
} VIOsPAPRVTYDevice;
+#define TYPE_VIO_SPAPR_VTY_DEVICE "spapr-vty"
+#define VIO_SPAPR_VTY_DEVICE(obj) \
+ OBJECT_CHECK(VIOsPAPRVTYDevice, (obj), TYPE_VIO_SPAPR_VTY_DEVICE)
+
static int vty_can_receive(void *opaque)
{
- VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)opaque;
+ VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(opaque);
return (dev->in - dev->out) < VTERM_BUFSIZE;
}
static void vty_receive(void *opaque, const uint8_t *buf, int size)
{
- VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)opaque;
+ VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(opaque);
int i;
if ((dev->in == dev->out) && size) {
@@ -36,7 +40,7 @@ static void vty_receive(void *opaque, const uint8_t *buf, int size)
static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max)
{
- VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
+ VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
int n = 0;
while ((n < max) && (dev->out != dev->in)) {
@@ -48,7 +52,7 @@ static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max)
void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
{
- VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
+ VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
/* FIXME: should check the qemu_chr_fe_write() return value */
qemu_chr_fe_write(dev->chardev, buf, len);
@@ -56,7 +60,7 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
static int spapr_vty_init(VIOsPAPRDevice *sdev)
{
- VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
+ VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
if (!dev->chardev) {
fprintf(stderr, "spapr-vty: Can't create vty without a chardev!\n");
@@ -151,7 +155,7 @@ static void spapr_vty_class_init(ObjectClass *klass, void *data)
}
static const TypeInfo spapr_vty_info = {
- .name = "spapr-vty",
+ .name = TYPE_VIO_SPAPR_VTY_DEVICE,
.parent = TYPE_VIO_SPAPR_DEVICE,
.instance_size = sizeof(VIOsPAPRVTYDevice),
.class_init = spapr_vty_class_init,
@@ -177,7 +181,7 @@ VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
continue;
}
- sdev = DO_UPCAST(VIOsPAPRDevice, qdev, iter);
+ sdev = VIO_SPAPR_DEVICE(iter);
/* First VTY we've found, so it is selected for now */
if (!selected) {
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 2/7] pseries: Generate device paths for VIO devices
2013-04-08 5:08 [Qemu-devel] [0/7] Pending pseries updates David Gibson
2013-04-08 5:08 ` [Qemu-devel] [PATCH 1/7] pseries: Convert VIO code to QOM style type safe(ish) casts David Gibson
@ 2013-04-08 5:08 ` David Gibson
2013-04-08 5:08 ` [Qemu-devel] [PATCH 3/7] pseries: Fix incorrect calculation of RMA size in certain configurations David Gibson
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: David Gibson @ 2013-04-08 5:08 UTC (permalink / raw)
To: agraf; +Cc: qemu-ppc, qemu-devel, David Gibson
This patch implements a get_dev_path qdev hook for the pseries paravirtual
VIO bus. With upcoming savevm support, this will become very important for
scsi disks hanging of VIO virtual SCSI adapters. scsibus_get_dev_path
uses the get_dev_path of the parent adapter if available, but otherwise
just uses a local channel/target/lun number to identify the device. So if
two disks are present in the system having the same target and lun on
seperate VIO scsi adapters, savevm cannot distinguish them. Since the
conventional way of using VSCSI adapters is to have just one disk per
adapter, such a conflict is very likely.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
hw/ppc/spapr_vio.c | 37 +++++++++++++++++++++++--------------
1 file changed, 23 insertions(+), 14 deletions(-)
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 614b4a8..fc27cdc 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -53,9 +53,29 @@ static Property spapr_vio_props[] = {
DEFINE_PROP_END_OF_LIST(),
};
+static char *spapr_vio_get_dev_name(DeviceState *qdev)
+{
+ VIOsPAPRDevice *dev = VIO_SPAPR_DEVICE(qdev);
+ VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+ char *name;
+
+ /* Device tree style name device@reg */
+ name = g_strdup_printf("%s@%x", pc->dt_name, dev->reg);
+
+ return name;
+}
+
+static void spapr_vio_bus_class_init(ObjectClass *klass, void *data)
+{
+ BusClass *k = BUS_CLASS(klass);
+
+ k->get_dev_path = spapr_vio_get_dev_name;
+}
+
static const TypeInfo spapr_vio_bus_info = {
.name = TYPE_SPAPR_VIO_BUS,
.parent = TYPE_BUS,
+ .class_init = spapr_vio_bus_class_init,
.instance_size = sizeof(VIOsPAPRBus),
};
@@ -74,17 +94,6 @@ VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
return NULL;
}
-static char *vio_format_dev_name(VIOsPAPRDevice *dev)
-{
- VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
- char *name;
-
- /* Device tree style name device@reg */
- name = g_strdup_printf("%s@%x", pc->dt_name, dev->reg);
-
- return name;
-}
-
#ifdef CONFIG_FDT
static int vio_make_devnode(VIOsPAPRDevice *dev,
void *fdt)
@@ -98,7 +107,7 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
return vdevice_off;
}
- dt_name = vio_format_dev_name(dev);
+ dt_name = spapr_vio_get_dev_name(DEVICE(dev));
node_off = fdt_add_subnode(fdt, vdevice_off, dt_name);
g_free(dt_name);
if (node_off < 0) {
@@ -437,7 +446,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
/* Don't overwrite ids assigned on the command line */
if (!dev->qdev.id) {
- id = vio_format_dev_name(dev);
+ id = spapr_vio_get_dev_name(DEVICE(dev));
dev->qdev.id = id;
}
@@ -636,7 +645,7 @@ int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus)
return offset;
}
- name = vio_format_dev_name(dev);
+ name = spapr_vio_get_dev_name(DEVICE(dev));
path = g_strdup_printf("/vdevice/%s", name);
ret = fdt_setprop_string(fdt, offset, "linux,stdout-path", path);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 3/7] pseries: Fix incorrect calculation of RMA size in certain configurations
2013-04-08 5:08 [Qemu-devel] [0/7] Pending pseries updates David Gibson
2013-04-08 5:08 ` [Qemu-devel] [PATCH 1/7] pseries: Convert VIO code to QOM style type safe(ish) casts David Gibson
2013-04-08 5:08 ` [Qemu-devel] [PATCH 2/7] pseries: Generate device paths for VIO devices David Gibson
@ 2013-04-08 5:08 ` David Gibson
2013-04-08 5:08 ` [Qemu-devel] [PATCH 4/7] pseries: Fixes and enhancements to L1 cache properties David Gibson
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: David Gibson @ 2013-04-08 5:08 UTC (permalink / raw)
To: agraf; +Cc: qemu-ppc, qemu-devel, David Gibson
For the pseries machine, we need to advertise to the guest the size of its
RMA - that is the amount of memory it can access with the MMU off. For HV
KVM, this is constrained by the hardware limitations on the virtual RMA of
one hash PTE per PTE group in the hash page table. We already had code to
calculate this, but it was assuming the VRMA page size was the same as the
(host) backing page size for guest RAM.
In the case of a host kernel configured for 64k base page size, but running
on hardware (or firmware) which only allows 4k pages, the hose will do all
its allocations with a 64k page size, but still use 4k hardware pages for
actual mappings. Usually that's transparent to things running under the
host, but in the case of the maximum VRMA size it's not.
This patch refines the RMA size calculation to instead use the largest
available hardware page size (as reported by the SMMU_INFO call) which is
less than or equal to the backing page size. This now gives the correct
RMA size in all cases I've tested.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
target-ppc/kvm.c | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 597066f..d3a478e 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1370,11 +1370,35 @@ off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
{
+ struct kvm_ppc_smmu_info info;
+ long rampagesize, best_page_shift;
+ int i;
+
if (cap_ppc_rma >= 2) {
return current_size;
}
+
+ /* Find the largest hardware supported page size that's less than
+ * or equal to the (logical) backing page size of guest RAM */
+ kvm_get_smmu_info(ppc_env_get_cpu(first_cpu), &info);
+ rampagesize = getrampagesize();
+ best_page_shift = 0;
+
+ for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) {
+ struct kvm_ppc_one_seg_page_size *sps = &info.sps[i];
+
+ if (!sps->page_shift) {
+ continue;
+ }
+
+ if ((sps->page_shift > best_page_shift)
+ && ((1UL << sps->page_shift) <= rampagesize)) {
+ best_page_shift = sps->page_shift;
+ }
+ }
+
return MIN(current_size,
- getrampagesize() << (hash_shift - 7));
+ 1ULL << (best_page_shift + hash_shift - 7));
}
#endif
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 4/7] pseries: Fixes and enhancements to L1 cache properties
2013-04-08 5:08 [Qemu-devel] [0/7] Pending pseries updates David Gibson
` (2 preceding siblings ...)
2013-04-08 5:08 ` [Qemu-devel] [PATCH 3/7] pseries: Fix incorrect calculation of RMA size in certain configurations David Gibson
@ 2013-04-08 5:08 ` David Gibson
2013-04-08 5:08 ` [Qemu-devel] [PATCH 5/7] target-ppc: Add more stubs for POWER7 PMU registers David Gibson
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: David Gibson @ 2013-04-08 5:08 UTC (permalink / raw)
To: agraf; +Cc: qemu-ppc, qemu-devel, David Gibson
PAPR requires that the device tree's CPU nodes have several properties
with information about the L1 cache. We already create two of these
properties, but with incorrect names - "[id]cache-block-size" instead
of "[id]-cache-block-size" (note the extra hyphen).
We were also missing some of the required cache properties. This
patch adds the [id]-cache-line-size properties (which have the same
values as the block size properties in all current cases). We also
add the [id]-cache-size properties.
Adding the cache sizes requires some extra infrastructure in the
general target-ppc code to (optionally) set the cache sizes for
various CPUs. The CPU family descriptions in translate_init.c can set
these sizes - this patch adds correct information for POWER7, I'm
leaving other CPU types to people who have a physical example to
verify against. In addition, for -cpu host we take the values
advertised by the host (if available) and use those to override the
information based on PVR.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
hw/ppc/spapr.c | 21 +++++++++++++++++++--
target-ppc/cpu-qom.h | 1 +
target-ppc/kvm.c | 10 ++++++++++
target-ppc/translate_init.c | 3 +++
4 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 7b2a11f..d7c3742 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -308,6 +308,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
for (env = first_cpu; env != NULL; env = env->next_cpu) {
CPUState *cpu = CPU(ppc_env_get_cpu(env));
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
int index = cpu->cpu_index;
uint32_t servers_prop[smp_threads];
uint32_t gservers_prop[smp_threads * 2];
@@ -333,10 +334,26 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
_FDT((fdt_property_string(fdt, "device_type", "cpu")));
_FDT((fdt_property_cell(fdt, "cpu-version", env->spr[SPR_PVR])));
- _FDT((fdt_property_cell(fdt, "dcache-block-size",
+ _FDT((fdt_property_cell(fdt, "d-cache-block-size",
env->dcache_line_size)));
- _FDT((fdt_property_cell(fdt, "icache-block-size",
+ _FDT((fdt_property_cell(fdt, "d-cache-line-size",
+ env->dcache_line_size)));
+ _FDT((fdt_property_cell(fdt, "i-cache-block-size",
+ env->icache_line_size)));
+ _FDT((fdt_property_cell(fdt, "i-cache-line-size",
env->icache_line_size)));
+
+ if (pcc->l1_dcache_size) {
+ _FDT((fdt_property_cell(fdt, "d-cache-size", pcc->l1_dcache_size)));
+ } else {
+ fprintf(stderr, "Warning: Unknown L1 dcache size for cpu\n");
+ }
+ if (pcc->l1_icache_size) {
+ _FDT((fdt_property_cell(fdt, "i-cache-size", pcc->l1_icache_size)));
+ } else {
+ fprintf(stderr, "Warning: Unknown L1 icache size for cpu\n");
+ }
+
_FDT((fdt_property_cell(fdt, "timebase-frequency", tbfreq)));
_FDT((fdt_property_cell(fdt, "clock-frequency", cpufreq)));
_FDT((fdt_property_cell(fdt, "ibm,slb-size", env->slb_nr)));
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index c27cef7..eb03a00 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -63,6 +63,7 @@ typedef struct PowerPCCPUClass {
powerpc_input_t bus_model;
uint32_t flags;
int bfd_mach;
+ uint32_t l1_dcache_size, l1_icache_size;
#if defined(TARGET_PPC64)
const struct ppc_segment_page_sizes *sps;
#endif
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index d3a478e..6a676cc 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1527,6 +1527,8 @@ static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
uint32_t vmx = kvmppc_get_vmx();
uint32_t dfp = kvmppc_get_dfp();
+ uint32_t dcache_size = kvmppc_read_int_cpu_dt("d-cache-size");
+ uint32_t icache_size = kvmppc_read_int_cpu_dt("i-cache-size");
/* Now fix up the class with information we can query from the host */
@@ -1539,6 +1541,14 @@ static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
/* Only override when we know what the host supports */
alter_insns(&pcc->insns_flags2, PPC2_DFP, dfp);
}
+
+ if (dcache_size != -1) {
+ pcc->l1_dcache_size = dcache_size;
+ }
+
+ if (icache_size != -1) {
+ pcc->l1_icache_size = icache_size;
+ }
}
int kvmppc_fixup_cpu(PowerPCCPU *cpu)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 781170f..6e20b55 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -6989,6 +6989,7 @@ static void init_proc_POWER7 (CPUPPCState *env)
init_excp_POWER7(env);
env->dcache_line_size = 128;
env->icache_line_size = 128;
+
/* Allocate hardware IRQ controller */
ppcPOWER7_irq_init(env);
/* Can't find information on what this should be on reset. This
@@ -7026,6 +7027,8 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR;
+ pcc->l1_dcache_size = 0x8000;
+ pcc->l1_icache_size = 0x8000;
}
#endif /* defined (TARGET_PPC64) */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 5/7] target-ppc: Add more stubs for POWER7 PMU registers
2013-04-08 5:08 [Qemu-devel] [0/7] Pending pseries updates David Gibson
` (3 preceding siblings ...)
2013-04-08 5:08 ` [Qemu-devel] [PATCH 4/7] pseries: Fixes and enhancements to L1 cache properties David Gibson
@ 2013-04-08 5:08 ` David Gibson
2013-04-08 5:08 ` [Qemu-devel] [PATCH 6/7] pseries: Fix some small errors in XICS logic David Gibson
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: David Gibson @ 2013-04-08 5:08 UTC (permalink / raw)
To: agraf; +Cc: qemu-ppc, qemu-devel, David Gibson
In addition to the performance monitor registers found on nearly all
6xx chips, the POWER7 has two additional counters (PMC5 & PMC6) and an
extra control register (MMCRA). This patch adds stub support for them to
qemu - the registers won't do anything, but with this change won't cause
illegal instruction traps accessing them. They're also registered with
their ONE_REG ids, so their value will be kept in sync with KVM where
appropriate.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
target-ppc/cpu.h | 1 +
target-ppc/translate_init.c | 12 ++++++++++++
2 files changed, 13 insertions(+)
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 42c36e2..94bd36b 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1446,6 +1446,7 @@ static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp)
#define SPR_PERF2 (0x302)
#define SPR_RCPU_MI_RBA2 (0x302)
#define SPR_MPC_MI_AP (0x302)
+#define SPR_MMCRA (0x302)
#define SPR_PERF3 (0x303)
#define SPR_RCPU_MI_RBA3 (0x303)
#define SPR_MPC_MI_EPN (0x303)
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 6e20b55..71e434a 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -6962,6 +6962,18 @@ static void init_proc_POWER7 (CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
KVM_REG_PPC_DSCR, 0x00000000);
+ spr_register_kvm(env, SPR_MMCRA, "SPR_MMCRA",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_MMCRA, 0x00000000);
+ spr_register_kvm(env, SPR_PMC5, "SPR_PMC5",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_PMC5, 0x00000000);
+ spr_register_kvm(env, SPR_PMC6, "SPR_PMC6",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_PMC6, 0x00000000);
#endif /* !CONFIG_USER_ONLY */
/* Memory management */
/* XXX : not implemented */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 6/7] pseries: Fix some small errors in XICS logic
2013-04-08 5:08 [Qemu-devel] [0/7] Pending pseries updates David Gibson
` (4 preceding siblings ...)
2013-04-08 5:08 ` [Qemu-devel] [PATCH 5/7] target-ppc: Add more stubs for POWER7 PMU registers David Gibson
@ 2013-04-08 5:08 ` David Gibson
2013-04-08 5:08 ` [Qemu-devel] [PATCH 7/7] target-ppc: Synchronize VPA state with KVM David Gibson
2013-04-19 15:27 ` [Qemu-devel] [0/7] Pending pseries updates Alexander Graf
7 siblings, 0 replies; 9+ messages in thread
From: David Gibson @ 2013-04-08 5:08 UTC (permalink / raw)
To: agraf; +Cc: qemu-ppc, qemu-devel, David Gibson
Under certain circumstances the emulation for the pseries "XICS" interrupt
controller was clearing a pending interrupt from the XISR register, without
also clearing the corresponding priority variable. This will cause
problems later when can trigger sanity checks in the under-development
in-kernel XICS implementation.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
hw/ppc/xics.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/hw/ppc/xics.c b/hw/ppc/xics.c
index 374da5b..207691b 100644
--- a/hw/ppc/xics.c
+++ b/hw/ppc/xics.c
@@ -101,6 +101,7 @@ static void icp_set_cppr(struct icp_state *icp, int server, uint8_t cppr)
if (XISR(ss) && (cppr <= ss->pending_priority)) {
old_xisr = XISR(ss);
ss->xirr &= ~XISR_MASK; /* Clear XISR */
+ ss->pending_priority = 0xff;
qemu_irq_lower(ss->output);
ics_reject(icp->ics, old_xisr);
}
@@ -127,6 +128,7 @@ static uint32_t icp_accept(struct icp_server_state *ss)
qemu_irq_lower(ss->output);
ss->xirr = ss->pending_priority << 24;
+ ss->pending_priority = 0xff;
trace_xics_icp_accept(xirr, ss->xirr);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH 7/7] target-ppc: Synchronize VPA state with KVM
2013-04-08 5:08 [Qemu-devel] [0/7] Pending pseries updates David Gibson
` (5 preceding siblings ...)
2013-04-08 5:08 ` [Qemu-devel] [PATCH 6/7] pseries: Fix some small errors in XICS logic David Gibson
@ 2013-04-08 5:08 ` David Gibson
2013-04-19 15:27 ` [Qemu-devel] [0/7] Pending pseries updates Alexander Graf
7 siblings, 0 replies; 9+ messages in thread
From: David Gibson @ 2013-04-08 5:08 UTC (permalink / raw)
To: agraf; +Cc: qemu-ppc, qemu-devel, David Gibson
For PAPR guests, KVM tracks the various areas registered with the
H_REGISTER_VPA hypercall. For full emulation, of course, these are tracked
within qemu. At present these values are not synchronized. This is a
problem for reset (qemu's reset of the VPA address is not pushed to KVM)
and will also be a problem for savevm / migration.
The kernel now supports accessing the VPA state via the ONE_REG interface,
this patch adds code to qemu to use that interface to keep the qemu and
KVM ideas of the VPA state synchronized.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
target-ppc/kvm.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 120 insertions(+)
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 6a676cc..7d06ad9 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -63,6 +63,7 @@ static int cap_ppc_rma;
static int cap_spapr_tce;
static int cap_hior;
static int cap_one_reg;
+static int cap_papr;
/* XXX We have a race condition where we actually have a level triggered
* interrupt, but the infrastructure can't expose that yet, so the guest
@@ -95,6 +96,8 @@ int kvm_arch_init(KVMState *s)
cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
cap_one_reg = kvm_check_extension(s, KVM_CAP_ONE_REG);
cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR);
+ /* Note: we don't set cap_papr here, because this capability is
+ * only activated after this by kvmppc_set_papr() */
if (!cap_interrupt_level) {
fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -652,6 +655,103 @@ static int kvm_get_fp(CPUState *cs)
return 0;
}
+#if defined(TARGET_PPC64)
+static int kvm_get_vpa(CPUState *cs)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+ struct kvm_one_reg reg;
+ int ret;
+
+ reg.id = KVM_REG_PPC_VPA_ADDR;
+ reg.addr = (uintptr_t)&env->vpa_addr;
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
+ if (ret < 0) {
+ dprintf("Unable to get VPA address from KVM: %s\n", strerror(errno));
+ return ret;
+ }
+
+ assert((uintptr_t)&env->slb_shadow_size
+ == ((uintptr_t)&env->slb_shadow_addr + 8));
+ reg.id = KVM_REG_PPC_VPA_SLB;
+ reg.addr = (uintptr_t)&env->slb_shadow_addr;
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
+ if (ret < 0) {
+ dprintf("Unable to get SLB shadow state from KVM: %s\n",
+ strerror(errno));
+ return ret;
+ }
+
+ assert((uintptr_t)&env->dtl_size == ((uintptr_t)&env->dtl_addr + 8));
+ reg.id = KVM_REG_PPC_VPA_DTL;
+ reg.addr = (uintptr_t)&env->dtl_addr;
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
+ if (ret < 0) {
+ dprintf("Unable to get dispatch trace log state from KVM: %s\n",
+ strerror(errno));
+ return ret;
+ }
+
+ return 0;
+}
+
+static int kvm_put_vpa(CPUState *cs)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+ struct kvm_one_reg reg;
+ int ret;
+
+ /* SLB shadow or DTL can't be registered unless a master VPA is
+ * registered. That means when restoring state, if a VPA *is*
+ * registered, we need to set that up first. If not, we need to
+ * deregister the others before deregistering the master VPA */
+ assert(env->vpa_addr || !(env->slb_shadow_addr || env->dtl_addr));
+
+ if (env->vpa_addr) {
+ reg.id = KVM_REG_PPC_VPA_ADDR;
+ reg.addr = (uintptr_t)&env->vpa_addr;
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
+ if (ret < 0) {
+ dprintf("Unable to set VPA address to KVM: %s\n", strerror(errno));
+ return ret;
+ }
+ }
+
+ assert((uintptr_t)&env->slb_shadow_size
+ == ((uintptr_t)&env->slb_shadow_addr + 8));
+ reg.id = KVM_REG_PPC_VPA_SLB;
+ reg.addr = (uintptr_t)&env->slb_shadow_addr;
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
+ if (ret < 0) {
+ dprintf("Unable to set SLB shadow state to KVM: %s\n", strerror(errno));
+ return ret;
+ }
+
+ assert((uintptr_t)&env->dtl_size == ((uintptr_t)&env->dtl_addr + 8));
+ reg.id = KVM_REG_PPC_VPA_DTL;
+ reg.addr = (uintptr_t)&env->dtl_addr;
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
+ if (ret < 0) {
+ dprintf("Unable to set dispatch trace log state to KVM: %s\n",
+ strerror(errno));
+ return ret;
+ }
+
+ if (!env->vpa_addr) {
+ reg.id = KVM_REG_PPC_VPA_ADDR;
+ reg.addr = (uintptr_t)&env->vpa_addr;
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
+ if (ret < 0) {
+ dprintf("Unable to set VPA address to KVM: %s\n", strerror(errno));
+ return ret;
+ }
+ }
+
+ return 0;
+}
+#endif /* TARGET_PPC64 */
+
int kvm_arch_put_registers(CPUState *cs, int level)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
@@ -752,6 +852,14 @@ int kvm_arch_put_registers(CPUState *cs, int level)
kvm_put_one_spr(cs, id, i);
}
}
+
+#ifdef TARGET_PPC64
+ if (cap_papr) {
+ if (kvm_put_vpa(cs) < 0) {
+ dprintf("Warning: Unable to set VPA information to KVM\n");
+ }
+ }
+#endif /* TARGET_PPC64 */
}
return ret;
@@ -953,6 +1061,14 @@ int kvm_arch_get_registers(CPUState *cs)
kvm_get_one_spr(cs, id, i);
}
}
+
+#ifdef TARGET_PPC64
+ if (cap_papr) {
+ if (kvm_get_vpa(cs) < 0) {
+ dprintf("Warning: Unable to get VPA information from KVM\n");
+ }
+ }
+#endif
}
return 0;
@@ -1301,6 +1417,10 @@ void kvmppc_set_papr(PowerPCCPU *cpu)
if (ret) {
cpu_abort(env, "This KVM version does not support PAPR\n");
}
+
+ /* Update the capability flag so we sync the right information
+ * with kvm */
+ cap_papr = 1;
}
void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy)
--
1.7.10.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [0/7] Pending pseries updates
2013-04-08 5:08 [Qemu-devel] [0/7] Pending pseries updates David Gibson
` (6 preceding siblings ...)
2013-04-08 5:08 ` [Qemu-devel] [PATCH 7/7] target-ppc: Synchronize VPA state with KVM David Gibson
@ 2013-04-19 15:27 ` Alexander Graf
7 siblings, 0 replies; 9+ messages in thread
From: Alexander Graf @ 2013-04-19 15:27 UTC (permalink / raw)
To: David Gibson; +Cc: qemu-ppc, qemu-devel
On 08.04.2013, at 07:08, David Gibson wrote:
> Hi Alex,
>
> Here's my latest batch of pending pseries updates. Mostly pretty
> small bugfixes and extensions.
Thanks, applied all to ppc-next.
Alex
^ permalink raw reply [flat|nested] 9+ messages in thread