mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/dgibson/tags/spapr-next-20150923' into staging
sPAPR Patch Queue: 2015-09-23
Highlights:
* pseries-2.5 machine type
* Memory hotplug for "pseries" guests
* Fixes to the PAPR Dynamic Reconfiguration hotplug code
* Several PAPR compliance fixes
* New SLOF with:
* GPT support
* Much faster VGA handling
# gpg: Signature made Wed 23 Sep 2015 02:50:10 BST using DSA key ID FDDA6FC6
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: F730 2185 38B4 D13E FD80 34F2 6882 CAC6 FDDA 6FC6
* remotes/dgibson/tags/spapr-next-20150923: (36 commits)
sPAPR: Enable EEH on VFIO PCI device only
sPAPR: Revert don't enable EEH on emulated PCI devices
ppc/spapr: Implement H_RANDOM hypercall in QEMU
ppc/spapr: Fix buffer overflow in spapr_populate_drconf_memory()
spapr: Fix default NUMA node allocation for threads
spapr: Move memory hotplug to RTAS_LOG_V6_HP_ID_DRC_COUNT type
spapr: Support hotplug by specifying DRC count
spapr: Revert to memory@XXXX representation for non-hotplugged memory
spapr: Populate ibm,associativity-lookup-arrays correctly for non-NUMA
spapr: Provide better error message when slots exceed max allowed
spapr: Don't allow memory hotplug to memory less nodes
spapr: Memory hotplug support
spapr: Make hash table size a factor of maxram_size
spapr: Support ibm,dynamic-reconfiguration-memory
spapr: Add LMB DR connectors
spapr: Use QEMU limit for maximum CPUs number
spapr: Don't use QOM [*] syntax for DR connectors.
spapr_drc: use RTAS return codes for methods called by RTAS
spapr: Initialize hotplug memory address space
spapr_drc: don't allow 'empty' DRCs to be unisolated or allocated
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -52,3 +52,4 @@ CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM))
|
||||
# For PReP
|
||||
CONFIG_MC146818RTC=y
|
||||
CONFIG_ISA_TESTDEV=y
|
||||
CONFIG_MEM_HOTPLUG=y
|
||||
|
||||
@@ -302,4 +302,52 @@ consisting of <phys>, <size> and <maxcpus>.
|
||||
pseries guests use this property to note the maximum allowed CPUs for the
|
||||
guest.
|
||||
|
||||
== ibm,dynamic-reconfiguration-memory ==
|
||||
|
||||
ibm,dynamic-reconfiguration-memory is a device tree node that represents
|
||||
dynamically reconfigurable logical memory blocks (LMB). This node
|
||||
is generated only when the guest advertises the support for it via
|
||||
ibm,client-architecture-support call. Memory that is not dynamically
|
||||
reconfigurable is represented by /memory nodes. The properties of this
|
||||
node that are of interest to the sPAPR memory hotplug implementation
|
||||
in QEMU are described here.
|
||||
|
||||
ibm,lmb-size
|
||||
|
||||
This 64bit integer defines the size of each dynamically reconfigurable LMB.
|
||||
|
||||
ibm,associativity-lookup-arrays
|
||||
|
||||
This property defines a lookup array in which the NUMA associativity
|
||||
information for each LMB can be found. It is a property encoded array
|
||||
that begins with an integer M, the number of associativity lists followed
|
||||
by an integer N, the number of entries per associativity list and terminated
|
||||
by M associativity lists each of length N integers.
|
||||
|
||||
This property provides the same information as given by ibm,associativity
|
||||
property in a /memory node. Each assigned LMB has an index value between
|
||||
0 and M-1 which is used as an index into this table to select which
|
||||
associativity list to use for the LMB. This index value for each LMB
|
||||
is defined in ibm,dynamic-memory property.
|
||||
|
||||
ibm,dynamic-memory
|
||||
|
||||
This property describes the dynamically reconfigurable memory. It is a
|
||||
property encoded array that has an integer N, the number of LMBs followed
|
||||
by N LMB list entires.
|
||||
|
||||
Each LMB list entry consists of the following elements:
|
||||
|
||||
- Logical address of the start of the LMB encoded as a 64bit integer. This
|
||||
corresponds to reg property in /memory node.
|
||||
- DRC index of the LMB that corresponds to ibm,my-drc-index property
|
||||
in a /memory node.
|
||||
- Four bytes reserved for expansion.
|
||||
- Associativity list index for the LMB that is used as an index into
|
||||
ibm,associativity-lookup-arrays property described earlier. This
|
||||
is used to retrieve the right associativity list to be used for this
|
||||
LMB.
|
||||
- A 32bit flags word. The bit at bit position 0x00000008 defines whether
|
||||
the LMB is assigned to the the partition as of boot time.
|
||||
|
||||
[1] http://thread.gmane.org/gmane.linux.ports.ppc.embedded/75350/focus=106867
|
||||
|
||||
@@ -3,7 +3,7 @@ obj-y += ppc.o ppc_booke.o
|
||||
# IBM pSeries (sPAPR)
|
||||
obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o
|
||||
obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o
|
||||
obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o
|
||||
obj-$(CONFIG_PSERIES) += spapr_pci.o spapr_rtc.o spapr_drc.o spapr_rng.o
|
||||
ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
|
||||
obj-y += spapr_pci_vfio.o
|
||||
endif
|
||||
|
||||
+435
-48
File diff suppressed because it is too large
Load Diff
+46
-21
@@ -15,6 +15,7 @@
|
||||
#include "hw/qdev.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/ppc/spapr.h" /* for RTAS return codes */
|
||||
|
||||
/* #define DEBUG_SPAPR_DRC */
|
||||
|
||||
@@ -32,7 +33,7 @@
|
||||
|
||||
#define DRC_CONTAINER_PATH "/dr-connector"
|
||||
#define DRC_INDEX_TYPE_SHIFT 28
|
||||
#define DRC_INDEX_ID_MASK (~(~0 << DRC_INDEX_TYPE_SHIFT))
|
||||
#define DRC_INDEX_ID_MASK ((1ULL << DRC_INDEX_TYPE_SHIFT) - 1)
|
||||
|
||||
static sPAPRDRConnectorTypeShift get_type_shift(sPAPRDRConnectorType type)
|
||||
{
|
||||
@@ -59,13 +60,23 @@ static uint32_t get_index(sPAPRDRConnector *drc)
|
||||
(drc->id & DRC_INDEX_ID_MASK);
|
||||
}
|
||||
|
||||
static int set_isolation_state(sPAPRDRConnector *drc,
|
||||
sPAPRDRIsolationState state)
|
||||
static uint32_t set_isolation_state(sPAPRDRConnector *drc,
|
||||
sPAPRDRIsolationState state)
|
||||
{
|
||||
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
|
||||
|
||||
DPRINTFN("drc: %x, set_isolation_state: %x", get_index(drc), state);
|
||||
|
||||
if (state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) {
|
||||
/* cannot unisolate a non-existant resource, and, or resources
|
||||
* which are in an 'UNUSABLE' allocation state. (PAPR 2.7, 13.5.3.5)
|
||||
*/
|
||||
if (!drc->dev ||
|
||||
drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) {
|
||||
return RTAS_OUT_NO_SUCH_INDICATOR;
|
||||
}
|
||||
}
|
||||
|
||||
drc->isolation_state = state;
|
||||
|
||||
if (drc->isolation_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) {
|
||||
@@ -89,24 +100,35 @@ static int set_isolation_state(sPAPRDRConnector *drc,
|
||||
drc->configured = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return RTAS_OUT_SUCCESS;
|
||||
}
|
||||
|
||||
static int set_indicator_state(sPAPRDRConnector *drc,
|
||||
sPAPRDRIndicatorState state)
|
||||
static uint32_t set_indicator_state(sPAPRDRConnector *drc,
|
||||
sPAPRDRIndicatorState state)
|
||||
{
|
||||
DPRINTFN("drc: %x, set_indicator_state: %x", get_index(drc), state);
|
||||
drc->indicator_state = state;
|
||||
return 0;
|
||||
return RTAS_OUT_SUCCESS;
|
||||
}
|
||||
|
||||
static int set_allocation_state(sPAPRDRConnector *drc,
|
||||
sPAPRDRAllocationState state)
|
||||
static uint32_t set_allocation_state(sPAPRDRConnector *drc,
|
||||
sPAPRDRAllocationState state)
|
||||
{
|
||||
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
|
||||
|
||||
DPRINTFN("drc: %x, set_allocation_state: %x", get_index(drc), state);
|
||||
|
||||
if (state == SPAPR_DR_ALLOCATION_STATE_USABLE) {
|
||||
/* if there's no resource/device associated with the DRC, there's
|
||||
* no way for us to put it in an allocation state consistent with
|
||||
* being 'USABLE'. PAPR 2.7, 13.5.3.4 documents that this should
|
||||
* result in an RTAS return code of -3 / "no such indicator"
|
||||
*/
|
||||
if (!drc->dev) {
|
||||
return RTAS_OUT_NO_SUCH_INDICATOR;
|
||||
}
|
||||
}
|
||||
|
||||
if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI) {
|
||||
drc->allocation_state = state;
|
||||
if (drc->awaiting_release &&
|
||||
@@ -116,7 +138,7 @@ static int set_allocation_state(sPAPRDRConnector *drc,
|
||||
drc->detach_cb_opaque, NULL);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return RTAS_OUT_SUCCESS;
|
||||
}
|
||||
|
||||
static uint32_t get_type(sPAPRDRConnector *drc)
|
||||
@@ -157,10 +179,8 @@ static void set_configured(sPAPRDRConnector *drc)
|
||||
* based on the current allocation/indicator/power states
|
||||
* for the DR connector.
|
||||
*/
|
||||
static sPAPRDREntitySense entity_sense(sPAPRDRConnector *drc)
|
||||
static uint32_t entity_sense(sPAPRDRConnector *drc, sPAPRDREntitySense *state)
|
||||
{
|
||||
sPAPRDREntitySense state;
|
||||
|
||||
if (drc->dev) {
|
||||
if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI &&
|
||||
drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) {
|
||||
@@ -169,7 +189,7 @@ static sPAPRDREntitySense entity_sense(sPAPRDRConnector *drc)
|
||||
* Otherwise, report the state as USABLE/PRESENT,
|
||||
* as we would for PCI.
|
||||
*/
|
||||
state = SPAPR_DR_ENTITY_SENSE_UNUSABLE;
|
||||
*state = SPAPR_DR_ENTITY_SENSE_UNUSABLE;
|
||||
} else {
|
||||
/* this assumes all PCI devices are assigned to
|
||||
* a 'live insertion' power domain, where QEMU
|
||||
@@ -177,21 +197,21 @@ static sPAPRDREntitySense entity_sense(sPAPRDRConnector *drc)
|
||||
* to the guest. present, non-PCI resources are
|
||||
* unaffected by power state.
|
||||
*/
|
||||
state = SPAPR_DR_ENTITY_SENSE_PRESENT;
|
||||
*state = SPAPR_DR_ENTITY_SENSE_PRESENT;
|
||||
}
|
||||
} else {
|
||||
if (drc->type == SPAPR_DR_CONNECTOR_TYPE_PCI) {
|
||||
/* PCI devices, and only PCI devices, use EMPTY
|
||||
* in cases where we'd otherwise use UNUSABLE
|
||||
*/
|
||||
state = SPAPR_DR_ENTITY_SENSE_EMPTY;
|
||||
*state = SPAPR_DR_ENTITY_SENSE_EMPTY;
|
||||
} else {
|
||||
state = SPAPR_DR_ENTITY_SENSE_UNUSABLE;
|
||||
*state = SPAPR_DR_ENTITY_SENSE_UNUSABLE;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTFN("drc: %x, entity_sense: %x", get_index(drc), state);
|
||||
return state;
|
||||
return RTAS_OUT_SUCCESS;
|
||||
}
|
||||
|
||||
static void prop_get_index(Object *obj, Visitor *v, void *opaque,
|
||||
@@ -224,7 +244,9 @@ static void prop_get_entity_sense(Object *obj, Visitor *v, void *opaque,
|
||||
{
|
||||
sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj);
|
||||
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
|
||||
uint32_t value = (uint32_t)drck->entity_sense(drc);
|
||||
uint32_t value;
|
||||
|
||||
drck->entity_sense(drc, &value);
|
||||
visit_type_uint32(v, &value, name, errp);
|
||||
}
|
||||
|
||||
@@ -310,7 +332,7 @@ static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt,
|
||||
drc->dev = d;
|
||||
drc->fdt = fdt;
|
||||
drc->fdt_start_offset = fdt_start_offset;
|
||||
drc->configured = false;
|
||||
drc->configured = coldplug;
|
||||
|
||||
object_property_add_link(OBJECT(drc), "device",
|
||||
object_get_typename(OBJECT(drc->dev)),
|
||||
@@ -451,14 +473,17 @@ sPAPRDRConnector *spapr_dr_connector_new(Object *owner,
|
||||
{
|
||||
sPAPRDRConnector *drc =
|
||||
SPAPR_DR_CONNECTOR(object_new(TYPE_SPAPR_DR_CONNECTOR));
|
||||
char *prop_name;
|
||||
|
||||
g_assert(type);
|
||||
|
||||
drc->type = type;
|
||||
drc->id = id;
|
||||
drc->owner = owner;
|
||||
object_property_add_child(owner, "dr-connector[*]", OBJECT(drc), NULL);
|
||||
prop_name = g_strdup_printf("dr-connector[%"PRIu32"]", get_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);
|
||||
|
||||
/* human-readable name for a DRC to encode into the DT
|
||||
* description. this is mainly only used within a guest in place
|
||||
|
||||
+41
-10
@@ -386,7 +386,9 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
|
||||
qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq));
|
||||
}
|
||||
|
||||
static void spapr_hotplug_req_event(sPAPRDRConnector *drc, uint8_t hp_action)
|
||||
static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
|
||||
sPAPRDRConnectorType drc_type,
|
||||
uint32_t drc)
|
||||
{
|
||||
sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
|
||||
struct hp_log_full *new_hp;
|
||||
@@ -395,8 +397,6 @@ static void spapr_hotplug_req_event(sPAPRDRConnector *drc, uint8_t hp_action)
|
||||
struct rtas_event_log_v6_maina *maina;
|
||||
struct rtas_event_log_v6_mainb *mainb;
|
||||
struct rtas_event_log_v6_hp *hp;
|
||||
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
|
||||
sPAPRDRConnectorType drc_type = drck->get_type(drc);
|
||||
|
||||
new_hp = g_malloc0(sizeof(struct hp_log_full));
|
||||
hdr = &new_hp->hdr;
|
||||
@@ -427,14 +427,15 @@ static void spapr_hotplug_req_event(sPAPRDRConnector *drc, uint8_t hp_action)
|
||||
hp->hdr.section_length = cpu_to_be16(sizeof(*hp));
|
||||
hp->hdr.section_version = 1; /* includes extended modifier */
|
||||
hp->hotplug_action = hp_action;
|
||||
|
||||
hp->hotplug_identifier = hp_id;
|
||||
|
||||
switch (drc_type) {
|
||||
case SPAPR_DR_CONNECTOR_TYPE_PCI:
|
||||
hp->drc.index = cpu_to_be32(drck->get_index(drc));
|
||||
hp->hotplug_identifier = RTAS_LOG_V6_HP_ID_DRC_INDEX;
|
||||
hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_PCI;
|
||||
break;
|
||||
case SPAPR_DR_CONNECTOR_TYPE_LMB:
|
||||
hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_MEMORY;
|
||||
break;
|
||||
default:
|
||||
/* we shouldn't be signaling hotplug events for resources
|
||||
* that don't support them
|
||||
@@ -443,19 +444,49 @@ static void spapr_hotplug_req_event(sPAPRDRConnector *drc, uint8_t hp_action)
|
||||
return;
|
||||
}
|
||||
|
||||
if (hp_id == RTAS_LOG_V6_HP_ID_DRC_COUNT) {
|
||||
hp->drc.count = cpu_to_be32(drc);
|
||||
} else if (hp_id == RTAS_LOG_V6_HP_ID_DRC_INDEX) {
|
||||
hp->drc.index = cpu_to_be32(drc);
|
||||
}
|
||||
|
||||
rtas_event_log_queue(RTAS_LOG_TYPE_HOTPLUG, new_hp, true);
|
||||
|
||||
qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq));
|
||||
}
|
||||
|
||||
void spapr_hotplug_req_add_event(sPAPRDRConnector *drc)
|
||||
void spapr_hotplug_req_add_by_index(sPAPRDRConnector *drc)
|
||||
{
|
||||
spapr_hotplug_req_event(drc, RTAS_LOG_V6_HP_ACTION_ADD);
|
||||
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
|
||||
sPAPRDRConnectorType drc_type = drck->get_type(drc);
|
||||
uint32 index = drck->get_index(drc);
|
||||
|
||||
spapr_hotplug_req_event(RTAS_LOG_V6_HP_ID_DRC_INDEX,
|
||||
RTAS_LOG_V6_HP_ACTION_ADD, drc_type, index);
|
||||
}
|
||||
|
||||
void spapr_hotplug_req_remove_event(sPAPRDRConnector *drc)
|
||||
void spapr_hotplug_req_remove_by_index(sPAPRDRConnector *drc)
|
||||
{
|
||||
spapr_hotplug_req_event(drc, RTAS_LOG_V6_HP_ACTION_REMOVE);
|
||||
sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
|
||||
sPAPRDRConnectorType drc_type = drck->get_type(drc);
|
||||
uint32 index = drck->get_index(drc);
|
||||
|
||||
spapr_hotplug_req_event(RTAS_LOG_V6_HP_ID_DRC_INDEX,
|
||||
RTAS_LOG_V6_HP_ACTION_REMOVE, drc_type, index);
|
||||
}
|
||||
|
||||
void spapr_hotplug_req_add_by_count(sPAPRDRConnectorType drc_type,
|
||||
uint32_t count)
|
||||
{
|
||||
spapr_hotplug_req_event(RTAS_LOG_V6_HP_ID_DRC_COUNT,
|
||||
RTAS_LOG_V6_HP_ACTION_ADD, drc_type, count);
|
||||
}
|
||||
|
||||
void spapr_hotplug_req_remove_by_count(sPAPRDRConnectorType drc_type,
|
||||
uint32_t count)
|
||||
{
|
||||
spapr_hotplug_req_event(RTAS_LOG_V6_HP_ID_DRC_COUNT,
|
||||
RTAS_LOG_V6_HP_ACTION_REMOVE, drc_type, count);
|
||||
}
|
||||
|
||||
static void check_exception(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
|
||||
+47
-7
@@ -808,6 +808,32 @@ static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the offset to the requested option vector @vector in the
|
||||
* option vector table @table.
|
||||
*/
|
||||
static target_ulong cas_get_option_vector(int vector, target_ulong table)
|
||||
{
|
||||
int i;
|
||||
char nr_vectors, nr_entries;
|
||||
|
||||
if (!table) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
nr_vectors = (ldl_phys(&address_space_memory, table) >> 24) + 1;
|
||||
if (!vector || vector > nr_vectors) {
|
||||
return 0;
|
||||
}
|
||||
table++; /* skip nr option vectors */
|
||||
|
||||
for (i = 0; i < vector - 1; i++) {
|
||||
nr_entries = ldl_phys(&address_space_memory, table) >> 24;
|
||||
table += nr_entries + 2;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
PowerPCCPU *cpu;
|
||||
uint32_t cpu_version;
|
||||
@@ -828,19 +854,22 @@ static void do_set_compat(void *arg)
|
||||
((cpuver) == CPU_POWERPC_LOGICAL_2_06_PLUS) ? 2061 : \
|
||||
((cpuver) == CPU_POWERPC_LOGICAL_2_07) ? 2070 : 0)
|
||||
|
||||
#define OV5_DRCONF_MEMORY 0x20
|
||||
|
||||
static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
|
||||
sPAPRMachineState *spapr,
|
||||
target_ulong opcode,
|
||||
target_ulong *args)
|
||||
{
|
||||
target_ulong list = args[0];
|
||||
target_ulong list = args[0], ov_table;
|
||||
PowerPCCPUClass *pcc_ = POWERPC_CPU_GET_CLASS(cpu_);
|
||||
CPUState *cs;
|
||||
bool cpu_match = false;
|
||||
bool cpu_match = false, cpu_update = true, memory_update = false;
|
||||
unsigned old_cpu_version = cpu_->cpu_version;
|
||||
unsigned compat_lvl = 0, cpu_version = 0;
|
||||
unsigned max_lvl = get_compat_level(cpu_->max_compat);
|
||||
int counter;
|
||||
char ov5_byte2;
|
||||
|
||||
/* Parse PVR list */
|
||||
for (counter = 0; counter < 512; ++counter) {
|
||||
@@ -890,8 +919,6 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
|
||||
}
|
||||
}
|
||||
|
||||
/* For the future use: here @list points to the first capability */
|
||||
|
||||
/* Parsing finished */
|
||||
trace_spapr_cas_pvr(cpu_->cpu_version, cpu_match,
|
||||
cpu_version, pcc_->pcr_mask);
|
||||
@@ -915,14 +942,26 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
|
||||
}
|
||||
|
||||
if (!cpu_version) {
|
||||
return H_SUCCESS;
|
||||
cpu_update = false;
|
||||
}
|
||||
|
||||
/* For the future use: here @ov_table points to the first option vector */
|
||||
ov_table = list;
|
||||
|
||||
list = cas_get_option_vector(5, ov_table);
|
||||
if (!list) {
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
if (spapr_h_cas_compose_response(spapr, args[1], args[2])) {
|
||||
/* @list now points to OV 5 */
|
||||
list += 2;
|
||||
ov5_byte2 = rtas_ld(list, 0) >> 24;
|
||||
if (ov5_byte2 & OV5_DRCONF_MEMORY) {
|
||||
memory_update = true;
|
||||
}
|
||||
|
||||
if (spapr_h_cas_compose_response(spapr, args[1], args[2],
|
||||
cpu_update, memory_update)) {
|
||||
qemu_system_reset_request();
|
||||
}
|
||||
|
||||
@@ -971,7 +1010,8 @@ target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
|
||||
}
|
||||
}
|
||||
|
||||
hcall_dprintf("Unimplemented hcall 0x" TARGET_FMT_lx "\n", opcode);
|
||||
qemu_log_mask(LOG_UNIMP, "Unimplemented SPAPR hcall 0x" TARGET_FMT_lx "\n",
|
||||
opcode);
|
||||
return H_FUNCTION;
|
||||
}
|
||||
|
||||
|
||||
+25
-22
@@ -140,7 +140,7 @@ static void rtas_ibm_read_pci_config(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
return;
|
||||
}
|
||||
|
||||
buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
buid = rtas_ldq(args, 1);
|
||||
size = rtas_ld(args, 3);
|
||||
addr = rtas_ld(args, 0);
|
||||
|
||||
@@ -206,7 +206,7 @@ static void rtas_ibm_write_pci_config(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
return;
|
||||
}
|
||||
|
||||
buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
buid = rtas_ldq(args, 1);
|
||||
val = rtas_ld(args, 4);
|
||||
size = rtas_ld(args, 3);
|
||||
addr = rtas_ld(args, 0);
|
||||
@@ -269,7 +269,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
target_ulong rets)
|
||||
{
|
||||
uint32_t config_addr = rtas_ld(args, 0);
|
||||
uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
uint64_t buid = rtas_ldq(args, 1);
|
||||
unsigned int func = rtas_ld(args, 3);
|
||||
unsigned int req_num = rtas_ld(args, 4); /* 0 == remove all */
|
||||
unsigned int seq_num = rtas_ld(args, 5);
|
||||
@@ -375,7 +375,9 @@ out:
|
||||
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
|
||||
rtas_st(rets, 1, req_num);
|
||||
rtas_st(rets, 2, ++seq_num);
|
||||
rtas_st(rets, 3, ret_intr_type);
|
||||
if (nret > 3) {
|
||||
rtas_st(rets, 3, ret_intr_type);
|
||||
}
|
||||
|
||||
trace_spapr_pci_rtas_ibm_change_msi(config_addr, func, req_num, irq);
|
||||
}
|
||||
@@ -389,7 +391,7 @@ static void rtas_ibm_query_interrupt_source_number(PowerPCCPU *cpu,
|
||||
target_ulong rets)
|
||||
{
|
||||
uint32_t config_addr = rtas_ld(args, 0);
|
||||
uint64_t buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
uint64_t buid = rtas_ldq(args, 1);
|
||||
unsigned int intr_src_num = -1, ioa_intr_num = rtas_ld(args, 3);
|
||||
sPAPRPHBState *phb = NULL;
|
||||
PCIDevice *pdev = NULL;
|
||||
@@ -429,7 +431,6 @@ static void rtas_ibm_set_eeh_option(PowerPCCPU *cpu,
|
||||
{
|
||||
sPAPRPHBState *sphb;
|
||||
sPAPRPHBClass *spc;
|
||||
PCIDevice *pdev;
|
||||
uint32_t addr, option;
|
||||
uint64_t buid;
|
||||
int ret;
|
||||
@@ -438,7 +439,7 @@ static void rtas_ibm_set_eeh_option(PowerPCCPU *cpu,
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
buid = rtas_ldq(args, 1);
|
||||
addr = rtas_ld(args, 0);
|
||||
option = rtas_ld(args, 3);
|
||||
|
||||
@@ -447,12 +448,6 @@ static void rtas_ibm_set_eeh_option(PowerPCCPU *cpu,
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
pdev = pci_find_device(PCI_HOST_BRIDGE(sphb)->bus,
|
||||
(addr >> 16) & 0xFF, (addr >> 8) & 0xFF);
|
||||
if (!pdev || !object_dynamic_cast(OBJECT(pdev), "vfio-pci")) {
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
spc = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(sphb);
|
||||
if (!spc->eeh_set_option) {
|
||||
goto param_error_exit;
|
||||
@@ -482,7 +477,7 @@ static void rtas_ibm_get_config_addr_info2(PowerPCCPU *cpu,
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
buid = rtas_ldq(args, 1);
|
||||
sphb = spapr_pci_find_phb(spapr, buid);
|
||||
if (!sphb) {
|
||||
goto param_error_exit;
|
||||
@@ -537,7 +532,7 @@ static void rtas_ibm_read_slot_reset_state2(PowerPCCPU *cpu,
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
buid = rtas_ldq(args, 1);
|
||||
sphb = spapr_pci_find_phb(spapr, buid);
|
||||
if (!sphb) {
|
||||
goto param_error_exit;
|
||||
@@ -582,7 +577,7 @@ static void rtas_ibm_set_slot_reset(PowerPCCPU *cpu,
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
buid = rtas_ldq(args, 1);
|
||||
option = rtas_ld(args, 3);
|
||||
sphb = spapr_pci_find_phb(spapr, buid);
|
||||
if (!sphb) {
|
||||
@@ -617,7 +612,7 @@ static void rtas_ibm_configure_pe(PowerPCCPU *cpu,
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
buid = rtas_ldq(args, 1);
|
||||
sphb = spapr_pci_find_phb(spapr, buid);
|
||||
if (!sphb) {
|
||||
goto param_error_exit;
|
||||
@@ -652,7 +647,7 @@ static void rtas_ibm_slot_error_detail(PowerPCCPU *cpu,
|
||||
goto param_error_exit;
|
||||
}
|
||||
|
||||
buid = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 2);
|
||||
buid = rtas_ldq(args, 1);
|
||||
sphb = spapr_pci_find_phb(spapr, buid);
|
||||
if (!sphb) {
|
||||
goto param_error_exit;
|
||||
@@ -955,6 +950,7 @@ static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
|
||||
int pci_status, err;
|
||||
char *buf = NULL;
|
||||
uint32_t drc_index = spapr_phb_get_pci_drc_index(sphb, dev);
|
||||
uint32_t max_msi, max_msix;
|
||||
|
||||
if (pci_default_read_config(dev, PCI_HEADER_TYPE, 1) ==
|
||||
PCI_HEADER_TYPE_BRIDGE) {
|
||||
@@ -1035,8 +1031,15 @@ static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
|
||||
RESOURCE_CELLS_ADDRESS));
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "#size-cells",
|
||||
RESOURCE_CELLS_SIZE));
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi-x",
|
||||
RESOURCE_CELLS_SIZE));
|
||||
|
||||
max_msi = msi_nr_vectors_allocated(dev);
|
||||
if (max_msi) {
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi", max_msi));
|
||||
}
|
||||
max_msix = dev->msix_entries_nr;
|
||||
if (max_msix) {
|
||||
_FDT(fdt_setprop_cell(fdt, offset, "ibm,req#msi-x", max_msix));
|
||||
}
|
||||
|
||||
populate_resource_props(dev, &rp);
|
||||
_FDT(fdt_setprop(fdt, offset, "reg", (uint8_t *)rp.reg, rp.reg_len));
|
||||
@@ -1177,7 +1180,7 @@ static void spapr_phb_hot_plug_child(HotplugHandler *plug_handler,
|
||||
return;
|
||||
}
|
||||
if (plugged_dev->hotplugged) {
|
||||
spapr_hotplug_req_add_event(drc);
|
||||
spapr_hotplug_req_add_by_index(drc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1205,7 +1208,7 @@ static void spapr_phb_hot_unplug_child(HotplugHandler *plug_handler,
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
spapr_hotplug_req_remove_event(drc);
|
||||
spapr_hotplug_req_remove_by_index(drc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ static int spapr_phb_vfio_eeh_set_option(sPAPRPHBState *sphb,
|
||||
phb = PCI_HOST_BRIDGE(sphb);
|
||||
pdev = pci_find_device(phb->bus,
|
||||
(addr >> 16) & 0xFF, (addr >> 8) & 0xFF);
|
||||
if (!pdev) {
|
||||
if (!pdev || !object_dynamic_cast(OBJECT(pdev), "vfio-pci")) {
|
||||
return RTAS_OUT_PARAM_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* QEMU sPAPR random number generator "device" for H_RANDOM hypercall
|
||||
*
|
||||
* Copyright 2015 Thomas Huth, Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/device_tree.h"
|
||||
#include "sysemu/rng.h"
|
||||
#include "hw/ppc/spapr.h"
|
||||
#include "kvm_ppc.h"
|
||||
|
||||
#define SPAPR_RNG(obj) \
|
||||
OBJECT_CHECK(sPAPRRngState, (obj), TYPE_SPAPR_RNG)
|
||||
|
||||
struct sPAPRRngState {
|
||||
/*< private >*/
|
||||
DeviceState ds;
|
||||
RngBackend *backend;
|
||||
bool use_kvm;
|
||||
};
|
||||
typedef struct sPAPRRngState sPAPRRngState;
|
||||
|
||||
struct HRandomData {
|
||||
QemuSemaphore sem;
|
||||
union {
|
||||
uint64_t v64;
|
||||
uint8_t v8[8];
|
||||
} val;
|
||||
int received;
|
||||
};
|
||||
typedef struct HRandomData HRandomData;
|
||||
|
||||
/* Callback function for the RngBackend */
|
||||
static void random_recv(void *dest, const void *src, size_t size)
|
||||
{
|
||||
HRandomData *hrdp = dest;
|
||||
|
||||
if (src && size > 0) {
|
||||
assert(size + hrdp->received <= sizeof(hrdp->val.v8));
|
||||
memcpy(&hrdp->val.v8[hrdp->received], src, size);
|
||||
hrdp->received += size;
|
||||
}
|
||||
|
||||
qemu_sem_post(&hrdp->sem);
|
||||
}
|
||||
|
||||
/* Handler for the H_RANDOM hypercall */
|
||||
static target_ulong h_random(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
target_ulong opcode, target_ulong *args)
|
||||
{
|
||||
sPAPRRngState *rngstate;
|
||||
HRandomData hrdata;
|
||||
|
||||
rngstate = SPAPR_RNG(object_resolve_path_type("", TYPE_SPAPR_RNG, NULL));
|
||||
|
||||
if (!rngstate || !rngstate->backend) {
|
||||
return H_HARDWARE;
|
||||
}
|
||||
|
||||
qemu_sem_init(&hrdata.sem, 0);
|
||||
hrdata.val.v64 = 0;
|
||||
hrdata.received = 0;
|
||||
|
||||
qemu_mutex_unlock_iothread();
|
||||
while (hrdata.received < 8) {
|
||||
rng_backend_request_entropy(rngstate->backend, 8 - hrdata.received,
|
||||
random_recv, &hrdata);
|
||||
qemu_sem_wait(&hrdata.sem);
|
||||
}
|
||||
qemu_mutex_lock_iothread();
|
||||
|
||||
qemu_sem_destroy(&hrdata.sem);
|
||||
args[0] = hrdata.val.v64;
|
||||
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
static void spapr_rng_instance_init(Object *obj)
|
||||
{
|
||||
sPAPRRngState *rngstate = SPAPR_RNG(obj);
|
||||
|
||||
if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL) != NULL) {
|
||||
error_report("spapr-rng can not be instantiated twice!");
|
||||
return;
|
||||
}
|
||||
|
||||
object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
|
||||
(Object **)&rngstate->backend,
|
||||
object_property_allow_set_link,
|
||||
OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
|
||||
object_property_set_description(obj, "rng",
|
||||
"ID of the random number generator backend",
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void spapr_rng_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
|
||||
sPAPRRngState *rngstate = SPAPR_RNG(dev);
|
||||
|
||||
if (rngstate->use_kvm) {
|
||||
if (kvmppc_enable_hwrng() == 0) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* If user specified both, use-kvm and a backend, we fall back to
|
||||
* the backend now. If not, provide an appropriate error message.
|
||||
*/
|
||||
if (!rngstate->backend) {
|
||||
error_setg(errp, "Could not initialize in-kernel H_RANDOM call!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (rngstate->backend) {
|
||||
spapr_register_hypercall(H_RANDOM, h_random);
|
||||
} else {
|
||||
error_setg(errp, "spapr-rng needs an RNG backend!");
|
||||
}
|
||||
}
|
||||
|
||||
int spapr_rng_populate_dt(void *fdt)
|
||||
{
|
||||
int node;
|
||||
int ret;
|
||||
|
||||
node = qemu_fdt_add_subnode(fdt, "/ibm,platform-facilities");
|
||||
if (node <= 0) {
|
||||
return -1;
|
||||
}
|
||||
ret = fdt_setprop_string(fdt, node, "device_type",
|
||||
"ibm,platform-facilities");
|
||||
ret |= fdt_setprop_cell(fdt, node, "#address-cells", 0x1);
|
||||
ret |= fdt_setprop_cell(fdt, node, "#size-cells", 0x0);
|
||||
|
||||
node = fdt_add_subnode(fdt, node, "ibm,random-v1");
|
||||
if (node <= 0) {
|
||||
return -1;
|
||||
}
|
||||
ret |= fdt_setprop_string(fdt, node, "compatible", "ibm,random");
|
||||
|
||||
return ret ? -1 : 0;
|
||||
}
|
||||
|
||||
static Property spapr_rng_properties[] = {
|
||||
DEFINE_PROP_BOOL("use-kvm", sPAPRRngState, use_kvm, false),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void spapr_rng_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
dc->realize = spapr_rng_realize;
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
dc->props = spapr_rng_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo spapr_rng_info = {
|
||||
.name = TYPE_SPAPR_RNG,
|
||||
.parent = TYPE_DEVICE,
|
||||
.instance_size = sizeof(sPAPRRngState),
|
||||
.instance_init = spapr_rng_instance_init,
|
||||
.class_init = spapr_rng_class_init,
|
||||
};
|
||||
|
||||
static void spapr_rng_register_type(void)
|
||||
{
|
||||
type_register_static(&spapr_rng_info);
|
||||
}
|
||||
type_init(spapr_rng_register_type)
|
||||
+37
-20
@@ -34,6 +34,7 @@
|
||||
#include "hw/ppc/spapr.h"
|
||||
#include "hw/ppc/spapr_vio.h"
|
||||
#include "qapi-event.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
#include <libfdt.h>
|
||||
#include "hw/ppc/spapr_drc.h"
|
||||
@@ -240,8 +241,14 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
|
||||
|
||||
switch (parameter) {
|
||||
case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS: {
|
||||
char *param_val = g_strdup_printf("MaxEntCap=%d,MaxPlatProcs=%d",
|
||||
max_cpus, smp_cpus);
|
||||
char *param_val = g_strdup_printf("MaxEntCap=%d,"
|
||||
"DesMem=%llu,"
|
||||
"DesProcs=%d,"
|
||||
"MaxPlatProcs=%d",
|
||||
max_cpus,
|
||||
current_machine->ram_size / M_BYTE,
|
||||
smp_cpus,
|
||||
max_cpus);
|
||||
rtas_st_buffer(buffer, length, (uint8_t *)param_val, strlen(param_val));
|
||||
g_free(param_val);
|
||||
break;
|
||||
@@ -365,12 +372,13 @@ static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
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) {
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
ret = RTAS_OUT_PARAM_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sensor_type = rtas_ld(args, 0);
|
||||
@@ -386,8 +394,8 @@ static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
if (!drc) {
|
||||
DPRINTF("rtas_set_indicator: invalid sensor/DRC index: %xh\n",
|
||||
sensor_index);
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
ret = RTAS_OUT_PARAM_ERROR;
|
||||
goto out;
|
||||
}
|
||||
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
|
||||
|
||||
@@ -406,19 +414,20 @@ static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
spapr_ccs_remove(spapr, ccs);
|
||||
}
|
||||
}
|
||||
drck->set_isolation_state(drc, sensor_state);
|
||||
ret = drck->set_isolation_state(drc, sensor_state);
|
||||
break;
|
||||
case RTAS_SENSOR_TYPE_DR:
|
||||
drck->set_indicator_state(drc, sensor_state);
|
||||
ret = drck->set_indicator_state(drc, sensor_state);
|
||||
break;
|
||||
case RTAS_SENSOR_TYPE_ALLOCATION_STATE:
|
||||
drck->set_allocation_state(drc, sensor_state);
|
||||
ret = drck->set_allocation_state(drc, sensor_state);
|
||||
break;
|
||||
default:
|
||||
goto out_unimplemented;
|
||||
}
|
||||
|
||||
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
|
||||
out:
|
||||
rtas_st(rets, 0, ret);
|
||||
return;
|
||||
|
||||
out_unimplemented:
|
||||
@@ -435,13 +444,14 @@ static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
{
|
||||
uint32_t sensor_type;
|
||||
uint32_t sensor_index;
|
||||
uint32_t sensor_state = 0;
|
||||
sPAPRDRConnector *drc;
|
||||
sPAPRDRConnectorClass *drck;
|
||||
uint32_t entity_sense;
|
||||
uint32_t ret = RTAS_OUT_SUCCESS;
|
||||
|
||||
if (nargs != 2 || nret != 2) {
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
ret = RTAS_OUT_PARAM_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sensor_type = rtas_ld(args, 0);
|
||||
@@ -451,22 +461,23 @@ static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
/* currently only DR-related sensors are implemented */
|
||||
DPRINTF("rtas_get_sensor_state: sensor/indicator not implemented: %d\n",
|
||||
sensor_type);
|
||||
rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
|
||||
return;
|
||||
ret = RTAS_OUT_NOT_SUPPORTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
drc = spapr_dr_connector_by_index(sensor_index);
|
||||
if (!drc) {
|
||||
DPRINTF("rtas_get_sensor_state: invalid sensor/DRC index: %xh\n",
|
||||
sensor_index);
|
||||
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
|
||||
return;
|
||||
ret = RTAS_OUT_PARAM_ERROR;
|
||||
goto out;
|
||||
}
|
||||
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
|
||||
entity_sense = drck->entity_sense(drc);
|
||||
ret = drck->entity_sense(drc, &sensor_state);
|
||||
|
||||
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
|
||||
rtas_st(rets, 1, entity_sense);
|
||||
out:
|
||||
rtas_st(rets, 0, ret);
|
||||
rtas_st(rets, 1, sensor_state);
|
||||
}
|
||||
|
||||
/* configure-connector work area offsets, int32_t units for field
|
||||
@@ -515,6 +526,12 @@ static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
|
||||
|
||||
drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
|
||||
fdt = drck->get_fdt(drc, NULL);
|
||||
if (!fdt) {
|
||||
DPRINTF("rtas_ibm_configure_connector: Missing FDT for DRC index: %xh\n",
|
||||
drc_index);
|
||||
rc = SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ccs = spapr_ccs_find(spapr, drc_index);
|
||||
if (!ccs) {
|
||||
|
||||
+46
-11
@@ -5,6 +5,7 @@
|
||||
#include "hw/boards.h"
|
||||
#include "hw/ppc/xics.h"
|
||||
#include "hw/ppc/spapr_drc.h"
|
||||
#include "hw/mem/pc-dimm.h"
|
||||
|
||||
struct VIOsPAPRBus;
|
||||
struct sPAPRPHBState;
|
||||
@@ -34,6 +35,7 @@ struct sPAPRMachineClass {
|
||||
MachineClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
bool dr_lmb_enabled; /* enable dynamic-reconfig/hotplug of LMBs */
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -76,6 +78,7 @@ struct sPAPRMachineState {
|
||||
|
||||
/*< public >*/
|
||||
char *kvm_type;
|
||||
MemoryHotplugState hotplug_memory;
|
||||
};
|
||||
|
||||
#define H_SUCCESS 0
|
||||
@@ -331,6 +334,7 @@ struct sPAPRMachineState {
|
||||
#define H_SET_MPP 0x2D0
|
||||
#define H_GET_MPP 0x2D4
|
||||
#define H_XIRR_X 0x2FC
|
||||
#define H_RANDOM 0x300
|
||||
#define H_SET_MODE 0x31C
|
||||
#define MAX_HCALL_OPCODE H_SET_MODE
|
||||
|
||||
@@ -353,15 +357,10 @@ typedef struct sPAPRDeviceTreeUpdateHeader {
|
||||
uint32_t version_id;
|
||||
} sPAPRDeviceTreeUpdateHeader;
|
||||
|
||||
/*#define DEBUG_SPAPR_HCALLS*/
|
||||
|
||||
#ifdef DEBUG_SPAPR_HCALLS
|
||||
#define hcall_dprintf(fmt, ...) \
|
||||
do { fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define hcall_dprintf(fmt, ...) \
|
||||
do { } while (0)
|
||||
#endif
|
||||
do { \
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: " fmt, __func__, ## __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
typedef target_ulong (*spapr_hcall_fn)(PowerPCCPU *cpu, sPAPRMachineState *sm,
|
||||
target_ulong opcode,
|
||||
@@ -414,6 +413,7 @@ int spapr_allocate_irq_block(int num, bool lsi, bool msi);
|
||||
#define RTAS_OUT_BUSY -2
|
||||
#define RTAS_OUT_PARAM_ERROR -3
|
||||
#define RTAS_OUT_NOT_SUPPORTED -3
|
||||
#define RTAS_OUT_NO_SUCH_INDICATOR -3
|
||||
#define RTAS_OUT_NOT_AUTHORIZED -9002
|
||||
|
||||
/* RTAS tokens */
|
||||
@@ -494,6 +494,11 @@ static inline uint32_t rtas_ld(target_ulong phys, int n)
|
||||
return ldl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4*n));
|
||||
}
|
||||
|
||||
static inline uint64_t rtas_ldq(target_ulong phys, int n)
|
||||
{
|
||||
return (uint64_t)rtas_ld(phys, n) << 32 | rtas_ld(phys, n + 1);
|
||||
}
|
||||
|
||||
static inline void rtas_st(target_ulong phys, int n, uint32_t val)
|
||||
{
|
||||
stl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4*n), val);
|
||||
@@ -577,7 +582,8 @@ struct sPAPREventLogEntry {
|
||||
void spapr_events_init(sPAPRMachineState *sm);
|
||||
void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
|
||||
int spapr_h_cas_compose_response(sPAPRMachineState *sm,
|
||||
target_ulong addr, target_ulong size);
|
||||
target_ulong addr, target_ulong size,
|
||||
bool cpu_update, bool memory_update);
|
||||
sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
|
||||
uint64_t bus_offset,
|
||||
uint32_t page_shift,
|
||||
@@ -589,8 +595,12 @@ int spapr_dma_dt(void *fdt, int node_off, const char *propname,
|
||||
int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
|
||||
sPAPRTCETable *tcet);
|
||||
void spapr_pci_switch_vga(bool big_endian);
|
||||
void spapr_hotplug_req_add_event(sPAPRDRConnector *drc);
|
||||
void spapr_hotplug_req_remove_event(sPAPRDRConnector *drc);
|
||||
void spapr_hotplug_req_add_by_index(sPAPRDRConnector *drc);
|
||||
void spapr_hotplug_req_remove_by_index(sPAPRDRConnector *drc);
|
||||
void spapr_hotplug_req_add_by_count(sPAPRDRConnectorType drc_type,
|
||||
uint32_t count);
|
||||
void spapr_hotplug_req_remove_by_count(sPAPRDRConnectorType drc_type,
|
||||
uint32_t count);
|
||||
|
||||
/* rtas-configure-connector state */
|
||||
struct sPAPRConfigureConnectorState {
|
||||
@@ -603,10 +613,35 @@ struct sPAPRConfigureConnectorState {
|
||||
void spapr_ccs_reset_hook(void *opaque);
|
||||
|
||||
#define TYPE_SPAPR_RTC "spapr-rtc"
|
||||
#define TYPE_SPAPR_RNG "spapr-rng"
|
||||
|
||||
void spapr_rtc_read(DeviceState *dev, struct tm *tm, uint32_t *ns);
|
||||
int spapr_rtc_import_offset(DeviceState *dev, int64_t legacy_offset);
|
||||
|
||||
int spapr_rng_populate_dt(void *fdt);
|
||||
|
||||
#define SPAPR_MEMORY_BLOCK_SIZE (1 << 28) /* 256MB */
|
||||
|
||||
/*
|
||||
* This defines the maximum number of DIMM slots we can have for sPAPR
|
||||
* guest. This is not defined by sPAPR but we are defining it to 32 slots
|
||||
* based on default number of slots provided by PowerPC kernel.
|
||||
*/
|
||||
#define SPAPR_MAX_RAM_SLOTS 32
|
||||
|
||||
/* 1GB alignment for hotplug memory region */
|
||||
#define SPAPR_HOTPLUG_MEM_ALIGN (1ULL << 30)
|
||||
|
||||
/*
|
||||
* Number of 32 bit words in each LMB list entry in ibm,dynamic-memory
|
||||
* property under ibm,dynamic-reconfiguration-memory node.
|
||||
*/
|
||||
#define SPAPR_DR_LMB_LIST_ENTRY_SIZE 6
|
||||
|
||||
/*
|
||||
* This flag value defines the LMB as assigned in ibm,dynamic-memory
|
||||
* property under ibm,dynamic-reconfiguration-memory node.
|
||||
*/
|
||||
#define SPAPR_LMB_FLAGS_ASSIGNED 0x00000008
|
||||
|
||||
#endif /* !defined (__HW_SPAPR_H__) */
|
||||
|
||||
+15
-14
@@ -119,13 +119,14 @@ typedef enum {
|
||||
} sPAPRDREntitySense;
|
||||
|
||||
typedef enum {
|
||||
SPAPR_DR_CC_RESPONSE_NEXT_SIB = 1, /* currently unused */
|
||||
SPAPR_DR_CC_RESPONSE_NEXT_CHILD = 2,
|
||||
SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY = 3,
|
||||
SPAPR_DR_CC_RESPONSE_PREV_PARENT = 4,
|
||||
SPAPR_DR_CC_RESPONSE_SUCCESS = 0,
|
||||
SPAPR_DR_CC_RESPONSE_ERROR = -1,
|
||||
SPAPR_DR_CC_RESPONSE_CONTINUE = -2,
|
||||
SPAPR_DR_CC_RESPONSE_NEXT_SIB = 1, /* currently unused */
|
||||
SPAPR_DR_CC_RESPONSE_NEXT_CHILD = 2,
|
||||
SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY = 3,
|
||||
SPAPR_DR_CC_RESPONSE_PREV_PARENT = 4,
|
||||
SPAPR_DR_CC_RESPONSE_SUCCESS = 0,
|
||||
SPAPR_DR_CC_RESPONSE_ERROR = -1,
|
||||
SPAPR_DR_CC_RESPONSE_CONTINUE = -2,
|
||||
SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE = -9003,
|
||||
} sPAPRDRCCResponse;
|
||||
|
||||
typedef void (spapr_drc_detach_cb)(DeviceState *d, void *opaque);
|
||||
@@ -164,17 +165,17 @@ typedef struct sPAPRDRConnectorClass {
|
||||
/*< public >*/
|
||||
|
||||
/* accessors for guest-visible (generally via RTAS) DR state */
|
||||
int (*set_isolation_state)(sPAPRDRConnector *drc,
|
||||
sPAPRDRIsolationState state);
|
||||
int (*set_indicator_state)(sPAPRDRConnector *drc,
|
||||
sPAPRDRIndicatorState state);
|
||||
int (*set_allocation_state)(sPAPRDRConnector *drc,
|
||||
sPAPRDRAllocationState state);
|
||||
uint32_t (*set_isolation_state)(sPAPRDRConnector *drc,
|
||||
sPAPRDRIsolationState state);
|
||||
uint32_t (*set_indicator_state)(sPAPRDRConnector *drc,
|
||||
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);
|
||||
|
||||
sPAPRDREntitySense (*entity_sense)(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);
|
||||
|
||||
+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-20150429.
|
||||
built from git tag qemu-slof-20150813.
|
||||
|
||||
- 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.
+1
-1
Submodule roms/SLOF updated: 7d766a3ac9...811277ac91
@@ -1953,6 +1953,11 @@ void kvmppc_enable_logical_ci_hcalls(void)
|
||||
kvmppc_enable_hcall(kvm_state, H_LOGICAL_CI_STORE);
|
||||
}
|
||||
|
||||
void kvmppc_enable_set_mode_hcall(void)
|
||||
{
|
||||
kvmppc_enable_hcall(kvm_state, H_SET_MODE);
|
||||
}
|
||||
|
||||
void kvmppc_set_papr(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
@@ -2484,3 +2489,12 @@ int kvm_arch_msi_data_to_gsi(uint32_t data)
|
||||
{
|
||||
return data & 0xffff;
|
||||
}
|
||||
|
||||
int kvmppc_enable_hwrng(void)
|
||||
{
|
||||
if (!kvm_enabled() || !kvm_check_extension(kvm_state, KVM_CAP_PPC_HWRNG)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return kvmppc_enable_hcall(kvm_state, H_RANDOM);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ int kvmppc_get_hasidle(CPUPPCState *env);
|
||||
int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len);
|
||||
int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level);
|
||||
void kvmppc_enable_logical_ci_hcalls(void);
|
||||
void kvmppc_enable_set_mode_hcall(void);
|
||||
void kvmppc_set_papr(PowerPCCPU *cpu);
|
||||
int kvmppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version);
|
||||
void kvmppc_set_mpic_proxy(PowerPCCPU *cpu, int mpic_proxy);
|
||||
@@ -53,6 +54,7 @@ void kvmppc_hash64_free_pteg(uint64_t token);
|
||||
void kvmppc_hash64_write_pte(CPUPPCState *env, target_ulong pte_index,
|
||||
target_ulong pte0, target_ulong pte1);
|
||||
bool kvmppc_has_cap_fixup_hcalls(void);
|
||||
int kvmppc_enable_hwrng(void);
|
||||
|
||||
#else
|
||||
|
||||
@@ -110,6 +112,10 @@ static inline void kvmppc_enable_logical_ci_hcalls(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void kvmppc_enable_set_mode_hcall(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void kvmppc_set_papr(PowerPCCPU *cpu)
|
||||
{
|
||||
}
|
||||
@@ -246,6 +252,10 @@ static inline bool kvmppc_has_cap_fixup_hcalls(void)
|
||||
abort();
|
||||
}
|
||||
|
||||
static inline int kvmppc_enable_hwrng(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_KVM
|
||||
|
||||
Reference in New Issue
Block a user