iPXE
bios_mp.c File Reference

BIOS multiprocessor API implementation. More...

#include <registers.h>
#include <librm.h>
#include <ipxe/uaccess.h>
#include <ipxe/timer.h>
#include <ipxe/msr.h>
#include <ipxe/mp.h>

Go to the source code of this file.

Macros

#define MSR_APIC_BASE   0x0000001b
 Local APIC base address MSR.
#define MSR_APIC_BASE_X2APIC   0x400
 Local APIC is in x2APIC mode.
#define MSR_APIC_BASE_MASK   ( ~0xfffULL )
 Local APIC base address mask.
#define APIC_ICR   0x0300
 Interrupt command register.
#define MSR_X2APIC_ICR   0x830
 Interrupt command register (x2APIC)
#define APIC_ICR_ALL_NOT_SELF   0x000c0000
 Interrupt command register: send to all excluding self.
#define APIC_ICR_LEVEL   0x00008000
 Interrupt command register: level mode.
#define APIC_ICR_LEVEL_ASSERT   0x00004000
 Interrupt command register: level asserted.
#define APIC_ICR_INIT   0x00000500
 Interrupt command register: INIT.
#define APIC_ICR_SIPI(vector)
 Interrupt command register: SIPI.
#define IPI_WAIT_MS   10
 Time to wait for an IPI to complete.
#define SIPI_VECTOR   0x08
 Startup IPI vector.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
void __asmcall mp_jump (mp_addr_t func, mp_addr_t opaque)
 Protected-mode startup IPI handler.
static void bios_mp_exec_boot (mp_func_t func, void *opaque)
 Execute a multiprocessor function on the boot processor.
static void bios_mp_ipi (void *apic, int x2apic, uint32_t icr)
 Send an interprocessor interrupt.
static void bios_mp_start_all (mp_func_t func, void *opaque)
 Start a multiprocessor function on all application processors.
 PROVIDE_MPAPI_INLINE (pcbios, mp_address)
 PROVIDE_MPAPI (pcbios, mp_exec_boot, bios_mp_exec_boot)
 PROVIDE_MPAPI (pcbios, mp_start_all, bios_mp_start_all)

Detailed Description

BIOS multiprocessor API implementation.

Definition in file bios_mp.c.

Macro Definition Documentation

◆ MSR_APIC_BASE

#define MSR_APIC_BASE   0x0000001b

Local APIC base address MSR.

Definition at line 40 of file bios_mp.c.

Referenced by bios_mp_ipi(), and bios_mp_start_all().

◆ MSR_APIC_BASE_X2APIC

#define MSR_APIC_BASE_X2APIC   0x400

Local APIC is in x2APIC mode.

Definition at line 43 of file bios_mp.c.

Referenced by bios_mp_start_all().

◆ MSR_APIC_BASE_MASK

#define MSR_APIC_BASE_MASK   ( ~0xfffULL )

Local APIC base address mask.

Definition at line 46 of file bios_mp.c.

Referenced by bios_mp_start_all().

◆ APIC_ICR

#define APIC_ICR   0x0300

Interrupt command register.

Definition at line 49 of file bios_mp.c.

Referenced by bios_mp_ipi().

◆ MSR_X2APIC_ICR

#define MSR_X2APIC_ICR   0x830

Interrupt command register (x2APIC)

Definition at line 52 of file bios_mp.c.

Referenced by bios_mp_ipi().

◆ APIC_ICR_ALL_NOT_SELF

#define APIC_ICR_ALL_NOT_SELF   0x000c0000

Interrupt command register: send to all excluding self.

Definition at line 55 of file bios_mp.c.

Referenced by bios_mp_start_all().

◆ APIC_ICR_LEVEL

#define APIC_ICR_LEVEL   0x00008000

Interrupt command register: level mode.

Definition at line 58 of file bios_mp.c.

Referenced by bios_mp_start_all().

◆ APIC_ICR_LEVEL_ASSERT

#define APIC_ICR_LEVEL_ASSERT   0x00004000

Interrupt command register: level asserted.

Definition at line 61 of file bios_mp.c.

Referenced by bios_mp_start_all().

◆ APIC_ICR_INIT

#define APIC_ICR_INIT   0x00000500

Interrupt command register: INIT.

Definition at line 64 of file bios_mp.c.

Referenced by bios_mp_start_all().

◆ APIC_ICR_SIPI

#define APIC_ICR_SIPI ( vector)
Value:
( 0x00000600 | (vector) )
uint32_t vector
MSI-X vector.
Definition ena.h:9

Interrupt command register: SIPI.

Definition at line 67 of file bios_mp.c.

Referenced by bios_mp_start_all().

◆ IPI_WAIT_MS

#define IPI_WAIT_MS   10

Time to wait for an IPI to complete.

Definition at line 70 of file bios_mp.c.

Referenced by bios_mp_ipi().

◆ SIPI_VECTOR

#define SIPI_VECTOR   0x08

Startup IPI vector.

The real-mode startup IPI code must be copied to a page boundary in base memory. We fairly arbitrarily choose to place this at 0x8000.

Definition at line 78 of file bios_mp.c.

Referenced by bios_mp_start_all().

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ mp_jump()

void __asmcall mp_jump ( mp_addr_t func,
mp_addr_t opaque )
extern

Protected-mode startup IPI handler.

References __asmcall.

Referenced by bios_mp_start_all().

◆ bios_mp_exec_boot()

void bios_mp_exec_boot ( mp_func_t func,
void * opaque )
static

Execute a multiprocessor function on the boot processor.

Parameters
funcMultiprocessor function
opaqueOpaque data pointer

Definition at line 89 of file bios_mp.c.

89 {
90
91 /* Call multiprocessor function with physical addressing */
92 __asm__ __volatile__ ( PHYS_CODE ( "pushl %k2\n\t"
93 "pushl %k1\n\t"
94 "call *%k0\n\t"
95 "addl $8, %%esp\n\t" )
96 : : "R" ( mp_address ( mp_call ) ),
97 "R" ( mp_address ( func ) ),
98 "R" ( mp_address ( opaque ) ) );
99}
__asm__ __volatile__("call *%9" :"=a"(result), "=c"(discard_ecx), "=d"(discard_edx) :"d"(0), "a"(code), "b"(0), "c"(in_phys), "D"(0), "S"(out_phys), "m"(hypercall))
static mp_address(void *address)
Calculate address as seen by a multiprocessor function.
Definition bios_mp.h:27
void __asmcall mp_call(mp_addr_t func, mp_addr_t opaque)
Call a multiprocessor function from C code on the current CPU.
#define PHYS_CODE(asm_code_str)
Definition librm.h:167
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")

References __asm__(), __volatile__(), mp_address(), mp_call(), and PHYS_CODE.

Referenced by PROVIDE_MPAPI().

◆ bios_mp_ipi()

void bios_mp_ipi ( void * apic,
int x2apic,
uint32_t icr )
static

Send an interprocessor interrupt.

Parameters
apicAPIC base address
x2apicx2APIC mode enabled
icrInterrupt control register value

Definition at line 108 of file bios_mp.c.

108 {
109
110 /* Write ICR according to APIC/x2APIC mode */
111 DBGC ( MSR_APIC_BASE, "BIOSMP sending IPI %#08x\n", icr );
112 if ( x2apic ) {
113 wrmsr ( MSR_X2APIC_ICR, icr );
114 } else {
115 writel ( icr, ( apic + APIC_ICR ) );
116 }
117
118 /* Allow plenty of time for delivery to complete */
120}
#define MSR_APIC_BASE
Local APIC base address MSR.
Definition bios_mp.c:40
#define IPI_WAIT_MS
Time to wait for an IPI to complete.
Definition bios_mp.c:70
#define MSR_X2APIC_ICR
Interrupt command register (x2APIC)
Definition bios_mp.c:52
#define APIC_ICR
Interrupt command register.
Definition bios_mp.c:49
#define DBGC(...)
Definition compiler.h:505
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition timer.c:79
#define writel
Definition w89c840.c:160

References APIC_ICR, DBGC, IPI_WAIT_MS, mdelay(), MSR_APIC_BASE, MSR_X2APIC_ICR, and writel.

Referenced by bios_mp_start_all().

◆ bios_mp_start_all()

void bios_mp_start_all ( mp_func_t func,
void * opaque )
static

Start a multiprocessor function on all application processors.

Parameters
funcMultiprocessor function
opaqueOpaque data pointer

Definition at line 128 of file bios_mp.c.

128 {
129 struct i386_regs regs;
131 uint32_t ipi;
132 void *apic;
133 int x2apic;
134
135 /* Prepare SIPI handler */
136 regs.eax = mp_address ( func );
137 regs.edx = mp_address ( opaque );
138 setup_sipi ( SIPI_VECTOR, virt_to_phys ( mp_jump ), &regs );
139
140 /* Get local APIC base address and mode */
141 base = rdmsr ( MSR_APIC_BASE );
142 x2apic = ( base & MSR_APIC_BASE_X2APIC );
143 DBGC ( MSR_APIC_BASE, "BIOSMP local %sAPIC base %#llx\n",
144 ( x2apic ? "x2" : "" ), ( ( unsigned long long ) base ) );
145
146 /* Map local APIC */
147 apic = ioremap ( ( base & MSR_APIC_BASE_MASK ), PAGE_SIZE );
148 if ( ! apic )
149 goto err_ioremap;
150
151 /* Assert INIT IPI */
154 bios_mp_ipi ( apic, x2apic, ipi );
155
156 /* Clear INIT IPI */
158 bios_mp_ipi ( apic, x2apic, ipi );
159
160 /* Send SIPI */
162 bios_mp_ipi ( apic, x2apic, ipi );
163
164 iounmap ( apic );
165 err_ioremap:
166 /* No way to handle errors: caller must check that
167 * multiprocessor function executed as expected.
168 */
169 return;
170}
unsigned int uint32_t
Definition stdint.h:12
unsigned long long uint64_t
Definition stdint.h:13
#define APIC_ICR_LEVEL
Interrupt command register: level mode.
Definition bios_mp.c:58
#define APIC_ICR_ALL_NOT_SELF
Interrupt command register: send to all excluding self.
Definition bios_mp.c:55
void __asmcall mp_jump(mp_addr_t func, mp_addr_t opaque)
Protected-mode startup IPI handler.
static void bios_mp_ipi(void *apic, int x2apic, uint32_t icr)
Send an interprocessor interrupt.
Definition bios_mp.c:108
#define SIPI_VECTOR
Startup IPI vector.
Definition bios_mp.c:78
#define APIC_ICR_INIT
Interrupt command register: INIT.
Definition bios_mp.c:64
#define MSR_APIC_BASE_X2APIC
Local APIC is in x2APIC mode.
Definition bios_mp.c:43
#define APIC_ICR_LEVEL_ASSERT
Interrupt command register: level asserted.
Definition bios_mp.c:61
#define MSR_APIC_BASE_MASK
Local APIC base address mask.
Definition bios_mp.c:46
#define APIC_ICR_SIPI(vector)
Interrupt command register: SIPI.
Definition bios_mp.c:67
#define PAGE_SIZE
Page size.
Definition io.h:28
void * ioremap(unsigned long bus_addr, size_t len)
Map bus address as an I/O address.
void iounmap(volatile const void *io_addr)
Unmap I/O address.
uint32_t base
Base.
Definition librm.h:3
void setup_sipi(unsigned int vector, uint32_t handler, struct i386_regs *regs)
Set up startup IPI handler.
Definition librm_mgmt.c:417
struct i386_regs regs
Definition registers.h:1
A 32-bit general register dump.
Definition registers.h:62

References APIC_ICR_ALL_NOT_SELF, APIC_ICR_INIT, APIC_ICR_LEVEL, APIC_ICR_LEVEL_ASSERT, APIC_ICR_SIPI, base, bios_mp_ipi(), DBGC, ioremap(), iounmap(), mp_address(), mp_jump(), MSR_APIC_BASE, MSR_APIC_BASE_MASK, MSR_APIC_BASE_X2APIC, PAGE_SIZE, regs, setup_sipi(), and SIPI_VECTOR.

Referenced by PROVIDE_MPAPI().

◆ PROVIDE_MPAPI_INLINE()

PROVIDE_MPAPI_INLINE ( pcbios ,
mp_address  )

References mp_address().

◆ PROVIDE_MPAPI() [1/2]

PROVIDE_MPAPI ( pcbios ,
mp_exec_boot ,
bios_mp_exec_boot  )

◆ PROVIDE_MPAPI() [2/2]

PROVIDE_MPAPI ( pcbios ,
mp_start_all ,
bios_mp_start_all  )