The hypercall page populated with instructions by the hypervisor is not IBT
authoranton <anton@openbsd.org>
Wed, 5 Jul 2023 18:23:10 +0000 (18:23 +0000)
committeranton <anton@openbsd.org>
Wed, 5 Jul 2023 18:23:10 +0000 (18:23 +0000)
compatible due to lack of endbr64. Replace the indirect call with a new
hv_hypercall_trampoline() routine which jumps to the hypercall page without any
indirection.

Allows me to boot OpenBSD using Hyper-V on Windows 11 again.

ok guenther@

sys/arch/amd64/amd64/locore.S
sys/dev/pv/hyperv.c

index 677c816..ec41559 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: locore.S,v 1.134 2023/04/17 00:14:59 deraadt Exp $    */
+/*     $OpenBSD: locore.S,v 1.135 2023/07/05 18:23:10 anton Exp $      */
 /*     $NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $     */
 
 /*
@@ -1149,20 +1149,28 @@ NENTRY(rdmsr_resume)
        lfence
 END(rdmsr_safe)
 
-#if NXEN > 0
+#if NHYPERV > 0
+/* uint64_t hv_hypercall_trampoline(uint64_t control, paddr_t input, paddr_t output) */
+NENTRY(hv_hypercall_trampoline)
+       endbr64
+       mov     %rdx, %r8
+       mov     %rsi, %rdx
+       mov     %rdi, %rcx
+       jmp     hv_hypercall_page
+END(hv_hypercall_trampoline)
        /* Hypercall page needs to be page aligned */
        .text
        .align  NBPG, 0xcc
-       .globl  xen_hypercall_page
-xen_hypercall_page:
+       .globl  hv_hypercall_page
+hv_hypercall_page:
        .skip   0x1000, 0xcc
-#endif /* NXEN > 0 */
+#endif /* NHYPERV > 0 */
 
-#if NHYPERV > 0
+#if NXEN > 0
        /* Hypercall page needs to be page aligned */
        .text
        .align  NBPG, 0xcc
-       .globl  hv_hypercall_page
-hv_hypercall_page:
+       .globl  xen_hypercall_page
+xen_hypercall_page:
        .skip   0x1000, 0xcc
 #endif /* NXEN > 0 */
index 08a713d..da9bf3a 100644 (file)
@@ -407,9 +407,8 @@ hv_hypercall(struct hv_softc *sc, uint64_t control, void *input,
        }
 
 #ifdef __amd64__
-       __asm__ volatile ("mov %0, %%r8" : : "r" (output_pa) : "r8");
-       __asm__ volatile ("call *%3" : "=a" (status) : "c" (control),
-           "d" (input_pa), "m" (sc->sc_hc));
+       extern uint64_t hv_hypercall_trampoline(uint64_t, paddr_t, paddr_t);
+       status = hv_hypercall_trampoline(control, input_pa, output_pa);
 #else  /* __i386__ */
        {
                uint32_t control_hi = control >> 32;