From a9a2a60a37e3c6921b46c26c7fc00ae63e66a116 Mon Sep 17 00:00:00 2001 From: Ryo Shimizu Date: Fri, 17 Mar 2023 07:54:11 +0900 Subject: [PATCH 03/13] Split target/i386/nvmm/nvmm.c into accel/nvmm/nvmm-all.c for the common part and target/i386/nvmm/nvmm.c for the machine dependent part. --- accel/nvmm/meson.build | 1 + accel/nvmm/nvmm-all.c | 384 ++++++++++++++++++++++++++++++++++++++++ include/system/nvmm.h | 21 ++- target/i386/nvmm/nvmm.c | 343 +---------------------------------- 4 files changed, 411 insertions(+), 338 deletions(-) create mode 100644 accel/nvmm/nvmm-all.c diff --git a/accel/nvmm/meson.build b/accel/nvmm/meson.build index 0308ab1e3f..ca67f7d54b 100644 --- a/accel/nvmm/meson.build +++ b/accel/nvmm/meson.build @@ -1,6 +1,7 @@ nvmm_ss = ss.source_set() nvmm_ss.add(files( 'nvmm-accel-ops.c', + 'nvmm-all.c', )) specific_ss.add_all(when: 'CONFIG_NVMM', if_true: nvmm_ss) diff --git a/accel/nvmm/nvmm-all.c b/accel/nvmm/nvmm-all.c new file mode 100644 index 0000000000..315029ff31 --- /dev/null +++ b/accel/nvmm/nvmm-all.c @@ -0,0 +1,384 @@ +/* + * Copyright (c) 2018-2019 Maxime Villard, All rights reserved. + * + * NetBSD Virtual Machine Monitor (NVMM) accelerator for QEMU. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/address-spaces.h" +#include "exec/ioport.h" +#include "qemu/accel.h" +#include "sysemu/nvmm.h" + +#include + +struct qemu_machine { + struct nvmm_capability cap; + struct nvmm_machine mach; +}; + +/* -------------------------------------------------------------------------- */ + +static bool nvmm_allowed; +static struct qemu_machine qemu_mach; + +static struct nvmm_machine * +get_nvmm_mach(void) +{ + return &qemu_mach.mach; +} + +struct nvmm_capability * +get_nvmm_cap(void) +{ + return &qemu_mach.cap; +} + +/* -------------------------------------------------------------------------- */ + +#ifdef NVMM_VCPU_EXIT_IO +static void +nvmm_io_callback(struct nvmm_io *io) +{ + MemTxAttrs attrs = { 0 }; + int ret; + + ret = address_space_rw(&address_space_io, io->port, attrs, io->data, + io->size, !io->in); + if (ret != MEMTX_OK) { + error_report("NVMM: I/O Transaction Failed " + "[%s, port=%u, size=%zu]", (io->in ? "in" : "out"), + io->port, io->size); + } + + /* Needed, otherwise infinite loop. */ + current_cpu->vcpu_dirty = false; +} +#endif /* NVMM_VCPU_EXIT_IO */ + +static void +nvmm_mem_callback(struct nvmm_mem *mem) +{ + cpu_physical_memory_rw(mem->gpa, mem->data, mem->size, mem->write); + + /* Needed, otherwise infinite loop. */ + current_cpu->vcpu_dirty = false; +} + +struct nvmm_assist_callbacks nvmm_callbacks = { +#ifdef NVMM_VCPU_EXIT_IO + .io = nvmm_io_callback, +#endif + .mem = nvmm_mem_callback +}; + +/* -------------------------------------------------------------------------- */ + +int +nvmm_handle_mem(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) +{ + int ret; + + ret = nvmm_assist_mem(mach, vcpu); + if (ret == -1) { + error_report("NVMM: Mem Assist Failed [gpa=%p]", + (void *)vcpu->exit->u.mem.gpa); + } + + return ret; +} + +#ifdef NVMM_VCPU_EXIT_IO +int +nvmm_handle_io(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) +{ + int ret; + + ret = nvmm_assist_io(mach, vcpu); + if (ret == -1) { + error_report("NVMM: I/O Assist Failed [port=%d]", + (int)vcpu->exit->u.io.port); + } + + return ret; +} +#endif + +/* -------------------------------------------------------------------------- */ + +static void +do_nvmm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) +{ + nvmm_get_registers(cpu); + cpu->vcpu_dirty = true; +} + +static void +do_nvmm_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg) +{ + nvmm_set_registers(cpu); + cpu->vcpu_dirty = false; +} + +static void +do_nvmm_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg) +{ + nvmm_set_registers(cpu); + cpu->vcpu_dirty = false; +} + +static void +do_nvmm_cpu_synchronize_pre_loadvm(CPUState *cpu, run_on_cpu_data arg) +{ + cpu->vcpu_dirty = true; +} + +void nvmm_cpu_synchronize_state(CPUState *cpu) +{ + if (!cpu->vcpu_dirty) { + run_on_cpu(cpu, do_nvmm_cpu_synchronize_state, RUN_ON_CPU_NULL); + } +} + +void nvmm_cpu_synchronize_post_reset(CPUState *cpu) +{ + run_on_cpu(cpu, do_nvmm_cpu_synchronize_post_reset, RUN_ON_CPU_NULL); +} + +void nvmm_cpu_synchronize_post_init(CPUState *cpu) +{ + run_on_cpu(cpu, do_nvmm_cpu_synchronize_post_init, RUN_ON_CPU_NULL); +} + +void nvmm_cpu_synchronize_pre_loadvm(CPUState *cpu) +{ + run_on_cpu(cpu, do_nvmm_cpu_synchronize_pre_loadvm, RUN_ON_CPU_NULL); +} + +/* -------------------------------------------------------------------------- */ + +int +nvmm_vcpu_exec(CPUState *cpu) +{ + int ret, fatal; + + while (1) { + if (cpu->exception_index >= EXCP_INTERRUPT) { + ret = cpu->exception_index; + cpu->exception_index = -1; + break; + } + + fatal = nvmm_vcpu_loop(cpu); + + if (fatal) { + error_report("NVMM: Failed to execute a VCPU."); + abort(); + } + } + + return ret; +} + +static void +nvmm_update_mapping(hwaddr start_pa, ram_addr_t size, uintptr_t hva, + bool add, bool rom, const char *name) +{ + struct nvmm_machine *mach = get_nvmm_mach(); + int ret, prot; + + if (add) { + prot = PROT_READ | PROT_EXEC; + if (!rom) { + prot |= PROT_WRITE; + } + ret = nvmm_gpa_map(mach, hva, start_pa, size, prot); + } else { + ret = nvmm_gpa_unmap(mach, hva, start_pa, size); + } + + if (ret == -1) { + error_report("NVMM: Failed to %s GPA range '%s' PA:%p, " + "Size:%p bytes, HostVA:%p, error=%d", + (add ? "map" : "unmap"), name, (void *)(uintptr_t)start_pa, + (void *)size, (void *)hva, errno); + } +} + +static void +nvmm_process_section(MemoryRegionSection *section, int add) +{ + MemoryRegion *mr = section->mr; + hwaddr start_pa = section->offset_within_address_space; + ram_addr_t size = int128_get64(section->size); + unsigned int delta; + uintptr_t hva; + + if (!memory_region_is_ram(mr)) { + return; + } + + /* Adjust start_pa and size so that they are page-aligned. */ + delta = qemu_real_host_page_size() - (start_pa & ~qemu_real_host_page_mask()); + delta &= ~qemu_real_host_page_mask(); + if (delta > size) { + return; + } + start_pa += delta; + size -= delta; + size &= qemu_real_host_page_mask(); + if (!size || (start_pa & ~qemu_real_host_page_mask())) { + return; + } + + hva = (uintptr_t)memory_region_get_ram_ptr(mr) + + section->offset_within_region + delta; + + nvmm_update_mapping(start_pa, size, hva, add, + memory_region_is_rom(mr), mr->name); +} + +static void +nvmm_region_add(MemoryListener *listener, MemoryRegionSection *section) +{ + memory_region_ref(section->mr); + nvmm_process_section(section, 1); +} + +static void +nvmm_region_del(MemoryListener *listener, MemoryRegionSection *section) +{ + nvmm_process_section(section, 0); + memory_region_unref(section->mr); +} + +static void +nvmm_transaction_begin(MemoryListener *listener) +{ + /* nothing */ +} + +static void +nvmm_transaction_commit(MemoryListener *listener) +{ + /* nothing */ +} + +static void +nvmm_log_sync(MemoryListener *listener, MemoryRegionSection *section) +{ + MemoryRegion *mr = section->mr; + + if (!memory_region_is_ram(mr)) { + return; + } + + memory_region_set_dirty(mr, 0, int128_get64(section->size)); +} + +static MemoryListener nvmm_memory_listener = { + .name = "nvmm", + .begin = nvmm_transaction_begin, + .commit = nvmm_transaction_commit, + .region_add = nvmm_region_add, + .region_del = nvmm_region_del, + .log_sync = nvmm_log_sync, + .priority = MEMORY_LISTENER_PRIORITY_ACCEL +}; + +static void +nvmm_ram_block_added(RAMBlockNotifier *n, void *host, size_t size, + size_t max_size) +{ + struct nvmm_machine *mach = get_nvmm_mach(); + uintptr_t hva = (uintptr_t)host; + int ret; + + ret = nvmm_hva_map(mach, hva, max_size); + + if (ret == -1) { + error_report("NVMM: Failed to map HVA, HostVA:%p " + "Size:%p bytes, error=%d", + (void *)hva, (void *)size, errno); + } +} + +static struct RAMBlockNotifier nvmm_ram_notifier = { + .ram_block_added = nvmm_ram_block_added +}; + +/* -------------------------------------------------------------------------- */ + +static int +nvmm_accel_init(MachineState *ms) +{ + int ret, err; + + ret = nvmm_init(); + if (ret == -1) { + err = errno; + error_report("NVMM: Initialization failed, error=%d", errno); + return -err; + } + + ret = nvmm_capability(&qemu_mach.cap); + if (ret == -1) { + err = errno; + error_report("NVMM: Unable to fetch capability, error=%d", errno); + return -err; + } + if (qemu_mach.cap.version < NVMM_KERN_VERSION) { + error_report("NVMM: Unsupported version %u", qemu_mach.cap.version); + return -EPROGMISMATCH; + } + if (qemu_mach.cap.state_size != sizeof(struct nvmm_vcpu_state)) { + error_report("NVMM: Wrong state size %u", qemu_mach.cap.state_size); + return -EPROGMISMATCH; + } + + ret = nvmm_machine_create(&qemu_mach.mach); + if (ret == -1) { + err = errno; + error_report("NVMM: Machine creation failed, error=%d", errno); + return -err; + } + + memory_listener_register(&nvmm_memory_listener, &address_space_memory); + ram_block_notifier_add(&nvmm_ram_notifier); + + printf("NetBSD Virtual Machine Monitor accelerator is operational\n"); + return 0; +} + +int +nvmm_enabled(void) +{ + return nvmm_allowed; +} + +static void +nvmm_accel_class_init(ObjectClass *oc, void *data) +{ + AccelClass *ac = ACCEL_CLASS(oc); + ac->name = "NVMM"; + ac->init_machine = nvmm_accel_init; + ac->allowed = &nvmm_allowed; +} + +static const TypeInfo nvmm_accel_type = { + .name = ACCEL_CLASS_NAME("nvmm"), + .parent = TYPE_ACCEL, + .class_init = nvmm_accel_class_init, +}; + +static void +nvmm_type_init(void) +{ + type_register_static(&nvmm_accel_type); +} + +type_init(nvmm_type_init); diff --git a/include/system/nvmm.h b/include/system/nvmm.h index 39d06957a5..5ecff76cba 100644 --- a/include/system/nvmm.h +++ b/include/system/nvmm.h @@ -12,6 +12,8 @@ #ifndef QEMU_NVMM_H #define QEMU_NVMM_H +#include + #ifdef COMPILING_PER_TARGET # ifdef CONFIG_NVMM # define CONFIG_NVMM_IS_POSSIBLE @@ -20,14 +22,27 @@ # define CONFIG_NVMM_IS_POSSIBLE #endif /* COMPILING_PER_TARGET */ -int nvmm_init_vcpu(CPUState *cpu); +/* MI: accel/nvmm/nvmm-all.c */ +struct nvmm_machine *get_nvmm_mach(void); +struct nvmm_capability *get_nvmm_cap(void); int nvmm_vcpu_exec(CPUState *cpu); -void nvmm_destroy_vcpu(CPUState *cpu); - void nvmm_cpu_synchronize_state(CPUState *cpu); void nvmm_cpu_synchronize_post_reset(CPUState *cpu); void nvmm_cpu_synchronize_post_init(CPUState *cpu); void nvmm_cpu_synchronize_pre_loadvm(CPUState *cpu); +int nvmm_handle_mem(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu); +int nvmm_handle_io(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu); +void nvmm_ipi_signal(int sigcpu); +void nvmm_init_cpu_signals(void); + +extern struct nvmm_assist_callbacks nvmm_callbacks; + +/* MD: target//nvmm/nvmm.c */ +int nvmm_init_vcpu(CPUState *cpu); +void nvmm_destroy_vcpu(CPUState *cpu); +void nvmm_get_registers(CPUState *cpu); +void nvmm_set_registers(CPUState *cpu); +int nvmm_vcpu_loop(CPUState *cpu); #ifdef CONFIG_NVMM_IS_POSSIBLE extern bool nvmm_allowed; diff --git a/target/i386/nvmm/nvmm.c b/target/i386/nvmm/nvmm.c index 824fa94d60..26ab2f1371 100644 --- a/target/i386/nvmm/nvmm.c +++ b/target/i386/nvmm/nvmm.c @@ -26,8 +26,6 @@ #include "migration/blocker.h" #include "strings.h" -#include - struct AccelCPUState { struct nvmm_vcpu vcpu; uint8_t tpr; @@ -41,22 +39,6 @@ struct AccelCPUState { bool int_shadow; }; -struct qemu_machine { - struct nvmm_capability cap; - struct nvmm_machine mach; -}; - -/* -------------------------------------------------------------------------- */ - -bool nvmm_allowed; -static struct qemu_machine qemu_mach; - -static struct nvmm_machine * -get_nvmm_mach(void) -{ - return &qemu_mach.mach; -} - /* -------------------------------------------------------------------------- */ static void @@ -77,7 +59,7 @@ nvmm_set_segment(struct nvmm_x64_state_seg *nseg, const SegmentCache *qseg) nseg->attrib.g = __SHIFTOUT(attrib, DESC_G_MASK); } -static void +void nvmm_set_registers(CPUState *cpu) { CPUX86State *env = cpu_env(cpu); @@ -214,7 +196,7 @@ nvmm_get_segment(SegmentCache *qseg, const struct nvmm_x64_state_seg *nseg) __SHIFTIN((uint32_t)nseg->attrib.g, DESC_G_MASK); } -static void +void nvmm_get_registers(CPUState *cpu) { CPUX86State *env = cpu_env(cpu); @@ -494,70 +476,6 @@ nvmm_vcpu_post_run(CPUState *cpu, struct nvmm_vcpu_exit *exit) /* -------------------------------------------------------------------------- */ -static void -nvmm_io_callback(struct nvmm_io *io) -{ - MemTxAttrs attrs = { 0 }; - int ret; - - ret = address_space_rw(&address_space_io, io->port, attrs, io->data, - io->size, !io->in); - if (ret != MEMTX_OK) { - error_report("NVMM: I/O Transaction Failed " - "[%s, port=%u, size=%zu]", (io->in ? "in" : "out"), - io->port, io->size); - } - - /* Needed, otherwise infinite loop. */ - current_cpu->vcpu_dirty = false; -} - -static void -nvmm_mem_callback(struct nvmm_mem *mem) -{ - /* TODO: Get CPUState via mem->vcpu? */ - address_space_rw(&address_space_memory, mem->gpa, MEMTXATTRS_UNSPECIFIED, - mem->data, mem->size, mem->write); - - /* Needed, otherwise infinite loop. */ - current_cpu->vcpu_dirty = false; -} - -static struct nvmm_assist_callbacks nvmm_callbacks = { - .io = nvmm_io_callback, - .mem = nvmm_mem_callback -}; - -/* -------------------------------------------------------------------------- */ - -static int -nvmm_handle_mem(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) -{ - int ret; - - ret = nvmm_assist_mem(mach, vcpu); - if (ret == -1) { - error_report("NVMM: Mem Assist Failed [gpa=%p]", - (void *)vcpu->exit->u.mem.gpa); - } - - return ret; -} - -static int -nvmm_handle_io(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) -{ - int ret; - - ret = nvmm_assist_io(mach, vcpu); - if (ret == -1) { - error_report("NVMM: I/O Assist Failed [port=%d]", - (int)vcpu->exit->u.io.port); - } - - return ret; -} - static int nvmm_handle_rdmsr(struct nvmm_machine *mach, CPUState *cpu, struct nvmm_vcpu_exit *exit) @@ -677,7 +595,7 @@ nvmm_inject_ud(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) return nvmm_vcpu_inject(mach, vcpu); } -static int +int nvmm_vcpu_loop(CPUState *cpu) { struct nvmm_machine *mach = get_nvmm_mach(); @@ -824,57 +742,6 @@ nvmm_vcpu_loop(CPUState *cpu) /* -------------------------------------------------------------------------- */ -static void -do_nvmm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) -{ - nvmm_get_registers(cpu); - cpu->vcpu_dirty = true; -} - -static void -do_nvmm_cpu_synchronize_post_reset(CPUState *cpu, run_on_cpu_data arg) -{ - nvmm_set_registers(cpu); - cpu->vcpu_dirty = false; -} - -static void -do_nvmm_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg) -{ - nvmm_set_registers(cpu); - cpu->vcpu_dirty = false; -} - -static void -do_nvmm_cpu_synchronize_pre_loadvm(CPUState *cpu, run_on_cpu_data arg) -{ - cpu->vcpu_dirty = true; -} - -void nvmm_cpu_synchronize_state(CPUState *cpu) -{ - if (!cpu->vcpu_dirty) { - run_on_cpu(cpu, do_nvmm_cpu_synchronize_state, RUN_ON_CPU_NULL); - } -} - -void nvmm_cpu_synchronize_post_reset(CPUState *cpu) -{ - run_on_cpu(cpu, do_nvmm_cpu_synchronize_post_reset, RUN_ON_CPU_NULL); -} - -void nvmm_cpu_synchronize_post_init(CPUState *cpu) -{ - run_on_cpu(cpu, do_nvmm_cpu_synchronize_post_init, RUN_ON_CPU_NULL); -} - -void nvmm_cpu_synchronize_pre_loadvm(CPUState *cpu) -{ - run_on_cpu(cpu, do_nvmm_cpu_synchronize_pre_loadvm, RUN_ON_CPU_NULL); -} - -/* -------------------------------------------------------------------------- */ - static Error *nvmm_migration_blocker; /* @@ -882,11 +749,11 @@ static Error *nvmm_migration_blocker; * and another thread signaling the vCPU thread to exit. */ -static void +void nvmm_ipi_signal(int sigcpu) { if (current_cpu) { - AccelCPUState *qcpu = current_cpu->accel; + AccelCPUState *qcpu = get_qemu_vcpu(current_cpu); #if NVMM_USER_VERSION >= 2 struct nvmm_vcpu *vcpu = &qcpu->vcpu; nvmm_vcpu_stop(vcpu); @@ -896,7 +763,7 @@ nvmm_ipi_signal(int sigcpu) } } -static void +void nvmm_init_cpu_signals(void) { struct sigaction sigact; @@ -917,6 +784,7 @@ int nvmm_init_vcpu(CPUState *cpu) { struct nvmm_machine *mach = get_nvmm_mach(); + struct nvmm_capability *cap = get_nvmm_cap(); struct nvmm_vcpu_conf_cpuid cpuid; struct nvmm_vcpu_conf_tpr tpr; Error *local_error = NULL; @@ -970,7 +838,7 @@ nvmm_init_vcpu(CPUState *cpu) return -err; } - if (qemu_mach.cap.arch.vcpu_conf_support & NVMM_CAP_ARCH_VCPU_CONF_TPR) { + if (cap->arch.vcpu_conf_support & NVMM_CAP_ARCH_VCPU_CONF_TPR) { memset(&tpr, 0, sizeof(tpr)); tpr.exit_changed = 1; ret = nvmm_vcpu_configure(mach, &qcpu->vcpu, NVMM_VCPU_CONF_TPR, &tpr); @@ -989,29 +857,6 @@ nvmm_init_vcpu(CPUState *cpu) return 0; } -int -nvmm_vcpu_exec(CPUState *cpu) -{ - int ret, fatal; - - while (1) { - if (cpu->exception_index >= EXCP_INTERRUPT) { - ret = cpu->exception_index; - cpu->exception_index = -1; - break; - } - - fatal = nvmm_vcpu_loop(cpu); - - if (fatal) { - error_report("NVMM: Failed to execute a VCPU."); - abort(); - } - } - - return ret; -} - void nvmm_destroy_vcpu(CPUState *cpu) { @@ -1022,178 +867,6 @@ nvmm_destroy_vcpu(CPUState *cpu) g_free(cpu->accel); } -/* -------------------------------------------------------------------------- */ - -static void -nvmm_update_mapping(hwaddr start_pa, ram_addr_t size, uintptr_t hva, - bool add, bool rom, const char *name) -{ - struct nvmm_machine *mach = get_nvmm_mach(); - int ret, prot; - - if (add) { - prot = PROT_READ | PROT_EXEC; - if (!rom) { - prot |= PROT_WRITE; - } - ret = nvmm_gpa_map(mach, hva, start_pa, size, prot); - } else { - ret = nvmm_gpa_unmap(mach, hva, start_pa, size); - } - - if (ret == -1) { - error_report("NVMM: Failed to %s GPA range '%s' PA:%p, " - "Size:%p bytes, HostVA:%p, error=%d", - (add ? "map" : "unmap"), name, (void *)(uintptr_t)start_pa, - (void *)size, (void *)hva, errno); - } -} - -static void -nvmm_process_section(MemoryRegionSection *section, int add) -{ - MemoryRegion *mr = section->mr; - hwaddr start_pa = section->offset_within_address_space; - ram_addr_t size = int128_get64(section->size); - unsigned int delta; - uintptr_t hva; - - if (!memory_region_is_ram(mr)) { - return; - } - - /* Adjust start_pa and size so that they are page-aligned. */ - delta = qemu_real_host_page_size() - (start_pa & ~qemu_real_host_page_mask()); - delta &= ~qemu_real_host_page_mask(); - if (delta > size) { - return; - } - start_pa += delta; - size -= delta; - size &= qemu_real_host_page_mask(); - if (!size || (start_pa & ~qemu_real_host_page_mask())) { - return; - } - - hva = (uintptr_t)memory_region_get_ram_ptr(mr) + - section->offset_within_region + delta; - - nvmm_update_mapping(start_pa, size, hva, add, - memory_region_is_rom(mr), mr->name); -} - -static void -nvmm_region_add(MemoryListener *listener, MemoryRegionSection *section) -{ - memory_region_ref(section->mr); - nvmm_process_section(section, 1); -} - -static void -nvmm_region_del(MemoryListener *listener, MemoryRegionSection *section) -{ - nvmm_process_section(section, 0); - memory_region_unref(section->mr); -} - -static void -nvmm_transaction_begin(MemoryListener *listener) -{ - /* nothing */ -} - -static void -nvmm_transaction_commit(MemoryListener *listener) -{ - /* nothing */ -} - -static void -nvmm_log_sync(MemoryListener *listener, MemoryRegionSection *section) -{ - MemoryRegion *mr = section->mr; - - if (!memory_region_is_ram(mr)) { - return; - } - - memory_region_set_dirty(mr, 0, int128_get64(section->size)); -} - -static MemoryListener nvmm_memory_listener = { - .name = "nvmm", - .begin = nvmm_transaction_begin, - .commit = nvmm_transaction_commit, - .region_add = nvmm_region_add, - .region_del = nvmm_region_del, - .log_sync = nvmm_log_sync, - .priority = MEMORY_LISTENER_PRIORITY_ACCEL, -}; - -static void -nvmm_ram_block_added(RAMBlockNotifier *n, void *host, size_t size, - size_t max_size) -{ - struct nvmm_machine *mach = get_nvmm_mach(); - uintptr_t hva = (uintptr_t)host; - int ret; - - ret = nvmm_hva_map(mach, hva, max_size); - - if (ret == -1) { - error_report("NVMM: Failed to map HVA, HostVA:%p " - "Size:%p bytes, error=%d", - (void *)hva, (void *)size, errno); - } -} - -static struct RAMBlockNotifier nvmm_ram_notifier = { - .ram_block_added = nvmm_ram_block_added -}; - -/* -------------------------------------------------------------------------- */ - -static int -nvmm_accel_init(AccelState *as, MachineState *ms) -{ - int ret, err; - - ret = nvmm_init(); - if (ret == -1) { - err = errno; - error_report("NVMM: Initialization failed, error=%d", errno); - return -err; - } - - ret = nvmm_capability(&qemu_mach.cap); - if (ret == -1) { - err = errno; - error_report("NVMM: Unable to fetch capability, error=%d", errno); - return -err; - } - if (qemu_mach.cap.version < NVMM_KERN_VERSION) { - error_report("NVMM: Unsupported version %u", qemu_mach.cap.version); - return -EPROGMISMATCH; - } - if (qemu_mach.cap.state_size != sizeof(struct nvmm_x64_state)) { - error_report("NVMM: Wrong state size %u", qemu_mach.cap.state_size); - return -EPROGMISMATCH; - } - - ret = nvmm_machine_create(&qemu_mach.mach); - if (ret == -1) { - err = errno; - error_report("NVMM: Machine creation failed, error=%d", errno); - return -err; - } - - memory_listener_register(&nvmm_memory_listener, &address_space_memory); - ram_block_notifier_add(&nvmm_ram_notifier); - - printf("NetBSD Virtual Machine Monitor accelerator is operational\n"); - return 0; -} - static void nvmm_accel_class_init(ObjectClass *oc, const void *data) { -- 2.54.0 (Apple Git-157)