mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
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:
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+9
-9
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user