[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen master] tools/hvmloader: Wake APs with hypercalls rather than INIT+SIPI+SIPI



commit 752ec9a9b195759aa7f6059e65155d404654e316
Author:     Alejandro Vallejo <alejandro.vallejo@xxxxxxxxx>
AuthorDate: Wed May 8 13:39:23 2024 +0100
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Thu May 9 18:19:49 2024 +0100

    tools/hvmloader: Wake APs with hypercalls rather than INIT+SIPI+SIPI
    
    ... in order to change how LAPIC_ID handling works.  Importantly, this 
allows
    us to start APs by vCPU ID in order to query the LAPIC_ID, rather than 
needing
    to know the APIC_ID in order to wake them.
    
    Other improvements avoid:
     * The 16bit entry stub
     * A LMSW insn, which has no decode assist on AMD and needs emulating fully
     * 13 vLAPIC emulations when 3 hypercalls can do
     * 4 pages of stack when 1 in plenty
    
    Signed-off-by: Alejandro Vallejo <alejandro.vallejo@xxxxxxxxx>
    Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 tools/firmware/hvmloader/smp.c | 112 +++++++++++++++++------------------------
 1 file changed, 46 insertions(+), 66 deletions(-)

diff --git a/tools/firmware/hvmloader/smp.c b/tools/firmware/hvmloader/smp.c
index 082b17f138..6ebf0b60fa 100644
--- a/tools/firmware/hvmloader/smp.c
+++ b/tools/firmware/hvmloader/smp.c
@@ -22,88 +22,71 @@
 #include "util.h"
 #include "config.h"
 #include "apic_regs.h"
+#include "hypercall.h"
 
-#define AP_BOOT_EIP 0x1000
-extern char ap_boot_start[], ap_boot_end[];
+#include <xen/asm/x86-defns.h>
+#include <xen/hvm/hvm_vcpu.h>
+
+#include <xen/vcpu.h>
 
 static int ap_callin, ap_cpuid;
 
-asm (
-    "    .text                       \n"
-    "    .code16                     \n"
-    "ap_boot_start: .code16          \n"
-    "    mov   %cs,%ax               \n"
-    "    mov   %ax,%ds               \n"
-    "    lgdt  gdt_desr-ap_boot_start\n"
-    "    xor   %ax, %ax              \n"
-    "    inc   %ax                   \n"
-    "    lmsw  %ax                   \n"
-    "    ljmpl $0x08,$1f             \n"
-    "gdt_desr:                       \n"
-    "    .word gdt_end - gdt - 1     \n"
-    "    .long gdt                   \n"
-    "ap_boot_end: .code32            \n"
-    "1:  mov   $0x10,%eax            \n"
-    "    mov   %eax,%ds              \n"
-    "    mov   %eax,%es              \n"
-    "    mov   %eax,%ss              \n"
-    "    movl  $stack_top,%esp       \n"
-    "    movl  %esp,%ebp             \n"
-    "    call  ap_start              \n"
-    "1:  hlt                         \n"
-    "    jmp  1b                     \n"
-    "                                \n"
-    "    .align 8                    \n"
-    "gdt:                            \n"
-    "    .quad 0x0000000000000000    \n"
-    "    .quad 0x00cf9a000000ffff    \n" /* 0x08: Flat code segment */
-    "    .quad 0x00cf92000000ffff    \n" /* 0x10: Flat data segment */
-    "gdt_end:                        \n"
-    "                                \n"
-    "    .bss                        \n"
-    "    .align    8                 \n"
-    "stack:                          \n"
-    "    .skip    0x4000             \n"
-    "stack_top:                      \n"
-    "    .text                       \n"
-    );
-
-void ap_start(void); /* non-static avoids unused-function compiler warning */
-/*static*/ void ap_start(void)
+static void ap_start(void)
 {
     printf(" - CPU%d ... ", ap_cpuid);
     cacheattr_init();
     printf("done.\n");
+
+    if ( !ap_cpuid ) /* Used on the BSP too */
+        return;
+
     wmb();
     ap_callin = 1;
-}
 
-static void lapic_wait_ready(void)
-{
-    while ( lapic_read(APIC_ICR) & APIC_ICR_BUSY )
-        cpu_relax();
+    /* After this point, the BSP will shut us down. */
+
+    for ( ;; )
+        asm volatile ( "hlt" );
 }
 
 static void boot_cpu(unsigned int cpu)
 {
-    unsigned int icr2 = SET_APIC_DEST_FIELD(LAPIC_ID(cpu));
+    static uint8_t ap_stack[PAGE_SIZE] __attribute__ ((aligned (16)));
+    static struct vcpu_hvm_context ap;
 
     /* Initialise shared variables. */
     ap_cpuid = cpu;
     ap_callin = 0;
     wmb();
 
-    /* Wake up the secondary processor: INIT-SIPI-SIPI... */
-    lapic_wait_ready();
-    lapic_write(APIC_ICR2, icr2);
-    lapic_write(APIC_ICR, APIC_DM_INIT);
-    lapic_wait_ready();
-    lapic_write(APIC_ICR2, icr2);
-    lapic_write(APIC_ICR, APIC_DM_STARTUP | (AP_BOOT_EIP >> 12));
-    lapic_wait_ready();
-    lapic_write(APIC_ICR2, icr2);
-    lapic_write(APIC_ICR, APIC_DM_STARTUP | (AP_BOOT_EIP >> 12));
-    lapic_wait_ready();
+    /* Wake up the secondary processor */
+    ap = (struct vcpu_hvm_context) {
+        .mode = VCPU_HVM_MODE_32B,
+        .cpu_regs.x86_32 = {
+            .eip = (unsigned long)ap_start,
+            .esp = (unsigned long)ap_stack + ARRAY_SIZE(ap_stack),
+
+            /* Protected Mode, no paging. */
+            .cr0 = X86_CR0_PE,
+
+            /* 32bit Flat Mode */
+            .cs_limit = -1U,
+            .ds_limit = -1U,
+            .ss_limit = -1U,
+            .es_limit = -1U,
+            .tr_limit = 0x67,
+            .cs_ar = 0xc9b,
+            .ds_ar = 0xc93,
+            .es_ar = 0xc93,
+            .ss_ar = 0xc93,
+            .tr_ar = 0x8b,
+        },
+    };
+
+    if ( hypercall_vcpu_op(VCPUOP_initialise, cpu, &ap) )
+        BUG();
+    if ( hypercall_vcpu_op(VCPUOP_up, cpu, NULL) )
+        BUG();
 
     /*
      * Wait for the secondary processor to complete initialisation.
@@ -113,17 +96,14 @@ static void boot_cpu(unsigned int cpu)
         cpu_relax();
 
     /* Take the secondary processor offline. */
-    lapic_write(APIC_ICR2, icr2);
-    lapic_write(APIC_ICR, APIC_DM_INIT);
-    lapic_wait_ready();    
+    if ( hypercall_vcpu_op(VCPUOP_down, cpu, NULL) )
+        BUG();
 }
 
 void smp_initialise(void)
 {
     unsigned int i, nr_cpus = hvm_info->nr_vcpus;
 
-    memcpy((void *)AP_BOOT_EIP, ap_boot_start, ap_boot_end - ap_boot_start);
-
     printf("Multiprocessor initialisation:\n");
     ap_start();
     for ( i = 1; i < nr_cpus; i++ )
--
generated by git-patchbot for /home/xen/git/xen.git#master



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.