diff --git a/emulators/qemu/patches/patch-target_i386_nvmm_nvmm-all.c b/emulators/qemu/patches/patch-target_i386_nvmm_nvmm-all.c index 78c6fff10b1e..fd3a78d7e86c 100644 --- a/emulators/qemu/patches/patch-target_i386_nvmm_nvmm-all.c +++ b/emulators/qemu/patches/patch-target_i386_nvmm_nvmm-all.c @@ -5,9 +5,35 @@ emulators/qemu: Fix NVMM for UEFI (OVMF) * From DragonFly BSD's Redmine's issue 3310 to fix memory error when UEFI boot. ---- target/i386/nvmm/nvmm-all.c.orig 2025-08-26 18:32:38.000000000 +0000 +--- target/i386/nvmm/nvmm-all.c.orig 2025-12-06 15:26:45.000000000 +0000 +++ target/i386/nvmm/nvmm-all.c -@@ -984,7 +984,7 @@ nvmm_init_vcpu(CPUState *cpu) +@@ -24,6 +24,8 @@ + #include "host-cpu.h" + #include "migration/blocker.h" + #include "strings.h" ++#include "qemu/option.h" ++#include "qom/object.h" + + #include "nvmm-accel-ops.h" + +@@ -42,6 +44,16 @@ struct AccelCPUState { + bool int_shadow; + }; + ++typedef struct NVMMState { ++ AccelState parent_obj; ++ ++ bool prefault; ++} NVMMState; ++ ++#define TYPE_NVMM_ACCEL ACCEL_CLASS_NAME("nvmm") ++DECLARE_INSTANCE_CHECKER(NVMMState, NVMM_STATE, ++ TYPE_NVMM_ACCEL) ++ + struct qemu_machine { + struct nvmm_capability cap; + struct nvmm_machine mach; +@@ -985,7 +997,7 @@ nvmm_init_vcpu(CPUState *cpu) } } @@ -16,7 +42,29 @@ emulators/qemu: Fix NVMM for UEFI (OVMF) cpu->accel = qcpu; return 0; -@@ -1059,7 +1059,11 @@ nvmm_process_section(MemoryRegionSection +@@ -1032,13 +1044,21 @@ nvmm_update_mapping(hwaddr start_pa, ram + { + struct nvmm_machine *mach = get_nvmm_mach(); + int ret, prot; ++#ifdef NVMM_HAS_PREFAULT ++ NVMMState *nvmm_state = NVMM_STATE(current_accel()); ++#endif + + if (add) { + prot = PROT_READ | PROT_EXEC; + if (!rom) { + prot |= PROT_WRITE; + } ++#ifdef NVMM_HAS_PREFAULT ++ ret = nvmm_gpa_map_prefault(mach, hva, start_pa, size, ++ prot, nvmm_state->prefault); ++#else + ret = nvmm_gpa_map(mach, hva, start_pa, size, prot); ++#endif + } else { + ret = nvmm_gpa_unmap(mach, hva, start_pa, size); + } +@@ -1060,7 +1080,11 @@ nvmm_process_section(MemoryRegionSection unsigned int delta; uintptr_t hva; @@ -29,3 +77,46 @@ emulators/qemu: Fix NVMM for UEFI (OVMF) return; } +@@ -1196,6 +1220,24 @@ nvmm_accel_init(AccelState *as, MachineS + return 0; + } + ++static bool nvmm_get_prefault(Object *obj, Error **errp) ++{ ++ NVMMState *s = NVMM_STATE(obj); ++ return s->prefault; ++} ++ ++static void nvmm_set_prefault(Object *obj, bool value, Error **errp) ++{ ++ NVMMState *s = NVMM_STATE(obj); ++ s->prefault = value; ++} ++ ++static void nvmm_accel_instance_init(Object *obj) ++{ ++ NVMMState *s = NVMM_STATE(obj); ++ s->prefault = false; ++} ++ + static void + nvmm_accel_class_init(ObjectClass *oc, const void *data) + { +@@ -1203,11 +1245,16 @@ nvmm_accel_class_init(ObjectClass *oc, c + ac->name = "NVMM"; + ac->init_machine = nvmm_accel_init; + ac->allowed = &nvmm_allowed; ++ ++ object_class_property_add_bool(oc, "prefault", ++ nvmm_get_prefault, nvmm_set_prefault); + } + + static const TypeInfo nvmm_accel_type = { +- .name = ACCEL_CLASS_NAME("nvmm"), ++ .name = TYPE_NVMM_ACCEL, + .parent = TYPE_ACCEL, ++ .instance_size = sizeof(NVMMState), ++ .instance_init = nvmm_accel_instance_init, + .class_init = nvmm_accel_class_init, + }; + diff --git a/lib/libnvmm/libnvmm.c b/lib/libnvmm/libnvmm.c index 11fbfab79a26..657e022ed585 100644 --- a/lib/libnvmm/libnvmm.c +++ b/lib/libnvmm/libnvmm.c @@ -431,9 +431,9 @@ nvmm_vcpu_run(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) return 0; } -int -nvmm_gpa_map(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa, - size_t size, int prot) +static int +nvmm_gpa_map_private(struct nvmm_machine *mach, uintptr_t hva, + gpaddr_t gpa, size_t size, int prot, bool prefault) { struct nvmm_ioc_gpa_map args; int ret; @@ -447,6 +447,9 @@ nvmm_gpa_map(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa, args.gpa = gpa; args.size = size; args.prot = prot; +#ifdef NVMM_HAS_PREFAULT + args.prefault = prefault; +#endif ret = ioctl(nvmm_fd, NVMM_IOC_GPA_MAP, &args); if (ret == -1) { @@ -457,6 +460,20 @@ nvmm_gpa_map(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa, return 0; } +int +nvmm_gpa_map(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa, + size_t size, int prot) +{ + return nvmm_gpa_map_private(mach, hva, gpa, size, prot, false); +} + +int +nvmm_gpa_map_prefault(struct nvmm_machine *mach, uintptr_t hva, + gpaddr_t gpa, size_t size, int prot, bool prefault) +{ + return nvmm_gpa_map_private(mach, hva, gpa, size, prot, prefault); +} + int nvmm_gpa_unmap(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa, size_t size) diff --git a/lib/libnvmm/nvmm.h b/lib/libnvmm/nvmm.h index fc258d2867dd..a8b1f5167892 100644 --- a/lib/libnvmm/nvmm.h +++ b/lib/libnvmm/nvmm.h @@ -113,6 +113,8 @@ int nvmm_vcpu_inject(struct nvmm_machine *, struct nvmm_vcpu *); int nvmm_vcpu_run(struct nvmm_machine *, struct nvmm_vcpu *); int nvmm_gpa_map(struct nvmm_machine *, uintptr_t, gpaddr_t, size_t, int); +int nvmm_gpa_map_prefault(struct nvmm_machine *, uintptr_t, gpaddr_t, size_t, + int, bool); int nvmm_gpa_unmap(struct nvmm_machine *, uintptr_t, gpaddr_t, size_t); int nvmm_hva_map(struct nvmm_machine *, uintptr_t, size_t); int nvmm_hva_unmap(struct nvmm_machine *, uintptr_t, size_t); diff --git a/lib/libnvmm/nvmm.x86_64.expsym b/lib/libnvmm/nvmm.x86_64.expsym index bfb9721bbe4e..ca52478d2ed4 100644 --- a/lib/libnvmm/nvmm.x86_64.expsym +++ b/lib/libnvmm/nvmm.x86_64.expsym @@ -3,6 +3,7 @@ nvmm_assist_mem nvmm_capability nvmm_ctl nvmm_gpa_map +nvmm_gpa_map_prefault nvmm_gpa_to_hva nvmm_gpa_unmap nvmm_gva_to_gpa diff --git a/sys/dev/nvmm/nvmm.c b/sys/dev/nvmm/nvmm.c index 80931acfc50f..3c03189e51d1 100644 --- a/sys/dev/nvmm/nvmm.c +++ b/sys/dev/nvmm/nvmm.c @@ -913,6 +913,12 @@ nvmm_gpa_map(struct nvmm_owner *owner, struct nvmm_ioc_gpa_map *args) goto out; } +#ifdef NVMM_HAS_PREFAULT + if (args->prefault && uvm_map_pageable(&mach->vm->vm_map, + gpa, gpa + args->size, false, 0) == 0) + error = uvm_map_pageable(&mach->vm->vm_map, + gpa, gpa + args->size, true, 0); +#endif out: nvmm_machine_put(mach); return error; diff --git a/sys/dev/nvmm/nvmm.h b/sys/dev/nvmm/nvmm.h index e75931b3369d..9c962509d5f2 100644 --- a/sys/dev/nvmm/nvmm.h +++ b/sys/dev/nvmm/nvmm.h @@ -48,6 +48,7 @@ typedef uint32_t nvmm_cpuid_t; #endif #define NVMM_KERN_VERSION 2 +#define NVMM_HAS_PREFAULT 1 /* * Version 1 - Initial release in NetBSD 9.0. diff --git a/sys/dev/nvmm/nvmm_ioctl.h b/sys/dev/nvmm/nvmm_ioctl.h index 749549ab0f5f..b51ec967b67d 100644 --- a/sys/dev/nvmm/nvmm_ioctl.h +++ b/sys/dev/nvmm/nvmm_ioctl.h @@ -112,6 +112,9 @@ struct nvmm_ioc_gpa_map { gpaddr_t gpa; size_t size; int prot; +#ifdef NVMM_HAS_PREFAULT + bool prefault; +#endif }; struct nvmm_ioc_gpa_unmap {