From a67f913d6635772af746fc215066e3d510ae25d1 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 15 Mar 2024 13:12:22 +0000 Subject: [librm] Add support for installing a startup IPI handler Application processors are started via INIT and SIPI interprocessor interrupts: the INIT places the processor into a "wait for SIPI" state, and the SIPI then starts the processor in real mode at a page-aligned address derived from the SIPI vector number. Add support for installing a real-mode SIPI handler that will switch the CPU into protected mode with flat physical addressing, load initial register contents, and then jump to the address of a protected-mode SIPI handler. No stack pointer is set up, to avoid the need to allocate stack space for each available processor. We use 32-bit physical addressing in order to minimise the changes required for a 64-bit build. The existing long mode transition code relies on the existence of the stack, so we cannot easily switch the application processor into long mode. We could use 32-bit virtual addressing, but this runtime environment does not currently exist outside of librm.S itself in a 64-bit build, and using it would complicate the implementation of the protected-mode SIPI handler. Signed-off-by: Michael Brown --- src/arch/x86/transitions/librm.S | 67 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'src/arch/x86/transitions/librm.S') diff --git a/src/arch/x86/transitions/librm.S b/src/arch/x86/transitions/librm.S index 39431324..a93b0251 100644 --- a/src/arch/x86/transitions/librm.S +++ b/src/arch/x86/transitions/librm.S @@ -1632,3 +1632,70 @@ init_pages: /* Return */ ret + +/**************************************************************************** + * sipi (real-mode jump) + * + * Handle Startup IPI + * + * This code must be copied to a page-aligned boundary in base memory. + * It will be entered with %cs:0000 pointing to the start of the code. + * The stack pointer is undefined and so no stack space can be used. + * + **************************************************************************** + */ + .section ".text16.sipi", "ax", @progbits + .code16 + .globl sipi +sipi: + /* Retrieve rm_ds from copy */ + movw %cs:( sipi_ds - sipi ), %ax + movw %ax, %ds + + /* Load GDT and switch to protected mode */ + data32 lgdt gdtr + movl %cr0, %eax + orb $CR0_PE, %al + movl %eax, %cr0 + data32 ljmp $VIRTUAL_CS, $VIRTUAL(1f) + + /* Copy of rm_ds required to access GDT */ + .globl sipi_ds +sipi_ds: + .word 0 + + /* Length of real-mode SIPI handler to be copied */ + .globl sipi_len + .equ sipi_len, . - sipi + + .section ".text.sipi", "ax", @progbits + .code32 +1: /* Set up protected-mode segment registers (with no stack) */ + movw $VIRTUAL_DS, %ax + movw %ax, %ds + movw %ax, %ss + movw $PHYSICAL_DS, %ax + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + + /* Load register state and clear stack pointer */ + movl $VIRTUAL(sipi_regs), %esp + popal + + /* Switch to flat physical addressing */ + movw $PHYSICAL_DS, %sp + movw %sp, %ds + movw %sp, %ss + + /* Clear stack pointer */ + xorl %esp, %esp + + /* Jump to protected-mode SIPI handler */ + ljmp %cs:*VIRTUAL(sipi_handler) + + /* Protected-mode SIPI handler vector */ + .section ".data.sipi_handler", "aw", @progbits + .globl sipi_handler +sipi_handler: + .long 0, PHYSICAL_CS -- cgit v1.2.3-55-g7522