1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-28 16:43:09 +00:00

Added POST code output to various points of the startup code.

General cleanup.

New functions to stop/start CPUs via IPIs:

 - int stop_cpus( u_int map );
 - int restart_cpus( u_int map );

Turned off by default, enabled via smptests.h:TEST_CPUSTOP.
Current version has a BUG, perhaps a deadlock?
This commit is contained in:
Steve Passe 1997-06-27 23:33:17 +00:00
parent b1c3894d1b
commit b7f7f066f6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=27005
7 changed files with 1211 additions and 140 deletions

View File

@ -45,7 +45,7 @@
#include <machine/mpapic.h>
#include <machine/cpufunc.h>
#include <machine/segments.h>
#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG */
#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG, TEST_CPUSTOP */
#include <machine/tss.h>
#include <machine/specialreg.h>
@ -57,23 +57,24 @@
#include <i386/isa/intr_machdep.h> /* Xinvltlb() */
#endif /* APIC_IO */
#define WARMBOOT_TARGET 0
#define WARMBOOT_OFF (KERNBASE + 0x0467)
#define WARMBOOT_SEG (KERNBASE + 0x0469)
#define WARMBOOT_TARGET 0
#define WARMBOOT_OFF (KERNBASE + 0x0467)
#define WARMBOOT_SEG (KERNBASE + 0x0469)
#define BIOS_BASE (0xf0000)
#define BIOS_SIZE (0x10000)
#define BIOS_COUNT (BIOS_SIZE/4)
#define BIOS_BASE (0xf0000)
#define BIOS_SIZE (0x10000)
#define BIOS_COUNT (BIOS_SIZE/4)
#define CMOS_REG (0x70)
#define CMOS_DATA (0x71)
#define BIOS_RESET (0x0f)
#define BIOS_WARM (0x0a)
#define CMOS_REG (0x70)
#define CMOS_DATA (0x71)
#define BIOS_RESET (0x0f)
#define BIOS_WARM (0x0a)
#define PROCENTRY_FLAG_EN 0x01
#define PROCENTRY_FLAG_BP 0x02
#define IOAPICENTRY_FLAG_EN 0x01
/* MP Floating Pointer Structure */
typedef struct MPFPS {
char signature[4];
@ -185,6 +186,23 @@ typedef struct BASETABLE_ENTRY {
#endif /* CHECK_POINTS */
/*
* Values to send to the POST hardware.
*/
#ifndef POSTCODE
#define POSTCODE(X)
#endif
#define MP_BOOTADDRESS_POST 0x10
#define MP_PROBE_POST 0x11
#define MP_START_POST 0x12
#define MP_ANNOUNCE_POST 0x13
#define MPTABLE_PASS1_POST 0x14
#define MPTABLE_PASS2_POST 0x15
#define MP_ENABLE_POST 0x16
#define START_ALL_APS_POST 0x17
#define INSTALL_AP_TRAMP_POST 0x18
#define START_AP_POST 0x19
/** FIXME: what system files declare these??? */
extern struct region_descriptor r_gdt, r_idt;
@ -208,6 +226,9 @@ int cpu_num_to_apic_id[NAPICID];
int io_num_to_apic_id[NAPICID];
int apic_id_to_logical[NAPICID];
/* Bitmap of all available CPUs */
u_int all_cpus;
/* Boot of AP uses this PTD */
u_int *bootPTD;
@ -244,6 +265,8 @@ static int start_ap(int logicalCpu, u_int boot_addr);
u_int
mp_bootaddress(u_int basemem)
{
POSTCODE(MP_BOOTADDRESS_POST);
base_memory = basemem * 1024; /* convert to bytes */
boot_address = base_memory & ~0xfff; /* round down to 4k boundary */
@ -261,6 +284,8 @@ mp_probe(void)
u_long segment;
u_int32_t target;
POSTCODE(MP_PROBE_POST);
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
@ -302,6 +327,8 @@ mp_probe(void)
void
mp_start(void)
{
POSTCODE(MP_START_POST);
/* look for MP capable motherboard */
if (mp_capable)
mp_enable(boot_address);
@ -318,6 +345,8 @@ mp_announce(void)
{
int x;
POSTCODE(MP_ANNOUNCE_POST);
printf("FreeBSD/SMP: Multiprocessor motherboard\n");
printf(" cpu0 (BSP): apic id: %d", CPU_TO_ID(0));
printf(", version: 0x%08x", cpu_apic_versions[0]);
@ -389,13 +418,13 @@ configure_local_apic(void)
/* setup lint1 to handle NMI */
#if 1
/** XXX FIXME:
* should we arrange for ALL CPUs to catch NMI???
* it would probably crash, so for now only the BSP
* will catch it
/** XXX FIXME:
* should we arrange for ALL CPUs to catch NMI???
* it would probably crash, so for now only the BSP
* will catch it
*/
if (cpuid != 0)
return;
return;
#endif /* 0/1 */
temp = lapic.lvt_lint1;
@ -408,7 +437,7 @@ configure_local_apic(void)
lapic.lvt_lint1 = temp;
}
#endif /* APIC_IO */
#endif /* APIC_IO */
/*******************************************************************
@ -427,6 +456,8 @@ mp_enable(u_int boot_addr)
u_int ux;
#endif /* APIC_IO */
POSTCODE(MP_ENABLE_POST);
/* Turn on 4MB of V == P addressing so we can get to MP table */
*(int *)PTD = PG_V | PG_RW | ((u_long)KPTphys & PG_FRAME);
invltlb();
@ -454,8 +485,14 @@ mp_enable(u_int boot_addr)
panic("IO APIC setup failure");
/* install an inter-CPU IPI for TLB invalidation */
setidt(ICU_OFFSET + XINVLTLB_OFFSET, Xinvltlb,
setidt(XINVLTLB_OFFSET, Xinvltlb,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#if defined(TEST_CPUSTOP)
/* install an inter-CPU IPI for CPU stop/restart */
setidt(XCPUSTOP_OFFSET, Xcpustop,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#endif /* TEST_CPUSTOP */
#endif /* APIC_IO */
/* start each Application Processor */
@ -597,6 +634,8 @@ mptable_pass1(void)
int type;
int mustpanic;
POSTCODE(MPTABLE_PASS1_POST);
mustpanic = 0;
/* clear various tables */
@ -722,6 +761,8 @@ mptable_pass2(void)
int type;
int apic, bus, cpu, intr;
POSTCODE(MPTABLE_PASS2_POST);
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
ID_TO_IO(x) = -1; /* phy APIC ID to log CPU/IO table */
@ -1370,6 +1411,8 @@ start_all_aps(u_int boot_addr)
pt_entry_t newpt;
int *newpp;
POSTCODE(START_ALL_APS_POST);
/**
* NOTE: this needs further thought:
* where does it get released?
@ -1391,6 +1434,9 @@ start_all_aps(u_int boot_addr)
outb(CMOS_REG, BIOS_RESET);
mpbiosreason = inb(CMOS_DATA);
/* record BSP in CPU map */
all_cpus = 1;
/* start each AP */
for (x = 1; x <= mp_naps; ++x) {
@ -1462,12 +1508,17 @@ start_all_aps(u_int boot_addr)
if (cngetc() != 'n')
panic("bye-bye");
}
CHECK_PRINT("trace"); /* show checkpoints */
CHECK_PRINT("trace"); /* show checkpoints */
/* record its version info */
cpu_apic_versions[x] = cpu_apic_versions[0];
all_cpus |= (1 << x); /* record AP in CPU map */
}
/* build our map of 'other' CPUs */
other_cpus = all_cpus & ~(1 << cpuid);
/* fill in our (BSP) APIC version */
cpu_apic_versions[0] = lapic.version;
@ -1505,6 +1556,8 @@ install_ap_tramp(u_int boot_addr)
u_int16_t *dst16;
u_int32_t *dst32;
POSTCODE(INSTALL_AP_TRAMP_POST);
for (x = 0; x < size; ++x)
*dst++ = *src++;
@ -1554,6 +1607,8 @@ start_ap(int logical_cpu, u_int boot_addr)
int cpus;
u_long icr_lo, icr_hi;
POSTCODE(START_AP_POST);
/* get the PHYSICAL APIC ID# */
physical_cpu = CPU_TO_ID(logical_cpu);
@ -1638,7 +1693,7 @@ smp_invltlb(void)
{
#if defined(APIC_IO)
if (smp_active && invltlb_ok)
all_but_self_ipi(ICU_OFFSET + XINVLTLB_OFFSET);
all_but_self_ipi(XINVLTLB_OFFSET);
#endif /* APIC_IO */
}
@ -1665,3 +1720,101 @@ invltlb(void)
/* send a message to the other CPUs */
smp_invltlb();
}
#if defined(TEST_CPUSTOP)
/*
* When called the executing CPU will send an IPI to all other CPUs
* requesting that they halt execution.
*
* Usually (but not necessarily) called with 'other_cpus' as its arg.
*
* - Signals all CPUs in map to stop.
* - Waits for each to stop.
*
* Returns:
* -1: error
* 0: NA
* 1: ok
*
* XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs
* from executing at same time.
*/
int
stop_cpus( u_int map )
{
if (!smp_active)
return 0;
stopped_cpus = 0;
/* send IPI to all CPUs in map */
#if defined(DEBUG_CPUSTOP)
db_printf("\nCPU%d stopping CPUs: 0x%08x\n", cpuid, map);
#endif /* DEBUG_CPUSTOP */
#if 0
selected_apic_ipi(map, XCPUSTOP_OFFSET, APIC_DELMODE_FIXED);
#else
all_but_self_ipi(XCPUSTOP_OFFSET);
#endif
#if defined(DEBUG_CPUSTOP)
db_printf(" stopped_cpus: 0x%08x, map: 0x%08x, spin\n",
stopped_cpus, map);
#endif /* DEBUG_CPUSTOP */
while (stopped_cpus != map) {
#if 0
/* spin */ ;
#else
POSTCODE(stopped_cpus & 0xff);
#endif
}
#if defined(DEBUG_CPUSTOP)
db_printf(" spun\nstopped\n");
#endif /* DEBUG_CPUSTOP */
return 1;
}
/*
* Called by a CPU to restart stopped CPUs.
*
* Usually (but not necessarily) called with 'stopped_cpus' as its arg.
*
* - Signals all CPUs in map to restart.
* - Waits for each to restart.
*
* Returns:
* -1: error
* 0: NA
* 1: ok
*/
int
restart_cpus( u_int map )
{
if (!smp_active)
return 0;
started_cpus = map; /* signal other cpus to restart */
#if defined(DEBUG_CPUSTOP)
db_printf("\nCPU%d restarting CPUs: 0x%08x (0x%08x)\n",
cpuid, started_cpus, stopped_cpus);
#endif /* DEBUG_CPUSTOP */
while (started_cpus) /* wait for each to clear its bit */
/* spin */ ;
#if defined(DEBUG_CPUSTOP)
db_printf(" restarted\n");
#endif /* DEBUG_CPUSTOP */
return 1;
}
#endif /* TEST_CPUSTOP */

View File

@ -45,7 +45,7 @@
#include <machine/mpapic.h>
#include <machine/cpufunc.h>
#include <machine/segments.h>
#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG */
#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG, TEST_CPUSTOP */
#include <machine/tss.h>
#include <machine/specialreg.h>
@ -57,23 +57,24 @@
#include <i386/isa/intr_machdep.h> /* Xinvltlb() */
#endif /* APIC_IO */
#define WARMBOOT_TARGET 0
#define WARMBOOT_OFF (KERNBASE + 0x0467)
#define WARMBOOT_SEG (KERNBASE + 0x0469)
#define WARMBOOT_TARGET 0
#define WARMBOOT_OFF (KERNBASE + 0x0467)
#define WARMBOOT_SEG (KERNBASE + 0x0469)
#define BIOS_BASE (0xf0000)
#define BIOS_SIZE (0x10000)
#define BIOS_COUNT (BIOS_SIZE/4)
#define BIOS_BASE (0xf0000)
#define BIOS_SIZE (0x10000)
#define BIOS_COUNT (BIOS_SIZE/4)
#define CMOS_REG (0x70)
#define CMOS_DATA (0x71)
#define BIOS_RESET (0x0f)
#define BIOS_WARM (0x0a)
#define CMOS_REG (0x70)
#define CMOS_DATA (0x71)
#define BIOS_RESET (0x0f)
#define BIOS_WARM (0x0a)
#define PROCENTRY_FLAG_EN 0x01
#define PROCENTRY_FLAG_BP 0x02
#define IOAPICENTRY_FLAG_EN 0x01
/* MP Floating Pointer Structure */
typedef struct MPFPS {
char signature[4];
@ -185,6 +186,23 @@ typedef struct BASETABLE_ENTRY {
#endif /* CHECK_POINTS */
/*
* Values to send to the POST hardware.
*/
#ifndef POSTCODE
#define POSTCODE(X)
#endif
#define MP_BOOTADDRESS_POST 0x10
#define MP_PROBE_POST 0x11
#define MP_START_POST 0x12
#define MP_ANNOUNCE_POST 0x13
#define MPTABLE_PASS1_POST 0x14
#define MPTABLE_PASS2_POST 0x15
#define MP_ENABLE_POST 0x16
#define START_ALL_APS_POST 0x17
#define INSTALL_AP_TRAMP_POST 0x18
#define START_AP_POST 0x19
/** FIXME: what system files declare these??? */
extern struct region_descriptor r_gdt, r_idt;
@ -208,6 +226,9 @@ int cpu_num_to_apic_id[NAPICID];
int io_num_to_apic_id[NAPICID];
int apic_id_to_logical[NAPICID];
/* Bitmap of all available CPUs */
u_int all_cpus;
/* Boot of AP uses this PTD */
u_int *bootPTD;
@ -244,6 +265,8 @@ static int start_ap(int logicalCpu, u_int boot_addr);
u_int
mp_bootaddress(u_int basemem)
{
POSTCODE(MP_BOOTADDRESS_POST);
base_memory = basemem * 1024; /* convert to bytes */
boot_address = base_memory & ~0xfff; /* round down to 4k boundary */
@ -261,6 +284,8 @@ mp_probe(void)
u_long segment;
u_int32_t target;
POSTCODE(MP_PROBE_POST);
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
@ -302,6 +327,8 @@ mp_probe(void)
void
mp_start(void)
{
POSTCODE(MP_START_POST);
/* look for MP capable motherboard */
if (mp_capable)
mp_enable(boot_address);
@ -318,6 +345,8 @@ mp_announce(void)
{
int x;
POSTCODE(MP_ANNOUNCE_POST);
printf("FreeBSD/SMP: Multiprocessor motherboard\n");
printf(" cpu0 (BSP): apic id: %d", CPU_TO_ID(0));
printf(", version: 0x%08x", cpu_apic_versions[0]);
@ -389,13 +418,13 @@ configure_local_apic(void)
/* setup lint1 to handle NMI */
#if 1
/** XXX FIXME:
* should we arrange for ALL CPUs to catch NMI???
* it would probably crash, so for now only the BSP
* will catch it
/** XXX FIXME:
* should we arrange for ALL CPUs to catch NMI???
* it would probably crash, so for now only the BSP
* will catch it
*/
if (cpuid != 0)
return;
return;
#endif /* 0/1 */
temp = lapic.lvt_lint1;
@ -408,7 +437,7 @@ configure_local_apic(void)
lapic.lvt_lint1 = temp;
}
#endif /* APIC_IO */
#endif /* APIC_IO */
/*******************************************************************
@ -427,6 +456,8 @@ mp_enable(u_int boot_addr)
u_int ux;
#endif /* APIC_IO */
POSTCODE(MP_ENABLE_POST);
/* Turn on 4MB of V == P addressing so we can get to MP table */
*(int *)PTD = PG_V | PG_RW | ((u_long)KPTphys & PG_FRAME);
invltlb();
@ -454,8 +485,14 @@ mp_enable(u_int boot_addr)
panic("IO APIC setup failure");
/* install an inter-CPU IPI for TLB invalidation */
setidt(ICU_OFFSET + XINVLTLB_OFFSET, Xinvltlb,
setidt(XINVLTLB_OFFSET, Xinvltlb,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#if defined(TEST_CPUSTOP)
/* install an inter-CPU IPI for CPU stop/restart */
setidt(XCPUSTOP_OFFSET, Xcpustop,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#endif /* TEST_CPUSTOP */
#endif /* APIC_IO */
/* start each Application Processor */
@ -597,6 +634,8 @@ mptable_pass1(void)
int type;
int mustpanic;
POSTCODE(MPTABLE_PASS1_POST);
mustpanic = 0;
/* clear various tables */
@ -722,6 +761,8 @@ mptable_pass2(void)
int type;
int apic, bus, cpu, intr;
POSTCODE(MPTABLE_PASS2_POST);
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
ID_TO_IO(x) = -1; /* phy APIC ID to log CPU/IO table */
@ -1370,6 +1411,8 @@ start_all_aps(u_int boot_addr)
pt_entry_t newpt;
int *newpp;
POSTCODE(START_ALL_APS_POST);
/**
* NOTE: this needs further thought:
* where does it get released?
@ -1391,6 +1434,9 @@ start_all_aps(u_int boot_addr)
outb(CMOS_REG, BIOS_RESET);
mpbiosreason = inb(CMOS_DATA);
/* record BSP in CPU map */
all_cpus = 1;
/* start each AP */
for (x = 1; x <= mp_naps; ++x) {
@ -1462,12 +1508,17 @@ start_all_aps(u_int boot_addr)
if (cngetc() != 'n')
panic("bye-bye");
}
CHECK_PRINT("trace"); /* show checkpoints */
CHECK_PRINT("trace"); /* show checkpoints */
/* record its version info */
cpu_apic_versions[x] = cpu_apic_versions[0];
all_cpus |= (1 << x); /* record AP in CPU map */
}
/* build our map of 'other' CPUs */
other_cpus = all_cpus & ~(1 << cpuid);
/* fill in our (BSP) APIC version */
cpu_apic_versions[0] = lapic.version;
@ -1505,6 +1556,8 @@ install_ap_tramp(u_int boot_addr)
u_int16_t *dst16;
u_int32_t *dst32;
POSTCODE(INSTALL_AP_TRAMP_POST);
for (x = 0; x < size; ++x)
*dst++ = *src++;
@ -1554,6 +1607,8 @@ start_ap(int logical_cpu, u_int boot_addr)
int cpus;
u_long icr_lo, icr_hi;
POSTCODE(START_AP_POST);
/* get the PHYSICAL APIC ID# */
physical_cpu = CPU_TO_ID(logical_cpu);
@ -1638,7 +1693,7 @@ smp_invltlb(void)
{
#if defined(APIC_IO)
if (smp_active && invltlb_ok)
all_but_self_ipi(ICU_OFFSET + XINVLTLB_OFFSET);
all_but_self_ipi(XINVLTLB_OFFSET);
#endif /* APIC_IO */
}
@ -1665,3 +1720,101 @@ invltlb(void)
/* send a message to the other CPUs */
smp_invltlb();
}
#if defined(TEST_CPUSTOP)
/*
* When called the executing CPU will send an IPI to all other CPUs
* requesting that they halt execution.
*
* Usually (but not necessarily) called with 'other_cpus' as its arg.
*
* - Signals all CPUs in map to stop.
* - Waits for each to stop.
*
* Returns:
* -1: error
* 0: NA
* 1: ok
*
* XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs
* from executing at same time.
*/
int
stop_cpus( u_int map )
{
if (!smp_active)
return 0;
stopped_cpus = 0;
/* send IPI to all CPUs in map */
#if defined(DEBUG_CPUSTOP)
db_printf("\nCPU%d stopping CPUs: 0x%08x\n", cpuid, map);
#endif /* DEBUG_CPUSTOP */
#if 0
selected_apic_ipi(map, XCPUSTOP_OFFSET, APIC_DELMODE_FIXED);
#else
all_but_self_ipi(XCPUSTOP_OFFSET);
#endif
#if defined(DEBUG_CPUSTOP)
db_printf(" stopped_cpus: 0x%08x, map: 0x%08x, spin\n",
stopped_cpus, map);
#endif /* DEBUG_CPUSTOP */
while (stopped_cpus != map) {
#if 0
/* spin */ ;
#else
POSTCODE(stopped_cpus & 0xff);
#endif
}
#if defined(DEBUG_CPUSTOP)
db_printf(" spun\nstopped\n");
#endif /* DEBUG_CPUSTOP */
return 1;
}
/*
* Called by a CPU to restart stopped CPUs.
*
* Usually (but not necessarily) called with 'stopped_cpus' as its arg.
*
* - Signals all CPUs in map to restart.
* - Waits for each to restart.
*
* Returns:
* -1: error
* 0: NA
* 1: ok
*/
int
restart_cpus( u_int map )
{
if (!smp_active)
return 0;
started_cpus = map; /* signal other cpus to restart */
#if defined(DEBUG_CPUSTOP)
db_printf("\nCPU%d restarting CPUs: 0x%08x (0x%08x)\n",
cpuid, started_cpus, stopped_cpus);
#endif /* DEBUG_CPUSTOP */
while (started_cpus) /* wait for each to clear its bit */
/* spin */ ;
#if defined(DEBUG_CPUSTOP)
db_printf(" restarted\n");
#endif /* DEBUG_CPUSTOP */
return 1;
}
#endif /* TEST_CPUSTOP */

View File

@ -45,7 +45,7 @@
#include <machine/mpapic.h>
#include <machine/cpufunc.h>
#include <machine/segments.h>
#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG */
#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG, TEST_CPUSTOP */
#include <machine/tss.h>
#include <machine/specialreg.h>
@ -57,23 +57,24 @@
#include <i386/isa/intr_machdep.h> /* Xinvltlb() */
#endif /* APIC_IO */
#define WARMBOOT_TARGET 0
#define WARMBOOT_OFF (KERNBASE + 0x0467)
#define WARMBOOT_SEG (KERNBASE + 0x0469)
#define WARMBOOT_TARGET 0
#define WARMBOOT_OFF (KERNBASE + 0x0467)
#define WARMBOOT_SEG (KERNBASE + 0x0469)
#define BIOS_BASE (0xf0000)
#define BIOS_SIZE (0x10000)
#define BIOS_COUNT (BIOS_SIZE/4)
#define BIOS_BASE (0xf0000)
#define BIOS_SIZE (0x10000)
#define BIOS_COUNT (BIOS_SIZE/4)
#define CMOS_REG (0x70)
#define CMOS_DATA (0x71)
#define BIOS_RESET (0x0f)
#define BIOS_WARM (0x0a)
#define CMOS_REG (0x70)
#define CMOS_DATA (0x71)
#define BIOS_RESET (0x0f)
#define BIOS_WARM (0x0a)
#define PROCENTRY_FLAG_EN 0x01
#define PROCENTRY_FLAG_BP 0x02
#define IOAPICENTRY_FLAG_EN 0x01
/* MP Floating Pointer Structure */
typedef struct MPFPS {
char signature[4];
@ -185,6 +186,23 @@ typedef struct BASETABLE_ENTRY {
#endif /* CHECK_POINTS */
/*
* Values to send to the POST hardware.
*/
#ifndef POSTCODE
#define POSTCODE(X)
#endif
#define MP_BOOTADDRESS_POST 0x10
#define MP_PROBE_POST 0x11
#define MP_START_POST 0x12
#define MP_ANNOUNCE_POST 0x13
#define MPTABLE_PASS1_POST 0x14
#define MPTABLE_PASS2_POST 0x15
#define MP_ENABLE_POST 0x16
#define START_ALL_APS_POST 0x17
#define INSTALL_AP_TRAMP_POST 0x18
#define START_AP_POST 0x19
/** FIXME: what system files declare these??? */
extern struct region_descriptor r_gdt, r_idt;
@ -208,6 +226,9 @@ int cpu_num_to_apic_id[NAPICID];
int io_num_to_apic_id[NAPICID];
int apic_id_to_logical[NAPICID];
/* Bitmap of all available CPUs */
u_int all_cpus;
/* Boot of AP uses this PTD */
u_int *bootPTD;
@ -244,6 +265,8 @@ static int start_ap(int logicalCpu, u_int boot_addr);
u_int
mp_bootaddress(u_int basemem)
{
POSTCODE(MP_BOOTADDRESS_POST);
base_memory = basemem * 1024; /* convert to bytes */
boot_address = base_memory & ~0xfff; /* round down to 4k boundary */
@ -261,6 +284,8 @@ mp_probe(void)
u_long segment;
u_int32_t target;
POSTCODE(MP_PROBE_POST);
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
@ -302,6 +327,8 @@ mp_probe(void)
void
mp_start(void)
{
POSTCODE(MP_START_POST);
/* look for MP capable motherboard */
if (mp_capable)
mp_enable(boot_address);
@ -318,6 +345,8 @@ mp_announce(void)
{
int x;
POSTCODE(MP_ANNOUNCE_POST);
printf("FreeBSD/SMP: Multiprocessor motherboard\n");
printf(" cpu0 (BSP): apic id: %d", CPU_TO_ID(0));
printf(", version: 0x%08x", cpu_apic_versions[0]);
@ -389,13 +418,13 @@ configure_local_apic(void)
/* setup lint1 to handle NMI */
#if 1
/** XXX FIXME:
* should we arrange for ALL CPUs to catch NMI???
* it would probably crash, so for now only the BSP
* will catch it
/** XXX FIXME:
* should we arrange for ALL CPUs to catch NMI???
* it would probably crash, so for now only the BSP
* will catch it
*/
if (cpuid != 0)
return;
return;
#endif /* 0/1 */
temp = lapic.lvt_lint1;
@ -408,7 +437,7 @@ configure_local_apic(void)
lapic.lvt_lint1 = temp;
}
#endif /* APIC_IO */
#endif /* APIC_IO */
/*******************************************************************
@ -427,6 +456,8 @@ mp_enable(u_int boot_addr)
u_int ux;
#endif /* APIC_IO */
POSTCODE(MP_ENABLE_POST);
/* Turn on 4MB of V == P addressing so we can get to MP table */
*(int *)PTD = PG_V | PG_RW | ((u_long)KPTphys & PG_FRAME);
invltlb();
@ -454,8 +485,14 @@ mp_enable(u_int boot_addr)
panic("IO APIC setup failure");
/* install an inter-CPU IPI for TLB invalidation */
setidt(ICU_OFFSET + XINVLTLB_OFFSET, Xinvltlb,
setidt(XINVLTLB_OFFSET, Xinvltlb,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#if defined(TEST_CPUSTOP)
/* install an inter-CPU IPI for CPU stop/restart */
setidt(XCPUSTOP_OFFSET, Xcpustop,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#endif /* TEST_CPUSTOP */
#endif /* APIC_IO */
/* start each Application Processor */
@ -597,6 +634,8 @@ mptable_pass1(void)
int type;
int mustpanic;
POSTCODE(MPTABLE_PASS1_POST);
mustpanic = 0;
/* clear various tables */
@ -722,6 +761,8 @@ mptable_pass2(void)
int type;
int apic, bus, cpu, intr;
POSTCODE(MPTABLE_PASS2_POST);
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
ID_TO_IO(x) = -1; /* phy APIC ID to log CPU/IO table */
@ -1370,6 +1411,8 @@ start_all_aps(u_int boot_addr)
pt_entry_t newpt;
int *newpp;
POSTCODE(START_ALL_APS_POST);
/**
* NOTE: this needs further thought:
* where does it get released?
@ -1391,6 +1434,9 @@ start_all_aps(u_int boot_addr)
outb(CMOS_REG, BIOS_RESET);
mpbiosreason = inb(CMOS_DATA);
/* record BSP in CPU map */
all_cpus = 1;
/* start each AP */
for (x = 1; x <= mp_naps; ++x) {
@ -1462,12 +1508,17 @@ start_all_aps(u_int boot_addr)
if (cngetc() != 'n')
panic("bye-bye");
}
CHECK_PRINT("trace"); /* show checkpoints */
CHECK_PRINT("trace"); /* show checkpoints */
/* record its version info */
cpu_apic_versions[x] = cpu_apic_versions[0];
all_cpus |= (1 << x); /* record AP in CPU map */
}
/* build our map of 'other' CPUs */
other_cpus = all_cpus & ~(1 << cpuid);
/* fill in our (BSP) APIC version */
cpu_apic_versions[0] = lapic.version;
@ -1505,6 +1556,8 @@ install_ap_tramp(u_int boot_addr)
u_int16_t *dst16;
u_int32_t *dst32;
POSTCODE(INSTALL_AP_TRAMP_POST);
for (x = 0; x < size; ++x)
*dst++ = *src++;
@ -1554,6 +1607,8 @@ start_ap(int logical_cpu, u_int boot_addr)
int cpus;
u_long icr_lo, icr_hi;
POSTCODE(START_AP_POST);
/* get the PHYSICAL APIC ID# */
physical_cpu = CPU_TO_ID(logical_cpu);
@ -1638,7 +1693,7 @@ smp_invltlb(void)
{
#if defined(APIC_IO)
if (smp_active && invltlb_ok)
all_but_self_ipi(ICU_OFFSET + XINVLTLB_OFFSET);
all_but_self_ipi(XINVLTLB_OFFSET);
#endif /* APIC_IO */
}
@ -1665,3 +1720,101 @@ invltlb(void)
/* send a message to the other CPUs */
smp_invltlb();
}
#if defined(TEST_CPUSTOP)
/*
* When called the executing CPU will send an IPI to all other CPUs
* requesting that they halt execution.
*
* Usually (but not necessarily) called with 'other_cpus' as its arg.
*
* - Signals all CPUs in map to stop.
* - Waits for each to stop.
*
* Returns:
* -1: error
* 0: NA
* 1: ok
*
* XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs
* from executing at same time.
*/
int
stop_cpus( u_int map )
{
if (!smp_active)
return 0;
stopped_cpus = 0;
/* send IPI to all CPUs in map */
#if defined(DEBUG_CPUSTOP)
db_printf("\nCPU%d stopping CPUs: 0x%08x\n", cpuid, map);
#endif /* DEBUG_CPUSTOP */
#if 0
selected_apic_ipi(map, XCPUSTOP_OFFSET, APIC_DELMODE_FIXED);
#else
all_but_self_ipi(XCPUSTOP_OFFSET);
#endif
#if defined(DEBUG_CPUSTOP)
db_printf(" stopped_cpus: 0x%08x, map: 0x%08x, spin\n",
stopped_cpus, map);
#endif /* DEBUG_CPUSTOP */
while (stopped_cpus != map) {
#if 0
/* spin */ ;
#else
POSTCODE(stopped_cpus & 0xff);
#endif
}
#if defined(DEBUG_CPUSTOP)
db_printf(" spun\nstopped\n");
#endif /* DEBUG_CPUSTOP */
return 1;
}
/*
* Called by a CPU to restart stopped CPUs.
*
* Usually (but not necessarily) called with 'stopped_cpus' as its arg.
*
* - Signals all CPUs in map to restart.
* - Waits for each to restart.
*
* Returns:
* -1: error
* 0: NA
* 1: ok
*/
int
restart_cpus( u_int map )
{
if (!smp_active)
return 0;
started_cpus = map; /* signal other cpus to restart */
#if defined(DEBUG_CPUSTOP)
db_printf("\nCPU%d restarting CPUs: 0x%08x (0x%08x)\n",
cpuid, started_cpus, stopped_cpus);
#endif /* DEBUG_CPUSTOP */
while (started_cpus) /* wait for each to clear its bit */
/* spin */ ;
#if defined(DEBUG_CPUSTOP)
db_printf(" restarted\n");
#endif /* DEBUG_CPUSTOP */
return 1;
}
#endif /* TEST_CPUSTOP */

View File

@ -45,7 +45,7 @@
#include <machine/mpapic.h>
#include <machine/cpufunc.h>
#include <machine/segments.h>
#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG */
#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG, TEST_CPUSTOP */
#include <machine/tss.h>
#include <machine/specialreg.h>
@ -57,23 +57,24 @@
#include <i386/isa/intr_machdep.h> /* Xinvltlb() */
#endif /* APIC_IO */
#define WARMBOOT_TARGET 0
#define WARMBOOT_OFF (KERNBASE + 0x0467)
#define WARMBOOT_SEG (KERNBASE + 0x0469)
#define WARMBOOT_TARGET 0
#define WARMBOOT_OFF (KERNBASE + 0x0467)
#define WARMBOOT_SEG (KERNBASE + 0x0469)
#define BIOS_BASE (0xf0000)
#define BIOS_SIZE (0x10000)
#define BIOS_COUNT (BIOS_SIZE/4)
#define BIOS_BASE (0xf0000)
#define BIOS_SIZE (0x10000)
#define BIOS_COUNT (BIOS_SIZE/4)
#define CMOS_REG (0x70)
#define CMOS_DATA (0x71)
#define BIOS_RESET (0x0f)
#define BIOS_WARM (0x0a)
#define CMOS_REG (0x70)
#define CMOS_DATA (0x71)
#define BIOS_RESET (0x0f)
#define BIOS_WARM (0x0a)
#define PROCENTRY_FLAG_EN 0x01
#define PROCENTRY_FLAG_BP 0x02
#define IOAPICENTRY_FLAG_EN 0x01
/* MP Floating Pointer Structure */
typedef struct MPFPS {
char signature[4];
@ -185,6 +186,23 @@ typedef struct BASETABLE_ENTRY {
#endif /* CHECK_POINTS */
/*
* Values to send to the POST hardware.
*/
#ifndef POSTCODE
#define POSTCODE(X)
#endif
#define MP_BOOTADDRESS_POST 0x10
#define MP_PROBE_POST 0x11
#define MP_START_POST 0x12
#define MP_ANNOUNCE_POST 0x13
#define MPTABLE_PASS1_POST 0x14
#define MPTABLE_PASS2_POST 0x15
#define MP_ENABLE_POST 0x16
#define START_ALL_APS_POST 0x17
#define INSTALL_AP_TRAMP_POST 0x18
#define START_AP_POST 0x19
/** FIXME: what system files declare these??? */
extern struct region_descriptor r_gdt, r_idt;
@ -208,6 +226,9 @@ int cpu_num_to_apic_id[NAPICID];
int io_num_to_apic_id[NAPICID];
int apic_id_to_logical[NAPICID];
/* Bitmap of all available CPUs */
u_int all_cpus;
/* Boot of AP uses this PTD */
u_int *bootPTD;
@ -244,6 +265,8 @@ static int start_ap(int logicalCpu, u_int boot_addr);
u_int
mp_bootaddress(u_int basemem)
{
POSTCODE(MP_BOOTADDRESS_POST);
base_memory = basemem * 1024; /* convert to bytes */
boot_address = base_memory & ~0xfff; /* round down to 4k boundary */
@ -261,6 +284,8 @@ mp_probe(void)
u_long segment;
u_int32_t target;
POSTCODE(MP_PROBE_POST);
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
@ -302,6 +327,8 @@ mp_probe(void)
void
mp_start(void)
{
POSTCODE(MP_START_POST);
/* look for MP capable motherboard */
if (mp_capable)
mp_enable(boot_address);
@ -318,6 +345,8 @@ mp_announce(void)
{
int x;
POSTCODE(MP_ANNOUNCE_POST);
printf("FreeBSD/SMP: Multiprocessor motherboard\n");
printf(" cpu0 (BSP): apic id: %d", CPU_TO_ID(0));
printf(", version: 0x%08x", cpu_apic_versions[0]);
@ -389,13 +418,13 @@ configure_local_apic(void)
/* setup lint1 to handle NMI */
#if 1
/** XXX FIXME:
* should we arrange for ALL CPUs to catch NMI???
* it would probably crash, so for now only the BSP
* will catch it
/** XXX FIXME:
* should we arrange for ALL CPUs to catch NMI???
* it would probably crash, so for now only the BSP
* will catch it
*/
if (cpuid != 0)
return;
return;
#endif /* 0/1 */
temp = lapic.lvt_lint1;
@ -408,7 +437,7 @@ configure_local_apic(void)
lapic.lvt_lint1 = temp;
}
#endif /* APIC_IO */
#endif /* APIC_IO */
/*******************************************************************
@ -427,6 +456,8 @@ mp_enable(u_int boot_addr)
u_int ux;
#endif /* APIC_IO */
POSTCODE(MP_ENABLE_POST);
/* Turn on 4MB of V == P addressing so we can get to MP table */
*(int *)PTD = PG_V | PG_RW | ((u_long)KPTphys & PG_FRAME);
invltlb();
@ -454,8 +485,14 @@ mp_enable(u_int boot_addr)
panic("IO APIC setup failure");
/* install an inter-CPU IPI for TLB invalidation */
setidt(ICU_OFFSET + XINVLTLB_OFFSET, Xinvltlb,
setidt(XINVLTLB_OFFSET, Xinvltlb,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#if defined(TEST_CPUSTOP)
/* install an inter-CPU IPI for CPU stop/restart */
setidt(XCPUSTOP_OFFSET, Xcpustop,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#endif /* TEST_CPUSTOP */
#endif /* APIC_IO */
/* start each Application Processor */
@ -597,6 +634,8 @@ mptable_pass1(void)
int type;
int mustpanic;
POSTCODE(MPTABLE_PASS1_POST);
mustpanic = 0;
/* clear various tables */
@ -722,6 +761,8 @@ mptable_pass2(void)
int type;
int apic, bus, cpu, intr;
POSTCODE(MPTABLE_PASS2_POST);
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
ID_TO_IO(x) = -1; /* phy APIC ID to log CPU/IO table */
@ -1370,6 +1411,8 @@ start_all_aps(u_int boot_addr)
pt_entry_t newpt;
int *newpp;
POSTCODE(START_ALL_APS_POST);
/**
* NOTE: this needs further thought:
* where does it get released?
@ -1391,6 +1434,9 @@ start_all_aps(u_int boot_addr)
outb(CMOS_REG, BIOS_RESET);
mpbiosreason = inb(CMOS_DATA);
/* record BSP in CPU map */
all_cpus = 1;
/* start each AP */
for (x = 1; x <= mp_naps; ++x) {
@ -1462,12 +1508,17 @@ start_all_aps(u_int boot_addr)
if (cngetc() != 'n')
panic("bye-bye");
}
CHECK_PRINT("trace"); /* show checkpoints */
CHECK_PRINT("trace"); /* show checkpoints */
/* record its version info */
cpu_apic_versions[x] = cpu_apic_versions[0];
all_cpus |= (1 << x); /* record AP in CPU map */
}
/* build our map of 'other' CPUs */
other_cpus = all_cpus & ~(1 << cpuid);
/* fill in our (BSP) APIC version */
cpu_apic_versions[0] = lapic.version;
@ -1505,6 +1556,8 @@ install_ap_tramp(u_int boot_addr)
u_int16_t *dst16;
u_int32_t *dst32;
POSTCODE(INSTALL_AP_TRAMP_POST);
for (x = 0; x < size; ++x)
*dst++ = *src++;
@ -1554,6 +1607,8 @@ start_ap(int logical_cpu, u_int boot_addr)
int cpus;
u_long icr_lo, icr_hi;
POSTCODE(START_AP_POST);
/* get the PHYSICAL APIC ID# */
physical_cpu = CPU_TO_ID(logical_cpu);
@ -1638,7 +1693,7 @@ smp_invltlb(void)
{
#if defined(APIC_IO)
if (smp_active && invltlb_ok)
all_but_self_ipi(ICU_OFFSET + XINVLTLB_OFFSET);
all_but_self_ipi(XINVLTLB_OFFSET);
#endif /* APIC_IO */
}
@ -1665,3 +1720,101 @@ invltlb(void)
/* send a message to the other CPUs */
smp_invltlb();
}
#if defined(TEST_CPUSTOP)
/*
* When called the executing CPU will send an IPI to all other CPUs
* requesting that they halt execution.
*
* Usually (but not necessarily) called with 'other_cpus' as its arg.
*
* - Signals all CPUs in map to stop.
* - Waits for each to stop.
*
* Returns:
* -1: error
* 0: NA
* 1: ok
*
* XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs
* from executing at same time.
*/
int
stop_cpus( u_int map )
{
if (!smp_active)
return 0;
stopped_cpus = 0;
/* send IPI to all CPUs in map */
#if defined(DEBUG_CPUSTOP)
db_printf("\nCPU%d stopping CPUs: 0x%08x\n", cpuid, map);
#endif /* DEBUG_CPUSTOP */
#if 0
selected_apic_ipi(map, XCPUSTOP_OFFSET, APIC_DELMODE_FIXED);
#else
all_but_self_ipi(XCPUSTOP_OFFSET);
#endif
#if defined(DEBUG_CPUSTOP)
db_printf(" stopped_cpus: 0x%08x, map: 0x%08x, spin\n",
stopped_cpus, map);
#endif /* DEBUG_CPUSTOP */
while (stopped_cpus != map) {
#if 0
/* spin */ ;
#else
POSTCODE(stopped_cpus & 0xff);
#endif
}
#if defined(DEBUG_CPUSTOP)
db_printf(" spun\nstopped\n");
#endif /* DEBUG_CPUSTOP */
return 1;
}
/*
* Called by a CPU to restart stopped CPUs.
*
* Usually (but not necessarily) called with 'stopped_cpus' as its arg.
*
* - Signals all CPUs in map to restart.
* - Waits for each to restart.
*
* Returns:
* -1: error
* 0: NA
* 1: ok
*/
int
restart_cpus( u_int map )
{
if (!smp_active)
return 0;
started_cpus = map; /* signal other cpus to restart */
#if defined(DEBUG_CPUSTOP)
db_printf("\nCPU%d restarting CPUs: 0x%08x (0x%08x)\n",
cpuid, started_cpus, stopped_cpus);
#endif /* DEBUG_CPUSTOP */
while (started_cpus) /* wait for each to clear its bit */
/* spin */ ;
#if defined(DEBUG_CPUSTOP)
db_printf(" restarted\n");
#endif /* DEBUG_CPUSTOP */
return 1;
}
#endif /* TEST_CPUSTOP */

View File

@ -45,7 +45,7 @@
#include <machine/mpapic.h>
#include <machine/cpufunc.h>
#include <machine/segments.h>
#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG */
#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG, TEST_CPUSTOP */
#include <machine/tss.h>
#include <machine/specialreg.h>
@ -57,23 +57,24 @@
#include <i386/isa/intr_machdep.h> /* Xinvltlb() */
#endif /* APIC_IO */
#define WARMBOOT_TARGET 0
#define WARMBOOT_OFF (KERNBASE + 0x0467)
#define WARMBOOT_SEG (KERNBASE + 0x0469)
#define WARMBOOT_TARGET 0
#define WARMBOOT_OFF (KERNBASE + 0x0467)
#define WARMBOOT_SEG (KERNBASE + 0x0469)
#define BIOS_BASE (0xf0000)
#define BIOS_SIZE (0x10000)
#define BIOS_COUNT (BIOS_SIZE/4)
#define BIOS_BASE (0xf0000)
#define BIOS_SIZE (0x10000)
#define BIOS_COUNT (BIOS_SIZE/4)
#define CMOS_REG (0x70)
#define CMOS_DATA (0x71)
#define BIOS_RESET (0x0f)
#define BIOS_WARM (0x0a)
#define CMOS_REG (0x70)
#define CMOS_DATA (0x71)
#define BIOS_RESET (0x0f)
#define BIOS_WARM (0x0a)
#define PROCENTRY_FLAG_EN 0x01
#define PROCENTRY_FLAG_BP 0x02
#define IOAPICENTRY_FLAG_EN 0x01
/* MP Floating Pointer Structure */
typedef struct MPFPS {
char signature[4];
@ -185,6 +186,23 @@ typedef struct BASETABLE_ENTRY {
#endif /* CHECK_POINTS */
/*
* Values to send to the POST hardware.
*/
#ifndef POSTCODE
#define POSTCODE(X)
#endif
#define MP_BOOTADDRESS_POST 0x10
#define MP_PROBE_POST 0x11
#define MP_START_POST 0x12
#define MP_ANNOUNCE_POST 0x13
#define MPTABLE_PASS1_POST 0x14
#define MPTABLE_PASS2_POST 0x15
#define MP_ENABLE_POST 0x16
#define START_ALL_APS_POST 0x17
#define INSTALL_AP_TRAMP_POST 0x18
#define START_AP_POST 0x19
/** FIXME: what system files declare these??? */
extern struct region_descriptor r_gdt, r_idt;
@ -208,6 +226,9 @@ int cpu_num_to_apic_id[NAPICID];
int io_num_to_apic_id[NAPICID];
int apic_id_to_logical[NAPICID];
/* Bitmap of all available CPUs */
u_int all_cpus;
/* Boot of AP uses this PTD */
u_int *bootPTD;
@ -244,6 +265,8 @@ static int start_ap(int logicalCpu, u_int boot_addr);
u_int
mp_bootaddress(u_int basemem)
{
POSTCODE(MP_BOOTADDRESS_POST);
base_memory = basemem * 1024; /* convert to bytes */
boot_address = base_memory & ~0xfff; /* round down to 4k boundary */
@ -261,6 +284,8 @@ mp_probe(void)
u_long segment;
u_int32_t target;
POSTCODE(MP_PROBE_POST);
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
@ -302,6 +327,8 @@ mp_probe(void)
void
mp_start(void)
{
POSTCODE(MP_START_POST);
/* look for MP capable motherboard */
if (mp_capable)
mp_enable(boot_address);
@ -318,6 +345,8 @@ mp_announce(void)
{
int x;
POSTCODE(MP_ANNOUNCE_POST);
printf("FreeBSD/SMP: Multiprocessor motherboard\n");
printf(" cpu0 (BSP): apic id: %d", CPU_TO_ID(0));
printf(", version: 0x%08x", cpu_apic_versions[0]);
@ -389,13 +418,13 @@ configure_local_apic(void)
/* setup lint1 to handle NMI */
#if 1
/** XXX FIXME:
* should we arrange for ALL CPUs to catch NMI???
* it would probably crash, so for now only the BSP
* will catch it
/** XXX FIXME:
* should we arrange for ALL CPUs to catch NMI???
* it would probably crash, so for now only the BSP
* will catch it
*/
if (cpuid != 0)
return;
return;
#endif /* 0/1 */
temp = lapic.lvt_lint1;
@ -408,7 +437,7 @@ configure_local_apic(void)
lapic.lvt_lint1 = temp;
}
#endif /* APIC_IO */
#endif /* APIC_IO */
/*******************************************************************
@ -427,6 +456,8 @@ mp_enable(u_int boot_addr)
u_int ux;
#endif /* APIC_IO */
POSTCODE(MP_ENABLE_POST);
/* Turn on 4MB of V == P addressing so we can get to MP table */
*(int *)PTD = PG_V | PG_RW | ((u_long)KPTphys & PG_FRAME);
invltlb();
@ -454,8 +485,14 @@ mp_enable(u_int boot_addr)
panic("IO APIC setup failure");
/* install an inter-CPU IPI for TLB invalidation */
setidt(ICU_OFFSET + XINVLTLB_OFFSET, Xinvltlb,
setidt(XINVLTLB_OFFSET, Xinvltlb,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#if defined(TEST_CPUSTOP)
/* install an inter-CPU IPI for CPU stop/restart */
setidt(XCPUSTOP_OFFSET, Xcpustop,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#endif /* TEST_CPUSTOP */
#endif /* APIC_IO */
/* start each Application Processor */
@ -597,6 +634,8 @@ mptable_pass1(void)
int type;
int mustpanic;
POSTCODE(MPTABLE_PASS1_POST);
mustpanic = 0;
/* clear various tables */
@ -722,6 +761,8 @@ mptable_pass2(void)
int type;
int apic, bus, cpu, intr;
POSTCODE(MPTABLE_PASS2_POST);
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
ID_TO_IO(x) = -1; /* phy APIC ID to log CPU/IO table */
@ -1370,6 +1411,8 @@ start_all_aps(u_int boot_addr)
pt_entry_t newpt;
int *newpp;
POSTCODE(START_ALL_APS_POST);
/**
* NOTE: this needs further thought:
* where does it get released?
@ -1391,6 +1434,9 @@ start_all_aps(u_int boot_addr)
outb(CMOS_REG, BIOS_RESET);
mpbiosreason = inb(CMOS_DATA);
/* record BSP in CPU map */
all_cpus = 1;
/* start each AP */
for (x = 1; x <= mp_naps; ++x) {
@ -1462,12 +1508,17 @@ start_all_aps(u_int boot_addr)
if (cngetc() != 'n')
panic("bye-bye");
}
CHECK_PRINT("trace"); /* show checkpoints */
CHECK_PRINT("trace"); /* show checkpoints */
/* record its version info */
cpu_apic_versions[x] = cpu_apic_versions[0];
all_cpus |= (1 << x); /* record AP in CPU map */
}
/* build our map of 'other' CPUs */
other_cpus = all_cpus & ~(1 << cpuid);
/* fill in our (BSP) APIC version */
cpu_apic_versions[0] = lapic.version;
@ -1505,6 +1556,8 @@ install_ap_tramp(u_int boot_addr)
u_int16_t *dst16;
u_int32_t *dst32;
POSTCODE(INSTALL_AP_TRAMP_POST);
for (x = 0; x < size; ++x)
*dst++ = *src++;
@ -1554,6 +1607,8 @@ start_ap(int logical_cpu, u_int boot_addr)
int cpus;
u_long icr_lo, icr_hi;
POSTCODE(START_AP_POST);
/* get the PHYSICAL APIC ID# */
physical_cpu = CPU_TO_ID(logical_cpu);
@ -1638,7 +1693,7 @@ smp_invltlb(void)
{
#if defined(APIC_IO)
if (smp_active && invltlb_ok)
all_but_self_ipi(ICU_OFFSET + XINVLTLB_OFFSET);
all_but_self_ipi(XINVLTLB_OFFSET);
#endif /* APIC_IO */
}
@ -1665,3 +1720,101 @@ invltlb(void)
/* send a message to the other CPUs */
smp_invltlb();
}
#if defined(TEST_CPUSTOP)
/*
* When called the executing CPU will send an IPI to all other CPUs
* requesting that they halt execution.
*
* Usually (but not necessarily) called with 'other_cpus' as its arg.
*
* - Signals all CPUs in map to stop.
* - Waits for each to stop.
*
* Returns:
* -1: error
* 0: NA
* 1: ok
*
* XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs
* from executing at same time.
*/
int
stop_cpus( u_int map )
{
if (!smp_active)
return 0;
stopped_cpus = 0;
/* send IPI to all CPUs in map */
#if defined(DEBUG_CPUSTOP)
db_printf("\nCPU%d stopping CPUs: 0x%08x\n", cpuid, map);
#endif /* DEBUG_CPUSTOP */
#if 0
selected_apic_ipi(map, XCPUSTOP_OFFSET, APIC_DELMODE_FIXED);
#else
all_but_self_ipi(XCPUSTOP_OFFSET);
#endif
#if defined(DEBUG_CPUSTOP)
db_printf(" stopped_cpus: 0x%08x, map: 0x%08x, spin\n",
stopped_cpus, map);
#endif /* DEBUG_CPUSTOP */
while (stopped_cpus != map) {
#if 0
/* spin */ ;
#else
POSTCODE(stopped_cpus & 0xff);
#endif
}
#if defined(DEBUG_CPUSTOP)
db_printf(" spun\nstopped\n");
#endif /* DEBUG_CPUSTOP */
return 1;
}
/*
* Called by a CPU to restart stopped CPUs.
*
* Usually (but not necessarily) called with 'stopped_cpus' as its arg.
*
* - Signals all CPUs in map to restart.
* - Waits for each to restart.
*
* Returns:
* -1: error
* 0: NA
* 1: ok
*/
int
restart_cpus( u_int map )
{
if (!smp_active)
return 0;
started_cpus = map; /* signal other cpus to restart */
#if defined(DEBUG_CPUSTOP)
db_printf("\nCPU%d restarting CPUs: 0x%08x (0x%08x)\n",
cpuid, started_cpus, stopped_cpus);
#endif /* DEBUG_CPUSTOP */
while (started_cpus) /* wait for each to clear its bit */
/* spin */ ;
#if defined(DEBUG_CPUSTOP)
db_printf(" restarted\n");
#endif /* DEBUG_CPUSTOP */
return 1;
}
#endif /* TEST_CPUSTOP */

View File

@ -45,7 +45,7 @@
#include <machine/mpapic.h>
#include <machine/cpufunc.h>
#include <machine/segments.h>
#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG */
#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG, TEST_CPUSTOP */
#include <machine/tss.h>
#include <machine/specialreg.h>
@ -57,23 +57,24 @@
#include <i386/isa/intr_machdep.h> /* Xinvltlb() */
#endif /* APIC_IO */
#define WARMBOOT_TARGET 0
#define WARMBOOT_OFF (KERNBASE + 0x0467)
#define WARMBOOT_SEG (KERNBASE + 0x0469)
#define WARMBOOT_TARGET 0
#define WARMBOOT_OFF (KERNBASE + 0x0467)
#define WARMBOOT_SEG (KERNBASE + 0x0469)
#define BIOS_BASE (0xf0000)
#define BIOS_SIZE (0x10000)
#define BIOS_COUNT (BIOS_SIZE/4)
#define BIOS_BASE (0xf0000)
#define BIOS_SIZE (0x10000)
#define BIOS_COUNT (BIOS_SIZE/4)
#define CMOS_REG (0x70)
#define CMOS_DATA (0x71)
#define BIOS_RESET (0x0f)
#define BIOS_WARM (0x0a)
#define CMOS_REG (0x70)
#define CMOS_DATA (0x71)
#define BIOS_RESET (0x0f)
#define BIOS_WARM (0x0a)
#define PROCENTRY_FLAG_EN 0x01
#define PROCENTRY_FLAG_BP 0x02
#define IOAPICENTRY_FLAG_EN 0x01
/* MP Floating Pointer Structure */
typedef struct MPFPS {
char signature[4];
@ -185,6 +186,23 @@ typedef struct BASETABLE_ENTRY {
#endif /* CHECK_POINTS */
/*
* Values to send to the POST hardware.
*/
#ifndef POSTCODE
#define POSTCODE(X)
#endif
#define MP_BOOTADDRESS_POST 0x10
#define MP_PROBE_POST 0x11
#define MP_START_POST 0x12
#define MP_ANNOUNCE_POST 0x13
#define MPTABLE_PASS1_POST 0x14
#define MPTABLE_PASS2_POST 0x15
#define MP_ENABLE_POST 0x16
#define START_ALL_APS_POST 0x17
#define INSTALL_AP_TRAMP_POST 0x18
#define START_AP_POST 0x19
/** FIXME: what system files declare these??? */
extern struct region_descriptor r_gdt, r_idt;
@ -208,6 +226,9 @@ int cpu_num_to_apic_id[NAPICID];
int io_num_to_apic_id[NAPICID];
int apic_id_to_logical[NAPICID];
/* Bitmap of all available CPUs */
u_int all_cpus;
/* Boot of AP uses this PTD */
u_int *bootPTD;
@ -244,6 +265,8 @@ static int start_ap(int logicalCpu, u_int boot_addr);
u_int
mp_bootaddress(u_int basemem)
{
POSTCODE(MP_BOOTADDRESS_POST);
base_memory = basemem * 1024; /* convert to bytes */
boot_address = base_memory & ~0xfff; /* round down to 4k boundary */
@ -261,6 +284,8 @@ mp_probe(void)
u_long segment;
u_int32_t target;
POSTCODE(MP_PROBE_POST);
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
@ -302,6 +327,8 @@ mp_probe(void)
void
mp_start(void)
{
POSTCODE(MP_START_POST);
/* look for MP capable motherboard */
if (mp_capable)
mp_enable(boot_address);
@ -318,6 +345,8 @@ mp_announce(void)
{
int x;
POSTCODE(MP_ANNOUNCE_POST);
printf("FreeBSD/SMP: Multiprocessor motherboard\n");
printf(" cpu0 (BSP): apic id: %d", CPU_TO_ID(0));
printf(", version: 0x%08x", cpu_apic_versions[0]);
@ -389,13 +418,13 @@ configure_local_apic(void)
/* setup lint1 to handle NMI */
#if 1
/** XXX FIXME:
* should we arrange for ALL CPUs to catch NMI???
* it would probably crash, so for now only the BSP
* will catch it
/** XXX FIXME:
* should we arrange for ALL CPUs to catch NMI???
* it would probably crash, so for now only the BSP
* will catch it
*/
if (cpuid != 0)
return;
return;
#endif /* 0/1 */
temp = lapic.lvt_lint1;
@ -408,7 +437,7 @@ configure_local_apic(void)
lapic.lvt_lint1 = temp;
}
#endif /* APIC_IO */
#endif /* APIC_IO */
/*******************************************************************
@ -427,6 +456,8 @@ mp_enable(u_int boot_addr)
u_int ux;
#endif /* APIC_IO */
POSTCODE(MP_ENABLE_POST);
/* Turn on 4MB of V == P addressing so we can get to MP table */
*(int *)PTD = PG_V | PG_RW | ((u_long)KPTphys & PG_FRAME);
invltlb();
@ -454,8 +485,14 @@ mp_enable(u_int boot_addr)
panic("IO APIC setup failure");
/* install an inter-CPU IPI for TLB invalidation */
setidt(ICU_OFFSET + XINVLTLB_OFFSET, Xinvltlb,
setidt(XINVLTLB_OFFSET, Xinvltlb,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#if defined(TEST_CPUSTOP)
/* install an inter-CPU IPI for CPU stop/restart */
setidt(XCPUSTOP_OFFSET, Xcpustop,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#endif /* TEST_CPUSTOP */
#endif /* APIC_IO */
/* start each Application Processor */
@ -597,6 +634,8 @@ mptable_pass1(void)
int type;
int mustpanic;
POSTCODE(MPTABLE_PASS1_POST);
mustpanic = 0;
/* clear various tables */
@ -722,6 +761,8 @@ mptable_pass2(void)
int type;
int apic, bus, cpu, intr;
POSTCODE(MPTABLE_PASS2_POST);
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
ID_TO_IO(x) = -1; /* phy APIC ID to log CPU/IO table */
@ -1370,6 +1411,8 @@ start_all_aps(u_int boot_addr)
pt_entry_t newpt;
int *newpp;
POSTCODE(START_ALL_APS_POST);
/**
* NOTE: this needs further thought:
* where does it get released?
@ -1391,6 +1434,9 @@ start_all_aps(u_int boot_addr)
outb(CMOS_REG, BIOS_RESET);
mpbiosreason = inb(CMOS_DATA);
/* record BSP in CPU map */
all_cpus = 1;
/* start each AP */
for (x = 1; x <= mp_naps; ++x) {
@ -1462,12 +1508,17 @@ start_all_aps(u_int boot_addr)
if (cngetc() != 'n')
panic("bye-bye");
}
CHECK_PRINT("trace"); /* show checkpoints */
CHECK_PRINT("trace"); /* show checkpoints */
/* record its version info */
cpu_apic_versions[x] = cpu_apic_versions[0];
all_cpus |= (1 << x); /* record AP in CPU map */
}
/* build our map of 'other' CPUs */
other_cpus = all_cpus & ~(1 << cpuid);
/* fill in our (BSP) APIC version */
cpu_apic_versions[0] = lapic.version;
@ -1505,6 +1556,8 @@ install_ap_tramp(u_int boot_addr)
u_int16_t *dst16;
u_int32_t *dst32;
POSTCODE(INSTALL_AP_TRAMP_POST);
for (x = 0; x < size; ++x)
*dst++ = *src++;
@ -1554,6 +1607,8 @@ start_ap(int logical_cpu, u_int boot_addr)
int cpus;
u_long icr_lo, icr_hi;
POSTCODE(START_AP_POST);
/* get the PHYSICAL APIC ID# */
physical_cpu = CPU_TO_ID(logical_cpu);
@ -1638,7 +1693,7 @@ smp_invltlb(void)
{
#if defined(APIC_IO)
if (smp_active && invltlb_ok)
all_but_self_ipi(ICU_OFFSET + XINVLTLB_OFFSET);
all_but_self_ipi(XINVLTLB_OFFSET);
#endif /* APIC_IO */
}
@ -1665,3 +1720,101 @@ invltlb(void)
/* send a message to the other CPUs */
smp_invltlb();
}
#if defined(TEST_CPUSTOP)
/*
* When called the executing CPU will send an IPI to all other CPUs
* requesting that they halt execution.
*
* Usually (but not necessarily) called with 'other_cpus' as its arg.
*
* - Signals all CPUs in map to stop.
* - Waits for each to stop.
*
* Returns:
* -1: error
* 0: NA
* 1: ok
*
* XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs
* from executing at same time.
*/
int
stop_cpus( u_int map )
{
if (!smp_active)
return 0;
stopped_cpus = 0;
/* send IPI to all CPUs in map */
#if defined(DEBUG_CPUSTOP)
db_printf("\nCPU%d stopping CPUs: 0x%08x\n", cpuid, map);
#endif /* DEBUG_CPUSTOP */
#if 0
selected_apic_ipi(map, XCPUSTOP_OFFSET, APIC_DELMODE_FIXED);
#else
all_but_self_ipi(XCPUSTOP_OFFSET);
#endif
#if defined(DEBUG_CPUSTOP)
db_printf(" stopped_cpus: 0x%08x, map: 0x%08x, spin\n",
stopped_cpus, map);
#endif /* DEBUG_CPUSTOP */
while (stopped_cpus != map) {
#if 0
/* spin */ ;
#else
POSTCODE(stopped_cpus & 0xff);
#endif
}
#if defined(DEBUG_CPUSTOP)
db_printf(" spun\nstopped\n");
#endif /* DEBUG_CPUSTOP */
return 1;
}
/*
* Called by a CPU to restart stopped CPUs.
*
* Usually (but not necessarily) called with 'stopped_cpus' as its arg.
*
* - Signals all CPUs in map to restart.
* - Waits for each to restart.
*
* Returns:
* -1: error
* 0: NA
* 1: ok
*/
int
restart_cpus( u_int map )
{
if (!smp_active)
return 0;
started_cpus = map; /* signal other cpus to restart */
#if defined(DEBUG_CPUSTOP)
db_printf("\nCPU%d restarting CPUs: 0x%08x (0x%08x)\n",
cpuid, started_cpus, stopped_cpus);
#endif /* DEBUG_CPUSTOP */
while (started_cpus) /* wait for each to clear its bit */
/* spin */ ;
#if defined(DEBUG_CPUSTOP)
db_printf(" restarted\n");
#endif /* DEBUG_CPUSTOP */
return 1;
}
#endif /* TEST_CPUSTOP */

View File

@ -45,7 +45,7 @@
#include <machine/mpapic.h>
#include <machine/cpufunc.h>
#include <machine/segments.h>
#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG */
#include <machine/smptests.h> /** TEST_DEFAULT_CONFIG, TEST_CPUSTOP */
#include <machine/tss.h>
#include <machine/specialreg.h>
@ -57,23 +57,24 @@
#include <i386/isa/intr_machdep.h> /* Xinvltlb() */
#endif /* APIC_IO */
#define WARMBOOT_TARGET 0
#define WARMBOOT_OFF (KERNBASE + 0x0467)
#define WARMBOOT_SEG (KERNBASE + 0x0469)
#define WARMBOOT_TARGET 0
#define WARMBOOT_OFF (KERNBASE + 0x0467)
#define WARMBOOT_SEG (KERNBASE + 0x0469)
#define BIOS_BASE (0xf0000)
#define BIOS_SIZE (0x10000)
#define BIOS_COUNT (BIOS_SIZE/4)
#define BIOS_BASE (0xf0000)
#define BIOS_SIZE (0x10000)
#define BIOS_COUNT (BIOS_SIZE/4)
#define CMOS_REG (0x70)
#define CMOS_DATA (0x71)
#define BIOS_RESET (0x0f)
#define BIOS_WARM (0x0a)
#define CMOS_REG (0x70)
#define CMOS_DATA (0x71)
#define BIOS_RESET (0x0f)
#define BIOS_WARM (0x0a)
#define PROCENTRY_FLAG_EN 0x01
#define PROCENTRY_FLAG_BP 0x02
#define IOAPICENTRY_FLAG_EN 0x01
/* MP Floating Pointer Structure */
typedef struct MPFPS {
char signature[4];
@ -185,6 +186,23 @@ typedef struct BASETABLE_ENTRY {
#endif /* CHECK_POINTS */
/*
* Values to send to the POST hardware.
*/
#ifndef POSTCODE
#define POSTCODE(X)
#endif
#define MP_BOOTADDRESS_POST 0x10
#define MP_PROBE_POST 0x11
#define MP_START_POST 0x12
#define MP_ANNOUNCE_POST 0x13
#define MPTABLE_PASS1_POST 0x14
#define MPTABLE_PASS2_POST 0x15
#define MP_ENABLE_POST 0x16
#define START_ALL_APS_POST 0x17
#define INSTALL_AP_TRAMP_POST 0x18
#define START_AP_POST 0x19
/** FIXME: what system files declare these??? */
extern struct region_descriptor r_gdt, r_idt;
@ -208,6 +226,9 @@ int cpu_num_to_apic_id[NAPICID];
int io_num_to_apic_id[NAPICID];
int apic_id_to_logical[NAPICID];
/* Bitmap of all available CPUs */
u_int all_cpus;
/* Boot of AP uses this PTD */
u_int *bootPTD;
@ -244,6 +265,8 @@ static int start_ap(int logicalCpu, u_int boot_addr);
u_int
mp_bootaddress(u_int basemem)
{
POSTCODE(MP_BOOTADDRESS_POST);
base_memory = basemem * 1024; /* convert to bytes */
boot_address = base_memory & ~0xfff; /* round down to 4k boundary */
@ -261,6 +284,8 @@ mp_probe(void)
u_long segment;
u_int32_t target;
POSTCODE(MP_PROBE_POST);
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
@ -302,6 +327,8 @@ mp_probe(void)
void
mp_start(void)
{
POSTCODE(MP_START_POST);
/* look for MP capable motherboard */
if (mp_capable)
mp_enable(boot_address);
@ -318,6 +345,8 @@ mp_announce(void)
{
int x;
POSTCODE(MP_ANNOUNCE_POST);
printf("FreeBSD/SMP: Multiprocessor motherboard\n");
printf(" cpu0 (BSP): apic id: %d", CPU_TO_ID(0));
printf(", version: 0x%08x", cpu_apic_versions[0]);
@ -389,13 +418,13 @@ configure_local_apic(void)
/* setup lint1 to handle NMI */
#if 1
/** XXX FIXME:
* should we arrange for ALL CPUs to catch NMI???
* it would probably crash, so for now only the BSP
* will catch it
/** XXX FIXME:
* should we arrange for ALL CPUs to catch NMI???
* it would probably crash, so for now only the BSP
* will catch it
*/
if (cpuid != 0)
return;
return;
#endif /* 0/1 */
temp = lapic.lvt_lint1;
@ -408,7 +437,7 @@ configure_local_apic(void)
lapic.lvt_lint1 = temp;
}
#endif /* APIC_IO */
#endif /* APIC_IO */
/*******************************************************************
@ -427,6 +456,8 @@ mp_enable(u_int boot_addr)
u_int ux;
#endif /* APIC_IO */
POSTCODE(MP_ENABLE_POST);
/* Turn on 4MB of V == P addressing so we can get to MP table */
*(int *)PTD = PG_V | PG_RW | ((u_long)KPTphys & PG_FRAME);
invltlb();
@ -454,8 +485,14 @@ mp_enable(u_int boot_addr)
panic("IO APIC setup failure");
/* install an inter-CPU IPI for TLB invalidation */
setidt(ICU_OFFSET + XINVLTLB_OFFSET, Xinvltlb,
setidt(XINVLTLB_OFFSET, Xinvltlb,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#if defined(TEST_CPUSTOP)
/* install an inter-CPU IPI for CPU stop/restart */
setidt(XCPUSTOP_OFFSET, Xcpustop,
SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
#endif /* TEST_CPUSTOP */
#endif /* APIC_IO */
/* start each Application Processor */
@ -597,6 +634,8 @@ mptable_pass1(void)
int type;
int mustpanic;
POSTCODE(MPTABLE_PASS1_POST);
mustpanic = 0;
/* clear various tables */
@ -722,6 +761,8 @@ mptable_pass2(void)
int type;
int apic, bus, cpu, intr;
POSTCODE(MPTABLE_PASS2_POST);
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
ID_TO_IO(x) = -1; /* phy APIC ID to log CPU/IO table */
@ -1370,6 +1411,8 @@ start_all_aps(u_int boot_addr)
pt_entry_t newpt;
int *newpp;
POSTCODE(START_ALL_APS_POST);
/**
* NOTE: this needs further thought:
* where does it get released?
@ -1391,6 +1434,9 @@ start_all_aps(u_int boot_addr)
outb(CMOS_REG, BIOS_RESET);
mpbiosreason = inb(CMOS_DATA);
/* record BSP in CPU map */
all_cpus = 1;
/* start each AP */
for (x = 1; x <= mp_naps; ++x) {
@ -1462,12 +1508,17 @@ start_all_aps(u_int boot_addr)
if (cngetc() != 'n')
panic("bye-bye");
}
CHECK_PRINT("trace"); /* show checkpoints */
CHECK_PRINT("trace"); /* show checkpoints */
/* record its version info */
cpu_apic_versions[x] = cpu_apic_versions[0];
all_cpus |= (1 << x); /* record AP in CPU map */
}
/* build our map of 'other' CPUs */
other_cpus = all_cpus & ~(1 << cpuid);
/* fill in our (BSP) APIC version */
cpu_apic_versions[0] = lapic.version;
@ -1505,6 +1556,8 @@ install_ap_tramp(u_int boot_addr)
u_int16_t *dst16;
u_int32_t *dst32;
POSTCODE(INSTALL_AP_TRAMP_POST);
for (x = 0; x < size; ++x)
*dst++ = *src++;
@ -1554,6 +1607,8 @@ start_ap(int logical_cpu, u_int boot_addr)
int cpus;
u_long icr_lo, icr_hi;
POSTCODE(START_AP_POST);
/* get the PHYSICAL APIC ID# */
physical_cpu = CPU_TO_ID(logical_cpu);
@ -1638,7 +1693,7 @@ smp_invltlb(void)
{
#if defined(APIC_IO)
if (smp_active && invltlb_ok)
all_but_self_ipi(ICU_OFFSET + XINVLTLB_OFFSET);
all_but_self_ipi(XINVLTLB_OFFSET);
#endif /* APIC_IO */
}
@ -1665,3 +1720,101 @@ invltlb(void)
/* send a message to the other CPUs */
smp_invltlb();
}
#if defined(TEST_CPUSTOP)
/*
* When called the executing CPU will send an IPI to all other CPUs
* requesting that they halt execution.
*
* Usually (but not necessarily) called with 'other_cpus' as its arg.
*
* - Signals all CPUs in map to stop.
* - Waits for each to stop.
*
* Returns:
* -1: error
* 0: NA
* 1: ok
*
* XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs
* from executing at same time.
*/
int
stop_cpus( u_int map )
{
if (!smp_active)
return 0;
stopped_cpus = 0;
/* send IPI to all CPUs in map */
#if defined(DEBUG_CPUSTOP)
db_printf("\nCPU%d stopping CPUs: 0x%08x\n", cpuid, map);
#endif /* DEBUG_CPUSTOP */
#if 0
selected_apic_ipi(map, XCPUSTOP_OFFSET, APIC_DELMODE_FIXED);
#else
all_but_self_ipi(XCPUSTOP_OFFSET);
#endif
#if defined(DEBUG_CPUSTOP)
db_printf(" stopped_cpus: 0x%08x, map: 0x%08x, spin\n",
stopped_cpus, map);
#endif /* DEBUG_CPUSTOP */
while (stopped_cpus != map) {
#if 0
/* spin */ ;
#else
POSTCODE(stopped_cpus & 0xff);
#endif
}
#if defined(DEBUG_CPUSTOP)
db_printf(" spun\nstopped\n");
#endif /* DEBUG_CPUSTOP */
return 1;
}
/*
* Called by a CPU to restart stopped CPUs.
*
* Usually (but not necessarily) called with 'stopped_cpus' as its arg.
*
* - Signals all CPUs in map to restart.
* - Waits for each to restart.
*
* Returns:
* -1: error
* 0: NA
* 1: ok
*/
int
restart_cpus( u_int map )
{
if (!smp_active)
return 0;
started_cpus = map; /* signal other cpus to restart */
#if defined(DEBUG_CPUSTOP)
db_printf("\nCPU%d restarting CPUs: 0x%08x (0x%08x)\n",
cpuid, started_cpus, stopped_cpus);
#endif /* DEBUG_CPUSTOP */
while (started_cpus) /* wait for each to clear its bit */
/* spin */ ;
#if defined(DEBUG_CPUSTOP)
db_printf(" restarted\n");
#endif /* DEBUG_CPUSTOP */
return 1;
}
#endif /* TEST_CPUSTOP */