From 93de2a6a4b91b72607136dd656edf03fb399d27f Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Wed, 23 Sep 2026 09:37:21 -0700 Subject: KVM: SEV: Do cache maintenance on the source VM during intra-host migration Manually perform cache maintenance on the source VM during intra-host migration to ensure no stale data is left in CPU caches after the VM is destroyed. Because the source VM is "converted" to a non-SEV VM, KVM's memory reclaim flows won't trigger cache maintenance, e.g. when all guest memory is reclaimed in response to detaching from the mmu_notifier. Note, relying on the destination VM to do cache maintenance isn't an option as KVM doesn't require identical guest memory configurations, i.e. the source VM may have access to memory that the destination VM does not. Enforcing equivalent memory configurations is infeasible, as it would require a *deep* comparison of memslots, e.g. to verify that not only are the memslot identical, but what the memslots point at is also identical. Fixes: b56639318bb2 ("KVM: SEV: Add support for SEV intra host migration") Cc: stable@vger.kernel.org Reported-by: Stefan Teodorescu Signed-off-by: Sean Christopherson Message-ID: <20260923163721.1584779-3-seanjc@google.com> Signed-off-by: Paolo Bonzini --- arch/powerpc/boot/opal.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 arch/powerpc/boot/opal.c (limited to 'arch/powerpc/boot/opal.c') diff --git a/arch/powerpc/boot/opal.c b/arch/powerpc/boot/opal.c new file mode 100644 index 000000000..b69818ce5 --- /dev/null +++ b/arch/powerpc/boot/opal.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2016 IBM Corporation. + */ + +#include "ops.h" +#include "stdio.h" +#include "io.h" +#include +#include "../include/asm/opal-api.h" + +/* Global OPAL struct used by opal-call.S */ +struct opal { + u64 base; + u64 entry; +} opal; + +static u32 opal_con_id; + +/* see opal-wrappers.S */ +int64_t opal_console_write(int64_t term_number, u64 *length, const u8 *buffer); +int64_t opal_console_read(int64_t term_number, uint64_t *length, u8 *buffer); +int64_t opal_console_write_buffer_space(uint64_t term_number, uint64_t *length); +int64_t opal_console_flush(uint64_t term_number); +int64_t opal_poll_events(uint64_t *outstanding_event_mask); + +void opal_kentry(unsigned long fdt_addr, void *vmlinux_addr); + +static int opal_con_open(void) +{ + /* + * When OPAL loads the boot kernel it stashes the OPAL base and entry + * address in r8 and r9 so the kernel can use the OPAL console + * before unflattening the devicetree. While executing the wrapper will + * probably trash r8 and r9 so this kentry hook restores them before + * entering the decompressed kernel. + */ + platform_ops.kentry = opal_kentry; + return 0; +} + +static void opal_con_putc(unsigned char c) +{ + int64_t rc; + uint64_t olen, len; + + do { + rc = opal_console_write_buffer_space(opal_con_id, &olen); + len = be64_to_cpu(olen); + if (rc) + return; + opal_poll_events(NULL); + } while (len < 1); + + + olen = cpu_to_be64(1); + opal_console_write(opal_con_id, &olen, &c); +} + +static void opal_con_close(void) +{ + opal_console_flush(opal_con_id); +} + +static void opal_init(void) +{ + void *opal_node; + + opal_node = finddevice("/ibm,opal"); + if (!opal_node) + return; + if (getprop(opal_node, "opal-base-address", &opal.base, sizeof(u64)) < 0) + return; + opal.base = be64_to_cpu(opal.base); + if (getprop(opal_node, "opal-entry-address", &opal.entry, sizeof(u64)) < 0) + return; + opal.entry = be64_to_cpu(opal.entry); +} + +int opal_console_init(void *devp, struct serial_console_data *scdp) +{ + opal_init(); + + if (devp) { + int n = getprop(devp, "reg", &opal_con_id, sizeof(u32)); + if (n != sizeof(u32)) + return -1; + opal_con_id = be32_to_cpu(opal_con_id); + } else + opal_con_id = 0; + + scdp->open = opal_con_open; + scdp->putc = opal_con_putc; + scdp->close = opal_con_close; + + return 0; +} -- cgit v1.3.1