new file mode 100644
@@ -0,0 +1,85 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+
+#include "hw/cxl/cxl_mctp_message.h"
+
+#define BUFFER_SIZE 4096
+
+void read_qmp_response(int sockfd)
+{
+ char buffer[BUFFER_SIZE];
+ memset(buffer, 0, BUFFER_SIZE);
+ int len = read(sockfd, buffer, BUFFER_SIZE - 1);
+ if (len > 0) {
+ printf("QMP Response:\n%s\n", buffer);
+ }
+}
+
+static void send_qmp_command(int sockfd, const char *cmd)
+{
+ send(sockfd, cmd, strlen(cmd), 0);
+}
+
+static void send_qmp_cap_command(int sockfd)
+{
+ const char *cap_cmd = "{ \"execute\": \"qmp_capabilities\" }\n";
+ send_qmp_command(sockfd, cap_cmd);
+ read_qmp_response(sockfd);
+}
+
+static int connect_to_qmp(const char *server, uint16_t port)
+{
+ int sockfd;
+ struct sockaddr_in serv_addr;
+
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if (sockfd < 0) {
+ return -1;
+ }
+
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_port = htons(port);
+
+ if (inet_pton(AF_INET, server, &serv_addr.sin_addr) <= 0) {
+ return -1;
+ }
+
+ if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
+ return -1;
+ }
+
+ send_qmp_cap_command(sockfd);
+
+ return sockfd;
+}
+
+int setup_mctp_qmp_connection(const char *qmp_str)
+{
+ char host[256];
+ uint16_t port;
+
+ memset(host, 0, 256);
+ if (sscanf(qmp_str, "%255[^:]:%hu", host, &port) != 2) {
+ return -1;
+ }
+
+ return connect_to_qmp(host, port);
+}
+
+void qmp_cxl_mctp_process_cci_message(const int sockfd, const char *cci_name)
+{
+ char command[256];
+
+ memset(command, 0, 256);
+ sprintf(command, "{ \"execute\": \"cxl-process-mctp-message\", \
+ \"arguments\": { \
+ \"cci-name\": \"%s\" \
+}}\n", cci_name);
+ send_qmp_command(sockfd, command);
+ read_qmp_response(sockfd);
+}
@@ -29,6 +29,7 @@
#include "hw/pci/pcie_port.h"
#include "hw/qdev-properties.h"
#include "hw/registerfields.h"
+#include "hw/cxl/cxl_mctp_message.h"
#define TYPE_I2C_MCTP_CXL "i2c_mctp_cxl"
@@ -83,6 +84,10 @@ struct I2C_MCTP_CXL_State {
int64_t pos;
uint8_t buffer[MCTP_CXL_MAX_MSG_LEN];
uint8_t scratch[MCTP_CXL_MAX_MSG_LEN];
+ char *qmp_str;
+ int qmp_fd;
+
+ bool mctp_msg_forward;
};
OBJECT_DECLARE_SIMPLE_TYPE(I2C_MCTP_CXL_State, I2C_MCTP_CXL)
@@ -90,6 +95,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(I2C_MCTP_CXL_State, I2C_MCTP_CXL)
static const Property i2c_mctp_cxl_props[] = {
DEFINE_PROP_LINK("target", I2C_MCTP_CXL_State,
target, TYPE_PCI_DEVICE, PCIDevice *),
+ DEFINE_PROP_STRING("qmp", I2C_MCTP_CXL_State, qmp_str),
+ DEFINE_PROP_BOOL("mctp-msg-forward", I2C_MCTP_CXL_State,
+ mctp_msg_forward, false),
};
static size_t i2c_mctp_cxl_get_buf(MCTPI2CEndpoint *mctp,
@@ -211,12 +219,46 @@ static void i2c_mctp_cxl_handle_message(MCTPI2CEndpoint *mctp)
len_in = msg->pl_length[2] << 16 | msg->pl_length[1] << 8 |
msg->pl_length[0];
-
- rc = cxl_process_cci_message(s->cci, msg->command_set, msg->command,
- len_in, msg->payload,
- &len_out,
- s->scratch + sizeof(CXLMCTPMessage),
- &bg_started);
+ if (s->mctp_msg_forward) {
+ CXLType3Dev *ct3d = CXL_TYPE3(s->target);
+ CXLMCTPCommandBuf *mctp_buf;
+ int i;
+ char *cci_name = NULL;
+
+ g_assert(cci_map_buf);
+ g_assert(ct3d->mctp_shared_buffer);
+
+ for (i = 0; i < cci_map_buf->num_mappings; i++) {
+ if (cci_map_buf->maps[i].cci_pointer == s->cci) {
+ break;
+ }
+ }
+
+ g_assert(i < cci_map_buf->num_mappings);
+ cci_name = cci_map_buf->maps[i].cci_name;
+
+ mctp_buf = &ct3d->mctp_shared_buffer->command_buf;
+ g_assert(mctp_buf);
+
+ mctp_buf->command_set = msg->command_set;
+ mctp_buf->command = msg->command;
+ mctp_buf->len_in = len_in;
+ memcpy(mctp_buf->payload, msg->payload, len_in);
+ ct3d->mctp_shared_buffer->status = 1;
+ qmp_cxl_mctp_process_cci_message(s->qmp_fd, cci_name);
+ if (mctp_buf->len_out) {
+ memcpy(s->scratch + sizeof(CXLMCTPMessage),
+ mctp_buf->payload_out, mctp_buf->len_out);
+ }
+ rc = mctp_buf->ret_val;
+ len_out = mctp_buf->len_out;
+ } else {
+ rc = cxl_process_cci_message(s->cci, msg->command_set, msg->command,
+ len_in, msg->payload,
+ &len_out,
+ s->scratch + sizeof(CXLMCTPMessage),
+ &bg_started);
+ }
buf->rc = rc;
s->pos += len_out;
s->len = s->pos;
@@ -253,6 +295,20 @@ static void i2c_mctp_cxl_realize(DeviceState *d, Error **errp)
cxl_initialize_t3_fm_owned_ld_mctpcci(s->cci, DEVICE(s->target), d,
MCTP_CXL_MAILBOX_BYTES);
+ if (s->mctp_msg_forward) {
+ g_assert(s->qmp_str);
+ s->qmp_fd = setup_mctp_qmp_connection(s->qmp_str);
+ if (s->qmp_fd < 0) {
+ error_setg(errp, "setup connection to qmp server failed");
+ } else {
+ read_qmp_response(s->qmp_fd);
+ }
+
+ init_cci_name_ptr_mapping();
+ ct3_setup_mctp_command_share_buffer(ct3d, false);
+ } else {
+ s->qmp_fd = -1;
+ }
return;
}
@@ -13,7 +13,7 @@ system_ss.add(when: 'CONFIG_CXL',
if_false: files(
'cxl-host-stubs.c',
))
-system_ss.add(when: 'CONFIG_I2C_MCTP_CXL', if_true: files('i2c_mctp_cxl.c'))
+system_ss.add(when: 'CONFIG_I2C_MCTP_CXL', if_true: files('i2c_mctp_cxl.c', 'cxl-mctp-qmp.c'))
system_ss.add(when: 'CONFIG_ALL', if_true: files('cxl-host-stubs.c'))
@@ -1051,7 +1051,7 @@ static int ct3_mctp_buf_create(const char *filename, size_t size)
return fd;
}
-static int ct3_setup_mctp_command_share_buffer(CXLType3Dev *ct3d, bool create)
+int ct3_setup_mctp_command_share_buffer(CXLType3Dev *ct3d, bool create)
{
int fd;
int size = sizeof(*ct3d->mctp_shared_buffer);
@@ -1074,7 +1074,7 @@ static int ct3_setup_mctp_command_share_buffer(CXLType3Dev *ct3d, bool create)
return -1;
}
-static int init_cci_name_ptr_mapping(void)
+int init_cci_name_ptr_mapping(void)
{
if (!cci_map_buf) {
cci_map_buf = g_malloc(sizeof(*cci_map_buf));
@@ -810,4 +810,6 @@ 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);
+int ct3_setup_mctp_command_share_buffer(CXLType3Dev *ct3d, bool create);
+int init_cci_name_ptr_mapping(void);
#endif
@@ -37,4 +37,7 @@ struct CXLMCTPSharedBuf {
typedef struct CXLMCTPSharedBuf CXLMCTPSharedBuf;
extern struct CXLCCINamePtrMaps *cci_map_buf;
+int setup_mctp_qmp_connection(const char *qmp_str);
+void read_qmp_response(int sockfd);
+void qmp_cxl_mctp_process_cci_message(const int sockfd, const char *cci_name);
#endif