hw/cxl: mailbox-utils: 0x5602 - FMAPI Set DC Region Config

FM DCD Management command 0x5602 implemented per CXL r3.2 Spec Section 7.6.7.6.3

Reviewed-by: Fan Ni <fan.ni@samsung.com>
Signed-off-by: Anisa Su <anisa.su@samsung.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20250714174509.1984430-8-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Anisa Su 2025-07-14 18:45:03 +01:00 committed by Michael S. Tsirkin
parent 69798d000b
commit 1befc7bde3
4 changed files with 99 additions and 3 deletions

View file

@ -18,6 +18,7 @@
#include "hw/pci/pci.h"
#include "hw/pci-bridge/cxl_upstream_port.h"
#include "qemu/cutils.h"
#include "qemu/host-utils.h"
#include "qemu/log.h"
#include "qemu/units.h"
#include "qemu/uuid.h"
@ -121,6 +122,7 @@ enum {
FMAPI_DCD_MGMT = 0x56,
#define GET_DCD_INFO 0x0
#define GET_HOST_DC_REGION_CONFIG 0x1
#define SET_DC_REGION_CONFIG 0x2
};
/* CCI Message Format CXL r3.1 Figure 7-19 */
@ -3390,6 +3392,84 @@ static CXLRetCode cmd_fm_get_host_dc_region_config(const struct cxl_cmd *cmd,
return CXL_MBOX_SUCCESS;
}
/* CXL r3.2 section 7.6.7.6.3: Set Host DC Region Configuration (Opcode 5602) */
static CXLRetCode cmd_fm_set_dc_region_config(const struct cxl_cmd *cmd,
uint8_t *payload_in,
size_t len_in,
uint8_t *payload_out,
size_t *len_out,
CXLCCI *cci)
{
struct {
uint8_t reg_id;
uint8_t rsvd[3];
uint64_t block_sz;
uint8_t flags;
uint8_t rsvd2[3];
} QEMU_PACKED *in = (void *)payload_in;
CXLType3Dev *ct3d = CXL_TYPE3(cci->d);
CXLEventDynamicCapacity dcEvent = {};
CXLDCRegion *region = &ct3d->dc.regions[in->reg_id];
/*
* CXL r3.2 7.6.7.6.3: Set DC Region Configuration
* This command shall fail with Unsupported when the Sanitize on Release
* field does not match the regions configuration... and the device
* does not support reconfiguration of the Sanitize on Release setting.
*
* Currently not reconfigurable, so always fail if sanitize bit (bit 0)
* doesn't match.
*/
if ((in->flags & 0x1) != (region->flags & 0x1)) {
return CXL_MBOX_UNSUPPORTED;
}
if (in->reg_id >= DCD_MAX_NUM_REGION) {
return CXL_MBOX_UNSUPPORTED;
}
/* Check that no extents are in the region being reconfigured */
if (!bitmap_empty(region->blk_bitmap, region->len / region->block_size)) {
return CXL_MBOX_UNSUPPORTED;
}
/* Check that new block size is supported */
if (!is_power_of_2(in->block_sz) ||
!(in->block_sz & region->supported_blk_size_bitmask)) {
return CXL_MBOX_INVALID_INPUT;
}
/* Return success if new block size == current block size */
if (in->block_sz == region->block_size) {
return CXL_MBOX_SUCCESS;
}
/* Free bitmap and create new one for new block size. */
qemu_mutex_lock(&region->bitmap_lock);
g_free(region->blk_bitmap);
region->blk_bitmap = bitmap_new(region->len / in->block_sz);
qemu_mutex_unlock(&region->bitmap_lock);
region->block_size = in->block_sz;
/* Create event record and insert into event log */
cxl_assign_event_header(&dcEvent.hdr,
&dynamic_capacity_uuid,
(1 << CXL_EVENT_TYPE_INFO),
sizeof(dcEvent),
cxl_device_get_timestamp(&ct3d->cxl_dstate));
dcEvent.type = DC_EVENT_REGION_CONFIG_UPDATED;
dcEvent.validity_flags = 1;
dcEvent.host_id = 0;
dcEvent.updated_region_id = in->reg_id;
if (cxl_event_insert(&ct3d->cxl_dstate,
CXL_EVENT_TYPE_DYNAMIC_CAP,
(CXLEventRecordRaw *)&dcEvent)) {
cxl_event_irq_assert(ct3d);
}
return CXL_MBOX_SUCCESS;
}
static const struct cxl_cmd cxl_cmd_set[256][256] = {
[INFOSTAT][BACKGROUND_OPERATION_ABORT] = { "BACKGROUND_OPERATION_ABORT",
cmd_infostat_bg_op_abort, 0, 0 },
@ -3508,6 +3588,13 @@ static const struct cxl_cmd cxl_cmd_set_fm_dcd[256][256] = {
cmd_fm_get_dcd_info, 0, 0 },
[FMAPI_DCD_MGMT][GET_HOST_DC_REGION_CONFIG] = { "GET_HOST_DC_REGION_CONFIG",
cmd_fm_get_host_dc_region_config, 4, 0 },
[FMAPI_DCD_MGMT][SET_DC_REGION_CONFIG] = { "SET_DC_REGION_CONFIG",
cmd_fm_set_dc_region_config, 16,
(CXL_MBOX_CONFIG_CHANGE_COLD_RESET |
CXL_MBOX_CONFIG_CHANGE_CONV_RESET |
CXL_MBOX_CONFIG_CHANGE_CXL_RESET |
CXL_MBOX_IMMEDIATE_CONFIG_CHANGE |
CXL_MBOX_IMMEDIATE_DATA_CHANGE) },
};
/*

View file

@ -1590,9 +1590,9 @@ void qmp_cxl_inject_correctable_error(const char *path, CxlCorErrorType type,
pcie_aer_inject_error(PCI_DEVICE(obj), &err);
}
static void cxl_assign_event_header(CXLEventRecordHdr *hdr,
const QemuUUID *uuid, uint32_t flags,
uint8_t length, uint64_t timestamp)
void cxl_assign_event_header(CXLEventRecordHdr *hdr,
const QemuUUID *uuid, uint32_t flags,
uint8_t length, uint64_t timestamp)
{
st24_le_p(&hdr->flags, flags);
hdr->length = length;

View file

@ -721,4 +721,7 @@ void ct3_clear_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa,
uint64_t len);
bool ct3_test_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa,
uint64_t len);
void cxl_assign_event_header(CXLEventRecordHdr *hdr,
const QemuUUID *uuid, uint32_t flags,
uint8_t length, uint64_t timestamp);
#endif

View file

@ -8,6 +8,7 @@
#ifndef CXL_MAILBOX_H
#define CXL_MAILBOX_H
#define CXL_MBOX_CONFIG_CHANGE_COLD_RESET (1)
#define CXL_MBOX_IMMEDIATE_CONFIG_CHANGE (1 << 1)
#define CXL_MBOX_IMMEDIATE_DATA_CHANGE (1 << 2)
#define CXL_MBOX_IMMEDIATE_POLICY_CHANGE (1 << 3)
@ -15,5 +16,10 @@
#define CXL_MBOX_SECURITY_STATE_CHANGE (1 << 5)
#define CXL_MBOX_BACKGROUND_OPERATION (1 << 6)
#define CXL_MBOX_BACKGROUND_OPERATION_ABORT (1 << 7)
#define CXL_MBOX_SECONDARY_MBOX_SUPPORTED (1 << 8)
#define CXL_MBOX_REQUEST_ABORT_BACKGROUND_OP_SUPPORTED (1 << 9)
#define CXL_MBOX_CEL_10_TO_11_VALID (1 << 10)
#define CXL_MBOX_CONFIG_CHANGE_CONV_RESET (1 << 11)
#define CXL_MBOX_CONFIG_CHANGE_CXL_RESET (1 << 12)
#endif