Skip to content

Commit

Permalink
Merge branch 'ppc-for-upstream' of git://github.com/agraf/qemu
Browse files Browse the repository at this point in the history
* 'ppc-for-upstream' of git://github.com/agraf/qemu:
  PPC: spapr: iommu: rework traces
  spapr: add "stop-self" RTAS call required to support hot CPU unplug
  PPC: KVM: Compile fix for qemu_notify_event
  pseries: Add H_SET_MODE hcall to change guest exception endianness
  xics: move registration of global state to realize()
  spapr-pci: rework MSI/MSIX
  target-ppc: Use #define instead of opencoding SLB valid bit
  spapr-pci: fix config space access to support bridges
  target-ppc: fix bit extraction for FPBF and FPL
  ppc405_boards: Don't enforce presence of firmware for qtest
  ppc405_uc: Disable debug output
  ppc405_boards: Disable debug output
  ppc: virtex_ml507: QEMU_OPTION_dtb support for this machine.
  disas/ppc.c: Fix little endian disassembly
  target-ppc: POWER7 supports the MSR_LE bit
  target-ppc: USE LPCR_ILE to control exception endian on POWER7
  pseries: Fix stalls on hypervisor virtual console
  PPC: E500: Generate device tree on reset
  • Loading branch information
aurel32 committed Sep 2, 2013
2 parents 3207bf2 + 7e47226 commit 32f3bd6
Show file tree
Hide file tree
Showing 21 changed files with 305 additions and 160 deletions.
3 changes: 2 additions & 1 deletion disas/ppc.c
Expand Up @@ -5157,7 +5157,8 @@ int
print_insn_ppc (bfd_vma memaddr, struct disassemble_info *info)
{
int dialect = (char *) info->private_data - (char *) 0;
return print_insn_powerpc (memaddr, info, 1, dialect);
return print_insn_powerpc (memaddr, info, info->endian == BFD_ENDIAN_BIG,
dialect);
}

/* Print a big endian PowerPC instruction. */
Expand Down
2 changes: 2 additions & 0 deletions hw/char/spapr_vty.c
Expand Up @@ -47,6 +47,8 @@ static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max)
buf[n++] = dev->buf[dev->out++ % VTERM_BUFSIZE];
}

qemu_chr_accept_input(dev->chardev);

return n;
}

Expand Down
21 changes: 11 additions & 10 deletions hw/intc/xics.c
Expand Up @@ -642,6 +642,17 @@ static void xics_realize(DeviceState *dev, Error **errp)
ICSState *ics = icp->ics;
int i;

/* Registration of global state belongs into realize */
spapr_rtas_register("ibm,set-xive", rtas_set_xive);
spapr_rtas_register("ibm,get-xive", rtas_get_xive);
spapr_rtas_register("ibm,int-off", rtas_int_off);
spapr_rtas_register("ibm,int-on", rtas_int_on);

spapr_register_hypercall(H_CPPR, h_cppr);
spapr_register_hypercall(H_IPI, h_ipi);
spapr_register_hypercall(H_XIRR, h_xirr);
spapr_register_hypercall(H_EOI, h_eoi);

ics->nr_irqs = icp->nr_irqs;
ics->offset = XICS_IRQ_BASE;
ics->icp = icp;
Expand Down Expand Up @@ -678,16 +689,6 @@ static void xics_class_init(ObjectClass *oc, void *data)
dc->realize = xics_realize;
dc->props = xics_properties;
dc->reset = xics_reset;

spapr_rtas_register("ibm,set-xive", rtas_set_xive);
spapr_rtas_register("ibm,get-xive", rtas_get_xive);
spapr_rtas_register("ibm,int-off", rtas_int_off);
spapr_rtas_register("ibm,int-on", rtas_int_on);

spapr_register_hypercall(H_CPPR, h_cppr);
spapr_register_hypercall(H_IPI, h_ipi);
spapr_register_hypercall(H_XIRR, h_xirr);
spapr_register_hypercall(H_EOI, h_eoi);
}

static const TypeInfo xics_info = {
Expand Down
52 changes: 43 additions & 9 deletions hw/ppc/e500.c
Expand Up @@ -123,13 +123,14 @@ static void dt_serial_create(void *fdt, unsigned long long offset,
}
}

static int ppce500_load_device_tree(CPUPPCState *env,
QEMUMachineInitArgs *args,
static int ppce500_load_device_tree(QEMUMachineInitArgs *args,
PPCE500Params *params,
hwaddr addr,
hwaddr initrd_base,
hwaddr initrd_size)
hwaddr initrd_size,
bool dry_run)
{
CPUPPCState *env = first_cpu->env_ptr;
int ret = -1;
uint64_t mem_reg_property[] = { 0, cpu_to_be64(args->ram_size) };
int fdt_size;
Expand Down Expand Up @@ -369,12 +370,10 @@ static int ppce500_load_device_tree(CPUPPCState *env,
}

done:
qemu_devtree_dumpdtb(fdt, fdt_size);
ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
if (ret < 0) {
goto out;
if (!dry_run) {
qemu_devtree_dumpdtb(fdt, fdt_size);
cpu_physical_memory_write(addr, fdt, fdt_size);
}
g_free(fdt);
ret = fdt_size;

out:
Expand All @@ -383,6 +382,41 @@ static int ppce500_load_device_tree(CPUPPCState *env,
return ret;
}

typedef struct DeviceTreeParams {
QEMUMachineInitArgs args;
PPCE500Params params;
hwaddr addr;
hwaddr initrd_base;
hwaddr initrd_size;
} DeviceTreeParams;

static void ppce500_reset_device_tree(void *opaque)
{
DeviceTreeParams *p = opaque;
ppce500_load_device_tree(&p->args, &p->params, p->addr, p->initrd_base,
p->initrd_size, false);
}

static int ppce500_prep_device_tree(QEMUMachineInitArgs *args,
PPCE500Params *params,
hwaddr addr,
hwaddr initrd_base,
hwaddr initrd_size)
{
DeviceTreeParams *p = g_new(DeviceTreeParams, 1);
p->args = *args;
p->params = *params;
p->addr = addr;
p->initrd_base = initrd_base;
p->initrd_size = initrd_size;

qemu_register_reset(ppce500_reset_device_tree, p);

/* Issue the device tree loader once, so that we get the size of the blob */
return ppce500_load_device_tree(args, params, addr, initrd_base,
initrd_size, true);
}

/* Create -kernel TLB entries for BookE. */
static inline hwaddr booke206_page_size_to_tlb(uint64_t size)
{
Expand Down Expand Up @@ -746,7 +780,7 @@ void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params)
struct boot_info *boot_info;
int dt_size;

dt_size = ppce500_load_device_tree(env, args, params, dt_base,
dt_size = ppce500_prep_device_tree(args, params, dt_base,
initrd_base, initrd_size);
if (dt_size < 0) {
fprintf(stderr, "couldn't load device tree\n");
Expand Down
39 changes: 22 additions & 17 deletions hw/ppc/ppc405_boards.c
Expand Up @@ -27,9 +27,11 @@
#include "hw/timer/m48t59.h"
#include "hw/block/flash.h"
#include "sysemu/sysemu.h"
#include "sysemu/qtest.h"
#include "block/block.h"
#include "hw/boards.h"
#include "qemu/log.h"
#include "qemu/error-report.h"
#include "hw/loader.h"
#include "sysemu/blockdev.h"
#include "exec/address-spaces.h"
Expand All @@ -42,7 +44,7 @@

#define USE_FLASH_BIOS

#define DEBUG_BOARD_INIT
//#define DEBUG_BOARD_INIT

/*****************************************************************************/
/* PPC405EP reference board (IBM) */
Expand Down Expand Up @@ -252,17 +254,20 @@ static void ref405ep_init(QEMUMachineInitArgs *args)
if (filename) {
bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
g_free(filename);
if (bios_size < 0 || bios_size > BIOS_SIZE) {
error_report("Could not load PowerPC BIOS '%s'", bios_name);
exit(1);
}
bios_size = (bios_size + 0xfff) & ~0xfff;
memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
} else if (!qtest_enabled() || kernel_filename != NULL) {
error_report("Could not load PowerPC BIOS '%s'", bios_name);
exit(1);
} else {
/* Avoid an uninitialized variable warning */
bios_size = -1;
}
if (bios_size < 0 || bios_size > BIOS_SIZE) {
fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n",
bios_name);
exit(1);
}
bios_size = (bios_size + 0xfff) & ~0xfff;
memory_region_set_readonly(bios, true);
memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
}
/* Register FPGA */
#ifdef DEBUG_BOARD_INIT
Expand Down Expand Up @@ -353,9 +358,9 @@ static void ref405ep_init(QEMUMachineInitArgs *args)
bdloc = 0;
}
#ifdef DEBUG_BOARD_INIT
printf("bdloc " RAM_ADDR_FMT "\n", bdloc);
printf("%s: Done\n", __func__);
#endif
printf("bdloc " RAM_ADDR_FMT "\n", bdloc);
}

static QEMUMachine ref405ep_machine = {
Expand Down Expand Up @@ -569,17 +574,17 @@ static void taihu_405ep_init(QEMUMachineInitArgs *args)
if (filename) {
bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
g_free(filename);
} else {
bios_size = -1;
}
if (bios_size < 0 || bios_size > BIOS_SIZE) {
fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n",
bios_name);
if (bios_size < 0 || bios_size > BIOS_SIZE) {
error_report("Could not load PowerPC BIOS '%s'", bios_name);
exit(1);
}
bios_size = (bios_size + 0xfff) & ~0xfff;
memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
} else if (!qtest_enabled()) {
error_report("Could not load PowerPC BIOS '%s'", bios_name);
exit(1);
}
bios_size = (bios_size + 0xfff) & ~0xfff;
memory_region_set_readonly(bios, true);
memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
}
/* Register Linux flash */
dinfo = drive_get(IF_PFLASH, 0, fl_idx);
Expand Down
16 changes: 8 additions & 8 deletions hw/ppc/ppc405_uc.c
Expand Up @@ -30,15 +30,15 @@
#include "qemu/log.h"
#include "exec/address-spaces.h"

#define DEBUG_OPBA
#define DEBUG_SDRAM
#define DEBUG_GPIO
#define DEBUG_SERIAL
#define DEBUG_OCM
//#define DEBUG_OPBA
//#define DEBUG_SDRAM
//#define DEBUG_GPIO
//#define DEBUG_SERIAL
//#define DEBUG_OCM
//#define DEBUG_I2C
#define DEBUG_GPT
#define DEBUG_MAL
#define DEBUG_CLOCKS
//#define DEBUG_GPT
//#define DEBUG_MAL
//#define DEBUG_CLOCKS
//#define DEBUG_CLOCKS_LL

ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd,
Expand Down
31 changes: 26 additions & 5 deletions hw/ppc/spapr.c
Expand Up @@ -88,6 +88,9 @@ int spapr_allocate_irq(int hint, bool lsi)

if (hint) {
irq = hint;
if (hint >= spapr->next_irq) {
spapr->next_irq = hint + 1;
}
/* FIXME: we should probably check for collisions somehow */
} else {
irq = spapr->next_irq++;
Expand All @@ -103,22 +106,39 @@ int spapr_allocate_irq(int hint, bool lsi)
return irq;
}

/* Allocate block of consequtive IRQs, returns a number of the first */
int spapr_allocate_irq_block(int num, bool lsi)
/*
* Allocate block of consequtive IRQs, returns a number of the first.
* If msi==true, aligns the first IRQ number to num.
*/
int spapr_allocate_irq_block(int num, bool lsi, bool msi)
{
int first = -1;
int i;
int i, hint = 0;

/*
* MSIMesage::data is used for storing VIRQ so
* it has to be aligned to num to support multiple
* MSI vectors. MSI-X is not affected by this.
* The hint is used for the first IRQ, the rest should
* be allocated continously.
*/
if (msi) {
assert((num == 1) || (num == 2) || (num == 4) ||
(num == 8) || (num == 16) || (num == 32));
hint = (spapr->next_irq + num - 1) & ~(num - 1);
}

for (i = 0; i < num; ++i) {
int irq;

irq = spapr_allocate_irq(0, lsi);
irq = spapr_allocate_irq(hint, lsi);
if (!irq) {
return -1;
}

if (0 == i) {
first = irq;
hint = 0;
}

/* If the above doesn't create a consecutive block then that's
Expand Down Expand Up @@ -262,7 +282,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
uint32_t start_prop = cpu_to_be32(initrd_base);
uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
"\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk";
"\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk\0hcall-set-mode";
char qemu_hypertas_prop[] = "hcall-memop1";
uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
Expand Down Expand Up @@ -1214,6 +1234,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
spapr_create_nvram(spapr);

/* Set up PCI */
spapr_pci_msi_init(spapr, SPAPR_PCI_MSI_WINDOW);
spapr_pci_rtas_init();

phb = spapr_create_phb(spapr, 0);
Expand Down
50 changes: 50 additions & 0 deletions hw/ppc/spapr_hcall.c
Expand Up @@ -657,6 +657,54 @@ static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr,
return H_SUCCESS;
}

static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
CPUState *cs;
target_ulong mflags = args[0];
target_ulong resource = args[1];
target_ulong value1 = args[2];
target_ulong value2 = args[3];
target_ulong ret = H_P2;

if (resource == H_SET_MODE_ENDIAN) {
if (value1) {
ret = H_P3;
goto out;
}
if (value2) {
ret = H_P4;
goto out;
}

switch (mflags) {
case H_SET_MODE_ENDIAN_BIG:
for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
PowerPCCPU *cp = POWERPC_CPU(cs);
CPUPPCState *env = &cp->env;
env->spr[SPR_LPCR] &= ~LPCR_ILE;
}
ret = H_SUCCESS;
break;

case H_SET_MODE_ENDIAN_LITTLE:
for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
PowerPCCPU *cp = POWERPC_CPU(cs);
CPUPPCState *env = &cp->env;
env->spr[SPR_LPCR] |= LPCR_ILE;
}
ret = H_SUCCESS;
break;

default:
ret = H_UNSUPPORTED_FLAG;
}
}

out:
return ret;
}

static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1];

Expand Down Expand Up @@ -734,6 +782,8 @@ static void hypercall_register_types(void)

/* qemu/KVM-PPC specific hcalls */
spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);

spapr_register_hypercall(H_SET_MODE, h_set_mode);
}

type_init(hypercall_register_types)

0 comments on commit 32f3bd6

Please sign in to comment.