From: nifan.cxl@gmail.com
To: jonathan.cameron@huawei.com, qemu-devel@nongnu.org
Cc: linux-cxl@vger.kernel.org, a.manzanares@samsung.com,
dave@stgolabs.net, nmtadam.samsung@gmail.com,
nifan.cxl@gmail.com, anisa.su887@gmail.com, gourry@gourry.net,
Fan Ni <fan.ni@samsung.com>
Subject: [RFC 3/3] cxl/i2c_mctp_cxl: Add support to process MCTP command remotely
Date: Mon, 7 Apr 2025 21:20:30 -0700 [thread overview]
Message-ID: <20250408043051.430340-4-nifan.cxl@gmail.com> (raw)
In-Reply-To: <20250408043051.430340-1-nifan.cxl@gmail.com>
From: Fan Ni <fan.ni@samsung.com>
With the change, if "mctp-msg-forward" property is turned on for
i2c_mctp_cxl device, we setup a QMP connection to the other VM identified
by the "qmp" property, and forward the MCTP requests to the VM for processing.
Note:
1. The VM with "mctp-msg-forward=on" acts as a FM VM.
2. Before the FM VM is started, the target VM to connect to must be on
and ready to connect.
3. For the FM VM instance, it needs to share the same CXL topology with
the VM we want to connect to, and the cxl device to connect needs to
have "allow-fm-attach=on".
Signed-off-by: Fan Ni <fan.ni@samsung.com>
---
hw/cxl/cxl-mctp-qmp.c | 85 +++++++++++++++++++++++++++++++
hw/cxl/i2c_mctp_cxl.c | 68 ++++++++++++++++++++++---
hw/cxl/meson.build | 2 +-
hw/mem/cxl_type3.c | 4 +-
include/hw/cxl/cxl_device.h | 2 +
include/hw/cxl/cxl_mctp_message.h | 3 ++
6 files changed, 155 insertions(+), 9 deletions(-)
create mode 100644 hw/cxl/cxl-mctp-qmp.c
diff --git a/hw/cxl/cxl-mctp-qmp.c b/hw/cxl/cxl-mctp-qmp.c
new file mode 100644
index 0000000000..f0ea5e2cc0
--- /dev/null
+++ b/hw/cxl/cxl-mctp-qmp.c
@@ -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);
+}
diff --git a/hw/cxl/i2c_mctp_cxl.c b/hw/cxl/i2c_mctp_cxl.c
index 7d2cbc3b75..e146fa2039 100644
--- a/hw/cxl/i2c_mctp_cxl.c
+++ b/hw/cxl/i2c_mctp_cxl.c
@@ -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;
}
diff --git a/hw/cxl/meson.build b/hw/cxl/meson.build
index e780344d85..d0a8f78462 100644
--- a/hw/cxl/meson.build
+++ b/hw/cxl/meson.build
@@ -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'))
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index f7ac8e8da7..d44b1b6dc6 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.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));
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
index 9a00ef7a1e..5c8813af20 100644
--- a/include/hw/cxl/cxl_device.h
+++ b/include/hw/cxl/cxl_device.h
@@ -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
diff --git a/include/hw/cxl/cxl_mctp_message.h b/include/hw/cxl/cxl_mctp_message.h
index 85b3664cf7..718dc8c0a2 100644
--- a/include/hw/cxl/cxl_mctp_message.h
+++ b/include/hw/cxl/cxl_mctp_message.h
@@ -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
--
2.47.2
next prev parent reply other threads:[~2025-04-08 4:33 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-08 4:20 [RFC 0/3] Qemu FM emulation nifan.cxl
2025-04-08 4:20 ` [RFC 1/3] cxl_type3: Preparing information sharing between VMs nifan.cxl
2025-04-08 4:20 ` [RFC 2/3] cxl_type3: Add qmp_cxl_process_mctp_message qmp interface nifan.cxl
2025-04-08 4:20 ` nifan.cxl [this message]
2025-04-08 15:04 ` [RFC 0/3] Qemu FM emulation Gregory Price
2025-04-14 15:44 ` Fan Ni
2025-04-15 15:37 ` Jonathan Cameron via
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250408043051.430340-4-nifan.cxl@gmail.com \
--to=nifan.cxl@gmail.com \
--cc=a.manzanares@samsung.com \
--cc=anisa.su887@gmail.com \
--cc=dave@stgolabs.net \
--cc=fan.ni@samsung.com \
--cc=gourry@gourry.net \
--cc=jonathan.cameron@huawei.com \
--cc=linux-cxl@vger.kernel.org \
--cc=nmtadam.samsung@gmail.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).