Lines Matching +full:cci +full:- +full:400

7  * COPYING file in the top-level directory.
17 #include "hw/pci-bridge/cxl_upstream_port.h"
47 * payload from cmd->payload and operating upon it as necessary. It must then
48 * fill the output data into cmd->payload (overwriting what was there),
108 /* CCI Message Format CXL r3.1 Figure 7-19 */
129 CXLCCI *cci) in cmd_tunnel_management_cmd() argument
148 if (cmd->in < sizeof(*in)) { in cmd_tunnel_management_cmd()
157 /* Enough room for minimum sized message - no payload */ in cmd_tunnel_management_cmd()
158 if (in->size < sizeof(in->ccimessage)) { in cmd_tunnel_management_cmd()
161 /* Length of input payload should be in->size + a wrapping tunnel header */ in cmd_tunnel_management_cmd()
162 if (in->size != len_in - offsetof(typeof(*out), ccimessage)) { in cmd_tunnel_management_cmd()
165 if (in->ccimessage.category != CXL_CCI_CAT_REQ) { in cmd_tunnel_management_cmd()
169 if (in->target_type != 0) { in cmd_tunnel_management_cmd()
171 "Tunneled Command sent to non existent FM-LD"); in cmd_tunnel_management_cmd()
176 * Target of a tunnel unfortunately depends on type of CCI readint in cmd_tunnel_management_cmd()
182 if (object_dynamic_cast(OBJECT(cci->d), TYPE_CXL_TYPE3)) { in cmd_tunnel_management_cmd()
183 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_tunnel_management_cmd()
184 if (in->port_or_ld_id != 0) { in cmd_tunnel_management_cmd()
188 target_cci = &ct3d->ld0_cci; in cmd_tunnel_management_cmd()
189 } else if (object_dynamic_cast(OBJECT(cci->d), TYPE_CXL_USP)) { in cmd_tunnel_management_cmd()
190 CXLUpstreamPort *usp = CXL_USP(cci->d); in cmd_tunnel_management_cmd()
192 tunnel_target = pcie_find_port_by_pn(&PCI_BRIDGE(usp)->sec_bus, in cmd_tunnel_management_cmd()
193 in->port_or_ld_id); in cmd_tunnel_management_cmd()
198 pci_bridge_get_sec_bus(PCI_BRIDGE(tunnel_target))->devices[0]; in cmd_tunnel_management_cmd()
205 target_cci = &ct3d->vdm_fm_owned_ld_mctp_cci; in cmd_tunnel_management_cmd()
213 pl_length = in->ccimessage.pl_length[2] << 16 | in cmd_tunnel_management_cmd()
214 in->ccimessage.pl_length[1] << 8 | in->ccimessage.pl_length[0]; in cmd_tunnel_management_cmd()
216 in->ccimessage.command_set, in cmd_tunnel_management_cmd()
217 in->ccimessage.command, in cmd_tunnel_management_cmd()
218 pl_length, in->ccimessage.payload, in cmd_tunnel_management_cmd()
219 &length_out, out->ccimessage.payload, in cmd_tunnel_management_cmd()
221 /* Payload should be in place. Rest of CCI header and needs filling */ in cmd_tunnel_management_cmd()
222 out->resp_len = length_out + sizeof(CXLCCIMessage); in cmd_tunnel_management_cmd()
223 st24_le_p(out->ccimessage.pl_length, length_out); in cmd_tunnel_management_cmd()
224 out->ccimessage.rc = rc; in cmd_tunnel_management_cmd()
225 out->ccimessage.category = CXL_CCI_CAT_RSP; in cmd_tunnel_management_cmd()
226 out->ccimessage.command = in->ccimessage.command; in cmd_tunnel_management_cmd()
227 out->ccimessage.command_set = in->ccimessage.command_set; in cmd_tunnel_management_cmd()
228 out->ccimessage.tag = in->ccimessage.tag; in cmd_tunnel_management_cmd()
237 CXLCCI *cci) in cmd_events_get_records() argument
239 CXLDeviceState *cxlds = &CXL_TYPE3(cci->d)->cxl_dstate; in cmd_events_get_records()
244 if (cmd->in < sizeof(log_type)) { in cmd_events_get_records()
252 max_recs = (cxlds->payload_size - CXL_EVENT_PAYLOAD_HDR_SIZE) / in cmd_events_get_records()
266 CXLCCI *cci) in cmd_events_clear_records() argument
268 CXLDeviceState *cxlds = &CXL_TYPE3(cci->d)->cxl_dstate; in cmd_events_clear_records()
274 len_in < sizeof(*pl) + sizeof(*pl->handle) * pl->nr_recs) { in cmd_events_clear_records()
287 CXLCCI *cci) in cmd_events_get_interrupt_policy() argument
289 CXLDeviceState *cxlds = &CXL_TYPE3(cci->d)->cxl_dstate; in cmd_events_get_interrupt_policy()
295 log = &cxlds->event_logs[CXL_EVENT_TYPE_INFO]; in cmd_events_get_interrupt_policy()
296 if (log->irq_enabled) { in cmd_events_get_interrupt_policy()
297 policy->info_settings = CXL_EVENT_INT_SETTING(log->irq_vec); in cmd_events_get_interrupt_policy()
300 log = &cxlds->event_logs[CXL_EVENT_TYPE_WARN]; in cmd_events_get_interrupt_policy()
301 if (log->irq_enabled) { in cmd_events_get_interrupt_policy()
302 policy->warn_settings = CXL_EVENT_INT_SETTING(log->irq_vec); in cmd_events_get_interrupt_policy()
305 log = &cxlds->event_logs[CXL_EVENT_TYPE_FAIL]; in cmd_events_get_interrupt_policy()
306 if (log->irq_enabled) { in cmd_events_get_interrupt_policy()
307 policy->failure_settings = CXL_EVENT_INT_SETTING(log->irq_vec); in cmd_events_get_interrupt_policy()
310 log = &cxlds->event_logs[CXL_EVENT_TYPE_FATAL]; in cmd_events_get_interrupt_policy()
311 if (log->irq_enabled) { in cmd_events_get_interrupt_policy()
312 policy->fatal_settings = CXL_EVENT_INT_SETTING(log->irq_vec); in cmd_events_get_interrupt_policy()
315 log = &cxlds->event_logs[CXL_EVENT_TYPE_DYNAMIC_CAP]; in cmd_events_get_interrupt_policy()
316 if (log->irq_enabled) { in cmd_events_get_interrupt_policy()
318 policy->dyn_cap_settings = CXL_INT_MSI_MSIX; in cmd_events_get_interrupt_policy()
330 CXLCCI *cci) in cmd_events_set_interrupt_policy() argument
332 CXLDeviceState *cxlds = &CXL_TYPE3(cci->d)->cxl_dstate; in cmd_events_set_interrupt_policy()
342 log = &cxlds->event_logs[CXL_EVENT_TYPE_INFO]; in cmd_events_set_interrupt_policy()
343 log->irq_enabled = (policy->info_settings & CXL_EVENT_INT_MODE_MASK) == in cmd_events_set_interrupt_policy()
346 log = &cxlds->event_logs[CXL_EVENT_TYPE_WARN]; in cmd_events_set_interrupt_policy()
347 log->irq_enabled = (policy->warn_settings & CXL_EVENT_INT_MODE_MASK) == in cmd_events_set_interrupt_policy()
350 log = &cxlds->event_logs[CXL_EVENT_TYPE_FAIL]; in cmd_events_set_interrupt_policy()
351 log->irq_enabled = (policy->failure_settings & CXL_EVENT_INT_MODE_MASK) == in cmd_events_set_interrupt_policy()
354 log = &cxlds->event_logs[CXL_EVENT_TYPE_FATAL]; in cmd_events_set_interrupt_policy()
355 log->irq_enabled = (policy->fatal_settings & CXL_EVENT_INT_MODE_MASK) == in cmd_events_set_interrupt_policy()
363 log = &cxlds->event_logs[CXL_EVENT_TYPE_DYNAMIC_CAP]; in cmd_events_set_interrupt_policy()
364 log->irq_enabled = (policy->dyn_cap_settings & CXL_EVENT_INT_MODE_MASK) == in cmd_events_set_interrupt_policy()
377 CXLCCI *cci) in cmd_infostat_identify() argument
379 PCIDeviceClass *class = PCI_DEVICE_GET_CLASS(cci->d); in cmd_infostat_identify()
392 is_identify->pcie_vid = class->vendor_id; in cmd_infostat_identify()
393 is_identify->pcie_did = class->device_id; in cmd_infostat_identify()
394 if (object_dynamic_cast(OBJECT(cci->d), TYPE_CXL_USP)) { in cmd_infostat_identify()
395 is_identify->sn = CXL_USP(cci->d)->sn; in cmd_infostat_identify()
397 is_identify->pcie_subsys_vid = 0; in cmd_infostat_identify()
398 is_identify->pcie_subsys_id = 0; in cmd_infostat_identify()
399 is_identify->component_type = 0x0; /* Switch */ in cmd_infostat_identify()
400 } else if (object_dynamic_cast(OBJECT(cci->d), TYPE_CXL_TYPE3)) { in cmd_infostat_identify()
401 PCIDevice *pci_dev = PCI_DEVICE(cci->d); in cmd_infostat_identify()
403 is_identify->sn = CXL_TYPE3(cci->d)->sn; in cmd_infostat_identify()
405 * We can't always use class->subsystem_vendor_id as in cmd_infostat_identify()
408 is_identify->pcie_subsys_vid = in cmd_infostat_identify()
409 pci_get_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID); in cmd_infostat_identify()
410 is_identify->pcie_subsys_id = in cmd_infostat_identify()
411 pci_get_word(pci_dev->config + PCI_SUBSYSTEM_ID); in cmd_infostat_identify()
412 is_identify->component_type = 0x3; /* Type 3 */ in cmd_infostat_identify()
416 is_identify->max_message_size = 9; /* 512 bytes - MCTP_CXL_MAILBOX_BYTES */ in cmd_infostat_identify()
426 uint8_t port = PCIE_PORT(d)->port; in cxl_set_dsp_active_bm()
437 CXLCCI *cci) in cmd_identify_switch_device() argument
439 PCIEPort *usp = PCIE_PORT(cci->d); in cmd_identify_switch_device()
440 PCIBus *bus = &PCI_BRIDGE(cci->d)->sec_bus; in cmd_identify_switch_device()
459 .num_vcss = 1, /* Not yet support multiple VCS - potentially tricky */ in cmd_identify_switch_device()
466 /* Depends on the CCI type */ in cmd_identify_switch_device()
467 if (object_dynamic_cast(OBJECT(cci->intf), TYPE_PCIE_PORT)) { in cmd_identify_switch_device()
468 out->ingress_port_id = PCIE_PORT(cci->intf)->port; in cmd_identify_switch_device()
471 out->ingress_port_id = 0; in cmd_identify_switch_device()
475 out->active_port_bitmask); in cmd_identify_switch_device()
476 out->active_port_bitmask[usp->port / 8] |= (1 << usp->port % 8); in cmd_identify_switch_device()
489 CXLCCI *cci) in cmd_get_physical_port_state() argument
491 /* CXL r3.1 Table 7-17: Get Physical Port State Request Payload */ in cmd_get_physical_port_state()
498 * CXL r3.1 Table 7-19: Get Physical Port State Port Information Block in cmd_get_physical_port_state()
519 /* CXL r3.1 Table 7-18: Get Physical Port State Response Payload */ in cmd_get_physical_port_state()
525 PCIBus *bus = &PCI_BRIDGE(cci->d)->sec_bus; in cmd_get_physical_port_state()
526 PCIEPort *usp = PCIE_PORT(cci->d); in cmd_get_physical_port_state()
537 if (sizeof(*out) + sizeof(*out->ports) * in->num_ports > cci->payload_max) { in cmd_get_physical_port_state()
542 out->num_ports = in->num_ports; in cmd_get_physical_port_state()
544 for (i = 0; i < in->num_ports; i++) { in cmd_get_physical_port_state()
550 port = &out->ports[i]; in cmd_get_physical_port_state()
552 port_dev = pcie_find_port_by_pn(bus, in->ports[i]); in cmd_get_physical_port_state()
555 ->devices[0]; in cmd_get_physical_port_state()
556 port->config_state = 3; in cmd_get_physical_port_state()
559 port->connected_device_type = 5; /* Assume MLD for now */ in cmd_get_physical_port_state()
561 port->connected_device_type = 1; in cmd_get_physical_port_state()
564 port->connected_device_type = 0; in cmd_get_physical_port_state()
566 port->supported_ld_count = 3; in cmd_get_physical_port_state()
567 } else if (usp->port == in->ports[i]) { /* USP */ in cmd_get_physical_port_state()
569 port->config_state = 4; in cmd_get_physical_port_state()
570 port->connected_device_type = 0; in cmd_get_physical_port_state()
575 port->port_id = in->ports[i]; in cmd_get_physical_port_state()
577 if (!port_dev->exp.exp_cap) { in cmd_get_physical_port_state()
580 lnksta = port_dev->config_read(port_dev, in cmd_get_physical_port_state()
581 port_dev->exp.exp_cap + PCI_EXP_LNKSTA, in cmd_get_physical_port_state()
583 lnkcap = port_dev->config_read(port_dev, in cmd_get_physical_port_state()
584 port_dev->exp.exp_cap + PCI_EXP_LNKCAP, in cmd_get_physical_port_state()
586 lnkcap2 = port_dev->config_read(port_dev, in cmd_get_physical_port_state()
587 port_dev->exp.exp_cap + PCI_EXP_LNKCAP2, in cmd_get_physical_port_state()
590 port->max_link_width = (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4; in cmd_get_physical_port_state()
591 port->negotiated_link_width = (lnksta & PCI_EXP_LNKSTA_NLW) >> 4; in cmd_get_physical_port_state()
593 port->supported_link_speeds_vector = (lnkcap2 & 0xFE) >> 1; in cmd_get_physical_port_state()
594 port->max_link_speed = lnkcap & PCI_EXP_LNKCAP_SLS; in cmd_get_physical_port_state()
595 port->current_link_speed = lnksta & PCI_EXP_LNKSTA_CLS; in cmd_get_physical_port_state()
597 port->ltssm_state = 0x7; in cmd_get_physical_port_state()
598 port->first_lane_num = 0; in cmd_get_physical_port_state()
599 port->link_state = 0; in cmd_get_physical_port_state()
600 port->port_cxl_version_bitmask = 0x2; in cmd_get_physical_port_state()
601 port->connected_device_cxl_version = 0x2; in cmd_get_physical_port_state()
604 pl_size = sizeof(*out) + sizeof(*out->ports) * in->num_ports; in cmd_get_physical_port_state()
616 CXLCCI *cci) in cmd_infostat_bg_op_sts() argument
628 bg_op_status->status = cci->bg.complete_pct << 1; in cmd_infostat_bg_op_sts()
629 if (cci->bg.runtime > 0) { in cmd_infostat_bg_op_sts()
630 bg_op_status->status |= 1U << 0; in cmd_infostat_bg_op_sts()
632 bg_op_status->opcode = cci->bg.opcode; in cmd_infostat_bg_op_sts()
633 bg_op_status->returncode = cci->bg.ret_code; in cmd_infostat_bg_op_sts()
648 CXLCCI *cci) in cmd_firmware_update_get_info() argument
650 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_firmware_update_get_info()
651 CXLDeviceState *cxl_dstate = &ct3d->cxl_dstate; in cmd_firmware_update_get_info()
664 if (!QEMU_IS_ALIGNED(cxl_dstate->vmem_size, CXL_CAPACITY_MULTIPLIER) || in cmd_firmware_update_get_info()
665 !QEMU_IS_ALIGNED(cxl_dstate->pmem_size, CXL_CAPACITY_MULTIPLIER) || in cmd_firmware_update_get_info()
666 !QEMU_IS_ALIGNED(ct3d->dc.total_capacity, CXL_CAPACITY_MULTIPLIER)) { in cmd_firmware_update_get_info()
672 fw_info->slots_supported = CXL_FW_SLOTS; in cmd_firmware_update_get_info()
673 fw_info->slot_info = (cci->fw.active_slot & 0x7) | in cmd_firmware_update_get_info()
674 ((cci->fw.staged_slot & 0x7) << 3); in cmd_firmware_update_get_info()
675 fw_info->caps = BIT(0); /* online update supported */ in cmd_firmware_update_get_info()
677 if (cci->fw.slot[0]) { in cmd_firmware_update_get_info()
678 pstrcpy(fw_info->fw_rev1, sizeof(fw_info->fw_rev1), "BWFW VERSION 0"); in cmd_firmware_update_get_info()
680 if (cci->fw.slot[1]) { in cmd_firmware_update_get_info()
681 pstrcpy(fw_info->fw_rev2, sizeof(fw_info->fw_rev2), "BWFW VERSION 1"); in cmd_firmware_update_get_info()
702 CXLCCI *cci) in cmd_firmware_update_transfer() argument
718 if (fw_transfer->action == CXL_FW_XFER_ACTION_ABORT) { in cmd_firmware_update_transfer()
720 * At this point there aren't any on-going transfers in cmd_firmware_update_transfer()
721 * running in the bg - this is serialized before this in cmd_firmware_update_transfer()
725 cci->fw.transferring = false; in cmd_firmware_update_transfer()
729 offset = fw_transfer->offset * CXL_FW_XFER_ALIGNMENT; in cmd_firmware_update_transfer()
730 length = len - sizeof(*fw_transfer); in cmd_firmware_update_transfer()
735 if (cci->fw.transferring) { in cmd_firmware_update_transfer()
736 if (fw_transfer->action == CXL_FW_XFER_ACTION_FULL || in cmd_firmware_update_transfer()
737 fw_transfer->action == CXL_FW_XFER_ACTION_INIT) { in cmd_firmware_update_transfer()
743 * semantically treat this condition as an error - as in cmd_firmware_update_transfer()
746 if (difftime(time(NULL), cci->fw.last_partxfer) > 30.0) { in cmd_firmware_update_transfer()
747 cci->fw.transferring = false; in cmd_firmware_update_transfer()
750 } else if (fw_transfer->action == CXL_FW_XFER_ACTION_CONTINUE || in cmd_firmware_update_transfer()
751 fw_transfer->action == CXL_FW_XFER_ACTION_END) { in cmd_firmware_update_transfer()
755 /* allow back-to-back retransmission */ in cmd_firmware_update_transfer()
756 if ((offset != cci->fw.prev_offset || length != cci->fw.prev_len) && in cmd_firmware_update_transfer()
757 (fw_transfer->action == CXL_FW_XFER_ACTION_CONTINUE || in cmd_firmware_update_transfer()
758 fw_transfer->action == CXL_FW_XFER_ACTION_END)) { in cmd_firmware_update_transfer()
760 if (offset < cci->fw.prev_offset + cci->fw.prev_len) { in cmd_firmware_update_transfer()
765 switch (fw_transfer->action) { in cmd_firmware_update_transfer()
768 if (fw_transfer->slot == 0 || in cmd_firmware_update_transfer()
769 fw_transfer->slot == cci->fw.active_slot || in cmd_firmware_update_transfer()
770 fw_transfer->slot > CXL_FW_SLOTS) { in cmd_firmware_update_transfer()
781 cci->fw.transferring = true; in cmd_firmware_update_transfer()
782 cci->fw.prev_offset = offset; in cmd_firmware_update_transfer()
783 cci->fw.prev_len = length; in cmd_firmware_update_transfer()
786 cci->fw.prev_offset = offset; in cmd_firmware_update_transfer()
787 cci->fw.prev_len = length; in cmd_firmware_update_transfer()
793 if (fw_transfer->action == CXL_FW_XFER_ACTION_FULL) { in cmd_firmware_update_transfer()
794 cci->bg.runtime = 10 * 1000UL; in cmd_firmware_update_transfer()
796 cci->bg.runtime = 2 * 1000UL; in cmd_firmware_update_transfer()
799 cci->fw.curr_action = fw_transfer->action; in cmd_firmware_update_transfer()
800 cci->fw.curr_slot = fw_transfer->slot; in cmd_firmware_update_transfer()
806 static void __do_firmware_xfer(CXLCCI *cci) in __do_firmware_xfer() argument
808 switch (cci->fw.curr_action) { in __do_firmware_xfer()
811 cci->fw.slot[cci->fw.curr_slot - 1] = true; in __do_firmware_xfer()
812 cci->fw.transferring = false; in __do_firmware_xfer()
816 time(&cci->fw.last_partxfer); in __do_firmware_xfer()
829 CXLCCI *cci) in cmd_firmware_update_activate() argument
837 if (fw_activate->slot == 0 || in cmd_firmware_update_activate()
838 fw_activate->slot == cci->fw.active_slot || in cmd_firmware_update_activate()
839 fw_activate->slot > CXL_FW_SLOTS) { in cmd_firmware_update_activate()
844 if (!cci->fw.slot[fw_activate->slot - 1]) { in cmd_firmware_update_activate()
848 switch (fw_activate->action) { in cmd_firmware_update_activate()
850 cci->fw.active_slot = fw_activate->slot; in cmd_firmware_update_activate()
853 cci->fw.staged_slot = fw_activate->slot; in cmd_firmware_update_activate()
868 CXLCCI *cci) in cmd_timestamp_get() argument
870 CXLDeviceState *cxl_dstate = &CXL_TYPE3(cci->d)->cxl_dstate; in cmd_timestamp_get()
885 CXLCCI *cci) in cmd_timestamp_set() argument
887 CXLDeviceState *cxl_dstate = &CXL_TYPE3(cci->d)->cxl_dstate; in cmd_timestamp_set()
889 cxl_dstate->timestamp.set = true; in cmd_timestamp_set()
890 cxl_dstate->timestamp.last_set = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); in cmd_timestamp_set()
892 cxl_dstate->timestamp.host_set = le64_to_cpu(*(uint64_t *)payload_in); in cmd_timestamp_set()
910 CXLCCI *cci) in cmd_logs_get_supported() argument
922 supported_logs->entries = 1; in cmd_logs_get_supported()
923 supported_logs->log_entries[0].uuid = cel_uuid; in cmd_logs_get_supported()
924 supported_logs->log_entries[0].size = 4 * cci->cel_size; in cmd_logs_get_supported()
936 CXLCCI *cci) in cmd_logs_get_log() argument
946 if (get_log->length > cci->payload_max) { in cmd_logs_get_log()
950 if (!qemu_uuid_is_equal(&get_log->uuid, &cel_uuid)) { in cmd_logs_get_log()
962 * beyond the end of cci->cel_log. in cmd_logs_get_log()
964 if ((uint64_t)get_log->offset + get_log->length >= sizeof(cci->cel_log)) { in cmd_logs_get_log()
969 *len_out = get_log->length; in cmd_logs_get_log()
971 memmove(payload_out, cci->cel_log + get_log->offset, get_log->length); in cmd_logs_get_log()
979 * CXL r3.1 section 8.2.9.6.1 Table 8-96
989 * CXL r3.1 section 8.2.9.6.1 Table 8-97
1005 * CXL rev 3.1 section 8.2.9.6.1 Table 8-97
1037 * CXL r3.1 section 8.2.9.6.2 Table 8-99
1050 * CXL r3.1 section 8.2.9.6.3 Table 8-101
1103 CXLCCI *cci) in cmd_features_get_supported() argument
1118 if (!object_dynamic_cast(OBJECT(cci->d), TYPE_CXL_TYPE3)) { in cmd_features_get_supported()
1121 if (get_feats_in->count < sizeof(CXLSupportedFeatureHeader) || in cmd_features_get_supported()
1122 get_feats_in->start_index >= CXL_FEATURE_MAX) { in cmd_features_get_supported()
1126 req_entries = (get_feats_in->count - in cmd_features_get_supported()
1130 (CXL_FEATURE_MAX - get_feats_in->start_index)); in cmd_features_get_supported()
1132 for (entry = 0, index = get_feats_in->start_index; in cmd_features_get_supported()
1137 get_feats_out->feat_entries[entry++] = in cmd_features_get_supported()
1152 get_feats_out->feat_entries[entry++] = in cmd_features_get_supported()
1169 get_feats_out->hdr.nsuppfeats_dev = CXL_FEATURE_MAX; in cmd_features_get_supported()
1170 get_feats_out->hdr.entries = req_entries; in cmd_features_get_supported()
1183 CXLCCI *cci) in cmd_features_get_feature() argument
1195 if (!object_dynamic_cast(OBJECT(cci->d), TYPE_CXL_TYPE3)) { in cmd_features_get_feature()
1199 ct3d = CXL_TYPE3(cci->d); in cmd_features_get_feature()
1202 set_feat_info = &ct3d->set_feat_info; in cmd_features_get_feature()
1203 if (qemu_uuid_is_equal(&get_feature->uuid, &set_feat_info->uuid)) { in cmd_features_get_feature()
1207 if (get_feature->selection != CXL_GET_FEATURE_SEL_CURRENT_VALUE) { in cmd_features_get_feature()
1210 if (get_feature->offset + get_feature->count > cci->payload_max) { in cmd_features_get_feature()
1214 if (qemu_uuid_is_equal(&get_feature->uuid, &patrol_scrub_uuid)) { in cmd_features_get_feature()
1215 if (get_feature->offset >= sizeof(CXLMemPatrolScrubReadAttrs)) { in cmd_features_get_feature()
1218 bytes_to_copy = sizeof(CXLMemPatrolScrubReadAttrs) - in cmd_features_get_feature()
1219 get_feature->offset; in cmd_features_get_feature()
1220 bytes_to_copy = MIN(bytes_to_copy, get_feature->count); in cmd_features_get_feature()
1222 (uint8_t *)&ct3d->patrol_scrub_attrs + get_feature->offset, in cmd_features_get_feature()
1224 } else if (qemu_uuid_is_equal(&get_feature->uuid, &ecs_uuid)) { in cmd_features_get_feature()
1225 if (get_feature->offset >= sizeof(CXLMemECSReadAttrs)) { in cmd_features_get_feature()
1228 bytes_to_copy = sizeof(CXLMemECSReadAttrs) - get_feature->offset; in cmd_features_get_feature()
1229 bytes_to_copy = MIN(bytes_to_copy, get_feature->count); in cmd_features_get_feature()
1231 (uint8_t *)&ct3d->ecs_attrs + get_feature->offset, in cmd_features_get_feature()
1248 CXLCCI *cci) in cmd_features_set_feature() argument
1265 if (!object_dynamic_cast(OBJECT(cci->d), TYPE_CXL_TYPE3)) { in cmd_features_set_feature()
1268 ct3d = CXL_TYPE3(cci->d); in cmd_features_set_feature()
1269 set_feat_info = &ct3d->set_feat_info; in cmd_features_set_feature()
1271 if (!qemu_uuid_is_null(&set_feat_info->uuid) && in cmd_features_set_feature()
1272 !qemu_uuid_is_equal(&hdr->uuid, &set_feat_info->uuid)) { in cmd_features_set_feature()
1275 if (hdr->flags & CXL_SET_FEAT_DATA_SAVED_ACROSS_RESET) { in cmd_features_set_feature()
1276 set_feat_info->data_saved_across_reset = true; in cmd_features_set_feature()
1278 set_feat_info->data_saved_across_reset = false; in cmd_features_set_feature()
1282 hdr->flags & CXL_SET_FEATURE_FLAG_DATA_TRANSFER_MASK; in cmd_features_set_feature()
1284 set_feat_info->uuid = hdr->uuid; in cmd_features_set_feature()
1285 set_feat_info->data_size = 0; in cmd_features_set_feature()
1287 set_feat_info->data_transfer_flag = data_transfer_flag; in cmd_features_set_feature()
1288 set_feat_info->data_offset = hdr->offset; in cmd_features_set_feature()
1289 bytes_to_copy = len_in - sizeof(CXLSetFeatureInHeader); in cmd_features_set_feature()
1295 if (qemu_uuid_is_equal(&hdr->uuid, &patrol_scrub_uuid)) { in cmd_features_set_feature()
1296 if (hdr->version != CXL_MEMDEV_PS_SET_FEATURE_VERSION) { in cmd_features_set_feature()
1301 ps_write_attrs = &ps_set_feature->feat_data; in cmd_features_set_feature()
1303 if ((uint32_t)hdr->offset + bytes_to_copy > in cmd_features_set_feature()
1304 sizeof(ct3d->patrol_scrub_wr_attrs)) { in cmd_features_set_feature()
1307 memcpy((uint8_t *)&ct3d->patrol_scrub_wr_attrs + hdr->offset, in cmd_features_set_feature()
1310 set_feat_info->data_size += bytes_to_copy; in cmd_features_set_feature()
1314 ct3d->patrol_scrub_attrs.scrub_cycle &= ~0xFF; in cmd_features_set_feature()
1315 ct3d->patrol_scrub_attrs.scrub_cycle |= in cmd_features_set_feature()
1316 ct3d->patrol_scrub_wr_attrs.scrub_cycle_hr & 0xFF; in cmd_features_set_feature()
1317 ct3d->patrol_scrub_attrs.scrub_flags &= ~0x1; in cmd_features_set_feature()
1318 ct3d->patrol_scrub_attrs.scrub_flags |= in cmd_features_set_feature()
1319 ct3d->patrol_scrub_wr_attrs.scrub_flags & 0x1; in cmd_features_set_feature()
1321 } else if (qemu_uuid_is_equal(&hdr->uuid, in cmd_features_set_feature()
1323 if (hdr->version != CXL_ECS_SET_FEATURE_VERSION) { in cmd_features_set_feature()
1328 ecs_write_attrs = ecs_set_feature->feat_data; in cmd_features_set_feature()
1330 if ((uint32_t)hdr->offset + bytes_to_copy > in cmd_features_set_feature()
1331 sizeof(ct3d->ecs_wr_attrs)) { in cmd_features_set_feature()
1334 memcpy((uint8_t *)&ct3d->ecs_wr_attrs + hdr->offset, in cmd_features_set_feature()
1337 set_feat_info->data_size += bytes_to_copy; in cmd_features_set_feature()
1341 ct3d->ecs_attrs.ecs_log_cap = ct3d->ecs_wr_attrs.ecs_log_cap; in cmd_features_set_feature()
1343 ct3d->ecs_attrs.fru_attrs[count].ecs_config = in cmd_features_set_feature()
1344 ct3d->ecs_wr_attrs.fru_attrs[count].ecs_config & 0x1F; in cmd_features_set_feature()
1354 memset(&set_feat_info->uuid, 0, sizeof(QemuUUID)); in cmd_features_set_feature()
1355 if (qemu_uuid_is_equal(&hdr->uuid, &patrol_scrub_uuid)) { in cmd_features_set_feature()
1356 memset(&ct3d->patrol_scrub_wr_attrs, 0, set_feat_info->data_size); in cmd_features_set_feature()
1357 } else if (qemu_uuid_is_equal(&hdr->uuid, &ecs_uuid)) { in cmd_features_set_feature()
1358 memset(&ct3d->ecs_wr_attrs, 0, set_feat_info->data_size); in cmd_features_set_feature()
1360 set_feat_info->data_transfer_flag = 0; in cmd_features_set_feature()
1361 set_feat_info->data_saved_across_reset = false; in cmd_features_set_feature()
1362 set_feat_info->data_offset = 0; in cmd_features_set_feature()
1363 set_feat_info->data_size = 0; in cmd_features_set_feature()
1375 CXLCCI *cci) in cmd_identify_memory_device() argument
1395 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_identify_memory_device()
1397 CXLDeviceState *cxl_dstate = &ct3d->cxl_dstate; in cmd_identify_memory_device()
1399 if ((!QEMU_IS_ALIGNED(cxl_dstate->vmem_size, CXL_CAPACITY_MULTIPLIER)) || in cmd_identify_memory_device()
1400 (!QEMU_IS_ALIGNED(cxl_dstate->pmem_size, CXL_CAPACITY_MULTIPLIER)) || in cmd_identify_memory_device()
1401 (!QEMU_IS_ALIGNED(ct3d->dc.total_capacity, CXL_CAPACITY_MULTIPLIER))) { in cmd_identify_memory_device()
1407 snprintf(id->fw_revision, 0x10, "BWFW VERSION %02d", 0); in cmd_identify_memory_device()
1409 stq_le_p(&id->total_capacity, in cmd_identify_memory_device()
1410 cxl_dstate->static_mem_size / CXL_CAPACITY_MULTIPLIER); in cmd_identify_memory_device()
1411 stq_le_p(&id->persistent_capacity, in cmd_identify_memory_device()
1412 cxl_dstate->pmem_size / CXL_CAPACITY_MULTIPLIER); in cmd_identify_memory_device()
1413 stq_le_p(&id->volatile_capacity, in cmd_identify_memory_device()
1414 cxl_dstate->vmem_size / CXL_CAPACITY_MULTIPLIER); in cmd_identify_memory_device()
1415 stl_le_p(&id->lsa_size, cvc->get_lsa_size(ct3d)); in cmd_identify_memory_device()
1417 st24_le_p(id->poison_list_max_mer, 256); in cmd_identify_memory_device()
1418 /* No limit - so limited by main poison record limit */ in cmd_identify_memory_device()
1419 stw_le_p(&id->inject_poison_limit, 0); in cmd_identify_memory_device()
1420 stw_le_p(&id->dc_event_log_size, CXL_DC_EVENT_LOG_SIZE); in cmd_identify_memory_device()
1432 CXLCCI *cci) in cmd_ccls_get_partition_info() argument
1434 CXLDeviceState *cxl_dstate = &CXL_TYPE3(cci->d)->cxl_dstate; in cmd_ccls_get_partition_info()
1444 if ((!QEMU_IS_ALIGNED(cxl_dstate->vmem_size, CXL_CAPACITY_MULTIPLIER)) || in cmd_ccls_get_partition_info()
1445 (!QEMU_IS_ALIGNED(cxl_dstate->pmem_size, CXL_CAPACITY_MULTIPLIER)) || in cmd_ccls_get_partition_info()
1446 (!QEMU_IS_ALIGNED(ct3d->dc.total_capacity, CXL_CAPACITY_MULTIPLIER))) { in cmd_ccls_get_partition_info()
1450 stq_le_p(&part_info->active_vmem, in cmd_ccls_get_partition_info()
1451 cxl_dstate->vmem_size / CXL_CAPACITY_MULTIPLIER); in cmd_ccls_get_partition_info()
1456 stq_le_p(&part_info->next_vmem, 0); in cmd_ccls_get_partition_info()
1457 stq_le_p(&part_info->active_pmem, in cmd_ccls_get_partition_info()
1458 cxl_dstate->pmem_size / CXL_CAPACITY_MULTIPLIER); in cmd_ccls_get_partition_info()
1459 stq_le_p(&part_info->next_pmem, 0); in cmd_ccls_get_partition_info()
1471 CXLCCI *cci) in cmd_ccls_get_lsa() argument
1477 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_ccls_get_lsa()
1482 offset = get_lsa->offset; in cmd_ccls_get_lsa()
1483 length = get_lsa->length; in cmd_ccls_get_lsa()
1485 if (offset + length > cvc->get_lsa_size(ct3d)) { in cmd_ccls_get_lsa()
1490 *len_out = cvc->get_lsa(ct3d, payload_out, length, offset); in cmd_ccls_get_lsa()
1500 CXLCCI *cci) in cmd_ccls_set_lsa() argument
1508 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_ccls_set_lsa()
1517 if (set_lsa_payload->offset + len_in > cvc->get_lsa_size(ct3d) + hdr_len) { in cmd_ccls_set_lsa()
1520 len_in -= hdr_len; in cmd_ccls_set_lsa()
1522 cvc->set_lsa(ct3d, set_lsa_payload->data, len_in, set_lsa_payload->offset); in cmd_ccls_set_lsa()
1531 if (ct3d->hostvmem) { in __do_sanitization()
1532 mr = host_memory_backend_get_memory(ct3d->hostvmem); in __do_sanitization()
1539 if (ct3d->hostpmem) { in __do_sanitization()
1540 mr = host_memory_backend_get_memory(ct3d->hostpmem); in __do_sanitization()
1546 if (ct3d->lsa) { in __do_sanitization()
1547 mr = host_memory_backend_get_memory(ct3d->lsa); in __do_sanitization()
1553 cxl_discard_all_event_records(&ct3d->cxl_dstate); in __do_sanitization()
1577 CXLCCI *cci) in cmd_sanitize_overwrite() argument
1579 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_sanitize_overwrite()
1583 total_mem = (ct3d->cxl_dstate.vmem_size + ct3d->cxl_dstate.pmem_size) >> 20; in cmd_sanitize_overwrite()
1613 cci->bg.runtime = secs * 1000UL; in cmd_sanitize_overwrite()
1616 cxl_dev_disable_media(&ct3d->cxl_dstate); in cmd_sanitize_overwrite()
1627 CXLCCI *cci) in cmd_get_security_state() argument
1649 CXLCCI *cci) in cmd_media_get_poison_list() argument
1671 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_media_get_poison_list()
1674 CXLPoisonList *poison_list = &ct3d->poison_list; in cmd_media_get_poison_list()
1678 query_start = ldq_le_p(&in->pa); in cmd_media_get_poison_list()
1683 query_length = ldq_le_p(&in->length) * CXL_CACHE_LINE_SIZE; in cmd_media_get_poison_list()
1687 if (!ranges_overlap(ent->start, ent->length, in cmd_media_get_poison_list()
1693 out_pl_len = sizeof(*out) + record_count * sizeof(out->records[0]); in cmd_media_get_poison_list()
1700 if (!ranges_overlap(ent->start, ent->length, in cmd_media_get_poison_list()
1706 start = MAX(ROUND_DOWN(ent->start, 64ull), query_start); in cmd_media_get_poison_list()
1707 stop = MIN(ROUND_DOWN(ent->start, 64ull) + ent->length, in cmd_media_get_poison_list()
1709 stq_le_p(&out->records[i].addr, start | (ent->type & 0x7)); in cmd_media_get_poison_list()
1710 stl_le_p(&out->records[i].length, (stop - start) / CXL_CACHE_LINE_SIZE); in cmd_media_get_poison_list()
1713 if (ct3d->poison_list_overflowed) { in cmd_media_get_poison_list()
1714 out->flags = (1 << 1); in cmd_media_get_poison_list()
1715 stq_le_p(&out->overflow_timestamp, ct3d->poison_list_overflow_ts); in cmd_media_get_poison_list()
1717 if (scan_media_running(cci)) { in cmd_media_get_poison_list()
1718 out->flags |= (1 << 2); in cmd_media_get_poison_list()
1721 stw_le_p(&out->count, record_count); in cmd_media_get_poison_list()
1732 CXLCCI *cci) in cmd_media_inject_poison() argument
1734 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_media_inject_poison()
1735 CXLPoisonList *poison_list = &ct3d->poison_list; in cmd_media_inject_poison()
1741 uint64_t dpa = ldq_le_p(&in->dpa); in cmd_media_inject_poison()
1745 if (dpa >= ent->start && in cmd_media_inject_poison()
1746 dpa + CXL_CACHE_LINE_SIZE <= ent->start + ent->length) { in cmd_media_inject_poison()
1751 * Freeze the list if there is an on-going scan media operation. in cmd_media_inject_poison()
1753 if (scan_media_running(cci)) { in cmd_media_inject_poison()
1755 * XXX: Spec is ambiguous - is this case considered in cmd_media_inject_poison()
1761 if (ct3d->poison_list_cnt == CXL_POISON_LIST_LIMIT) { in cmd_media_inject_poison()
1766 p->length = CXL_CACHE_LINE_SIZE; in cmd_media_inject_poison()
1767 p->start = dpa; in cmd_media_inject_poison()
1768 p->type = CXL_POISON_TYPE_INJECTED; in cmd_media_inject_poison()
1774 ct3d->poison_list_cnt++; in cmd_media_inject_poison()
1787 CXLCCI *cci) in cmd_media_clear_poison() argument
1789 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_media_clear_poison()
1790 CXLDeviceState *cxl_dstate = &ct3d->cxl_dstate; in cmd_media_clear_poison()
1791 CXLPoisonList *poison_list = &ct3d->poison_list; in cmd_media_clear_poison()
1802 dpa = ldq_le_p(&in->dpa); in cmd_media_clear_poison()
1803 if (dpa + CXL_CACHE_LINE_SIZE > cxl_dstate->static_mem_size + in cmd_media_clear_poison()
1804 ct3d->dc.total_capacity) { in cmd_media_clear_poison()
1809 if (cvc->set_cacheline) { in cmd_media_clear_poison()
1810 if (!cvc->set_cacheline(ct3d, dpa, in->data)) { in cmd_media_clear_poison()
1816 * Freeze the list if there is an on-going scan media operation. in cmd_media_clear_poison()
1818 if (scan_media_running(cci)) { in cmd_media_clear_poison()
1820 * XXX: Spec is ambiguous - is this case considered in cmd_media_clear_poison()
1831 if ((dpa >= ent->start) && (dpa < ent->start + ent->length)) { in cmd_media_clear_poison()
1840 ct3d->poison_list_cnt--; in cmd_media_clear_poison()
1842 if (dpa > ent->start) { in cmd_media_clear_poison()
1848 frag->start = ent->start; in cmd_media_clear_poison()
1849 frag->length = dpa - ent->start; in cmd_media_clear_poison()
1850 frag->type = ent->type; in cmd_media_clear_poison()
1853 ct3d->poison_list_cnt++; in cmd_media_clear_poison()
1856 if (dpa + CXL_CACHE_LINE_SIZE < ent->start + ent->length) { in cmd_media_clear_poison()
1859 if (ct3d->poison_list_cnt == CXL_POISON_LIST_LIMIT) { in cmd_media_clear_poison()
1864 frag->start = dpa + CXL_CACHE_LINE_SIZE; in cmd_media_clear_poison()
1865 frag->length = ent->start + ent->length - frag->start; in cmd_media_clear_poison()
1866 frag->type = ent->type; in cmd_media_clear_poison()
1868 ct3d->poison_list_cnt++; in cmd_media_clear_poison()
1888 CXLCCI *cci) in cmd_media_get_scan_media_capabilities() argument
1899 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_media_get_scan_media_capabilities()
1900 CXLDeviceState *cxl_dstate = &ct3d->cxl_dstate; in cmd_media_get_scan_media_capabilities()
1906 query_start = ldq_le_p(&in->pa); in cmd_media_get_scan_media_capabilities()
1911 query_length = ldq_le_p(&in->length) * CXL_CACHE_LINE_SIZE; in cmd_media_get_scan_media_capabilities()
1913 if (query_start + query_length > cxl_dstate->static_mem_size) { in cmd_media_get_scan_media_capabilities()
1918 * Just use 400 nanosecond access/read latency + 100 ns for in cmd_media_get_scan_media_capabilities()
1922 stl_le_p(&out->estimated_runtime_ms, in cmd_media_get_scan_media_capabilities()
1934 QLIST_FOREACH(ent, &ct3d->scan_media_results, node) { in __do_scan_media()
1939 if (ct3d->poison_list_overflowed && in __do_scan_media()
1940 ct3d->poison_list_cnt == results_cnt) { in __do_scan_media()
1944 ct3d->scan_media_hasrun = true; in __do_scan_media()
1955 CXLCCI *cci) in cmd_media_scan_media() argument
1964 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_media_scan_media()
1965 CXLDeviceState *cxl_dstate = &ct3d->cxl_dstate; in cmd_media_scan_media()
1970 query_start = ldq_le_p(&in->pa); in cmd_media_scan_media()
1975 query_length = ldq_le_p(&in->length) * CXL_CACHE_LINE_SIZE; in cmd_media_scan_media()
1977 if (query_start + query_length > cxl_dstate->static_mem_size) { in cmd_media_scan_media()
1980 if (ct3d->dc.num_regions && query_start + query_length >= in cmd_media_scan_media()
1981 cxl_dstate->static_mem_size + ct3d->dc.total_capacity) { in cmd_media_scan_media()
1985 if (in->flags == 0) { /* TODO */ in cmd_media_scan_media()
1991 QLIST_FOREACH_SAFE(ent, &ct3d->scan_media_results, node, next) { in cmd_media_scan_media()
1996 /* kill the poison list - it will be recreated */ in cmd_media_scan_media()
1997 if (ct3d->poison_list_overflowed) { in cmd_media_scan_media()
1998 QLIST_FOREACH_SAFE(ent, &ct3d->poison_list, node, next) { in cmd_media_scan_media()
2001 ct3d->poison_list_cnt--; in cmd_media_scan_media()
2010 QLIST_FOREACH_SAFE(ent, &ct3d->poison_list_bkp, node, next) { in cmd_media_scan_media()
2013 if (ent->start >= query_start + query_length || in cmd_media_scan_media()
2014 ent->start + ent->length <= query_start) { in cmd_media_scan_media()
2023 if (ct3d->poison_list_cnt < CXL_POISON_LIST_LIMIT) { in cmd_media_scan_media()
2026 p->start = ent->start; in cmd_media_scan_media()
2027 p->length = ent->length; in cmd_media_scan_media()
2028 p->type = ent->type; in cmd_media_scan_media()
2029 QLIST_INSERT_HEAD(&ct3d->poison_list, p, node); in cmd_media_scan_media()
2030 ct3d->poison_list_cnt++; in cmd_media_scan_media()
2034 res->start = ent->start; in cmd_media_scan_media()
2035 res->length = ent->length; in cmd_media_scan_media()
2036 res->type = ent->type; in cmd_media_scan_media()
2037 QLIST_INSERT_HEAD(&ct3d->scan_media_results, res, node); in cmd_media_scan_media()
2043 cci->bg.runtime = MAX(1, query_length * (0.0005L / 64)); in cmd_media_scan_media()
2057 CXLCCI *cci) in cmd_media_get_scan_media_results() argument
2074 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_media_get_scan_media_results()
2075 CXLPoisonList *scan_media_results = &ct3d->scan_media_results; in cmd_media_get_scan_media_results()
2080 if (!ct3d->scan_media_hasrun) { in cmd_media_get_scan_media_results()
2089 size_t rec_size = record_count * sizeof(out->records[0]); in cmd_media_get_scan_media_results()
2097 out_pl_len = sizeof(*out) + record_count * sizeof(out->records[0]); in cmd_media_get_scan_media_results()
2108 start = ROUND_DOWN(ent->start, 64ull); in cmd_media_get_scan_media_results()
2109 stop = ROUND_DOWN(ent->start, 64ull) + ent->length; in cmd_media_get_scan_media_results()
2110 stq_le_p(&out->records[i].addr, start); in cmd_media_get_scan_media_results()
2111 stl_le_p(&out->records[i].length, (stop - start) / CXL_CACHE_LINE_SIZE); in cmd_media_get_scan_media_results()
2119 stw_le_p(&out->count, record_count); in cmd_media_get_scan_media_results()
2121 out->flags = (1 << 0); /* More Media Error Records */ in cmd_media_get_scan_media_results()
2137 CXLCCI *cci) in cmd_dcd_get_dyn_cap_config() argument
2139 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_dcd_get_dyn_cap_config()
2169 start_rid = in->start_rid; in cmd_dcd_get_dyn_cap_config()
2170 if (start_rid >= ct3d->dc.num_regions) { in cmd_dcd_get_dyn_cap_config()
2174 record_count = MIN(ct3d->dc.num_regions - in->start_rid, in->region_cnt); in cmd_dcd_get_dyn_cap_config()
2176 out_pl_len = sizeof(*out) + record_count * sizeof(out->records[0]); in cmd_dcd_get_dyn_cap_config()
2181 out->num_regions = ct3d->dc.num_regions; in cmd_dcd_get_dyn_cap_config()
2182 out->regions_returned = record_count; in cmd_dcd_get_dyn_cap_config()
2184 stq_le_p(&out->records[i].base, in cmd_dcd_get_dyn_cap_config()
2185 ct3d->dc.regions[start_rid + i].base); in cmd_dcd_get_dyn_cap_config()
2186 stq_le_p(&out->records[i].decode_len, in cmd_dcd_get_dyn_cap_config()
2187 ct3d->dc.regions[start_rid + i].decode_len / in cmd_dcd_get_dyn_cap_config()
2189 stq_le_p(&out->records[i].region_len, in cmd_dcd_get_dyn_cap_config()
2190 ct3d->dc.regions[start_rid + i].len); in cmd_dcd_get_dyn_cap_config()
2191 stq_le_p(&out->records[i].block_size, in cmd_dcd_get_dyn_cap_config()
2192 ct3d->dc.regions[start_rid + i].block_size); in cmd_dcd_get_dyn_cap_config()
2193 stl_le_p(&out->records[i].dsmadhandle, in cmd_dcd_get_dyn_cap_config()
2194 ct3d->dc.regions[start_rid + i].dsmadhandle); in cmd_dcd_get_dyn_cap_config()
2195 out->records[i].flags = ct3d->dc.regions[start_rid + i].flags; in cmd_dcd_get_dyn_cap_config()
2201 stl_le_p(&extra_out->num_extents_supported, CXL_NUM_EXTENTS_SUPPORTED); in cmd_dcd_get_dyn_cap_config()
2202 stl_le_p(&extra_out->num_extents_available, CXL_NUM_EXTENTS_SUPPORTED - in cmd_dcd_get_dyn_cap_config()
2203 ct3d->dc.total_extent_count); in cmd_dcd_get_dyn_cap_config()
2204 stl_le_p(&extra_out->num_tags_supported, CXL_NUM_TAGS_SUPPORTED); in cmd_dcd_get_dyn_cap_config()
2205 stl_le_p(&extra_out->num_tags_available, CXL_NUM_TAGS_SUPPORTED); in cmd_dcd_get_dyn_cap_config()
2220 CXLCCI *cci) in cmd_dcd_get_dyn_cap_ext_list() argument
2222 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_dcd_get_dyn_cap_ext_list()
2234 uint32_t start_extent_id = in->start_extent_id; in cmd_dcd_get_dyn_cap_ext_list()
2235 CXLDCExtentList *extent_list = &ct3d->dc.extents; in cmd_dcd_get_dyn_cap_ext_list()
2240 if (start_extent_id > ct3d->dc.total_extent_count) { in cmd_dcd_get_dyn_cap_ext_list()
2244 record_count = MIN(in->extent_cnt, in cmd_dcd_get_dyn_cap_ext_list()
2245 ct3d->dc.total_extent_count - start_extent_id); in cmd_dcd_get_dyn_cap_ext_list()
2246 size = CXL_MAILBOX_MAX_PAYLOAD_SIZE - sizeof(*out); in cmd_dcd_get_dyn_cap_ext_list()
2247 record_count = MIN(record_count, size / sizeof(out->records[0])); in cmd_dcd_get_dyn_cap_ext_list()
2248 out_pl_len = sizeof(*out) + record_count * sizeof(out->records[0]); in cmd_dcd_get_dyn_cap_ext_list()
2250 stl_le_p(&out->count, record_count); in cmd_dcd_get_dyn_cap_ext_list()
2251 stl_le_p(&out->total_extents, ct3d->dc.total_extent_count); in cmd_dcd_get_dyn_cap_ext_list()
2252 stl_le_p(&out->generation_num, ct3d->dc.ext_list_gen_seq); in cmd_dcd_get_dyn_cap_ext_list()
2255 CXLDCExtentRaw *out_rec = &out->records[record_done]; in cmd_dcd_get_dyn_cap_ext_list()
2261 stq_le_p(&out_rec->start_dpa, ent->start_dpa); in cmd_dcd_get_dyn_cap_ext_list()
2262 stq_le_p(&out_rec->len, ent->len); in cmd_dcd_get_dyn_cap_ext_list()
2263 memcpy(&out_rec->tag, ent->tag, 0x10); in cmd_dcd_get_dyn_cap_ext_list()
2264 stw_le_p(&out_rec->shared_seq, ent->shared_seq); in cmd_dcd_get_dyn_cap_ext_list()
2293 CXLDCRegion *region = &ct3d->dc.regions[0]; in cxl_find_dc_region()
2295 if (dpa < region->base || in cxl_find_dc_region()
2296 dpa >= region->base + ct3d->dc.total_capacity) { in cxl_find_dc_region()
2303 * Regions are used in increasing-DPA order, with Region 0 being used for in cxl_find_dc_region()
2308 for (i = ct3d->dc.num_regions - 1; i >= 0; i--) { in cxl_find_dc_region()
2309 region = &ct3d->dc.regions[i]; in cxl_find_dc_region()
2310 if (dpa >= region->base) { in cxl_find_dc_region()
2311 if (dpa + len > region->base + region->len) { in cxl_find_dc_region()
2330 extent->start_dpa = dpa; in cxl_insert_extent_to_extent_list()
2331 extent->len = len; in cxl_insert_extent_to_extent_list()
2333 memcpy(extent->tag, tag, 0x10); in cxl_insert_extent_to_extent_list()
2335 extent->shared_seq = shared_seq; in cxl_insert_extent_to_extent_list()
2360 QTAILQ_INIT(&group->list); in cxl_insert_extent_to_extent_group()
2362 cxl_insert_extent_to_extent_list(&group->list, dpa, len, in cxl_insert_extent_to_extent_group()
2379 QTAILQ_FOREACH_SAFE(ent, &group->list, node, ent_next) { in cxl_extent_group_list_delete_front()
2380 cxl_remove_extent_from_extent_list(&group->list, ent); in cxl_extent_group_list_delete_front()
2386 * CXL r3.1 Table 8-168: Add Dynamic Capacity Response Input Payload
2387 * CXL r3.1 Table 8-170: Release Dynamic Capacity Input Payload
2393 /* CXL r3.1 Table 8-169: Updated Extent */
2414 CXLDCRegion *lastregion = &ct3d->dc.regions[ct3d->dc.num_regions - 1]; in cxl_detect_malformed_extent_list()
2419 for (i = 0; i < ct3d->dc.num_regions; i++) { in cxl_detect_malformed_extent_list()
2420 region = &ct3d->dc.regions[i]; in cxl_detect_malformed_extent_list()
2421 min_block_size = MIN(min_block_size, region->block_size); in cxl_detect_malformed_extent_list()
2424 blk_bitmap = bitmap_new((lastregion->base + lastregion->len - in cxl_detect_malformed_extent_list()
2425 ct3d->dc.regions[0].base) / min_block_size); in cxl_detect_malformed_extent_list()
2427 for (i = 0; i < in->num_entries_updated; i++) { in cxl_detect_malformed_extent_list()
2428 dpa = in->updated_entries[i].start_dpa; in cxl_detect_malformed_extent_list()
2429 len = in->updated_entries[i].len; in cxl_detect_malformed_extent_list()
2436 dpa -= ct3d->dc.regions[0].base; in cxl_detect_malformed_extent_list()
2437 if (dpa % region->block_size || len % region->block_size) { in cxl_detect_malformed_extent_list()
2460 for (i = 0; i < in->num_entries_updated; i++) { in cxl_dcd_add_dyn_cap_rsp_dry_run()
2461 dpa = in->updated_entries[i].start_dpa; in cxl_dcd_add_dyn_cap_rsp_dry_run()
2462 len = in->updated_entries[i].len; in cxl_dcd_add_dyn_cap_rsp_dry_run()
2467 * The host-accepted DPA range must be contained by the first extent in cxl_dcd_add_dyn_cap_rsp_dry_run()
2470 ext_group = QTAILQ_FIRST(&ct3d->dc.extents_pending); in cxl_dcd_add_dyn_cap_rsp_dry_run()
2471 if (!cxl_extents_contains_dpa_range(&ext_group->list, dpa, len)) { in cxl_dcd_add_dyn_cap_rsp_dry_run()
2475 /* to-be-added range should not overlap with range already accepted */ in cxl_dcd_add_dyn_cap_rsp_dry_run()
2476 QTAILQ_FOREACH(ent, &ct3d->dc.extents, node) { in cxl_dcd_add_dyn_cap_rsp_dry_run()
2477 range_init_nofail(&range2, ent->start_dpa, ent->len); in cxl_dcd_add_dyn_cap_rsp_dry_run()
2496 CXLCCI *cci) in cmd_dcd_add_dyn_cap_rsp() argument
2499 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_dcd_add_dyn_cap_rsp()
2500 CXLDCExtentList *extent_list = &ct3d->dc.extents; in cmd_dcd_add_dyn_cap_rsp()
2509 if (in->num_entries_updated == 0) { in cmd_dcd_add_dyn_cap_rsp()
2510 cxl_extent_group_list_delete_front(&ct3d->dc.extents_pending); in cmd_dcd_add_dyn_cap_rsp()
2515 sizeof(*in) + sizeof(*in->updated_entries) * in->num_entries_updated) { in cmd_dcd_add_dyn_cap_rsp()
2520 if (in->num_entries_updated + ct3d->dc.total_extent_count > in cmd_dcd_add_dyn_cap_rsp()
2535 for (i = 0; i < in->num_entries_updated; i++) { in cmd_dcd_add_dyn_cap_rsp()
2536 dpa = in->updated_entries[i].start_dpa; in cmd_dcd_add_dyn_cap_rsp()
2537 len = in->updated_entries[i].len; in cmd_dcd_add_dyn_cap_rsp()
2540 ct3d->dc.total_extent_count += 1; in cmd_dcd_add_dyn_cap_rsp()
2544 cxl_extent_group_list_delete_front(&ct3d->dc.extents_pending); in cmd_dcd_add_dyn_cap_rsp()
2564 cxl_insert_extent_to_extent_list(dst, ent->start_dpa, ent->len, in copy_extent_list()
2565 ent->tag, ent->shared_seq); in copy_extent_list()
2582 copy_extent_list(updated_list, &ct3d->dc.extents); in cxl_dc_extent_release_dry_run()
2584 for (i = 0; i < in->num_entries_updated; i++) { in cxl_dc_extent_release_dry_run()
2587 dpa = in->updated_entries[i].start_dpa; in cxl_dc_extent_release_dry_run()
2588 len = in->updated_entries[i].len; in cxl_dc_extent_release_dry_run()
2599 range_init_nofail(&range, ent->start_dpa, ent->len); in cxl_dc_extent_release_dry_run()
2603 uint64_t ent_start_dpa = ent->start_dpa; in cxl_dc_extent_release_dry_run()
2604 uint64_t ent_len = ent->len; in cxl_dc_extent_release_dry_run()
2606 len1 = dpa - ent->start_dpa; in cxl_dc_extent_release_dry_run()
2608 if (range_contains(&range, dpa + len - 1)) { in cxl_dc_extent_release_dry_run()
2609 len2 = ent_start_dpa + ent_len - dpa - len; in cxl_dc_extent_release_dry_run()
2613 len_done = ent_len - len1 - len2; in cxl_dc_extent_release_dry_run()
2616 cnt_delta--; in cxl_dc_extent_release_dry_run()
2631 if (cnt_delta + ct3d->dc.total_extent_count > in cxl_dc_extent_release_dry_run()
2637 len -= len_done; in cxl_dc_extent_release_dry_run()
2650 *updated_list_size = ct3d->dc.total_extent_count + cnt_delta; in cxl_dc_extent_release_dry_run()
2664 CXLCCI *cci) in cmd_dcd_release_dyn_cap() argument
2667 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in cmd_dcd_release_dyn_cap()
2677 if (in->num_entries_updated == 0) { in cmd_dcd_release_dyn_cap()
2682 sizeof(*in) + sizeof(*in->updated_entries) * in->num_entries_updated) { in cmd_dcd_release_dyn_cap()
2703 QTAILQ_FOREACH_SAFE(ent, &ct3d->dc.extents, node, ent_next) { in cmd_dcd_release_dyn_cap()
2704 ct3_clear_region_block_backed(ct3d, ent->start_dpa, ent->len); in cmd_dcd_release_dyn_cap()
2705 cxl_remove_extent_from_extent_list(&ct3d->dc.extents, ent); in cmd_dcd_release_dyn_cap()
2707 copy_extent_list(&ct3d->dc.extents, &updated_list); in cmd_dcd_release_dyn_cap()
2709 ct3_set_region_block_backed(ct3d, ent->start_dpa, ent->len); in cmd_dcd_release_dyn_cap()
2712 ct3d->dc.total_extent_count = updated_list_size; in cmd_dcd_release_dyn_cap()
2820 int cxl_process_cci_message(CXLCCI *cci, uint8_t set, uint8_t cmd, in cxl_process_cci_message() argument
2830 cxl_cmd = &cci->cxl_cmd_set[set][cmd]; in cxl_process_cci_message()
2831 h = cxl_cmd->handler; in cxl_process_cci_message()
2838 if (len_in != cxl_cmd->in && cxl_cmd->in != ~0) { in cxl_process_cci_message()
2843 if ((cxl_cmd->effect & CXL_MBOX_BACKGROUND_OPERATION) && in cxl_process_cci_message()
2844 cci->bg.runtime > 0) { in cxl_process_cci_message()
2849 if (object_dynamic_cast(OBJECT(cci->d), TYPE_CXL_TYPE3)) { in cxl_process_cci_message()
2850 cxl_dstate = &CXL_TYPE3(cci->d)->cxl_dstate; in cxl_process_cci_message()
2869 ret = (*h)(cxl_cmd, pl_in, len_in, pl_out, len_out, cci); in cxl_process_cci_message()
2870 if ((cxl_cmd->effect & CXL_MBOX_BACKGROUND_OPERATION) && in cxl_process_cci_message()
2881 cci->bg.opcode = (set << 8) | cmd; in cxl_process_cci_message()
2883 cci->bg.complete_pct = 0; in cxl_process_cci_message()
2884 cci->bg.ret_code = 0; in cxl_process_cci_message()
2887 cci->bg.starttime = now; in cxl_process_cci_message()
2888 timer_mod(cci->bg.timer, now + CXL_MBOX_BG_UPDATE_FREQ); in cxl_process_cci_message()
2896 CXLCCI *cci = opaque; in bg_timercb() local
2898 uint64_t total_time = cci->bg.starttime + cci->bg.runtime; in bg_timercb()
2900 assert(cci->bg.runtime > 0); in bg_timercb()
2905 cci->bg.complete_pct = 100; in bg_timercb()
2906 cci->bg.ret_code = ret; in bg_timercb()
2907 switch (cci->bg.opcode) { in bg_timercb()
2909 __do_firmware_xfer(cci); in bg_timercb()
2913 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in bg_timercb()
2916 cxl_dev_enable_media(&ct3d->cxl_dstate); in bg_timercb()
2921 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in bg_timercb()
2932 cci->bg.complete_pct = in bg_timercb()
2933 100 * (now - cci->bg.starttime) / cci->bg.runtime; in bg_timercb()
2934 timer_mod(cci->bg.timer, now + CXL_MBOX_BG_UPDATE_FREQ); in bg_timercb()
2937 if (cci->bg.complete_pct == 100) { in bg_timercb()
2938 /* TODO: generalize to switch CCI */ in bg_timercb()
2939 CXLType3Dev *ct3d = CXL_TYPE3(cci->d); in bg_timercb()
2940 CXLDeviceState *cxl_dstate = &ct3d->cxl_dstate; in bg_timercb()
2941 PCIDevice *pdev = PCI_DEVICE(cci->d); in bg_timercb()
2943 cci->bg.starttime = 0; in bg_timercb()
2944 /* registers are updated, allow new bg-capable cmds */ in bg_timercb()
2945 cci->bg.runtime = 0; in bg_timercb()
2948 msix_notify(pdev, cxl_dstate->mbox_msi_n); in bg_timercb()
2950 msi_notify(pdev, cxl_dstate->mbox_msi_n); in bg_timercb()
2955 static void cxl_rebuild_cel(CXLCCI *cci) in cxl_rebuild_cel() argument
2957 cci->cel_size = 0; /* Reset for a fresh build */ in cxl_rebuild_cel()
2960 if (cci->cxl_cmd_set[set][cmd].handler) { in cxl_rebuild_cel()
2961 const struct cxl_cmd *c = &cci->cxl_cmd_set[set][cmd]; in cxl_rebuild_cel()
2963 &cci->cel_log[cci->cel_size]; in cxl_rebuild_cel()
2965 log->opcode = (set << 8) | cmd; in cxl_rebuild_cel()
2966 log->effect = c->effect; in cxl_rebuild_cel()
2967 cci->cel_size++; in cxl_rebuild_cel()
2973 void cxl_init_cci(CXLCCI *cci, size_t payload_max) in cxl_init_cci() argument
2975 cci->payload_max = payload_max; in cxl_init_cci()
2976 cxl_rebuild_cel(cci); in cxl_init_cci()
2978 cci->bg.complete_pct = 0; in cxl_init_cci()
2979 cci->bg.starttime = 0; in cxl_init_cci()
2980 cci->bg.runtime = 0; in cxl_init_cci()
2981 cci->bg.timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, in cxl_init_cci()
2982 bg_timercb, cci); in cxl_init_cci()
2984 memset(&cci->fw, 0, sizeof(cci->fw)); in cxl_init_cci()
2985 cci->fw.active_slot = 1; in cxl_init_cci()
2986 cci->fw.slot[cci->fw.active_slot - 1] = true; in cxl_init_cci()
2989 static void cxl_copy_cci_commands(CXLCCI *cci, const struct cxl_cmd (*cxl_cmds)[256]) in cxl_copy_cci_commands() argument
2994 cci->cxl_cmd_set[set][cmd] = cxl_cmds[set][cmd]; in cxl_copy_cci_commands()
3000 void cxl_add_cci_commands(CXLCCI *cci, const struct cxl_cmd (*cxl_cmd_set)[256], in cxl_add_cci_commands() argument
3003 cci->payload_max = MAX(payload_max, cci->payload_max); in cxl_add_cci_commands()
3004 cxl_copy_cci_commands(cci, cxl_cmd_set); in cxl_add_cci_commands()
3005 cxl_rebuild_cel(cci); in cxl_add_cci_commands()
3008 void cxl_initialize_mailbox_swcci(CXLCCI *cci, DeviceState *intf, in cxl_initialize_mailbox_swcci() argument
3011 cxl_copy_cci_commands(cci, cxl_cmd_set_sw); in cxl_initialize_mailbox_swcci()
3012 cci->d = d; in cxl_initialize_mailbox_swcci()
3013 cci->intf = intf; in cxl_initialize_mailbox_swcci()
3014 cxl_init_cci(cci, payload_max); in cxl_initialize_mailbox_swcci()
3017 void cxl_initialize_mailbox_t3(CXLCCI *cci, DeviceState *d, size_t payload_max) in cxl_initialize_mailbox_t3() argument
3021 cxl_copy_cci_commands(cci, cxl_cmd_set); in cxl_initialize_mailbox_t3()
3022 if (ct3d->dc.num_regions) { in cxl_initialize_mailbox_t3()
3023 cxl_copy_cci_commands(cci, cxl_cmd_set_dcd); in cxl_initialize_mailbox_t3()
3025 cci->d = d; in cxl_initialize_mailbox_t3()
3028 cci->intf = d; in cxl_initialize_mailbox_t3()
3029 cxl_init_cci(cci, payload_max); in cxl_initialize_mailbox_t3()
3039 void cxl_initialize_t3_ld_cci(CXLCCI *cci, DeviceState *d, DeviceState *intf, in cxl_initialize_t3_ld_cci() argument
3042 cxl_copy_cci_commands(cci, cxl_cmd_set_t3_ld); in cxl_initialize_t3_ld_cci()
3043 cci->d = d; in cxl_initialize_t3_ld_cci()
3044 cci->intf = intf; in cxl_initialize_t3_ld_cci()
3045 cxl_init_cci(cci, payload_max); in cxl_initialize_t3_ld_cci()
3058 void cxl_initialize_t3_fm_owned_ld_mctpcci(CXLCCI *cci, DeviceState *d, in cxl_initialize_t3_fm_owned_ld_mctpcci() argument
3062 cxl_copy_cci_commands(cci, cxl_cmd_set_t3_fm_owned_ld_mctp); in cxl_initialize_t3_fm_owned_ld_mctpcci()
3063 cci->d = d; in cxl_initialize_t3_fm_owned_ld_mctpcci()
3064 cci->intf = intf; in cxl_initialize_t3_fm_owned_ld_mctpcci()
3065 cxl_init_cci(cci, payload_max); in cxl_initialize_t3_fm_owned_ld_mctpcci()