mirror of https://github.com/xqemu/xqemu.git
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:
commit
05a86f23e5
10
hw/spapr.c
10
hw/spapr.c
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue