提交 e02bbe19 编写于 作者: P Peter Maydell

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.10-20170606' into staging

ppc patch queue 2017-06-06

Accumulated patches for ppc targets and the pseries machine type.

The big thing in this batch is a start on a substantial cleanup of the
pseries hotplug mechanisms, which were pretty confusing.  For now
these shouldn't cause substantial behavioural changes, but I am hoping
these lead to clearer code and eventually to fixes for the bugs we
have in hotplug handling, particularly when hotplug and migration are
combined.

The remaining patches are mostly bugfixes.

# gpg: Signature made Tue 06 Jun 2017 03:48:50 BST
# gpg:                using RSA key 0x6C38CACA20D9B392
# 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-2.10-20170606:
  spapr: Remove some non-useful properties on DRC objects
  spapr: Eliminate spapr_drc_get_type_str()
  spapr: Move configure-connector state into DRC
  spapr: Clean up spapr_dr_connector_by_*()
  spapr: Introduce DRC subclasses
  spapr/drc: don't migrate DRC of cold-plugged CPUs and LMBs
  spapr: Allow boot from vhost-*-scsi backends
  ppc/pnv: check the return value of fdt_setprop()
  spapr_nvram: Check return value from blk_getlength()
  target/ppc: Fixup set_spr error in h_register_process_table
  target-ppc: Fix openpic timer read register offset
  spapr: Make DRC get_index and get_type methods into plain functions
  spapr: Abolish DRC set_configured method
  spapr: Abolish DRC get_fdt method
  spapr: Move DRC RTAS calls into spapr_drc.c
  migration: Mark CPU states dirty before incoming migration/loadvm
  migration: remove register_savevm()
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
......@@ -921,6 +921,15 @@ void cpu_synchronize_all_post_init(void)
}
}
void cpu_synchronize_all_pre_loadvm(void)
{
CPUState *cpu;
CPU_FOREACH(cpu) {
cpu_synchronize_pre_loadvm(cpu);
}
}
static int do_vm_stop(RunState state)
{
int ret = 0;
......
......@@ -796,27 +796,24 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
}
static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
unsigned len)
unsigned len)
{
OpenPICState *opp = opaque;
int idx;
addr += 0x10f0;
DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n",
__func__, addr, val);
__func__, (addr + 0x10f0), val);
if (addr & 0xF) {
return;
}
if (addr == 0x10f0) {
if (addr == 0) {
/* TFRR */
opp->tfrr = val;
return;
}
addr -= 0x10; /* correct for TFRR */
idx = (addr >> 6) & 0x3;
addr = addr & 0x30;
switch (addr & 0x30) {
case 0x00: /* TCCR */
......@@ -844,16 +841,17 @@ static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
uint32_t retval = -1;
int idx;
DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr + 0x10f0);
if (addr & 0xF) {
goto out;
}
idx = (addr >> 6) & 0x3;
if (addr == 0x0) {
if (addr == 0) {
/* TFRR */
retval = opp->tfrr;
goto out;
}
addr -= 0x10; /* correct for TFRR */
idx = (addr >> 6) & 0x3;
switch (addr & 0x30) {
case 0x00: /* TCCR */
retval = opp->timers[idx].tccr;
......@@ -861,10 +859,10 @@ static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
case 0x10: /* TBCR */
retval = opp->timers[idx].tbcr;
break;
case 0x20: /* TIPV */
case 0x20: /* TVPR */
retval = read_IRQreg_ivpr(opp, opp->irq_tim0 + idx);
break;
case 0x30: /* TIDE (TIDR) */
case 0x30: /* TDR */
retval = read_IRQreg_idr(opp, opp->irq_tim0 + idx);
break;
}
......
......@@ -2262,6 +2262,11 @@ static const MemoryRegionOps b1_ops = {
},
};
static SaveVMHandlers savevm_vmxnet3_msix = {
.save_state = vmxnet3_msix_save,
.load_state = vmxnet3_msix_load,
};
static uint64_t vmxnet3_device_serial_num(VMXNET3State *s)
{
uint64_t dsn_payload;
......@@ -2331,8 +2336,7 @@ static void vmxnet3_pci_realize(PCIDevice *pci_dev, Error **errp)
vmxnet3_device_serial_num(s));
}
register_savevm(dev, "vmxnet3-msix", -1, 1,
vmxnet3_msix_save, vmxnet3_msix_load, s);
register_savevm_live(dev, "vmxnet3-msix", -1, 1, &savevm_vmxnet3_msix, s);
}
static void vmxnet3_instance_init(Object *obj)
......
......@@ -144,7 +144,15 @@ static void spapr_nvram_realize(VIOsPAPRDevice *dev, Error **errp)
int ret;
if (nvram->blk) {
nvram->size = blk_getlength(nvram->blk);
int64_t len = blk_getlength(nvram->blk);
if (len < 0) {
error_setg_errno(errp, -len,
"could not get length of backing image");
return;
}
nvram->size = len;
ret = blk_set_perm(nvram->blk,
BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE,
......
......@@ -378,8 +378,9 @@ static void powernv_populate_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
_FDT(node);
g_free(name);
fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs));
fdt_setprop(fdt, node, "compatible", compatible, sizeof(compatible));
_FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
_FDT((fdt_setprop(fdt, node, "compatible", compatible,
sizeof(compatible))));
/* Mark it as reserved to avoid Linux trying to claim it */
_FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
......
......@@ -57,6 +57,7 @@
#include "hw/pci/pci.h"
#include "hw/scsi/scsi.h"
#include "hw/virtio/virtio-scsi.h"
#include "hw/virtio/vhost-scsi-common.h"
#include "exec/address-spaces.h"
#include "hw/usb.h"
......@@ -452,15 +453,13 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
int compat_smt = MIN(smp_threads, ppc_compat_max_threads(cpu));
sPAPRDRConnector *drc;
sPAPRDRConnectorClass *drck;
int drc_index;
uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ];
int i;
drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index);
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index);
if (drc) {
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
drc_index = drck->get_index(drc);
drc_index = spapr_drc_index(drc);
_FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index)));
}
......@@ -652,15 +651,13 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
if (i >= hotplug_lmb_start) {
sPAPRDRConnector *drc;
sPAPRDRConnectorClass *drck;
drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, i);
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i);
g_assert(drc);
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
dynamic_memory[0] = cpu_to_be32(addr >> 32);
dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff);
dynamic_memory[2] = cpu_to_be32(drck->get_index(drc));
dynamic_memory[2] = cpu_to_be32(spapr_drc_index(drc));
dynamic_memory[3] = cpu_to_be32(0); /* reserved */
dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL));
if (memory_region_present(get_system_memory(), addr)) {
......@@ -1913,7 +1910,7 @@ static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr)
uint64_t addr;
addr = i * lmb_size + spapr->hotplug_memory.base;
drc = spapr_dr_connector_new(OBJECT(spapr), SPAPR_DR_CONNECTOR_TYPE_LMB,
drc = spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB,
addr/lmb_size);
qemu_register_reset(spapr_drc_reset, drc);
}
......@@ -2010,8 +2007,7 @@ static void spapr_init_cpus(sPAPRMachineState *spapr)
if (mc->has_hotpluggable_cpus) {
sPAPRDRConnector *drc =
spapr_dr_connector_new(OBJECT(spapr),
SPAPR_DR_CONNECTOR_TYPE_CPU,
spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU,
(core_id / smp_threads) * smt);
qemu_register_reset(spapr_drc_reset, drc);
......@@ -2342,10 +2338,6 @@ static void ppc_spapr_init(MachineState *machine)
register_savevm_live(NULL, "spapr/htab", -1, 1,
&savevm_htab_handlers, spapr);
/* used by RTAS */
QTAILQ_INIT(&spapr->ccs_list);
qemu_register_reset(spapr_ccs_reset_hook, spapr);
qemu_register_boot_set(spapr_boot_set, spapr);
if (kvm_enabled()) {
......@@ -2386,6 +2378,7 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus,
((type *)object_dynamic_cast(OBJECT(obj), (name)))
SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE);
sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE);
VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON);
if (d) {
void *spapr = CAST(void, bus->parent, "spapr-vscsi");
......@@ -2442,6 +2435,12 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus,
return g_strdup_printf("pci@%"PRIX64, phb->buid);
}
if (vsc) {
/* Same logic as virtio above */
unsigned id = 0x1000000 | (vsc->target << 16) | vsc->lun;
return g_strdup_printf("disk@%"PRIX64, (uint64_t)id << 32);
}
return NULL;
}
......@@ -2531,8 +2530,8 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
uint64_t addr = addr_start;
for (i = 0; i < nr_lmbs; i++) {
drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
addr/SPAPR_MEMORY_BLOCK_SIZE);
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
addr / SPAPR_MEMORY_BLOCK_SIZE);
g_assert(drc);
fdt = create_device_tree(&fdt_size);
......@@ -2553,12 +2552,12 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
*/
if (dev->hotplugged) {
if (dedicated_hp_event_source) {
drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
addr_start / SPAPR_MEMORY_BLOCK_SIZE);
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
addr_start / SPAPR_MEMORY_BLOCK_SIZE);
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB,
nr_lmbs,
drck->get_index(drc));
spapr_drc_index(drc));
} else {
spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB,
nr_lmbs);
......@@ -2671,8 +2670,8 @@ static sPAPRDIMMState *spapr_recover_pending_dimm_state(sPAPRMachineState *ms,
addr = addr_start;
for (i = 0; i < nr_lmbs; i++) {
drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
addr / SPAPR_MEMORY_BLOCK_SIZE);
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
addr / SPAPR_MEMORY_BLOCK_SIZE);
g_assert(drc);
if (drc->indicator_state != SPAPR_DR_INDICATOR_STATE_INACTIVE) {
avail_lmbs++;
......@@ -2755,8 +2754,8 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
addr = addr_start;
for (i = 0; i < nr_lmbs; i++) {
drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
addr / SPAPR_MEMORY_BLOCK_SIZE);
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
addr / SPAPR_MEMORY_BLOCK_SIZE);
g_assert(drc);
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
......@@ -2764,12 +2763,11 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
addr += SPAPR_MEMORY_BLOCK_SIZE;
}
drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
addr_start / SPAPR_MEMORY_BLOCK_SIZE);
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
addr_start / SPAPR_MEMORY_BLOCK_SIZE);
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB,
nr_lmbs,
drck->get_index(drc));
nr_lmbs, spapr_drc_index(drc));
out:
error_propagate(errp, local_err);
}
......@@ -2837,7 +2835,7 @@ void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev,
return;
}
drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index * smt);
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index * smt);
g_assert(drc);
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
......@@ -2872,7 +2870,7 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
cc->core_id);
return;
}
drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index * smt);
drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index * smt);
g_assert(drc || !mc->has_hotpluggable_cpus);
......
......@@ -27,29 +27,23 @@
#define DRC_INDEX_TYPE_SHIFT 28
#define DRC_INDEX_ID_MASK ((1ULL << DRC_INDEX_TYPE_SHIFT) - 1)
static sPAPRDRConnectorTypeShift get_type_shift(sPAPRDRConnectorType type)
sPAPRDRConnectorType spapr_drc_type(sPAPRDRConnector *drc)
{
uint32_t shift = 0;
/* make sure this isn't SPAPR_DR_CONNECTOR_TYPE_ANY, or some
* other wonky value.
*/
g_assert(is_power_of_2(type));
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
while (type != (1 << shift)) {
shift++;
}
return shift;
return 1 << drck->typeshift;
}
static uint32_t get_index(sPAPRDRConnector *drc)
uint32_t spapr_drc_index(sPAPRDRConnector *drc)
{
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
/* no set format for a drc index: it only needs to be globally
* unique. this is how we encode the DRC type on bare-metal
* however, so might as well do that here
*/
return (get_type_shift(drc->type) << DRC_INDEX_TYPE_SHIFT) |
(drc->id & DRC_INDEX_ID_MASK);
return (drck->typeshift << DRC_INDEX_TYPE_SHIFT)
| (drc->id & DRC_INDEX_ID_MASK);
}
static uint32_t set_isolation_state(sPAPRDRConnector *drc,
......@@ -57,7 +51,17 @@ static uint32_t set_isolation_state(sPAPRDRConnector *drc,
{
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
trace_spapr_drc_set_isolation_state(get_index(drc), state);
trace_spapr_drc_set_isolation_state(spapr_drc_index(drc), state);
/* if the guest is configuring a device attached to this DRC, we
* should reset the configuration state at this point since it may
* no longer be reliable (guest released device and needs to start
* over, or unplug occurred so the FDT is no longer valid)
*/
if (state == SPAPR_DR_ISOLATION_STATE_ISOLATED) {
g_free(drc->ccs);
drc->ccs = NULL;
}
if (state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) {
/* cannot unisolate a non-existent resource, and, or resources
......@@ -79,7 +83,7 @@ static uint32_t set_isolation_state(sPAPRDRConnector *drc,
* If the LMB being removed doesn't belong to a DIMM device that is
* actually being unplugged, fail the isolation request here.
*/
if (drc->type == SPAPR_DR_CONNECTOR_TYPE_LMB) {
if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_LMB) {
if ((state == SPAPR_DR_ISOLATION_STATE_ISOLATED) &&
!drc->awaiting_release) {
return RTAS_OUT_HW_ERROR;
......@@ -98,11 +102,12 @@ static uint32_t set_isolation_state(sPAPRDRConnector *drc,
* PAPR+ 2.7, 13.4
*/
if (drc->awaiting_release) {
uint32_t drc_index = spapr_drc_index(drc);
if (drc->configured) {
trace_spapr_drc_set_isolation_state_finalizing(get_index(drc));
trace_spapr_drc_set_isolation_state_finalizing(drc_index);
drck->detach(drc, DEVICE(drc->dev), NULL);
} else {
trace_spapr_drc_set_isolation_state_deferring(get_index(drc));
trace_spapr_drc_set_isolation_state_deferring(drc_index);
}
}
drc->configured = false;
......@@ -114,7 +119,7 @@ static uint32_t set_isolation_state(sPAPRDRConnector *drc,
static uint32_t set_indicator_state(sPAPRDRConnector *drc,
sPAPRDRIndicatorState state)
{
trace_spapr_drc_set_indicator_state(get_index(drc), state);
trace_spapr_drc_set_indicator_state(spapr_drc_index(drc), state);
drc->indicator_state = state;
return RTAS_OUT_SUCCESS;
}
......@@ -124,7 +129,7 @@ static uint32_t set_allocation_state(sPAPRDRConnector *drc,
{
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
trace_spapr_drc_set_allocation_state(get_index(drc), state);
trace_spapr_drc_set_allocation_state(spapr_drc_index(drc), state);
if (state == SPAPR_DR_ALLOCATION_STATE_USABLE) {
/* if there's no resource/device associated with the DRC, there's
......@@ -148,11 +153,12 @@ static uint32_t set_allocation_state(sPAPRDRConnector *drc,
}
}
if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI) {
if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI) {
drc->allocation_state = state;
if (drc->awaiting_release &&
drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) {
trace_spapr_drc_set_allocation_state_finalizing(get_index(drc));
uint32_t drc_index = spapr_drc_index(drc);
trace_spapr_drc_set_allocation_state_finalizing(drc_index);
drck->detach(drc, DEVICE(drc->dev), NULL);
} else if (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) {
drc->awaiting_allocation = false;
......@@ -161,36 +167,11 @@ static uint32_t set_allocation_state(sPAPRDRConnector *drc,
return RTAS_OUT_SUCCESS;
}
static uint32_t get_type(sPAPRDRConnector *drc)
{
return drc->type;
}
static const char *get_name(sPAPRDRConnector *drc)
{
return drc->name;
}
static const void *get_fdt(sPAPRDRConnector *drc, int *fdt_start_offset)
{
if (fdt_start_offset) {
*fdt_start_offset = drc->fdt_start_offset;
}
return drc->fdt;
}
static void set_configured(sPAPRDRConnector *drc)
{
trace_spapr_drc_set_configured(get_index(drc));
if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_UNISOLATED) {
/* guest should be not configuring an isolated device */
trace_spapr_drc_set_configured_skipping(get_index(drc));
return;
}
drc->configured = true;
}
/* has the guest been notified of device attachment? */
static void set_signalled(sPAPRDRConnector *drc)
{
......@@ -207,7 +188,7 @@ static void set_signalled(sPAPRDRConnector *drc)
static uint32_t entity_sense(sPAPRDRConnector *drc, sPAPRDREntitySense *state)
{
if (drc->dev) {
if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI &&
if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI &&
drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) {
/* for logical DR, we return a state of UNUSABLE
* iff the allocation state UNUSABLE.
......@@ -225,7 +206,7 @@ static uint32_t entity_sense(sPAPRDRConnector *drc, sPAPRDREntitySense *state)
*state = SPAPR_DR_ENTITY_SENSE_PRESENT;
}
} else {
if (drc->type == SPAPR_DR_CONNECTOR_TYPE_PCI) {
if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) {
/* PCI devices, and only PCI devices, use EMPTY
* in cases where we'd otherwise use UNUSABLE
*/
......@@ -235,7 +216,7 @@ static uint32_t entity_sense(sPAPRDRConnector *drc, sPAPRDREntitySense *state)
}
}
trace_spapr_drc_entity_sense(get_index(drc), *state);
trace_spapr_drc_entity_sense(spapr_drc_index(drc), *state);
return RTAS_OUT_SUCCESS;
}
......@@ -243,17 +224,7 @@ static void prop_get_index(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
uint32_t value = (uint32_t)drck->get_index(drc);
visit_type_uint32(v, name, &value, errp);
}
static void prop_get_type(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
uint32_t value = (uint32_t)drck->get_type(drc);
uint32_t value = spapr_drc_index(drc);
visit_type_uint32(v, name, &value, errp);
}
......@@ -264,17 +235,6 @@ static char *prop_get_name(Object *obj, Error **errp)
return g_strdup(drck->get_name(drc));
}
static void prop_get_entity_sense(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
uint32_t value;
drck->entity_sense(drc, &value);
visit_type_uint32(v, name, &value, errp);
}
static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
......@@ -354,13 +314,13 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
int fdt_start_offset, bool coldplug, Error **errp)
{
trace_spapr_drc_attach(get_index(drc));
trace_spapr_drc_attach(spapr_drc_index(drc));
if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_ISOLATED) {
error_setg(errp, "an attached device is still awaiting release");
return;
}
if (drc->type == SPAPR_DR_CONNECTOR_TYPE_PCI) {
if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) {
g_assert(drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE);
}
g_assert(fdt || coldplug);
......@@ -372,7 +332,7 @@ static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
* may be accessing the device, we can easily crash the guest, so we
* we defer completion of removal in such cases to the reset() hook.
*/
if (drc->type == SPAPR_DR_CONNECTOR_TYPE_PCI) {
if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) {
drc->isolation_state = SPAPR_DR_ISOLATION_STATE_UNISOLATED;
}
drc->indicator_state = SPAPR_DR_INDICATOR_STATE_ACTIVE;
......@@ -390,10 +350,10 @@ static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
* 'physical' DR resources such as PCI where each device/resource is
* signalled individually.
*/
drc->signalled = (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI)
drc->signalled = (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI)
? true : coldplug;
if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI) {
if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI) {
drc->awaiting_allocation = true;
}
......@@ -405,7 +365,7 @@ static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
static void detach(sPAPRDRConnector *drc, DeviceState *d, Error **errp)
{
trace_spapr_drc_detach(get_index(drc));
trace_spapr_drc_detach(spapr_drc_index(drc));
/* if we've signalled device presence to the guest, or if the guest
* has gone ahead and configured the device (via manually-executed
......@@ -428,14 +388,14 @@ static void detach(sPAPRDRConnector *drc, DeviceState *d, Error **errp)
}
if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_ISOLATED) {
trace_spapr_drc_awaiting_isolated(get_index(drc));
trace_spapr_drc_awaiting_isolated(spapr_drc_index(drc));
drc->awaiting_release = true;
return;
}
if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI &&
if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI &&
drc->allocation_state != SPAPR_DR_ALLOCATION_STATE_UNUSABLE) {
trace_spapr_drc_awaiting_unusable(get_index(drc));
trace_spapr_drc_awaiting_unusable(spapr_drc_index(drc));
drc->awaiting_release = true;
return;
}
......@@ -443,15 +403,15 @@ static void detach(sPAPRDRConnector *drc, DeviceState *d, Error **errp)
if (drc->awaiting_allocation) {
if (!drc->awaiting_allocation_skippable) {
drc->awaiting_release = true;
trace_spapr_drc_awaiting_allocation(get_index(drc));
trace_spapr_drc_awaiting_allocation(spapr_drc_index(drc));
return;
}
}
drc->indicator_state = SPAPR_DR_INDICATOR_STATE_INACTIVE;
/* Calling release callbacks based on drc->type. */
switch (drc->type) {
/* Calling release callbacks based on spapr_drc_type(drc). */
switch (spapr_drc_type(drc)) {
case SPAPR_DR_CONNECTOR_TYPE_CPU:
spapr_core_release(drc->dev);
break;
......@@ -487,7 +447,11 @@ static void reset(DeviceState *d)
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
sPAPRDREntitySense state;
trace_spapr_drc_reset(drck->get_index(drc));
trace_spapr_drc_reset(spapr_drc_index(drc));
g_free(drc->ccs);
drc->ccs = NULL;
/* immediately upon reset we can safely assume DRCs whose devices
* are pending removal can be safely removed, and that they will
* subsequently be left in an ISOLATED state. move the DRC to this
......@@ -507,7 +471,7 @@ static void reset(DeviceState *d)
}
/* non-PCI devices may be awaiting a transition to UNUSABLE */
if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI &&
if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI &&
drc->awaiting_release) {
drck->set_allocation_state(drc, SPAPR_DR_ALLOCATION_STATE_UNUSABLE);
}
......@@ -536,22 +500,18 @@ static bool spapr_drc_needed(void *opaque)
* If there is dev plugged in, we need to migrate the DRC state when
* it is different from cold-plugged state
*/
switch (drc->type) {
switch (spapr_drc_type(drc)) {
case SPAPR_DR_CONNECTOR_TYPE_PCI:
rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) &&
(drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) &&
drc->configured && drc->signalled && !drc->awaiting_release);
break;
case SPAPR_DR_CONNECTOR_TYPE_CPU:
case SPAPR_DR_CONNECTOR_TYPE_LMB:
rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) &&
(drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) &&
rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) &&
(drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) &&
drc->configured && drc->signalled && !drc->awaiting_release);
break;
case SPAPR_DR_CONNECTOR_TYPE_PHB:
case SPAPR_DR_CONNECTOR_TYPE_VIO:
default:
g_assert(false);
g_assert_not_reached();
}
return rc;
}
......@@ -576,13 +536,12 @@ static const VMStateDescription vmstate_spapr_drc = {
static void realize(DeviceState *d, Error **errp)
{
sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d);
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
Object *root_container;
char link_name[256];
gchar *child_name;
Error *err = NULL;
trace_spapr_drc_realize(drck->get_index(drc));
trace_spapr_drc_realize(spapr_drc_index(drc));
/* NOTE: we do this as part of realize/unrealize due to the fact
* that the guest will communicate with the DRC via RTAS calls
* referencing the global DRC index. By unlinking the DRC
......@@ -591,9 +550,9 @@ static void realize(DeviceState *d, Error **errp)
* existing in the composition tree
*/
root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
snprintf(link_name, sizeof(link_name), "%x", drck->get_index(drc));
snprintf(link_name, sizeof(link_name), "%x", spapr_drc_index(drc));
child_name = object_get_canonical_path_component(OBJECT(drc));
trace_spapr_drc_realize_child(drck->get_index(drc), child_name);
trace_spapr_drc_realize_child(spapr_drc_index(drc), child_name);
object_property_add_alias(root_container, link_name,
drc->owner, child_name, &err);
if (err) {
......@@ -601,22 +560,21 @@ static void realize(DeviceState *d, Error **errp)
object_unref(OBJECT(drc));
}
g_free(child_name);
vmstate_register(DEVICE(drc), drck->get_index(drc), &vmstate_spapr_drc,
vmstate_register(DEVICE(drc), spapr_drc_index(drc), &vmstate_spapr_drc,
drc);
trace_spapr_drc_realize_complete(drck->get_index(drc));
trace_spapr_drc_realize_complete(spapr_drc_index(drc));
}
static void unrealize(DeviceState *d, Error **errp)
{
sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d);
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
Object *root_container;
char name[256];
Error *err = NULL;
trace_spapr_drc_unrealize(drck->get_index(drc));
trace_spapr_drc_unrealize(spapr_drc_index(drc));
root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
snprintf(name, sizeof(name), "%x", drck->get_index(drc));
snprintf(name, sizeof(name), "%x", spapr_drc_index(drc));
object_property_del(root_container, name, &err);
if (err) {
error_report_err(err);
......@@ -624,20 +582,16 @@ static void unrealize(DeviceState *d, Error **errp)
}
}
sPAPRDRConnector *spapr_dr_connector_new(Object *owner,
sPAPRDRConnectorType type,
sPAPRDRConnector *spapr_dr_connector_new(Object *owner, const char *type,
uint32_t id)
{
sPAPRDRConnector *drc =
SPAPR_DR_CONNECTOR(object_new(TYPE_SPAPR_DR_CONNECTOR));
sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(object_new(type));
char *prop_name;
g_assert(type);
drc->type = type;
drc->id = id;
drc->owner = owner;
prop_name = g_strdup_printf("dr-connector[%"PRIu32"]", get_index(drc));
prop_name = g_strdup_printf("dr-connector[%"PRIu32"]",
spapr_drc_index(drc));
object_property_add_child(owner, prop_name, OBJECT(drc), NULL);
object_property_set_bool(OBJECT(drc), true, "realized", NULL);
g_free(prop_name);
......@@ -663,7 +617,7 @@ sPAPRDRConnector *spapr_dr_connector_new(Object *owner,
* DRC names as documented by PAPR+ v2.7, 13.5.2.4
* location codes as documented by PAPR+ v2.7, 12.3.1.5
*/
switch (drc->type) {
switch (spapr_drc_type(drc)) {
case SPAPR_DR_CONNECTOR_TYPE_CPU:
drc->name = g_strdup_printf("CPU %d", id);
break;
......@@ -682,7 +636,7 @@ sPAPRDRConnector *spapr_dr_connector_new(Object *owner,
}
/* PCI slot always start in a USABLE state, and stay there */
if (drc->type == SPAPR_DR_CONNECTOR_TYPE_PCI) {
if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) {
drc->allocation_state = SPAPR_DR_ALLOCATION_STATE_USABLE;
}
......@@ -693,20 +647,10 @@ static void spapr_dr_connector_instance_init(Object *obj)
{
sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
object_property_add_uint32_ptr(obj, "isolation-state",
&drc->isolation_state, NULL);
object_property_add_uint32_ptr(obj, "indicator-state",
&drc->indicator_state, NULL);
object_property_add_uint32_ptr(obj, "allocation-state",
&drc->allocation_state, NULL);
object_property_add_uint32_ptr(obj, "id", &drc->id, NULL);
object_property_add(obj, "index", "uint32", prop_get_index,
NULL, NULL, NULL, NULL);
object_property_add(obj, "connector_type", "uint32", prop_get_type,
NULL, NULL, NULL, NULL);
object_property_add_str(obj, "name", prop_get_name, NULL, NULL);
object_property_add(obj, "entity-sense", "uint32", prop_get_entity_sense,
NULL, NULL, NULL, NULL);
object_property_add(obj, "fdt", "struct", prop_get_fdt,
NULL, NULL, NULL, NULL);
}
......@@ -722,11 +666,7 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
drck->set_isolation_state = set_isolation_state;
drck->set_indicator_state = set_indicator_state;
drck->set_allocation_state = set_allocation_state;
drck->get_index = get_index;
drck->get_type = get_type;
drck->get_name = get_name;
drck->get_fdt = get_fdt;
drck->set_configured = set_configured;
drck->entity_sense = entity_sense;
drck->attach = attach;
drck->detach = detach;
......@@ -738,6 +678,30 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
dk->user_creatable = false;
}
static void spapr_drc_cpu_class_init(ObjectClass *k, void *data)
{
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU;
drck->typename = "CPU";
}
static void spapr_drc_pci_class_init(ObjectClass *k, void *data)
{
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI;
drck->typename = "28";
}
static void spapr_drc_lmb_class_init(ObjectClass *k, void *data)
{
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB;
drck->typename = "MEM";
}
static const TypeInfo spapr_dr_connector_info = {
.name = TYPE_SPAPR_DR_CONNECTOR,
.parent = TYPE_DEVICE,
......@@ -745,18 +709,47 @@ static const TypeInfo spapr_dr_connector_info = {
.instance_init = spapr_dr_connector_instance_init,
.class_size = sizeof(sPAPRDRConnectorClass),
.class_init = spapr_dr_connector_class_init,
.abstract = true,
};
static void spapr_drc_register_types(void)
{
type_register_static(&spapr_dr_connector_info);
}
static const TypeInfo spapr_drc_physical_info = {
.name = TYPE_SPAPR_DRC_PHYSICAL,
.parent = TYPE_SPAPR_DR_CONNECTOR,
.instance_size = sizeof(sPAPRDRConnector),
.abstract = true,
};
type_init(spapr_drc_register_types)
static const TypeInfo spapr_drc_logical_info = {
.name = TYPE_SPAPR_DRC_LOGICAL,
.parent = TYPE_SPAPR_DR_CONNECTOR,
.instance_size = sizeof(sPAPRDRConnector),
.abstract = true,
};
static const TypeInfo spapr_drc_cpu_info = {
.name = TYPE_SPAPR_DRC_CPU,
.parent = TYPE_SPAPR_DRC_LOGICAL,
.instance_size = sizeof(sPAPRDRConnector),
.class_init = spapr_drc_cpu_class_init,
};
static const TypeInfo spapr_drc_pci_info = {
.name = TYPE_SPAPR_DRC_PCI,
.parent = TYPE_SPAPR_DRC_PHYSICAL,
.instance_size = sizeof(sPAPRDRConnector),
.class_init = spapr_drc_pci_class_init,
};
static const TypeInfo spapr_drc_lmb_info = {
.name = TYPE_SPAPR_DRC_LMB,
.parent = TYPE_SPAPR_DRC_LOGICAL,
.instance_size = sizeof(sPAPRDRConnector),
.class_init = spapr_drc_lmb_class_init,
};
/* helper functions for external users */
sPAPRDRConnector *spapr_dr_connector_by_index(uint32_t index)
sPAPRDRConnector *spapr_drc_by_index(uint32_t index)
{
Object *obj;
char name[256];
......@@ -767,37 +760,13 @@ sPAPRDRConnector *spapr_dr_connector_by_index(uint32_t index)
return !obj ? NULL : SPAPR_DR_CONNECTOR(obj);
}
sPAPRDRConnector *spapr_dr_connector_by_id(sPAPRDRConnectorType type,
uint32_t id)
sPAPRDRConnector *spapr_drc_by_id(const char *type, uint32_t id)
{
return spapr_dr_connector_by_index(
(get_type_shift(type) << DRC_INDEX_TYPE_SHIFT) |
(id & DRC_INDEX_ID_MASK));
}
/* generate a string the describes the DRC to encode into the
* device tree.
*
* as documented by PAPR+ v2.7, 13.5.2.6 and C.6.1
*/
static const char *spapr_drc_get_type_str(sPAPRDRConnectorType type)
{
switch (type) {
case SPAPR_DR_CONNECTOR_TYPE_CPU:
return "CPU";
case SPAPR_DR_CONNECTOR_TYPE_PHB:
return "PHB";
case SPAPR_DR_CONNECTOR_TYPE_VIO:
return "SLOT";
case SPAPR_DR_CONNECTOR_TYPE_PCI:
return "28";
case SPAPR_DR_CONNECTOR_TYPE_LMB:
return "MEM";
default:
g_assert(false);
}
sPAPRDRConnectorClass *drck
= SPAPR_DR_CONNECTOR_CLASS(object_class_by_name(type));
return NULL;
return spapr_drc_by_index(drck->typeshift << DRC_INDEX_TYPE_SHIFT
| (id & DRC_INDEX_ID_MASK));
}
/**
......@@ -862,14 +831,14 @@ int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
continue;
}
if ((drc->type & drc_type_mask) == 0) {
if ((spapr_drc_type(drc) & drc_type_mask) == 0) {
continue;
}
drc_count++;
/* ibm,drc-indexes */
drc_index = cpu_to_be32(drck->get_index(drc));
drc_index = cpu_to_be32(spapr_drc_index(drc));
g_array_append_val(drc_indexes, drc_index);
/* ibm,drc-power-domains */
......@@ -881,8 +850,7 @@ int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
drc_names = g_string_insert_len(drc_names, -1, "\0", 1);
/* ibm,drc-types */
drc_types = g_string_append(drc_types,
spapr_drc_get_type_str(drc->type));
drc_types = g_string_append(drc_types, drck->typename);
drc_types = g_string_insert_len(drc_types, -1, "\0", 1);
}
......@@ -932,3 +900,276 @@ out:
return ret;
}
/*
* RTAS calls
*/
static bool sensor_type_is_dr(uint32_t sensor_type)
{
switch (sensor_type) {
case RTAS_SENSOR_TYPE_ISOLATION_STATE:
case RTAS_SENSOR_TYPE_DR:
case RTAS_SENSOR_TYPE_ALLOCATION_STATE:
return true;
}
return false;
}
static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr,
uint32_t token, uint32_t nargs,
target_ulong args, uint32_t nret,
target_ulong rets)
{
uint32_t sensor_type;
uint32_t sensor_index;
uint32_t sensor_state;
uint32_t ret = RTAS_OUT_SUCCESS;
sPAPRDRConnector *drc;
sPAPRDRConnectorClass *drck;
if (nargs != 3 || nret != 1) {
ret = RTAS_OUT_PARAM_ERROR;
goto out;
}
sensor_type = rtas_ld(args, 0);
sensor_index = rtas_ld(args, 1);
sensor_state = rtas_ld(args, 2);
if (!sensor_type_is_dr(sensor_type)) {
goto out_unimplemented;
}
/* if this is a DR sensor we can assume sensor_index == drc_index */
drc = spapr_drc_by_index(sensor_index);
if (!drc) {
trace_spapr_rtas_set_indicator_invalid(sensor_index);
ret = RTAS_OUT_PARAM_ERROR;
goto out;
}
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
switch (sensor_type) {
case RTAS_SENSOR_TYPE_ISOLATION_STATE:
ret = drck->set_isolation_state(drc, sensor_state);
break;
case RTAS_SENSOR_TYPE_DR:
ret = drck->set_indicator_state(drc, sensor_state);
break;
case RTAS_SENSOR_TYPE_ALLOCATION_STATE:
ret = drck->set_allocation_state(drc, sensor_state);
break;
default:
goto out_unimplemented;
}
out:
rtas_st(rets, 0, ret);
return;
out_unimplemented:
/* currently only DR-related sensors are implemented */
trace_spapr_rtas_set_indicator_not_supported(sensor_index, sensor_type);
rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
}
static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr,
uint32_t token, uint32_t nargs,
target_ulong args, uint32_t nret,
target_ulong rets)
{
uint32_t sensor_type;
uint32_t sensor_index;
uint32_t sensor_state = 0;
sPAPRDRConnector *drc;
sPAPRDRConnectorClass *drck;
uint32_t ret = RTAS_OUT_SUCCESS;
if (nargs != 2 || nret != 2) {
ret = RTAS_OUT_PARAM_ERROR;
goto out;
}
sensor_type = rtas_ld(args, 0);
sensor_index = rtas_ld(args, 1);
if (sensor_type != RTAS_SENSOR_TYPE_ENTITY_SENSE) {
/* currently only DR-related sensors are implemented */
trace_spapr_rtas_get_sensor_state_not_supported(sensor_index,
sensor_type);
ret = RTAS_OUT_NOT_SUPPORTED;
goto out;
}
drc = spapr_drc_by_index(sensor_index);
if (!drc) {
trace_spapr_rtas_get_sensor_state_invalid(sensor_index);
ret = RTAS_OUT_PARAM_ERROR;
goto out;
}
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
ret = drck->entity_sense(drc, &sensor_state);
out:
rtas_st(rets, 0, ret);
rtas_st(rets, 1, sensor_state);
}
/* configure-connector work area offsets, int32_t units for field
* indexes, bytes for field offset/len values.
*
* as documented by PAPR+ v2.7, 13.5.3.5
*/
#define CC_IDX_NODE_NAME_OFFSET 2
#define CC_IDX_PROP_NAME_OFFSET 2
#define CC_IDX_PROP_LEN 3
#define CC_IDX_PROP_DATA_OFFSET 4
#define CC_VAL_DATA_OFFSET ((CC_IDX_PROP_DATA_OFFSET + 1) * 4)
#define CC_WA_LEN 4096
static void configure_connector_st(target_ulong addr, target_ulong offset,
const void *buf, size_t len)
{
cpu_physical_memory_write(ppc64_phys_to_real(addr + offset),
buf, MIN(len, CC_WA_LEN - offset));
}
static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
sPAPRMachineState *spapr,
uint32_t token, uint32_t nargs,
target_ulong args, uint32_t nret,
target_ulong rets)
{
uint64_t wa_addr;
uint64_t wa_offset;
uint32_t drc_index;
sPAPRDRConnector *drc;
sPAPRConfigureConnectorState *ccs;
sPAPRDRCCResponse resp = SPAPR_DR_CC_RESPONSE_CONTINUE;
int rc;
if (nargs != 2 || nret != 1) {
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
wa_addr = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 0);
drc_index = rtas_ld(wa_addr, 0);
drc = spapr_drc_by_index(drc_index);
if (!drc) {
trace_spapr_rtas_ibm_configure_connector_invalid(drc_index);
rc = RTAS_OUT_PARAM_ERROR;
goto out;
}
if (!drc->fdt) {
trace_spapr_rtas_ibm_configure_connector_missing_fdt(drc_index);
rc = SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE;
goto out;
}
ccs = drc->ccs;
if (!ccs) {
ccs = g_new0(sPAPRConfigureConnectorState, 1);
ccs->fdt_offset = drc->fdt_start_offset;
drc->ccs = ccs;
}
do {
uint32_t tag;
const char *name;
const struct fdt_property *prop;
int fdt_offset_next, prop_len;
tag = fdt_next_tag(drc->fdt, ccs->fdt_offset, &fdt_offset_next);
switch (tag) {
case FDT_BEGIN_NODE:
ccs->fdt_depth++;
name = fdt_get_name(drc->fdt, ccs->fdt_offset, NULL);
/* provide the name of the next OF node */
wa_offset = CC_VAL_DATA_OFFSET;
rtas_st(wa_addr, CC_IDX_NODE_NAME_OFFSET, wa_offset);
configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1);
resp = SPAPR_DR_CC_RESPONSE_NEXT_CHILD;
break;
case FDT_END_NODE:
ccs->fdt_depth--;
if (ccs->fdt_depth == 0) {
sPAPRDRIsolationState state = drc->isolation_state;
uint32_t drc_index = spapr_drc_index(drc);
/* done sending the device tree, don't need to track
* the state anymore
*/
trace_spapr_drc_set_configured(drc_index);
if (state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) {
drc->configured = true;
} else {
/* guest should be not configuring an isolated device */
trace_spapr_drc_set_configured_skipping(drc_index);
}
g_free(ccs);
drc->ccs = NULL;
ccs = NULL;
resp = SPAPR_DR_CC_RESPONSE_SUCCESS;
} else {
resp = SPAPR_DR_CC_RESPONSE_PREV_PARENT;
}
break;
case FDT_PROP:
prop = fdt_get_property_by_offset(drc->fdt, ccs->fdt_offset,
&prop_len);
name = fdt_string(drc->fdt, fdt32_to_cpu(prop->nameoff));
/* provide the name of the next OF property */
wa_offset = CC_VAL_DATA_OFFSET;
rtas_st(wa_addr, CC_IDX_PROP_NAME_OFFSET, wa_offset);
configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1);
/* provide the length and value of the OF property. data gets
* placed immediately after NULL terminator of the OF property's
* name string
*/
wa_offset += strlen(name) + 1,
rtas_st(wa_addr, CC_IDX_PROP_LEN, prop_len);
rtas_st(wa_addr, CC_IDX_PROP_DATA_OFFSET, wa_offset);
configure_connector_st(wa_addr, wa_offset, prop->data, prop_len);
resp = SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY;
break;
case FDT_END:
resp = SPAPR_DR_CC_RESPONSE_ERROR;
default:
/* keep seeking for an actionable tag */
break;
}
if (ccs) {
ccs->fdt_offset = fdt_offset_next;
}
} while (resp == SPAPR_DR_CC_RESPONSE_CONTINUE);
rc = resp;
out:
rtas_st(rets, 0, rc);
}
static void spapr_drc_register_types(void)
{
type_register_static(&spapr_dr_connector_info);
type_register_static(&spapr_drc_physical_info);
type_register_static(&spapr_drc_logical_info);
type_register_static(&spapr_drc_cpu_info);
type_register_static(&spapr_drc_pci_info);
type_register_static(&spapr_drc_lmb_info);
spapr_rtas_register(RTAS_SET_INDICATOR, "set-indicator",
rtas_set_indicator);
spapr_rtas_register(RTAS_GET_SENSOR_STATE, "get-sensor-state",
rtas_get_sensor_state);
spapr_rtas_register(RTAS_IBM_CONFIGURE_CONNECTOR, "ibm,configure-connector",
rtas_ibm_configure_connector);
}
type_init(spapr_drc_register_types)
......@@ -477,7 +477,7 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
static void spapr_hotplug_set_signalled(uint32_t drc_index)
{
sPAPRDRConnector *drc = spapr_dr_connector_by_index(drc_index);
sPAPRDRConnector *drc = spapr_drc_by_index(drc_index);
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
drck->set_signalled(drc);
}
......@@ -570,22 +570,20 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
void spapr_hotplug_req_add_by_index(sPAPRDRConnector *drc)
{
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
sPAPRDRConnectorType drc_type = drck->get_type(drc);
sPAPRDRConnectorType drc_type = spapr_drc_type(drc);
union drc_identifier drc_id;
drc_id.index = drck->get_index(drc);
drc_id.index = spapr_drc_index(drc);
spapr_hotplug_req_event(RTAS_LOG_V6_HP_ID_DRC_INDEX,
RTAS_LOG_V6_HP_ACTION_ADD, drc_type, &drc_id);
}
void spapr_hotplug_req_remove_by_index(sPAPRDRConnector *drc)
{
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
sPAPRDRConnectorType drc_type = drck->get_type(drc);
sPAPRDRConnectorType drc_type = spapr_drc_type(drc);
union drc_identifier drc_id;
drc_id.index = drck->get_index(drc);
drc_id.index = spapr_drc_index(drc);
spapr_hotplug_req_event(RTAS_LOG_V6_HP_ID_DRC_INDEX,
RTAS_LOG_V6_HP_ACTION_REMOVE, drc_type, &drc_id);
}
......
......@@ -992,9 +992,10 @@ static target_ulong h_register_process_table(PowerPCCPU *cpu,
/* Update the UPRT and GTSE bits in the LPCR for all cpus */
CPU_FOREACH(cs) {
set_spr(cs, SPR_LPCR, LPCR_UPRT | LPCR_GTSE,
set_spr(cs, SPR_LPCR,
((flags & (FLAG_RADIX | FLAG_HASH_PROC_TBL)) ? LPCR_UPRT : 0) |
((flags & FLAG_GTSE) ? LPCR_GTSE : 0));
((flags & FLAG_GTSE) ? LPCR_GTSE : 0),
LPCR_UPRT | LPCR_GTSE);
}
if (kvm_enabled()) {
......
......@@ -1400,10 +1400,8 @@ static sPAPRDRConnector *spapr_phb_get_pci_func_drc(sPAPRPHBState *phb,
uint32_t busnr,
int32_t devfn)
{
return spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_PCI,
(phb->index << 16) |
(busnr << 8) |
devfn);
return spapr_drc_by_id(TYPE_SPAPR_DRC_PCI,
(phb->index << 16) | (busnr << 8) | devfn);
}
static sPAPRDRConnector *spapr_phb_get_pci_drc(sPAPRPHBState *phb,
......@@ -1417,14 +1415,12 @@ static uint32_t spapr_phb_get_pci_drc_index(sPAPRPHBState *phb,
PCIDevice *pdev)
{
sPAPRDRConnector *drc = spapr_phb_get_pci_drc(phb, pdev);
sPAPRDRConnectorClass *drck;
if (!drc) {
return 0;
}
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
return drck->get_index(drc);
return spapr_drc_index(drc);
}
static void spapr_phb_hot_plug_child(HotplugHandler *plug_handler,
......@@ -1763,8 +1759,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
/* allocate connectors for child PCI devices */
if (sphb->dr_enabled) {
for (i = 0; i < PCI_SLOT_MAX * 8; i++) {
spapr_dr_connector_new(OBJECT(phb),
SPAPR_DR_CONNECTOR_TYPE_PCI,
spapr_dr_connector_new(OBJECT(phb), TYPE_SPAPR_DRC_PCI,
(sphb->index << 16) | i);
}
}
......
......@@ -47,44 +47,6 @@
#include "trace.h"
#include "hw/ppc/fdt.h"
static sPAPRConfigureConnectorState *spapr_ccs_find(sPAPRMachineState *spapr,
uint32_t drc_index)
{
sPAPRConfigureConnectorState *ccs = NULL;
QTAILQ_FOREACH(ccs, &spapr->ccs_list, next) {
if (ccs->drc_index == drc_index) {
break;
}
}
return ccs;
}
static void spapr_ccs_add(sPAPRMachineState *spapr,
sPAPRConfigureConnectorState *ccs)
{
g_assert(!spapr_ccs_find(spapr, ccs->drc_index));
QTAILQ_INSERT_HEAD(&spapr->ccs_list, ccs, next);
}
static void spapr_ccs_remove(sPAPRMachineState *spapr,
sPAPRConfigureConnectorState *ccs)
{
QTAILQ_REMOVE(&spapr->ccs_list, ccs, next);
g_free(ccs);
}
void spapr_ccs_reset_hook(void *opaque)
{
sPAPRMachineState *spapr = opaque;
sPAPRConfigureConnectorState *ccs, *ccs_tmp;
QTAILQ_FOREACH_SAFE(ccs, &spapr->ccs_list, next, ccs_tmp) {
spapr_ccs_remove(spapr, ccs);
}
}
static void rtas_display_character(PowerPCCPU *cpu, sPAPRMachineState *spapr,
uint32_t token, uint32_t nargs,
target_ulong args,
......@@ -389,266 +351,6 @@ static void rtas_get_power_level(PowerPCCPU *cpu, sPAPRMachineState *spapr,
rtas_st(rets, 1, 100);
}
static bool sensor_type_is_dr(uint32_t sensor_type)
{
switch (sensor_type) {
case RTAS_SENSOR_TYPE_ISOLATION_STATE:
case RTAS_SENSOR_TYPE_DR:
case RTAS_SENSOR_TYPE_ALLOCATION_STATE:
return true;
}
return false;
}
static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr,
uint32_t token, uint32_t nargs,
target_ulong args, uint32_t nret,
target_ulong rets)
{
uint32_t sensor_type;
uint32_t sensor_index;
uint32_t sensor_state;
uint32_t ret = RTAS_OUT_SUCCESS;
sPAPRDRConnector *drc;
sPAPRDRConnectorClass *drck;
if (nargs != 3 || nret != 1) {
ret = RTAS_OUT_PARAM_ERROR;
goto out;
}
sensor_type = rtas_ld(args, 0);
sensor_index = rtas_ld(args, 1);
sensor_state = rtas_ld(args, 2);
if (!sensor_type_is_dr(sensor_type)) {
goto out_unimplemented;
}
/* if this is a DR sensor we can assume sensor_index == drc_index */
drc = spapr_dr_connector_by_index(sensor_index);
if (!drc) {
trace_spapr_rtas_set_indicator_invalid(sensor_index);
ret = RTAS_OUT_PARAM_ERROR;
goto out;
}
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
switch (sensor_type) {
case RTAS_SENSOR_TYPE_ISOLATION_STATE:
/* if the guest is configuring a device attached to this
* DRC, we should reset the configuration state at this
* point since it may no longer be reliable (guest released
* device and needs to start over, or unplug occurred so
* the FDT is no longer valid)
*/
if (sensor_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) {
sPAPRConfigureConnectorState *ccs = spapr_ccs_find(spapr,
sensor_index);
if (ccs) {
spapr_ccs_remove(spapr, ccs);
}
}
ret = drck->set_isolation_state(drc, sensor_state);
break;
case RTAS_SENSOR_TYPE_DR:
ret = drck->set_indicator_state(drc, sensor_state);
break;
case RTAS_SENSOR_TYPE_ALLOCATION_STATE:
ret = drck->set_allocation_state(drc, sensor_state);
break;
default:
goto out_unimplemented;
}
out:
rtas_st(rets, 0, ret);
return;
out_unimplemented:
/* currently only DR-related sensors are implemented */
trace_spapr_rtas_set_indicator_not_supported(sensor_index, sensor_type);
rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
}
static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr,
uint32_t token, uint32_t nargs,
target_ulong args, uint32_t nret,
target_ulong rets)
{
uint32_t sensor_type;
uint32_t sensor_index;
uint32_t sensor_state = 0;
sPAPRDRConnector *drc;
sPAPRDRConnectorClass *drck;
uint32_t ret = RTAS_OUT_SUCCESS;
if (nargs != 2 || nret != 2) {
ret = RTAS_OUT_PARAM_ERROR;
goto out;
}
sensor_type = rtas_ld(args, 0);
sensor_index = rtas_ld(args, 1);
if (sensor_type != RTAS_SENSOR_TYPE_ENTITY_SENSE) {
/* currently only DR-related sensors are implemented */
trace_spapr_rtas_get_sensor_state_not_supported(sensor_index,
sensor_type);
ret = RTAS_OUT_NOT_SUPPORTED;
goto out;
}
drc = spapr_dr_connector_by_index(sensor_index);
if (!drc) {
trace_spapr_rtas_get_sensor_state_invalid(sensor_index);
ret = RTAS_OUT_PARAM_ERROR;
goto out;
}
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
ret = drck->entity_sense(drc, &sensor_state);
out:
rtas_st(rets, 0, ret);
rtas_st(rets, 1, sensor_state);
}
/* configure-connector work area offsets, int32_t units for field
* indexes, bytes for field offset/len values.
*
* as documented by PAPR+ v2.7, 13.5.3.5
*/
#define CC_IDX_NODE_NAME_OFFSET 2
#define CC_IDX_PROP_NAME_OFFSET 2
#define CC_IDX_PROP_LEN 3
#define CC_IDX_PROP_DATA_OFFSET 4
#define CC_VAL_DATA_OFFSET ((CC_IDX_PROP_DATA_OFFSET + 1) * 4)
#define CC_WA_LEN 4096
static void configure_connector_st(target_ulong addr, target_ulong offset,
const void *buf, size_t len)
{
cpu_physical_memory_write(ppc64_phys_to_real(addr + offset),
buf, MIN(len, CC_WA_LEN - offset));
}
static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
sPAPRMachineState *spapr,
uint32_t token, uint32_t nargs,
target_ulong args, uint32_t nret,
target_ulong rets)
{
uint64_t wa_addr;
uint64_t wa_offset;
uint32_t drc_index;
sPAPRDRConnector *drc;
sPAPRDRConnectorClass *drck;
sPAPRConfigureConnectorState *ccs;
sPAPRDRCCResponse resp = SPAPR_DR_CC_RESPONSE_CONTINUE;
int rc;
const void *fdt;
if (nargs != 2 || nret != 1) {
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
wa_addr = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 0);
drc_index = rtas_ld(wa_addr, 0);
drc = spapr_dr_connector_by_index(drc_index);
if (!drc) {
trace_spapr_rtas_ibm_configure_connector_invalid(drc_index);
rc = RTAS_OUT_PARAM_ERROR;
goto out;
}
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
fdt = drck->get_fdt(drc, NULL);
if (!fdt) {
trace_spapr_rtas_ibm_configure_connector_missing_fdt(drc_index);
rc = SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE;
goto out;
}
ccs = spapr_ccs_find(spapr, drc_index);
if (!ccs) {
ccs = g_new0(sPAPRConfigureConnectorState, 1);
(void)drck->get_fdt(drc, &ccs->fdt_offset);
ccs->drc_index = drc_index;
spapr_ccs_add(spapr, ccs);
}
do {
uint32_t tag;
const char *name;
const struct fdt_property *prop;
int fdt_offset_next, prop_len;
tag = fdt_next_tag(fdt, ccs->fdt_offset, &fdt_offset_next);
switch (tag) {
case FDT_BEGIN_NODE:
ccs->fdt_depth++;
name = fdt_get_name(fdt, ccs->fdt_offset, NULL);
/* provide the name of the next OF node */
wa_offset = CC_VAL_DATA_OFFSET;
rtas_st(wa_addr, CC_IDX_NODE_NAME_OFFSET, wa_offset);
configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1);
resp = SPAPR_DR_CC_RESPONSE_NEXT_CHILD;
break;
case FDT_END_NODE:
ccs->fdt_depth--;
if (ccs->fdt_depth == 0) {
/* done sending the device tree, don't need to track
* the state anymore
*/
drck->set_configured(drc);
spapr_ccs_remove(spapr, ccs);
ccs = NULL;
resp = SPAPR_DR_CC_RESPONSE_SUCCESS;
} else {
resp = SPAPR_DR_CC_RESPONSE_PREV_PARENT;
}
break;
case FDT_PROP:
prop = fdt_get_property_by_offset(fdt, ccs->fdt_offset,
&prop_len);
name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
/* provide the name of the next OF property */
wa_offset = CC_VAL_DATA_OFFSET;
rtas_st(wa_addr, CC_IDX_PROP_NAME_OFFSET, wa_offset);
configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1);
/* provide the length and value of the OF property. data gets
* placed immediately after NULL terminator of the OF property's
* name string
*/
wa_offset += strlen(name) + 1,
rtas_st(wa_addr, CC_IDX_PROP_LEN, prop_len);
rtas_st(wa_addr, CC_IDX_PROP_DATA_OFFSET, wa_offset);
configure_connector_st(wa_addr, wa_offset, prop->data, prop_len);
resp = SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY;
break;
case FDT_END:
resp = SPAPR_DR_CC_RESPONSE_ERROR;
default:
/* keep seeking for an actionable tag */
break;
}
if (ccs) {
ccs->fdt_offset = fdt_offset_next;
}
} while (resp == SPAPR_DR_CC_RESPONSE_CONTINUE);
rc = resp;
out:
rtas_st(rets, 0, rc);
}
static struct rtas_call {
const char *name;
spapr_rtas_fn fn;
......@@ -790,12 +492,6 @@ static void core_rtas_register_types(void)
rtas_set_power_level);
spapr_rtas_register(RTAS_GET_POWER_LEVEL, "get-power-level",
rtas_get_power_level);
spapr_rtas_register(RTAS_SET_INDICATOR, "set-indicator",
rtas_set_indicator);
spapr_rtas_register(RTAS_GET_SENSOR_STATE, "get-sensor-state",
rtas_get_sensor_state);
spapr_rtas_register(RTAS_IBM_CONFIGURE_CONNECTOR, "ibm,configure-connector",
rtas_ibm_configure_connector);
}
type_init(core_rtas_register_types)
......@@ -362,6 +362,11 @@ static inline bool s390_skeys_get_migration_enabled(Object *obj, Error **errp)
return ss->migration_enabled;
}
static SaveVMHandlers savevm_s390_storage_keys = {
.save_state = s390_storage_keys_save,
.load_state = s390_storage_keys_load,
};
static inline void s390_skeys_set_migration_enabled(Object *obj, bool value,
Error **errp)
{
......@@ -375,8 +380,8 @@ static inline void s390_skeys_set_migration_enabled(Object *obj, bool value,
ss->migration_enabled = value;
if (ss->migration_enabled) {
register_savevm(NULL, TYPE_S390_SKEYS, 0, 1, s390_storage_keys_save,
s390_storage_keys_load, ss);
register_savevm_live(NULL, TYPE_S390_SKEYS, 0, 1,
&savevm_s390_storage_keys, ss);
} else {
unregister_savevm(DEVICE(ss), TYPE_S390_SKEYS, ss);
}
......
......@@ -104,6 +104,11 @@ void s390_memory_init(ram_addr_t mem_size)
s390_skeys_init();
}
static SaveVMHandlers savevm_gtod = {
.save_state = gtod_save,
.load_state = gtod_load,
};
static void ccw_init(MachineState *machine)
{
int ret;
......@@ -151,8 +156,7 @@ static void ccw_init(MachineState *machine)
s390_create_virtio_net(BUS(css_bus), "virtio-net-ccw");
/* Register savevm handler for guest TOD clock */
register_savevm(NULL, "todclock", 0, 1,
gtod_save, gtod_load, kvm_state);
register_savevm_live(NULL, "todclock", 0, 1, &savevm_gtod, kvm_state);
}
static void s390_cpu_plug(HotplugHandler *hotplug_dev,
......
......@@ -11,7 +11,6 @@
struct VIOsPAPRBus;
struct sPAPRPHBState;
struct sPAPRNVRAM;
typedef struct sPAPRConfigureConnectorState sPAPRConfigureConnectorState;
typedef struct sPAPREventLogEntry sPAPREventLogEntry;
typedef struct sPAPREventSource sPAPREventSource;
......@@ -102,9 +101,6 @@ struct sPAPRMachineState {
bool htab_first_pass;
int htab_fd;
/* RTAS state */
QTAILQ_HEAD(, sPAPRConfigureConnectorState) ccs_list;
/* Pending DIMM unplug cache. It is populated when a LMB
* unplug starts. It can be regenerated if a migration
* occurs during the unplug process. */
......@@ -646,16 +642,6 @@ void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset,
void spapr_core_release(DeviceState *dev);
void spapr_lmb_release(DeviceState *dev);
/* rtas-configure-connector state */
struct sPAPRConfigureConnectorState {
uint32_t drc_index;
int fdt_offset;
int fdt_depth;
QTAILQ_ENTRY(sPAPRConfigureConnectorState) next;
};
void spapr_ccs_reset_hook(void *opaque);
void spapr_rtc_read(sPAPRRTCState *rtc, struct tm *tm, uint32_t *ns);
int spapr_rtc_import_offset(sPAPRRTCState *rtc, int64_t legacy_offset);
......
......@@ -26,6 +26,48 @@
#define SPAPR_DR_CONNECTOR(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
TYPE_SPAPR_DR_CONNECTOR)
#define TYPE_SPAPR_DRC_PHYSICAL "spapr-drc-physical"
#define SPAPR_DRC_PHYSICAL_GET_CLASS(obj) \
OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DRC_PHYSICAL)
#define SPAPR_DRC_PHYSICAL_CLASS(klass) \
OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, \
TYPE_SPAPR_DRC_PHYSICAL)
#define SPAPR_DRC_PHYSICAL(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
TYPE_SPAPR_DRC_PHYSICAL)
#define TYPE_SPAPR_DRC_LOGICAL "spapr-drc-logical"
#define SPAPR_DRC_LOGICAL_GET_CLASS(obj) \
OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DRC_LOGICAL)
#define SPAPR_DRC_LOGICAL_CLASS(klass) \
OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, \
TYPE_SPAPR_DRC_LOGICAL)
#define SPAPR_DRC_LOGICAL(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
TYPE_SPAPR_DRC_LOGICAL)
#define TYPE_SPAPR_DRC_CPU "spapr-drc-cpu"
#define SPAPR_DRC_CPU_GET_CLASS(obj) \
OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DRC_CPU)
#define SPAPR_DRC_CPU_CLASS(klass) \
OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, TYPE_SPAPR_DRC_CPU)
#define SPAPR_DRC_CPU(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
TYPE_SPAPR_DRC_CPU)
#define TYPE_SPAPR_DRC_PCI "spapr-drc-pci"
#define SPAPR_DRC_PCI_GET_CLASS(obj) \
OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DRC_PCI)
#define SPAPR_DRC_PCI_CLASS(klass) \
OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, TYPE_SPAPR_DRC_PCI)
#define SPAPR_DRC_PCI(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
TYPE_SPAPR_DRC_PCI)
#define TYPE_SPAPR_DRC_LMB "spapr-drc-lmb"
#define SPAPR_DRC_LMB_GET_CLASS(obj) \
OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DRC_LMB)
#define SPAPR_DRC_LMB_CLASS(klass) \
OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, TYPE_SPAPR_DRC_LMB)
#define SPAPR_DRC_LMB(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \
TYPE_SPAPR_DRC_LMB)
/*
* Various hotplug types managed by sPAPRDRConnector
*
......@@ -130,11 +172,16 @@ typedef enum {
SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE = -9003,
} sPAPRDRCCResponse;
/* rtas-configure-connector state */
typedef struct sPAPRConfigureConnectorState {
int fdt_offset;
int fdt_depth;
} sPAPRConfigureConnectorState;
typedef struct sPAPRDRConnector {
/*< private >*/
DeviceState parent;
sPAPRDRConnectorType type;
uint32_t id;
Object *owner;
const char *name;
......@@ -148,6 +195,7 @@ typedef struct sPAPRDRConnector {
void *fdt;
int fdt_start_offset;
bool configured;
sPAPRConfigureConnectorState *ccs;
bool awaiting_release;
bool signalled;
......@@ -163,6 +211,8 @@ typedef struct sPAPRDRConnectorClass {
DeviceClass parent;
/*< public >*/
sPAPRDRConnectorTypeShift typeshift;
const char *typename; /* used in device tree, PAPR 13.5.2.6 & C.6.1 */
/* accessors for guest-visible (generally via RTAS) DR state */
uint32_t (*set_isolation_state)(sPAPRDRConnector *drc,
......@@ -171,16 +221,10 @@ typedef struct sPAPRDRConnectorClass {
sPAPRDRIndicatorState state);
uint32_t (*set_allocation_state)(sPAPRDRConnector *drc,
sPAPRDRAllocationState state);
uint32_t (*get_index)(sPAPRDRConnector *drc);
uint32_t (*get_type)(sPAPRDRConnector *drc);
const char *(*get_name)(sPAPRDRConnector *drc);
uint32_t (*entity_sense)(sPAPRDRConnector *drc, sPAPRDREntitySense *state);
/* QEMU interfaces for managing FDT/configure-connector */
const void *(*get_fdt)(sPAPRDRConnector *drc, int *fdt_start_offset);
void (*set_configured)(sPAPRDRConnector *drc);
/* QEMU interfaces for managing hotplug operations */
void (*attach)(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
int fdt_start_offset, bool coldplug, Error **errp);
......@@ -189,12 +233,13 @@ typedef struct sPAPRDRConnectorClass {
void (*set_signalled)(sPAPRDRConnector *drc);
} sPAPRDRConnectorClass;
sPAPRDRConnector *spapr_dr_connector_new(Object *owner,
sPAPRDRConnectorType type,
uint32_t spapr_drc_index(sPAPRDRConnector *drc);
sPAPRDRConnectorType spapr_drc_type(sPAPRDRConnector *drc);
sPAPRDRConnector *spapr_dr_connector_new(Object *owner, const char *type,
uint32_t id);
sPAPRDRConnector *spapr_dr_connector_by_index(uint32_t index);
sPAPRDRConnector *spapr_dr_connector_by_id(sPAPRDRConnectorType type,
uint32_t id);
sPAPRDRConnector *spapr_drc_by_index(uint32_t index);
sPAPRDRConnector *spapr_drc_by_id(const char *type, uint32_t id);
int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner,
uint32_t drc_type_mask);
......
......@@ -59,14 +59,6 @@ typedef struct SaveVMHandlers {
LoadStateHandler *load_state;
} SaveVMHandlers;
int register_savevm(DeviceState *dev,
const char *idstr,
int instance_id,
int version_id,
SaveStateHandler *save_state,
LoadStateHandler *load_state,
void *opaque);
int register_savevm_live(DeviceState *dev,
const char *idstr,
int instance_id,
......
......@@ -27,6 +27,7 @@ void qemu_timer_notify_cb(void *opaque, QEMUClockType type);
void cpu_synchronize_all_states(void);
void cpu_synchronize_all_post_reset(void);
void cpu_synchronize_all_post_init(void);
void cpu_synchronize_all_pre_loadvm(void);
void qtest_clock_warp(int64_t dest);
......
......@@ -33,6 +33,7 @@ int hax_populate_ram(uint64_t va, uint32_t size);
void hax_cpu_synchronize_state(CPUState *cpu);
void hax_cpu_synchronize_post_reset(CPUState *cpu);
void hax_cpu_synchronize_post_init(CPUState *cpu);
void hax_cpu_synchronize_pre_loadvm(CPUState *cpu);
#ifdef CONFIG_HAX
......
......@@ -45,4 +45,14 @@ static inline void cpu_synchronize_post_init(CPUState *cpu)
}
}
static inline void cpu_synchronize_pre_loadvm(CPUState *cpu)
{
if (kvm_enabled()) {
kvm_cpu_synchronize_pre_loadvm(cpu);
}
if (hax_enabled()) {
hax_cpu_synchronize_pre_loadvm(cpu);
}
}
#endif /* QEMU_HW_ACCEL_H */
......@@ -459,6 +459,7 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
void kvm_cpu_synchronize_state(CPUState *cpu);
void kvm_cpu_synchronize_post_reset(CPUState *cpu);
void kvm_cpu_synchronize_post_init(CPUState *cpu);
void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu);
void kvm_init_cpu_signals(CPUState *cpu);
......
......@@ -1896,6 +1896,16 @@ void kvm_cpu_synchronize_post_init(CPUState *cpu)
run_on_cpu(cpu, do_kvm_cpu_synchronize_post_init, RUN_ON_CPU_NULL);
}
static void do_kvm_cpu_synchronize_pre_loadvm(CPUState *cpu, run_on_cpu_data arg)
{
cpu->kvm_vcpu_dirty = true;
}
void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu)
{
run_on_cpu(cpu, do_kvm_cpu_synchronize_pre_loadvm, RUN_ON_CPU_NULL);
}
#ifdef KVM_HAVE_MCE_INJECTION
static __thread void *pending_sigbus_addr;
static __thread int pending_sigbus_code;
......
......@@ -645,21 +645,6 @@ int register_savevm_live(DeviceState *dev,
return 0;
}
int register_savevm(DeviceState *dev,
const char *idstr,
int instance_id,
int version_id,
SaveStateHandler *save_state,
LoadStateHandler *load_state,
void *opaque)
{
SaveVMHandlers *ops = g_new0(SaveVMHandlers, 1);
ops->save_state = save_state;
ops->load_state = load_state;
return register_savevm_live(dev, idstr, instance_id, version_id,
ops, opaque);
}
void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
{
SaveStateEntry *se, *new_se;
......@@ -679,7 +664,6 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) {
QTAILQ_REMOVE(&savevm_state.handlers, se, entry);
g_free(se->compat);
g_free(se->ops);
g_free(se);
}
}
......@@ -2015,6 +1999,8 @@ int qemu_loadvm_state(QEMUFile *f)
}
}
cpu_synchronize_all_pre_loadvm();
ret = qemu_loadvm_state_main(f, mis);
qemu_event_set(&mis->main_thread_load_event);
......
......@@ -272,6 +272,11 @@ static void slirp_init_once(void)
static void slirp_state_save(QEMUFile *f, void *opaque);
static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
static SaveVMHandlers savevm_slirp_state = {
.save_state = slirp_state_save,
.load_state = slirp_state_load,
};
Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
struct in_addr vnetmask, struct in_addr vhost,
bool in6_enabled,
......@@ -321,8 +326,7 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
slirp->opaque = opaque;
register_savevm(NULL, "slirp", 0, 4,
slirp_state_save, slirp_state_load, slirp);
register_savevm_live(NULL, "slirp", 0, 4, &savevm_slirp_state, slirp);
QTAILQ_INSERT_TAIL(&slirp_instances, slirp, entry);
......
......@@ -635,6 +635,16 @@ void hax_cpu_synchronize_post_init(CPUState *cpu)
run_on_cpu(cpu, do_hax_cpu_synchronize_post_init, RUN_ON_CPU_NULL);
}
static void do_hax_cpu_synchronize_pre_loadvm(CPUState *cpu, run_on_cpu_data arg)
{
cpu->hax_vcpu_dirty = true;
}
void hax_cpu_synchronize_pre_loadvm(CPUState *cpu)
{
run_on_cpu(cpu, do_hax_cpu_synchronize_pre_loadvm, RUN_ON_CPU_NULL);
}
int hax_smp_cpu_exec(CPUState *cpu)
{
CPUArchState *env = (CPUArchState *) (cpu->env_ptr);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册