aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorBlue Swirl <blauwirbel@gmail.com>2011-11-19 11:17:11 +0000
committerBlue Swirl <blauwirbel@gmail.com>2011-11-19 11:17:11 +0000
commit05a86f23e5ca83348eface349429341cefb8697b (patch)
tree6c33ddc0703342c418e697eaba72b6b0c1fafbb9 /hw
parent15d4a723381bb57dc31007ca46661f42eb67a100 (diff)
parent1e34d859d01a408dc8479b1858bb103aa3b4f9a7 (diff)
Merge branch 'ppc-1.0' of git://repo.or.cz/qemu/agraf
* 'ppc-1.0' of git://repo.or.cz/qemu/agraf: pseries: Fix qdev.id handling in the VIO bus code pseries: Allow kernel's early debug output to work pseries: Default reg for vty should be SPAPR_VTY_BASE_ADDRESS pseries: Check we have a chardev in spapr_vty_init() pseries: Fix buggy spapr_vio_find_by_reg() pseries: Correct RAM size check for SLOF PPC: Fix for the gdb single step problem on an rfi instruction tcg-ppc64: Fix compile errors for userspace only builds with gcc 4.6 pseries: Fix initialization of sPAPREnvironment structure
Diffstat (limited to 'hw')
-rw-r--r--hw/spapr.c10
-rw-r--r--hw/spapr_vio.c40
-rw-r--r--hw/spapr_vty.c39
3 files changed, 73 insertions, 16 deletions
diff --git a/hw/spapr.c b/hw/spapr.c
index bdaa938b6b..2b901f105e 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -57,7 +57,7 @@
#define FW_MAX_SIZE 0x400000
#define FW_FILE_NAME "slof.bin"
-#define MIN_RAM_SLOF 512UL
+#define MIN_RMA_SLOF 128UL
#define TIMEBASE_FREQ 512000000ULL
@@ -407,7 +407,9 @@ static void ppc_spapr_init(ram_addr_t ram_size,
long pteg_shift = 17;
char *filename;
- spapr = g_malloc(sizeof(*spapr));
+ spapr = g_malloc0(sizeof(*spapr));
+ QLIST_INIT(&spapr->phbs);
+
cpu_ppc_hypercall = emulate_spapr_hypercall;
/* Allocate RMA if necessary */
@@ -560,9 +562,9 @@ static void ppc_spapr_init(ram_addr_t ram_size,
spapr->entry_point = KERNEL_LOAD_ADDR;
} else {
- if (ram_size < (MIN_RAM_SLOF << 20)) {
+ if (rma_size < (MIN_RMA_SLOF << 20)) {
fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
- "%ldM guest RAM\n", MIN_RAM_SLOF);
+ "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF);
exit(1);
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME);
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 25cfc9d912..2dcc0361ed 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -66,11 +66,24 @@ VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
dev = (VIOsPAPRDevice *)qdev;
if (dev->reg == reg) {
- break;
+ return dev;
}
}
- return dev;
+ return NULL;
+}
+
+static char *vio_format_dev_name(VIOsPAPRDevice *dev)
+{
+ VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)dev->qdev.info;
+ char *name;
+
+ /* Device tree style name device@reg */
+ if (asprintf(&name, "%s@%x", info->dt_name, dev->reg) < 0) {
+ return NULL;
+ }
+
+ return name;
}
#ifdef CONFIG_FDT
@@ -78,15 +91,21 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
void *fdt)
{
VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)dev->qdev.info;
- int vdevice_off, node_off;
- int ret;
+ int vdevice_off, node_off, ret;
+ char *dt_name;
vdevice_off = fdt_path_offset(fdt, "/vdevice");
if (vdevice_off < 0) {
return vdevice_off;
}
- node_off = fdt_add_subnode(fdt, vdevice_off, dev->qdev.id);
+ dt_name = vio_format_dev_name(dev);
+ if (!dt_name) {
+ return -ENOMEM;
+ }
+
+ node_off = fdt_add_subnode(fdt, vdevice_off, dt_name);
+ free(dt_name);
if (node_off < 0) {
return node_off;
}
@@ -608,12 +627,15 @@ static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
char *id;
- if (asprintf(&id, "%s@%x", info->dt_name, dev->reg) < 0) {
- return -1;
+ /* Don't overwrite ids assigned on the command line */
+ if (!dev->qdev.id) {
+ id = vio_format_dev_name(dev);
+ if (!id) {
+ return -1;
+ }
+ dev->qdev.id = id;
}
- dev->qdev.id = id;
-
dev->qirq = spapr_allocate_irq(dev->vio_irq_num, &dev->vio_irq_num);
if (!dev->qirq) {
return -1;
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index a9d4b035e2..f23cc36231 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -58,12 +58,20 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev)
{
VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
+ if (!dev->chardev) {
+ fprintf(stderr, "spapr-vty: Can't create vty without a chardev!\n");
+ exit(1);
+ }
+
qemu_chr_add_handlers(dev->chardev, vty_can_receive,
vty_receive, NULL, dev);
return 0;
}
+/* Forward declaration */
+static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg);
+
static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
@@ -71,9 +79,10 @@ static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
target_ulong len = args[1];
target_ulong char0_7 = args[2];
target_ulong char8_15 = args[3];
- VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+ VIOsPAPRDevice *sdev;
uint8_t buf[16];
+ sdev = vty_lookup(spapr, reg);
if (!sdev) {
return H_PARAMETER;
}
@@ -97,9 +106,10 @@ static target_ulong h_get_term_char(CPUState *env, sPAPREnvironment *spapr,
target_ulong *len = args + 0;
target_ulong *char0_7 = args + 1;
target_ulong *char8_15 = args + 2;
- VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+ VIOsPAPRDevice *sdev;
uint8_t buf[16];
+ sdev = vty_lookup(spapr, reg);
if (!sdev) {
return H_PARAMETER;
}
@@ -140,12 +150,35 @@ static VIOsPAPRDeviceInfo spapr_vty = {
.qdev.name = "spapr-vty",
.qdev.size = sizeof(VIOsPAPRVTYDevice),
.qdev.props = (Property[]) {
- DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, 0, 0),
+ DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, SPAPR_VTY_BASE_ADDRESS, 0),
DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
DEFINE_PROP_END_OF_LIST(),
},
};
+static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
+{
+ VIOsPAPRDevice *sdev;
+
+ sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+ if (!sdev && reg == 0) {
+ DeviceState *qdev;
+
+ /* Hack for kernel early debug, which always specifies reg==0.
+ * We search all VIO devices, and grab the first available vty
+ * device. This attempts to mimic existing PowerVM behaviour
+ * (early debug does work there, despite having no vty with
+ * reg==0. */
+ QTAILQ_FOREACH(qdev, &spapr->vio_bus->bus.children, sibling) {
+ if (qdev->info == &spapr_vty.qdev) {
+ return DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
+ }
+ }
+ }
+
+ return sdev;
+}
+
static void spapr_vty_register(void)
{
spapr_vio_bus_register_withprop(&spapr_vty);