virtio,pc,pci: features, fixes

virtio sound card support
 
 vhost-user: back-end state migration
 
 cxl:
      line length reduction
      enabling fabric management
 
 vhost-vdpa:
      shadow virtqueue hash calculation Support
      shadow virtqueue RSS Support
 
 tests:
     CPU topology related smbios test cases
 
 Fixes, cleanups all over the place
 
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmVKDDoPHG1zdEByZWRo
 YXQuY29tAAoJECgfDbjSjVRpF08H/0Zts8uvkHbgiOEJw4JMHU6/VaCipfIYsp01
 GSfwYOyEsXJ7GIxKWaCiMnWXEm7tebNCPKf3DoUtcAojQj3vuF9XbWBKw/bfRn83
 nGO/iiwbYViSKxkwqUI+Up5YiN9o0M8gBFrY0kScPezbnYmo5u2bcADdEEq6gH68
 D0Ea8i+WmszL891ypvgCDBL2ObDk3qX3vA5Q6J2I+HKX2ofJM59BwaKwS5ghw+IG
 BmbKXUZJNjUQfN9dQ7vJuiuqdknJ2xUzwW2Vn612ffarbOZB1DZ6ruWlrHty5TjX
 0w4IXEJPBgZYbX9oc6zvTQnbLDBJbDU89mnme0TcmNMKWmQKTtc=
 =vEv+
 -----END PGP SIGNATURE-----

Merge tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu into staging

virtio,pc,pci: features, fixes

virtio sound card support

vhost-user: back-end state migration

cxl:
     line length reduction
     enabling fabric management

vhost-vdpa:
     shadow virtqueue hash calculation Support
     shadow virtqueue RSS Support

tests:
    CPU topology related smbios test cases

Fixes, cleanups all over the place

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# -----BEGIN PGP SIGNATURE-----
#
# iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmVKDDoPHG1zdEByZWRo
# YXQuY29tAAoJECgfDbjSjVRpF08H/0Zts8uvkHbgiOEJw4JMHU6/VaCipfIYsp01
# GSfwYOyEsXJ7GIxKWaCiMnWXEm7tebNCPKf3DoUtcAojQj3vuF9XbWBKw/bfRn83
# nGO/iiwbYViSKxkwqUI+Up5YiN9o0M8gBFrY0kScPezbnYmo5u2bcADdEEq6gH68
# D0Ea8i+WmszL891ypvgCDBL2ObDk3qX3vA5Q6J2I+HKX2ofJM59BwaKwS5ghw+IG
# BmbKXUZJNjUQfN9dQ7vJuiuqdknJ2xUzwW2Vn612ffarbOZB1DZ6ruWlrHty5TjX
# 0w4IXEJPBgZYbX9oc6zvTQnbLDBJbDU89mnme0TcmNMKWmQKTtc=
# =vEv+
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 07 Nov 2023 18:06:50 HKT
# gpg:                using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469
# gpg:                issuer "mst@redhat.com"
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full]
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>" [full]
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17  0970 C350 3912 AFBE 8E67
#      Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA  8A0D 281F 0DB8 D28D 5469

* tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu: (63 commits)
  acpi/tests/avocado/bits: enable console logging from bits VM
  acpi/tests/avocado/bits: enforce 32-bit SMBIOS entry point
  hw/cxl: Add tunneled command support to mailbox for switch cci.
  hw/cxl: Add dummy security state get
  hw/cxl/type3: Cleanup multiple CXL_TYPE3() calls in read/write functions
  hw/cxl/mbox: Add Get Background Operation Status Command
  hw/cxl: Add support for device sanitation
  hw/cxl/mbox: Wire up interrupts for background completion
  hw/cxl/mbox: Add support for background operations
  hw/cxl: Implement Physical Ports status retrieval
  hw/pci-bridge/cxl_downstream: Set default link width and link speed
  hw/cxl/mbox: Add Physical Switch Identify command.
  hw/cxl/mbox: Add Information and Status / Identify command
  hw/cxl: Add a switch mailbox CCI function
  hw/pci-bridge/cxl_upstream: Move defintion of device to header.
  hw/cxl/mbox: Generalize the CCI command processing
  hw/cxl/mbox: Pull the CCI definition out of the CXLDeviceState
  hw/cxl/mbox: Split mailbox command payload into separate input and output
  hw/cxl/mbox: Pull the payload out of struct cxl_cmd and make instances constant
  hw/cxl: Fix a QEMU_BUILD_BUG_ON() in switch statement scope issue.
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2023-11-07 18:59:40 +08:00
commit f6b615b52d
53 changed files with 4477 additions and 324 deletions

View file

@ -0,0 +1,235 @@
/*
* VIRTIO Sound Device conforming to
*
* "Virtual I/O Device (VIRTIO) Version 1.2
* Committee Specification Draft 01
* 09 May 2022"
*
* Copyright (c) 2023 Emmanouil Pitsidianakis <manos.pitsidianakis@linaro.org>
* Copyright (C) 2019 OpenSynergy GmbH
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
* top-level directory.
*/
#ifndef QEMU_VIRTIO_SOUND_H
#define QEMU_VIRTIO_SOUND_H
#include "hw/virtio/virtio.h"
#include "audio/audio.h"
#include "standard-headers/linux/virtio_ids.h"
#include "standard-headers/linux/virtio_snd.h"
#define TYPE_VIRTIO_SND "virtio-sound-device"
#define VIRTIO_SND(obj) \
OBJECT_CHECK(VirtIOSound, (obj), TYPE_VIRTIO_SND)
/* CONFIGURATION SPACE */
typedef struct virtio_snd_config virtio_snd_config;
/* COMMON DEFINITIONS */
/* common header for request/response*/
typedef struct virtio_snd_hdr virtio_snd_hdr;
/* event notification */
typedef struct virtio_snd_event virtio_snd_event;
/* common control request to query an item information */
typedef struct virtio_snd_query_info virtio_snd_query_info;
/* JACK CONTROL MESSAGES */
typedef struct virtio_snd_jack_hdr virtio_snd_jack_hdr;
/* jack information structure */
typedef struct virtio_snd_jack_info virtio_snd_jack_info;
/* jack remapping control request */
typedef struct virtio_snd_jack_remap virtio_snd_jack_remap;
/*
* PCM CONTROL MESSAGES
*/
typedef struct virtio_snd_pcm_hdr virtio_snd_pcm_hdr;
/* PCM stream info structure */
typedef struct virtio_snd_pcm_info virtio_snd_pcm_info;
/* set PCM stream params */
typedef struct virtio_snd_pcm_set_params virtio_snd_pcm_set_params;
/* I/O request header */
typedef struct virtio_snd_pcm_xfer virtio_snd_pcm_xfer;
/* I/O request status */
typedef struct virtio_snd_pcm_status virtio_snd_pcm_status;
/* device structs */
typedef struct VirtIOSound VirtIOSound;
typedef struct VirtIOSoundPCMStream VirtIOSoundPCMStream;
typedef struct virtio_snd_ctrl_command virtio_snd_ctrl_command;
typedef struct VirtIOSoundPCM VirtIOSoundPCM;
typedef struct VirtIOSoundPCMBuffer VirtIOSoundPCMBuffer;
/*
* The VirtIO sound spec reuses layouts and values from the High Definition
* Audio spec (virtio/v1.2: 5.14 Sound Device). This struct handles each I/O
* message's buffer (virtio/v1.2: 5.14.6.8 PCM I/O Messages).
*
* In the case of TX (i.e. playback) buffers, we defer reading the raw PCM data
* from the virtqueue until QEMU's sound backsystem calls the output callback.
* This is tracked by the `bool populated;` field, which is set to true when
* data has been read into our own buffer for consumption.
*
* VirtIOSoundPCMBuffer has a dynamic size since it includes the raw PCM data
* in its allocation. It must be initialized and destroyed as follows:
*
* size_t size = [[derived from owned VQ element descriptor sizes]];
* buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer) + size);
* buffer->elem = [[owned VQ element]];
*
* [..]
*
* g_free(buffer->elem);
* g_free(buffer);
*/
struct VirtIOSoundPCMBuffer {
QSIMPLEQ_ENTRY(VirtIOSoundPCMBuffer) entry;
VirtQueueElement *elem;
VirtQueue *vq;
size_t size;
/*
* In TX / Plaback, `offset` represents the first unused position inside
* `data`. If `offset == size` then there are no unused data left.
*/
uint64_t offset;
/* Used for the TX queue for lazy I/O copy from `elem` */
bool populated;
/*
* VirtIOSoundPCMBuffer is an unsized type because it ends with an array of
* bytes. The size of `data` is determined from the I/O message's read-only
* or write-only size when allocating VirtIOSoundPCMBuffer.
*/
uint8_t data[];
};
struct VirtIOSoundPCM {
VirtIOSound *snd;
/*
* PCM parameters are a separate field instead of a VirtIOSoundPCMStream
* field, because the operation of PCM control requests is first
* VIRTIO_SND_R_PCM_SET_PARAMS and then VIRTIO_SND_R_PCM_PREPARE; this
* means that some times we get parameters without having an allocated
* stream yet.
*/
virtio_snd_pcm_set_params *pcm_params;
VirtIOSoundPCMStream **streams;
};
struct VirtIOSoundPCMStream {
VirtIOSoundPCM *pcm;
virtio_snd_pcm_info info;
virtio_snd_pcm_set_params params;
uint32_t id;
/* channel position values (VIRTIO_SND_CHMAP_XXX) */
uint8_t positions[VIRTIO_SND_CHMAP_MAX_SIZE];
VirtIOSound *s;
bool flushing;
audsettings as;
union {
SWVoiceIn *in;
SWVoiceOut *out;
} voice;
QemuMutex queue_mutex;
bool active;
QSIMPLEQ_HEAD(, VirtIOSoundPCMBuffer) queue;
QSIMPLEQ_HEAD(, VirtIOSoundPCMBuffer) invalid;
};
/*
* PCM stream state machine.
* -------------------------
*
* 5.14.6.6.1 PCM Command Lifecycle
* ================================
*
* A PCM stream has the following command lifecycle:
* - `SET PARAMETERS`
* The driver negotiates the stream parameters (format, transport, etc) with
* the device.
* Possible valid transitions: `SET PARAMETERS`, `PREPARE`.
* - `PREPARE`
* The device prepares the stream (allocates resources, etc).
* Possible valid transitions: `SET PARAMETERS`, `PREPARE`, `START`,
* `RELEASE`. Output only: the driver transfers data for pre-buffing.
* - `START`
* The device starts the stream (unmute, putting into running state, etc).
* Possible valid transitions: `STOP`.
* The driver transfers data to/from the stream.
* - `STOP`
* The device stops the stream (mute, putting into non-running state, etc).
* Possible valid transitions: `START`, `RELEASE`.
* - `RELEASE`
* The device releases the stream (frees resources, etc).
* Possible valid transitions: `SET PARAMETERS`, `PREPARE`.
*
* +---------------+ +---------+ +---------+ +-------+ +-------+
* | SetParameters | | Prepare | | Release | | Start | | Stop |
* +---------------+ +---------+ +---------+ +-------+ +-------+
* |- | | | |
* || | | | |
* |< | | | |
* |------------->| | | |
* |<-------------| | | |
* | |- | | |
* | || | | |
* | |< | | |
* | |--------------------->| |
* | |---------->| | |
* | | | |-------->|
* | | | |<--------|
* | | |<-------------------|
* |<-------------------------| | |
* | |<----------| | |
*
* CTRL in the VirtIOSound device
* ==============================
*
* The control messages that affect the state of a stream arrive in the
* `virtio_snd_handle_ctrl()` queue callback and are of type `struct
* virtio_snd_ctrl_command`. They are stored in a queue field in the device
* type, `VirtIOSound`. This allows deferring the CTRL request completion if
* it's not immediately possible due to locking/state reasons.
*
* The CTRL message is finally handled in `process_cmd()`.
*/
struct VirtIOSound {
VirtIODevice parent_obj;
VirtQueue *queues[VIRTIO_SND_VQ_MAX];
uint64_t features;
VirtIOSoundPCM *pcm;
QEMUSoundCard card;
VMChangeStateEntry *vmstate;
virtio_snd_config snd_conf;
QemuMutex cmdq_mutex;
QTAILQ_HEAD(, virtio_snd_ctrl_command) cmdq;
bool processing_cmdq;
};
struct virtio_snd_ctrl_command {
VirtQueueElement *elem;
VirtQueue *vq;
virtio_snd_hdr ctrl;
virtio_snd_hdr resp;
QTAILQ_ENTRY(virtio_snd_ctrl_command) next;
};
#endif

View file

@ -61,4 +61,10 @@ OBJECT_DECLARE_SIMPLE_TYPE(CXLHost, PXB_CXL_HOST)
typedef struct CXLUpstreamPort CXLUpstreamPort;
DECLARE_INSTANCE_CHECKER(CXLUpstreamPort, CXL_USP, TYPE_CXL_USP)
CXLComponentState *cxl_usp_to_cstate(CXLUpstreamPort *usp);
#define TYPE_CXL_DSP "cxl-downstream"
typedef struct CXLDownstreamPort CXLDownstreamPort;
DECLARE_INSTANCE_CHECKER(CXLDownstreamPort, CXL_DSP, TYPE_CXL_DSP)
#endif

View file

@ -26,7 +26,8 @@ enum reg_type {
CXL2_LOGICAL_DEVICE,
CXL2_ROOT_PORT,
CXL2_UPSTREAM_PORT,
CXL2_DOWNSTREAM_PORT
CXL2_DOWNSTREAM_PORT,
CXL3_SWITCH_MAILBOX_CCI,
};
/*
@ -175,7 +176,8 @@ HDM_DECODER_INIT(3);
(CXL_IDE_REGISTERS_OFFSET + CXL_IDE_REGISTERS_SIZE)
#define CXL_SNOOP_REGISTERS_SIZE 0x8
QEMU_BUILD_BUG_MSG((CXL_SNOOP_REGISTERS_OFFSET + CXL_SNOOP_REGISTERS_SIZE) >= 0x1000,
QEMU_BUILD_BUG_MSG((CXL_SNOOP_REGISTERS_OFFSET +
CXL_SNOOP_REGISTERS_SIZE) >= 0x1000,
"No space for registers");
typedef struct component_registers {

View file

@ -111,6 +111,20 @@ typedef enum {
CXL_MBOX_MAX = 0x17
} CXLRetCode;
typedef struct CXLCCI CXLCCI;
typedef struct cxl_device_state CXLDeviceState;
struct cxl_cmd;
typedef CXLRetCode (*opcode_handler)(const struct cxl_cmd *cmd,
uint8_t *payload_in, size_t len_in,
uint8_t *payload_out, size_t *len_out,
CXLCCI *cci);
struct cxl_cmd {
const char *name;
opcode_handler handler;
ssize_t in;
uint16_t effect; /* Reported in CEL */
};
typedef struct CXLEvent {
CXLEventRecordRaw data;
QSIMPLEQ_ENTRY(CXLEvent) node;
@ -127,6 +141,31 @@ typedef struct CXLEventLog {
QSIMPLEQ_HEAD(, CXLEvent) events;
} CXLEventLog;
typedef struct CXLCCI {
const struct cxl_cmd (*cxl_cmd_set)[256];
struct cel_log {
uint16_t opcode;
uint16_t effect;
} cel_log[1 << 16];
size_t cel_size;
/* background command handling (times in ms) */
struct {
uint16_t opcode;
uint16_t complete_pct;
uint16_t ret_code; /* Current value of retcode */
uint64_t starttime;
/* set by each bg cmd, cleared by the bg_timer when complete */
uint64_t runtime;
QEMUTimer *timer;
} bg;
size_t payload_max;
/* Pointer to device hosting the CCI */
DeviceState *d;
/* Pointer to the device hosting the protocol conversion */
DeviceState *intf;
} CXLCCI;
typedef struct cxl_device_state {
MemoryRegion device_registers;
@ -154,17 +193,13 @@ typedef struct cxl_device_state {
struct {
MemoryRegion mailbox;
uint16_t payload_size;
uint8_t mbox_msi_n;
union {
uint8_t mbox_reg_state[CXL_MAILBOX_REGISTERS_LENGTH];
uint16_t mbox_reg_state16[CXL_MAILBOX_REGISTERS_LENGTH / 2];
uint32_t mbox_reg_state32[CXL_MAILBOX_REGISTERS_LENGTH / 4];
uint64_t mbox_reg_state64[CXL_MAILBOX_REGISTERS_LENGTH / 8];
};
struct cel_log {
uint16_t opcode;
uint16_t effect;
} cel_log[1 << 16];
size_t cel_size;
};
struct {
@ -178,21 +213,26 @@ typedef struct cxl_device_state {
uint64_t pmem_size;
uint64_t vmem_size;
const struct cxl_cmd (*cxl_cmd_set)[256];
CXLEventLog event_logs[CXL_EVENT_TYPE_MAX];
} CXLDeviceState;
/* Initialize the register block for a device */
void cxl_device_register_block_init(Object *obj, CXLDeviceState *dev);
void cxl_device_register_block_init(Object *obj, CXLDeviceState *dev,
CXLCCI *cci);
typedef struct CXLType3Dev CXLType3Dev;
typedef struct CSWMBCCIDev CSWMBCCIDev;
/* Set up default values for the register block */
void cxl_device_register_init_common(CXLDeviceState *dev);
void cxl_device_register_init_t3(CXLType3Dev *ct3d);
void cxl_device_register_init_swcci(CSWMBCCIDev *sw);
/*
* CXL 2.0 - 8.2.8.1 including errata F4
* Documented as a 128 bit register, but 64 bit accesses and the second
* 64 bits are currently reserved.
*/
REG64(CXL_DEV_CAP_ARRAY, 0) /* Documented as 128 bit register but 64 byte accesses */
REG64(CXL_DEV_CAP_ARRAY, 0)
FIELD(CXL_DEV_CAP_ARRAY, CAP_ID, 0, 16)
FIELD(CXL_DEV_CAP_ARRAY, CAP_VERSION, 16, 8)
FIELD(CXL_DEV_CAP_ARRAY, CAP_COUNT, 32, 16)
@ -231,8 +271,20 @@ CXL_DEVICE_CAPABILITY_HEADER_REGISTER(MEMORY_DEVICE,
CXL_DEVICE_CAP_HDR1_OFFSET +
CXL_DEVICE_CAP_REG_SIZE * 2)
void cxl_initialize_mailbox(CXLDeviceState *cxl_dstate);
void cxl_process_mailbox(CXLDeviceState *cxl_dstate);
void cxl_initialize_mailbox_t3(CXLCCI *cci, DeviceState *d, size_t payload_max);
void cxl_initialize_mailbox_swcci(CXLCCI *cci, DeviceState *intf,
DeviceState *d, size_t payload_max);
void cxl_init_cci(CXLCCI *cci, size_t payload_max);
int cxl_process_cci_message(CXLCCI *cci, uint8_t set, uint8_t cmd,
size_t len_in, uint8_t *pl_in,
size_t *len_out, uint8_t *pl_out,
bool *bg_started);
void cxl_initialize_t3_fm_owned_ld_mctpcci(CXLCCI *cci, DeviceState *d,
DeviceState *intf,
size_t payload_max);
void cxl_initialize_t3_ld_cci(CXLCCI *cci, DeviceState *d,
DeviceState *intf, size_t payload_max);
#define cxl_device_cap_init(dstate, reg, cap_id, ver) \
do { \
@ -297,6 +349,23 @@ REG64(CXL_MEM_DEV_STS, 0)
FIELD(CXL_MEM_DEV_STS, MBOX_READY, 4, 1)
FIELD(CXL_MEM_DEV_STS, RESET_NEEDED, 5, 3)
static inline void __toggle_media(CXLDeviceState *cxl_dstate, int val)
{
uint64_t dev_status_reg;
dev_status_reg = FIELD_DP64(0, CXL_MEM_DEV_STS, MEDIA_STATUS, val);
cxl_dstate->mbox_reg_state64[R_CXL_MEM_DEV_STS] = dev_status_reg;
}
#define cxl_dev_disable_media(cxlds) \
do { __toggle_media((cxlds), 0x3); } while (0)
#define cxl_dev_enable_media(cxlds) \
do { __toggle_media((cxlds), 0x1); } while (0)
static inline bool sanitize_running(CXLCCI *cci)
{
return !!cci->bg.runtime && cci->bg.opcode == 0x4400;
}
typedef struct CXLError {
QTAILQ_ENTRY(CXLError) node;
int type; /* Error code as per FE definition */
@ -333,6 +402,10 @@ struct CXLType3Dev {
AddressSpace hostpmem_as;
CXLComponentState cxl_cstate;
CXLDeviceState cxl_dstate;
CXLCCI cci; /* Primary PCI mailbox CCI */
/* Always intialized as no way to know if a VDM might show up */
CXLCCI vdm_fm_owned_ld_mctp_cci;
CXLCCI ld0_cci;
/* DOE */
DOECap doe_cdat;
@ -361,9 +434,21 @@ struct CXLType3Class {
uint64_t offset);
void (*set_lsa)(CXLType3Dev *ct3d, const void *buf, uint64_t size,
uint64_t offset);
bool (*set_cacheline)(CXLType3Dev *ct3d, uint64_t dpa_offset, uint8_t *data);
bool (*set_cacheline)(CXLType3Dev *ct3d, uint64_t dpa_offset,
uint8_t *data);
};
struct CSWMBCCIDev {
PCIDevice parent_obj;
PCIDevice *target;
CXLComponentState cxl_cstate;
CXLDeviceState cxl_dstate;
CXLCCI *cci;
};
#define TYPE_CXL_SWITCH_MAILBOX_CCI "cxl-switch-mailbox-cci"
OBJECT_DECLARE_TYPE(CSWMBCCIDev, CSWMBCCIClass, CXL_SWITCH_MAILBOX_CCI)
MemTxResult cxl_type3_read(PCIDevice *d, hwaddr host_addr, uint64_t *data,
unsigned size, MemTxAttrs attrs);
MemTxResult cxl_type3_write(PCIDevice *d, hwaddr host_addr, uint64_t data,
@ -376,7 +461,7 @@ bool cxl_event_insert(CXLDeviceState *cxlds, CXLEventLogType log_type,
CXLEventRecordRaw *event);
CXLRetCode cxl_event_get_records(CXLDeviceState *cxlds, CXLGetEventPayload *pl,
uint8_t log_type, int max_recs,
uint16_t *len);
size_t *len);
CXLRetCode cxl_event_clear_records(CXLDeviceState *cxlds,
CXLClearEventPayload *pl);

View file

@ -92,7 +92,8 @@ typedef enum CXLEventIntMode {
CXL_INT_RES = 0x03,
} CXLEventIntMode;
#define CXL_EVENT_INT_MODE_MASK 0x3
#define CXL_EVENT_INT_SETTING(vector) ((((uint8_t)vector & 0xf) << 4) | CXL_INT_MSI_MSIX)
#define CXL_EVENT_INT_SETTING(vector) \
((((uint8_t)vector & 0xf) << 4) | CXL_INT_MSI_MSIX)
typedef struct CXLEventInterruptPolicy {
uint8_t info_settings;
uint8_t warn_settings;

View file

@ -86,7 +86,7 @@ typedef struct CXLDVSECDevice {
QEMU_BUILD_BUG_ON(sizeof(CXLDVSECDevice) != 0x38);
/* CXL 2.0 - 8.1.5 (ID 0003) */
typedef struct CXLDVSECPortExtensions {
typedef struct CXLDVSECPortExt {
DVSECHeader hdr;
uint16_t status;
uint16_t control;
@ -100,8 +100,8 @@ typedef struct CXLDVSECPortExtensions {
uint32_t alt_prefetch_limit_high;
uint32_t rcrb_base;
uint32_t rcrb_base_high;
} CXLDVSECPortExtensions;
QEMU_BUILD_BUG_ON(sizeof(CXLDVSECPortExtensions) != 0x28);
} CXLDVSECPortExt;
QEMU_BUILD_BUG_ON(sizeof(CXLDVSECPortExt) != 0x28);
#define PORT_CONTROL_OFFSET 0xc
#define PORT_CONTROL_UNMASK_SBR 1

View file

@ -0,0 +1,19 @@
#ifndef CXL_USP_H
#define CXL_USP_H
#include "hw/pci/pcie.h"
#include "hw/pci/pcie_port.h"
#include "hw/cxl/cxl.h"
typedef struct CXLUpstreamPort {
/*< private >*/
PCIEPort parent_obj;
/*< public >*/
CXLComponentState cxl_cstate;
CXLCCI swcci;
DOECap doe_cdat;
uint64_t sn;
} CXLUpstreamPort;
#endif /* CXL_SUP_H */

View file

@ -26,6 +26,18 @@ typedef enum VhostSetConfigType {
VHOST_SET_CONFIG_TYPE_MIGRATION = 1,
} VhostSetConfigType;
typedef enum VhostDeviceStateDirection {
/* Transfer state from back-end (device) to front-end */
VHOST_TRANSFER_STATE_DIRECTION_SAVE = 0,
/* Transfer state from front-end to back-end (device) */
VHOST_TRANSFER_STATE_DIRECTION_LOAD = 1,
} VhostDeviceStateDirection;
typedef enum VhostDeviceStatePhase {
/* The device (and all its vrings) is stopped */
VHOST_TRANSFER_STATE_PHASE_STOPPED = 0,
} VhostDeviceStatePhase;
struct vhost_inflight;
struct vhost_dev;
struct vhost_log;
@ -129,6 +141,15 @@ typedef int (*vhost_set_config_call_op)(struct vhost_dev *dev,
typedef void (*vhost_reset_status_op)(struct vhost_dev *dev);
typedef bool (*vhost_supports_device_state_op)(struct vhost_dev *dev);
typedef int (*vhost_set_device_state_fd_op)(struct vhost_dev *dev,
VhostDeviceStateDirection direction,
VhostDeviceStatePhase phase,
int fd,
int *reply_fd,
Error **errp);
typedef int (*vhost_check_device_state_op)(struct vhost_dev *dev, Error **errp);
typedef struct VhostOps {
VhostBackendType backend_type;
vhost_backend_init vhost_backend_init;
@ -176,6 +197,9 @@ typedef struct VhostOps {
vhost_force_iommu_op vhost_force_iommu;
vhost_set_config_call_op vhost_set_config_call;
vhost_reset_status_op vhost_reset_status;
vhost_supports_device_state_op vhost_supports_device_state;
vhost_set_device_state_fd_op vhost_set_device_state_fd;
vhost_check_device_state_op vhost_check_device_state;
} VhostOps;
int vhost_backend_update_device_iotlb(struct vhost_dev *dev,

View file

@ -31,6 +31,7 @@ enum VhostUserProtocolFeature {
VHOST_USER_PROTOCOL_F_STATUS = 16,
/* Feature 17 reserved for VHOST_USER_PROTOCOL_F_XEN_MMAP. */
VHOST_USER_PROTOCOL_F_SHARED_OBJECT = 18,
VHOST_USER_PROTOCOL_F_DEVICE_STATE = 19,
VHOST_USER_PROTOCOL_F_MAX
};

View file

@ -351,4 +351,117 @@ static inline int vhost_reset_device(struct vhost_dev *hdev)
}
#endif /* CONFIG_VHOST */
/**
* vhost_supports_device_state(): Checks whether the back-end supports
* transferring internal device state for the purpose of migration.
* Support for this feature is required for vhost_set_device_state_fd()
* and vhost_check_device_state().
*
* @dev: The vhost device
*
* Returns true if the device supports these commands, and false if it
* does not.
*/
bool vhost_supports_device_state(struct vhost_dev *dev);
/**
* vhost_set_device_state_fd(): Begin transfer of internal state from/to
* the back-end for the purpose of migration. Data is to be transferred
* over a pipe according to @direction and @phase. The sending end must
* only write to the pipe, and the receiving end must only read from it.
* Once the sending end is done, it closes its FD. The receiving end
* must take this as the end-of-transfer signal and close its FD, too.
*
* @fd is the back-end's end of the pipe: The write FD for SAVE, and the
* read FD for LOAD. This function transfers ownership of @fd to the
* back-end, i.e. closes it in the front-end.
*
* The back-end may optionally reply with an FD of its own, if this
* improves efficiency on its end. In this case, the returned FD is
* stored in *reply_fd. The back-end will discard the FD sent to it,
* and the front-end must use *reply_fd for transferring state to/from
* the back-end.
*
* @dev: The vhost device
* @direction: The direction in which the state is to be transferred.
* For outgoing migrations, this is SAVE, and data is read
* from the back-end and stored by the front-end in the
* migration stream.
* For incoming migrations, this is LOAD, and data is read
* by the front-end from the migration stream and sent to
* the back-end to restore the saved state.
* @phase: Which migration phase we are in. Currently, there is only
* STOPPED (device and all vrings are stopped), in the future,
* more phases such as PRE_COPY or POST_COPY may be added.
* @fd: Back-end's end of the pipe through which to transfer state; note
* that ownership is transferred to the back-end, so this function
* closes @fd in the front-end.
* @reply_fd: If the back-end wishes to use a different pipe for state
* transfer, this will contain an FD for the front-end to
* use. Otherwise, -1 is stored here.
* @errp: Potential error description
*
* Returns 0 on success, and -errno on failure.
*/
int vhost_set_device_state_fd(struct vhost_dev *dev,
VhostDeviceStateDirection direction,
VhostDeviceStatePhase phase,
int fd,
int *reply_fd,
Error **errp);
/**
* vhost_set_device_state_fd(): After transferring state from/to the
* back-end via vhost_set_device_state_fd(), i.e. once the sending end
* has closed the pipe, inquire the back-end to report any potential
* errors that have occurred on its side. This allows to sense errors
* like:
* - During outgoing migration, when the source side had already started
* to produce its state, something went wrong and it failed to finish
* - During incoming migration, when the received state is somehow
* invalid and cannot be processed by the back-end
*
* @dev: The vhost device
* @errp: Potential error description
*
* Returns 0 when the back-end reports successful state transfer and
* processing, and -errno when an error occurred somewhere.
*/
int vhost_check_device_state(struct vhost_dev *dev, Error **errp);
/**
* vhost_save_backend_state(): High-level function to receive a vhost
* back-end's state, and save it in @f. Uses
* `vhost_set_device_state_fd()` to get the data from the back-end, and
* stores it in consecutive chunks that are each prefixed by their
* respective length (be32). The end is marked by a 0-length chunk.
*
* Must only be called while the device and all its vrings are stopped
* (`VHOST_TRANSFER_STATE_PHASE_STOPPED`).
*
* @dev: The vhost device from which to save the state
* @f: Migration stream in which to save the state
* @errp: Potential error message
*
* Returns 0 on success, and -errno otherwise.
*/
int vhost_save_backend_state(struct vhost_dev *dev, QEMUFile *f, Error **errp);
/**
* vhost_load_backend_state(): High-level function to load a vhost
* back-end's state from @f, and send it over to the back-end. Reads
* the data from @f in the format used by `vhost_save_state()`, and uses
* `vhost_set_device_state_fd()` to transfer it to the back-end.
*
* Must only be called while the device and all its vrings are stopped
* (`VHOST_TRANSFER_STATE_PHASE_STOPPED`).
*
* @dev: The vhost device to which to send the sate
* @f: Migration stream from which to load the state
* @errp: Potential error message
*
* Returns 0 on success, and -errno otherwise.
*/
int vhost_load_backend_state(struct vhost_dev *dev, QEMUFile *f, Error **errp);
#endif