On Wed, 25 Feb 2026, at 23:27, Mukesh R wrote:
> On 2/21/26 08:43, Ard Biesheuvel wrote:
>> Just spotted this code in v7.0-rc
>>
>> On Wed, 10 Sep 2025, at 02:10, Mukesh Rathor wrote:
>> ...
>>
>>> +static asmlinkage void __noreturn hv_crash_c_entry(void)
>>
>> 'asmlinkage' means that the function may be called from another compilation
>> unit written in assembler, but it doesn't actually evaluate to anything in
>> most cases. Combining it with 'static' makes no sense whatsoever.
>
> 'static' means scope is limited to the file. Common in cases where function
> pointers are used, like here in this file way below.
>
> Like the comment says:
> "This is the C entry point from the asm glue code after...."
>
> IOW, called from assembly function (asm == assembly).
>
I wasn't asking you to explain what 'static' means. I was explaining to you
that asmlinkage means 'external linkage' whereas 'static' means the opposite,
and so combining them makes no sense.
>>
>>> +{
>>> + struct hv_crash_ctxt *ctxt = &hv_crash_ctxt;
>>> +
>>> + /* first thing, restore kernel gdt */
>>> + native_load_gdt(&ctxt->gdtr);
>>> +
>>> + asm volatile("movw %%ax, %%ss" : : "a"(ctxt->ss));
>>> + asm volatile("movq %0, %%rsp" : : "m"(ctxt->rsp));
>>> +
>>
>> This code is truly very broken. You cannot enter a C function without a
>> stack, and assign RSP half way down the function. Especially after
>> allocating local variables and/or calling other functions - it may happen to
>> work in most cases, but it is very fragile. (Other architectures have the
>> concept of 'naked' functions for this purpose but x86 does not)
>
> Local variable refers to static bss struct. IOW,
>
> asm volatile("movq %0, %%rsp" : : "m"(ctxt->rsp));
>
> same as:
> asm volatile("movq %0, %%rsp" : : "m"(&hv_crash_ctxt.rsp));
>
>
No, it is *not* the same. In practice, the compiler might perform this
substitution, but there is no guarantee that this happens.
>> IOW, this whole function should be written in asm.
>>> + 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));
>>> +
>>> + native_wrmsrq(MSR_IA32_CR_PAT, ctxt->pat);
>>> + asm volatile("movq %0, %%cr0" : : "r"(ctxt->cr0));
>>> +
>>> + asm volatile("movq %0, %%cr8" : : "r"(ctxt->cr8));
>>> + asm volatile("movq %0, %%cr4" : : "r"(ctxt->cr4));
>>> + asm volatile("movq %0, %%cr2" : : "r"(ctxt->cr4));
>>> +
>>> + native_load_idt(&ctxt->idtr);
>>> + native_wrmsrq(MSR_GS_BASE, ctxt->gsbase);
>>> + native_wrmsrq(MSR_EFER, ctxt->efer);
>>> +
>>> + /* 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,
>>
>> You just switched to __KERNEL_CS via the stack.
>
> compiler doesn't know that.
>
So? But does it means to 'be in asmlinkage' in your interpretation? Did you
check what 'asmlinkage' actually evaluates to?
I am not asking you to justify why this broken code works in practice, I am
asking you to fix it.
>>> hence make a C function
>>> + * call which will buy stack frame to restore the tss or clear PT
>>> entry.
>>> + */
>>
>> Where does one buy a stack frame?
>
> A stack market :). Callee will create stack frame now that rsp is
> setup.
>
This code is beyond broken. Please propose fixes rather than try to argue why
carrying broken code like this is acceptable.