|
@@ -16,11 +16,14 @@
|
|
|
#include "qapi/error.h"
|
|
|
#include "sysemu/runstate.h"
|
|
|
#include "hw/pci/pci.h"
|
|
|
+#include "exec/memattrs.h"
|
|
|
|
|
|
static void process_config_write(QIOChannel *ioc, PCIDevice *dev,
|
|
|
MPQemuMsg *msg, Error **errp);
|
|
|
static void process_config_read(QIOChannel *ioc, PCIDevice *dev,
|
|
|
MPQemuMsg *msg, Error **errp);
|
|
|
+static void process_bar_write(QIOChannel *ioc, MPQemuMsg *msg, Error **errp);
|
|
|
+static void process_bar_read(QIOChannel *ioc, MPQemuMsg *msg, Error **errp);
|
|
|
|
|
|
void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
|
|
|
{
|
|
@@ -52,6 +55,12 @@ void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
|
|
|
case MPQEMU_CMD_PCI_CFGREAD:
|
|
|
process_config_read(com->ioc, pci_dev, &msg, &local_err);
|
|
|
break;
|
|
|
+ case MPQEMU_CMD_BAR_WRITE:
|
|
|
+ process_bar_write(com->ioc, &msg, &local_err);
|
|
|
+ break;
|
|
|
+ case MPQEMU_CMD_BAR_READ:
|
|
|
+ process_bar_read(com->ioc, &msg, &local_err);
|
|
|
+ break;
|
|
|
default:
|
|
|
error_setg(&local_err,
|
|
|
"Unknown command (%d) received for device %s"
|
|
@@ -115,3 +124,77 @@ static void process_config_read(QIOChannel *ioc, PCIDevice *dev,
|
|
|
getpid());
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+static void process_bar_write(QIOChannel *ioc, MPQemuMsg *msg, Error **errp)
|
|
|
+{
|
|
|
+ ERRP_GUARD();
|
|
|
+ BarAccessMsg *bar_access = &msg->data.bar_access;
|
|
|
+ AddressSpace *as =
|
|
|
+ bar_access->memory ? &address_space_memory : &address_space_io;
|
|
|
+ MPQemuMsg ret = { 0 };
|
|
|
+ MemTxResult res;
|
|
|
+ uint64_t val;
|
|
|
+
|
|
|
+ if (!is_power_of_2(bar_access->size) ||
|
|
|
+ (bar_access->size > sizeof(uint64_t))) {
|
|
|
+ ret.data.u64 = UINT64_MAX;
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ val = cpu_to_le64(bar_access->val);
|
|
|
+
|
|
|
+ res = address_space_rw(as, bar_access->addr, MEMTXATTRS_UNSPECIFIED,
|
|
|
+ (void *)&val, bar_access->size, true);
|
|
|
+
|
|
|
+ if (res != MEMTX_OK) {
|
|
|
+ error_setg(errp, "Bad address %"PRIx64" for mem write, pid "FMT_pid".",
|
|
|
+ bar_access->addr, getpid());
|
|
|
+ ret.data.u64 = -1;
|
|
|
+ }
|
|
|
+
|
|
|
+fail:
|
|
|
+ ret.cmd = MPQEMU_CMD_RET;
|
|
|
+ ret.size = sizeof(ret.data.u64);
|
|
|
+
|
|
|
+ if (!mpqemu_msg_send(&ret, ioc, NULL)) {
|
|
|
+ error_prepend(errp, "Error returning code to proxy, pid "FMT_pid": ",
|
|
|
+ getpid());
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void process_bar_read(QIOChannel *ioc, MPQemuMsg *msg, Error **errp)
|
|
|
+{
|
|
|
+ ERRP_GUARD();
|
|
|
+ BarAccessMsg *bar_access = &msg->data.bar_access;
|
|
|
+ MPQemuMsg ret = { 0 };
|
|
|
+ AddressSpace *as;
|
|
|
+ MemTxResult res;
|
|
|
+ uint64_t val = 0;
|
|
|
+
|
|
|
+ as = bar_access->memory ? &address_space_memory : &address_space_io;
|
|
|
+
|
|
|
+ if (!is_power_of_2(bar_access->size) ||
|
|
|
+ (bar_access->size > sizeof(uint64_t))) {
|
|
|
+ val = UINT64_MAX;
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
+ res = address_space_rw(as, bar_access->addr, MEMTXATTRS_UNSPECIFIED,
|
|
|
+ (void *)&val, bar_access->size, false);
|
|
|
+
|
|
|
+ if (res != MEMTX_OK) {
|
|
|
+ error_setg(errp, "Bad address %"PRIx64" for mem read, pid "FMT_pid".",
|
|
|
+ bar_access->addr, getpid());
|
|
|
+ val = UINT64_MAX;
|
|
|
+ }
|
|
|
+
|
|
|
+fail:
|
|
|
+ ret.cmd = MPQEMU_CMD_RET;
|
|
|
+ ret.data.u64 = le64_to_cpu(val);
|
|
|
+ ret.size = sizeof(ret.data.u64);
|
|
|
+
|
|
|
+ if (!mpqemu_msg_send(&ret, ioc, NULL)) {
|
|
|
+ error_prepend(errp, "Error returning code to proxy, pid "FMT_pid": ",
|
|
|
+ getpid());
|
|
|
+ }
|
|
|
+}
|