hw/cxl/events: Add qmp interfaces to add/release dynamic capacity extents

To simulate FM functionalities for initiating Dynamic Capacity Add
(Opcode 5604h) and Dynamic Capacity Release (Opcode 5605h) as in CXL spec
r3.1 7.6.7.6.5 and 7.6.7.6.6, we implemented two QMP interfaces to issue
add/release dynamic capacity extents requests.

With the change, we allow to release an extent only when its DPA range
is contained by a single accepted extent in the device. That is to say,
extent superset release is not supported yet.

1. Add dynamic capacity extents:

For example, the command to add two continuous extents (each 128MiB long)
to region 0 (starting at DPA offset 0) looks like below:

{ "execute": "qmp_capabilities" }

{ "execute": "cxl-add-dynamic-capacity",
  "arguments": {
      "path": "/machine/peripheral/cxl-dcd0",
      "host-id": 0,
      "selection-policy": "prescriptive",
      "region": 0,
      "extents": [
      {
          "offset": 0,
          "len": 134217728
      },
      {
          "offset": 134217728,
          "len": 134217728
      }
      ]
  }
}

2. Release dynamic capacity extents:

For example, the command to release an extent of size 128MiB from region 0
(DPA offset 128MiB) looks like below:

{ "execute": "cxl-release-dynamic-capacity",
  "arguments": {
      "path": "/machine/peripheral/cxl-dcd0",
      "host-id": 0,
      "removal-policy":"prescriptive",
      "region": 0,
      "extents": [
      {
          "offset": 134217728,
          "len": 134217728
      }
      ]
  }
}

Tested-by: Svetly Todorov <svetly.todorov@memverge.com>
Reviewed-by: Gregory Price <gregory.price@memverge.com>
Signed-off-by: Fan Ni <fan.ni@samsung.com>
Message-Id: <20240523174651.1089554-12-nifan.cxl@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Fan Ni 2024-05-23 10:44:51 -07:00 committed by Michael S. Tsirkin
parent 16fd1b1216
commit d0b9b28a5b
6 changed files with 563 additions and 13 deletions

View file

@ -443,6 +443,12 @@ typedef struct CXLDCExtent {
} CXLDCExtent;
typedef QTAILQ_HEAD(, CXLDCExtent) CXLDCExtentList;
typedef struct CXLDCExtentGroup {
CXLDCExtentList list;
QTAILQ_ENTRY(CXLDCExtentGroup) node;
} CXLDCExtentGroup;
typedef QTAILQ_HEAD(, CXLDCExtentGroup) CXLDCExtentGroupList;
typedef struct CXLDCRegion {
uint64_t base; /* aligned to 256*MiB */
uint64_t decode_len; /* aligned to 256*MiB */
@ -494,6 +500,7 @@ struct CXLType3Dev {
*/
uint64_t total_capacity; /* 256M aligned */
CXLDCExtentList extents;
CXLDCExtentGroupList extents_pending;
uint32_t total_extent_count;
uint32_t ext_list_gen_seq;
@ -555,4 +562,19 @@ CXLDCRegion *cxl_find_dc_region(CXLType3Dev *ct3d, uint64_t dpa, uint64_t len);
void cxl_remove_extent_from_extent_list(CXLDCExtentList *list,
CXLDCExtent *extent);
void cxl_insert_extent_to_extent_list(CXLDCExtentList *list, uint64_t dpa,
uint64_t len, uint8_t *tag,
uint16_t shared_seq);
bool test_any_bits_set(const unsigned long *addr, unsigned long nr,
unsigned long size);
bool cxl_extents_contains_dpa_range(CXLDCExtentList *list,
uint64_t dpa, uint64_t len);
CXLDCExtentGroup *cxl_insert_extent_to_extent_group(CXLDCExtentGroup *group,
uint64_t dpa,
uint64_t len,
uint8_t *tag,
uint16_t shared_seq);
void cxl_extent_group_list_insert_tail(CXLDCExtentGroupList *list,
CXLDCExtentGroup *group);
void cxl_extent_group_list_delete_front(CXLDCExtentGroupList *list);
#endif

View file

@ -166,4 +166,22 @@ typedef struct CXLEventMemoryModule {
uint8_t reserved[0x3d];
} QEMU_PACKED CXLEventMemoryModule;
/*
* CXL r3.1 section Table 8-50: Dynamic Capacity Event Record
* All fields little endian.
*/
typedef struct CXLEventDynamicCapacity {
CXLEventRecordHdr hdr;
uint8_t type;
uint8_t validity_flags;
uint16_t host_id;
uint8_t updated_region_id;
uint8_t flags;
uint8_t reserved2[2];
uint8_t dynamic_capacity_extent[0x28]; /* defined in cxl_device.h */
uint8_t reserved[0x18];
uint32_t extents_avail;
uint32_t tags_avail;
} QEMU_PACKED CXLEventDynamicCapacity;
#endif /* CXL_EVENTS_H */