From nobody Tue Apr 7 15:26:07 2026 Received: from mail-ed1-f74.google.com (mail-ed1-f74.google.com [209.85.208.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 066E0314B61 for ; Thu, 26 Feb 2026 09:51:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772099463; cv=none; b=M7vRG6C320bh7Bz7pp59l75TL/7afjImbGq0pcl3+GaJDHaBM7Ufef6bjs+/YC4DRt9SMupzhGLlQH8BPeE9DIQWCFsEyqQM3q8orbh8Ju9ROc3xkXuHHEBfQUsTwaDPEUAPm/BA9q9+qiQjyE8slvXaJtvjoqgFhlCM419M/6I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772099463; c=relaxed/simple; bh=uxteyQ3fL17gew0uasQskuQXwAnlJW6j4RzRyg/Wkfw=; h=Date:Mime-Version:Message-ID:Subject:From:To:Cc:Content-Type; b=DupZK4ykGuxCMsuM5aZdXRLoHJ1kes38KSfVPXxs20hdXMi8NJGPa7iP9/7Az4vm3j/kYqQsQD7eF2nBOkpU2OIhSp1mNB956rfUwjcgIjFk8HERj7MfARAr6oTztHJjiZJeHotGEnerguCncthRmKrNTXshlMkGVhLs2pdK7w0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--ardb.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Y32nwXxT; arc=none smtp.client-ip=209.85.208.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--ardb.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Y32nwXxT" Received: by mail-ed1-f74.google.com with SMTP id 4fb4d7f45d1cf-65fa9f433bdso886437a12.3 for ; Thu, 26 Feb 2026 01:51:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1772099460; x=1772704260; darn=vger.kernel.org; h=cc:to:from:subject:message-id:mime-version:date:from:to:cc:subject :date:message-id:reply-to; bh=r9siQRAI82XGd/XT7KGSnYfEQ1ezHfSjxlnQISpmf08=; b=Y32nwXxTUza9y17nVfFPdp3G8TzTZNSEJyLQlzdxN8CC8ieGGQscVkb0SiGPhoEpIn OacudqyFXkSwjv+pG1FJGZS56zg2n9zgcIkQTn348ErCbeymIcRBCThDlFNtV5mQxWRv 6TortUQryen5UxAcsBY/W2rQE1GevbCgkdGy7V9OGi3+UPLxmuC8//Dcs++aEQa8k4n4 oeCuY2POTw+75ygdS7j0vWIQaKkbqki5uxSe3ytC59ezqQCZ20SwDFoNdhbQefMagDLS 6n5V4qF7xQLltM5qAw7dfN9RfAUBUr5xCY5MayWpi49hfqGGzU4ZgQ/oPVUaWILJ55+I ScOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772099460; x=1772704260; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=r9siQRAI82XGd/XT7KGSnYfEQ1ezHfSjxlnQISpmf08=; b=WNNW81wFpEN1FmEnXjv1Tk0fd3ArlIbN+prLebzPGDA6jF3M2fCVfiVJG/tsExUnhp 498mdVJictgwKVopuAVKD8t5HMx5PmBRFDRtYfR+allOr8StXgUQKo0LHPMa08iOKIUJ xcaOYrFUwBzUkNIEevukDaZ4z5DP7UGyv8mmwG38OvhGc/YvCGg5gfL9nEer2Wr6XAmr gyXy7AW2Cuq2fJV/OeX4JI3PWFXOYazeoyXAbNUUN/KyxOMmcuWElAFIm7xzXRiss5Wx FJ6zpGKZMq6hQmzN71jt9eyDU+ju0meXbwlFWpeMqoXg8nqqsT0v1+syQ+R+E510Emru WsFw== X-Gm-Message-State: AOJu0Yw6AvbevVmeceCsckdBz3Jtfxp6m/J6KOghYd5J60wWM0r/xrxF XwBB2xlSYUhe0ymktQJDBMwFlBMRyPqVwaNQF37nLZ83oXwI+8Osxpqch+4hc+m47JVzep3bQJb ebI2HM95xkOAn1pShanuUg5T0QaQ7603xXdJHBSVmmbWHdCkeb1yM75S/ImeSQakgjXjSiV9QhP duQyYprljsM+/S+1leseE2gMz4K/8YnjABMg== X-Received: from edtn17.prod.google.com ([2002:aa7:db51:0:b0:658:31e3:4242]) (user=ardb job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6402:510f:b0:65f:7f90:fb89 with SMTP id 4fb4d7f45d1cf-65fb6c6ea8dmr913495a12.17.1772099460068; Thu, 26 Feb 2026 01:51:00 -0800 (PST) Date: Thu, 26 Feb 2026 10:50:57 +0100 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 X-Developer-Signature: v=1; a=openpgp-sha256; l=5779; i=ardb@kernel.org; h=from:subject; bh=sPCEU5F7szViGGqi8+aB6tyXk98FodC657hmbHdoY/0=; b=owGbwMvMwCVmkMcZplerG8N4Wi2JIXOBeGOn6XeFsKeSUza7VTw7Zlk3pUm006MqvMQy2Gz35 S1Bhm87SlkYxLgYZMUUWQRm/3238/REqVrnWbIwc1iZQIYwcHEKwEQaXzP8s3NdqDtf46uXrl9D 6Zwj9frMNyT3a+5fwsKfzM70yz5HipHh4+lsnjoWXilOlXkebgyPtnWFnz/9xWiWZOd9MyHOw16 MAA== X-Mailer: git-send-email 2.53.0.414.gf7e9f6c205-goog Message-ID: <20260226095056.46410-2-ardb+git@google.com> Subject: [RFT PATCH] x86/hyperv: Use __naked attribute to fix stackless C function From: Ard Biesheuvel To: linux-kernel@vger.kernel.org Cc: Ard Biesheuvel , Mukesh Rathor , "K. Y. Srinivasan" , Haiyang Zhang , Wei Liu , Dexuan Cui , Long Li , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Uros Bizjak , linux-hyperv@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ard Biesheuvel hv_crash_c_entry() is a C function that is entered without a stack, and this is only allowed for functions that have the __naked attribute, which informs the compiler that it must not emit the usual prologue and epilogue or emit any other kind of instrumentation that relies on a stack frame. So split up the function, and set the __naked attribute on the initial part that sets up the stack, GDT, IDT and other pieces that are needed for ordinary C execution. Given that function calls are not permitted either, use the existing long return coded in an asm() block to call the second part of the function, which is an ordinary function that is permitted to call other functions as usual. Fixes: 94212d34618c ("x86/hyperv: Implement hypervisor RAM collection into = vmcore") Signed-off-by: Ard Biesheuvel --- Build tested only. Cc: Mukesh Rathor Cc: "K. Y. Srinivasan" Cc: Haiyang Zhang Cc: Wei Liu Cc: Dexuan Cui Cc: Long Li Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: Dave Hansen Cc: "H. Peter Anvin" Cc: Uros Bizjak Cc: linux-hyperv@vger.kernel.org arch/x86/hyperv/hv_crash.c | 80 ++++++++++---------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/arch/x86/hyperv/hv_crash.c b/arch/x86/hyperv/hv_crash.c index a78e4fed5720..d77766e8d37e 100644 --- a/arch/x86/hyperv/hv_crash.c +++ b/arch/x86/hyperv/hv_crash.c @@ -107,14 +107,12 @@ static void __noreturn hv_panic_timeout_reboot(void) cpu_relax(); } =20 -/* This cannot be inlined as it needs stack */ -static noinline __noclone void hv_crash_restore_tss(void) +static void hv_crash_restore_tss(void) { load_TR_desc(); } =20 -/* This cannot be inlined as it needs stack */ -static noinline void hv_crash_clear_kernpt(void) +static void hv_crash_clear_kernpt(void) { pgd_t *pgd; p4d_t *p4d; @@ -125,6 +123,25 @@ static noinline void hv_crash_clear_kernpt(void) native_p4d_clear(p4d); } =20 + +static void __noreturn hv_crash_handle(void) +{ + hv_crash_restore_tss(); + hv_crash_clear_kernpt(); + + /* we are now fully in devirtualized normal kernel mode */ + __crash_kexec(NULL); + + hv_panic_timeout_reboot(); +} + +/* + * __naked functions do not permit function calls, not even to __always_in= line + * functions that only contain asm() blocks themselves. So use a macro ins= tead. + */ +#define hv_wrmsr(msr, val) \ + asm("wrmsr" :: "c"(msr), "a"((u32)val), "d"((u32)(val >> 32)) : "memory") + /* * This is the C entry point from the asm glue code after the disable hype= rcall. * We enter here in IA32-e long mode, ie, full 64bit mode running on kernel @@ -133,49 +150,36 @@ static noinline void hv_crash_clear_kernpt(void) * available. We restore kernel GDT, and rest of the context, and continue * to kexec. */ -static asmlinkage void __noreturn hv_crash_c_entry(void) +static void __naked hv_crash_c_entry(void) { - struct hv_crash_ctxt *ctxt =3D &hv_crash_ctxt; - /* first thing, restore kernel gdt */ - native_load_gdt(&ctxt->gdtr); + asm volatile("lgdt %0" : : "m" (hv_crash_ctxt.gdtr)); =20 - asm volatile("movw %%ax, %%ss" : : "a"(ctxt->ss)); - asm volatile("movq %0, %%rsp" : : "m"(ctxt->rsp)); + asm volatile("movw %%ax, %%ss" : : "a"(hv_crash_ctxt.ss)); + asm volatile("movq %0, %%rsp" : : "m"(hv_crash_ctxt.rsp)); =20 - asm volatile("movw %%ax, %%ds" : : "a"(ctxt->ds)); - asm volatile("movw %%ax, %%es" : : "a"(ctxt->es)); - asm volatile("movw %%ax, %%fs" : : "a"(ctxt->fs)); - asm volatile("movw %%ax, %%gs" : : "a"(ctxt->gs)); + asm volatile("movw %%ax, %%ds" : : "a"(hv_crash_ctxt.ds)); + asm volatile("movw %%ax, %%es" : : "a"(hv_crash_ctxt.es)); + asm volatile("movw %%ax, %%fs" : : "a"(hv_crash_ctxt.fs)); + asm volatile("movw %%ax, %%gs" : : "a"(hv_crash_ctxt.gs)); =20 - native_wrmsrq(MSR_IA32_CR_PAT, ctxt->pat); - asm volatile("movq %0, %%cr0" : : "r"(ctxt->cr0)); + hv_wrmsr(MSR_IA32_CR_PAT, hv_crash_ctxt.pat); + asm volatile("movq %0, %%cr0" : : "r"(hv_crash_ctxt.cr0)); =20 - asm volatile("movq %0, %%cr8" : : "r"(ctxt->cr8)); - asm volatile("movq %0, %%cr4" : : "r"(ctxt->cr4)); - asm volatile("movq %0, %%cr2" : : "r"(ctxt->cr4)); + asm volatile("movq %0, %%cr8" : : "r"(hv_crash_ctxt.cr8)); + asm volatile("movq %0, %%cr4" : : "r"(hv_crash_ctxt.cr4)); + asm volatile("movq %0, %%cr2" : : "r"(hv_crash_ctxt.cr4)); =20 - native_load_idt(&ctxt->idtr); - native_wrmsrq(MSR_GS_BASE, ctxt->gsbase); - native_wrmsrq(MSR_EFER, ctxt->efer); + asm volatile("lidt %0" : : "m" (hv_crash_ctxt.idtr)); + hv_wrmsr(MSR_GS_BASE, hv_crash_ctxt.gsbase); + hv_wrmsr(MSR_EFER, hv_crash_ctxt.efer); =20 /* restore the original kernel CS now via far return */ - asm volatile("movzwq %0, %%rax\n\t" - "pushq %%rax\n\t" - "pushq $1f\n\t" - "lretq\n\t" - "1:nop\n\t" : : "m"(ctxt->cs) : "rax"); - - /* We are in asmlinkage without stack frame, hence make C function - * calls which will buy stack frames. - */ - hv_crash_restore_tss(); - hv_crash_clear_kernpt(); - - /* we are now fully in devirtualized normal kernel mode */ - __crash_kexec(NULL); - - hv_panic_timeout_reboot(); + asm volatile("pushq %q0 \n\t" + "leaq %c1(%%rip), %q0 \n\t" + "pushq %q0 \n\t" + "lretq \n\t" + :: "a"(hv_crash_ctxt.cs), "i"(hv_crash_handle)); } /* Tell gcc we are using lretq long jump in the above function intentional= ly */ STACK_FRAME_NON_STANDARD(hv_crash_c_entry); --=20 2.53.0.414.gf7e9f6c205-goog