1*bbf5c878SMichael Roth /* 2*bbf5c878SMichael Roth * QEMU SPAPR Dynamic Reconfiguration Connector Implementation 3*bbf5c878SMichael Roth * 4*bbf5c878SMichael Roth * Copyright IBM Corp. 2014 5*bbf5c878SMichael Roth * 6*bbf5c878SMichael Roth * Authors: 7*bbf5c878SMichael Roth * Michael Roth <mdroth@linux.vnet.ibm.com> 8*bbf5c878SMichael Roth * 9*bbf5c878SMichael Roth * This work is licensed under the terms of the GNU GPL, version 2 or later. 10*bbf5c878SMichael Roth * See the COPYING file in the top-level directory. 11*bbf5c878SMichael Roth */ 12*bbf5c878SMichael Roth #if !defined(__HW_SPAPR_DRC_H__) 13*bbf5c878SMichael Roth #define __HW_SPAPR_DRC_H__ 14*bbf5c878SMichael Roth 15*bbf5c878SMichael Roth #include "qom/object.h" 16*bbf5c878SMichael Roth #include "hw/qdev.h" 17*bbf5c878SMichael Roth #include "libfdt.h" 18*bbf5c878SMichael Roth 19*bbf5c878SMichael Roth #define TYPE_SPAPR_DR_CONNECTOR "spapr-dr-connector" 20*bbf5c878SMichael Roth #define SPAPR_DR_CONNECTOR_GET_CLASS(obj) \ 21*bbf5c878SMichael Roth OBJECT_GET_CLASS(sPAPRDRConnectorClass, obj, TYPE_SPAPR_DR_CONNECTOR) 22*bbf5c878SMichael Roth #define SPAPR_DR_CONNECTOR_CLASS(klass) \ 23*bbf5c878SMichael Roth OBJECT_CLASS_CHECK(sPAPRDRConnectorClass, klass, \ 24*bbf5c878SMichael Roth TYPE_SPAPR_DR_CONNECTOR) 25*bbf5c878SMichael Roth #define SPAPR_DR_CONNECTOR(obj) OBJECT_CHECK(sPAPRDRConnector, (obj), \ 26*bbf5c878SMichael Roth TYPE_SPAPR_DR_CONNECTOR) 27*bbf5c878SMichael Roth 28*bbf5c878SMichael Roth /* 29*bbf5c878SMichael Roth * Various hotplug types managed by sPAPRDRConnector 30*bbf5c878SMichael Roth * 31*bbf5c878SMichael Roth * these are somewhat arbitrary, but to make things easier 32*bbf5c878SMichael Roth * when generating DRC indexes later we've aligned the bit 33*bbf5c878SMichael Roth * positions with the values used to assign DRC indexes on 34*bbf5c878SMichael Roth * pSeries. we use those values as bit shifts to allow for 35*bbf5c878SMichael Roth * the OR'ing of these values in various QEMU routines, but 36*bbf5c878SMichael Roth * for values exposed to the guest (via DRC indexes for 37*bbf5c878SMichael Roth * instance) we will use the shift amounts. 38*bbf5c878SMichael Roth */ 39*bbf5c878SMichael Roth typedef enum { 40*bbf5c878SMichael Roth SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU = 1, 41*bbf5c878SMichael Roth SPAPR_DR_CONNECTOR_TYPE_SHIFT_PHB = 2, 42*bbf5c878SMichael Roth SPAPR_DR_CONNECTOR_TYPE_SHIFT_VIO = 3, 43*bbf5c878SMichael Roth SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI = 4, 44*bbf5c878SMichael Roth SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB = 8, 45*bbf5c878SMichael Roth } sPAPRDRConnectorTypeShift; 46*bbf5c878SMichael Roth 47*bbf5c878SMichael Roth typedef enum { 48*bbf5c878SMichael Roth SPAPR_DR_CONNECTOR_TYPE_ANY = ~0, 49*bbf5c878SMichael Roth SPAPR_DR_CONNECTOR_TYPE_CPU = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU, 50*bbf5c878SMichael Roth SPAPR_DR_CONNECTOR_TYPE_PHB = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_PHB, 51*bbf5c878SMichael Roth SPAPR_DR_CONNECTOR_TYPE_VIO = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_VIO, 52*bbf5c878SMichael Roth SPAPR_DR_CONNECTOR_TYPE_PCI = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI, 53*bbf5c878SMichael Roth SPAPR_DR_CONNECTOR_TYPE_LMB = 1 << SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB, 54*bbf5c878SMichael Roth } sPAPRDRConnectorType; 55*bbf5c878SMichael Roth 56*bbf5c878SMichael Roth /* 57*bbf5c878SMichael Roth * set via set-indicator RTAS calls 58*bbf5c878SMichael Roth * as documented by PAPR+ 2.7 13.5.3.4, Table 177 59*bbf5c878SMichael Roth * 60*bbf5c878SMichael Roth * isolated: put device under firmware control 61*bbf5c878SMichael Roth * unisolated: claim OS control of device (may or may not be in use) 62*bbf5c878SMichael Roth */ 63*bbf5c878SMichael Roth typedef enum { 64*bbf5c878SMichael Roth SPAPR_DR_ISOLATION_STATE_ISOLATED = 0, 65*bbf5c878SMichael Roth SPAPR_DR_ISOLATION_STATE_UNISOLATED = 1 66*bbf5c878SMichael Roth } sPAPRDRIsolationState; 67*bbf5c878SMichael Roth 68*bbf5c878SMichael Roth /* 69*bbf5c878SMichael Roth * set via set-indicator RTAS calls 70*bbf5c878SMichael Roth * as documented by PAPR+ 2.7 13.5.3.4, Table 177 71*bbf5c878SMichael Roth * 72*bbf5c878SMichael Roth * unusable: mark device as unavailable to OS 73*bbf5c878SMichael Roth * usable: mark device as available to OS 74*bbf5c878SMichael Roth * exchange: (currently unused) 75*bbf5c878SMichael Roth * recover: (currently unused) 76*bbf5c878SMichael Roth */ 77*bbf5c878SMichael Roth typedef enum { 78*bbf5c878SMichael Roth SPAPR_DR_ALLOCATION_STATE_UNUSABLE = 0, 79*bbf5c878SMichael Roth SPAPR_DR_ALLOCATION_STATE_USABLE = 1, 80*bbf5c878SMichael Roth SPAPR_DR_ALLOCATION_STATE_EXCHANGE = 2, 81*bbf5c878SMichael Roth SPAPR_DR_ALLOCATION_STATE_RECOVER = 3 82*bbf5c878SMichael Roth } sPAPRDRAllocationState; 83*bbf5c878SMichael Roth 84*bbf5c878SMichael Roth /* 85*bbf5c878SMichael Roth * LED/visual indicator state 86*bbf5c878SMichael Roth * 87*bbf5c878SMichael Roth * set via set-indicator RTAS calls 88*bbf5c878SMichael Roth * as documented by PAPR+ 2.7 13.5.3.4, Table 177, 89*bbf5c878SMichael Roth * and PAPR+ 2.7 13.5.4.1, Table 180 90*bbf5c878SMichael Roth * 91*bbf5c878SMichael Roth * inactive: hotpluggable entity inactive and safely removable 92*bbf5c878SMichael Roth * active: hotpluggable entity in use and not safely removable 93*bbf5c878SMichael Roth * identify: (currently unused) 94*bbf5c878SMichael Roth * action: (currently unused) 95*bbf5c878SMichael Roth */ 96*bbf5c878SMichael Roth typedef enum { 97*bbf5c878SMichael Roth SPAPR_DR_INDICATOR_STATE_INACTIVE = 0, 98*bbf5c878SMichael Roth SPAPR_DR_INDICATOR_STATE_ACTIVE = 1, 99*bbf5c878SMichael Roth SPAPR_DR_INDICATOR_STATE_IDENTIFY = 2, 100*bbf5c878SMichael Roth SPAPR_DR_INDICATOR_STATE_ACTION = 3, 101*bbf5c878SMichael Roth } sPAPRDRIndicatorState; 102*bbf5c878SMichael Roth 103*bbf5c878SMichael Roth /* 104*bbf5c878SMichael Roth * returned via get-sensor-state RTAS calls 105*bbf5c878SMichael Roth * as documented by PAPR+ 2.7 13.5.3.3, Table 175: 106*bbf5c878SMichael Roth * 107*bbf5c878SMichael Roth * empty: connector slot empty (e.g. empty hotpluggable PCI slot) 108*bbf5c878SMichael Roth * present: connector slot populated and device available to OS 109*bbf5c878SMichael Roth * unusable: device not currently available to OS 110*bbf5c878SMichael Roth * exchange: (currently unused) 111*bbf5c878SMichael Roth * recover: (currently unused) 112*bbf5c878SMichael Roth */ 113*bbf5c878SMichael Roth typedef enum { 114*bbf5c878SMichael Roth SPAPR_DR_ENTITY_SENSE_EMPTY = 0, 115*bbf5c878SMichael Roth SPAPR_DR_ENTITY_SENSE_PRESENT = 1, 116*bbf5c878SMichael Roth SPAPR_DR_ENTITY_SENSE_UNUSABLE = 2, 117*bbf5c878SMichael Roth SPAPR_DR_ENTITY_SENSE_EXCHANGE = 3, 118*bbf5c878SMichael Roth SPAPR_DR_ENTITY_SENSE_RECOVER = 4, 119*bbf5c878SMichael Roth } sPAPRDREntitySense; 120*bbf5c878SMichael Roth 121*bbf5c878SMichael Roth typedef enum { 122*bbf5c878SMichael Roth SPAPR_DR_CC_RESPONSE_NEXT_SIB = 1, /* currently unused */ 123*bbf5c878SMichael Roth SPAPR_DR_CC_RESPONSE_NEXT_CHILD = 2, 124*bbf5c878SMichael Roth SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY = 3, 125*bbf5c878SMichael Roth SPAPR_DR_CC_RESPONSE_PREV_PARENT = 4, 126*bbf5c878SMichael Roth SPAPR_DR_CC_RESPONSE_SUCCESS = 0, 127*bbf5c878SMichael Roth SPAPR_DR_CC_RESPONSE_ERROR = -1, 128*bbf5c878SMichael Roth SPAPR_DR_CC_RESPONSE_CONTINUE = -2, 129*bbf5c878SMichael Roth } sPAPRDRCCResponse; 130*bbf5c878SMichael Roth 131*bbf5c878SMichael Roth typedef void (spapr_drc_detach_cb)(DeviceState *d, void *opaque); 132*bbf5c878SMichael Roth 133*bbf5c878SMichael Roth typedef struct sPAPRDRConnector { 134*bbf5c878SMichael Roth /*< private >*/ 135*bbf5c878SMichael Roth DeviceState parent; 136*bbf5c878SMichael Roth 137*bbf5c878SMichael Roth sPAPRDRConnectorType type; 138*bbf5c878SMichael Roth uint32_t id; 139*bbf5c878SMichael Roth Object *owner; 140*bbf5c878SMichael Roth const char *name; 141*bbf5c878SMichael Roth 142*bbf5c878SMichael Roth /* sensor/indicator states */ 143*bbf5c878SMichael Roth uint32_t isolation_state; 144*bbf5c878SMichael Roth uint32_t allocation_state; 145*bbf5c878SMichael Roth uint32_t indicator_state; 146*bbf5c878SMichael Roth 147*bbf5c878SMichael Roth /* configure-connector state */ 148*bbf5c878SMichael Roth void *fdt; 149*bbf5c878SMichael Roth int fdt_start_offset; 150*bbf5c878SMichael Roth bool configured; 151*bbf5c878SMichael Roth 152*bbf5c878SMichael Roth bool awaiting_release; 153*bbf5c878SMichael Roth 154*bbf5c878SMichael Roth /* device pointer, via link property */ 155*bbf5c878SMichael Roth DeviceState *dev; 156*bbf5c878SMichael Roth spapr_drc_detach_cb *detach_cb; 157*bbf5c878SMichael Roth void *detach_cb_opaque; 158*bbf5c878SMichael Roth } sPAPRDRConnector; 159*bbf5c878SMichael Roth 160*bbf5c878SMichael Roth typedef struct sPAPRDRConnectorClass { 161*bbf5c878SMichael Roth /*< private >*/ 162*bbf5c878SMichael Roth DeviceClass parent; 163*bbf5c878SMichael Roth 164*bbf5c878SMichael Roth /*< public >*/ 165*bbf5c878SMichael Roth 166*bbf5c878SMichael Roth /* accessors for guest-visible (generally via RTAS) DR state */ 167*bbf5c878SMichael Roth int (*set_isolation_state)(sPAPRDRConnector *drc, 168*bbf5c878SMichael Roth sPAPRDRIsolationState state); 169*bbf5c878SMichael Roth int (*set_indicator_state)(sPAPRDRConnector *drc, 170*bbf5c878SMichael Roth sPAPRDRIndicatorState state); 171*bbf5c878SMichael Roth int (*set_allocation_state)(sPAPRDRConnector *drc, 172*bbf5c878SMichael Roth sPAPRDRAllocationState state); 173*bbf5c878SMichael Roth uint32_t (*get_index)(sPAPRDRConnector *drc); 174*bbf5c878SMichael Roth uint32_t (*get_type)(sPAPRDRConnector *drc); 175*bbf5c878SMichael Roth const char *(*get_name)(sPAPRDRConnector *drc); 176*bbf5c878SMichael Roth 177*bbf5c878SMichael Roth sPAPRDREntitySense (*entity_sense)(sPAPRDRConnector *drc); 178*bbf5c878SMichael Roth 179*bbf5c878SMichael Roth /* QEMU interfaces for managing FDT/configure-connector */ 180*bbf5c878SMichael Roth const void *(*get_fdt)(sPAPRDRConnector *drc, int *fdt_start_offset); 181*bbf5c878SMichael Roth void (*set_configured)(sPAPRDRConnector *drc); 182*bbf5c878SMichael Roth 183*bbf5c878SMichael Roth /* QEMU interfaces for managing hotplug operations */ 184*bbf5c878SMichael Roth void (*attach)(sPAPRDRConnector *drc, DeviceState *d, void *fdt, 185*bbf5c878SMichael Roth int fdt_start_offset, bool coldplug, Error **errp); 186*bbf5c878SMichael Roth void (*detach)(sPAPRDRConnector *drc, DeviceState *d, 187*bbf5c878SMichael Roth spapr_drc_detach_cb *detach_cb, 188*bbf5c878SMichael Roth void *detach_cb_opaque, Error **errp); 189*bbf5c878SMichael Roth bool (*release_pending)(sPAPRDRConnector *drc); 190*bbf5c878SMichael Roth } sPAPRDRConnectorClass; 191*bbf5c878SMichael Roth 192*bbf5c878SMichael Roth sPAPRDRConnector *spapr_dr_connector_new(Object *owner, 193*bbf5c878SMichael Roth sPAPRDRConnectorType type, 194*bbf5c878SMichael Roth uint32_t id); 195*bbf5c878SMichael Roth sPAPRDRConnector *spapr_dr_connector_by_index(uint32_t index); 196*bbf5c878SMichael Roth sPAPRDRConnector *spapr_dr_connector_by_id(sPAPRDRConnectorType type, 197*bbf5c878SMichael Roth uint32_t id); 198*bbf5c878SMichael Roth 199*bbf5c878SMichael Roth #endif /* __HW_SPAPR_DRC_H__ */ 200