o Do not parse the MADT as a side-effect in AcpiOsGetRootPointer,
do it as a side-effect of probing for MP hardware. This allows us to scan for local SAPICs early (especially before MBUF initialization). o Fix the Local SAPIC structure so that matches the Local SAPIC table entry. Now that the Local SAPIC info is the same as the Local APIC info, stop dumping the Local APIC entries. o For every Local SAPIC entry in the MADT that's not disabled, let the SMP code know about it. They represent actual CPUs. o Register the OS_BOOT_RENDEZ entry point and provide a (bogus) implementation for the entry point. o Provide a mapping for internal IPI numbers to ExtINT vectors. o In a MP system, announce the CPUs and start them by sending IPI_AP_WAKEUP to each of them. Not that it makes a difference at this time :-) o Miscellaneous style fixes and other adjustments.
This commit is contained in:
parent
434d21ccbf
commit
229778f87e
@ -51,25 +51,15 @@ AcpiOsTerminate(void)
|
||||
}
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiOsGetRootPointer(
|
||||
UINT32 Flags,
|
||||
ACPI_PHYSICAL_ADDRESS *RsdpPhysicalAddress)
|
||||
AcpiOsGetRootPointer(UINT32 Flags, ACPI_PHYSICAL_ADDRESS *RsdpPhysicalAddress)
|
||||
{
|
||||
RSDP_DESCRIPTOR *rsdp;
|
||||
XSDT_DESCRIPTOR *xsdt;
|
||||
|
||||
if (ia64_efi_acpi20_table) {
|
||||
if (ia64_efi_acpi20_table)
|
||||
*RsdpPhysicalAddress = ia64_efi_acpi20_table;
|
||||
rsdp = (RSDP_DESCRIPTOR *)
|
||||
IA64_PHYS_TO_RR7(ia64_efi_acpi20_table);
|
||||
xsdt = (XSDT_DESCRIPTOR *)
|
||||
IA64_PHYS_TO_RR7(rsdp->XsdtPhysicalAddress);
|
||||
ia64_parse_xsdt(xsdt);
|
||||
return(AE_OK);
|
||||
} else if (ia64_efi_acpi_table) {
|
||||
else if (ia64_efi_acpi_table)
|
||||
*RsdpPhysicalAddress = ia64_efi_acpi_table;
|
||||
return(AE_OK);
|
||||
}
|
||||
else
|
||||
return(AE_NOT_FOUND);
|
||||
|
||||
return(AE_NOT_FOUND);
|
||||
return(AE_OK);
|
||||
}
|
||||
|
@ -28,96 +28,71 @@
|
||||
|
||||
#include "acpi.h"
|
||||
|
||||
void cpu_mp_add(uint, uint, uint);
|
||||
struct sapic *sapic_create(int, int, u_int64_t);
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
#define APIC_INTERRUPT_SOURCE_OVERRIDE 2
|
||||
#define APIC_NMI 3
|
||||
#define APIC_LOCAL_APIC_NMI 4
|
||||
#define APIC_LOCAL_APIC_OVERRIDE 5
|
||||
#define APIC_IO_SAPIC 6
|
||||
#define APIC_LOCAL_SAPIC 7
|
||||
#define APIC_PLATFORM_INTERRUPT 8
|
||||
#define APIC_INTERRUPT_SOURCE_OVERRIDE 2
|
||||
#define APIC_NMI 3
|
||||
#define APIC_LOCAL_APIC_NMI 4
|
||||
#define APIC_LOCAL_APIC_OVERRIDE 5
|
||||
#define APIC_IO_SAPIC 6
|
||||
#define APIC_LOCAL_SAPIC 7
|
||||
#define APIC_PLATFORM_INTERRUPT 8
|
||||
|
||||
|
||||
typedef struct /* Interrupt Source Override */
|
||||
typedef struct /* Interrupt Source Override */
|
||||
{
|
||||
APIC_HEADER header;
|
||||
UINT8 Bus;
|
||||
UINT8 Source;
|
||||
UINT32 GlobalSystemInterrupt;
|
||||
UINT16 Flags;
|
||||
APIC_HEADER header;
|
||||
UINT8 Bus;
|
||||
UINT8 Source;
|
||||
UINT32 GlobalSystemInterrupt;
|
||||
UINT16 Flags;
|
||||
} INTERRUPT_SOURCE_OVERRIDE;
|
||||
|
||||
typedef struct /* IO SAPIC */
|
||||
typedef struct /* IO SAPIC */
|
||||
{
|
||||
APIC_HEADER header;
|
||||
UINT8 IoSapicId; /* I/O SAPIC ID */
|
||||
UINT8 Reserved; /* reserved - must be zero */
|
||||
UINT32 Vector; /* interrupt vector index where INTI
|
||||
* lines start */
|
||||
UINT64 IoSapicAddress; /* SAPIC's physical address */
|
||||
|
||||
APIC_HEADER header;
|
||||
UINT8 IoSapicId; /* I/O SAPIC ID */
|
||||
UINT8 Reserved; /* reserved - must be zero */
|
||||
UINT32 Vector; /* interrupt base */
|
||||
UINT64 IoSapicAddress; /* SAPIC's physical address */
|
||||
} IO_SAPIC;
|
||||
|
||||
|
||||
typedef struct /* LOCAL SAPIC */
|
||||
{
|
||||
APIC_HEADER header;
|
||||
UINT16 ProcessorId; /* ACPI processor id */
|
||||
UINT16 ProcessorEnabled: 1; /* Processor is usable if set */
|
||||
UINT16 Reserved1 : 15;
|
||||
UINT8 LocalSapicId; /* processor's local SAPIC id */
|
||||
UINT8 LocalSapicEid; /* processor's local SAPIC eid */
|
||||
|
||||
APIC_HEADER header;
|
||||
UINT8 ProcessorId; /* ACPI processor id */
|
||||
UINT8 LocalSapicId; /* Processor local SAPIC id */
|
||||
UINT8 LocalSapicEid; /* Processor local SAPIC eid */
|
||||
UINT8 Reserved;
|
||||
UINT32 Reserved1: 16;
|
||||
UINT32 ProcessorEnabled: 1;
|
||||
UINT32 Reserved2: 15;
|
||||
} LOCAL_SAPIC;
|
||||
|
||||
|
||||
typedef struct /* PLATFORM INTERRUPT SOURCE */
|
||||
{
|
||||
APIC_HEADER header;
|
||||
UINT16 Polarity : 2; /* Polarity of input signal */
|
||||
UINT16 TriggerMode: 2; /* Trigger mode of input signal */
|
||||
UINT16 Reserved1 : 12;
|
||||
UINT8 InterruptType; /* 1-PMI, 2-INIT, 3-Error */
|
||||
UINT8 ProcessorId; /* Processor ID of destination */
|
||||
UINT8 ProcessorEid; /* Processor EID of destination */
|
||||
UINT8 IoSapicVector; /* Value for redirection table */
|
||||
UINT32 GlobalSystemInterrupt; /* Global System Interrupt */
|
||||
UINT32 Reserved2;
|
||||
|
||||
APIC_HEADER header;
|
||||
UINT16 Polarity : 2; /* Polarity of input signal */
|
||||
UINT16 TriggerMode: 2; /* Trigger mode of input signal */
|
||||
UINT16 Reserved1 : 12;
|
||||
UINT8 InterruptType; /* 1-PMI, 2-INIT, 3-Error */
|
||||
UINT8 ProcessorId; /* Processor ID of destination */
|
||||
UINT8 ProcessorEid; /* Processor EID of destination */
|
||||
UINT8 IoSapicVector; /* Value for redirection table */
|
||||
UINT32 GlobalSystemInterrupt; /* Global System Interrupt */
|
||||
UINT32 Reserved2;
|
||||
} PLATFORM_INTERRUPT_SOURCE;
|
||||
|
||||
|
||||
#pragma pack()
|
||||
|
||||
static void
|
||||
parse_local_apic(PROCESSOR_APIC *apic)
|
||||
{
|
||||
if (bootverbose) {
|
||||
printf("\t\tProcessorId=0x%x, APIC Id=0x%x",
|
||||
apic->ProcessorApicId, apic->LocalApicId);
|
||||
if (!apic->ProcessorEnabled)
|
||||
printf(" (disabled)");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parse_io_apic(IO_APIC *apic)
|
||||
{
|
||||
if (bootverbose)
|
||||
printf("\t\tId=0x%x, Vector=0x%x, Address=0x%lx\n",
|
||||
apic->IoApicId, apic->Vector, apic->IoApicAddress);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_interrupt_override(INTERRUPT_SOURCE_OVERRIDE *override)
|
||||
{
|
||||
if (bootverbose)
|
||||
printf("\t\tBus=%d, Source=%d, Irq=0x%x\n",
|
||||
override->Bus,
|
||||
override->Source,
|
||||
override->GlobalSystemInterrupt);
|
||||
printf("\t\tBus=%d, Source=%d, Irq=0x%x\n", override->Bus,
|
||||
override->Source, override->GlobalSystemInterrupt);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -125,9 +100,7 @@ parse_io_sapic(IO_SAPIC *sapic)
|
||||
{
|
||||
if (bootverbose)
|
||||
printf("\t\tId=0x%x, Vector=0x%x, Address=0x%lx\n",
|
||||
sapic->IoSapicId,
|
||||
sapic->Vector,
|
||||
sapic->IoSapicAddress);
|
||||
sapic->IoSapicId, sapic->Vector, sapic->IoSapicAddress);
|
||||
sapic_create(sapic->IoSapicId, sapic->Vector, sapic->IoSapicAddress);
|
||||
}
|
||||
|
||||
@ -142,6 +115,11 @@ parse_local_sapic(LOCAL_SAPIC *sapic)
|
||||
printf(" (disabled)");
|
||||
printf("\n");
|
||||
}
|
||||
#ifdef SMP
|
||||
if (sapic->ProcessorEnabled)
|
||||
cpu_mp_add(sapic->ProcessorId, sapic->LocalSapicId,
|
||||
sapic->LocalSapicEid);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@ -149,13 +127,10 @@ parse_platform_interrupt(PLATFORM_INTERRUPT_SOURCE *source)
|
||||
{
|
||||
if (bootverbose)
|
||||
printf("\t\tPolarity=%d, TriggerMode=%d, Id=0x%x, "
|
||||
"Eid=0x%x, Vector=0x%x, Irq=%d\n",
|
||||
source->Polarity,
|
||||
source->TriggerMode,
|
||||
source->ProcessorId,
|
||||
source->ProcessorEid,
|
||||
source->IoSapicVector,
|
||||
source->GlobalSystemInterrupt);
|
||||
"Eid=0x%x, Vector=0x%x, Irq=%d\n", source->Polarity,
|
||||
source->TriggerMode, source->ProcessorId,
|
||||
source->ProcessorEid, source->IoSapicVector,
|
||||
source->GlobalSystemInterrupt);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -177,13 +152,11 @@ parse_madt(APIC_TABLE *madt)
|
||||
case APIC_PROC:
|
||||
if (bootverbose)
|
||||
printf("Local APIC entry\n");
|
||||
parse_local_apic((PROCESSOR_APIC *) head);
|
||||
break;
|
||||
|
||||
case APIC_IO:
|
||||
if (bootverbose)
|
||||
printf("I/O APIC entry\n");
|
||||
parse_io_apic((IO_APIC *) head);
|
||||
break;
|
||||
|
||||
case APIC_INTERRUPT_SOURCE_OVERRIDE:
|
||||
@ -203,6 +176,7 @@ parse_madt(APIC_TABLE *madt)
|
||||
printf("Local APIC NMI entry\n");
|
||||
break;
|
||||
|
||||
|
||||
case APIC_LOCAL_APIC_OVERRIDE:
|
||||
if (bootverbose)
|
||||
printf("Local APIC override entry\n");
|
||||
@ -238,28 +212,32 @@ parse_madt(APIC_TABLE *madt)
|
||||
}
|
||||
|
||||
void
|
||||
ia64_parse_xsdt(XSDT_DESCRIPTOR *xsdt)
|
||||
ia64_probe_sapics(void)
|
||||
{
|
||||
int i, count;
|
||||
ACPI_PHYSICAL_ADDRESS rsdp_phys;
|
||||
RSDP_DESCRIPTOR *rsdp;
|
||||
XSDT_DESCRIPTOR *xsdt;
|
||||
ACPI_TABLE_HEADER *table;
|
||||
int i, count;
|
||||
|
||||
/*
|
||||
* First find the MADT.
|
||||
*/
|
||||
count = (UINT64 *) ((char *) xsdt + xsdt->Header.Length)
|
||||
- &xsdt->TableOffsetEntry[0];
|
||||
if (AcpiOsGetRootPointer(0, &rsdp_phys) != AE_OK)
|
||||
return;
|
||||
|
||||
rsdp = (RSDP_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp_phys);
|
||||
xsdt = (XSDT_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp->XsdtPhysicalAddress);
|
||||
|
||||
count = (UINT64 *)((char *)xsdt + xsdt->Header.Length)
|
||||
- xsdt->TableOffsetEntry;
|
||||
for (i = 0; i < count; i++) {
|
||||
table = (ACPI_TABLE_HEADER *)
|
||||
IA64_PHYS_TO_RR7(xsdt->TableOffsetEntry[i]);
|
||||
|
||||
if (bootverbose)
|
||||
printf("Table '%c%c%c%c' at %p\n",
|
||||
table->Signature[0],
|
||||
table->Signature[1],
|
||||
table->Signature[2],
|
||||
table->Signature[3],
|
||||
table);
|
||||
if (!strncmp(table->Signature, APIC_SIG, 4)) {
|
||||
printf("Table '%c%c%c%c' at %p\n", table->Signature[0],
|
||||
table->Signature[1], table->Signature[2],
|
||||
table->Signature[3], table);
|
||||
|
||||
if (!strncmp(table->Signature, APIC_SIG, 4))
|
||||
parse_madt((APIC_TABLE *) table);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,7 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <machine/asm.h>
|
||||
#include <machine/ia64_cpu.h>
|
||||
#include <machine/fpu.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <assym.s>
|
||||
@ -74,7 +75,6 @@ kstack: .space KSTACK_PAGES * PAGE_SIZE
|
||||
* Not really a leaf but we can't return.
|
||||
*/
|
||||
ENTRY(__start, 1)
|
||||
|
||||
movl r8=ia64_vector_table // set up IVT early
|
||||
movl r9=ia64_vhpt+(1<<8)+(15<<2)+1 // and VHPT
|
||||
;;
|
||||
@ -130,6 +130,56 @@ ENTRY(__start, 1)
|
||||
|
||||
END(__start)
|
||||
|
||||
/*
|
||||
* AP wake-up entry point. The handoff state is similar as for the BSP,
|
||||
* as described on page 3-9 of the IPF SAL Specification. The difference
|
||||
* lies in the contents of register b0. For APs this register holds the
|
||||
* return address into the SAL rendezvous routine.
|
||||
*/
|
||||
.align 32
|
||||
ENTRY(os_boot_rendez,0)
|
||||
1: mov r16 = ip
|
||||
movl r17 = (IA64_PSR_AC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_IT|IA64_PSR_BN)
|
||||
mov r18 = 7
|
||||
;;
|
||||
add r16 = 2f-1b, r16
|
||||
mov cr.ipsr = r17
|
||||
;;
|
||||
dep r16 = r18, r16, 61, 3
|
||||
;;
|
||||
mov cr.iip = r16
|
||||
;;
|
||||
rfi
|
||||
|
||||
.align 32
|
||||
2: movl r16 = ia64_vector_table // set up IVT early
|
||||
movl r17 = ia64_vhpt+(1<<8)+(15<<2)+1 // and VHPT
|
||||
;;
|
||||
mov cr.iva = r16
|
||||
mov cr.pta = r17
|
||||
;;
|
||||
srlz.i
|
||||
;;
|
||||
srlz.d
|
||||
movl gp = __gp
|
||||
;;
|
||||
br.call.sptk.many rp = ia64_ap_get_stack
|
||||
;;
|
||||
mov r9 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16
|
||||
;;
|
||||
add sp = r9, r8
|
||||
mov ar.bspstore = r8
|
||||
;;
|
||||
loadrs
|
||||
;;
|
||||
mov ar.rsc = 3
|
||||
;;
|
||||
alloc r16=ar.pfs,0,0,0,0
|
||||
;;
|
||||
br.call.sptk.many rp=ia64_ap_startup
|
||||
/* NOT REACHED */
|
||||
END(os_boot_rendez)
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
/*
|
||||
|
@ -54,6 +54,7 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <machine/asm.h>
|
||||
#include <machine/ia64_cpu.h>
|
||||
#include <machine/fpu.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <assym.s>
|
||||
@ -74,7 +75,6 @@ kstack: .space KSTACK_PAGES * PAGE_SIZE
|
||||
* Not really a leaf but we can't return.
|
||||
*/
|
||||
ENTRY(__start, 1)
|
||||
|
||||
movl r8=ia64_vector_table // set up IVT early
|
||||
movl r9=ia64_vhpt+(1<<8)+(15<<2)+1 // and VHPT
|
||||
;;
|
||||
@ -130,6 +130,56 @@ ENTRY(__start, 1)
|
||||
|
||||
END(__start)
|
||||
|
||||
/*
|
||||
* AP wake-up entry point. The handoff state is similar as for the BSP,
|
||||
* as described on page 3-9 of the IPF SAL Specification. The difference
|
||||
* lies in the contents of register b0. For APs this register holds the
|
||||
* return address into the SAL rendezvous routine.
|
||||
*/
|
||||
.align 32
|
||||
ENTRY(os_boot_rendez,0)
|
||||
1: mov r16 = ip
|
||||
movl r17 = (IA64_PSR_AC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_IT|IA64_PSR_BN)
|
||||
mov r18 = 7
|
||||
;;
|
||||
add r16 = 2f-1b, r16
|
||||
mov cr.ipsr = r17
|
||||
;;
|
||||
dep r16 = r18, r16, 61, 3
|
||||
;;
|
||||
mov cr.iip = r16
|
||||
;;
|
||||
rfi
|
||||
|
||||
.align 32
|
||||
2: movl r16 = ia64_vector_table // set up IVT early
|
||||
movl r17 = ia64_vhpt+(1<<8)+(15<<2)+1 // and VHPT
|
||||
;;
|
||||
mov cr.iva = r16
|
||||
mov cr.pta = r17
|
||||
;;
|
||||
srlz.i
|
||||
;;
|
||||
srlz.d
|
||||
movl gp = __gp
|
||||
;;
|
||||
br.call.sptk.many rp = ia64_ap_get_stack
|
||||
;;
|
||||
mov r9 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16
|
||||
;;
|
||||
add sp = r9, r8
|
||||
mov ar.bspstore = r8
|
||||
;;
|
||||
loadrs
|
||||
;;
|
||||
mov ar.rsc = 3
|
||||
;;
|
||||
alloc r16=ar.pfs,0,0,0,0
|
||||
;;
|
||||
br.call.sptk.many rp=ia64_ap_startup
|
||||
/* NOT REACHED */
|
||||
END(os_boot_rendez)
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
/*
|
||||
|
@ -46,77 +46,186 @@
|
||||
#include <machine/pal.h>
|
||||
#include <machine/pmap.h>
|
||||
#include <machine/clock.h>
|
||||
#include <machine/sal.h>
|
||||
|
||||
static void ipi_send(u_int64_t, u_int64_t);
|
||||
#define LID_SAPIC_ID(x) ((int)((x) >> 24) & 0xff)
|
||||
#define LID_SAPIC_EID(x) ((int)((x) >> 16) & 0xff)
|
||||
|
||||
u_int64_t cpu_to_lid[MAXCPU];
|
||||
int ncpus;
|
||||
void ia64_probe_sapics(void);
|
||||
|
||||
static MALLOC_DEFINE(M_SMP, "smp", "SMP structures");
|
||||
|
||||
static void ipi_send(u_int64_t, int);
|
||||
static void cpu_mp_unleash(void *);
|
||||
|
||||
struct mp_cpu {
|
||||
TAILQ_ENTRY(mp_cpu) cpu_next;
|
||||
u_int64_t cpu_lid; /* Local processor ID */
|
||||
int32_t cpu_no; /* Sequential CPU number */
|
||||
u_int32_t cpu_bsp:1; /* 1=BSP; 0=AP */
|
||||
u_int32_t cpu_awake:1; /* 1=Awake; 0=sleeping */
|
||||
void *cpu_stack;
|
||||
};
|
||||
|
||||
int mp_hardware = 0;
|
||||
int mp_ipi_vector[IPI_COUNT];
|
||||
|
||||
TAILQ_HEAD(, mp_cpu) ia64_cpus = TAILQ_HEAD_INITIALIZER(ia64_cpus);
|
||||
|
||||
void *
|
||||
ia64_ap_get_stack(void)
|
||||
{
|
||||
struct mp_cpu *cpu;
|
||||
u_int64_t lid = ia64_get_lid() & 0xffff0000;
|
||||
|
||||
TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
|
||||
if (cpu->cpu_lid == lid)
|
||||
return (cpu->cpu_stack);
|
||||
}
|
||||
|
||||
/* XXX - Should never reach here */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ia64_ap_startup(void)
|
||||
{
|
||||
struct mp_cpu *cpu;
|
||||
u_int64_t lid = ia64_get_lid() & 0xffff0000;
|
||||
|
||||
TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
|
||||
if (cpu->cpu_lid == lid) {
|
||||
cpu->cpu_lid = ia64_get_lid();
|
||||
cpu->cpu_awake = 1;
|
||||
printf("SMP: CPU%d is awake!\n", cpu->cpu_no);
|
||||
while (1)
|
||||
ia64_call_pal_static(PAL_HALT_LIGHT, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
cpu_mp_probe()
|
||||
{
|
||||
all_cpus = 1; /* Needed for MB init code */
|
||||
return (0);
|
||||
ia64_probe_sapics();
|
||||
return (mp_hardware);
|
||||
}
|
||||
|
||||
void
|
||||
cpu_mp_start()
|
||||
cpu_mp_add(uint acpiid, uint apicid, uint apiceid)
|
||||
{
|
||||
struct mp_cpu *cpu;
|
||||
u_int64_t lid = ia64_get_lid() & 0xffff0000;
|
||||
|
||||
cpu = malloc(sizeof(*cpu), M_SMP, M_WAITOK|M_ZERO);
|
||||
if (cpu == NULL)
|
||||
return;
|
||||
|
||||
TAILQ_INSERT_TAIL(&ia64_cpus, cpu, cpu_next);
|
||||
cpu->cpu_no = acpiid;
|
||||
lid = ((apicid & 0xff) << 8 | (apiceid & 0xff)) << 16;
|
||||
if (lid == (ia64_get_lid() & 0xffff0000L)) {
|
||||
cpu->cpu_lid = ia64_get_lid();
|
||||
cpu->cpu_bsp = 1;
|
||||
cpu->cpu_awake = 1;
|
||||
} else
|
||||
cpu->cpu_lid = lid;
|
||||
all_cpus |= (1 << acpiid);
|
||||
mp_ncpus++;
|
||||
}
|
||||
|
||||
void
|
||||
cpu_mp_announce()
|
||||
{
|
||||
struct mp_cpu *cpu;
|
||||
|
||||
TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
|
||||
printf("cpu%d: SAPIC Id=%x, SAPIC Eid=%x (%s)\n", cpu->cpu_no,
|
||||
LID_SAPIC_ID(cpu->cpu_lid), LID_SAPIC_EID(cpu->cpu_lid),
|
||||
(cpu->cpu_bsp) ? "BSP" : "AP");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cpu_mp_start()
|
||||
{
|
||||
struct mp_cpu *cpu;
|
||||
|
||||
TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
|
||||
if (!cpu->cpu_bsp) {
|
||||
cpu->cpu_stack = malloc(KSTACK_PAGES * PAGE_SIZE,
|
||||
M_SMP, M_WAITOK);
|
||||
if (bootverbose)
|
||||
printf("SMP: waking up CPU%d\n", cpu->cpu_no);
|
||||
ipi_send(cpu->cpu_lid, IPI_AP_WAKEUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cpu_mp_unleash(void *dummy)
|
||||
{
|
||||
struct mp_cpu *cpu;
|
||||
int awake = 0;
|
||||
|
||||
if (!mp_hardware)
|
||||
return;
|
||||
|
||||
TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
|
||||
if (cpu->cpu_awake)
|
||||
awake++;
|
||||
}
|
||||
|
||||
printf("SMP: %d CPUs, %d awake\n", mp_ncpus, awake);
|
||||
}
|
||||
|
||||
/*
|
||||
* send an IPI to a set of cpus.
|
||||
*/
|
||||
void
|
||||
ipi_selected(u_int cpus, u_int64_t ipi)
|
||||
ipi_selected(u_int64_t cpus, int ipi)
|
||||
{
|
||||
u_int mask;
|
||||
int cpu;
|
||||
struct mp_cpu *cpu;
|
||||
|
||||
for (mask = 1, cpu = 0; cpu < ncpus; mask <<= 1, cpu++) {
|
||||
if (cpus & mask)
|
||||
ipi_send(cpu_to_lid[cpu], ipi);
|
||||
TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
|
||||
if (cpus & (1 << cpu->cpu_no))
|
||||
ipi_send(cpu->cpu_lid, ipi);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* send an IPI INTerrupt containing 'vector' to all CPUs, including myself
|
||||
* send an IPI to all CPUs, including myself.
|
||||
*/
|
||||
void
|
||||
ipi_all(u_int64_t ipi)
|
||||
ipi_all(int ipi)
|
||||
{
|
||||
int cpu;
|
||||
struct mp_cpu *cpu;
|
||||
|
||||
for (cpu = 0; cpu < ncpus; cpu++)
|
||||
ipi_send(cpu_to_lid[cpu], ipi);
|
||||
}
|
||||
|
||||
/*
|
||||
* send an IPI to all CPUs EXCEPT myself
|
||||
*/
|
||||
void
|
||||
ipi_all_but_self(u_int64_t ipi)
|
||||
{
|
||||
u_int64_t lid;
|
||||
int cpu;
|
||||
|
||||
for (cpu = 0; cpu < ncpus; cpu++) {
|
||||
lid = cpu_to_lid[cpu];
|
||||
if (lid != ia64_get_lid())
|
||||
ipi_send(lid, ipi);
|
||||
TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
|
||||
ipi_send(cpu->cpu_lid, ipi);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* send an IPI to myself
|
||||
* send an IPI to all CPUs EXCEPT myself.
|
||||
*/
|
||||
void
|
||||
ipi_self(u_int64_t ipi)
|
||||
ipi_all_but_self(int ipi)
|
||||
{
|
||||
struct mp_cpu *cpu;
|
||||
u_int64_t lid = ia64_get_lid();
|
||||
|
||||
TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
|
||||
if (cpu->cpu_lid != lid)
|
||||
ipi_send(cpu->cpu_lid, ipi);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* send an IPI to myself.
|
||||
*/
|
||||
void
|
||||
ipi_self(int ipi)
|
||||
{
|
||||
|
||||
ipi_send(ia64_get_lid(), ipi);
|
||||
@ -128,12 +237,15 @@ ipi_self(u_int64_t ipi)
|
||||
* fields are used here.
|
||||
*/
|
||||
static void
|
||||
ipi_send(u_int64_t lid, u_int64_t ipi)
|
||||
ipi_send(u_int64_t lid, int ipi)
|
||||
{
|
||||
volatile u_int64_t *pipi;
|
||||
u_int64_t vector;
|
||||
|
||||
CTR2(KTR_SMP, __func__ ": lid=%lx, ipi=%lx", lid, ipi);
|
||||
pipi = ia64_memory_address(PAL_PIB_DEFAULT_ADDR |
|
||||
((lid >> 12) & 0xFFFF0L));
|
||||
*pipi = ipi & 0xFF;
|
||||
vector = (u_int64_t)(mp_ipi_vector[ipi] & 0xff);
|
||||
*pipi = vector;
|
||||
}
|
||||
|
||||
SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL);
|
||||
|
@ -29,6 +29,9 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <machine/sal.h>
|
||||
#include <machine/smp.h>
|
||||
|
||||
void os_boot_rendez(void);
|
||||
|
||||
struct ia64_fdesc {
|
||||
u_int64_t func;
|
||||
@ -40,7 +43,6 @@ static sal_entry_t fake_sal;
|
||||
|
||||
extern u_int64_t ia64_pal_entry;
|
||||
sal_entry_t *ia64_sal_entry = fake_sal;
|
||||
u_int64_t ia64_sal_wakeup;
|
||||
|
||||
static struct ia64_sal_result
|
||||
fake_sal(u_int64_t a1, u_int64_t a2, u_int64_t a3, u_int64_t a4,
|
||||
@ -86,23 +88,28 @@ ia64_sal_init(struct sal_system_table *saltab)
|
||||
ia64_sal_entry = (sal_entry_t *) &sal_fdesc;
|
||||
break;
|
||||
}
|
||||
#ifdef SMP
|
||||
case 5: {
|
||||
struct sal_ap_wakeup_descriptor *dp;
|
||||
struct ia64_sal_result sal;
|
||||
int ipi;
|
||||
|
||||
dp = (struct sal_ap_wakeup_descriptor*)p;
|
||||
KASSERT(dp->sale_mechanism == 0,
|
||||
("Unsupported AP wake-up mechanism"));
|
||||
ia64_sal_wakeup = dp->sale_vector;
|
||||
if (bootverbose)
|
||||
printf("SMP: AP wake-up vector: 0x%lx\n",
|
||||
ia64_sal_wakeup);
|
||||
/*
|
||||
* Register OS_BOOT_RENDEZ using SAL_SET_VECTORS
|
||||
*/
|
||||
dp->sale_vector);
|
||||
for (ipi = 0; ipi < IPI_COUNT; ipi++)
|
||||
mp_ipi_vector[ipi] = dp->sale_vector + ipi;
|
||||
|
||||
sal = ia64_sal_entry(SAL_SET_VECTORS,
|
||||
SAL_OS_BOOT_RENDEZ,
|
||||
ia64_tpa((vm_offset_t)os_boot_rendez), 0, 0,
|
||||
0, 0, 0);
|
||||
|
||||
mp_hardware = 1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
p += sizes[*p];
|
||||
}
|
||||
|
@ -113,6 +113,11 @@ struct sal_ap_wakeup_descriptor {
|
||||
#define SAL_FREQ_BASE 0x01000012
|
||||
#define SAL_UPDATE_PAL 0x01000020
|
||||
|
||||
/* SAL_SET_VECTORS event handler types */
|
||||
#define SAL_OS_MCA 0
|
||||
#define SAL_OS_INIT 1
|
||||
#define SAL_OS_BOOT_RENDEZ 2
|
||||
|
||||
struct ia64_sal_result {
|
||||
int64_t sal_status;
|
||||
u_int64_t sal_result[3];
|
||||
|
@ -7,26 +7,28 @@
|
||||
#ifdef _KERNEL
|
||||
|
||||
/*
|
||||
* Interprocessor interrupts for SMP.
|
||||
* Interprocessor interrupts for SMP. The following values are indices
|
||||
* into the IPI vector table. The SAL gives us the vector used for AP
|
||||
* wake-up. Keep the IPI_AP_WAKEUP at index 0.
|
||||
*/
|
||||
#define IPI_INVLTLB 0x0001
|
||||
#define IPI_RENDEZVOUS 0x0002
|
||||
#define IPI_AST 0x0004
|
||||
#define IPI_CHECKSTATE 0x0008
|
||||
#define IPI_STOP 0x0010
|
||||
#define IPI_AP_WAKEUP 0
|
||||
#define IPI_AST 1
|
||||
#define IPI_CHECKSTATE 2
|
||||
#define IPI_INVLTLB 3
|
||||
#define IPI_RENDEZVOUS 4
|
||||
#define IPI_STOP 5
|
||||
|
||||
#define IPI_COUNT 6
|
||||
|
||||
#ifndef LOCORE
|
||||
|
||||
/* global data in mp_machdep.c */
|
||||
extern volatile u_int checkstate_probed_cpus;
|
||||
extern volatile u_int checkstate_need_ast;
|
||||
extern volatile u_int resched_cpus;
|
||||
extern int mp_hardware;
|
||||
extern int mp_ipi_vector[];
|
||||
|
||||
void ipi_all(u_int64_t ipi);
|
||||
void ipi_all_but_self(u_int64_t ipi);
|
||||
void ipi_selected(u_int cpus, u_int64_t ipi);
|
||||
void ipi_self(u_int64_t ipi);
|
||||
void smp_init_secondary(void);
|
||||
void ipi_all(int ipi);
|
||||
void ipi_all_but_self(int ipi);
|
||||
void ipi_selected(u_int64_t cpus, int ipi);
|
||||
void ipi_self(int ipi);
|
||||
|
||||
#endif /* !LOCORE */
|
||||
#endif /* _KERNEL */
|
||||
|
Loading…
Reference in New Issue
Block a user