* [Qemu-devel] [RFC PATCH v1 1/8] multi-process QEMU: build system for remote device process
2018-10-12 23:48 [Qemu-devel] [RFC PATCH v1 0/8] multi-process QEMU Jagannathan Raman
@ 2018-10-12 23:48 ` Jagannathan Raman
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 2/8] multi-process QEMU: define proxy-link object Jagannathan Raman
` (6 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Jagannathan Raman @ 2018-10-12 23:48 UTC (permalink / raw)
To: qemu-devel; +Cc: john.g.johnson, Kanth.Ghatraju, elena.ufimtseva, jag.raman
- Makefile changes necessary to support the building of the remote device
process is added
- functions that are necessary to compile the code, but are not needed at
run-time are stubbed out
- main() function of remote SCSI device process is implemented
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
---
Makefile | 3 +-
Makefile.objs | 16 ++++++++++
Makefile.target | 39 +++++++++++++++++++++++-
accel/stubs/kvm-stub.c | 5 +++
accel/stubs/tcg-stub.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++
backends/Makefile.objs | 2 ++
block/Makefile.objs | 2 ++
hw/Makefile.objs | 6 ++++
hw/block/Makefile.objs | 2 ++
hw/core/Makefile.objs | 14 +++++++++
hw/nvram/Makefile.objs | 2 ++
hw/pci/Makefile.objs | 4 +++
hw/scsi/Makefile.objs | 3 ++
hw/scsi/qemu-scsi-dev.c | 35 +++++++++++++++++++++
migration/Makefile.objs | 2 ++
qom/Makefile.objs | 4 +++
stubs/monitor.c | 25 +++++++++++++++
stubs/net-stub.c | 31 +++++++++++++++++++
stubs/replay.c | 14 +++++++++
stubs/vl-stub.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++
stubs/vmstate.c | 20 ++++++++++++
21 files changed, 387 insertions(+), 2 deletions(-)
create mode 100644 hw/scsi/qemu-scsi-dev.c
create mode 100644 stubs/net-stub.c
create mode 100644 stubs/vl-stub.c
diff --git a/Makefile b/Makefile
index 1144d6e..b6cac08 100644
--- a/Makefile
+++ b/Makefile
@@ -429,6 +429,7 @@ dummy := $(call unnest-vars,, \
qom-obj-y \
io-obj-y \
common-obj-y \
+ scsi-dev-obj-y \
common-obj-m \
ui-obj-y \
ui-obj-m \
@@ -507,7 +508,7 @@ CAP_CFLAGS += -DCAPSTONE_HAS_X86
subdir-capstone: .git-submodule-status
$(call quiet-command,$(MAKE) -C $(SRC_PATH)/capstone CAPSTONE_SHARED=no BUILDDIR="$(BUILD_DIR)/capstone" CC="$(CC)" AR="$(AR)" LD="$(LD)" RANLIB="$(RANLIB)" CFLAGS="$(CAP_CFLAGS)" $(SUBDIR_MAKEFLAGS) $(BUILD_DIR)/capstone/$(LIBCAPSTONE))
-$(SUBDIR_RULES): libqemuutil.a $(common-obj-y) $(chardev-obj-y) \
+$(SUBDIR_RULES): libqemuutil.a $(common-obj-y) $(chardev-obj-y) $(scsi-dev-obj-y) \
$(qom-obj-y) $(crypto-aes-obj-$(CONFIG_USER_ONLY))
ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS))
diff --git a/Makefile.objs b/Makefile.objs
index 1e1ff38..0a3799c 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -73,6 +73,22 @@ block-obj-$(CONFIG_REPLICATION) += replication.o
block-obj-m = block/
+####################################################
+# scsi-dev-obj-y is code used by remote SCSI device
+
+scsi-dev-obj-y += hw/
+scsi-dev-obj-y += qom/
+scsi-dev-obj-y += backends/
+scsi-dev-obj-y += block/
+scsi-dev-obj-y += migration/
+
+scsi-dev-obj-y += cpus-common.o
+scsi-dev-obj-y += dma-helpers.o
+scsi-dev-obj-y += blockdev.o
+scsi-dev-obj-y += qdev-monitor.o
+scsi-dev-obj-y += bootdevice.o
+scsi-dev-obj-y += iothread.o
+
#######################################################################
# crypto-obj-y is code used by both qemu system emulation and qemu-img
diff --git a/Makefile.target b/Makefile.target
index 4d56298..c5feda2 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -19,21 +19,26 @@ ifdef CONFIG_USER_ONLY
# user emulator name
QEMU_PROG=qemu-$(TARGET_NAME)
QEMU_PROG_BUILD = $(QEMU_PROG)
+SCSI_DEV_PROG=qemu-scsi-dev
+SCSI_DEV_BUILD = $(SCSI_DEV_PROG)
else
# system emulator name
QEMU_PROG=qemu-system-$(TARGET_NAME)$(EXESUF)
+SCSI_DEV_PROG=qemu-scsi-dev
ifneq (,$(findstring -mwindows,$(SDL_LIBS)))
# Terminate program name with a 'w' because the linker builds a windows executable.
QEMU_PROGW=qemu-system-$(TARGET_NAME)w$(EXESUF)
$(QEMU_PROG): $(QEMU_PROGW)
$(call quiet-command,$(OBJCOPY) --subsystem console $(QEMU_PROGW) $(QEMU_PROG),"GEN","$(TARGET_DIR)$(QEMU_PROG)")
QEMU_PROG_BUILD = $(QEMU_PROGW)
+SCSI_DEV_BUILD = $(SCSI_DEV_PROG)
else
QEMU_PROG_BUILD = $(QEMU_PROG)
+SCSI_DEV_BUILD = $(SCSI_DEV_PROG)
endif
endif
-PROGS=$(QEMU_PROG) $(QEMU_PROGW)
+PROGS=$(QEMU_PROG) $(QEMU_PROGW) $(SCSI_DEV_PROG)
STPFILES=
# Makefile Tests
@@ -107,6 +112,13 @@ obj-y += target/$(TARGET_BASE_ARCH)/
obj-y += disas.o
obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o
+scsi-dev-tgt-obj-y += accel/stubs/kvm-stub.o
+scsi-dev-tgt-obj-y += accel/stubs/tcg-stub.o
+scsi-dev-tgt-obj-y += stubs/vl-stub.o
+scsi-dev-tgt-obj-y += stubs/net-stub.o
+scsi-dev-tgt-obj-y += stubs/monitor.o
+scsi-dev-tgt-obj-y += stubs/replay.o
+
#########################################################
# Linux user emulator target
@@ -164,10 +176,20 @@ endif # CONFIG_SOFTMMU
dummy := $(call unnest-vars,,obj-y)
all-obj-y := $(obj-y)
+dummy := $(call unnest-vars,..,scsi-dev-tgt-obj-y)
+all-scsi-dev-obj-y := $(scsi-dev-tgt-obj-y)
+
+all-scsi-dev-obj-y += memory.o
+all-scsi-dev-obj-y += exec.o
+all-scsi-dev-obj-y += numa.o
+all-scsi-dev-obj-y += ioport.o
+all-scsi-dev-obj-y += cpus.o
+
target-obj-y :=
block-obj-y :=
common-obj-y :=
chardev-obj-y :=
+scsi-dev-obj-y :=
include $(SRC_PATH)/Makefile.objs
dummy := $(call unnest-vars,,target-obj-y)
target-obj-y-save := $(target-obj-y)
@@ -180,6 +202,7 @@ dummy := $(call unnest-vars,.., \
qom-obj-y \
io-obj-y \
common-obj-y \
+ scsi-dev-obj-y \
common-obj-m)
target-obj-y := $(target-obj-y-save)
all-obj-y += $(common-obj-y)
@@ -190,7 +213,14 @@ all-obj-$(CONFIG_USER_ONLY) += $(crypto-aes-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y)
+all-scsi-dev-obj-y += $(block-obj-y)
+all-scsi-dev-obj-y += $(crypto-obj-y)
+all-scsi-dev-obj-y += $(io-obj-y)
+all-scsi-dev-obj-y += $(chardev-obj-y)
+all-scsi-dev-obj-y += $(scsi-dev-obj-y)
+
$(QEMU_PROG_BUILD): config-devices.mak
+$(SCSI_DEV_BUILD): config-devices.mak
COMMON_LDADDS = ../libqemuutil.a
@@ -202,6 +232,13 @@ ifdef CONFIG_DARWIN
$(call quiet-command,SetFile -a C $@,"SETFILE","$(TARGET_DIR)$@")
endif
+$(SCSI_DEV_BUILD): $(all-scsi-dev-obj-y) $(COMMON_LDADDS)
+ $(call LINK, $(filter-out %.mak, $^))
+ifdef CONFIG_DARWIN
+ $(call quiet-command,Rez -append $(SRC_PATH)/pc-bios/qemu.rsrc -o $@,"REZ","$(TARGET_DIR)$@")
+ $(call quiet-command,SetFile -a C $@,"SETFILE","$(TARGET_DIR)$@")
+endif
+
gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
$(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES),"GEN","$(TARGET_DIR)$@")
diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
index 02d5170..573b4da 100644
--- a/accel/stubs/kvm-stub.c
+++ b/accel/stubs/kvm-stub.c
@@ -32,6 +32,7 @@ bool kvm_allowed;
bool kvm_readonly_mem_allowed;
bool kvm_ioeventfd_any_length_allowed;
bool kvm_msi_use_devid;
+bool kvm_halt_in_kernel_allowed;
int kvm_destroy_vcpu(CPUState *cpu)
{
@@ -59,6 +60,10 @@ void kvm_cpu_synchronize_post_init(CPUState *cpu)
{
}
+void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu)
+{
+}
+
int kvm_cpu_exec(CPUState *cpu)
{
abort();
diff --git a/accel/stubs/tcg-stub.c b/accel/stubs/tcg-stub.c
index 76ae461..e6efd65 100644
--- a/accel/stubs/tcg-stub.c
+++ b/accel/stubs/tcg-stub.c
@@ -16,11 +16,92 @@
#include "tcg/tcg.h"
#include "exec/cpu-common.h"
#include "exec/exec-all.h"
+#include "translate-all.h"
+#include "exec/ram_addr.h"
+
+bool parallel_cpus;
void tb_flush(CPUState *cpu)
{
}
+void tb_check_watchpoint(CPUState *cpu)
+{
+}
+
+void tb_invalidate_phys_range(ram_addr_t start, ram_addr_t end)
+{
+}
+
+void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
+ int is_cpu_write_access)
+{
+}
+
+void tb_invalidate_phys_page_fast(struct page_collection *pages,
+ tb_page_addr_t start, int len)
+{
+}
+
void tlb_set_dirty(CPUState *cpu, target_ulong vaddr)
{
}
+
+void tlb_flush(CPUState *cpu)
+{
+}
+
+void tlb_flush_page(CPUState *cpu, target_ulong addr)
+{
+}
+
+void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length)
+{
+}
+
+void tcg_region_init(void)
+{
+}
+
+void tcg_register_thread(void)
+{
+}
+
+void tcg_flush_softmmu_tlb(CPUState *cs)
+{
+}
+
+void cpu_loop_exit_noexc(CPUState *cpu)
+{
+ cpu->exception_index = -1;
+ cpu_loop_exit(cpu);
+}
+
+void cpu_loop_exit(CPUState *cpu)
+{
+ cpu->can_do_io = 1;
+ siglongjmp(cpu->jmp_env, 1);
+}
+
+void cpu_reloading_memory_map(void)
+{
+}
+
+int cpu_exec(CPUState *cpu)
+{
+ return 0;
+}
+
+void cpu_exec_step_atomic(CPUState *cpu)
+{
+}
+
+struct page_collection *
+page_collection_lock(tb_page_addr_t start, tb_page_addr_t end)
+{
+ return NULL;
+}
+
+void page_collection_unlock(struct page_collection *set)
+{
+}
diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 717fcbd..6c6aa03 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -16,3 +16,5 @@ common-obj-$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) += \
endif
common-obj-$(CONFIG_LINUX) += hostmem-memfd.o
+
+scsi-dev-obj-y += hostmem.o
diff --git a/block/Makefile.objs b/block/Makefile.objs
index c8337bf..50431ce 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -51,3 +51,5 @@ qcow.o-libs := -lz
linux-aio.o-libs := -laio
parallels.o-cflags := $(LIBXML2_CFLAGS)
parallels.o-libs := $(LIBXML2_LIBS)
+
+scsi-dev-obj-y += stream.o
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index a19c141..9c99c29 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -38,3 +38,9 @@ devices-dirs-$(CONFIG_SOFTMMU) += smbios/
devices-dirs-y += core/
common-obj-y += $(devices-dirs-y)
obj-y += $(devices-dirs-y)
+
+scsi-dev-obj-y += core/
+scsi-dev-obj-y += scsi/
+scsi-dev-obj-y += block/
+scsi-dev-obj-y += pci/
+scsi-dev-obj-y += nvram/
diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs
index 53ce575..e93aeba 100644
--- a/hw/block/Makefile.objs
+++ b/hw/block/Makefile.objs
@@ -14,3 +14,5 @@ obj-$(CONFIG_SH4) += tc58128.o
obj-$(CONFIG_VIRTIO_BLK) += virtio-blk.o
obj-$(CONFIG_VIRTIO_BLK) += dataplane/
obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk.o
+
+scsi-dev-obj-y += block.o cdrom.o hd-geometry.o
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
index eb88ca9..6fd29ac 100644
--- a/hw/core/Makefile.objs
+++ b/hw/core/Makefile.objs
@@ -23,3 +23,17 @@ common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o
obj-$(CONFIG_SOFTMMU) += generic-loader.o
obj-$(CONFIG_SOFTMMU) += null-machine.o
+
+scsi-dev-obj-y += qdev-properties.o
+scsi-dev-obj-y += qdev.o
+scsi-dev-obj-y += bus.o
+scsi-dev-obj-y += irq.o
+scsi-dev-obj-y += hotplug.o
+scsi-dev-obj-y += machine.o
+scsi-dev-obj-y += fw-path-provider.o
+scsi-dev-obj-y += reset.o
+scsi-dev-obj-y += sysbus.o
+scsi-dev-obj-y += loader.o
+scsi-dev-obj-y += nmi.o
+scsi-dev-obj-y += qdev-properties-system.o
+scsi-dev-obj-y += qdev-fw.o
diff --git a/hw/nvram/Makefile.objs b/hw/nvram/Makefile.objs
index a912d25..f52e770 100644
--- a/hw/nvram/Makefile.objs
+++ b/hw/nvram/Makefile.objs
@@ -5,3 +5,5 @@ common-obj-y += fw_cfg.o
common-obj-y += chrp_nvram.o
common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
obj-$(CONFIG_PSERIES) += spapr_nvram.o
+
+scsi-dev-obj-y += fw_cfg.o
diff --git a/hw/pci/Makefile.objs b/hw/pci/Makefile.objs
index 9f905e6..46af40a 100644
--- a/hw/pci/Makefile.objs
+++ b/hw/pci/Makefile.objs
@@ -7,3 +7,7 @@ common-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
common-obj-$(call lnot,$(CONFIG_PCI)) += pci-stub.o
common-obj-$(CONFIG_ALL) += pci-stub.o
+
+scsi-dev-obj-y += pci.o pci_bridge.o
+scsi-dev-obj-y += msi.o msix.o
+scsi-dev-obj-y += pcie.o
diff --git a/hw/scsi/Makefile.objs b/hw/scsi/Makefile.objs
index 718b4c2..8cf6344 100644
--- a/hw/scsi/Makefile.objs
+++ b/hw/scsi/Makefile.objs
@@ -13,3 +13,6 @@ obj-y += virtio-scsi.o virtio-scsi-dataplane.o
obj-$(CONFIG_VHOST_SCSI) += vhost-scsi-common.o vhost-scsi.o
obj-$(CONFIG_VHOST_USER_SCSI) += vhost-scsi-common.o vhost-user-scsi.o
endif
+
+scsi-dev-obj-y += qemu-scsi-dev.o
+scsi-dev-obj-y += scsi-generic.o scsi-bus.o lsi53c895a.o scsi-disk.o
diff --git a/hw/scsi/qemu-scsi-dev.c b/hw/scsi/qemu-scsi-dev.c
new file mode 100644
index 0000000..3cb8698
--- /dev/null
+++ b/hw/scsi/qemu-scsi-dev.c
@@ -0,0 +1,35 @@
+/*
+ * Remote SCSI device
+ *
+ * Copyright 2018, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+
+int main(int argc, char *argv[])
+{
+ module_call_init(MODULE_INIT_QOM);
+
+ return 0;
+}
diff --git a/migration/Makefile.objs b/migration/Makefile.objs
index c83ec47..c634b89 100644
--- a/migration/Makefile.objs
+++ b/migration/Makefile.objs
@@ -13,3 +13,5 @@ common-obj-$(CONFIG_RDMA) += rdma.o
common-obj-$(CONFIG_LIVE_BLOCK_MIGRATION) += block.o
rdma.o-libs := $(RDMA_LIBS)
+
+scsi-dev-obj-y += qemu-file.o vmstate.o qjson.o vmstate-types.o
diff --git a/qom/Makefile.objs b/qom/Makefile.objs
index 516349e..cf25361 100644
--- a/qom/Makefile.objs
+++ b/qom/Makefile.objs
@@ -2,3 +2,7 @@ qom-obj-y = object.o container.o qom-qobject.o
qom-obj-y += object_interfaces.o
common-obj-y = cpu.o
+
+scsi-dev-obj-y += object.o qom-qobject.o container.o
+scsi-dev-obj-y += object_interfaces.o
+scsi-dev-obj-y += cpu.o
diff --git a/stubs/monitor.c b/stubs/monitor.c
index 3890771..9280932 100644
--- a/stubs/monitor.c
+++ b/stubs/monitor.c
@@ -2,6 +2,8 @@
#include "qapi/error.h"
#include "qemu-common.h"
#include "monitor/monitor.h"
+#include "qapi/qapi-types-misc.h"
+#include "qapi/qapi-commands-misc.h"
__thread Monitor *cur_mon;
@@ -14,3 +16,26 @@ int monitor_get_fd(Monitor *mon, const char *name, Error **errp)
void monitor_init(Chardev *chr, int flags)
{
}
+
+int monitor_get_cpu_index(void)
+{
+ return -ENOSYS;
+}
+void monitor_printf(Monitor *mon, const char *fmt, ...)
+{
+}
+
+bool monitor_cur_is_qmp(void)
+{
+ return false;
+}
+
+ObjectPropertyInfoList *qmp_device_list_properties(const char *typename,
+ Error **errp)
+{
+ return NULL;
+}
+
+void monitor_vfprintf(FILE *stream, const char *fmt, va_list ap)
+{
+}
diff --git a/stubs/net-stub.c b/stubs/net-stub.c
new file mode 100644
index 0000000..cb2274b
--- /dev/null
+++ b/stubs/net-stub.c
@@ -0,0 +1,31 @@
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "net/net.h"
+
+int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
+ NetClientDriver type, int max)
+{
+ return -ENOSYS;
+}
+
+NetClientState *net_hub_port_find(int hub_id)
+{
+ return NULL;
+}
+
+int net_hub_id_for_client(NetClientState *nc, int *id)
+{
+ return -ENOSYS;
+}
+
+int qemu_show_nic_models(const char *arg, const char *const *models)
+{
+ return -ENOSYS;
+}
+
+int qemu_find_nic_model(NICInfo *nd, const char * const *models,
+ const char *default_model)
+{
+ return -ENOSYS;
+}
+
diff --git a/stubs/replay.c b/stubs/replay.c
index 04279ab..226ce54 100644
--- a/stubs/replay.c
+++ b/stubs/replay.c
@@ -80,3 +80,17 @@ void replay_mutex_lock(void)
void replay_mutex_unlock(void)
{
}
+
+bool replay_has_checkpoint(void)
+{
+ return false;
+}
+
+int replay_get_instructions(void)
+{
+ return 0;
+}
+
+void replay_account_executed_instructions(void)
+{
+}
diff --git a/stubs/vl-stub.c b/stubs/vl-stub.c
new file mode 100644
index 0000000..78925ac
--- /dev/null
+++ b/stubs/vl-stub.c
@@ -0,0 +1,79 @@
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/uuid.h"
+#include "sysemu/sysemu.h"
+#include "exec/cpu-common.h"
+#include "exec/gdbstub.h"
+#include "sysemu/replay.h"
+#include "disas/disas.h"
+
+bool tcg_allowed;
+bool xen_allowed;
+bool boot_strict;
+
+int mem_prealloc;
+int smp_cpus;
+int vga_interface_type = VGA_NONE;
+int smp_cores = 1;
+int smp_threads = 1;
+int icount_align_option;
+int boot_menu;
+
+unsigned int max_cpus;
+const uint32_t arch_type;
+const char *mem_path;
+uint8_t qemu_extra_params_fw[2];
+uint8_t *boot_splash_filedata;
+size_t boot_splash_filedata_size;
+struct syminfo *syminfos;
+
+ram_addr_t ram_size;
+MachineState *current_machine;
+QemuUUID qemu_uuid;
+
+int runstate_is_running(void)
+{
+ return 0;
+}
+
+void runstate_set(RunState new_state)
+{
+}
+
+void vm_state_notify(int running, RunState state)
+{
+}
+
+bool qemu_vmstop_requested(RunState *r)
+{
+ return false;
+}
+
+void qemu_system_debug_request(void)
+{
+}
+
+void qemu_remove_machine_init_done_notifier(Notifier *notify)
+{
+}
+
+char *qemu_find_file(int type, const char *name)
+{
+ return NULL;
+}
+
+void gdb_set_stop_cpu(CPUState *cpu)
+{
+}
+
+void replay_enable_events(void)
+{
+}
+
+void replay_disable_events(void)
+{
+}
+
+void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+{
+}
diff --git a/stubs/vmstate.c b/stubs/vmstate.c
index 6399474..2a8d109 100644
--- a/stubs/vmstate.c
+++ b/stubs/vmstate.c
@@ -1,9 +1,12 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "migration/vmstate.h"
+#include "migration/misc.h"
const VMStateDescription vmstate_dummy = {};
+const VMStateInfo vmstate_info_timer;
+
int vmstate_register_with_alias_id(DeviceState *dev,
int instance_id,
const VMStateDescription *vmsd,
@@ -24,3 +27,20 @@ bool vmstate_check_only_migratable(const VMStateDescription *vmsd)
{
return true;
}
+
+void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev)
+{
+}
+
+void vmstate_unregister_ram(MemoryRegion *mr, DeviceState *dev)
+{
+}
+
+void vmstate_register_ram_global(MemoryRegion *mr)
+{
+}
+
+bool migration_is_idle(void)
+{
+ return false;
+}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [RFC PATCH v1 2/8] multi-process QEMU: define proxy-link object
2018-10-12 23:48 [Qemu-devel] [RFC PATCH v1 0/8] multi-process QEMU Jagannathan Raman
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 1/8] multi-process QEMU: build system for remote device process Jagannathan Raman
@ 2018-10-12 23:48 ` Jagannathan Raman
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 3/8] multi-process QEMU: setup PCI host bridge for remote device Jagannathan Raman
` (5 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Jagannathan Raman @ 2018-10-12 23:48 UTC (permalink / raw)
To: qemu-devel; +Cc: john.g.johnson, Kanth.Ghatraju, elena.ufimtseva, jag.raman
- Define proxy-link object which forms the communication link between
QEMU & emulation program.
- Add functions to configure members of proxy-link object instance.
- Add functions to send and receive messages over the communication
channel.
- Add GMainLoop to handle events received on the communication channel.
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
---
include/glib-compat.h | 4 +
include/io/proxy-link.h | 103 +++++++++++++++++++
io/Makefile.objs | 1 +
io/proxy-link.c | 263 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 371 insertions(+)
create mode 100644 include/io/proxy-link.h
create mode 100644 io/proxy-link.c
diff --git a/include/glib-compat.h b/include/glib-compat.h
index fdf95a2..5e61d82 100644
--- a/include/glib-compat.h
+++ b/include/glib-compat.h
@@ -19,12 +19,16 @@
/* Ask for warnings for anything that was marked deprecated in
* the defined version, or before. It is a candidate for rewrite.
*/
+#ifndef GLIB_VERSION_MIN_REQUIRED
#define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_40
+#endif
/* Ask for warnings if code tries to use function that did not
* exist in the defined version. These risk breaking builds
*/
+#ifndef GLIB_VERSION_MAX_ALLOWED
#define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_40
+#endif
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
diff --git a/include/io/proxy-link.h b/include/io/proxy-link.h
new file mode 100644
index 0000000..6ce6c10
--- /dev/null
+++ b/include/io/proxy-link.h
@@ -0,0 +1,103 @@
+/*
+ * Communication channel between QEMU and remote device process
+ *
+ * Copyright 2018, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef PROXY_LINK_H
+#define PROXY_LINK_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <glib.h>
+#include <pthread.h>
+
+#include "qemu/osdep.h"
+#include "qom/object.h"
+
+typedef struct ProxyLinkState ProxyLinkState;
+
+#define TYPE_PROXY_LINK "proxy-link"
+#define PROXY_LINK(obj) \
+ OBJECT_CHECK(ProxyLinkState, (obj), TYPE_PROXY_LINK)
+
+#define MAX_FDS 8
+
+#define PROC_HDR_SIZE offsetof(ProcMsg, data1.u64)
+
+typedef enum {
+ INIT = 0,
+ CONF_READ,
+ CONF_WRITE,
+ MAX,
+} proc_cmd_t;
+
+typedef struct {
+ proc_cmd_t cmd;
+ int bytestream;
+ size_t size;
+
+ union {
+ uint64_t u64;
+ } data1;
+
+ int fds[MAX_FDS];
+ int num_fds;
+
+ uint8_t *data2;
+} ProcMsg;
+
+struct conf_data_msg {
+ uint32_t addr;
+ uint32_t val;
+ int l;
+};
+
+typedef void (*proxy_link_callback)(GIOCondition cond);
+
+typedef struct ProxySrc {
+ GSource gsrc;
+ GPollFD gpfd;
+} ProxySrc;
+
+struct ProxyLinkState {
+ Object obj;
+
+ GMainContext *ctx;
+ GMainLoop *loop;
+ ProxySrc *src;
+
+ int sock;
+ pthread_mutex_t lock;
+
+ proxy_link_callback callback;
+};
+
+ProxyLinkState *proxy_link_create(void);
+void proxy_link_finalize(ProxyLinkState *s);
+
+void proxy_proc_send(ProxyLinkState *s, ProcMsg *msg);
+int proxy_proc_recv(ProxyLinkState *s, ProcMsg *msg);
+void proxy_link_set_sock(ProxyLinkState *s, int fd);
+void proxy_link_set_callback(ProxyLinkState *s, proxy_link_callback callback);
+void start_handler(ProxyLinkState *s);
+
+#endif
diff --git a/io/Makefile.objs b/io/Makefile.objs
index 9a20fce..141e9ed 100644
--- a/io/Makefile.objs
+++ b/io/Makefile.objs
@@ -10,3 +10,4 @@ io-obj-y += channel-util.o
io-obj-y += dns-resolver.o
io-obj-y += net-listener.o
io-obj-y += task.o
+io-obj-y += proxy-link.o
diff --git a/io/proxy-link.c b/io/proxy-link.c
new file mode 100644
index 0000000..f5f7887
--- /dev/null
+++ b/io/proxy-link.c
@@ -0,0 +1,263 @@
+/*
+ * Communication channel between QEMU and remote device process
+ *
+ * Copyright 2018, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "qemu/module.h"
+#include "io/proxy-link.h"
+
+static void proxy_link_inst_init(Object *obj)
+{
+ ProxyLinkState *s = PROXY_LINK(obj);
+
+ pthread_mutex_init(&s->lock, NULL);
+
+ s->sock = STDIN_FILENO;
+ s->ctx = g_main_context_new();
+ s->loop = g_main_loop_new(s->ctx, FALSE);
+}
+
+static const TypeInfo proxy_link_info = {
+ .name = TYPE_PROXY_LINK,
+ .parent = TYPE_OBJECT,
+ .instance_size = sizeof(ProxyLinkState),
+ .instance_init = proxy_link_inst_init,
+};
+
+static void proxy_link_register_types(void)
+{
+ type_register_static(&proxy_link_info);
+}
+
+type_init(proxy_link_register_types)
+
+ProxyLinkState *proxy_link_create(void)
+{
+ return PROXY_LINK(object_new(TYPE_PROXY_LINK));
+}
+
+void proxy_link_finalize(ProxyLinkState *s)
+{
+ g_source_unref(&s->src->gsrc);
+ g_main_loop_unref(s->loop);
+ g_main_context_unref(s->ctx);
+ g_main_loop_quit(s->loop);
+
+ close(s->sock);
+
+ object_unref(OBJECT(s));
+}
+
+void proxy_proc_send(ProxyLinkState *s, ProcMsg *msg)
+{
+ int rc;
+ uint8_t *data;
+ char control[CMSG_SPACE(MAX_FDS * sizeof(int))] = { };
+ struct msghdr hdr;
+ struct cmsghdr *chdr;
+
+ struct iovec iov = {
+ .iov_base = (char *) msg,
+ .iov_len = PROC_HDR_SIZE,
+ };
+
+ memset(&hdr, 0, sizeof(hdr));
+ memset(control, 0, sizeof(control));
+
+ hdr.msg_iov = &iov;
+ hdr.msg_iovlen = 1;
+
+ assert(msg->num_fds <= MAX_FDS);
+
+ if (msg->num_fds > 0) {
+ size_t fdsize = msg->num_fds * sizeof(int);
+
+ hdr.msg_control = control;
+ hdr.msg_controllen = sizeof(control);
+
+ chdr = CMSG_FIRSTHDR(&hdr);
+ chdr->cmsg_len = CMSG_LEN(fdsize);
+ chdr->cmsg_level = SOL_SOCKET;
+ chdr->cmsg_type = SCM_RIGHTS;
+ memcpy(CMSG_DATA(chdr), msg->fds, fdsize);
+ hdr.msg_controllen = chdr->cmsg_len;
+ }
+
+ pthread_mutex_lock(&s->lock);
+
+ do {
+ rc = sendmsg(s->sock, &hdr, 0);
+ } while (rc < 0 && (errno == EINTR || errno == EAGAIN));
+
+ if (rc < 0) {
+ pthread_mutex_unlock(&s->lock);
+ return;
+ }
+
+ if (msg->bytestream) {
+ data = msg->data2;
+ } else {
+ data = (uint8_t *)msg + PROC_HDR_SIZE;
+ }
+
+ do {
+ rc = write(s->sock, data, msg->size);
+ } while (rc < 0 && (errno == EINTR || errno == EAGAIN));
+
+ pthread_mutex_unlock(&s->lock);
+}
+
+
+int proxy_proc_recv(ProxyLinkState *s, ProcMsg *msg)
+{
+ int rc;
+ uint8_t *data;
+ char control[CMSG_SPACE(MAX_FDS * sizeof(int))] = { };
+ struct msghdr hdr;
+ struct cmsghdr *chdr;
+ size_t fdsize;
+
+ struct iovec iov = {
+ .iov_base = (char *) msg,
+ .iov_len = PROC_HDR_SIZE,
+ };
+
+ memset(&hdr, 0, sizeof(hdr));
+ memset(control, 0, sizeof(control));
+
+ hdr.msg_iov = &iov;
+ hdr.msg_iovlen = 1;
+ hdr.msg_control = control;
+ hdr.msg_controllen = sizeof(control);
+
+ pthread_mutex_lock(&s->lock);
+
+ do {
+ rc = recvmsg(s->sock, &hdr, 0);
+ } while (rc < 0 && (errno == EINTR || errno == EAGAIN));
+
+ if (rc < 0) {
+ pthread_mutex_unlock(&s->lock);
+ return rc;
+ }
+
+ msg->num_fds = 0;
+ for (chdr = CMSG_FIRSTHDR(&hdr); chdr != NULL;
+ chdr = CMSG_NXTHDR(&hdr, chdr)) {
+ if ((chdr->cmsg_level == SOL_SOCKET) &&
+ (chdr->cmsg_type == SCM_RIGHTS)) {
+ fdsize = chdr->cmsg_len - CMSG_LEN(0);
+ msg->num_fds = fdsize / sizeof(int);
+ memcpy(msg->fds, CMSG_DATA(chdr), fdsize);
+ break;
+ }
+ }
+
+ if (msg->size && msg->bytestream) {
+ msg->data2 = calloc(1, msg->size);
+ data = msg->data2;
+ } else {
+ data = (uint8_t *)&msg->data1;
+ }
+
+ if (msg->size) {
+ do {
+ rc = read(s->sock, data, msg->size);
+ } while (rc < 0 && (errno == EINTR || errno == EAGAIN));
+ }
+
+ pthread_mutex_unlock(&s->lock);
+
+ return rc;
+}
+
+static gboolean proxy_link_handler_prepare(GSource *gsrc, gint *timeout)
+{
+ g_assert(timeout);
+
+ *timeout = -1;
+
+ return FALSE;
+}
+
+static gboolean proxy_link_handler_check(GSource *gsrc)
+{
+ ProxySrc *src = (ProxySrc *)gsrc;
+
+ return src->gpfd.events & src->gpfd.revents;
+}
+
+static gboolean proxy_link_handler_dispatch(GSource *gsrc, GSourceFunc func,
+ gpointer data)
+{
+ ProxySrc *src = (ProxySrc *)gsrc;
+ ProxyLinkState *s = (ProxyLinkState *)data;
+
+ s->callback(src->gpfd.revents);
+
+ if ((src->gpfd.revents & G_IO_HUP) || (src->gpfd.revents & G_IO_ERR)) {
+ return G_SOURCE_REMOVE;
+ }
+
+ return G_SOURCE_CONTINUE;
+}
+GSourceFuncs gsrc_funcs = (GSourceFuncs){
+ .prepare = proxy_link_handler_prepare,
+ .check = proxy_link_handler_check,
+ .dispatch = proxy_link_handler_dispatch,
+ .finalize = NULL,
+};
+
+void proxy_link_set_sock(ProxyLinkState *s, int fd)
+{
+ s->sock = fd;
+}
+
+void proxy_link_set_callback(ProxyLinkState *s, proxy_link_callback callback)
+{
+ s->callback = callback;
+}
+
+void start_handler(ProxyLinkState *s)
+{
+ ProxySrc *src = (ProxySrc *)g_source_new(&gsrc_funcs, sizeof(ProxySrc));
+
+ g_source_set_callback(&src->gsrc, NULL, (gpointer)s, NULL);
+
+ src->gpfd.fd = s->sock;
+ src->gpfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ g_source_add_poll(&src->gsrc, &src->gpfd);
+ g_assert(g_source_attach(&src->gsrc, s->ctx));
+ s->src = src;
+
+ g_main_loop_run(s->loop);
+}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [RFC PATCH v1 3/8] multi-process QEMU: setup PCI host bridge for remote device
2018-10-12 23:48 [Qemu-devel] [RFC PATCH v1 0/8] multi-process QEMU Jagannathan Raman
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 1/8] multi-process QEMU: build system for remote device process Jagannathan Raman
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 2/8] multi-process QEMU: define proxy-link object Jagannathan Raman
@ 2018-10-12 23:48 ` Jagannathan Raman
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 4/8] multi-process QEMU: setup a machine for remote device process Jagannathan Raman
` (4 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Jagannathan Raman @ 2018-10-12 23:48 UTC (permalink / raw)
To: qemu-devel; +Cc: john.g.johnson, Kanth.Ghatraju, elena.ufimtseva, jag.raman
- PCI host bridge is setup for the remote device process. It is
implemented using remote-pcihost object. It is an extension of the PCI
host bridge setup by QEMU.
- remote-pcihost configures a PCI bus which could be used by the remote
PCI device to latch on to.
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
---
Makefile | 1 +
Makefile.objs | 4 +++
Makefile.target | 3 ++
hw/pci/Makefile.objs | 2 +-
include/remote/pcihost.h | 58 +++++++++++++++++++++++++++++++++
remote/Makefile.objs | 1 +
remote/pcihost.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 152 insertions(+), 1 deletion(-)
create mode 100644 include/remote/pcihost.h
create mode 100644 remote/Makefile.objs
create mode 100644 remote/pcihost.c
diff --git a/Makefile b/Makefile
index b6cac08..fe4244a 100644
--- a/Makefile
+++ b/Makefile
@@ -429,6 +429,7 @@ dummy := $(call unnest-vars,, \
qom-obj-y \
io-obj-y \
common-obj-y \
+ remote-obj-y \
scsi-dev-obj-y \
common-obj-m \
ui-obj-y \
diff --git a/Makefile.objs b/Makefile.objs
index 0a3799c..41a8c77 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -89,6 +89,10 @@ scsi-dev-obj-y += qdev-monitor.o
scsi-dev-obj-y += bootdevice.o
scsi-dev-obj-y += iothread.o
+#################################################
+# remote-obj-y is code used by all remote devices
+remote-obj-y += remote/
+
#######################################################################
# crypto-obj-y is code used by both qemu system emulation and qemu-img
diff --git a/Makefile.target b/Makefile.target
index c5feda2..74aab39 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -190,6 +190,7 @@ block-obj-y :=
common-obj-y :=
chardev-obj-y :=
scsi-dev-obj-y :=
+remote-obj-y :=
include $(SRC_PATH)/Makefile.objs
dummy := $(call unnest-vars,,target-obj-y)
target-obj-y-save := $(target-obj-y)
@@ -202,6 +203,7 @@ dummy := $(call unnest-vars,.., \
qom-obj-y \
io-obj-y \
common-obj-y \
+ remote-obj-y \
scsi-dev-obj-y \
common-obj-m)
target-obj-y := $(target-obj-y-save)
@@ -217,6 +219,7 @@ all-scsi-dev-obj-y += $(block-obj-y)
all-scsi-dev-obj-y += $(crypto-obj-y)
all-scsi-dev-obj-y += $(io-obj-y)
all-scsi-dev-obj-y += $(chardev-obj-y)
+all-scsi-dev-obj-y += $(remote-obj-y)
all-scsi-dev-obj-y += $(scsi-dev-obj-y)
$(QEMU_PROG_BUILD): config-devices.mak
diff --git a/hw/pci/Makefile.objs b/hw/pci/Makefile.objs
index 46af40a..f779285 100644
--- a/hw/pci/Makefile.objs
+++ b/hw/pci/Makefile.objs
@@ -8,6 +8,6 @@ common-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
common-obj-$(call lnot,$(CONFIG_PCI)) += pci-stub.o
common-obj-$(CONFIG_ALL) += pci-stub.o
-scsi-dev-obj-y += pci.o pci_bridge.o
+scsi-dev-obj-y += pci.o pci_bridge.o pci_host.o pcie_host.o
scsi-dev-obj-y += msi.o msix.o
scsi-dev-obj-y += pcie.o
diff --git a/include/remote/pcihost.h b/include/remote/pcihost.h
new file mode 100644
index 0000000..7357445
--- /dev/null
+++ b/include/remote/pcihost.h
@@ -0,0 +1,58 @@
+/*
+ * PCI Host for remote device
+ *
+ * Copyright 2018, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef REMOTE_PCIHOST_H
+#define REMOTE_PCIHOST_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "exec/memory.h"
+#include "hw/pci/pcie_host.h"
+
+#define TYPE_REMOTE_HOST_DEVICE "remote-pcihost"
+#define REMOTE_HOST_DEVICE(obj) \
+ OBJECT_CHECK(RemPCIHost, (obj), TYPE_REMOTE_HOST_DEVICE)
+
+typedef struct RemPCIHost {
+ /*< private >*/
+ PCIExpressHost parent_obj;
+ /*< public >*/
+
+ /* Memory Controller Hub (MCH) may not be necessary for the emulation
+ * program. The two important reasons for implementing a PCI host in the
+ * emulation program are:
+ * - Provide a PCI bus for IO devices
+ * - Enable translation of guest PA to the PCI bar regions
+ *
+ * For both the above mentioned purposes, it doesn't look like we would
+ * need the MCH
+ */
+
+ MemoryRegion *mr_pci_mem;
+ MemoryRegion *mr_sys_mem;
+ MemoryRegion *mr_sys_io;
+} RemPCIHost;
+
+#endif
diff --git a/remote/Makefile.objs b/remote/Makefile.objs
new file mode 100644
index 0000000..3072f95
--- /dev/null
+++ b/remote/Makefile.objs
@@ -0,0 +1 @@
+remote-obj-y += pcihost.o
diff --git a/remote/pcihost.c b/remote/pcihost.c
new file mode 100644
index 0000000..31cd7e8
--- /dev/null
+++ b/remote/pcihost.c
@@ -0,0 +1,84 @@
+/*
+ * Remote PCI host device
+ *
+ * Copyright 2018, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#include "qemu/osdep.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pci/pcie_host.h"
+#include "remote/pcihost.h"
+#include "exec/memory.h"
+
+static const char *remote_host_root_bus_path(PCIHostState *host_bridge,
+ PCIBus *rootbus)
+{
+ return "0000:00";
+}
+
+static void remote_host_realize(DeviceState *dev, Error **errp)
+{
+ PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+ RemPCIHost *s = REMOTE_HOST_DEVICE(dev);
+
+ /*
+ * TODO: the name of the bus would be provided by QEMU. Use
+ * "pcie.0" for now.
+ */
+ pci->bus = pci_root_bus_new(DEVICE(s), "pcie.0",
+ s->mr_pci_mem, s->mr_sys_io,
+ 0, TYPE_PCIE_BUS);
+}
+
+static Property remote_host_props[] = {
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void remote_host_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
+
+ hc->root_bus_path = remote_host_root_bus_path;
+ dc->realize = remote_host_realize;
+ dc->props = remote_host_props;
+
+ dc->user_creatable = false;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+ dc->fw_name = "pci";
+}
+
+static const TypeInfo remote_host_info = {
+ .name = TYPE_REMOTE_HOST_DEVICE,
+ .parent = TYPE_PCIE_HOST_BRIDGE,
+ .instance_size = sizeof(RemPCIHost),
+ .class_init = remote_host_class_init,
+};
+
+static void remote_machine_register(void)
+{
+ type_register_static(&remote_host_info);
+}
+
+type_init(remote_machine_register)
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [RFC PATCH v1 4/8] multi-process QEMU: setup a machine for remote device process
2018-10-12 23:48 [Qemu-devel] [RFC PATCH v1 0/8] multi-process QEMU Jagannathan Raman
` (2 preceding siblings ...)
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 3/8] multi-process QEMU: setup PCI host bridge for remote device Jagannathan Raman
@ 2018-10-12 23:48 ` Jagannathan Raman
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 5/8] multi-process QEMU: setup memory manager for remote device Jagannathan Raman
` (3 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Jagannathan Raman @ 2018-10-12 23:48 UTC (permalink / raw)
To: qemu-devel; +Cc: john.g.johnson, Kanth.Ghatraju, elena.ufimtseva, jag.raman
- remote-machine object sets up various subsystems of the remote device
process.
- PCI host bridge is instantiated
- RAM, IO & PCI memory regions are initialized
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
---
exec.c | 3 +-
hw/scsi/qemu-scsi-dev.c | 9 +++++
include/exec/address-spaces.h | 2 ++
include/remote/machine.h | 43 ++++++++++++++++++++++++
remote/Makefile.objs | 1 +
remote/machine.c | 78 +++++++++++++++++++++++++++++++++++++++++++
6 files changed, 134 insertions(+), 2 deletions(-)
create mode 100644 include/remote/machine.h
create mode 100644 remote/machine.c
diff --git a/exec.c b/exec.c
index d0821e6..7dafc0b 100644
--- a/exec.c
+++ b/exec.c
@@ -192,7 +192,6 @@ typedef struct subpage_t {
#define PHYS_SECTION_WATCH 3
static void io_mem_init(void);
-static void memory_map_init(void);
static void tcg_commit(MemoryListener *listener);
static MemoryRegion io_mem_watch;
@@ -3070,7 +3069,7 @@ static void tcg_commit(MemoryListener *listener)
tlb_flush(cpuas->cpu);
}
-static void memory_map_init(void)
+void memory_map_init(void)
{
system_memory = g_malloc(sizeof(*system_memory));
diff --git a/hw/scsi/qemu-scsi-dev.c b/hw/scsi/qemu-scsi-dev.c
index 3cb8698..21aba91 100644
--- a/hw/scsi/qemu-scsi-dev.c
+++ b/hw/scsi/qemu-scsi-dev.c
@@ -26,10 +26,19 @@
#include "qemu/osdep.h"
#include "qemu/module.h"
+#include "remote/pcihost.h"
+#include "remote/machine.h"
+#include "hw/boards.h"
+
+static RemMachineState *machine;
int main(int argc, char *argv[])
{
module_call_init(MODULE_INIT_QOM);
+ machine = REMOTE_MACHINE(object_new(TYPE_REMOTE_MACHINE));
+
+ current_machine = MACHINE(machine);
+
return 0;
}
diff --git a/include/exec/address-spaces.h b/include/exec/address-spaces.h
index db8bfa9..56a877b 100644
--- a/include/exec/address-spaces.h
+++ b/include/exec/address-spaces.h
@@ -33,6 +33,8 @@ MemoryRegion *get_system_memory(void);
*/
MemoryRegion *get_system_io(void);
+void memory_map_init(void);
+
extern AddressSpace address_space_memory;
extern AddressSpace address_space_io;
diff --git a/include/remote/machine.h b/include/remote/machine.h
new file mode 100644
index 0000000..92f9793
--- /dev/null
+++ b/include/remote/machine.h
@@ -0,0 +1,43 @@
+/*
+ * Remote machine configuration
+ *
+ * Copyright 2018, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef REMOTE_MACHINE_H
+#define REMOTE_MACHINE_H
+
+#include "qemu/osdep.h"
+#include "qom/object.h"
+#include "hw/boards.h"
+#include "remote/pcihost.h"
+
+typedef struct RemMachineState {
+ MachineState parent_obj;
+
+ RemPCIHost *host;
+} RemMachineState;
+
+#define TYPE_REMOTE_MACHINE "remote-machine"
+#define REMOTE_MACHINE(obj) \
+ OBJECT_CHECK(RemMachineState, (obj), TYPE_REMOTE_MACHINE)
+
+#endif
diff --git a/remote/Makefile.objs b/remote/Makefile.objs
index 3072f95..e90ae20 100644
--- a/remote/Makefile.objs
+++ b/remote/Makefile.objs
@@ -1 +1,2 @@
remote-obj-y += pcihost.o
+remote-obj-y += machine.o
diff --git a/remote/machine.c b/remote/machine.c
new file mode 100644
index 0000000..9aea0ba
--- /dev/null
+++ b/remote/machine.c
@@ -0,0 +1,78 @@
+/*
+ * Machine for remote device
+ *
+ * Copyright 2018, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "qemu/osdep.h"
+#include "remote/pcihost.h"
+#include "remote/machine.h"
+#include "exec/address-spaces.h"
+#include "exec/memory.h"
+#include "exec/ioport.h"
+#include "exec/ramlist.h"
+#include "qemu/thread.h"
+#include "qom/object.h"
+#include "qemu/module.h"
+
+static void remote_machine_init(Object *obj)
+{
+ RemMachineState *s = REMOTE_MACHINE(obj);
+ RemPCIHost *rem_host;
+ MemoryRegion *system_memory, *system_io, *pci_memory;
+
+ qemu_mutex_init(&ram_list.mutex);
+
+ memory_map_init();
+
+ system_memory = get_system_memory();
+ system_io = get_system_io();
+
+ pci_memory = g_new(MemoryRegion, 1);
+ memory_region_init(pci_memory, NULL, "pci", UINT64_MAX);
+
+ rem_host = REMOTE_HOST_DEVICE(qdev_create(NULL, TYPE_REMOTE_HOST_DEVICE));
+
+ rem_host->mr_pci_mem = pci_memory;
+ rem_host->mr_sys_mem = system_memory;
+ rem_host->mr_sys_io = system_io;
+
+ s->host = rem_host;
+
+ qdev_init_nofail(DEVICE(rem_host));
+}
+
+static const TypeInfo remote_machine = {
+ .name = TYPE_REMOTE_MACHINE,
+ .parent = TYPE_MACHINE,
+ .instance_size = sizeof(RemMachineState),
+ .instance_init = remote_machine_init,
+};
+
+static void remote_machine_register_types(void)
+{
+ type_register_static(&remote_machine);
+}
+
+type_init(remote_machine_register_types);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [RFC PATCH v1 5/8] multi-process QEMU: setup memory manager for remote device
2018-10-12 23:48 [Qemu-devel] [RFC PATCH v1 0/8] multi-process QEMU Jagannathan Raman
` (3 preceding siblings ...)
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 4/8] multi-process QEMU: setup a machine for remote device process Jagannathan Raman
@ 2018-10-12 23:48 ` Jagannathan Raman
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 6/8] multi-process QEMU: remote process initialization Jagannathan Raman
` (2 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Jagannathan Raman @ 2018-10-12 23:48 UTC (permalink / raw)
To: qemu-devel; +Cc: john.g.johnson, Kanth.Ghatraju, elena.ufimtseva, jag.raman
- sync_sysmem_msg_t message format is defined. It is used to send
file descriptors of the RAM regions to remote device
- RAM on the remote device is configured with a set of file descriptors.
Old RAM regions are deleted and new regions, each with an fd, is
added to the RAM.
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
---
include/io/proxy-link.h | 9 +++++
include/remote/memory.h | 34 ++++++++++++++++++
remote/Makefile.objs | 1 +
remote/memory.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 137 insertions(+)
create mode 100644 include/remote/memory.h
create mode 100644 remote/memory.c
diff --git a/include/io/proxy-link.h b/include/io/proxy-link.h
index 6ce6c10..1eeabae 100644
--- a/include/io/proxy-link.h
+++ b/include/io/proxy-link.h
@@ -39,6 +39,8 @@ typedef struct ProxyLinkState ProxyLinkState;
#define PROXY_LINK(obj) \
OBJECT_CHECK(ProxyLinkState, (obj), TYPE_PROXY_LINK)
+#include "exec/hwaddr.h"
+
#define MAX_FDS 8
#define PROC_HDR_SIZE offsetof(ProcMsg, data1.u64)
@@ -47,16 +49,23 @@ typedef enum {
INIT = 0,
CONF_READ,
CONF_WRITE,
+ SYNC_SYSMEM,
MAX,
} proc_cmd_t;
typedef struct {
+ hwaddr gpas[MAX_FDS];
+ uint64_t sizes[MAX_FDS];
+} sync_sysmem_msg_t;
+
+typedef struct {
proc_cmd_t cmd;
int bytestream;
size_t size;
union {
uint64_t u64;
+ sync_sysmem_msg_t sync_sysmem;
} data1;
int fds[MAX_FDS];
diff --git a/include/remote/memory.h b/include/remote/memory.h
new file mode 100644
index 0000000..4500192
--- /dev/null
+++ b/include/remote/memory.h
@@ -0,0 +1,34 @@
+/*
+ * Memory manager for remote device
+ *
+ * Copyright 2018, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef REMOTE_MEMORY_H
+#define REMOTE_MEMORY_H
+
+#include "qemu/osdep.h"
+#include "exec/hwaddr.h"
+#include "io/proxy-link.h"
+
+void remote_sysmem_reconfig(ProcMsg *msg, Error **errp);
+
+#endif
diff --git a/remote/Makefile.objs b/remote/Makefile.objs
index e90ae20..c52d500 100644
--- a/remote/Makefile.objs
+++ b/remote/Makefile.objs
@@ -1,2 +1,3 @@
remote-obj-y += pcihost.o
remote-obj-y += machine.o
+remote-obj-y += memory.o
diff --git a/remote/memory.c b/remote/memory.c
new file mode 100644
index 0000000..f4cf2d2
--- /dev/null
+++ b/remote/memory.c
@@ -0,0 +1,93 @@
+/*
+ * Memory manager for remote device
+ *
+ * Copyright 2018, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "qemu/osdep.h"
+#include "qemu/queue.h"
+#include "qemu-common.h"
+#include "remote/memory.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "cpu.h"
+#include "exec/ram_addr.h"
+#include "io/proxy-link.h"
+#include "qemu/main-loop.h"
+
+static void remote_ram_destructor(MemoryRegion *mr)
+{
+ qemu_ram_free(mr->ram_block);
+}
+
+static void remote_ram_init_from_fd(MemoryRegion *mr, int fd, uint64_t size,
+ Error **errp)
+{
+ char *name;
+
+ name = g_malloc(sizeof(int) + 1);
+ snprintf(name, sizeof(int) + 1, "%x", fd);
+
+ memory_region_init(mr, NULL, name, size);
+ mr->ram = true;
+ mr->terminates = true;
+ mr->destructor = remote_ram_destructor;
+ mr->align = 0;
+ mr->ram_block = qemu_ram_alloc_from_fd(size, mr, false, fd, errp);
+ mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
+
+ g_free(name);
+}
+
+void remote_sysmem_reconfig(ProcMsg *msg, Error **errp)
+{
+ MemoryRegion *sysmem, *subregion, *next;
+ int region;
+ sync_sysmem_msg_t *sysmem_info = &msg->data1.sync_sysmem;
+
+ sysmem = get_system_memory();
+
+ qemu_mutex_lock_iothread();
+
+ memory_region_transaction_begin();
+
+ QTAILQ_FOREACH_SAFE(subregion, &sysmem->subregions, subregions_link, next) {
+ if (subregion->ram) {
+ memory_region_del_subregion(sysmem, subregion);
+ /* TODO: should subregion be finalized separately? */
+ }
+ }
+
+ for (region = 0; region < msg->num_fds; region++) {
+ subregion = g_new(MemoryRegion, 1);
+ remote_ram_init_from_fd(subregion, msg->fds[region],
+ sysmem_info->sizes[region], errp);
+ memory_region_add_subregion(sysmem, sysmem_info->gpas[region],
+ subregion);
+ }
+
+ memory_region_transaction_commit();
+
+ qemu_mutex_unlock_iothread();
+}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [RFC PATCH v1 6/8] multi-process QEMU: remote process initialization
2018-10-12 23:48 [Qemu-devel] [RFC PATCH v1 0/8] multi-process QEMU Jagannathan Raman
` (4 preceding siblings ...)
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 5/8] multi-process QEMU: setup memory manager for remote device Jagannathan Raman
@ 2018-10-12 23:48 ` Jagannathan Raman
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 7/8] multi-process QEMU: introduce proxy object Jagannathan Raman
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 8/8] multi-process QEMU: synchronize RAM between QEMU & remote device Jagannathan Raman
7 siblings, 0 replies; 10+ messages in thread
From: Jagannathan Raman @ 2018-10-12 23:48 UTC (permalink / raw)
To: qemu-devel; +Cc: john.g.johnson, Kanth.Ghatraju, elena.ufimtseva, jag.raman
Initialize remote process main loop and add the message
handling logic. Handle SYNC_SYSMEM message by updating
its "system_memory" container using shared file descriptors
received from QEMU.
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
---
hw/scsi/qemu-scsi-dev.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 71 insertions(+)
diff --git a/hw/scsi/qemu-scsi-dev.c b/hw/scsi/qemu-scsi-dev.c
index 21aba91..ede0c4b 100644
--- a/hw/scsi/qemu-scsi-dev.c
+++ b/hw/scsi/qemu-scsi-dev.c
@@ -23,22 +23,93 @@
*/
#include <stdio.h>
+#include <glib.h>
+#include <unistd.h>
#include "qemu/osdep.h"
#include "qemu/module.h"
#include "remote/pcihost.h"
#include "remote/machine.h"
#include "hw/boards.h"
+#include "remote/memory.h"
+#include "io/proxy-link.h"
+#include "qapi/error.h"
+#include "qemu/main-loop.h"
+#include "sysemu/cpus.h"
+#include "qemu-common.h"
static RemMachineState *machine;
+static ProxyLinkState *proxy_link;
+
+static void process_msg(GIOCondition cond)
+{
+ ProcMsg *msg = NULL;
+ Error *err = NULL;
+
+ if ((cond & G_IO_HUP) || (cond & G_IO_ERR)) {
+ error_setg(&err, "socket closed, cond is %d", cond);
+ goto finalize_loop;
+ }
+
+ msg = g_malloc0(sizeof(ProcMsg));
+
+ if (proxy_proc_recv(proxy_link, msg)) {
+ error_setg(&err, "Failed to receive message");
+ goto finalize_loop;
+ }
+
+ switch (msg->cmd) {
+ case INIT:
+ break;
+ case CONF_WRITE:
+ break;
+ case CONF_READ:
+ break;
+ default:
+ error_setg(&err, "Unknown command");
+ goto finalize_loop;
+ }
+
+ g_free(msg);
+
+ return;
+
+finalize_loop:
+ error_report_err(err);
+ g_free(msg);
+ proxy_link_finalize(proxy_link);
+ proxy_link = NULL;
+}
int main(int argc, char *argv[])
{
+ Error *err = NULL;
+
module_call_init(MODULE_INIT_QOM);
machine = REMOTE_MACHINE(object_new(TYPE_REMOTE_MACHINE));
current_machine = MACHINE(machine);
+ if (qemu_init_main_loop(&err)) {
+ error_report_err(err);
+ return -EBUSY;
+ }
+
+ qemu_init_cpu_loop();
+
+ page_size_init();
+
+ proxy_link = proxy_link_create();
+ if (!proxy_link) {
+ printf("Could not create proxy link\n");
+ return -1;
+ }
+
+ proxy_link_set_sock(proxy_link, STDIN_FILENO);
+ proxy_link_set_callback(proxy_link, process_msg);
+
+ start_handler(proxy_link);
+
return 0;
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [RFC PATCH v1 7/8] multi-process QEMU: introduce proxy object
2018-10-12 23:48 [Qemu-devel] [RFC PATCH v1 0/8] multi-process QEMU Jagannathan Raman
` (5 preceding siblings ...)
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 6/8] multi-process QEMU: remote process initialization Jagannathan Raman
@ 2018-10-12 23:48 ` Jagannathan Raman
2018-10-18 15:14 ` Elena Ufimtseva
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 8/8] multi-process QEMU: synchronize RAM between QEMU & remote device Jagannathan Raman
7 siblings, 1 reply; 10+ messages in thread
From: Jagannathan Raman @ 2018-10-12 23:48 UTC (permalink / raw)
To: qemu-devel; +Cc: john.g.johnson, Kanth.Ghatraju, elena.ufimtseva, jag.raman
From: Elena Ufimtseva <elena.ufimtseva@oracle.com>
Define PCI Device proxy object as a parent of TYPE_PCI_DEVICE.
PCI Proxy Object will register PCI BARs, MemoryRegionOps to handle
access to the BARs and forward those to the remote device.
PCI Proxy object intercepts config space reads and writes. In case
of pci config write it forwards it to the remote device using
communication channel.
TODO:
- Handle interrupt messages from the emulation program and implement
DMA operations.
Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
---
hw/Makefile.objs | 2 +
hw/qemu-proxy.c | 215 ++++++++++++++++++++++++++++++++++++++++++++++++
include/hw/qemu-proxy.h | 56 +++++++++++++
3 files changed, 273 insertions(+)
create mode 100644 hw/qemu-proxy.c
create mode 100644 include/hw/qemu-proxy.h
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 9c99c29..6bb2eb0 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -44,3 +44,5 @@ scsi-dev-obj-y += scsi/
scsi-dev-obj-y += block/
scsi-dev-obj-y += pci/
scsi-dev-obj-y += nvram/
+
+common-obj-y += qemu-proxy.o
diff --git a/hw/qemu-proxy.c b/hw/qemu-proxy.c
new file mode 100644
index 0000000..1712b41
--- /dev/null
+++ b/hw/qemu-proxy.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2018, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <assert.h>
+#include <string.h>
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "io/proxy-link.h"
+#include "exec/memory.h"
+#include "exec/cpu-common.h"
+#include "exec/address-spaces.h"
+#include "qemu/int128.h"
+#include "qemu/range.h"
+#include "hw/pci/pci.h"
+#include "qemu/option.h"
+#include "qemu/config-file.h"
+#include "qapi/qmp/qjson.h"
+#include "qapi/qmp/qstring.h"
+#include "sysemu/sysemu.h"
+#include "hw/qemu-proxy.h"
+
+char command[] = "qemu-scsi-dev";
+
+static void pci_proxy_dev_realize(PCIDevice *dev, Error **errp);
+
+int config_op_send(PCIProxyDev *dev, uint32_t addr, uint32_t val, int l,
+ unsigned int op)
+{
+ ProcMsg msg;
+ struct conf_data_msg conf_data;
+
+ conf_data.addr = addr;
+ conf_data.val = val;
+ conf_data.l = l;
+
+
+ msg.data2 = (uint8_t *)malloc(sizeof(conf_data));
+ if (!msg.data2) {
+ printf("Failed to allocate memory for msg.data2\n");
+ return -ENOMEM;
+ }
+ memcpy(msg.data2, (const uint8_t *)&conf_data, sizeof(conf_data));
+ msg.size = sizeof(conf_data);
+ msg.num_fds = 0;
+ msg.cmd = op;
+ msg.bytestream = 1;
+
+ proxy_proc_send(dev->proxy_dev.proxy_link, &msg);
+ free(msg.data2);
+
+ return 0;
+}
+
+static uint32_t pci_proxy_read_config(PCIDevice *d,
+ uint32_t addr, int len)
+{
+ config_op_send(PCI_PROXY_DEV(d), addr, 0, 0, CONF_READ);
+ return pci_default_read_config(d, addr, len);
+}
+
+static void pci_proxy_write_config(PCIDevice *d, uint32_t addr, uint32_t val,
+ int l)
+{
+ pci_default_write_config(d, addr, val, l);
+ config_op_send(PCI_PROXY_DEV(d), addr, val, l, CONF_WRITE);
+}
+
+
+static void pci_proxy_dev_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->realize = pci_proxy_dev_realize;
+ k->class_id = PCI_CLASS_SYSTEM_OTHER;
+ k->vendor_id = PCI_VENDOR_ID_REDHAT;
+ k->device_id = PCI_DEVICE_ID_REDHAT_TEST;
+ k->config_read = pci_proxy_read_config;
+ k->config_write = pci_proxy_write_config;
+
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ dc->desc = "PCI Proxy Device";
+}
+
+static const TypeInfo pci_proxy_dev_type_info = {
+ .name = TYPE_PCI_PROXY_DEV,
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIProxyDev),
+ .class_init = pci_proxy_dev_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { INTERFACE_CONVENTIONAL_PCI_DEVICE },
+ { },
+ }
+};
+
+static void pci_proxy_mmio_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ return;
+}
+
+static uint64_t pci_proxy_mmio_read(void *opaque, hwaddr addr, unsigned size)
+{
+ return 0;
+}
+
+static const MemoryRegionOps proxy_device_mmio_ops = {
+ .read = pci_proxy_mmio_read,
+ .write = pci_proxy_mmio_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ .min_access_size = 1,
+ }
+};
+
+static void pci_proxy_dev_register_types(void)
+{
+ type_register_static(&pci_proxy_dev_type_info);
+}
+
+static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
+{
+ PCIProxyDev *dev = PCI_PROXY_DEV(device);
+ uint8_t *pci_conf;
+
+ pci_conf = device->config;
+
+ init_emulation_process(dev, command, errp);
+ if (*errp) {
+ printf("Process did not start\n");
+ error_report_err(*errp);
+ }
+
+ if (!dev->proxy_dev.proxy_link) {
+ printf("Proxy link is not set\n");
+ }
+
+ pci_conf[PCI_LATENCY_TIMER] = 0xff;
+
+ memory_region_init_io(&dev->mmio_io, OBJECT(dev), &proxy_device_mmio_ops,
+ dev, "proxy-device-mmio", 0x400);
+
+ pci_register_bar(device, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &dev->mmio_io);
+
+}
+
+void init_emulation_process(PCIProxyDev *pdev, char *command, Error **errp)
+{
+ char *args[2];
+ pid_t rpid;
+ int fd[2];
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
+ error_setg(errp, "Unable to create unix socket.");
+ return;
+ }
+
+ rpid = qemu_fork(errp);
+
+ if (rpid == -1) {
+ error_setg(errp, "Unable to spawn emulation program.");
+ return;
+ }
+
+ if (rpid == 0) {
+ if (dup2(fd[1], STDIN_FILENO) != STDIN_FILENO) {
+ perror("Failed to acquire socket.");
+ exit(1);
+ }
+
+ close(fd[0]);
+ close(fd[1]);
+
+ args[0] = command;
+ args[1] = NULL;
+ execvp(args[0], (char *const *)args);
+ exit(1);
+ }
+
+ pdev->proxy_dev.proxy_link = proxy_link_create();
+
+ if (!pdev->proxy_dev.proxy_link) {
+ return;
+ }
+
+ proxy_link_set_sock(pdev->proxy_dev.proxy_link, fd[0]);
+ close(fd[1]);
+
+}
+
+type_init(pci_proxy_dev_register_types)
diff --git a/include/hw/qemu-proxy.h b/include/hw/qemu-proxy.h
new file mode 100644
index 0000000..0903626
--- /dev/null
+++ b/include/hw/qemu-proxy.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2018, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef QEMU_PROXY_H
+#define QEMU_PROXY_H
+
+#include "io/proxy-link.h"
+
+#define TYPE_PCI_PROXY_DEV "pci-proxy-dev"
+#define PCI_PROXY_DEV(obj) \
+ OBJECT_CHECK(PCIProxyDev, (obj), TYPE_PCI_PROXY_DEV)
+
+typedef struct proxy_device {
+ int n_mr_sections;
+ MemoryRegionSection *mr_sections;
+ ProxyLinkState *proxy_link;
+ int link_up;
+} proxy_device;
+
+typedef struct PCIProxyDev {
+ PCIDevice parent_dev;
+ struct proxy_device proxy_dev;
+
+ MemoryRegion bar;
+ MemoryRegion mmio_io;
+ MemoryRegion ram_io;
+
+ void (*proxy_read_config)(void);
+ void (*proxy_write_config) (void);
+
+} PCIProxyDev;
+
+void init_emulation_process(PCIProxyDev *pdev, char *command, Error **errp);
+int config_op_send(PCIProxyDev *dev, uint32_t addr, uint32_t val, int l,
+ unsigned int op);
+
+#endif
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [RFC PATCH v1 7/8] multi-process QEMU: introduce proxy object
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 7/8] multi-process QEMU: introduce proxy object Jagannathan Raman
@ 2018-10-18 15:14 ` Elena Ufimtseva
0 siblings, 0 replies; 10+ messages in thread
From: Elena Ufimtseva @ 2018-10-18 15:14 UTC (permalink / raw)
To: Jagannathan Raman; +Cc: qemu-devel, john.g.johnson, Kanth.Ghatraju
On Fri, Oct 12, 2018 at 07:48:34PM -0400, Jagannathan Raman wrote:
> From: Elena Ufimtseva <elena.ufimtseva@oracle.com>
>
> Define PCI Device proxy object as a parent of TYPE_PCI_DEVICE.
> PCI Proxy Object will register PCI BARs, MemoryRegionOps to handle
> access to the BARs and forward those to the remote device.
> PCI Proxy object intercepts config space reads and writes. In case
> of pci config write it forwards it to the remote device using
> communication channel.
>
> TODO:
> - Handle interrupt messages from the emulation program and implement
> DMA operations.
>
And one more to add to TODO:
- dont use malloc/free.
Elena
> Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
> ---
> hw/Makefile.objs | 2 +
> hw/qemu-proxy.c | 215 ++++++++++++++++++++++++++++++++++++++++++++++++
> include/hw/qemu-proxy.h | 56 +++++++++++++
> 3 files changed, 273 insertions(+)
> create mode 100644 hw/qemu-proxy.c
> create mode 100644 include/hw/qemu-proxy.h
>
> diff --git a/hw/Makefile.objs b/hw/Makefile.objs
> index 9c99c29..6bb2eb0 100644
> --- a/hw/Makefile.objs
> +++ b/hw/Makefile.objs
> @@ -44,3 +44,5 @@ scsi-dev-obj-y += scsi/
> scsi-dev-obj-y += block/
> scsi-dev-obj-y += pci/
> scsi-dev-obj-y += nvram/
> +
> +common-obj-y += qemu-proxy.o
> diff --git a/hw/qemu-proxy.c b/hw/qemu-proxy.c
> new file mode 100644
> index 0000000..1712b41
> --- /dev/null
> +++ b/hw/qemu-proxy.c
> @@ -0,0 +1,215 @@
> +/*
> + * Copyright 2018, Oracle and/or its affiliates. All rights reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <unistd.h>
> +#include <assert.h>
> +#include <string.h>
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "io/proxy-link.h"
> +#include "exec/memory.h"
> +#include "exec/cpu-common.h"
> +#include "exec/address-spaces.h"
> +#include "qemu/int128.h"
> +#include "qemu/range.h"
> +#include "hw/pci/pci.h"
> +#include "qemu/option.h"
> +#include "qemu/config-file.h"
> +#include "qapi/qmp/qjson.h"
> +#include "qapi/qmp/qstring.h"
> +#include "sysemu/sysemu.h"
> +#include "hw/qemu-proxy.h"
> +
> +char command[] = "qemu-scsi-dev";
> +
> +static void pci_proxy_dev_realize(PCIDevice *dev, Error **errp);
> +
> +int config_op_send(PCIProxyDev *dev, uint32_t addr, uint32_t val, int l,
> + unsigned int op)
> +{
> + ProcMsg msg;
> + struct conf_data_msg conf_data;
> +
> + conf_data.addr = addr;
> + conf_data.val = val;
> + conf_data.l = l;
> +
> +
> + msg.data2 = (uint8_t *)malloc(sizeof(conf_data));
> + if (!msg.data2) {
> + printf("Failed to allocate memory for msg.data2\n");
> + return -ENOMEM;
> + }
> + memcpy(msg.data2, (const uint8_t *)&conf_data, sizeof(conf_data));
> + msg.size = sizeof(conf_data);
> + msg.num_fds = 0;
> + msg.cmd = op;
> + msg.bytestream = 1;
> +
> + proxy_proc_send(dev->proxy_dev.proxy_link, &msg);
> + free(msg.data2);
> +
> + return 0;
> +}
> +
> +static uint32_t pci_proxy_read_config(PCIDevice *d,
> + uint32_t addr, int len)
> +{
> + config_op_send(PCI_PROXY_DEV(d), addr, 0, 0, CONF_READ);
> + return pci_default_read_config(d, addr, len);
> +}
> +
> +static void pci_proxy_write_config(PCIDevice *d, uint32_t addr, uint32_t val,
> + int l)
> +{
> + pci_default_write_config(d, addr, val, l);
> + config_op_send(PCI_PROXY_DEV(d), addr, val, l, CONF_WRITE);
> +}
> +
> +
> +static void pci_proxy_dev_class_init(ObjectClass *klass, void *data)
> +{
> + DeviceClass *dc = DEVICE_CLASS(klass);
> + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
> +
> + k->realize = pci_proxy_dev_realize;
> + k->class_id = PCI_CLASS_SYSTEM_OTHER;
> + k->vendor_id = PCI_VENDOR_ID_REDHAT;
> + k->device_id = PCI_DEVICE_ID_REDHAT_TEST;
> + k->config_read = pci_proxy_read_config;
> + k->config_write = pci_proxy_write_config;
> +
> + set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> + dc->desc = "PCI Proxy Device";
> +}
> +
> +static const TypeInfo pci_proxy_dev_type_info = {
> + .name = TYPE_PCI_PROXY_DEV,
> + .parent = TYPE_PCI_DEVICE,
> + .instance_size = sizeof(PCIProxyDev),
> + .class_init = pci_proxy_dev_class_init,
> + .interfaces = (InterfaceInfo[]) {
> + { INTERFACE_CONVENTIONAL_PCI_DEVICE },
> + { },
> + }
> +};
> +
> +static void pci_proxy_mmio_write(void *opaque, hwaddr addr, uint64_t val,
> + unsigned size)
> +{
> + return;
> +}
> +
> +static uint64_t pci_proxy_mmio_read(void *opaque, hwaddr addr, unsigned size)
> +{
> + return 0;
> +}
> +
> +static const MemoryRegionOps proxy_device_mmio_ops = {
> + .read = pci_proxy_mmio_read,
> + .write = pci_proxy_mmio_write,
> + .endianness = DEVICE_NATIVE_ENDIAN,
> + .impl = {
> + .min_access_size = 1,
> + }
> +};
> +
> +static void pci_proxy_dev_register_types(void)
> +{
> + type_register_static(&pci_proxy_dev_type_info);
> +}
> +
> +static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
> +{
> + PCIProxyDev *dev = PCI_PROXY_DEV(device);
> + uint8_t *pci_conf;
> +
> + pci_conf = device->config;
> +
> + init_emulation_process(dev, command, errp);
> + if (*errp) {
> + printf("Process did not start\n");
> + error_report_err(*errp);
> + }
> +
> + if (!dev->proxy_dev.proxy_link) {
> + printf("Proxy link is not set\n");
> + }
> +
> + pci_conf[PCI_LATENCY_TIMER] = 0xff;
> +
> + memory_region_init_io(&dev->mmio_io, OBJECT(dev), &proxy_device_mmio_ops,
> + dev, "proxy-device-mmio", 0x400);
> +
> + pci_register_bar(device, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &dev->mmio_io);
> +
> +}
> +
> +void init_emulation_process(PCIProxyDev *pdev, char *command, Error **errp)
> +{
> + char *args[2];
> + pid_t rpid;
> + int fd[2];
> +
> + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
> + error_setg(errp, "Unable to create unix socket.");
> + return;
> + }
> +
> + rpid = qemu_fork(errp);
> +
> + if (rpid == -1) {
> + error_setg(errp, "Unable to spawn emulation program.");
> + return;
> + }
> +
> + if (rpid == 0) {
> + if (dup2(fd[1], STDIN_FILENO) != STDIN_FILENO) {
> + perror("Failed to acquire socket.");
> + exit(1);
> + }
> +
> + close(fd[0]);
> + close(fd[1]);
> +
> + args[0] = command;
> + args[1] = NULL;
> + execvp(args[0], (char *const *)args);
> + exit(1);
> + }
> +
> + pdev->proxy_dev.proxy_link = proxy_link_create();
> +
> + if (!pdev->proxy_dev.proxy_link) {
> + return;
> + }
> +
> + proxy_link_set_sock(pdev->proxy_dev.proxy_link, fd[0]);
> + close(fd[1]);
> +
> +}
> +
> +type_init(pci_proxy_dev_register_types)
> diff --git a/include/hw/qemu-proxy.h b/include/hw/qemu-proxy.h
> new file mode 100644
> index 0000000..0903626
> --- /dev/null
> +++ b/include/hw/qemu-proxy.h
> @@ -0,0 +1,56 @@
> +/*
> + * Copyright 2018, Oracle and/or its affiliates. All rights reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#ifndef QEMU_PROXY_H
> +#define QEMU_PROXY_H
> +
> +#include "io/proxy-link.h"
> +
> +#define TYPE_PCI_PROXY_DEV "pci-proxy-dev"
> +#define PCI_PROXY_DEV(obj) \
> + OBJECT_CHECK(PCIProxyDev, (obj), TYPE_PCI_PROXY_DEV)
> +
> +typedef struct proxy_device {
> + int n_mr_sections;
> + MemoryRegionSection *mr_sections;
> + ProxyLinkState *proxy_link;
> + int link_up;
> +} proxy_device;
> +
> +typedef struct PCIProxyDev {
> + PCIDevice parent_dev;
> + struct proxy_device proxy_dev;
> +
> + MemoryRegion bar;
> + MemoryRegion mmio_io;
> + MemoryRegion ram_io;
> +
> + void (*proxy_read_config)(void);
> + void (*proxy_write_config) (void);
> +
> +} PCIProxyDev;
> +
> +void init_emulation_process(PCIProxyDev *pdev, char *command, Error **errp);
> +int config_op_send(PCIProxyDev *dev, uint32_t addr, uint32_t val, int l,
> + unsigned int op);
> +
> +#endif
> --
> 1.8.3.1
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] [RFC PATCH v1 8/8] multi-process QEMU: synchronize RAM between QEMU & remote device
2018-10-12 23:48 [Qemu-devel] [RFC PATCH v1 0/8] multi-process QEMU Jagannathan Raman
` (6 preceding siblings ...)
2018-10-12 23:48 ` [Qemu-devel] [RFC PATCH v1 7/8] multi-process QEMU: introduce proxy object Jagannathan Raman
@ 2018-10-12 23:48 ` Jagannathan Raman
7 siblings, 0 replies; 10+ messages in thread
From: Jagannathan Raman @ 2018-10-12 23:48 UTC (permalink / raw)
To: qemu-devel; +Cc: john.g.johnson, Kanth.Ghatraju, elena.ufimtseva, jag.raman
- Setup MemoryListener in QEMU to get all updates to sysmem, and
forward all RAM updates to remote device process
- Remote device process updates its "system_memory" container using
shared file descriptors provided by SYNC_SYSMEM message
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
---
hw/qemu-proxy.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++
hw/scsi/qemu-scsi-dev.c | 10 ++++
include/hw/qemu-proxy.h | 3 +
3 files changed, 169 insertions(+)
diff --git a/hw/qemu-proxy.c b/hw/qemu-proxy.c
index 1712b41..79cdd3f 100644
--- a/hw/qemu-proxy.c
+++ b/hw/qemu-proxy.c
@@ -159,6 +159,8 @@ static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
printf("Proxy link is not set\n");
}
+ configure_memory_listener(dev);
+
pci_conf[PCI_LATENCY_TIMER] = 0xff;
memory_region_init_io(&dev->mmio_io, OBJECT(dev), &proxy_device_mmio_ops,
@@ -213,3 +215,157 @@ void init_emulation_process(PCIProxyDev *pdev, char *command, Error **errp)
}
type_init(pci_proxy_dev_register_types)
+
+static void proxy_ml_begin(MemoryListener *listener)
+{
+ int mrs;
+ struct proxy_device *pdev = container_of(listener, struct proxy_device,
+ memory_listener);
+
+ for (mrs = 0; mrs < pdev->n_mr_sections; mrs++) {
+ memory_region_unref(pdev->mr_sections[mrs].mr);
+ }
+
+ g_free(pdev->mr_sections);
+ pdev->mr_sections = NULL;
+ pdev->n_mr_sections = 0;
+}
+
+static bool proxy_mrs_can_merge(uint64_t host, uint64_t prev_host, size_t size)
+{
+ bool merge;
+ ram_addr_t offset;
+ int fd1, fd2;
+ MemoryRegion *mr;
+
+ mr = memory_region_from_host((void *)(uintptr_t)host, &offset);
+ fd1 = memory_region_get_fd(mr);
+
+ mr = memory_region_from_host((void *)(uintptr_t)prev_host, &offset);
+ fd2 = memory_region_get_fd(mr);
+
+ merge = (fd1 == fd2);
+
+ merge &= ((prev_host + size) == host);
+
+ return merge;
+}
+
+static void proxy_ml_region_addnop(MemoryListener *listener,
+ MemoryRegionSection *section)
+{
+ bool need_add = true;
+ uint64_t mrs_size, mrs_gpa, mrs_page;
+ uintptr_t mrs_host;
+ RAMBlock *mrs_rb;
+ MemoryRegionSection *prev_sec;
+ struct proxy_device *pdev = container_of(listener, struct proxy_device,
+ memory_listener);
+
+ if (!(memory_region_is_ram(section->mr) &&
+ !memory_region_is_rom(section->mr))) {
+ return;
+ }
+
+ mrs_rb = section->mr->ram_block;
+ mrs_page = (uint64_t)qemu_ram_pagesize(mrs_rb);
+ mrs_size = int128_get64(section->size);
+ mrs_gpa = section->offset_within_address_space;
+ mrs_host = (uintptr_t)memory_region_get_ram_ptr(section->mr) +
+ section->offset_within_region;
+
+ mrs_host = mrs_host & ~(mrs_page - 1);
+ mrs_gpa = mrs_gpa & ~(mrs_page - 1);
+ mrs_size = ROUND_UP(mrs_size, mrs_page);
+
+ if (pdev->n_mr_sections) {
+ prev_sec = pdev->mr_sections + (pdev->n_mr_sections - 1);
+ uint64_t prev_gpa_start = prev_sec->offset_within_address_space;
+ uint64_t prev_size = int128_get64(prev_sec->size);
+ uint64_t prev_gpa_end = range_get_last(prev_gpa_start, prev_size);
+ uint64_t prev_host_start =
+ (uintptr_t)memory_region_get_ram_ptr(prev_sec->mr) +
+ prev_sec->offset_within_region;
+ uint64_t prev_host_end = range_get_last(prev_host_start, prev_size);
+
+ if (mrs_gpa <= (prev_gpa_end + 1)) {
+ if (mrs_gpa < prev_gpa_start) {
+ assert(0);
+ }
+
+ if ((section->mr == prev_sec->mr) &&
+ proxy_mrs_can_merge(mrs_host, prev_host_start,
+ (mrs_gpa - prev_gpa_start))) {
+ uint64_t max_end = MAX(prev_host_end, mrs_host + mrs_size);
+ need_add = false;
+ prev_sec->offset_within_address_space =
+ MIN(prev_gpa_start, mrs_gpa);
+ prev_sec->offset_within_region =
+ MIN(prev_host_start, mrs_host) -
+ (uintptr_t)memory_region_get_ram_ptr(prev_sec->mr);
+ prev_sec->size = int128_make64(max_end - MIN(prev_host_start,
+ mrs_host));
+ }
+ }
+ }
+
+ if (need_add) {
+ ++pdev->n_mr_sections;
+ pdev->mr_sections = g_renew(MemoryRegionSection, pdev->mr_sections,
+ pdev->n_mr_sections);
+ pdev->mr_sections[pdev->n_mr_sections - 1] = *section;
+ pdev->mr_sections[pdev->n_mr_sections - 1].fv = NULL;
+ memory_region_ref(section->mr);
+ }
+}
+
+static void proxy_ml_commit(MemoryListener *listener)
+{
+ ProcMsg msg;
+ ram_addr_t offset;
+ MemoryRegion *mr;
+ MemoryRegionSection section;
+ uintptr_t host_addr;
+ int region;
+ struct proxy_device *pdev = container_of(listener, struct proxy_device,
+ memory_listener);
+
+ msg.cmd = SYNC_SYSMEM;
+ msg.bytestream = 0;
+ msg.num_fds = pdev->n_mr_sections;
+ assert(msg.num_fds <= MAX_FDS);
+
+ for (region = 0; region < pdev->n_mr_sections; region++) {
+ section = pdev->mr_sections[region];
+ msg.data1.sync_sysmem.gpas[region] =
+ section.offset_within_address_space;
+ msg.data1.sync_sysmem.sizes[region] = int128_get64(section.size);
+ host_addr = (uintptr_t)memory_region_get_ram_ptr(section.mr) +
+ section.offset_within_region;
+ mr = memory_region_from_host((void *)host_addr, &offset);
+ msg.fds[region] = memory_region_get_fd(mr);
+ }
+ proxy_proc_send(pdev->proxy_link, &msg);
+}
+
+void deconfigure_memory_listener(PCIProxyDev *pdev)
+{
+ memory_listener_unregister(&pdev->proxy_dev.memory_listener);
+}
+
+static MemoryListener proxy_listener = {
+ .begin = proxy_ml_begin,
+ .commit = proxy_ml_commit,
+ .region_add = proxy_ml_region_addnop,
+ .region_nop = proxy_ml_region_addnop,
+ .priority = 10,
+};
+
+void configure_memory_listener(PCIProxyDev *dev)
+{
+ dev->proxy_dev.memory_listener = proxy_listener;
+ dev->proxy_dev.n_mr_sections = 0;
+ dev->proxy_dev.mr_sections = NULL;
+ memory_listener_register(&dev->proxy_dev.memory_listener,
+ &address_space_memory);
+}
diff --git a/hw/scsi/qemu-scsi-dev.c b/hw/scsi/qemu-scsi-dev.c
index ede0c4b..ff34cbc 100644
--- a/hw/scsi/qemu-scsi-dev.c
+++ b/hw/scsi/qemu-scsi-dev.c
@@ -65,6 +65,16 @@ static void process_msg(GIOCondition cond)
break;
case CONF_READ:
break;
+ case SYNC_SYSMEM:
+ /*
+ * TODO: ensure no active DMA is happening when
+ * sysmem is being updated
+ */
+ remote_sysmem_reconfig(msg, &err);
+ if (err) {
+ goto finalize_loop;
+ }
+ break;
default:
error_setg(&err, "Unknown command");
goto finalize_loop;
diff --git a/include/hw/qemu-proxy.h b/include/hw/qemu-proxy.h
index 0903626..867c3ce 100644
--- a/include/hw/qemu-proxy.h
+++ b/include/hw/qemu-proxy.h
@@ -33,6 +33,7 @@ typedef struct proxy_device {
int n_mr_sections;
MemoryRegionSection *mr_sections;
ProxyLinkState *proxy_link;
+ MemoryListener memory_listener;
int link_up;
} proxy_device;
@@ -52,5 +53,7 @@ typedef struct PCIProxyDev {
void init_emulation_process(PCIProxyDev *pdev, char *command, Error **errp);
int config_op_send(PCIProxyDev *dev, uint32_t addr, uint32_t val, int l,
unsigned int op);
+void deconfigure_memory_listener(PCIProxyDev *pdev);
+void configure_memory_listener(PCIProxyDev *pdev);
#endif
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread