diff --git a/hw/spapr.c b/hw/spapr.c index bdaa938b6b35bc2acaf74abb172634e316442c19..2b901f105ee6a7f0c92155612c071d5ba602ba8d 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 25cfc9d912691e4feee06b41975bd556aa6d073d..2dcc0361ed5801c06d279dbcd080e9128a8fc0a4 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 a9d4b035e28015a355ed70dc1e4ebd3a31dd5214..f23cc36231e2cc2e2475c63531eebfa8ee1d05f0 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); diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 99e995c7b6094b0651d176f9b813525b44b7a74e..66eae302098ea5d0dc331f417eca57446fc18bde 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -298,8 +298,10 @@ static inline void gen_debug_exception(DisasContext *ctx) { TCGv_i32 t0; - if (ctx->exception != POWERPC_EXCP_BRANCH) + if ((ctx->exception != POWERPC_EXCP_BRANCH) && + (ctx->exception != POWERPC_EXCP_SYNC)) { gen_update_nip(ctx, ctx->nip); + } t0 = tcg_const_i32(EXCP_DEBUG); gen_helper_raise_exception(t0); tcg_temp_free_i32(t0); diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c index 3d24cd4da4dd774240d137aaf2369e1fe32794f7..41f1e85cc9df1cb99a8d7b849da4baa1c0a39b34 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -616,18 +616,19 @@ static void tcg_out_tlb_read (TCGContext *s, int r0, int r1, int r2, static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) { - int addr_reg, data_reg, r0, r1, rbase, mem_index, s_bits, bswap; + int addr_reg, data_reg, r0, r1, rbase, bswap; #ifdef CONFIG_SOFTMMU - int r2; + int r2, mem_index, s_bits; void *label1_ptr, *label2_ptr; #endif data_reg = *args++; addr_reg = *args++; + +#ifdef CONFIG_SOFTMMU mem_index = *args; s_bits = opc & 3; -#ifdef CONFIG_SOFTMMU r0 = 3; r1 = 4; r2 = 0; @@ -763,17 +764,18 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) { - int addr_reg, r0, r1, rbase, data_reg, mem_index, bswap; + int addr_reg, r0, r1, rbase, data_reg, bswap; #ifdef CONFIG_SOFTMMU - int r2; + int r2, mem_index; void *label1_ptr, *label2_ptr; #endif data_reg = *args++; addr_reg = *args++; - mem_index = *args; #ifdef CONFIG_SOFTMMU + mem_index = *args; + r0 = 3; r1 = 4; r2 = 0;