Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-3.0-20180622' into staging

ppc patch queue 2018-06-22

Another assorted patch of patches for ppc and spapr.
    * Rework of guest pagesize handling for ppc, which avoids guest
      visibly different behaviour between accelerators
    * A number of Pnv cleanups, working towards more complete POWER9
      support
    * Migration of VPA data, a significant bugfix

# gpg: Signature made Fri 22 Jun 2018 05:23:16 BST
# gpg:                using RSA key 6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg:                 aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg:                 aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# gpg:                 aka "David Gibson (kernel.org) <dwg@kernel.org>"
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E  87DC 6C38 CACA 20D9 B392

* remotes/dgibson/tags/ppc-for-3.0-20180622: (23 commits)
  spapr: Don't rewrite mmu capabilities in KVM mode
  spapr: Limit available pagesizes to provide a consistent guest environment
  target/ppc: Add ppc_hash64_filter_pagesizes()
  spapr: Use maximum page size capability to simplify memory backend checking
  spapr: Maximum (HPT) pagesize property
  pseries: Update SLOF firmware image to qemu-slof-20180621
  target/ppc: Add missing opcode for icbt on PPC440
  ppc4xx_i2c: Implement directcntl register
  ppc4xx_i2c: Remove unimplemented sdata and intr registers
  sm501: Fix hardware cursor color conversion
  fpu_helper.c: fix helper_fpscr_clrbit() function
  spapr: remove unused spapr_irq routines
  spapr: split the IRQ allocation sequence
  target/ppc: Add kvmppc_hpt_needs_host_contiguous_pages() helper
  spapr: Add cpu_apply hook to capabilities
  spapr: Compute effective capability values earlier
  target/ppc: Allow cpu compatiblity checks based on type, not instance
  ppc/pnv: consolidate the creation of the ISA bus device tree
  ppc/pnv: introduce Pnv8Chip and Pnv9Chip models
  spapr_cpu_core: migrate VPA related state
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2018-06-22 15:14:08 +01:00
29 changed files with 868 additions and 370 deletions
+1
View File
@@ -26,6 +26,7 @@ CONFIG_USB_EHCI_SYSBUS=y
CONFIG_SM501=y
CONFIG_IDE_SII3112=y
CONFIG_I2C=y
CONFIG_BITBANG_I2C=y
# For Macs
CONFIG_MAC=y
+1
View File
@@ -19,3 +19,4 @@ CONFIG_USB_EHCI_SYSBUS=y
CONFIG_SM501=y
CONFIG_IDE_SII3112=y
CONFIG_I2C=y
CONFIG_BITBANG_I2C=y
+3 -3
View File
@@ -652,9 +652,9 @@ static inline void get_hwc_palette(SM501State *state, int crt, uint8_t *palette)
} else {
rgb565 = color_reg & 0xFFFF;
}
palette[i * 3 + 0] = (rgb565 << 3) & 0xf8; /* red */
palette[i * 3 + 1] = (rgb565 >> 3) & 0xfc; /* green */
palette[i * 3 + 2] = (rgb565 >> 8) & 0xf8; /* blue */
palette[i * 3 + 0] = ((rgb565 >> 11) * 527 + 23) >> 6; /* r */
palette[i * 3 + 1] = (((rgb565 >> 5) & 0x3f) * 259 + 33) >> 6; /* g */
palette[i * 3 + 2] = ((rgb565 & 0x1f) * 527 + 23) >> 6; /* b */
}
}
+14 -16
View File
@@ -3,7 +3,7 @@
*
* Copyright (c) 2007 Jocelyn Mayer
* Copyright (c) 2012 François Revol
* Copyright (c) 2016 BALATON Zoltan
* Copyright (c) 2016-2018 BALATON Zoltan
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -30,6 +30,7 @@
#include "cpu.h"
#include "hw/hw.h"
#include "hw/i2c/ppc4xx_i2c.h"
#include "bitbang_i2c.h"
#define PPC4xx_I2C_MEM_SIZE 18
@@ -46,6 +47,11 @@
#define IIC_XTCNTLSS_SRST (1 << 0)
#define IIC_DIRECTCNTL_SDAC (1 << 3)
#define IIC_DIRECTCNTL_SCLC (1 << 2)
#define IIC_DIRECTCNTL_MSDA (1 << 1)
#define IIC_DIRECTCNTL_MSCL (1 << 0)
static void ppc4xx_i2c_reset(DeviceState *s)
{
PPC4xxI2CState *i2c = PPC4xx_I2C(s);
@@ -63,7 +69,6 @@ static void ppc4xx_i2c_reset(DeviceState *s)
i2c->mdcntl = 0;
i2c->sts = 0;
i2c->extsts = 0x8f;
i2c->sdata = 0;
i2c->lsadr = 0;
i2c->hsadr = 0;
i2c->clkdiv = 0;
@@ -71,7 +76,6 @@ static void ppc4xx_i2c_reset(DeviceState *s)
i2c->xfrcnt = 0;
i2c->xtcntlss = 0;
i2c->directcntl = 0xf;
i2c->intr = 0;
}
static inline bool ppc4xx_i2c_is_master(PPC4xxI2CState *i2c)
@@ -139,9 +143,6 @@ static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
TYPE_PPC4xx_I2C, __func__);
}
break;
case 2:
ret = i2c->sdata;
break;
case 4:
ret = i2c->lmadr;
break;
@@ -181,9 +182,6 @@ static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
case 16:
ret = i2c->directcntl;
break;
case 17:
ret = i2c->intr;
break;
default:
if (addr < PPC4xx_I2C_MEM_SIZE) {
qemu_log_mask(LOG_UNIMP, "%s: Unimplemented register 0x%"
@@ -229,9 +227,6 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
}
}
break;
case 2:
i2c->sdata = value;
break;
case 4:
i2c->lmadr = value;
if (i2c_bus_busy(i2c->bus)) {
@@ -300,10 +295,12 @@ static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
i2c->xtcntlss = value;
break;
case 16:
i2c->directcntl = value & 0x7;
break;
case 17:
i2c->intr = value;
i2c->directcntl = value & (IIC_DIRECTCNTL_SDAC & IIC_DIRECTCNTL_SCLC);
i2c->directcntl |= (value & IIC_DIRECTCNTL_SCLC ? 1 : 0);
bitbang_i2c_set(i2c->bitbang, BITBANG_I2C_SCL,
i2c->directcntl & IIC_DIRECTCNTL_MSCL);
i2c->directcntl |= bitbang_i2c_set(i2c->bitbang, BITBANG_I2C_SDA,
(value & IIC_DIRECTCNTL_SDAC) != 0) << 1;
break;
default:
if (addr < PPC4xx_I2C_MEM_SIZE) {
@@ -336,6 +333,7 @@ static void ppc4xx_i2c_init(Object *o)
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
s->bus = i2c_init_bus(DEVICE(s), "i2c");
s->bitbang = bitbang_i2c_init(s->bus);
}
static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data)
+238 -145
View File
File diff suppressed because it is too large Load Diff
+9 -9
View File
@@ -99,13 +99,14 @@ static const MemoryRegionOps pnv_core_xscom_ops = {
.endianness = DEVICE_BIG_ENDIAN,
};
static void pnv_realize_vcpu(PowerPCCPU *cpu, XICSFabric *xi, Error **errp)
static void pnv_realize_vcpu(PowerPCCPU *cpu, PnvChip *chip, Error **errp)
{
CPUPPCState *env = &cpu->env;
int core_pir;
int thread_index = 0; /* TODO: TCG supports only one thread */
ppc_spr_t *pir = &env->spr_cb[SPR_PIR];
Error *local_err = NULL;
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
object_property_set_bool(OBJECT(cpu), true, "realized", &local_err);
if (local_err) {
@@ -113,7 +114,7 @@ static void pnv_realize_vcpu(PowerPCCPU *cpu, XICSFabric *xi, Error **errp)
return;
}
cpu->intc = icp_create(OBJECT(cpu), TYPE_PNV_ICP, xi, &local_err);
cpu->intc = pcc->intc_create(chip, OBJECT(cpu), &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
@@ -143,13 +144,12 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
void *obj;
int i, j;
char name[32];
Object *xi;
Object *chip;
xi = object_property_get_link(OBJECT(dev), "xics", &local_err);
if (!xi) {
error_setg(errp, "%s: required link 'xics' not found: %s",
__func__, error_get_pretty(local_err));
return;
chip = object_property_get_link(OBJECT(dev), "chip", &local_err);
if (!chip) {
error_propagate(errp, local_err);
error_prepend(errp, "required link 'chip' not found: ");
}
pc->threads = g_new(PowerPCCPU *, cc->nr_threads);
@@ -166,7 +166,7 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
}
for (j = 0; j < cc->nr_threads; j++) {
pnv_realize_vcpu(pc->threads[j], XICS_FABRIC(xi), &local_err);
pnv_realize_vcpu(pc->threads[j], PNV_CHIP(chip), &local_err);
if (local_err) {
goto err;
}
+25 -5
View File
@@ -22,6 +22,7 @@
#include "target/ppc/cpu.h"
#include "qapi/error.h"
#include "qemu/log.h"
#include "hw/isa/isa.h"
#include "hw/ppc/pnv.h"
#include "hw/ppc/pnv_lpc.h"
@@ -535,16 +536,35 @@ static void pnv_lpc_isa_irq_handler(void *opaque, int n, int level)
}
}
qemu_irq *pnv_lpc_isa_irq_create(PnvLpcController *lpc, int chip_type,
int nirqs)
ISABus *pnv_lpc_isa_create(PnvLpcController *lpc, bool use_cpld, Error **errp)
{
Error *local_err = NULL;
ISABus *isa_bus;
qemu_irq *irqs;
qemu_irq_handler handler;
/* let isa_bus_new() create its own bridge on SysBus otherwise
* devices speficied on the command line won't find the bus and
* will fail to create.
*/
isa_bus = isa_bus_new(NULL, &lpc->isa_mem, &lpc->isa_io, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return NULL;
}
/* Not all variants have a working serial irq decoder. If not,
* handling of LPC interrupts becomes a platform issue (some
* platforms have a CPLD to do it).
*/
if (chip_type == PNV_CHIP_POWER8NVL) {
return qemu_allocate_irqs(pnv_lpc_isa_irq_handler, lpc, nirqs);
if (use_cpld) {
handler = pnv_lpc_isa_irq_handler_cpld;
} else {
return qemu_allocate_irqs(pnv_lpc_isa_irq_handler_cpld, lpc, nirqs);
handler = pnv_lpc_isa_irq_handler;
}
irqs = qemu_allocate_irqs(handler, lpc, ISA_NUM_IRQS);
isa_bus_irqs(isa_bus, irqs);
return isa_bus;
}
+54 -68
View File
@@ -63,6 +63,7 @@
#include "hw/virtio/vhost-scsi-common.h"
#include "exec/address-spaces.h"
#include "exec/ram_addr.h"
#include "hw/usb.h"
#include "qemu/config-file.h"
#include "qemu/error-report.h"
@@ -1612,12 +1613,12 @@ static void spapr_machine_reset(void)
void *fdt;
int rc;
spapr_caps_reset(spapr);
spapr_caps_apply(spapr);
first_ppc_cpu = POWERPC_CPU(first_cpu);
if (kvm_enabled() && kvmppc_has_cap_mmu_radix() &&
ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0,
spapr->max_compat_pvr)) {
ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0,
spapr->max_compat_pvr)) {
/* If using KVM with radix mode available, VCPUs can be started
* without a HPT because KVM will start them in radix mode.
* Set the GR bit in PATB so that we know there is no HPT. */
@@ -2520,14 +2521,15 @@ static void spapr_machine_init(MachineState *machine)
long load_limit, fw_size;
char *filename;
Error *resize_hpt_err = NULL;
PowerPCCPU *first_ppc_cpu;
msi_nonbroken = true;
QLIST_INIT(&spapr->phbs);
QTAILQ_INIT(&spapr->pending_dimm_unplugs);
/* Check HPT resizing availability */
/* Determine capabilities to run with */
spapr_caps_init(spapr);
kvmppc_check_papr_resize_hpt(&resize_hpt_err);
if (spapr->resize_hpt == SPAPR_RESIZE_HPT_DEFAULT) {
/*
@@ -2618,10 +2620,9 @@ static void spapr_machine_init(MachineState *machine)
/* init CPUs */
spapr_init_cpus(spapr);
first_ppc_cpu = POWERPC_CPU(first_cpu);
if ((!kvm_enabled() || kvmppc_has_cap_mmu_radix()) &&
ppc_check_compat(first_ppc_cpu, CPU_POWERPC_LOGICAL_3_00, 0,
spapr->max_compat_pvr)) {
ppc_type_check_compat(machine->cpu_type, CPU_POWERPC_LOGICAL_3_00, 0,
spapr->max_compat_pvr)) {
/* KVM and TCG always allow GTSE with radix... */
spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE);
}
@@ -3191,11 +3192,13 @@ static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
const sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(hotplug_dev);
sPAPRMachineState *spapr = SPAPR_MACHINE(hotplug_dev);
PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
MemoryRegion *mr;
uint64_t size;
char *mem_dev;
Object *memdev;
hwaddr pagesize;
if (!smc->dr_lmb_enabled) {
error_setg(errp, "Memory hotplug not supported for this machine");
@@ -3214,15 +3217,10 @@ static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
return;
}
mem_dev = object_property_get_str(OBJECT(dimm), PC_DIMM_MEMDEV_PROP, NULL);
if (mem_dev && !kvmppc_is_mem_backend_page_size_ok(mem_dev)) {
error_setg(errp, "Memory backend has bad page size. "
"Use 'memory-backend-file' with correct mem-path.");
goto out;
}
out:
g_free(mem_dev);
memdev = object_property_get_link(OBJECT(dimm), PC_DIMM_MEMDEV_PROP,
&error_abort);
pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(memdev));
spapr_check_pagesize(spapr, pagesize, errp);
}
struct sPAPRDIMMState {
@@ -3816,52 +3814,10 @@ static int ics_find_free_block(ICSState *ics, int num, int alignnum)
return -1;
}
/*
* Allocate the IRQ number and set the IRQ type, LSI or MSI
*/
static void spapr_irq_set_lsi(sPAPRMachineState *spapr, int irq, bool lsi)
{
ics_set_irq_type(spapr->ics, irq - spapr->ics->offset, lsi);
}
int spapr_irq_alloc(sPAPRMachineState *spapr, int irq_hint, bool lsi,
Error **errp)
int spapr_irq_find(sPAPRMachineState *spapr, int num, bool align, Error **errp)
{
ICSState *ics = spapr->ics;
int irq;
assert(ics);
if (irq_hint) {
if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) {
error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint);
return -1;
}
irq = irq_hint;
} else {
irq = ics_find_free_block(ics, 1, 1);
if (irq < 0) {
error_setg(errp, "can't allocate IRQ: no IRQ left");
return -1;
}
irq += ics->offset;
}
spapr_irq_set_lsi(spapr, irq, lsi);
trace_spapr_irq_alloc(irq);
return irq;
}
/*
* Allocate block of consecutive IRQs, and return the number of the first IRQ in
* the block. If align==true, aligns the first IRQ number to num.
*/
int spapr_irq_alloc_block(sPAPRMachineState *spapr, int num, bool lsi,
bool align, Error **errp)
{
ICSState *ics = spapr->ics;
int i, first = -1;
int first = -1;
assert(ics);
@@ -3879,19 +3835,33 @@ int spapr_irq_alloc_block(sPAPRMachineState *spapr, int num, bool lsi,
} else {
first = ics_find_free_block(ics, num, 1);
}
if (first < 0) {
error_setg(errp, "can't find a free %d-IRQ block", num);
return -1;
}
first += ics->offset;
for (i = first; i < first + num; ++i) {
spapr_irq_set_lsi(spapr, i, lsi);
return first + ics->offset;
}
int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp)
{
ICSState *ics = spapr->ics;
assert(ics);
if (!ics_valid_irq(ics, irq)) {
error_setg(errp, "IRQ %d is invalid", irq);
return -1;
}
trace_spapr_irq_alloc_block(first, num, lsi, align);
if (!ICS_IRQ_FREE(ics, irq - ics->offset)) {
error_setg(errp, "IRQ %d is not free", irq);
return -1;
}
return first;
ics_set_irq_type(ics, irq - ics->offset, lsi);
return 0;
}
void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num)
@@ -4043,6 +4013,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
spapr_caps_add_properties(smc, &error_abort);
}
@@ -4115,7 +4086,12 @@ DEFINE_SPAPR_MACHINE(3_0, "3.0", true);
HW_COMPAT_2_12 \
{ \
.driver = TYPE_POWERPC_CPU, \
.property = "pre-3.0-migration", \
.property = "pre-3.0-migration", \
.value = "on", \
}, \
{ \
.driver = TYPE_SPAPR_CPU_CORE, \
.property = "pre-3.0-migration", \
.value = "on", \
},
@@ -4126,8 +4102,18 @@ static void spapr_machine_2_12_instance_options(MachineState *machine)
static void spapr_machine_2_12_class_options(MachineClass *mc)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
uint8_t mps;
spapr_machine_3_0_class_options(mc);
SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_12);
if (kvmppc_hpt_needs_host_contiguous_pages()) {
mps = ctz64(qemu_getrampagesize());
} else {
mps = 34; /* allow everything up to 16GiB, i.e. everything */
}
smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = mps;
}
DEFINE_SPAPR_MACHINE(2_12, "2.12", false);
+145 -13
View File
@@ -26,7 +26,9 @@
#include "qapi/error.h"
#include "qapi/visitor.h"
#include "sysemu/hw_accel.h"
#include "exec/ram_addr.h"
#include "target/ppc/cpu.h"
#include "target/ppc/mmu-hash64.h"
#include "cpu-models.h"
#include "kvm_ppc.h"
@@ -59,6 +61,8 @@ typedef struct sPAPRCapabilityInfo {
sPAPRCapPossible *possible;
/* Make sure the virtual hardware can support this capability */
void (*apply)(sPAPRMachineState *spapr, uint8_t val, Error **errp);
void (*cpu_apply)(sPAPRMachineState *spapr, PowerPCCPU *cpu,
uint8_t val, Error **errp);
} sPAPRCapabilityInfo;
static void spapr_cap_get_bool(Object *obj, Visitor *v, const char *name,
@@ -142,6 +146,42 @@ out:
g_free(val);
}
static void spapr_cap_get_pagesize(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
sPAPRCapabilityInfo *cap = opaque;
sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
uint8_t val = spapr_get_cap(spapr, cap->index);
uint64_t pagesize = (1ULL << val);
visit_type_size(v, name, &pagesize, errp);
}
static void spapr_cap_set_pagesize(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
sPAPRCapabilityInfo *cap = opaque;
sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
uint64_t pagesize;
uint8_t val;
Error *local_err = NULL;
visit_type_size(v, name, &pagesize, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
if (!is_power_of_2(pagesize)) {
error_setg(errp, "cap-%s must be a power of 2", cap->name);
return;
}
val = ctz64(pagesize);
spapr->cmd_line_caps[cap->index] = true;
spapr->eff.caps[cap->index] = val;
}
static void cap_htm_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
{
if (!val) {
@@ -265,6 +305,69 @@ static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
#define VALUE_DESC_TRISTATE " (broken, workaround, fixed)"
void spapr_check_pagesize(sPAPRMachineState *spapr, hwaddr pagesize,
Error **errp)
{
hwaddr maxpagesize = (1ULL << spapr->eff.caps[SPAPR_CAP_HPT_MAXPAGESIZE]);
if (!kvmppc_hpt_needs_host_contiguous_pages()) {
return;
}
if (maxpagesize > pagesize) {
error_setg(errp,
"Can't support %"HWADDR_PRIu" kiB guest pages with %"
HWADDR_PRIu" kiB host pages with this KVM implementation",
maxpagesize >> 10, pagesize >> 10);
}
}
static void cap_hpt_maxpagesize_apply(sPAPRMachineState *spapr,
uint8_t val, Error **errp)
{
if (val < 12) {
error_setg(errp, "Require at least 4kiB hpt-max-page-size");
return;
} else if (val < 16) {
warn_report("Many guests require at least 64kiB hpt-max-page-size");
}
spapr_check_pagesize(spapr, qemu_getrampagesize(), errp);
}
static bool spapr_pagesize_cb(void *opaque, uint32_t seg_pshift,
uint32_t pshift)
{
unsigned maxshift = *((unsigned *)opaque);
assert(pshift >= seg_pshift);
/* Don't allow the guest to use pages bigger than the configured
* maximum size */
if (pshift > maxshift) {
return false;
}
/* For whatever reason, KVM doesn't allow multiple pagesizes
* within a segment, *except* for the case of 16M pages in a 4k or
* 64k segment. Always exclude other cases, so that TCG and KVM
* guests see a consistent environment */
if ((pshift != seg_pshift) && (pshift != 24)) {
return false;
}
return true;
}
static void cap_hpt_maxpagesize_cpu_apply(sPAPRMachineState *spapr,
PowerPCCPU *cpu,
uint8_t val, Error **errp)
{
unsigned maxshift = val;
ppc_hash64_filter_pagesizes(cpu, spapr_pagesize_cb, &maxshift);
}
sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
[SPAPR_CAP_HTM] = {
.name = "htm",
@@ -324,30 +427,39 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
.possible = &cap_ibs_possible,
.apply = cap_safe_indirect_branch_apply,
},
[SPAPR_CAP_HPT_MAXPAGESIZE] = {
.name = "hpt-max-page-size",
.description = "Maximum page size for Hash Page Table guests",
.index = SPAPR_CAP_HPT_MAXPAGESIZE,
.get = spapr_cap_get_pagesize,
.set = spapr_cap_set_pagesize,
.type = "int",
.apply = cap_hpt_maxpagesize_apply,
.cpu_apply = cap_hpt_maxpagesize_cpu_apply,
},
};
static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
CPUState *cs)
const char *cputype)
{
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
PowerPCCPU *cpu = POWERPC_CPU(cs);
sPAPRCapabilities caps;
caps = smc->default_caps;
if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07,
0, spapr->max_compat_pvr)) {
if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_2_07,
0, spapr->max_compat_pvr)) {
caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
}
if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06_PLUS,
0, spapr->max_compat_pvr)) {
if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_2_06_PLUS,
0, spapr->max_compat_pvr)) {
caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
}
if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06,
0, spapr->max_compat_pvr)) {
if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_2_06,
0, spapr->max_compat_pvr)) {
caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_OFF;
caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_OFF;
caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
@@ -384,7 +496,7 @@ int spapr_caps_post_migration(sPAPRMachineState *spapr)
sPAPRCapabilities dstcaps = spapr->eff;
sPAPRCapabilities srccaps;
srccaps = default_caps_with_cpu(spapr, first_cpu);
srccaps = default_caps_with_cpu(spapr, MACHINE(spapr)->cpu_type);
for (i = 0; i < SPAPR_CAP_NUM; i++) {
/* If not default value then assume came in with the migration */
if (spapr->mig.caps[i] != spapr->def.caps[i]) {
@@ -440,13 +552,13 @@ SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC);
SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
void spapr_caps_reset(sPAPRMachineState *spapr)
void spapr_caps_init(sPAPRMachineState *spapr)
{
sPAPRCapabilities default_caps;
int i;
/* First compute the actual set of caps we're running with.. */
default_caps = default_caps_with_cpu(spapr, first_cpu);
/* Compute the actual set of caps we should run with */
default_caps = default_caps_with_cpu(spapr, MACHINE(spapr)->cpu_type);
for (i = 0; i < SPAPR_CAP_NUM; i++) {
/* Store the defaults */
@@ -456,8 +568,11 @@ void spapr_caps_reset(sPAPRMachineState *spapr)
spapr->eff.caps[i] = default_caps.caps[i];
}
}
}
/* .. then apply those caps to the virtual hardware */
void spapr_caps_apply(sPAPRMachineState *spapr)
{
int i;
for (i = 0; i < SPAPR_CAP_NUM; i++) {
sPAPRCapabilityInfo *info = &capability_table[i];
@@ -470,6 +585,23 @@ void spapr_caps_reset(sPAPRMachineState *spapr)
}
}
void spapr_caps_cpu_apply(sPAPRMachineState *spapr, PowerPCCPU *cpu)
{
int i;
for (i = 0; i < SPAPR_CAP_NUM; i++) {
sPAPRCapabilityInfo *info = &capability_table[i];
/*
* If the apply function can't set the desired level and thinks it's
* fatal, it should cause that.
*/
if (info->cpu_apply) {
info->cpu_apply(spapr, cpu, spapr->eff.caps[i], &error_fatal);
}
}
}
void spapr_caps_add_properties(sPAPRMachineClass *smc, Error **errp)
{
Error *local_err = NULL;
+89 -2
View File
@@ -76,6 +76,10 @@ static void spapr_cpu_reset(void *opaque)
spapr_cpu->slb_shadow_size = 0;
spapr_cpu->dtl_addr = 0;
spapr_cpu->dtl_size = 0;
spapr_caps_cpu_apply(SPAPR_MACHINE(qdev_get_machine()), cpu);
kvm_check_mmu(cpu, &error_fatal);
}
void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip, target_ulong r3)
@@ -129,6 +133,80 @@ static void spapr_cpu_core_unrealize(DeviceState *dev, Error **errp)
g_free(sc->threads);
}
static bool slb_shadow_needed(void *opaque)
{
sPAPRCPUState *spapr_cpu = opaque;
return spapr_cpu->slb_shadow_addr != 0;
}
static const VMStateDescription vmstate_spapr_cpu_slb_shadow = {
.name = "spapr_cpu/vpa/slb_shadow",
.version_id = 1,
.minimum_version_id = 1,
.needed = slb_shadow_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT64(slb_shadow_addr, sPAPRCPUState),
VMSTATE_UINT64(slb_shadow_size, sPAPRCPUState),
VMSTATE_END_OF_LIST()
}
};
static bool dtl_needed(void *opaque)
{
sPAPRCPUState *spapr_cpu = opaque;
return spapr_cpu->dtl_addr != 0;
}
static const VMStateDescription vmstate_spapr_cpu_dtl = {
.name = "spapr_cpu/vpa/dtl",
.version_id = 1,
.minimum_version_id = 1,
.needed = dtl_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT64(dtl_addr, sPAPRCPUState),
VMSTATE_UINT64(dtl_size, sPAPRCPUState),
VMSTATE_END_OF_LIST()
}
};
static bool vpa_needed(void *opaque)
{
sPAPRCPUState *spapr_cpu = opaque;
return spapr_cpu->vpa_addr != 0;
}
static const VMStateDescription vmstate_spapr_cpu_vpa = {
.name = "spapr_cpu/vpa",
.version_id = 1,
.minimum_version_id = 1,
.needed = vpa_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT64(vpa_addr, sPAPRCPUState),
VMSTATE_END_OF_LIST()
},
.subsections = (const VMStateDescription * []) {
&vmstate_spapr_cpu_slb_shadow,
&vmstate_spapr_cpu_dtl,
NULL
}
};
static const VMStateDescription vmstate_spapr_cpu_state = {
.name = "spapr_cpu",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_END_OF_LIST()
},
.subsections = (const VMStateDescription * []) {
&vmstate_spapr_cpu_vpa,
NULL
}
};
static void spapr_realize_vcpu(PowerPCCPU *cpu, sPAPRMachineState *spapr,
Error **errp)
{
@@ -194,6 +272,10 @@ static PowerPCCPU *spapr_create_vcpu(sPAPRCPUCore *sc, int i, Error **errp)
}
cpu->machine_data = g_new0(sPAPRCPUState, 1);
if (!sc->pre_3_0_migration) {
vmstate_register(NULL, cs->cpu_index, &vmstate_spapr_cpu_state,
cpu->machine_data);
}
object_unref(obj);
return cpu;
@@ -204,10 +286,13 @@ err:
return NULL;
}
static void spapr_delete_vcpu(PowerPCCPU *cpu)
static void spapr_delete_vcpu(PowerPCCPU *cpu, sPAPRCPUCore *sc)
{
sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
if (!sc->pre_3_0_migration) {
vmstate_unregister(NULL, &vmstate_spapr_cpu_state, cpu->machine_data);
}
cpu->machine_data = NULL;
g_free(spapr_cpu);
object_unparent(OBJECT(cpu));
@@ -253,7 +338,7 @@ err_unrealize:
}
err:
while (--i >= 0) {
spapr_delete_vcpu(sc->threads[i]);
spapr_delete_vcpu(sc->threads[i], sc);
}
g_free(sc->threads);
error_propagate(errp, local_err);
@@ -261,6 +346,8 @@ err:
static Property spapr_cpu_core_properties[] = {
DEFINE_PROP_INT32("node-id", sPAPRCPUCore, node_id, CPU_UNSET_NUMA_NODE_ID),
DEFINE_PROP_BOOL("pre-3.0-migration", sPAPRCPUCore, pre_3_0_migration,
false),
DEFINE_PROP_END_OF_LIST()
};
+14 -4
View File
@@ -707,13 +707,18 @@ void spapr_clear_pending_events(sPAPRMachineState *spapr)
void spapr_events_init(sPAPRMachineState *spapr)
{
int epow_irq;
epow_irq = spapr_irq_findone(spapr, &error_fatal);
spapr_irq_claim(spapr, epow_irq, false, &error_fatal);
QTAILQ_INIT(&spapr->pending_events);
spapr->event_sources = spapr_event_sources_new();
spapr_event_sources_register(spapr->event_sources, EVENT_CLASS_EPOW,
spapr_irq_alloc(spapr, 0, false,
&error_fatal));
epow_irq);
/* NOTE: if machine supports modern/dedicated hotplug event source,
* we add it to the device-tree unconditionally. This means we may
@@ -724,9 +729,14 @@ void spapr_events_init(sPAPRMachineState *spapr)
* checking that it's enabled.
*/
if (spapr->use_hotplug_event_source) {
int hp_irq;
hp_irq = spapr_irq_findone(spapr, &error_fatal);
spapr_irq_claim(spapr, hp_irq, false, &error_fatal);
spapr_event_sources_register(spapr->event_sources, EVENT_CLASS_HOT_PLUG,
spapr_irq_alloc(spapr, 0, false,
&error_fatal));
hp_irq);
}
spapr->epow_notifier.notify = spapr_powerdown_req;
+20 -3
View File
@@ -279,6 +279,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
spapr_pci_msi *msi;
int *config_addr_key;
Error *err = NULL;
int i;
/* Fins sPAPRPHBState */
phb = spapr_pci_find_phb(spapr, buid);
@@ -371,8 +372,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
}
/* Allocate MSIs */
irq = spapr_irq_alloc_block(spapr, req_num, false,
ret_intr_type == RTAS_TYPE_MSI, &err);
irq = spapr_irq_find(spapr, req_num, ret_intr_type == RTAS_TYPE_MSI, &err);
if (err) {
error_reportf_err(err, "Can't allocate MSIs for device %x: ",
config_addr);
@@ -380,6 +380,16 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
return;
}
for (i = 0; i < req_num; i++) {
spapr_irq_claim(spapr, irq + i, false, &err);
if (err) {
error_reportf_err(err, "Can't allocate MSIs for device %x: ",
config_addr);
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
return;
}
}
/* Release previous MSIs */
if (msi) {
spapr_irq_free(spapr, msi->first_irq, msi->num);
@@ -1698,7 +1708,14 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
uint32_t irq;
Error *local_err = NULL;
irq = spapr_irq_alloc_block(spapr, 1, true, false, &local_err);
irq = spapr_irq_findone(spapr, &local_err);
if (local_err) {
error_propagate(errp, local_err);
error_prepend(errp, "can't allocate LSIs: ");
return;
}
spapr_irq_claim(spapr, irq, true, &local_err);
if (local_err) {
error_propagate(errp, local_err);
error_prepend(errp, "can't allocate LSIs: ");
+9 -1
View File
@@ -475,7 +475,15 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
dev->qdev.id = id;
}
dev->irq = spapr_irq_alloc(spapr, dev->irq, false, &local_err);
if (!dev->irq) {
dev->irq = spapr_irq_findone(spapr, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
}
spapr_irq_claim(spapr, dev->irq, false, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
+5 -3
View File
@@ -3,7 +3,7 @@
*
* Copyright (c) 2007 Jocelyn Mayer
* Copyright (c) 2012 François Revol
* Copyright (c) 2016 BALATON Zoltan
* Copyright (c) 2016-2018 BALATON Zoltan
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -31,6 +31,9 @@
#include "hw/sysbus.h"
#include "hw/i2c/i2c.h"
/* from hw/i2c/bitbang_i2c.h */
typedef struct bitbang_i2c_interface bitbang_i2c_interface;
#define TYPE_PPC4xx_I2C "ppc4xx-i2c"
#define PPC4xx_I2C(obj) OBJECT_CHECK(PPC4xxI2CState, (obj), TYPE_PPC4xx_I2C)
@@ -42,6 +45,7 @@ typedef struct PPC4xxI2CState {
I2CBus *bus;
qemu_irq irq;
MemoryRegion iomem;
bitbang_i2c_interface *bitbang;
uint8_t mdata;
uint8_t lmadr;
uint8_t hmadr;
@@ -49,7 +53,6 @@ typedef struct PPC4xxI2CState {
uint8_t mdcntl;
uint8_t sts;
uint8_t extsts;
uint8_t sdata;
uint8_t lsadr;
uint8_t hsadr;
uint8_t clkdiv;
@@ -57,7 +60,6 @@ typedef struct PPC4xxI2CState {
uint8_t xfrcnt;
uint8_t xtcntlss;
uint8_t directcntl;
uint8_t intr;
} PPC4xxI2CState;
#endif /* PPC4XX_I2C_H */
+25 -1
View File
@@ -57,12 +57,32 @@ typedef struct PnvChip {
MemoryRegion xscom_mmio;
MemoryRegion xscom;
AddressSpace xscom_as;
} PnvChip;
#define TYPE_PNV8_CHIP "pnv8-chip"
#define PNV8_CHIP(obj) OBJECT_CHECK(Pnv8Chip, (obj), TYPE_PNV8_CHIP)
typedef struct Pnv8Chip {
/*< private >*/
PnvChip parent_obj;
/*< public >*/
MemoryRegion icp_mmio;
PnvLpcController lpc;
PnvPsi psi;
PnvOCC occ;
} PnvChip;
} Pnv8Chip;
#define TYPE_PNV9_CHIP "pnv9-chip"
#define PNV9_CHIP(obj) OBJECT_CHECK(Pnv9Chip, (obj), TYPE_PNV9_CHIP)
typedef struct Pnv9Chip {
/*< private >*/
PnvChip parent_obj;
/*< public >*/
} Pnv9Chip;
typedef struct PnvChipClass {
/*< private >*/
@@ -75,7 +95,11 @@ typedef struct PnvChipClass {
hwaddr xscom_base;
DeviceRealize parent_realize;
uint32_t (*core_pir)(PnvChip *chip, uint32_t core_id);
Object *(*intc_create)(PnvChip *chip, Object *child, Error **errp);
ISABus *(*isa_create)(PnvChip *chip, Error **errp);
} PnvChipClass;
#define PNV_CHIP_TYPE_SUFFIX "-" TYPE_PNV_CHIP
+1 -2
View File
@@ -70,7 +70,6 @@ typedef struct PnvLpcController {
PnvPsi *psi;
} PnvLpcController;
qemu_irq *pnv_lpc_isa_irq_create(PnvLpcController *lpc, int chip_type,
int nirqs);
ISABus *pnv_lpc_isa_create(PnvLpcController *lpc, bool use_cpld, Error **errp);
#endif /* _PPC_PNV_LPC_H */
+13 -6
View File
@@ -66,8 +66,10 @@ typedef enum {
#define SPAPR_CAP_SBBC 0x04
/* Indirect Branch Serialisation */
#define SPAPR_CAP_IBS 0x05
/* HPT Maximum Page Size (encoded as a shift) */
#define SPAPR_CAP_HPT_MAXPAGESIZE 0x06
/* Num Caps */
#define SPAPR_CAP_NUM (SPAPR_CAP_IBS + 1)
#define SPAPR_CAP_NUM (SPAPR_CAP_HPT_MAXPAGESIZE + 1)
/*
* Capability Values
@@ -772,10 +774,10 @@ int spapr_get_vcpu_id(PowerPCCPU *cpu);
void spapr_set_vcpu_id(PowerPCCPU *cpu, int cpu_index, Error **errp);
PowerPCCPU *spapr_find_cpu(int vcpu_id);
int spapr_irq_alloc(sPAPRMachineState *spapr, int irq_hint, bool lsi,
Error **errp);
int spapr_irq_alloc_block(sPAPRMachineState *spapr, int num, bool lsi,
bool align, Error **errp);
int spapr_irq_find(sPAPRMachineState *spapr, int num, bool align,
Error **errp);
#define spapr_irq_findone(spapr, errp) spapr_irq_find(spapr, 1, false, errp)
int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp);
void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num);
qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq);
@@ -798,8 +800,13 @@ static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap)
return spapr->eff.caps[cap];
}
void spapr_caps_reset(sPAPRMachineState *spapr);
void spapr_caps_init(sPAPRMachineState *spapr);
void spapr_caps_apply(sPAPRMachineState *spapr);
void spapr_caps_cpu_apply(sPAPRMachineState *spapr, PowerPCCPU *cpu);
void spapr_caps_add_properties(sPAPRMachineClass *smc, Error **errp);
int spapr_caps_post_migration(sPAPRMachineState *spapr);
void spapr_check_pagesize(sPAPRMachineState *spapr, hwaddr pagesize,
Error **errp);
#endif /* HW_SPAPR_H */
+1
View File
@@ -31,6 +31,7 @@ typedef struct sPAPRCPUCore {
/*< public >*/
PowerPCCPU **threads;
int node_id;
bool pre_3_0_migration; /* older machine don't know about sPAPRCPUState */
} sPAPRCPUCore;
typedef struct sPAPRCPUCoreClass {
+1 -1
View File
@@ -17,7 +17,7 @@
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
implementation for certain IBM POWER hardware. The sources are at
https://github.com/aik/SLOF, and the image currently in qemu is
built from git tag qemu-slof-20171214.
built from git tag qemu-slof-20180621.
- sgabios (the Serial Graphics Adapter option ROM) provides a means for
legacy x86 software to communicate with an attached serial console as
BIN
View File
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More