* Mon Jun 08 2026 Jon Maloy <jmaloy@redhat.com> - 10.1.0-21
- kvm-scsi-adjust-error_prepend-formatting.patch [RHEL-158243] - kvm-scsi-always-send-valid-PREEMPT-TYPE-field.patch [RHEL-158243] - kvm-scsi-register-again-after-PREEMPT-without-reservatio.patch [RHEL-158243] - kvm-accel-mshv-Remove-remap-overlapping-mappings-code.patch [RHEL-177969] - kvm-accel-mshv-implement-cpu_thread_is_idle-hook.patch [RHEL-177969] - Resolves: RHEL-158243 (live migration failed the VM just register key only [rhel-9.9]) - Resolves: RHEL-177969 (MSHV backport onto QEMU 10.1.0 is not able to launch MSHV guests)
This commit is contained in:
parent
594e611186
commit
8d37b1bdba
690
kvm-accel-mshv-Remove-remap-overlapping-mappings-code.patch
Normal file
690
kvm-accel-mshv-Remove-remap-overlapping-mappings-code.patch
Normal file
@ -0,0 +1,690 @@
|
||||
From f46de1630eddac4328b462070613235aca5e1149 Mon Sep 17 00:00:00 2001
|
||||
From: Magnus Kulke <magnuskulke@linux.microsoft.com>
|
||||
Date: Tue, 13 Jan 2026 16:37:08 +0100
|
||||
Subject: [PATCH 4/5] accel/mshv: Remove remap overlapping mappings code
|
||||
|
||||
RH-Author: Magnus Kulke <None>
|
||||
RH-MergeRequest: 491: accel/mshv: backport required patches for mshv guests
|
||||
RH-Jira: RHEL-177969
|
||||
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-Commit: [1/2] 78f5dc7530c84062f799cdc286f6cbb97b50b105 (mkulke/qemu-kvm)
|
||||
|
||||
This change removes userland code that worked around a restriction
|
||||
in the mshv driver in the 6.18 kernel: regions from userland
|
||||
couldn't be mapped to multiple regions in the kernel. We maintained a
|
||||
shadow mapping table in qemu and used a heuristic to swap in a requested
|
||||
region in case of UNMAPPED_GPA exits.
|
||||
|
||||
However, this heuristic wasn't reliable in all cases, since HyperV
|
||||
behaviour is not 100% reliable across versions. HyperV itself doesn't
|
||||
prohibit to map regions at multiple places into the guest, so the
|
||||
restriction has been removed in the mshv driver.
|
||||
|
||||
Hence we can remove the remapping code. Effectively this will mandate a
|
||||
6.19 kernel, if the workload attempt to map e.g. BIOS to multiple
|
||||
reagions. I still think it's the right call to remove this logic:
|
||||
|
||||
- The workaround only seems to work reliably with a certain revision
|
||||
of HyperV as a nested hypervisor.
|
||||
- We expect Direct Virtualization (L1VH) to be the main platform for
|
||||
the mshv accelerator, which also requires a 6.19 kernel
|
||||
|
||||
This reverts commit efc4093358511a58846a409b965213aa1bb9f31a.
|
||||
|
||||
Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
|
||||
Acked-by: Wei Liu (Microsoft) <wei.liu@kernel.org>
|
||||
Tested-by: Mohamed Mediouni <mohamed@unpredictable.fr>
|
||||
Link: https://lore.kernel.org/r/20260113153708.448968-1-magnuskulke@linux.microsoft.com
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
(cherry picked from commit 626e5dc999353d2c4a89febd46301bfec6daa3a7)
|
||||
---
|
||||
accel/mshv/mem.c | 406 +++---------------------------------
|
||||
accel/mshv/mshv-all.c | 2 -
|
||||
accel/mshv/trace-events | 5 -
|
||||
include/system/mshv_int.h | 22 +-
|
||||
target/i386/mshv/mshv-cpu.c | 43 ----
|
||||
5 files changed, 30 insertions(+), 448 deletions(-)
|
||||
|
||||
diff --git a/accel/mshv/mem.c b/accel/mshv/mem.c
|
||||
index 0e2164af3e..e55c38d4db 100644
|
||||
--- a/accel/mshv/mem.c
|
||||
+++ b/accel/mshv/mem.c
|
||||
@@ -11,9 +11,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
-#include "qemu/lockable.h"
|
||||
#include "qemu/error-report.h"
|
||||
-#include "qemu/rcu.h"
|
||||
#include "linux/mshv.h"
|
||||
#include "system/address-spaces.h"
|
||||
#include "system/mshv.h"
|
||||
@@ -22,137 +20,6 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include "trace.h"
|
||||
|
||||
-typedef struct SlotsRCUReclaim {
|
||||
- struct rcu_head rcu;
|
||||
- GList *old_head;
|
||||
- MshvMemorySlot *removed_slot;
|
||||
-} SlotsRCUReclaim;
|
||||
-
|
||||
-static void rcu_reclaim_slotlist(struct rcu_head *rcu)
|
||||
-{
|
||||
- SlotsRCUReclaim *r = container_of(rcu, SlotsRCUReclaim, rcu);
|
||||
- g_list_free(r->old_head);
|
||||
- g_free(r->removed_slot);
|
||||
- g_free(r);
|
||||
-}
|
||||
-
|
||||
-static void publish_slots(GList *new_head, GList *old_head,
|
||||
- MshvMemorySlot *removed_slot)
|
||||
-{
|
||||
- MshvMemorySlotManager *manager = &mshv_state->msm;
|
||||
-
|
||||
- assert(manager);
|
||||
- qatomic_store_release(&manager->slots, new_head);
|
||||
-
|
||||
- SlotsRCUReclaim *r = g_new(SlotsRCUReclaim, 1);
|
||||
- r->old_head = old_head;
|
||||
- r->removed_slot = removed_slot;
|
||||
-
|
||||
- call_rcu1(&r->rcu, rcu_reclaim_slotlist);
|
||||
-}
|
||||
-
|
||||
-/* Needs to be called with mshv_state->msm.mutex held */
|
||||
-static int remove_slot(MshvMemorySlot *slot)
|
||||
-{
|
||||
- GList *old_head, *new_head;
|
||||
- MshvMemorySlotManager *manager = &mshv_state->msm;
|
||||
-
|
||||
- assert(manager);
|
||||
- old_head = qatomic_load_acquire(&manager->slots);
|
||||
-
|
||||
- if (!g_list_find(old_head, slot)) {
|
||||
- error_report("slot requested for removal not found");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- new_head = g_list_copy(old_head);
|
||||
- new_head = g_list_remove(new_head, slot);
|
||||
- manager->n_slots--;
|
||||
-
|
||||
- publish_slots(new_head, old_head, slot);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-/* Needs to be called with mshv_state->msm.mutex held */
|
||||
-static MshvMemorySlot *append_slot(uint64_t gpa, uint64_t userspace_addr,
|
||||
- uint64_t size, bool readonly)
|
||||
-{
|
||||
- GList *old_head, *new_head;
|
||||
- MshvMemorySlot *slot;
|
||||
- MshvMemorySlotManager *manager = &mshv_state->msm;
|
||||
-
|
||||
- assert(manager);
|
||||
-
|
||||
- old_head = qatomic_load_acquire(&manager->slots);
|
||||
-
|
||||
- if (manager->n_slots >= MSHV_MAX_MEM_SLOTS) {
|
||||
- error_report("no free memory slots available");
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- slot = g_new0(MshvMemorySlot, 1);
|
||||
- slot->guest_phys_addr = gpa;
|
||||
- slot->userspace_addr = userspace_addr;
|
||||
- slot->memory_size = size;
|
||||
- slot->readonly = readonly;
|
||||
-
|
||||
- new_head = g_list_copy(old_head);
|
||||
- new_head = g_list_append(new_head, slot);
|
||||
- manager->n_slots++;
|
||||
-
|
||||
- publish_slots(new_head, old_head, NULL);
|
||||
-
|
||||
- return slot;
|
||||
-}
|
||||
-
|
||||
-static int slot_overlaps(const MshvMemorySlot *slot1,
|
||||
- const MshvMemorySlot *slot2)
|
||||
-{
|
||||
- uint64_t start_1 = slot1->userspace_addr,
|
||||
- start_2 = slot2->userspace_addr;
|
||||
- size_t len_1 = slot1->memory_size,
|
||||
- len_2 = slot2->memory_size;
|
||||
-
|
||||
- if (slot1 == slot2) {
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- return ranges_overlap(start_1, len_1, start_2, len_2) ? 0 : -1;
|
||||
-}
|
||||
-
|
||||
-static bool is_mapped(MshvMemorySlot *slot)
|
||||
-{
|
||||
- /* Subsequent reads of mapped field see a fully-initialized slot */
|
||||
- return qatomic_load_acquire(&slot->mapped);
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * Find slot that is:
|
||||
- * - overlapping in userspace
|
||||
- * - currently mapped in the guest
|
||||
- *
|
||||
- * Needs to be called with mshv_state->msm.mutex or RCU read lock held.
|
||||
- */
|
||||
-static MshvMemorySlot *find_overlap_mem_slot(GList *head, MshvMemorySlot *slot)
|
||||
-{
|
||||
- GList *found;
|
||||
- MshvMemorySlot *overlap_slot;
|
||||
-
|
||||
- found = g_list_find_custom(head, slot, (GCompareFunc) slot_overlaps);
|
||||
-
|
||||
- if (!found) {
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- overlap_slot = found->data;
|
||||
- if (!overlap_slot || !is_mapped(overlap_slot)) {
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- return overlap_slot;
|
||||
-}
|
||||
-
|
||||
static int set_guest_memory(int vm_fd,
|
||||
const struct mshv_user_mem_region *region)
|
||||
{
|
||||
@@ -160,169 +27,38 @@ static int set_guest_memory(int vm_fd,
|
||||
|
||||
ret = ioctl(vm_fd, MSHV_SET_GUEST_MEMORY, region);
|
||||
if (ret < 0) {
|
||||
- error_report("failed to set guest memory: %s", strerror(errno));
|
||||
- return -1;
|
||||
+ error_report("failed to set guest memory");
|
||||
+ return -errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int map_or_unmap(int vm_fd, const MshvMemorySlot *slot, bool map)
|
||||
+static int map_or_unmap(int vm_fd, const MshvMemoryRegion *mr, bool map)
|
||||
{
|
||||
struct mshv_user_mem_region region = {0};
|
||||
|
||||
- region.guest_pfn = slot->guest_phys_addr >> MSHV_PAGE_SHIFT;
|
||||
- region.size = slot->memory_size;
|
||||
- region.userspace_addr = slot->userspace_addr;
|
||||
+ region.guest_pfn = mr->guest_phys_addr >> MSHV_PAGE_SHIFT;
|
||||
+ region.size = mr->memory_size;
|
||||
+ region.userspace_addr = mr->userspace_addr;
|
||||
|
||||
if (!map) {
|
||||
region.flags |= (1 << MSHV_SET_MEM_BIT_UNMAP);
|
||||
- trace_mshv_unmap_memory(slot->userspace_addr, slot->guest_phys_addr,
|
||||
- slot->memory_size);
|
||||
+ trace_mshv_unmap_memory(mr->userspace_addr, mr->guest_phys_addr,
|
||||
+ mr->memory_size);
|
||||
return set_guest_memory(vm_fd, ®ion);
|
||||
}
|
||||
|
||||
region.flags = BIT(MSHV_SET_MEM_BIT_EXECUTABLE);
|
||||
- if (!slot->readonly) {
|
||||
+ if (!mr->readonly) {
|
||||
region.flags |= BIT(MSHV_SET_MEM_BIT_WRITABLE);
|
||||
}
|
||||
|
||||
- trace_mshv_map_memory(slot->userspace_addr, slot->guest_phys_addr,
|
||||
- slot->memory_size);
|
||||
+ trace_mshv_map_memory(mr->userspace_addr, mr->guest_phys_addr,
|
||||
+ mr->memory_size);
|
||||
return set_guest_memory(vm_fd, ®ion);
|
||||
}
|
||||
|
||||
-static int slot_matches_region(const MshvMemorySlot *slot1,
|
||||
- const MshvMemorySlot *slot2)
|
||||
-{
|
||||
- return (slot1->guest_phys_addr == slot2->guest_phys_addr &&
|
||||
- slot1->userspace_addr == slot2->userspace_addr &&
|
||||
- slot1->memory_size == slot2->memory_size) ? 0 : -1;
|
||||
-}
|
||||
-
|
||||
-/* Needs to be called with mshv_state->msm.mutex held */
|
||||
-static MshvMemorySlot *find_mem_slot_by_region(uint64_t gpa, uint64_t size,
|
||||
- uint64_t userspace_addr)
|
||||
-{
|
||||
- MshvMemorySlot ref_slot = {
|
||||
- .guest_phys_addr = gpa,
|
||||
- .userspace_addr = userspace_addr,
|
||||
- .memory_size = size,
|
||||
- };
|
||||
- GList *found;
|
||||
- MshvMemorySlotManager *manager = &mshv_state->msm;
|
||||
-
|
||||
- assert(manager);
|
||||
- found = g_list_find_custom(manager->slots, &ref_slot,
|
||||
- (GCompareFunc) slot_matches_region);
|
||||
-
|
||||
- return found ? found->data : NULL;
|
||||
-}
|
||||
-
|
||||
-static int slot_covers_gpa(const MshvMemorySlot *slot, uint64_t *gpa_p)
|
||||
-{
|
||||
- uint64_t gpa_offset, gpa = *gpa_p;
|
||||
-
|
||||
- gpa_offset = gpa - slot->guest_phys_addr;
|
||||
- return (slot->guest_phys_addr <= gpa && gpa_offset < slot->memory_size)
|
||||
- ? 0 : -1;
|
||||
-}
|
||||
-
|
||||
-/* Needs to be called with mshv_state->msm.mutex or RCU read lock held */
|
||||
-static MshvMemorySlot *find_mem_slot_by_gpa(GList *head, uint64_t gpa)
|
||||
-{
|
||||
- GList *found;
|
||||
- MshvMemorySlot *slot;
|
||||
-
|
||||
- trace_mshv_find_slot_by_gpa(gpa);
|
||||
-
|
||||
- found = g_list_find_custom(head, &gpa, (GCompareFunc) slot_covers_gpa);
|
||||
- if (found) {
|
||||
- slot = found->data;
|
||||
- trace_mshv_found_slot(slot->userspace_addr, slot->guest_phys_addr,
|
||||
- slot->memory_size);
|
||||
- return slot;
|
||||
- }
|
||||
-
|
||||
- return NULL;
|
||||
-}
|
||||
-
|
||||
-/* Needs to be called with mshv_state->msm.mutex held */
|
||||
-static void set_mapped(MshvMemorySlot *slot, bool mapped)
|
||||
-{
|
||||
- /* prior writes to mapped field becomes visible before readers see slot */
|
||||
- qatomic_store_release(&slot->mapped, mapped);
|
||||
-}
|
||||
-
|
||||
-MshvRemapResult mshv_remap_overlap_region(int vm_fd, uint64_t gpa)
|
||||
-{
|
||||
- MshvMemorySlot *gpa_slot, *overlap_slot;
|
||||
- GList *head;
|
||||
- int ret;
|
||||
- MshvMemorySlotManager *manager = &mshv_state->msm;
|
||||
-
|
||||
- /* fast path, called often by unmapped_gpa vm exit */
|
||||
- WITH_RCU_READ_LOCK_GUARD() {
|
||||
- assert(manager);
|
||||
- head = qatomic_load_acquire(&manager->slots);
|
||||
- /* return early if no slot is found */
|
||||
- gpa_slot = find_mem_slot_by_gpa(head, gpa);
|
||||
- if (gpa_slot == NULL) {
|
||||
- return MshvRemapNoMapping;
|
||||
- }
|
||||
-
|
||||
- /* return early if no overlapping slot is found */
|
||||
- overlap_slot = find_overlap_mem_slot(head, gpa_slot);
|
||||
- if (overlap_slot == NULL) {
|
||||
- return MshvRemapNoOverlap;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * We'll modify the mapping list, so we need to upgrade to mutex and
|
||||
- * recheck.
|
||||
- */
|
||||
- assert(manager);
|
||||
- QEMU_LOCK_GUARD(&manager->mutex);
|
||||
-
|
||||
- /* return early if no slot is found */
|
||||
- gpa_slot = find_mem_slot_by_gpa(manager->slots, gpa);
|
||||
- if (gpa_slot == NULL) {
|
||||
- return MshvRemapNoMapping;
|
||||
- }
|
||||
-
|
||||
- /* return early if no overlapping slot is found */
|
||||
- overlap_slot = find_overlap_mem_slot(manager->slots, gpa_slot);
|
||||
- if (overlap_slot == NULL) {
|
||||
- return MshvRemapNoOverlap;
|
||||
- }
|
||||
-
|
||||
- /* unmap overlapping slot */
|
||||
- ret = map_or_unmap(vm_fd, overlap_slot, false);
|
||||
- if (ret < 0) {
|
||||
- error_report("failed to unmap overlap region");
|
||||
- abort();
|
||||
- }
|
||||
- set_mapped(overlap_slot, false);
|
||||
- warn_report("mapped out userspace_addr=0x%016lx gpa=0x%010lx size=0x%lx",
|
||||
- overlap_slot->userspace_addr,
|
||||
- overlap_slot->guest_phys_addr,
|
||||
- overlap_slot->memory_size);
|
||||
-
|
||||
- /* map region for gpa */
|
||||
- ret = map_or_unmap(vm_fd, gpa_slot, true);
|
||||
- if (ret < 0) {
|
||||
- error_report("failed to map new region");
|
||||
- abort();
|
||||
- }
|
||||
- set_mapped(gpa_slot, true);
|
||||
- warn_report("mapped in userspace_addr=0x%016lx gpa=0x%010lx size=0x%lx",
|
||||
- gpa_slot->userspace_addr, gpa_slot->guest_phys_addr,
|
||||
- gpa_slot->memory_size);
|
||||
-
|
||||
- return MshvRemapOk;
|
||||
-}
|
||||
-
|
||||
static int handle_unmapped_mmio_region_read(uint64_t gpa, uint64_t size,
|
||||
uint8_t *data)
|
||||
{
|
||||
@@ -388,97 +124,20 @@ int mshv_guest_mem_write(uint64_t gpa, const uint8_t *data, uintptr_t size,
|
||||
return -1;
|
||||
}
|
||||
|
||||
-static int tracked_unmap(int vm_fd, uint64_t gpa, uint64_t size,
|
||||
- uint64_t userspace_addr)
|
||||
+static int set_memory(const MshvMemoryRegion *mshv_mr, bool add)
|
||||
{
|
||||
- int ret;
|
||||
- MshvMemorySlot *slot;
|
||||
- MshvMemorySlotManager *manager = &mshv_state->msm;
|
||||
-
|
||||
- assert(manager);
|
||||
-
|
||||
- QEMU_LOCK_GUARD(&manager->mutex);
|
||||
-
|
||||
- slot = find_mem_slot_by_region(gpa, size, userspace_addr);
|
||||
- if (!slot) {
|
||||
- trace_mshv_skip_unset_mem(userspace_addr, gpa, size);
|
||||
- /* no work to do */
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- if (!is_mapped(slot)) {
|
||||
- /* remove slot, no need to unmap */
|
||||
- return remove_slot(slot);
|
||||
- }
|
||||
-
|
||||
- ret = map_or_unmap(vm_fd, slot, false);
|
||||
- if (ret < 0) {
|
||||
- error_report("failed to unmap memory region");
|
||||
- return ret;
|
||||
- }
|
||||
- return remove_slot(slot);
|
||||
-}
|
||||
-
|
||||
-static int tracked_map(int vm_fd, uint64_t gpa, uint64_t size, bool readonly,
|
||||
- uint64_t userspace_addr)
|
||||
-{
|
||||
- MshvMemorySlot *slot, *overlap_slot;
|
||||
- int ret;
|
||||
- MshvMemorySlotManager *manager = &mshv_state->msm;
|
||||
-
|
||||
- assert(manager);
|
||||
-
|
||||
- QEMU_LOCK_GUARD(&manager->mutex);
|
||||
+ int ret = 0;
|
||||
|
||||
- slot = find_mem_slot_by_region(gpa, size, userspace_addr);
|
||||
- if (slot) {
|
||||
- error_report("memory region already mapped at gpa=0x%lx, "
|
||||
- "userspace_addr=0x%lx, size=0x%lx",
|
||||
- slot->guest_phys_addr, slot->userspace_addr,
|
||||
- slot->memory_size);
|
||||
+ if (!mshv_mr) {
|
||||
+ error_report("Invalid mshv_mr");
|
||||
return -1;
|
||||
}
|
||||
|
||||
- slot = append_slot(gpa, userspace_addr, size, readonly);
|
||||
-
|
||||
- overlap_slot = find_overlap_mem_slot(manager->slots, slot);
|
||||
- if (overlap_slot) {
|
||||
- trace_mshv_remap_attempt(slot->userspace_addr,
|
||||
- slot->guest_phys_addr,
|
||||
- slot->memory_size);
|
||||
- warn_report("attempt to map region [0x%lx-0x%lx], while "
|
||||
- "[0x%lx-0x%lx] is already mapped in the guest",
|
||||
- userspace_addr, userspace_addr + size - 1,
|
||||
- overlap_slot->userspace_addr,
|
||||
- overlap_slot->userspace_addr +
|
||||
- overlap_slot->memory_size - 1);
|
||||
-
|
||||
- /* do not register mem slot in hv, but record for later swap-in */
|
||||
- set_mapped(slot, false);
|
||||
-
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- ret = map_or_unmap(vm_fd, slot, true);
|
||||
- if (ret < 0) {
|
||||
- error_report("failed to map memory region");
|
||||
- return -1;
|
||||
- }
|
||||
- set_mapped(slot, true);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int set_memory(uint64_t gpa, uint64_t size, bool readonly,
|
||||
- uint64_t userspace_addr, bool add)
|
||||
-{
|
||||
- int vm_fd = mshv_state->vm;
|
||||
-
|
||||
- if (add) {
|
||||
- return tracked_map(vm_fd, gpa, size, readonly, userspace_addr);
|
||||
- }
|
||||
-
|
||||
- return tracked_unmap(vm_fd, gpa, size, userspace_addr);
|
||||
+ trace_mshv_set_memory(add, mshv_mr->guest_phys_addr,
|
||||
+ mshv_mr->memory_size,
|
||||
+ mshv_mr->userspace_addr, mshv_mr->readonly,
|
||||
+ ret);
|
||||
+ return map_or_unmap(mshv_state->vm, mshv_mr, add);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -514,9 +173,7 @@ void mshv_set_phys_mem(MshvMemoryListener *mml, MemoryRegionSection *section,
|
||||
bool writable = !area->readonly && !area->rom_device;
|
||||
hwaddr start_addr, mr_offset, size;
|
||||
void *ram;
|
||||
-
|
||||
- size = align_section(section, &start_addr);
|
||||
- trace_mshv_set_phys_mem(add, section->mr->name, start_addr);
|
||||
+ MshvMemoryRegion mshv_mr = {0};
|
||||
|
||||
size = align_section(section, &start_addr);
|
||||
trace_mshv_set_phys_mem(add, section->mr->name, start_addr);
|
||||
@@ -543,21 +200,14 @@ void mshv_set_phys_mem(MshvMemoryListener *mml, MemoryRegionSection *section,
|
||||
|
||||
ram = memory_region_get_ram_ptr(area) + mr_offset;
|
||||
|
||||
- ret = set_memory(start_addr, size, !writable, (uint64_t)ram, add);
|
||||
+ mshv_mr.guest_phys_addr = start_addr;
|
||||
+ mshv_mr.memory_size = size;
|
||||
+ mshv_mr.readonly = !writable;
|
||||
+ mshv_mr.userspace_addr = (uint64_t)ram;
|
||||
+
|
||||
+ ret = set_memory(&mshv_mr, add);
|
||||
if (ret < 0) {
|
||||
- error_report("failed to set memory region");
|
||||
+ error_report("Failed to set memory region");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
-
|
||||
-void mshv_init_memory_slot_manager(MshvState *mshv_state)
|
||||
-{
|
||||
- MshvMemorySlotManager *manager;
|
||||
-
|
||||
- assert(mshv_state);
|
||||
- manager = &mshv_state->msm;
|
||||
-
|
||||
- manager->n_slots = 0;
|
||||
- manager->slots = NULL;
|
||||
- qemu_mutex_init(&manager->mutex);
|
||||
-}
|
||||
diff --git a/accel/mshv/mshv-all.c b/accel/mshv/mshv-all.c
|
||||
index 80428d130d..88b66f2992 100644
|
||||
--- a/accel/mshv/mshv-all.c
|
||||
+++ b/accel/mshv/mshv-all.c
|
||||
@@ -437,8 +437,6 @@ static int mshv_init(AccelState *as, MachineState *ms)
|
||||
|
||||
mshv_init_msicontrol();
|
||||
|
||||
- mshv_init_memory_slot_manager(s);
|
||||
-
|
||||
ret = create_vm(mshv_fd, &vm_fd);
|
||||
if (ret < 0) {
|
||||
close(mshv_fd);
|
||||
diff --git a/accel/mshv/trace-events b/accel/mshv/trace-events
|
||||
index 36f0d59b38..a4dffeb24a 100644
|
||||
--- a/accel/mshv/trace-events
|
||||
+++ b/accel/mshv/trace-events
|
||||
@@ -26,8 +26,3 @@ mshv_map_memory(uint64_t userspace_addr, uint64_t gpa, uint64_t size) "\tu_a=0x%
|
||||
mshv_unmap_memory(uint64_t userspace_addr, uint64_t gpa, uint64_t size) "\tu_a=0x%" PRIx64 " gpa=0x%010" PRIx64 " size=0x%08" PRIx64
|
||||
mshv_set_phys_mem(bool add, const char *name, uint64_t gpa) "\tadd=%d name=%s gpa=0x%010" PRIx64
|
||||
mshv_handle_mmio(uint64_t gva, uint64_t gpa, uint64_t size, uint8_t access_type) "\tgva=0x%" PRIx64 " gpa=0x%010" PRIx64 " size=0x%" PRIx64 " access_type=%d"
|
||||
-
|
||||
-mshv_found_slot(uint64_t userspace_addr, uint64_t gpa, uint64_t size) "\tu_a=0x%" PRIx64 " gpa=0x%010" PRIx64 " size=0x%08" PRIx64
|
||||
-mshv_skip_unset_mem(uint64_t userspace_addr, uint64_t gpa, uint64_t size) "\tu_a=0x%" PRIx64 " gpa=0x%010" PRIx64 " size=0x%08" PRIx64
|
||||
-mshv_remap_attempt(uint64_t userspace_addr, uint64_t gpa, uint64_t size) "\tu_a=0x%" PRIx64 " gpa=0x%010" PRIx64 " size=0x%08" PRIx64
|
||||
-mshv_find_slot_by_gpa(uint64_t gpa) "\tgpa=0x%010" PRIx64
|
||||
diff --git a/include/system/mshv_int.h b/include/system/mshv_int.h
|
||||
index 490563c1ab..ad4d001c3c 100644
|
||||
--- a/include/system/mshv_int.h
|
||||
+++ b/include/system/mshv_int.h
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
#define MSHV_MSR_ENTRIES_COUNT 64
|
||||
|
||||
-#define MSHV_MAX_MEM_SLOTS 32
|
||||
-
|
||||
typedef struct hyperv_message hv_message;
|
||||
|
||||
typedef struct MshvHvCallArgs {
|
||||
@@ -42,12 +40,6 @@ typedef struct MshvAddressSpace {
|
||||
AddressSpace *as;
|
||||
} MshvAddressSpace;
|
||||
|
||||
-typedef struct MshvMemorySlotManager {
|
||||
- size_t n_slots;
|
||||
- GList *slots;
|
||||
- QemuMutex mutex;
|
||||
-} MshvMemorySlotManager;
|
||||
-
|
||||
struct MshvState {
|
||||
AccelState parent_obj;
|
||||
int vm;
|
||||
@@ -56,7 +48,6 @@ struct MshvState {
|
||||
int nr_as;
|
||||
MshvAddressSpace *as;
|
||||
int fd;
|
||||
- MshvMemorySlotManager msm;
|
||||
};
|
||||
|
||||
typedef struct MshvMsiControl {
|
||||
@@ -87,12 +78,6 @@ typedef enum MshvVmExit {
|
||||
MshvVmExitSpecial = 2,
|
||||
} MshvVmExit;
|
||||
|
||||
-typedef enum MshvRemapResult {
|
||||
- MshvRemapOk = 0,
|
||||
- MshvRemapNoMapping = 1,
|
||||
- MshvRemapNoOverlap = 2,
|
||||
-} MshvRemapResult;
|
||||
-
|
||||
void mshv_init_mmio_emu(void);
|
||||
int mshv_create_vcpu(int vm_fd, uint8_t vp_index, int *cpu_fd);
|
||||
void mshv_remove_vcpu(int vm_fd, int cpu_fd);
|
||||
@@ -116,22 +101,19 @@ int mshv_hvcall(int fd, const struct mshv_root_hvcall *args);
|
||||
#endif
|
||||
|
||||
/* memory */
|
||||
-typedef struct MshvMemorySlot {
|
||||
+typedef struct MshvMemoryRegion {
|
||||
uint64_t guest_phys_addr;
|
||||
uint64_t memory_size;
|
||||
uint64_t userspace_addr;
|
||||
bool readonly;
|
||||
- bool mapped;
|
||||
-} MshvMemorySlot;
|
||||
+} MshvMemoryRegion;
|
||||
|
||||
-MshvRemapResult mshv_remap_overlap_region(int vm_fd, uint64_t gpa);
|
||||
int mshv_guest_mem_read(uint64_t gpa, uint8_t *data, uintptr_t size,
|
||||
bool is_secure_mode, bool instruction_fetch);
|
||||
int mshv_guest_mem_write(uint64_t gpa, const uint8_t *data, uintptr_t size,
|
||||
bool is_secure_mode);
|
||||
void mshv_set_phys_mem(MshvMemoryListener *mml, MemoryRegionSection *section,
|
||||
bool add);
|
||||
-void mshv_init_memory_slot_manager(MshvState *mshv_state);
|
||||
|
||||
/* msr */
|
||||
typedef struct MshvMsrEntry {
|
||||
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
|
||||
index 1c3db02188..c577e284b4 100644
|
||||
--- a/target/i386/mshv/mshv-cpu.c
|
||||
+++ b/target/i386/mshv/mshv-cpu.c
|
||||
@@ -1168,43 +1168,6 @@ static int handle_mmio(CPUState *cpu, const struct hyperv_message *msg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int handle_unmapped_mem(int vm_fd, CPUState *cpu,
|
||||
- const struct hyperv_message *msg,
|
||||
- MshvVmExit *exit_reason)
|
||||
-{
|
||||
- struct hv_x64_memory_intercept_message info = { 0 };
|
||||
- uint64_t gpa;
|
||||
- int ret;
|
||||
- enum MshvRemapResult remap_result;
|
||||
-
|
||||
- ret = set_memory_info(msg, &info);
|
||||
- if (ret < 0) {
|
||||
- error_report("failed to convert message to memory info");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- gpa = info.guest_physical_address;
|
||||
-
|
||||
- /* attempt to remap the region, in case of overlapping userspace mappings */
|
||||
- remap_result = mshv_remap_overlap_region(vm_fd, gpa);
|
||||
- *exit_reason = MshvVmExitIgnore;
|
||||
-
|
||||
- switch (remap_result) {
|
||||
- case MshvRemapNoMapping:
|
||||
- /* if we didn't find a mapping, it is probably mmio */
|
||||
- return handle_mmio(cpu, msg, exit_reason);
|
||||
- case MshvRemapOk:
|
||||
- break;
|
||||
- case MshvRemapNoOverlap:
|
||||
- /* This should not happen, but we are forgiving it */
|
||||
- warn_report("found no overlap for unmapped region");
|
||||
- *exit_reason = MshvVmExitSpecial;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static int set_ioport_info(const struct hyperv_message *msg,
|
||||
hv_x64_io_port_intercept_message *info)
|
||||
{
|
||||
@@ -1546,12 +1509,6 @@ int mshv_run_vcpu(int vm_fd, CPUState *cpu, hv_message *msg, MshvVmExit *exit)
|
||||
case HVMSG_UNRECOVERABLE_EXCEPTION:
|
||||
return MshvVmExitShutdown;
|
||||
case HVMSG_UNMAPPED_GPA:
|
||||
- ret = handle_unmapped_mem(vm_fd, cpu, msg, &exit_reason);
|
||||
- if (ret < 0) {
|
||||
- error_report("failed to handle unmapped memory");
|
||||
- return -1;
|
||||
- }
|
||||
- return exit_reason;
|
||||
case HVMSG_GPA_INTERCEPT:
|
||||
ret = handle_mmio(cpu, msg, &exit_reason);
|
||||
if (ret < 0) {
|
||||
--
|
||||
2.52.0
|
||||
|
||||
58
kvm-accel-mshv-implement-cpu_thread_is_idle-hook.patch
Normal file
58
kvm-accel-mshv-implement-cpu_thread_is_idle-hook.patch
Normal file
@ -0,0 +1,58 @@
|
||||
From 4356c4191e1b7ba491a2dd6d8c6167f7eb9a3de1 Mon Sep 17 00:00:00 2001
|
||||
From: Magnus Kulke <magnuskulke@linux.microsoft.com>
|
||||
Date: Tue, 21 Apr 2026 05:21:54 +0000
|
||||
Subject: [PATCH 5/5] accel/mshv: implement cpu_thread_is_idle() hook
|
||||
|
||||
RH-Author: Magnus Kulke <None>
|
||||
RH-MergeRequest: 491: accel/mshv: backport required patches for mshv guests
|
||||
RH-Jira: RHEL-177969
|
||||
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-Commit: [2/2] 4880ec9edc01fda07186687f9d19159f3afd0689 (mkulke/qemu-kvm)
|
||||
|
||||
In MSHV the hypervisor APIC is always used, so we to implement this hook
|
||||
to make sure the AP's vcpu thread is not blocked waiting for an INIT SIPI
|
||||
by the BSP. Without this change soft reboots with -smp cpus>=2 will
|
||||
hang.
|
||||
|
||||
Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
|
||||
Reviewed-by: Mohamed Mediouni <mohamed@unpredictable.fr>
|
||||
Link: https://lore.kernel.org/r/20260421-mshv_accel_arm64_supp-v3-9-469f544778ba@linux.microsoft.com
|
||||
[Make comment not x86 specific. - Paolo]
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
(cherry picked from commit dbfb680772d5184544f7c0a8bba96bec229c96e6)
|
||||
---
|
||||
accel/mshv/mshv-all.c | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/accel/mshv/mshv-all.c b/accel/mshv/mshv-all.c
|
||||
index 88b66f2992..d7df89dbd2 100644
|
||||
--- a/accel/mshv/mshv-all.c
|
||||
+++ b/accel/mshv/mshv-all.c
|
||||
@@ -699,11 +699,23 @@ static const TypeInfo mshv_accel_type = {
|
||||
.instance_size = sizeof(MshvState),
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * MSHV manages secondary processors in the hypervisor. SIPI for x86 and
|
||||
+ * PSCI for Arm are handled internally. Halted vCPUs must still enter
|
||||
+ * mshv_cpu_exec() so that MSHV_RUN_VP is called and the hypervisor will
|
||||
+ * wake APs.
|
||||
+ */
|
||||
+static bool mshv_vcpu_thread_is_idle(CPUState *cpu)
|
||||
+{
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
static void mshv_accel_ops_class_init(ObjectClass *oc, const void *data)
|
||||
{
|
||||
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
|
||||
|
||||
ops->create_vcpu_thread = mshv_start_vcpu_thread;
|
||||
+ ops->cpu_thread_is_idle = mshv_vcpu_thread_is_idle;
|
||||
ops->synchronize_post_init = mshv_cpu_synchronize_post_init;
|
||||
ops->synchronize_post_reset = mshv_cpu_synchronize_post_reset;
|
||||
ops->synchronize_state = mshv_cpu_synchronize;
|
||||
--
|
||||
2.52.0
|
||||
|
||||
49
kvm-scsi-adjust-error_prepend-formatting.patch
Normal file
49
kvm-scsi-adjust-error_prepend-formatting.patch
Normal file
@ -0,0 +1,49 @@
|
||||
From bc38981e098c0dd2430c125ceb08188813e7ba12 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Date: Wed, 1 Apr 2026 13:19:25 -0400
|
||||
Subject: [PATCH 1/5] scsi: adjust error_prepend() formatting
|
||||
|
||||
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
RH-MergeRequest: 493: scsi: PR live migration PREEMPT fixes [9.9]
|
||||
RH-Jira: RHEL-158243
|
||||
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-Commit: [1/3] 8ba6738b878a8926f8aaab487b863a42a44a736e (stefanha/centos-stream-qemu-kvm)
|
||||
|
||||
The error strings will be concatenated so add a separator to make the
|
||||
combined error message easy to read.
|
||||
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Link: https://lore.kernel.org/r/20260401171927.396672-2-stefanha@redhat.com
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
(cherry picked from commit 15c57ac351ccb4af625cd7dc582831f472c1a68f)
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
---
|
||||
hw/scsi/scsi-generic.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
|
||||
index b8b3f399f0..5825a47311 100644
|
||||
--- a/hw/scsi/scsi-generic.c
|
||||
+++ b/hw/scsi/scsi-generic.c
|
||||
@@ -438,7 +438,7 @@ static bool scsi_generic_pr_register(SCSIDevice *s, uint64_t key, Error **errp)
|
||||
ret = scsi_SG_IO(s->conf.blk, SG_DXFER_TO_DEV, cmd, sizeof(cmd),
|
||||
buf, sizeof(buf), s->io_timeout, errp);
|
||||
if (ret < 0) {
|
||||
- error_prepend(errp, "PERSISTENT RESERVE OUT with REGISTER");
|
||||
+ error_prepend(errp, "PERSISTENT RESERVE OUT with REGISTER: ");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -462,7 +462,7 @@ static bool scsi_generic_pr_preempt(SCSIDevice *s, uint64_t key,
|
||||
ret = scsi_SG_IO(s->conf.blk, SG_DXFER_TO_DEV, cmd, sizeof(cmd),
|
||||
buf, sizeof(buf), s->io_timeout, errp);
|
||||
if (ret < 0) {
|
||||
- error_prepend(errp, "PERSISTENT RESERVE OUT with PREEMPT");
|
||||
+ error_prepend(errp, "PERSISTENT RESERVE OUT with PREEMPT: ");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
--
|
||||
2.52.0
|
||||
|
||||
73
kvm-scsi-always-send-valid-PREEMPT-TYPE-field.patch
Normal file
73
kvm-scsi-always-send-valid-PREEMPT-TYPE-field.patch
Normal file
@ -0,0 +1,73 @@
|
||||
From 45ca2a7d7a348dd1a48a5f218ca02331bc3d29a7 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Date: Wed, 1 Apr 2026 13:19:26 -0400
|
||||
Subject: [PATCH 2/5] scsi: always send valid PREEMPT TYPE field
|
||||
|
||||
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
RH-MergeRequest: 493: scsi: PR live migration PREEMPT fixes [9.9]
|
||||
RH-Jira: RHEL-158243
|
||||
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-Commit: [2/3] c1b10616023abe2ec648c1b0c4d095a87f0ff258 (stefanha/centos-stream-qemu-kvm)
|
||||
|
||||
The SPC-6 specification says that the PREEMPT service action ignores the
|
||||
TYPE field when there is no reservation. However, the LIO Linux iSCSI
|
||||
target rejects commands with a zero TYPE field. The field never ends up
|
||||
being used in this case, so replace it with a "valid" value to work
|
||||
around the issue.
|
||||
|
||||
Reported-by: Qing Wang <qinwang@redhat.com>
|
||||
Buglink: https://redhat.atlassian.net/browse/RHEL-155807
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Link: https://lore.kernel.org/r/20260401171927.396672-3-stefanha@redhat.com
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
(cherry picked from commit 15a202656cd553911272f9666aa067c706fc3dfe)
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
---
|
||||
hw/scsi/scsi-generic.c | 10 ++++++++++
|
||||
include/scsi/constants.h | 10 ++++++++++
|
||||
2 files changed, 20 insertions(+)
|
||||
|
||||
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
|
||||
index 5825a47311..8a57473623 100644
|
||||
--- a/hw/scsi/scsi-generic.c
|
||||
+++ b/hw/scsi/scsi-generic.c
|
||||
@@ -452,6 +452,16 @@ static bool scsi_generic_pr_preempt(SCSIDevice *s, uint64_t key,
|
||||
uint64_t key_be = cpu_to_be64(key);
|
||||
int ret;
|
||||
|
||||
+ /*
|
||||
+ * The LIO iSCSI target in Linux up to at least version 7.0 rejects PREEMPT
|
||||
+ * commands with a zero TYPE field although the SPC-6 specification says
|
||||
+ * the field should be ignored when there is no persistent reservation.
|
||||
+ * Work around this by choosing an arbitrary valid PR type value.
|
||||
+ */
|
||||
+ if (resv_type == 0) {
|
||||
+ resv_type = PR_TYPE_WRITE_EXCLUSIVE;
|
||||
+ }
|
||||
+
|
||||
cmd[0] = PERSISTENT_RESERVE_OUT;
|
||||
cmd[1] = PRO_PREEMPT;
|
||||
cmd[2] = resv_type & 0xf;
|
||||
diff --git a/include/scsi/constants.h b/include/scsi/constants.h
|
||||
index cb97bdb636..717e470a5d 100644
|
||||
--- a/include/scsi/constants.h
|
||||
+++ b/include/scsi/constants.h
|
||||
@@ -340,4 +340,14 @@
|
||||
#define PRO_REGISTER_AND_MOVE 0x07
|
||||
#define PRO_REPLACE_LOST_RESERVATION 0x08
|
||||
|
||||
+/*
|
||||
+ * Persistent reservation types
|
||||
+ */
|
||||
+#define PR_TYPE_WRITE_EXCLUSIVE 0x1
|
||||
+#define PR_TYPE_EXCLUSIVE_ACCESS 0x3
|
||||
+#define PR_TYPE_WRITE_EXCLUSIVE_REG_ONLY 0x5
|
||||
+#define PR_TYPE_EXCLUSIVE_ACCESS_REG_ONLY 0x6
|
||||
+#define PR_TYPE_WRITE_EXCLUSIVE_ALL_REGS 0x7
|
||||
+#define PR_TYPE_EXCLUSIVE_ACCESS_ALL_REGS 0x8
|
||||
+
|
||||
#endif
|
||||
--
|
||||
2.52.0
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
From 520f3f124b79709b8da67f1a8adb77da60fc4753 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Date: Wed, 1 Apr 2026 13:19:27 -0400
|
||||
Subject: [PATCH 3/5] scsi: register again after PREEMPT without reservation
|
||||
|
||||
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
RH-MergeRequest: 493: scsi: PR live migration PREEMPT fixes [9.9]
|
||||
RH-Jira: RHEL-158243
|
||||
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
|
||||
RH-Commit: [3/3] 4ba66cf81945645015cb5df9f0b7f4d163f84808 (stefanha/centos-stream-qemu-kvm)
|
||||
|
||||
The SCSI specification says PREEMPT without a reservation removes all
|
||||
registrations with the given key. Try to register again after PREEMPT
|
||||
since our key will have been removed.
|
||||
|
||||
In practice some SCSI targets keep the calling I_T nexus' registration
|
||||
instead of removing it. Therefore we need to handle both the
|
||||
spec-compliant and the non-compliant behavior.
|
||||
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Link: https://lore.kernel.org/r/20260401171927.396672-4-stefanha@redhat.com
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
(cherry picked from commit b9a3b329d09dea5a4692de483419693ef0e23052)
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
---
|
||||
hw/scsi/scsi-generic.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
|
||||
index 8a57473623..9c5927b543 100644
|
||||
--- a/hw/scsi/scsi-generic.c
|
||||
+++ b/hw/scsi/scsi-generic.c
|
||||
@@ -512,6 +512,16 @@ bool scsi_generic_pr_state_preempt(SCSIDevice *s, Error **errp)
|
||||
if (!scsi_generic_pr_preempt(s, key, resv_type, errp)) {
|
||||
return false;
|
||||
}
|
||||
+
|
||||
+ /*
|
||||
+ * Some SCSI targets, like the Linux LIO target, remove our
|
||||
+ * registration when preempting without a reservation (resv_type is 0).
|
||||
+ * Try to register again but ignore the error since a RESERVATION
|
||||
+ * CONFLICT is expected if our registration remained in place.
|
||||
+ */
|
||||
+ if (resv_type == 0) {
|
||||
+ scsi_generic_pr_register(s, key, NULL);
|
||||
+ }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
--
|
||||
2.52.0
|
||||
|
||||
@ -149,7 +149,7 @@ Obsoletes: %{name}-block-ssh <= %{epoch}:%{version} \
|
||||
Summary: QEMU is a machine emulator and virtualizer
|
||||
Name: qemu-kvm
|
||||
Version: 10.1.0
|
||||
Release: 20%{?rcrel}%{?dist}%{?cc_suffix}
|
||||
Release: 21%{?rcrel}%{?dist}%{?cc_suffix}
|
||||
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
|
||||
# Epoch 15 used for RHEL 8
|
||||
# Epoch 17 used for RHEL 9 (due to release versioning offset in RHEL 8.5)
|
||||
@ -385,6 +385,16 @@ Patch119: kvm-target-arm-cpu64-Define-cpreg-migration-tolerance-fo.patch
|
||||
Patch120: kvm-target-arm-helper-Define-cpreg-migration-tolerance-f.patch
|
||||
# For RHEL-174859 - [rhel9] Backport qemu cross-kernel migration mitigation series
|
||||
Patch121: kvm-Revert-target-arm-Reinstate-bogus-AArch32-DBGDTRTX-r.patch
|
||||
# For RHEL-158243 - live migration failed the VM just register key only [rhel-9.9]
|
||||
Patch122: kvm-scsi-adjust-error_prepend-formatting.patch
|
||||
# For RHEL-158243 - live migration failed the VM just register key only [rhel-9.9]
|
||||
Patch123: kvm-scsi-always-send-valid-PREEMPT-TYPE-field.patch
|
||||
# For RHEL-158243 - live migration failed the VM just register key only [rhel-9.9]
|
||||
Patch124: kvm-scsi-register-again-after-PREEMPT-without-reservatio.patch
|
||||
# For RHEL-177969 - MSHV backport onto QEMU 10.1.0 is not able to launch MSHV guests
|
||||
Patch125: kvm-accel-mshv-Remove-remap-overlapping-mappings-code.patch
|
||||
# For RHEL-177969 - MSHV backport onto QEMU 10.1.0 is not able to launch MSHV guests
|
||||
Patch126: kvm-accel-mshv-implement-cpu_thread_is_idle-hook.patch
|
||||
|
||||
|
||||
# For RHEL-11424 - [IBM 9.6 FEAT] KVM: Full boot order support - qemu part
|
||||
@ -2099,6 +2109,17 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Mon Jun 08 2026 Jon Maloy <jmaloy@redhat.com> - 10.1.0-21
|
||||
- kvm-scsi-adjust-error_prepend-formatting.patch [RHEL-158243]
|
||||
- kvm-scsi-always-send-valid-PREEMPT-TYPE-field.patch [RHEL-158243]
|
||||
- kvm-scsi-register-again-after-PREEMPT-without-reservatio.patch [RHEL-158243]
|
||||
- kvm-accel-mshv-Remove-remap-overlapping-mappings-code.patch [RHEL-177969]
|
||||
- kvm-accel-mshv-implement-cpu_thread_is_idle-hook.patch [RHEL-177969]
|
||||
- Resolves: RHEL-158243
|
||||
(live migration failed the VM just register key only [rhel-9.9])
|
||||
- Resolves: RHEL-177969
|
||||
(MSHV backport onto QEMU 10.1.0 is not able to launch MSHV guests)
|
||||
|
||||
* Tue May 19 2026 Jon Maloy <jmaloy@redhat.com> - 10.1.0-20
|
||||
- kvm-vmstate-Introduce-VMSTATE_VARRAY_INT32_ALLOC.patch [RHEL-174859]
|
||||
- kvm-target-arm-Move-compare_u64-to-helper.c.patch [RHEL-174859]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user