#include "kvm_ppc.h"
#include "hw/boards.h"
-#include "hw/ppc.h"
+#include "hw/ppc/ppc.h"
#include "hw/loader.h"
-#include "hw/spapr.h"
-#include "hw/spapr_vio.h"
-#include "hw/spapr_pci.h"
-#include "hw/xics.h"
+#include "hw/ppc/spapr.h"
+#include "hw/ppc/spapr_vio.h"
+#include "hw/pci-host/spapr.h"
+#include "hw/ppc/xics.h"
#include "hw/pci/msi.h"
-#include "sysemu/kvm.h"
-#include "kvm_ppc.h"
#include "hw/pci/pci.h"
#include "exec/address-spaces.h"
static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
{
int ret = 0, offset;
- CPUPPCState *env;
CPUState *cpu;
char cpu_model[32];
int smt = kvmppc_smt_threads();
assert(spapr->cpu_model);
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
- cpu = CPU(ppc_env_get_cpu(env));
+ for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
uint32_t associativity[] = {cpu_to_be32(0x5),
cpu_to_be32(0x0),
cpu_to_be32(0x0),
uint32_t epow_irq)
{
void *fdt;
- CPUPPCState *env;
+ CPUState *cs;
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"
/* This is needed during FDT finalization */
spapr->cpu_model = g_strdup(modelname);
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
- CPUState *cpu = CPU(ppc_env_get_cpu(env));
- int index = cpu->cpu_index;
+ for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
+ int index = cs->cpu_index;
uint32_t servers_prop[smp_threads];
uint32_t gservers_prop[smp_threads * 2];
char *nodename;
_FDT((fdt_property_string(fdt, "device_type", "cpu")));
_FDT((fdt_property_cell(fdt, "cpu-version", env->spr[SPR_PVR])));
- _FDT((fdt_property_cell(fdt, "dcache-block-size",
+ _FDT((fdt_property_cell(fdt, "d-cache-block-size",
env->dcache_line_size)));
- _FDT((fdt_property_cell(fdt, "icache-block-size",
+ _FDT((fdt_property_cell(fdt, "d-cache-line-size",
+ env->dcache_line_size)));
+ _FDT((fdt_property_cell(fdt, "i-cache-block-size",
+ env->icache_line_size)));
+ _FDT((fdt_property_cell(fdt, "i-cache-line-size",
env->icache_line_size)));
+
+ if (pcc->l1_dcache_size) {
+ _FDT((fdt_property_cell(fdt, "d-cache-size", pcc->l1_dcache_size)));
+ } else {
+ fprintf(stderr, "Warning: Unknown L1 dcache size for cpu\n");
+ }
+ if (pcc->l1_icache_size) {
+ _FDT((fdt_property_cell(fdt, "i-cache-size", pcc->l1_icache_size)));
+ } else {
+ fprintf(stderr, "Warning: Unknown L1 icache size for cpu\n");
+ }
+
_FDT((fdt_property_cell(fdt, "timebase-frequency", tbfreq)));
_FDT((fdt_property_cell(fdt, "clock-frequency", cpufreq)));
_FDT((fdt_property_cell(fdt, "ibm,slb-size", env->slb_nr)));
static void ppc_spapr_reset(void)
{
- CPUState *first_cpu_cpu;
+ PowerPCCPU *first_ppc_cpu;
/* Reset the hash table & recalc the RMA */
spapr_reset_htab(spapr);
spapr->rtas_size);
/* Set up the entry state */
- first_cpu_cpu = CPU(first_cpu);
- first_cpu->gpr[3] = spapr->fdt_addr;
- first_cpu->gpr[5] = 0;
- first_cpu_cpu->halted = 0;
- first_cpu->nip = spapr->entry_point;
+ first_ppc_cpu = POWERPC_CPU(first_cpu);
+ first_ppc_cpu->env.gpr[3] = spapr->fdt_addr;
+ first_ppc_cpu->env.gpr[5] = 0;
+ first_cpu->halted = 0;
+ first_ppc_cpu->env.nip = spapr->entry_point;
}
env->external_htab = spapr->htab;
env->htab_base = -1;
env->htab_mask = HTAB_SIZE(spapr) - 1;
- env->spr[SPR_SDR1] = (unsigned long)spapr->htab |
+ env->spr[SPR_SDR1] = (target_ulong)(uintptr_t)spapr->htab |
(spapr->htab_shift - 18);
}
static void spapr_create_nvram(sPAPREnvironment *spapr)
{
- QemuOpts *machine_opts;
- DeviceState *dev;
-
- dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
+ DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
+ const char *drivename = qemu_opt_get(qemu_get_machine_opts(), "nvram");
- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
- if (machine_opts) {
- const char *drivename;
+ if (drivename) {
+ BlockDriverState *bs;
- drivename = qemu_opt_get(machine_opts, "nvram");
- if (drivename) {
- BlockDriverState *bs;
-
- bs = bdrv_find(drivename);
- if (!bs) {
- fprintf(stderr, "No such block device \"%s\" for nvram\n",
- drivename);
- exit(1);
- }
- qdev_prop_set_drive_nofail(dev, "drive", bs);
+ bs = bdrv_find(drivename);
+ if (!bs) {
+ fprintf(stderr, "No such block device \"%s\" for nvram\n",
+ drivename);
+ exit(1);
}
+ qdev_prop_set_drive_nofail(dev, "drive", bs);
}
qdev_init_nofail(dev);
spapr->htab_shift++;
}
+ /* Set up Interrupt Controller before we create the VCPUs */
+ spapr->icp = xics_system_init(smp_cpus * kvmppc_smt_threads() / smp_threads,
+ XICS_IRQS);
+ spapr->next_irq = XICS_IRQ_BASE;
+
/* init CPUs */
if (cpu_model == NULL) {
cpu_model = kvm_enabled() ? "host" : "POWER7";
}
env = &cpu->env;
+ xics_cpu_setup(spapr->icp, cpu);
+
/* Set time-base frequency to 512 MHz */
cpu_ppc_tb_init(env, TIMEBASE_FREQ);
- /* PAPR always has exception vectors in RAM not ROM */
- env->hreset_excp_prefix = 0;
+ /* PAPR always has exception vectors in RAM not ROM. To ensure this,
+ * MSR[IP] should never be set.
+ */
+ env->msr_mask &= ~(1 << 6);
/* Tell KVM that we're in PAPR mode */
if (kvm_enabled()) {
ram_addr_t nonrma_base = rma_alloc_size;
ram_addr_t nonrma_size = spapr->ram_limit - rma_alloc_size;
- memory_region_init_ram(ram, "ppc_spapr.ram", nonrma_size);
+ memory_region_init_ram(ram, NULL, "ppc_spapr.ram", nonrma_size);
vmstate_register_ram_global(ram);
memory_region_add_subregion(sysmem, nonrma_base, ram);
}
}
g_free(filename);
-
- /* Set up Interrupt Controller */
- spapr->icp = xics_system_init(XICS_IRQS);
- spapr->next_irq = XICS_IRQ_BASE;
-
/* Set up EPOW events infrastructure */
spapr_events_init(spapr);
/* Set up PCI */
spapr_pci_rtas_init();
- phb = spapr_create_phb(spapr, 0, "pci");
+ phb = spapr_create_phb(spapr, 0);
for (i = 0; i < nb_nics; i++) {
NICInfo *nd = &nd_table[i];
if (strcmp(nd->model, "ibmveth") == 0) {
spapr_vlan_create(spapr->vio_bus, nd);
} else {
- pci_nic_init_nofail(&nd_table[i], nd->model, NULL);
+ pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL);
}
}
}
}
- filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME);
+ if (bios_name == NULL) {
+ bios_name = FW_FILE_NAME;
+ }
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
if (fw_size < 0) {
hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
static QEMUMachine spapr_machine = {
.name = "pseries",
.desc = "pSeries Logical Partition (PAPR compliant)",
+ .is_default = 1,
.init = ppc_spapr_init,
.reset = ppc_spapr_reset,
.block_default_type = IF_SCSI,