From: Zack Rusin <zack.rusin@broadcom.com>
To: Andrew Morton <akpm@linux-foundation.org>,
Petr Mladek <pmladek@suse.com>, Baoquan He <baoquan.he@linux.dev>,
Mike Rapoport <rppt@kernel.org>,
Pasha Tatashin <pasha.tatashin@soleen.com>,
Pratyush Yadav <pratyush@kernel.org>,
Dave Young <ruirui.yang@linux.dev>
Cc: Borislav Petkov <bp@alien8.de>,
Ajay Kaher <ajay.kaher@broadcom.com>,
Alexey Makhalov <alexey.makhalov@broadcom.com>,
x86@kernel.org, Joel Granados <joel.granados@kernel.org>,
Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>,
Dave Hansen <dave.hansen@linux.intel.com>,
"H. Peter Anvin" <hpa@zytor.com>,
virtualization@lists.linux.dev,
bcm-kernel-feedback-list@broadcom.com,
linux-kernel@vger.kernel.org,
John Ogness <john.ogness@linutronix.de>,
Steven Rostedt <rostedt@goodmis.org>,
Sergey Senozhatsky <senozhatsky@chromium.org>,
Kees Cook <kees@kernel.org>, Jonathan Corbet <corbet@lwn.net>,
Bo Gan <bo.gan@broadcom.com>,
Brennan Lamoreaux <brennan.lamoreaux@broadcom.com>,
kexec@lists.infradead.org, linux-doc@vger.kernel.org,
"Guilherme G. Piccoli" <gpiccoli@igalia.com>,
Maaz Mombasawala <maaz.mombasawala@broadcom.com>,
Shuah Khan <skhan@linuxfoundation.org>,
Randy Dunlap <rdunlap@infradead.org>,
Stephen Brennan <stephen.s.brennan@oracle.com>,
Michael Kelley <mhklinux@outlook.com>,
Ian Forbes <ian.forbes@broadcom.com>,
Bradley Morgan <brads@mainlining.org>
Subject: [PATCH v3 2/4] x86/vmware: Add a bounded panic log sender
Date: Mon, 9 Nov 2026 00:47:38 -0500 [thread overview]
Message-ID: <b4befd89cc0b5844f499606b7d42f13cdb37046a.1794201807.git.zack.rusin@broadcom.com> (raw)
In-Reply-To: <cover.1794201807.git.zack.rusin@broadcom.com>
A VMware guest may be unable to save its own logs after a crash. Copy
the newest kernel log records to the host's vmware.log before kdump,
so they remain available if the capture kernel fails.
Register the sender on the platform panic notifier list and send the
log through the low-bandwidth register interface. Allocate a fixed
8 KiB buffer during early init; 4 KiB can lose useful stack-trace
context. The callback allocates no memory and emits no printk
messages. Limit the transfer to the buffer size and make at most three
attempts, retrying only if a VM checkpoint interrupts the transfer.
Enable logging by default only in guests without memory encryption;
encrypted guests should send their log to the host only when an
administrator opts in. The copy is best-effort diagnostics; kdump does
not depend on it succeeding.
Suggested-by: Michael Kelley <mhklinux@outlook.com>
Link: https://lore.kernel.org/r/SN6PR02MB41574A11D309A0530C63E0FED4842@SN6PR02MB4157.namprd02.prod.outlook.com
Link: https://lore.kernel.org/r/20260309235250.2611115-3-alexey.makhalov@broadcom.com
Co-developed-by: Bo Gan <bo.gan@broadcom.com>
Signed-off-by: Bo Gan <bo.gan@broadcom.com>
Co-developed-by: Alexey Makhalov <alexey.makhalov@broadcom.com>
Signed-off-by: Alexey Makhalov <alexey.makhalov@broadcom.com>
Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
---
v3: Register on the platform list instead of the pre-kdump list. The
VMware code is otherwise unchanged from v2.
arch/x86/include/asm/vmware.h | 1 +
arch/x86/kernel/cpu/vmware.c | 173 ++++++++++++++++++++++++++++++++++
2 files changed, 174 insertions(+)
diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h
index 4220dae14a2d..598d4cd448ec 100644
--- a/arch/x86/include/asm/vmware.h
+++ b/arch/x86/include/asm/vmware.h
@@ -57,6 +57,7 @@
#define VMWARE_HYPERVISOR_MAGIC 0x564d5868U
#define VMWARE_CMD_GETVERSION 10
+#define VMWARE_CMD_MESSAGE 30
#define VMWARE_CMD_GETHZ 45
#define VMWARE_CMD_GETVCPU_INFO 68
#define VMWARE_CMD_STEALCLOCK 91
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index f7ab9e7902cf..0c6f7248a665 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -24,11 +24,16 @@
#include <linux/dmi.h>
#include <linux/init.h>
#include <linux/export.h>
+#include <linux/kmsg_dump.h>
+#include <linux/mm.h>
+#include <linux/panic_notifier.h>
#include <linux/clocksource.h>
#include <linux/cpu.h>
#include <linux/efi.h>
#include <linux/reboot.h>
+#include <linux/sizes.h>
#include <linux/static_call.h>
+#include <linux/wordpart.h>
#include <linux/sched/cputime.h>
#include <asm/div64.h>
#include <asm/x86_init.h>
@@ -52,6 +57,23 @@
#define STEALCLOCK_DISABLED 0
#define STEALCLOCK_ENABLED 1
+#define VMWARE_MSG_STATUS_SUCCESS BIT(16)
+#define VMWARE_MSG_STATUS_CPT BIT(20)
+
+#define VMWARE_RPCI_PROTOCOL 0x49435052
+#define VMWARE_GUESTMSG_COOKIE BIT(31)
+
+#define VMWARE_MSG_TYPE(n) ((n) << 16)
+#define VMWARE_MSG_OPEN VMWARE_MSG_TYPE(0U)
+#define VMWARE_MSG_SENDSIZE VMWARE_MSG_TYPE(1U)
+#define VMWARE_MSG_SENDPAYLOAD VMWARE_MSG_TYPE(2U)
+#define VMWARE_MSG_CLOSE VMWARE_MSG_TYPE(6U)
+
+#define VMWARE_LOG_BUF_SIZE SZ_8K
+#define VMWARE_LOG_ATTEMPTS 3
+#define VMWARE_LOG_PREFIX "log "
+#define VMWARE_LOG_PREFIX_LEN (sizeof(VMWARE_LOG_PREFIX) - 1)
+
struct vmware_steal_time {
union {
u64 clock; /* stolen time counter in units of vtsc */
@@ -64,6 +86,12 @@ struct vmware_steal_time {
u64 reserved[7];
};
+struct vmware_rpc_channel {
+ u16 id;
+ u32 cookie_high;
+ u32 cookie_low;
+};
+
static unsigned long vmware_tsc_khz __ro_after_init;
static u8 vmware_hypercall_mode __ro_after_init;
@@ -142,6 +170,151 @@ static unsigned long vmware_get_tsc_khz(void)
return vmware_tsc_khz;
}
+static int vmware_log_open(struct vmware_rpc_channel *channel)
+{
+ u32 info, id;
+
+ vmware_hypercall6(VMWARE_CMD_MESSAGE | VMWARE_MSG_OPEN,
+ VMWARE_RPCI_PROTOCOL | VMWARE_GUESTMSG_COOKIE, 0,
+ &info, &id, &channel->cookie_high,
+ &channel->cookie_low);
+ if (!(info & VMWARE_MSG_STATUS_SUCCESS))
+ return -EIO;
+
+ channel->id = upper_16_bits(id);
+ return 0;
+}
+
+static int vmware_log_close(const struct vmware_rpc_channel *channel)
+{
+ u32 info;
+
+ vmware_hypercall5(VMWARE_CMD_MESSAGE | VMWARE_MSG_CLOSE, 0,
+ (u32)channel->id << 16, channel->cookie_high,
+ channel->cookie_low, &info);
+
+ return info & VMWARE_MSG_STATUS_SUCCESS ? 0 : -EIO;
+}
+
+static int vmware_log_send_once(const struct vmware_rpc_channel *channel,
+ const char *buffer, size_t length)
+{
+ u32 info;
+
+ vmware_hypercall5(VMWARE_CMD_MESSAGE | VMWARE_MSG_SENDSIZE, length,
+ (u32)channel->id << 16, channel->cookie_high,
+ channel->cookie_low, &info);
+ if (!(info & VMWARE_MSG_STATUS_SUCCESS))
+ return info & VMWARE_MSG_STATUS_CPT ? -EAGAIN : -EIO;
+
+ while (length) {
+ size_t bytes = min_t(size_t, length, sizeof(u32));
+ u32 word = 0;
+
+ memcpy(&word, buffer, bytes);
+ vmware_hypercall5(VMWARE_CMD_MESSAGE | VMWARE_MSG_SENDPAYLOAD,
+ word, (u32)channel->id << 16,
+ channel->cookie_high, channel->cookie_low,
+ &info);
+ if (!(info & VMWARE_MSG_STATUS_SUCCESS))
+ return info & VMWARE_MSG_STATUS_CPT ? -EAGAIN : -EIO;
+
+ buffer += bytes;
+ length -= bytes;
+ }
+
+ return 0;
+}
+
+static int vmware_log_send(const struct vmware_rpc_channel *channel,
+ const char *buffer, size_t length)
+{
+ int attempt, ret;
+
+ for (attempt = 0; attempt < VMWARE_LOG_ATTEMPTS; attempt++) {
+ ret = vmware_log_send_once(channel, buffer, length);
+ if (ret != -EAGAIN)
+ return ret;
+ }
+
+ return -EAGAIN;
+}
+
+static int vmware_log_rpc(const char *buffer, size_t length)
+{
+ struct vmware_rpc_channel channel;
+ int close_ret, ret;
+
+ ret = vmware_log_open(&channel);
+ if (ret)
+ return ret;
+
+ ret = vmware_log_send(&channel, buffer, length);
+ close_ret = vmware_log_close(&channel);
+ if (!ret && close_ret)
+ ret = close_ret;
+
+ return ret;
+}
+
+static struct page *vmware_panic_page;
+static bool vmware_record_panic_msg;
+
+static int vmware_panic_log_notify(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct kmsg_dump_iter iter;
+ char *buffer = page_address(vmware_panic_page);
+ size_t length = 0;
+
+ if (!READ_ONCE(vmware_record_panic_msg))
+ return NOTIFY_DONE;
+
+ memcpy(buffer, VMWARE_LOG_PREFIX, VMWARE_LOG_PREFIX_LEN);
+ kmsg_dump_rewind(&iter);
+ (void)kmsg_dump_get_buffer(&iter, true,
+ buffer + VMWARE_LOG_PREFIX_LEN,
+ VMWARE_LOG_BUF_SIZE - VMWARE_LOG_PREFIX_LEN,
+ &length);
+ (void)vmware_log_rpc(buffer, length + VMWARE_LOG_PREFIX_LEN);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block vmware_panic_log_nb = {
+ .notifier_call = vmware_panic_log_notify,
+};
+
+static int __init vmware_panic_log_init(void)
+{
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_PRINTK) ||
+ !hypervisor_is_type(X86_HYPER_VMWARE))
+ return 0;
+
+ vmware_record_panic_msg =
+ !cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT);
+
+ vmware_panic_page = alloc_pages(GFP_KERNEL,
+ get_order(VMWARE_LOG_BUF_SIZE));
+ if (!vmware_panic_page) {
+ pr_err("failed to allocate panic log buffer\n");
+ return 0;
+ }
+
+ ret = atomic_notifier_chain_register(&panic_notifiers_platform_list,
+ &vmware_panic_log_nb);
+ if (ret) {
+ pr_err("failed to register panic log notifier: %d\n", ret);
+ __free_pages(vmware_panic_page, get_order(VMWARE_LOG_BUF_SIZE));
+ vmware_panic_page = NULL;
+ }
+
+ return 0;
+}
+early_initcall(vmware_panic_log_init);
+
#ifdef CONFIG_PARAVIRT
static struct cyc2ns_data vmware_cyc2ns __ro_after_init;
static bool vmw_sched_clock __initdata = true;
next prev parent reply other threads:[~2026-11-09 5:48 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-09 5:47 [PATCH v3 0/4] panic, x86/vmware: Preserve crash logs before kdump Zack Rusin
2026-11-09 5:47 ` [PATCH v3 1/4] panic: Add a platform panic notifier list Zack Rusin
2026-11-09 5:47 ` Zack Rusin [this message]
2026-11-09 5:47 ` [PATCH v3 3/4] x86/vmware: Add the vmware_record_panic_msg sysctl Zack Rusin
2026-11-09 5:47 ` [PATCH v3 4/4] x86/vmware: Report guest crashes after kmsg dumpers Zack Rusin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b4befd89cc0b5844f499606b7d42f13cdb37046a.1794201807.git.zack.rusin@broadcom.com \
--to=zack.rusin@broadcom.com \
--cc=ajay.kaher@broadcom.com \
--cc=akpm@linux-foundation.org \
--cc=alexey.makhalov@broadcom.com \
--cc=baoquan.he@linux.dev \
--cc=bcm-kernel-feedback-list@broadcom.com \
--cc=bo.gan@broadcom.com \
--cc=bp@alien8.de \
--cc=brads@mainlining.org \
--cc=brennan.lamoreaux@broadcom.com \
--cc=corbet@lwn.net \
--cc=dave.hansen@linux.intel.com \
--cc=gpiccoli@igalia.com \
--cc=hpa@zytor.com \
--cc=ian.forbes@broadcom.com \
--cc=joel.granados@kernel.org \
--cc=john.ogness@linutronix.de \
--cc=kees@kernel.org \
--cc=kexec@lists.infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=maaz.mombasawala@broadcom.com \
--cc=mhklinux@outlook.com \
--cc=mingo@redhat.com \
--cc=pasha.tatashin@soleen.com \
--cc=pmladek@suse.com \
--cc=pratyush@kernel.org \
--cc=rdunlap@infradead.org \
--cc=rostedt@goodmis.org \
--cc=rppt@kernel.org \
--cc=ruirui.yang@linux.dev \
--cc=senozhatsky@chromium.org \
--cc=skhan@linuxfoundation.org \
--cc=stephen.s.brennan@oracle.com \
--cc=tglx@kernel.org \
--cc=virtualization@lists.linux.dev \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®