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
This commit is contained in:
Blue Swirl 2011-11-19 11:17:11 +00:00
commit 05a86f23e5
5 changed files with 84 additions and 23 deletions

View File

@ -57,7 +57,7 @@
#define FW_MAX_SIZE 0x400000 #define FW_MAX_SIZE 0x400000
#define FW_FILE_NAME "slof.bin" #define FW_FILE_NAME "slof.bin"
#define MIN_RAM_SLOF 512UL #define MIN_RMA_SLOF 128UL
#define TIMEBASE_FREQ 512000000ULL #define TIMEBASE_FREQ 512000000ULL
@ -407,7 +407,9 @@ static void ppc_spapr_init(ram_addr_t ram_size,
long pteg_shift = 17; long pteg_shift = 17;
char *filename; char *filename;
spapr = g_malloc(sizeof(*spapr)); spapr = g_malloc0(sizeof(*spapr));
QLIST_INIT(&spapr->phbs);
cpu_ppc_hypercall = emulate_spapr_hypercall; cpu_ppc_hypercall = emulate_spapr_hypercall;
/* Allocate RMA if necessary */ /* Allocate RMA if necessary */
@ -560,9 +562,9 @@ static void ppc_spapr_init(ram_addr_t ram_size,
spapr->entry_point = KERNEL_LOAD_ADDR; spapr->entry_point = KERNEL_LOAD_ADDR;
} else { } else {
if (ram_size < (MIN_RAM_SLOF << 20)) { if (rma_size < (MIN_RMA_SLOF << 20)) {
fprintf(stderr, "qemu: pSeries SLOF firmware requires >= " 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); exit(1);
} }
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME); filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME);

View File

@ -66,11 +66,24 @@ VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) { QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
dev = (VIOsPAPRDevice *)qdev; dev = (VIOsPAPRDevice *)qdev;
if (dev->reg == reg) { 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 #ifdef CONFIG_FDT
@ -78,15 +91,21 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
void *fdt) void *fdt)
{ {
VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)dev->qdev.info; VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)dev->qdev.info;
int vdevice_off, node_off; int vdevice_off, node_off, ret;
int ret; char *dt_name;
vdevice_off = fdt_path_offset(fdt, "/vdevice"); vdevice_off = fdt_path_offset(fdt, "/vdevice");
if (vdevice_off < 0) { if (vdevice_off < 0) {
return vdevice_off; 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) { if (node_off < 0) {
return node_off; return node_off;
} }
@ -608,11 +627,14 @@ static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev; VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
char *id; char *id;
if (asprintf(&id, "%s@%x", info->dt_name, dev->reg) < 0) { /* Don't overwrite ids assigned on the command line */
if (!dev->qdev.id) {
id = vio_format_dev_name(dev);
if (!id) {
return -1; return -1;
} }
dev->qdev.id = id; dev->qdev.id = id;
}
dev->qirq = spapr_allocate_irq(dev->vio_irq_num, &dev->vio_irq_num); dev->qirq = spapr_allocate_irq(dev->vio_irq_num, &dev->vio_irq_num);
if (!dev->qirq) { if (!dev->qirq) {

View File

@ -58,12 +58,20 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev)
{ {
VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)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, qemu_chr_add_handlers(dev->chardev, vty_can_receive,
vty_receive, NULL, dev); vty_receive, NULL, dev);
return 0; return 0;
} }
/* Forward declaration */
static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg);
static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr, static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args) 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 len = args[1];
target_ulong char0_7 = args[2]; target_ulong char0_7 = args[2];
target_ulong char8_15 = args[3]; target_ulong char8_15 = args[3];
VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg); VIOsPAPRDevice *sdev;
uint8_t buf[16]; uint8_t buf[16];
sdev = vty_lookup(spapr, reg);
if (!sdev) { if (!sdev) {
return H_PARAMETER; 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 *len = args + 0;
target_ulong *char0_7 = args + 1; target_ulong *char0_7 = args + 1;
target_ulong *char8_15 = args + 2; target_ulong *char8_15 = args + 2;
VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg); VIOsPAPRDevice *sdev;
uint8_t buf[16]; uint8_t buf[16];
sdev = vty_lookup(spapr, reg);
if (!sdev) { if (!sdev) {
return H_PARAMETER; return H_PARAMETER;
} }
@ -140,12 +150,35 @@ static VIOsPAPRDeviceInfo spapr_vty = {
.qdev.name = "spapr-vty", .qdev.name = "spapr-vty",
.qdev.size = sizeof(VIOsPAPRVTYDevice), .qdev.size = sizeof(VIOsPAPRVTYDevice),
.qdev.props = (Property[]) { .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_CHR("chardev", VIOsPAPRVTYDevice, chardev),
DEFINE_PROP_END_OF_LIST(), 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) static void spapr_vty_register(void)
{ {
spapr_vio_bus_register_withprop(&spapr_vty); spapr_vio_bus_register_withprop(&spapr_vty);

View File

@ -298,8 +298,10 @@ static inline void gen_debug_exception(DisasContext *ctx)
{ {
TCGv_i32 t0; 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); gen_update_nip(ctx, ctx->nip);
}
t0 = tcg_const_i32(EXCP_DEBUG); t0 = tcg_const_i32(EXCP_DEBUG);
gen_helper_raise_exception(t0); gen_helper_raise_exception(t0);
tcg_temp_free_i32(t0); tcg_temp_free_i32(t0);

View File

@ -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) 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 #ifdef CONFIG_SOFTMMU
int r2; int r2, mem_index, s_bits;
void *label1_ptr, *label2_ptr; void *label1_ptr, *label2_ptr;
#endif #endif
data_reg = *args++; data_reg = *args++;
addr_reg = *args++; addr_reg = *args++;
#ifdef CONFIG_SOFTMMU
mem_index = *args; mem_index = *args;
s_bits = opc & 3; s_bits = opc & 3;
#ifdef CONFIG_SOFTMMU
r0 = 3; r0 = 3;
r1 = 4; r1 = 4;
r2 = 0; 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) 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 #ifdef CONFIG_SOFTMMU
int r2; int r2, mem_index;
void *label1_ptr, *label2_ptr; void *label1_ptr, *label2_ptr;
#endif #endif
data_reg = *args++; data_reg = *args++;
addr_reg = *args++; addr_reg = *args++;
mem_index = *args;
#ifdef CONFIG_SOFTMMU #ifdef CONFIG_SOFTMMU
mem_index = *args;
r0 = 3; r0 = 3;
r1 = 4; r1 = 4;
r2 = 0; r2 = 0;