Added a test called 'LATE_START'.

This is now the default, it delays most of the MP startup to the function
machdep.c:cpu_startup().  It should be possible to move the 2 functions
found there (mp_start() & mp_announce()) even further down the path once
we know exactly where that should be...

Help from: Peter Wemm <peter@spinner.dialix.com.au>
This commit is contained in:
Steve Passe 1997-05-26 09:23:30 +00:00
parent cfca7bde42
commit 1ffa54ef38
10 changed files with 1406 additions and 1341 deletions

View file

@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
* $Id: machdep.c,v 1.242 1997/05/21 23:21:27 jdp Exp $
* $Id: machdep.c,v 1.3 1997/05/26 09:12:19 smp Exp smp $
*/
#include "npx.h"
@ -110,6 +110,7 @@
#include <machine/md_var.h>
#ifdef SMP
#include <machine/smp.h>
#include <machine/smptests.h> /** LATE_START */
#endif
#ifdef PERFMON
#include <machine/perfmon.h>
@ -213,6 +214,9 @@ cpu_startup(dummy)
*/
printf(version);
#ifdef SMP
#if defined(LATE_START)
mp_start(); /* fire up the APs and APICs */
#endif /* LATE_START */
mp_announce();
#endif
earlysetcpuclass();
@ -1381,16 +1385,24 @@ init386(first)
msgbufmapped = 1;
#ifdef SMP
/* fire up the APs and APICs */
mp_start();
/* look for the MP hardware */
mp_probe();
/* make the initial tss so cpu can get interrupt stack on syscall! */
for(x = 0; x < NCPU; x++) {
/* make an initial tss so cpu can get interrupt stack on syscall! */
SMPcommon_tss[x].tss_esp0 = (int) proc0.p_addr + UPAGES*PAGE_SIZE;
SMPcommon_tss[x].tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
SMPcommon_tss[x].tss_ioopt = (sizeof SMPcommon_tss[x]) << 16;
}
#if 0
/** XXX FIXME:
* We can't access the LOCAL APIC till mp_enable() runs. Since
* this is run by the BSP, cpunumber() should always equal 0 anyway.
*/
gsel_tss = GSEL(NGDT + cpunumber(), SEL_KPL);
#else
gsel_tss = GSEL(NGDT /** + 0 */, SEL_KPL);
#endif /** 0 */
ltr(gsel_tss);
#else
/* make an initial tss so cpu can get interrupt stack on syscall! */
@ -1399,7 +1411,7 @@ init386(first)
common_tss.tss_ioopt = (sizeof common_tss) << 16;
gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
ltr(gsel_tss);
#endif
#endif /* SMP */
dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 =
dblfault_tss.tss_esp2 = (int) &dblfault_stack[sizeof(dblfault_stack)];
@ -1441,6 +1453,10 @@ init386(first)
proc0.p_addr->u_pcb.pcb_flags = 0;
proc0.p_addr->u_pcb.pcb_cr3 = IdlePTD;
proc0.p_addr->u_pcb.pcb_mpnest = 1;
#if !defined(LATE_START)
mp_start(); /* fire up the APs and APICs */
#endif /* LATE_START */
}
int

View file

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp_machdep.c,v 1.11 1997/05/24 18:48:53 fsmp Exp $
* $Id: mp_machdep.c,v 1.5 1997/05/26 09:12:19 smp Exp smp $
*/
#include "opt_smp.h"
@ -44,7 +44,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, LATE_START */
#include <i386/i386/cons.h> /* cngetc() */
@ -67,6 +67,84 @@
#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];
void *pap;
u_char length;
u_char spec_rev;
u_char checksum;
u_char mpfb1;
u_char mpfb2;
u_char mpfb3;
u_char mpfb4;
u_char mpfb5;
} *mpfps_t;
/* MP Configuration Table Header */
typedef struct MPCTH {
char signature[4];
u_short base_table_length;
u_char spec_rev;
u_char checksum;
u_char oem_id[8];
u_char product_id[12];
void *oem_table_pointer;
u_short oem_table_size;
u_short entry_count;
void *apic_address;
u_short extended_table_length;
u_char extended_table_checksum;
u_char reserved;
} *mpcth_t;
typedef struct PROCENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char cpu_flags;
u_long cpu_signature;
u_long feature_flags;
u_long reserved1;
u_long reserved2;
} *proc_entry_ptr;
typedef struct BUSENTRY {
u_char type;
u_char bus_id;
char bus_type[6];
} *bus_entry_ptr;
typedef struct IOAPICENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char apic_flags;
void *apic_address;
} *io_apic_entry_ptr;
typedef struct INTENTRY {
u_char type;
u_char int_type;
u_short int_flags;
u_char src_bus_id;
u_char src_bus_irq;
u_char dst_apic_id;
u_char dst_apic_int;
} *int_entry_ptr;
/* descriptions of MP basetable entries */
typedef struct BASETABLE_ENTRY {
u_char type;
u_char length;
char name[16];
} basetable_entry;
/*
* this code MUST be enabled here and in mpboot.s.
* it follows the very early stages of AP boot by placing values in CMOS ram.
@ -113,12 +191,11 @@ struct proc *SMPcurproc[NCPU];
struct pcb *SMPcurpcb[NCPU];
struct timeval SMPruntime[NCPU];
int mp_ncpus; /* # of CPUs, including BSP */
int mp_naps; /* # of Applications processors */
int mp_nbusses; /* # of busses */
int mp_napics; /* # of IO APICs */
int mpenabled;
int boot_cpu_id; /* designated BSP */
int mp_ncpus; /* # of CPUs, including BSP */
int mp_naps; /* # of Applications processors */
int mp_nbusses; /* # of busses */
int mp_napics; /* # of IO APICs */
int boot_cpu_id; /* designated BSP */
vm_offset_t cpu_apic_address;
vm_offset_t io_apic_address[NAPICID]; /* NAPICID is more than enough */
@ -137,14 +214,21 @@ int apic_id_to_logical[NAPICID];
* look for MP compliant motherboard.
*/
static u_int boot_address;
static u_int base_memory;
static int mp_capable;
static u_int boot_address;
static u_int base_memory;
static int picmode; /* 0: virtual wire mode, 1: PIC mode */
static u_int mpfps;
static int search_for_sig(u_int32_t target, int count);
static int mp_probe(u_int base_top);
static void mp_enable(u_int boot_addr);
static int picmode; /* 0: virtual wire mode, 1: PIC mode */
static mpfps_t mpfps;
static int search_for_sig(u_int32_t target, int count);
static void mp_enable(u_int boot_addr);
static int mptable_pass1(void);
static int mptable_pass2(void);
static void default_mp_table(int type);
static int start_all_aps(u_int boot_addr);
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
/*
@ -163,6 +247,53 @@ mp_bootaddress(u_int basemem)
}
int
mp_probe(void)
{
int x;
u_long segment;
u_int32_t target;
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
target = (u_int32_t) (segment << 4);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
} else {
/* last 1K of base memory, effective 'top of base' passed in */
target = (u_int32_t) (base_memory - 0x400);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
}
/* search the BIOS */
target = (u_int32_t) BIOS_BASE;
if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
goto found;
/* nothing found */
mpfps = (mpfps_t)0;
mp_capable = 0;
return 0;
found: /* please forgive the 'goto'! */
/* calculate needed resources */
mpfps = (mpfps_t)x;
if (mptable_pass1())
panic("you must reconfigure your kernel");
#if defined(LATE_START)
/* create pages for (address common) cpu APIC and each IO APIC */
pmap_bootstrap_apics();
#endif /* LATE_START */
/* flag fact that we are running multiple processors */
mp_capable = 1;
return 1;
}
/*
* startup the SMP processors
*/
@ -170,19 +301,10 @@ void
mp_start(void)
{
/* look for MP capable motherboard */
if (mp_probe(base_memory))
/*
* XXX: mp_probe() now does a 1st pass of the motherboard's MP table, so
* by this point we know how many busses, INTs, etc. exist, as well as
* the addresses of the LOCAL and IO APICs.
* This means we have the info necessary for malloc()ing memory for
* boot-time MP structs, as well as pmapping the APICs to known addrs.
* So when we get private pages working we will probably want to move
* mp_enable() further down in the boot process.
*/
if (mp_capable)
mp_enable(boot_address);
else
panic("MP FPS not found, can't continue!");
panic("MP hardware not found!");
/* finish pmap initialization - turn off V==P mapping at zero */
pmap_bootstrap2();
@ -263,51 +385,6 @@ configure_local_apic(void)
/*******************************************************************
* local functions and data
*/
static int preparse_mp_table(void);
static int parse_mp_table(void);
static void default_mp_table(int type);
static int start_all_aps(u_int boot_addr);
static int
mp_probe(u_int base_top)
{
int x;
u_long segment;
u_int32_t target;
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
target = (u_int32_t) (segment << 4);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
} else {
/*last 1K of base memory, effective 'top of base' is passed in*/
target = (u_int32_t) (base_top - 0x400);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
}
/* search the BIOS */
target = (u_int32_t) BIOS_BASE;
if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
goto found;
/* nothing found */
mpfps = mpenabled = 0;
return 0;
found: /* please forgive the 'goto'! */
/* calculate needed resources */
mpfps = x;
if (preparse_mp_table())
panic("you must reconfigure your kernel");
/* flag fact that we are running multiple processors */
mpenabled = 1;
return 1;
}
/*
* start the SMP system
@ -322,10 +399,12 @@ mp_enable(u_int boot_addr)
#endif /* APIC_IO */
/* examine the MP table for needed info */
x = parse_mp_table();
x = mptable_pass2();
#if !defined(LATE_START)
/* create pages for (address common) cpu APIC and each IO APIC */
pmap_bootstrap_apics();
#endif /* LATE_START */
/* can't process default configs till the CPU APIC is pmapped */
if (x)
@ -375,82 +454,6 @@ search_for_sig(u_int32_t target, int count)
}
#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];
void *pap;
u_char length;
u_char spec_rev;
u_char checksum;
u_char mpfb1;
u_char mpfb2;
u_char mpfb3;
u_char mpfb4;
u_char mpfb5;
} *mpfps_t;
/* MP Configuration Table Header */
typedef struct MPCTH {
char signature[4];
u_short base_table_length;
u_char spec_rev;
u_char checksum;
u_char oem_id[8];
u_char product_id[12];
void *oem_table_pointer;
u_short oem_table_size;
u_short entry_count;
void *apic_address;
u_short extended_table_length;
u_char extended_table_checksum;
u_char reserved;
} *mpcth_t;
typedef struct PROCENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char cpu_flags;
u_long cpu_signature;
u_long feature_flags;
u_long reserved1;
u_long reserved2;
} *proc_entry_ptr;
typedef struct BUSENTRY {
u_char type;
u_char bus_id;
char bus_type[6];
} *bus_entry_ptr;
typedef struct IOAPICENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char apic_flags;
void *apic_address;
} *io_apic_entry_ptr;
typedef struct INTENTRY {
u_char type;
u_char int_type;
u_short int_flags;
u_char src_bus_id;
u_char src_bus_irq;
u_char dst_apic_id;
u_char dst_apic_int;
} *int_entry_ptr;
/* descriptions of MP basetable entries */
typedef struct BASETABLE_ENTRY {
u_char type;
u_char length;
char name[16];
} basetable_entry;
static basetable_entry basetable_entry_types[] =
{
{0, 20, "Processor"},
@ -532,13 +535,23 @@ static int lookup_bus_type __P((char *name));
/*
* parse an Intel MP specification table
* 1st pass on motherboard's Intel MP specification table.
*
* initializes:
* mp_ncpus = 1
*
* determines:
* cpu_apic_address (common to all CPUs)
* io_apic_address[N]
* mp_naps
* mp_nbusses
* mp_napics
* nintrs
*/
static int
preparse_mp_table(void)
mptable_pass1(void)
{
int x;
mpfps_t fps;
mpcth_t cth;
int totalSize;
void* position;
@ -548,24 +561,10 @@ preparse_mp_table(void)
mustpanic = 0;
/* clear physical APIC ID to logical CPU/IO table */
for (x = 0; x < NAPICID; ++x)
ID_TO_IO(x) = -1;
/* clear logical CPU to APIC ID table */
for (x = 0; x < NAPICID; ++x)
CPU_TO_ID(x) = -1;
/* clear logical IO to APIC ID table */
for (x = 0; x < NAPICID; ++x)
IO_TO_ID(x) = -1;
/* clear IO APIC address table */
for (x = 0; x < NAPICID; ++x)
io_apic_address[x] = ~0;
/* local pointer */
fps = (mpfps_t) mpfps;
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
io_apic_address[x] = ~0; /* IO APIC address table */
}
/* init everything to empty */
mp_naps = 0;
@ -574,21 +573,21 @@ preparse_mp_table(void)
nintrs = 0;
/* check for use of 'default' configuration */
if (fps->mpfb1 != 0) {
if (mpfps->mpfb1 != 0) {
/* use default addresses */
cpu_apic_address = DEFAULT_APIC_BASE;
io_apic_address[0] = DEFAULT_IO_APIC_BASE;
/* fill in with defaults */
mp_naps = 1;
mp_nbusses = default_data[fps->mpfb1 - 1][0];
mp_nbusses = default_data[mpfps->mpfb1 - 1][0];
#if defined(APIC_IO)
mp_napics = 1;
nintrs = 16;
#endif /* APIC_IO */
}
else {
if ((cth = fps->pap) == 0)
if ((cth = mpfps->pap) == 0)
panic("MP Configuration Table Header MISSING!");
cpu_apic_address = (vm_offset_t) cth->apic_address;
@ -664,13 +663,20 @@ preparse_mp_table(void)
/*
* parse an Intel MP specification table
* 2nd pass on motherboard's Intel MP specification table.
*
* sets:
* boot_cpu_id
* ID_TO_IO(N), phy APIC ID to log CPU/IO table
* CPU_TO_ID(N), logical CPU to APIC ID table
* IO_TO_ID(N), logical IO to APIC ID table
* bus_data[N]
* io_apic_ints[N]
*/
static int
parse_mp_table(void)
mptable_pass2(void)
{
int x;
mpfps_t fps;
mpcth_t cth;
int totalSize;
void* position;
@ -678,6 +684,13 @@ parse_mp_table(void)
int type;
int apic, bus, cpu, intr;
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
ID_TO_IO(x) = -1; /* phy APIC ID to log CPU/IO table */
CPU_TO_ID(x) = -1; /* logical CPU to APIC ID table */
IO_TO_ID(x) = -1; /* logical IO to APIC ID table */
}
/* clear bus data table */
for (x = 0; x < NBUS; ++x)
bus_data[x].bus_id = 0xff;
@ -689,21 +702,18 @@ parse_mp_table(void)
/* setup the cpu/apic mapping arrays */
boot_cpu_id = -1;
/* local pointer */
fps = (mpfps_t) mpfps;
/* record whether PIC or virtual-wire mode */
picmode = (fps->mpfb2 & 0x80) ? 1 : 0;
picmode = (mpfps->mpfb2 & 0x80) ? 1 : 0;
/* check for use of 'default' configuration */
#if defined(TEST_DEFAULT_CONFIG)
return TEST_DEFAULT_CONFIG;
#else
if (fps->mpfb1 != 0)
return fps->mpfb1; /* return default configuration type */
if (mpfps->mpfb1 != 0)
return mpfps->mpfb1; /* return default configuration type */
#endif /* TEST_DEFAULT_CONFIG */
if ((cth = fps->pap) == 0)
if ((cth = mpfps->pap) == 0)
panic("MP Configuration Table Header MISSING!");
/* walk the table, recording info of interest */
@ -1331,9 +1341,6 @@ default_mp_table(int type)
}
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
/*
* start each AP in our list
*/
@ -1378,11 +1385,8 @@ start_all_aps(u_int boot_addr)
if (!start_ap(x, boot_addr)) {
printf("AP #%d (PHY# %d) failed!\n", x, CPU_TO_ID(x));
CHECK_PRINT("trace"); /* show checkpoints */
/*
* better panic as the AP may be running loose
* somewhere
*/
printf("panic y/n? [n] ");
/* better panic as the AP may be running loose */
printf("panic y/n? [y] ");
if (cngetc() != 'n')
panic("bye-bye");
}

View file

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp_machdep.c,v 1.11 1997/05/24 18:48:53 fsmp Exp $
* $Id: mp_machdep.c,v 1.5 1997/05/26 09:12:19 smp Exp smp $
*/
#include "opt_smp.h"
@ -44,7 +44,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, LATE_START */
#include <i386/i386/cons.h> /* cngetc() */
@ -67,6 +67,84 @@
#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];
void *pap;
u_char length;
u_char spec_rev;
u_char checksum;
u_char mpfb1;
u_char mpfb2;
u_char mpfb3;
u_char mpfb4;
u_char mpfb5;
} *mpfps_t;
/* MP Configuration Table Header */
typedef struct MPCTH {
char signature[4];
u_short base_table_length;
u_char spec_rev;
u_char checksum;
u_char oem_id[8];
u_char product_id[12];
void *oem_table_pointer;
u_short oem_table_size;
u_short entry_count;
void *apic_address;
u_short extended_table_length;
u_char extended_table_checksum;
u_char reserved;
} *mpcth_t;
typedef struct PROCENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char cpu_flags;
u_long cpu_signature;
u_long feature_flags;
u_long reserved1;
u_long reserved2;
} *proc_entry_ptr;
typedef struct BUSENTRY {
u_char type;
u_char bus_id;
char bus_type[6];
} *bus_entry_ptr;
typedef struct IOAPICENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char apic_flags;
void *apic_address;
} *io_apic_entry_ptr;
typedef struct INTENTRY {
u_char type;
u_char int_type;
u_short int_flags;
u_char src_bus_id;
u_char src_bus_irq;
u_char dst_apic_id;
u_char dst_apic_int;
} *int_entry_ptr;
/* descriptions of MP basetable entries */
typedef struct BASETABLE_ENTRY {
u_char type;
u_char length;
char name[16];
} basetable_entry;
/*
* this code MUST be enabled here and in mpboot.s.
* it follows the very early stages of AP boot by placing values in CMOS ram.
@ -113,12 +191,11 @@ struct proc *SMPcurproc[NCPU];
struct pcb *SMPcurpcb[NCPU];
struct timeval SMPruntime[NCPU];
int mp_ncpus; /* # of CPUs, including BSP */
int mp_naps; /* # of Applications processors */
int mp_nbusses; /* # of busses */
int mp_napics; /* # of IO APICs */
int mpenabled;
int boot_cpu_id; /* designated BSP */
int mp_ncpus; /* # of CPUs, including BSP */
int mp_naps; /* # of Applications processors */
int mp_nbusses; /* # of busses */
int mp_napics; /* # of IO APICs */
int boot_cpu_id; /* designated BSP */
vm_offset_t cpu_apic_address;
vm_offset_t io_apic_address[NAPICID]; /* NAPICID is more than enough */
@ -137,14 +214,21 @@ int apic_id_to_logical[NAPICID];
* look for MP compliant motherboard.
*/
static u_int boot_address;
static u_int base_memory;
static int mp_capable;
static u_int boot_address;
static u_int base_memory;
static int picmode; /* 0: virtual wire mode, 1: PIC mode */
static u_int mpfps;
static int search_for_sig(u_int32_t target, int count);
static int mp_probe(u_int base_top);
static void mp_enable(u_int boot_addr);
static int picmode; /* 0: virtual wire mode, 1: PIC mode */
static mpfps_t mpfps;
static int search_for_sig(u_int32_t target, int count);
static void mp_enable(u_int boot_addr);
static int mptable_pass1(void);
static int mptable_pass2(void);
static void default_mp_table(int type);
static int start_all_aps(u_int boot_addr);
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
/*
@ -163,6 +247,53 @@ mp_bootaddress(u_int basemem)
}
int
mp_probe(void)
{
int x;
u_long segment;
u_int32_t target;
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
target = (u_int32_t) (segment << 4);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
} else {
/* last 1K of base memory, effective 'top of base' passed in */
target = (u_int32_t) (base_memory - 0x400);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
}
/* search the BIOS */
target = (u_int32_t) BIOS_BASE;
if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
goto found;
/* nothing found */
mpfps = (mpfps_t)0;
mp_capable = 0;
return 0;
found: /* please forgive the 'goto'! */
/* calculate needed resources */
mpfps = (mpfps_t)x;
if (mptable_pass1())
panic("you must reconfigure your kernel");
#if defined(LATE_START)
/* create pages for (address common) cpu APIC and each IO APIC */
pmap_bootstrap_apics();
#endif /* LATE_START */
/* flag fact that we are running multiple processors */
mp_capable = 1;
return 1;
}
/*
* startup the SMP processors
*/
@ -170,19 +301,10 @@ void
mp_start(void)
{
/* look for MP capable motherboard */
if (mp_probe(base_memory))
/*
* XXX: mp_probe() now does a 1st pass of the motherboard's MP table, so
* by this point we know how many busses, INTs, etc. exist, as well as
* the addresses of the LOCAL and IO APICs.
* This means we have the info necessary for malloc()ing memory for
* boot-time MP structs, as well as pmapping the APICs to known addrs.
* So when we get private pages working we will probably want to move
* mp_enable() further down in the boot process.
*/
if (mp_capable)
mp_enable(boot_address);
else
panic("MP FPS not found, can't continue!");
panic("MP hardware not found!");
/* finish pmap initialization - turn off V==P mapping at zero */
pmap_bootstrap2();
@ -263,51 +385,6 @@ configure_local_apic(void)
/*******************************************************************
* local functions and data
*/
static int preparse_mp_table(void);
static int parse_mp_table(void);
static void default_mp_table(int type);
static int start_all_aps(u_int boot_addr);
static int
mp_probe(u_int base_top)
{
int x;
u_long segment;
u_int32_t target;
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
target = (u_int32_t) (segment << 4);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
} else {
/*last 1K of base memory, effective 'top of base' is passed in*/
target = (u_int32_t) (base_top - 0x400);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
}
/* search the BIOS */
target = (u_int32_t) BIOS_BASE;
if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
goto found;
/* nothing found */
mpfps = mpenabled = 0;
return 0;
found: /* please forgive the 'goto'! */
/* calculate needed resources */
mpfps = x;
if (preparse_mp_table())
panic("you must reconfigure your kernel");
/* flag fact that we are running multiple processors */
mpenabled = 1;
return 1;
}
/*
* start the SMP system
@ -322,10 +399,12 @@ mp_enable(u_int boot_addr)
#endif /* APIC_IO */
/* examine the MP table for needed info */
x = parse_mp_table();
x = mptable_pass2();
#if !defined(LATE_START)
/* create pages for (address common) cpu APIC and each IO APIC */
pmap_bootstrap_apics();
#endif /* LATE_START */
/* can't process default configs till the CPU APIC is pmapped */
if (x)
@ -375,82 +454,6 @@ search_for_sig(u_int32_t target, int count)
}
#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];
void *pap;
u_char length;
u_char spec_rev;
u_char checksum;
u_char mpfb1;
u_char mpfb2;
u_char mpfb3;
u_char mpfb4;
u_char mpfb5;
} *mpfps_t;
/* MP Configuration Table Header */
typedef struct MPCTH {
char signature[4];
u_short base_table_length;
u_char spec_rev;
u_char checksum;
u_char oem_id[8];
u_char product_id[12];
void *oem_table_pointer;
u_short oem_table_size;
u_short entry_count;
void *apic_address;
u_short extended_table_length;
u_char extended_table_checksum;
u_char reserved;
} *mpcth_t;
typedef struct PROCENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char cpu_flags;
u_long cpu_signature;
u_long feature_flags;
u_long reserved1;
u_long reserved2;
} *proc_entry_ptr;
typedef struct BUSENTRY {
u_char type;
u_char bus_id;
char bus_type[6];
} *bus_entry_ptr;
typedef struct IOAPICENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char apic_flags;
void *apic_address;
} *io_apic_entry_ptr;
typedef struct INTENTRY {
u_char type;
u_char int_type;
u_short int_flags;
u_char src_bus_id;
u_char src_bus_irq;
u_char dst_apic_id;
u_char dst_apic_int;
} *int_entry_ptr;
/* descriptions of MP basetable entries */
typedef struct BASETABLE_ENTRY {
u_char type;
u_char length;
char name[16];
} basetable_entry;
static basetable_entry basetable_entry_types[] =
{
{0, 20, "Processor"},
@ -532,13 +535,23 @@ static int lookup_bus_type __P((char *name));
/*
* parse an Intel MP specification table
* 1st pass on motherboard's Intel MP specification table.
*
* initializes:
* mp_ncpus = 1
*
* determines:
* cpu_apic_address (common to all CPUs)
* io_apic_address[N]
* mp_naps
* mp_nbusses
* mp_napics
* nintrs
*/
static int
preparse_mp_table(void)
mptable_pass1(void)
{
int x;
mpfps_t fps;
mpcth_t cth;
int totalSize;
void* position;
@ -548,24 +561,10 @@ preparse_mp_table(void)
mustpanic = 0;
/* clear physical APIC ID to logical CPU/IO table */
for (x = 0; x < NAPICID; ++x)
ID_TO_IO(x) = -1;
/* clear logical CPU to APIC ID table */
for (x = 0; x < NAPICID; ++x)
CPU_TO_ID(x) = -1;
/* clear logical IO to APIC ID table */
for (x = 0; x < NAPICID; ++x)
IO_TO_ID(x) = -1;
/* clear IO APIC address table */
for (x = 0; x < NAPICID; ++x)
io_apic_address[x] = ~0;
/* local pointer */
fps = (mpfps_t) mpfps;
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
io_apic_address[x] = ~0; /* IO APIC address table */
}
/* init everything to empty */
mp_naps = 0;
@ -574,21 +573,21 @@ preparse_mp_table(void)
nintrs = 0;
/* check for use of 'default' configuration */
if (fps->mpfb1 != 0) {
if (mpfps->mpfb1 != 0) {
/* use default addresses */
cpu_apic_address = DEFAULT_APIC_BASE;
io_apic_address[0] = DEFAULT_IO_APIC_BASE;
/* fill in with defaults */
mp_naps = 1;
mp_nbusses = default_data[fps->mpfb1 - 1][0];
mp_nbusses = default_data[mpfps->mpfb1 - 1][0];
#if defined(APIC_IO)
mp_napics = 1;
nintrs = 16;
#endif /* APIC_IO */
}
else {
if ((cth = fps->pap) == 0)
if ((cth = mpfps->pap) == 0)
panic("MP Configuration Table Header MISSING!");
cpu_apic_address = (vm_offset_t) cth->apic_address;
@ -664,13 +663,20 @@ preparse_mp_table(void)
/*
* parse an Intel MP specification table
* 2nd pass on motherboard's Intel MP specification table.
*
* sets:
* boot_cpu_id
* ID_TO_IO(N), phy APIC ID to log CPU/IO table
* CPU_TO_ID(N), logical CPU to APIC ID table
* IO_TO_ID(N), logical IO to APIC ID table
* bus_data[N]
* io_apic_ints[N]
*/
static int
parse_mp_table(void)
mptable_pass2(void)
{
int x;
mpfps_t fps;
mpcth_t cth;
int totalSize;
void* position;
@ -678,6 +684,13 @@ parse_mp_table(void)
int type;
int apic, bus, cpu, intr;
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
ID_TO_IO(x) = -1; /* phy APIC ID to log CPU/IO table */
CPU_TO_ID(x) = -1; /* logical CPU to APIC ID table */
IO_TO_ID(x) = -1; /* logical IO to APIC ID table */
}
/* clear bus data table */
for (x = 0; x < NBUS; ++x)
bus_data[x].bus_id = 0xff;
@ -689,21 +702,18 @@ parse_mp_table(void)
/* setup the cpu/apic mapping arrays */
boot_cpu_id = -1;
/* local pointer */
fps = (mpfps_t) mpfps;
/* record whether PIC or virtual-wire mode */
picmode = (fps->mpfb2 & 0x80) ? 1 : 0;
picmode = (mpfps->mpfb2 & 0x80) ? 1 : 0;
/* check for use of 'default' configuration */
#if defined(TEST_DEFAULT_CONFIG)
return TEST_DEFAULT_CONFIG;
#else
if (fps->mpfb1 != 0)
return fps->mpfb1; /* return default configuration type */
if (mpfps->mpfb1 != 0)
return mpfps->mpfb1; /* return default configuration type */
#endif /* TEST_DEFAULT_CONFIG */
if ((cth = fps->pap) == 0)
if ((cth = mpfps->pap) == 0)
panic("MP Configuration Table Header MISSING!");
/* walk the table, recording info of interest */
@ -1331,9 +1341,6 @@ default_mp_table(int type)
}
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
/*
* start each AP in our list
*/
@ -1378,11 +1385,8 @@ start_all_aps(u_int boot_addr)
if (!start_ap(x, boot_addr)) {
printf("AP #%d (PHY# %d) failed!\n", x, CPU_TO_ID(x));
CHECK_PRINT("trace"); /* show checkpoints */
/*
* better panic as the AP may be running loose
* somewhere
*/
printf("panic y/n? [n] ");
/* better panic as the AP may be running loose */
printf("panic y/n? [y] ");
if (cngetc() != 'n')
panic("bye-bye");
}

View file

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp_machdep.c,v 1.11 1997/05/24 18:48:53 fsmp Exp $
* $Id: mp_machdep.c,v 1.5 1997/05/26 09:12:19 smp Exp smp $
*/
#include "opt_smp.h"
@ -44,7 +44,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, LATE_START */
#include <i386/i386/cons.h> /* cngetc() */
@ -67,6 +67,84 @@
#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];
void *pap;
u_char length;
u_char spec_rev;
u_char checksum;
u_char mpfb1;
u_char mpfb2;
u_char mpfb3;
u_char mpfb4;
u_char mpfb5;
} *mpfps_t;
/* MP Configuration Table Header */
typedef struct MPCTH {
char signature[4];
u_short base_table_length;
u_char spec_rev;
u_char checksum;
u_char oem_id[8];
u_char product_id[12];
void *oem_table_pointer;
u_short oem_table_size;
u_short entry_count;
void *apic_address;
u_short extended_table_length;
u_char extended_table_checksum;
u_char reserved;
} *mpcth_t;
typedef struct PROCENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char cpu_flags;
u_long cpu_signature;
u_long feature_flags;
u_long reserved1;
u_long reserved2;
} *proc_entry_ptr;
typedef struct BUSENTRY {
u_char type;
u_char bus_id;
char bus_type[6];
} *bus_entry_ptr;
typedef struct IOAPICENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char apic_flags;
void *apic_address;
} *io_apic_entry_ptr;
typedef struct INTENTRY {
u_char type;
u_char int_type;
u_short int_flags;
u_char src_bus_id;
u_char src_bus_irq;
u_char dst_apic_id;
u_char dst_apic_int;
} *int_entry_ptr;
/* descriptions of MP basetable entries */
typedef struct BASETABLE_ENTRY {
u_char type;
u_char length;
char name[16];
} basetable_entry;
/*
* this code MUST be enabled here and in mpboot.s.
* it follows the very early stages of AP boot by placing values in CMOS ram.
@ -113,12 +191,11 @@ struct proc *SMPcurproc[NCPU];
struct pcb *SMPcurpcb[NCPU];
struct timeval SMPruntime[NCPU];
int mp_ncpus; /* # of CPUs, including BSP */
int mp_naps; /* # of Applications processors */
int mp_nbusses; /* # of busses */
int mp_napics; /* # of IO APICs */
int mpenabled;
int boot_cpu_id; /* designated BSP */
int mp_ncpus; /* # of CPUs, including BSP */
int mp_naps; /* # of Applications processors */
int mp_nbusses; /* # of busses */
int mp_napics; /* # of IO APICs */
int boot_cpu_id; /* designated BSP */
vm_offset_t cpu_apic_address;
vm_offset_t io_apic_address[NAPICID]; /* NAPICID is more than enough */
@ -137,14 +214,21 @@ int apic_id_to_logical[NAPICID];
* look for MP compliant motherboard.
*/
static u_int boot_address;
static u_int base_memory;
static int mp_capable;
static u_int boot_address;
static u_int base_memory;
static int picmode; /* 0: virtual wire mode, 1: PIC mode */
static u_int mpfps;
static int search_for_sig(u_int32_t target, int count);
static int mp_probe(u_int base_top);
static void mp_enable(u_int boot_addr);
static int picmode; /* 0: virtual wire mode, 1: PIC mode */
static mpfps_t mpfps;
static int search_for_sig(u_int32_t target, int count);
static void mp_enable(u_int boot_addr);
static int mptable_pass1(void);
static int mptable_pass2(void);
static void default_mp_table(int type);
static int start_all_aps(u_int boot_addr);
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
/*
@ -163,6 +247,53 @@ mp_bootaddress(u_int basemem)
}
int
mp_probe(void)
{
int x;
u_long segment;
u_int32_t target;
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
target = (u_int32_t) (segment << 4);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
} else {
/* last 1K of base memory, effective 'top of base' passed in */
target = (u_int32_t) (base_memory - 0x400);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
}
/* search the BIOS */
target = (u_int32_t) BIOS_BASE;
if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
goto found;
/* nothing found */
mpfps = (mpfps_t)0;
mp_capable = 0;
return 0;
found: /* please forgive the 'goto'! */
/* calculate needed resources */
mpfps = (mpfps_t)x;
if (mptable_pass1())
panic("you must reconfigure your kernel");
#if defined(LATE_START)
/* create pages for (address common) cpu APIC and each IO APIC */
pmap_bootstrap_apics();
#endif /* LATE_START */
/* flag fact that we are running multiple processors */
mp_capable = 1;
return 1;
}
/*
* startup the SMP processors
*/
@ -170,19 +301,10 @@ void
mp_start(void)
{
/* look for MP capable motherboard */
if (mp_probe(base_memory))
/*
* XXX: mp_probe() now does a 1st pass of the motherboard's MP table, so
* by this point we know how many busses, INTs, etc. exist, as well as
* the addresses of the LOCAL and IO APICs.
* This means we have the info necessary for malloc()ing memory for
* boot-time MP structs, as well as pmapping the APICs to known addrs.
* So when we get private pages working we will probably want to move
* mp_enable() further down in the boot process.
*/
if (mp_capable)
mp_enable(boot_address);
else
panic("MP FPS not found, can't continue!");
panic("MP hardware not found!");
/* finish pmap initialization - turn off V==P mapping at zero */
pmap_bootstrap2();
@ -263,51 +385,6 @@ configure_local_apic(void)
/*******************************************************************
* local functions and data
*/
static int preparse_mp_table(void);
static int parse_mp_table(void);
static void default_mp_table(int type);
static int start_all_aps(u_int boot_addr);
static int
mp_probe(u_int base_top)
{
int x;
u_long segment;
u_int32_t target;
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
target = (u_int32_t) (segment << 4);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
} else {
/*last 1K of base memory, effective 'top of base' is passed in*/
target = (u_int32_t) (base_top - 0x400);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
}
/* search the BIOS */
target = (u_int32_t) BIOS_BASE;
if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
goto found;
/* nothing found */
mpfps = mpenabled = 0;
return 0;
found: /* please forgive the 'goto'! */
/* calculate needed resources */
mpfps = x;
if (preparse_mp_table())
panic("you must reconfigure your kernel");
/* flag fact that we are running multiple processors */
mpenabled = 1;
return 1;
}
/*
* start the SMP system
@ -322,10 +399,12 @@ mp_enable(u_int boot_addr)
#endif /* APIC_IO */
/* examine the MP table for needed info */
x = parse_mp_table();
x = mptable_pass2();
#if !defined(LATE_START)
/* create pages for (address common) cpu APIC and each IO APIC */
pmap_bootstrap_apics();
#endif /* LATE_START */
/* can't process default configs till the CPU APIC is pmapped */
if (x)
@ -375,82 +454,6 @@ search_for_sig(u_int32_t target, int count)
}
#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];
void *pap;
u_char length;
u_char spec_rev;
u_char checksum;
u_char mpfb1;
u_char mpfb2;
u_char mpfb3;
u_char mpfb4;
u_char mpfb5;
} *mpfps_t;
/* MP Configuration Table Header */
typedef struct MPCTH {
char signature[4];
u_short base_table_length;
u_char spec_rev;
u_char checksum;
u_char oem_id[8];
u_char product_id[12];
void *oem_table_pointer;
u_short oem_table_size;
u_short entry_count;
void *apic_address;
u_short extended_table_length;
u_char extended_table_checksum;
u_char reserved;
} *mpcth_t;
typedef struct PROCENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char cpu_flags;
u_long cpu_signature;
u_long feature_flags;
u_long reserved1;
u_long reserved2;
} *proc_entry_ptr;
typedef struct BUSENTRY {
u_char type;
u_char bus_id;
char bus_type[6];
} *bus_entry_ptr;
typedef struct IOAPICENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char apic_flags;
void *apic_address;
} *io_apic_entry_ptr;
typedef struct INTENTRY {
u_char type;
u_char int_type;
u_short int_flags;
u_char src_bus_id;
u_char src_bus_irq;
u_char dst_apic_id;
u_char dst_apic_int;
} *int_entry_ptr;
/* descriptions of MP basetable entries */
typedef struct BASETABLE_ENTRY {
u_char type;
u_char length;
char name[16];
} basetable_entry;
static basetable_entry basetable_entry_types[] =
{
{0, 20, "Processor"},
@ -532,13 +535,23 @@ static int lookup_bus_type __P((char *name));
/*
* parse an Intel MP specification table
* 1st pass on motherboard's Intel MP specification table.
*
* initializes:
* mp_ncpus = 1
*
* determines:
* cpu_apic_address (common to all CPUs)
* io_apic_address[N]
* mp_naps
* mp_nbusses
* mp_napics
* nintrs
*/
static int
preparse_mp_table(void)
mptable_pass1(void)
{
int x;
mpfps_t fps;
mpcth_t cth;
int totalSize;
void* position;
@ -548,24 +561,10 @@ preparse_mp_table(void)
mustpanic = 0;
/* clear physical APIC ID to logical CPU/IO table */
for (x = 0; x < NAPICID; ++x)
ID_TO_IO(x) = -1;
/* clear logical CPU to APIC ID table */
for (x = 0; x < NAPICID; ++x)
CPU_TO_ID(x) = -1;
/* clear logical IO to APIC ID table */
for (x = 0; x < NAPICID; ++x)
IO_TO_ID(x) = -1;
/* clear IO APIC address table */
for (x = 0; x < NAPICID; ++x)
io_apic_address[x] = ~0;
/* local pointer */
fps = (mpfps_t) mpfps;
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
io_apic_address[x] = ~0; /* IO APIC address table */
}
/* init everything to empty */
mp_naps = 0;
@ -574,21 +573,21 @@ preparse_mp_table(void)
nintrs = 0;
/* check for use of 'default' configuration */
if (fps->mpfb1 != 0) {
if (mpfps->mpfb1 != 0) {
/* use default addresses */
cpu_apic_address = DEFAULT_APIC_BASE;
io_apic_address[0] = DEFAULT_IO_APIC_BASE;
/* fill in with defaults */
mp_naps = 1;
mp_nbusses = default_data[fps->mpfb1 - 1][0];
mp_nbusses = default_data[mpfps->mpfb1 - 1][0];
#if defined(APIC_IO)
mp_napics = 1;
nintrs = 16;
#endif /* APIC_IO */
}
else {
if ((cth = fps->pap) == 0)
if ((cth = mpfps->pap) == 0)
panic("MP Configuration Table Header MISSING!");
cpu_apic_address = (vm_offset_t) cth->apic_address;
@ -664,13 +663,20 @@ preparse_mp_table(void)
/*
* parse an Intel MP specification table
* 2nd pass on motherboard's Intel MP specification table.
*
* sets:
* boot_cpu_id
* ID_TO_IO(N), phy APIC ID to log CPU/IO table
* CPU_TO_ID(N), logical CPU to APIC ID table
* IO_TO_ID(N), logical IO to APIC ID table
* bus_data[N]
* io_apic_ints[N]
*/
static int
parse_mp_table(void)
mptable_pass2(void)
{
int x;
mpfps_t fps;
mpcth_t cth;
int totalSize;
void* position;
@ -678,6 +684,13 @@ parse_mp_table(void)
int type;
int apic, bus, cpu, intr;
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
ID_TO_IO(x) = -1; /* phy APIC ID to log CPU/IO table */
CPU_TO_ID(x) = -1; /* logical CPU to APIC ID table */
IO_TO_ID(x) = -1; /* logical IO to APIC ID table */
}
/* clear bus data table */
for (x = 0; x < NBUS; ++x)
bus_data[x].bus_id = 0xff;
@ -689,21 +702,18 @@ parse_mp_table(void)
/* setup the cpu/apic mapping arrays */
boot_cpu_id = -1;
/* local pointer */
fps = (mpfps_t) mpfps;
/* record whether PIC or virtual-wire mode */
picmode = (fps->mpfb2 & 0x80) ? 1 : 0;
picmode = (mpfps->mpfb2 & 0x80) ? 1 : 0;
/* check for use of 'default' configuration */
#if defined(TEST_DEFAULT_CONFIG)
return TEST_DEFAULT_CONFIG;
#else
if (fps->mpfb1 != 0)
return fps->mpfb1; /* return default configuration type */
if (mpfps->mpfb1 != 0)
return mpfps->mpfb1; /* return default configuration type */
#endif /* TEST_DEFAULT_CONFIG */
if ((cth = fps->pap) == 0)
if ((cth = mpfps->pap) == 0)
panic("MP Configuration Table Header MISSING!");
/* walk the table, recording info of interest */
@ -1331,9 +1341,6 @@ default_mp_table(int type)
}
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
/*
* start each AP in our list
*/
@ -1378,11 +1385,8 @@ start_all_aps(u_int boot_addr)
if (!start_ap(x, boot_addr)) {
printf("AP #%d (PHY# %d) failed!\n", x, CPU_TO_ID(x));
CHECK_PRINT("trace"); /* show checkpoints */
/*
* better panic as the AP may be running loose
* somewhere
*/
printf("panic y/n? [n] ");
/* better panic as the AP may be running loose */
printf("panic y/n? [y] ");
if (cngetc() != 'n')
panic("bye-bye");
}

View file

@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
* $Id: machdep.c,v 1.242 1997/05/21 23:21:27 jdp Exp $
* $Id: machdep.c,v 1.3 1997/05/26 09:12:19 smp Exp smp $
*/
#include "npx.h"
@ -110,6 +110,7 @@
#include <machine/md_var.h>
#ifdef SMP
#include <machine/smp.h>
#include <machine/smptests.h> /** LATE_START */
#endif
#ifdef PERFMON
#include <machine/perfmon.h>
@ -213,6 +214,9 @@ cpu_startup(dummy)
*/
printf(version);
#ifdef SMP
#if defined(LATE_START)
mp_start(); /* fire up the APs and APICs */
#endif /* LATE_START */
mp_announce();
#endif
earlysetcpuclass();
@ -1381,16 +1385,24 @@ init386(first)
msgbufmapped = 1;
#ifdef SMP
/* fire up the APs and APICs */
mp_start();
/* look for the MP hardware */
mp_probe();
/* make the initial tss so cpu can get interrupt stack on syscall! */
for(x = 0; x < NCPU; x++) {
/* make an initial tss so cpu can get interrupt stack on syscall! */
SMPcommon_tss[x].tss_esp0 = (int) proc0.p_addr + UPAGES*PAGE_SIZE;
SMPcommon_tss[x].tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
SMPcommon_tss[x].tss_ioopt = (sizeof SMPcommon_tss[x]) << 16;
}
#if 0
/** XXX FIXME:
* We can't access the LOCAL APIC till mp_enable() runs. Since
* this is run by the BSP, cpunumber() should always equal 0 anyway.
*/
gsel_tss = GSEL(NGDT + cpunumber(), SEL_KPL);
#else
gsel_tss = GSEL(NGDT /** + 0 */, SEL_KPL);
#endif /** 0 */
ltr(gsel_tss);
#else
/* make an initial tss so cpu can get interrupt stack on syscall! */
@ -1399,7 +1411,7 @@ init386(first)
common_tss.tss_ioopt = (sizeof common_tss) << 16;
gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
ltr(gsel_tss);
#endif
#endif /* SMP */
dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 =
dblfault_tss.tss_esp2 = (int) &dblfault_stack[sizeof(dblfault_stack)];
@ -1441,6 +1453,10 @@ init386(first)
proc0.p_addr->u_pcb.pcb_flags = 0;
proc0.p_addr->u_pcb.pcb_cr3 = IdlePTD;
proc0.p_addr->u_pcb.pcb_mpnest = 1;
#if !defined(LATE_START)
mp_start(); /* fire up the APs and APICs */
#endif /* LATE_START */
}
int

View file

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp_machdep.c,v 1.11 1997/05/24 18:48:53 fsmp Exp $
* $Id: mp_machdep.c,v 1.5 1997/05/26 09:12:19 smp Exp smp $
*/
#include "opt_smp.h"
@ -44,7 +44,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, LATE_START */
#include <i386/i386/cons.h> /* cngetc() */
@ -67,6 +67,84 @@
#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];
void *pap;
u_char length;
u_char spec_rev;
u_char checksum;
u_char mpfb1;
u_char mpfb2;
u_char mpfb3;
u_char mpfb4;
u_char mpfb5;
} *mpfps_t;
/* MP Configuration Table Header */
typedef struct MPCTH {
char signature[4];
u_short base_table_length;
u_char spec_rev;
u_char checksum;
u_char oem_id[8];
u_char product_id[12];
void *oem_table_pointer;
u_short oem_table_size;
u_short entry_count;
void *apic_address;
u_short extended_table_length;
u_char extended_table_checksum;
u_char reserved;
} *mpcth_t;
typedef struct PROCENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char cpu_flags;
u_long cpu_signature;
u_long feature_flags;
u_long reserved1;
u_long reserved2;
} *proc_entry_ptr;
typedef struct BUSENTRY {
u_char type;
u_char bus_id;
char bus_type[6];
} *bus_entry_ptr;
typedef struct IOAPICENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char apic_flags;
void *apic_address;
} *io_apic_entry_ptr;
typedef struct INTENTRY {
u_char type;
u_char int_type;
u_short int_flags;
u_char src_bus_id;
u_char src_bus_irq;
u_char dst_apic_id;
u_char dst_apic_int;
} *int_entry_ptr;
/* descriptions of MP basetable entries */
typedef struct BASETABLE_ENTRY {
u_char type;
u_char length;
char name[16];
} basetable_entry;
/*
* this code MUST be enabled here and in mpboot.s.
* it follows the very early stages of AP boot by placing values in CMOS ram.
@ -113,12 +191,11 @@ struct proc *SMPcurproc[NCPU];
struct pcb *SMPcurpcb[NCPU];
struct timeval SMPruntime[NCPU];
int mp_ncpus; /* # of CPUs, including BSP */
int mp_naps; /* # of Applications processors */
int mp_nbusses; /* # of busses */
int mp_napics; /* # of IO APICs */
int mpenabled;
int boot_cpu_id; /* designated BSP */
int mp_ncpus; /* # of CPUs, including BSP */
int mp_naps; /* # of Applications processors */
int mp_nbusses; /* # of busses */
int mp_napics; /* # of IO APICs */
int boot_cpu_id; /* designated BSP */
vm_offset_t cpu_apic_address;
vm_offset_t io_apic_address[NAPICID]; /* NAPICID is more than enough */
@ -137,14 +214,21 @@ int apic_id_to_logical[NAPICID];
* look for MP compliant motherboard.
*/
static u_int boot_address;
static u_int base_memory;
static int mp_capable;
static u_int boot_address;
static u_int base_memory;
static int picmode; /* 0: virtual wire mode, 1: PIC mode */
static u_int mpfps;
static int search_for_sig(u_int32_t target, int count);
static int mp_probe(u_int base_top);
static void mp_enable(u_int boot_addr);
static int picmode; /* 0: virtual wire mode, 1: PIC mode */
static mpfps_t mpfps;
static int search_for_sig(u_int32_t target, int count);
static void mp_enable(u_int boot_addr);
static int mptable_pass1(void);
static int mptable_pass2(void);
static void default_mp_table(int type);
static int start_all_aps(u_int boot_addr);
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
/*
@ -163,6 +247,53 @@ mp_bootaddress(u_int basemem)
}
int
mp_probe(void)
{
int x;
u_long segment;
u_int32_t target;
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
target = (u_int32_t) (segment << 4);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
} else {
/* last 1K of base memory, effective 'top of base' passed in */
target = (u_int32_t) (base_memory - 0x400);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
}
/* search the BIOS */
target = (u_int32_t) BIOS_BASE;
if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
goto found;
/* nothing found */
mpfps = (mpfps_t)0;
mp_capable = 0;
return 0;
found: /* please forgive the 'goto'! */
/* calculate needed resources */
mpfps = (mpfps_t)x;
if (mptable_pass1())
panic("you must reconfigure your kernel");
#if defined(LATE_START)
/* create pages for (address common) cpu APIC and each IO APIC */
pmap_bootstrap_apics();
#endif /* LATE_START */
/* flag fact that we are running multiple processors */
mp_capable = 1;
return 1;
}
/*
* startup the SMP processors
*/
@ -170,19 +301,10 @@ void
mp_start(void)
{
/* look for MP capable motherboard */
if (mp_probe(base_memory))
/*
* XXX: mp_probe() now does a 1st pass of the motherboard's MP table, so
* by this point we know how many busses, INTs, etc. exist, as well as
* the addresses of the LOCAL and IO APICs.
* This means we have the info necessary for malloc()ing memory for
* boot-time MP structs, as well as pmapping the APICs to known addrs.
* So when we get private pages working we will probably want to move
* mp_enable() further down in the boot process.
*/
if (mp_capable)
mp_enable(boot_address);
else
panic("MP FPS not found, can't continue!");
panic("MP hardware not found!");
/* finish pmap initialization - turn off V==P mapping at zero */
pmap_bootstrap2();
@ -263,51 +385,6 @@ configure_local_apic(void)
/*******************************************************************
* local functions and data
*/
static int preparse_mp_table(void);
static int parse_mp_table(void);
static void default_mp_table(int type);
static int start_all_aps(u_int boot_addr);
static int
mp_probe(u_int base_top)
{
int x;
u_long segment;
u_int32_t target;
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
target = (u_int32_t) (segment << 4);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
} else {
/*last 1K of base memory, effective 'top of base' is passed in*/
target = (u_int32_t) (base_top - 0x400);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
}
/* search the BIOS */
target = (u_int32_t) BIOS_BASE;
if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
goto found;
/* nothing found */
mpfps = mpenabled = 0;
return 0;
found: /* please forgive the 'goto'! */
/* calculate needed resources */
mpfps = x;
if (preparse_mp_table())
panic("you must reconfigure your kernel");
/* flag fact that we are running multiple processors */
mpenabled = 1;
return 1;
}
/*
* start the SMP system
@ -322,10 +399,12 @@ mp_enable(u_int boot_addr)
#endif /* APIC_IO */
/* examine the MP table for needed info */
x = parse_mp_table();
x = mptable_pass2();
#if !defined(LATE_START)
/* create pages for (address common) cpu APIC and each IO APIC */
pmap_bootstrap_apics();
#endif /* LATE_START */
/* can't process default configs till the CPU APIC is pmapped */
if (x)
@ -375,82 +454,6 @@ search_for_sig(u_int32_t target, int count)
}
#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];
void *pap;
u_char length;
u_char spec_rev;
u_char checksum;
u_char mpfb1;
u_char mpfb2;
u_char mpfb3;
u_char mpfb4;
u_char mpfb5;
} *mpfps_t;
/* MP Configuration Table Header */
typedef struct MPCTH {
char signature[4];
u_short base_table_length;
u_char spec_rev;
u_char checksum;
u_char oem_id[8];
u_char product_id[12];
void *oem_table_pointer;
u_short oem_table_size;
u_short entry_count;
void *apic_address;
u_short extended_table_length;
u_char extended_table_checksum;
u_char reserved;
} *mpcth_t;
typedef struct PROCENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char cpu_flags;
u_long cpu_signature;
u_long feature_flags;
u_long reserved1;
u_long reserved2;
} *proc_entry_ptr;
typedef struct BUSENTRY {
u_char type;
u_char bus_id;
char bus_type[6];
} *bus_entry_ptr;
typedef struct IOAPICENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char apic_flags;
void *apic_address;
} *io_apic_entry_ptr;
typedef struct INTENTRY {
u_char type;
u_char int_type;
u_short int_flags;
u_char src_bus_id;
u_char src_bus_irq;
u_char dst_apic_id;
u_char dst_apic_int;
} *int_entry_ptr;
/* descriptions of MP basetable entries */
typedef struct BASETABLE_ENTRY {
u_char type;
u_char length;
char name[16];
} basetable_entry;
static basetable_entry basetable_entry_types[] =
{
{0, 20, "Processor"},
@ -532,13 +535,23 @@ static int lookup_bus_type __P((char *name));
/*
* parse an Intel MP specification table
* 1st pass on motherboard's Intel MP specification table.
*
* initializes:
* mp_ncpus = 1
*
* determines:
* cpu_apic_address (common to all CPUs)
* io_apic_address[N]
* mp_naps
* mp_nbusses
* mp_napics
* nintrs
*/
static int
preparse_mp_table(void)
mptable_pass1(void)
{
int x;
mpfps_t fps;
mpcth_t cth;
int totalSize;
void* position;
@ -548,24 +561,10 @@ preparse_mp_table(void)
mustpanic = 0;
/* clear physical APIC ID to logical CPU/IO table */
for (x = 0; x < NAPICID; ++x)
ID_TO_IO(x) = -1;
/* clear logical CPU to APIC ID table */
for (x = 0; x < NAPICID; ++x)
CPU_TO_ID(x) = -1;
/* clear logical IO to APIC ID table */
for (x = 0; x < NAPICID; ++x)
IO_TO_ID(x) = -1;
/* clear IO APIC address table */
for (x = 0; x < NAPICID; ++x)
io_apic_address[x] = ~0;
/* local pointer */
fps = (mpfps_t) mpfps;
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
io_apic_address[x] = ~0; /* IO APIC address table */
}
/* init everything to empty */
mp_naps = 0;
@ -574,21 +573,21 @@ preparse_mp_table(void)
nintrs = 0;
/* check for use of 'default' configuration */
if (fps->mpfb1 != 0) {
if (mpfps->mpfb1 != 0) {
/* use default addresses */
cpu_apic_address = DEFAULT_APIC_BASE;
io_apic_address[0] = DEFAULT_IO_APIC_BASE;
/* fill in with defaults */
mp_naps = 1;
mp_nbusses = default_data[fps->mpfb1 - 1][0];
mp_nbusses = default_data[mpfps->mpfb1 - 1][0];
#if defined(APIC_IO)
mp_napics = 1;
nintrs = 16;
#endif /* APIC_IO */
}
else {
if ((cth = fps->pap) == 0)
if ((cth = mpfps->pap) == 0)
panic("MP Configuration Table Header MISSING!");
cpu_apic_address = (vm_offset_t) cth->apic_address;
@ -664,13 +663,20 @@ preparse_mp_table(void)
/*
* parse an Intel MP specification table
* 2nd pass on motherboard's Intel MP specification table.
*
* sets:
* boot_cpu_id
* ID_TO_IO(N), phy APIC ID to log CPU/IO table
* CPU_TO_ID(N), logical CPU to APIC ID table
* IO_TO_ID(N), logical IO to APIC ID table
* bus_data[N]
* io_apic_ints[N]
*/
static int
parse_mp_table(void)
mptable_pass2(void)
{
int x;
mpfps_t fps;
mpcth_t cth;
int totalSize;
void* position;
@ -678,6 +684,13 @@ parse_mp_table(void)
int type;
int apic, bus, cpu, intr;
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
ID_TO_IO(x) = -1; /* phy APIC ID to log CPU/IO table */
CPU_TO_ID(x) = -1; /* logical CPU to APIC ID table */
IO_TO_ID(x) = -1; /* logical IO to APIC ID table */
}
/* clear bus data table */
for (x = 0; x < NBUS; ++x)
bus_data[x].bus_id = 0xff;
@ -689,21 +702,18 @@ parse_mp_table(void)
/* setup the cpu/apic mapping arrays */
boot_cpu_id = -1;
/* local pointer */
fps = (mpfps_t) mpfps;
/* record whether PIC or virtual-wire mode */
picmode = (fps->mpfb2 & 0x80) ? 1 : 0;
picmode = (mpfps->mpfb2 & 0x80) ? 1 : 0;
/* check for use of 'default' configuration */
#if defined(TEST_DEFAULT_CONFIG)
return TEST_DEFAULT_CONFIG;
#else
if (fps->mpfb1 != 0)
return fps->mpfb1; /* return default configuration type */
if (mpfps->mpfb1 != 0)
return mpfps->mpfb1; /* return default configuration type */
#endif /* TEST_DEFAULT_CONFIG */
if ((cth = fps->pap) == 0)
if ((cth = mpfps->pap) == 0)
panic("MP Configuration Table Header MISSING!");
/* walk the table, recording info of interest */
@ -1331,9 +1341,6 @@ default_mp_table(int type)
}
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
/*
* start each AP in our list
*/
@ -1378,11 +1385,8 @@ start_all_aps(u_int boot_addr)
if (!start_ap(x, boot_addr)) {
printf("AP #%d (PHY# %d) failed!\n", x, CPU_TO_ID(x));
CHECK_PRINT("trace"); /* show checkpoints */
/*
* better panic as the AP may be running loose
* somewhere
*/
printf("panic y/n? [n] ");
/* better panic as the AP may be running loose */
printf("panic y/n? [y] ");
if (cngetc() != 'n')
panic("bye-bye");
}

View file

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp_machdep.c,v 1.11 1997/05/24 18:48:53 fsmp Exp $
* $Id: mp_machdep.c,v 1.5 1997/05/26 09:12:19 smp Exp smp $
*/
#include "opt_smp.h"
@ -44,7 +44,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, LATE_START */
#include <i386/i386/cons.h> /* cngetc() */
@ -67,6 +67,84 @@
#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];
void *pap;
u_char length;
u_char spec_rev;
u_char checksum;
u_char mpfb1;
u_char mpfb2;
u_char mpfb3;
u_char mpfb4;
u_char mpfb5;
} *mpfps_t;
/* MP Configuration Table Header */
typedef struct MPCTH {
char signature[4];
u_short base_table_length;
u_char spec_rev;
u_char checksum;
u_char oem_id[8];
u_char product_id[12];
void *oem_table_pointer;
u_short oem_table_size;
u_short entry_count;
void *apic_address;
u_short extended_table_length;
u_char extended_table_checksum;
u_char reserved;
} *mpcth_t;
typedef struct PROCENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char cpu_flags;
u_long cpu_signature;
u_long feature_flags;
u_long reserved1;
u_long reserved2;
} *proc_entry_ptr;
typedef struct BUSENTRY {
u_char type;
u_char bus_id;
char bus_type[6];
} *bus_entry_ptr;
typedef struct IOAPICENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char apic_flags;
void *apic_address;
} *io_apic_entry_ptr;
typedef struct INTENTRY {
u_char type;
u_char int_type;
u_short int_flags;
u_char src_bus_id;
u_char src_bus_irq;
u_char dst_apic_id;
u_char dst_apic_int;
} *int_entry_ptr;
/* descriptions of MP basetable entries */
typedef struct BASETABLE_ENTRY {
u_char type;
u_char length;
char name[16];
} basetable_entry;
/*
* this code MUST be enabled here and in mpboot.s.
* it follows the very early stages of AP boot by placing values in CMOS ram.
@ -113,12 +191,11 @@ struct proc *SMPcurproc[NCPU];
struct pcb *SMPcurpcb[NCPU];
struct timeval SMPruntime[NCPU];
int mp_ncpus; /* # of CPUs, including BSP */
int mp_naps; /* # of Applications processors */
int mp_nbusses; /* # of busses */
int mp_napics; /* # of IO APICs */
int mpenabled;
int boot_cpu_id; /* designated BSP */
int mp_ncpus; /* # of CPUs, including BSP */
int mp_naps; /* # of Applications processors */
int mp_nbusses; /* # of busses */
int mp_napics; /* # of IO APICs */
int boot_cpu_id; /* designated BSP */
vm_offset_t cpu_apic_address;
vm_offset_t io_apic_address[NAPICID]; /* NAPICID is more than enough */
@ -137,14 +214,21 @@ int apic_id_to_logical[NAPICID];
* look for MP compliant motherboard.
*/
static u_int boot_address;
static u_int base_memory;
static int mp_capable;
static u_int boot_address;
static u_int base_memory;
static int picmode; /* 0: virtual wire mode, 1: PIC mode */
static u_int mpfps;
static int search_for_sig(u_int32_t target, int count);
static int mp_probe(u_int base_top);
static void mp_enable(u_int boot_addr);
static int picmode; /* 0: virtual wire mode, 1: PIC mode */
static mpfps_t mpfps;
static int search_for_sig(u_int32_t target, int count);
static void mp_enable(u_int boot_addr);
static int mptable_pass1(void);
static int mptable_pass2(void);
static void default_mp_table(int type);
static int start_all_aps(u_int boot_addr);
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
/*
@ -163,6 +247,53 @@ mp_bootaddress(u_int basemem)
}
int
mp_probe(void)
{
int x;
u_long segment;
u_int32_t target;
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
target = (u_int32_t) (segment << 4);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
} else {
/* last 1K of base memory, effective 'top of base' passed in */
target = (u_int32_t) (base_memory - 0x400);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
}
/* search the BIOS */
target = (u_int32_t) BIOS_BASE;
if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
goto found;
/* nothing found */
mpfps = (mpfps_t)0;
mp_capable = 0;
return 0;
found: /* please forgive the 'goto'! */
/* calculate needed resources */
mpfps = (mpfps_t)x;
if (mptable_pass1())
panic("you must reconfigure your kernel");
#if defined(LATE_START)
/* create pages for (address common) cpu APIC and each IO APIC */
pmap_bootstrap_apics();
#endif /* LATE_START */
/* flag fact that we are running multiple processors */
mp_capable = 1;
return 1;
}
/*
* startup the SMP processors
*/
@ -170,19 +301,10 @@ void
mp_start(void)
{
/* look for MP capable motherboard */
if (mp_probe(base_memory))
/*
* XXX: mp_probe() now does a 1st pass of the motherboard's MP table, so
* by this point we know how many busses, INTs, etc. exist, as well as
* the addresses of the LOCAL and IO APICs.
* This means we have the info necessary for malloc()ing memory for
* boot-time MP structs, as well as pmapping the APICs to known addrs.
* So when we get private pages working we will probably want to move
* mp_enable() further down in the boot process.
*/
if (mp_capable)
mp_enable(boot_address);
else
panic("MP FPS not found, can't continue!");
panic("MP hardware not found!");
/* finish pmap initialization - turn off V==P mapping at zero */
pmap_bootstrap2();
@ -263,51 +385,6 @@ configure_local_apic(void)
/*******************************************************************
* local functions and data
*/
static int preparse_mp_table(void);
static int parse_mp_table(void);
static void default_mp_table(int type);
static int start_all_aps(u_int boot_addr);
static int
mp_probe(u_int base_top)
{
int x;
u_long segment;
u_int32_t target;
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
target = (u_int32_t) (segment << 4);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
} else {
/*last 1K of base memory, effective 'top of base' is passed in*/
target = (u_int32_t) (base_top - 0x400);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
}
/* search the BIOS */
target = (u_int32_t) BIOS_BASE;
if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
goto found;
/* nothing found */
mpfps = mpenabled = 0;
return 0;
found: /* please forgive the 'goto'! */
/* calculate needed resources */
mpfps = x;
if (preparse_mp_table())
panic("you must reconfigure your kernel");
/* flag fact that we are running multiple processors */
mpenabled = 1;
return 1;
}
/*
* start the SMP system
@ -322,10 +399,12 @@ mp_enable(u_int boot_addr)
#endif /* APIC_IO */
/* examine the MP table for needed info */
x = parse_mp_table();
x = mptable_pass2();
#if !defined(LATE_START)
/* create pages for (address common) cpu APIC and each IO APIC */
pmap_bootstrap_apics();
#endif /* LATE_START */
/* can't process default configs till the CPU APIC is pmapped */
if (x)
@ -375,82 +454,6 @@ search_for_sig(u_int32_t target, int count)
}
#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];
void *pap;
u_char length;
u_char spec_rev;
u_char checksum;
u_char mpfb1;
u_char mpfb2;
u_char mpfb3;
u_char mpfb4;
u_char mpfb5;
} *mpfps_t;
/* MP Configuration Table Header */
typedef struct MPCTH {
char signature[4];
u_short base_table_length;
u_char spec_rev;
u_char checksum;
u_char oem_id[8];
u_char product_id[12];
void *oem_table_pointer;
u_short oem_table_size;
u_short entry_count;
void *apic_address;
u_short extended_table_length;
u_char extended_table_checksum;
u_char reserved;
} *mpcth_t;
typedef struct PROCENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char cpu_flags;
u_long cpu_signature;
u_long feature_flags;
u_long reserved1;
u_long reserved2;
} *proc_entry_ptr;
typedef struct BUSENTRY {
u_char type;
u_char bus_id;
char bus_type[6];
} *bus_entry_ptr;
typedef struct IOAPICENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char apic_flags;
void *apic_address;
} *io_apic_entry_ptr;
typedef struct INTENTRY {
u_char type;
u_char int_type;
u_short int_flags;
u_char src_bus_id;
u_char src_bus_irq;
u_char dst_apic_id;
u_char dst_apic_int;
} *int_entry_ptr;
/* descriptions of MP basetable entries */
typedef struct BASETABLE_ENTRY {
u_char type;
u_char length;
char name[16];
} basetable_entry;
static basetable_entry basetable_entry_types[] =
{
{0, 20, "Processor"},
@ -532,13 +535,23 @@ static int lookup_bus_type __P((char *name));
/*
* parse an Intel MP specification table
* 1st pass on motherboard's Intel MP specification table.
*
* initializes:
* mp_ncpus = 1
*
* determines:
* cpu_apic_address (common to all CPUs)
* io_apic_address[N]
* mp_naps
* mp_nbusses
* mp_napics
* nintrs
*/
static int
preparse_mp_table(void)
mptable_pass1(void)
{
int x;
mpfps_t fps;
mpcth_t cth;
int totalSize;
void* position;
@ -548,24 +561,10 @@ preparse_mp_table(void)
mustpanic = 0;
/* clear physical APIC ID to logical CPU/IO table */
for (x = 0; x < NAPICID; ++x)
ID_TO_IO(x) = -1;
/* clear logical CPU to APIC ID table */
for (x = 0; x < NAPICID; ++x)
CPU_TO_ID(x) = -1;
/* clear logical IO to APIC ID table */
for (x = 0; x < NAPICID; ++x)
IO_TO_ID(x) = -1;
/* clear IO APIC address table */
for (x = 0; x < NAPICID; ++x)
io_apic_address[x] = ~0;
/* local pointer */
fps = (mpfps_t) mpfps;
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
io_apic_address[x] = ~0; /* IO APIC address table */
}
/* init everything to empty */
mp_naps = 0;
@ -574,21 +573,21 @@ preparse_mp_table(void)
nintrs = 0;
/* check for use of 'default' configuration */
if (fps->mpfb1 != 0) {
if (mpfps->mpfb1 != 0) {
/* use default addresses */
cpu_apic_address = DEFAULT_APIC_BASE;
io_apic_address[0] = DEFAULT_IO_APIC_BASE;
/* fill in with defaults */
mp_naps = 1;
mp_nbusses = default_data[fps->mpfb1 - 1][0];
mp_nbusses = default_data[mpfps->mpfb1 - 1][0];
#if defined(APIC_IO)
mp_napics = 1;
nintrs = 16;
#endif /* APIC_IO */
}
else {
if ((cth = fps->pap) == 0)
if ((cth = mpfps->pap) == 0)
panic("MP Configuration Table Header MISSING!");
cpu_apic_address = (vm_offset_t) cth->apic_address;
@ -664,13 +663,20 @@ preparse_mp_table(void)
/*
* parse an Intel MP specification table
* 2nd pass on motherboard's Intel MP specification table.
*
* sets:
* boot_cpu_id
* ID_TO_IO(N), phy APIC ID to log CPU/IO table
* CPU_TO_ID(N), logical CPU to APIC ID table
* IO_TO_ID(N), logical IO to APIC ID table
* bus_data[N]
* io_apic_ints[N]
*/
static int
parse_mp_table(void)
mptable_pass2(void)
{
int x;
mpfps_t fps;
mpcth_t cth;
int totalSize;
void* position;
@ -678,6 +684,13 @@ parse_mp_table(void)
int type;
int apic, bus, cpu, intr;
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
ID_TO_IO(x) = -1; /* phy APIC ID to log CPU/IO table */
CPU_TO_ID(x) = -1; /* logical CPU to APIC ID table */
IO_TO_ID(x) = -1; /* logical IO to APIC ID table */
}
/* clear bus data table */
for (x = 0; x < NBUS; ++x)
bus_data[x].bus_id = 0xff;
@ -689,21 +702,18 @@ parse_mp_table(void)
/* setup the cpu/apic mapping arrays */
boot_cpu_id = -1;
/* local pointer */
fps = (mpfps_t) mpfps;
/* record whether PIC or virtual-wire mode */
picmode = (fps->mpfb2 & 0x80) ? 1 : 0;
picmode = (mpfps->mpfb2 & 0x80) ? 1 : 0;
/* check for use of 'default' configuration */
#if defined(TEST_DEFAULT_CONFIG)
return TEST_DEFAULT_CONFIG;
#else
if (fps->mpfb1 != 0)
return fps->mpfb1; /* return default configuration type */
if (mpfps->mpfb1 != 0)
return mpfps->mpfb1; /* return default configuration type */
#endif /* TEST_DEFAULT_CONFIG */
if ((cth = fps->pap) == 0)
if ((cth = mpfps->pap) == 0)
panic("MP Configuration Table Header MISSING!");
/* walk the table, recording info of interest */
@ -1331,9 +1341,6 @@ default_mp_table(int type)
}
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
/*
* start each AP in our list
*/
@ -1378,11 +1385,8 @@ start_all_aps(u_int boot_addr)
if (!start_ap(x, boot_addr)) {
printf("AP #%d (PHY# %d) failed!\n", x, CPU_TO_ID(x));
CHECK_PRINT("trace"); /* show checkpoints */
/*
* better panic as the AP may be running loose
* somewhere
*/
printf("panic y/n? [n] ");
/* better panic as the AP may be running loose */
printf("panic y/n? [y] ");
if (cngetc() != 'n')
panic("bye-bye");
}

View file

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp_machdep.c,v 1.11 1997/05/24 18:48:53 fsmp Exp $
* $Id: mp_machdep.c,v 1.5 1997/05/26 09:12:19 smp Exp smp $
*/
#include "opt_smp.h"
@ -44,7 +44,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, LATE_START */
#include <i386/i386/cons.h> /* cngetc() */
@ -67,6 +67,84 @@
#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];
void *pap;
u_char length;
u_char spec_rev;
u_char checksum;
u_char mpfb1;
u_char mpfb2;
u_char mpfb3;
u_char mpfb4;
u_char mpfb5;
} *mpfps_t;
/* MP Configuration Table Header */
typedef struct MPCTH {
char signature[4];
u_short base_table_length;
u_char spec_rev;
u_char checksum;
u_char oem_id[8];
u_char product_id[12];
void *oem_table_pointer;
u_short oem_table_size;
u_short entry_count;
void *apic_address;
u_short extended_table_length;
u_char extended_table_checksum;
u_char reserved;
} *mpcth_t;
typedef struct PROCENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char cpu_flags;
u_long cpu_signature;
u_long feature_flags;
u_long reserved1;
u_long reserved2;
} *proc_entry_ptr;
typedef struct BUSENTRY {
u_char type;
u_char bus_id;
char bus_type[6];
} *bus_entry_ptr;
typedef struct IOAPICENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char apic_flags;
void *apic_address;
} *io_apic_entry_ptr;
typedef struct INTENTRY {
u_char type;
u_char int_type;
u_short int_flags;
u_char src_bus_id;
u_char src_bus_irq;
u_char dst_apic_id;
u_char dst_apic_int;
} *int_entry_ptr;
/* descriptions of MP basetable entries */
typedef struct BASETABLE_ENTRY {
u_char type;
u_char length;
char name[16];
} basetable_entry;
/*
* this code MUST be enabled here and in mpboot.s.
* it follows the very early stages of AP boot by placing values in CMOS ram.
@ -113,12 +191,11 @@ struct proc *SMPcurproc[NCPU];
struct pcb *SMPcurpcb[NCPU];
struct timeval SMPruntime[NCPU];
int mp_ncpus; /* # of CPUs, including BSP */
int mp_naps; /* # of Applications processors */
int mp_nbusses; /* # of busses */
int mp_napics; /* # of IO APICs */
int mpenabled;
int boot_cpu_id; /* designated BSP */
int mp_ncpus; /* # of CPUs, including BSP */
int mp_naps; /* # of Applications processors */
int mp_nbusses; /* # of busses */
int mp_napics; /* # of IO APICs */
int boot_cpu_id; /* designated BSP */
vm_offset_t cpu_apic_address;
vm_offset_t io_apic_address[NAPICID]; /* NAPICID is more than enough */
@ -137,14 +214,21 @@ int apic_id_to_logical[NAPICID];
* look for MP compliant motherboard.
*/
static u_int boot_address;
static u_int base_memory;
static int mp_capable;
static u_int boot_address;
static u_int base_memory;
static int picmode; /* 0: virtual wire mode, 1: PIC mode */
static u_int mpfps;
static int search_for_sig(u_int32_t target, int count);
static int mp_probe(u_int base_top);
static void mp_enable(u_int boot_addr);
static int picmode; /* 0: virtual wire mode, 1: PIC mode */
static mpfps_t mpfps;
static int search_for_sig(u_int32_t target, int count);
static void mp_enable(u_int boot_addr);
static int mptable_pass1(void);
static int mptable_pass2(void);
static void default_mp_table(int type);
static int start_all_aps(u_int boot_addr);
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
/*
@ -163,6 +247,53 @@ mp_bootaddress(u_int basemem)
}
int
mp_probe(void)
{
int x;
u_long segment;
u_int32_t target;
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
target = (u_int32_t) (segment << 4);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
} else {
/* last 1K of base memory, effective 'top of base' passed in */
target = (u_int32_t) (base_memory - 0x400);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
}
/* search the BIOS */
target = (u_int32_t) BIOS_BASE;
if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
goto found;
/* nothing found */
mpfps = (mpfps_t)0;
mp_capable = 0;
return 0;
found: /* please forgive the 'goto'! */
/* calculate needed resources */
mpfps = (mpfps_t)x;
if (mptable_pass1())
panic("you must reconfigure your kernel");
#if defined(LATE_START)
/* create pages for (address common) cpu APIC and each IO APIC */
pmap_bootstrap_apics();
#endif /* LATE_START */
/* flag fact that we are running multiple processors */
mp_capable = 1;
return 1;
}
/*
* startup the SMP processors
*/
@ -170,19 +301,10 @@ void
mp_start(void)
{
/* look for MP capable motherboard */
if (mp_probe(base_memory))
/*
* XXX: mp_probe() now does a 1st pass of the motherboard's MP table, so
* by this point we know how many busses, INTs, etc. exist, as well as
* the addresses of the LOCAL and IO APICs.
* This means we have the info necessary for malloc()ing memory for
* boot-time MP structs, as well as pmapping the APICs to known addrs.
* So when we get private pages working we will probably want to move
* mp_enable() further down in the boot process.
*/
if (mp_capable)
mp_enable(boot_address);
else
panic("MP FPS not found, can't continue!");
panic("MP hardware not found!");
/* finish pmap initialization - turn off V==P mapping at zero */
pmap_bootstrap2();
@ -263,51 +385,6 @@ configure_local_apic(void)
/*******************************************************************
* local functions and data
*/
static int preparse_mp_table(void);
static int parse_mp_table(void);
static void default_mp_table(int type);
static int start_all_aps(u_int boot_addr);
static int
mp_probe(u_int base_top)
{
int x;
u_long segment;
u_int32_t target;
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
target = (u_int32_t) (segment << 4);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
} else {
/*last 1K of base memory, effective 'top of base' is passed in*/
target = (u_int32_t) (base_top - 0x400);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
}
/* search the BIOS */
target = (u_int32_t) BIOS_BASE;
if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
goto found;
/* nothing found */
mpfps = mpenabled = 0;
return 0;
found: /* please forgive the 'goto'! */
/* calculate needed resources */
mpfps = x;
if (preparse_mp_table())
panic("you must reconfigure your kernel");
/* flag fact that we are running multiple processors */
mpenabled = 1;
return 1;
}
/*
* start the SMP system
@ -322,10 +399,12 @@ mp_enable(u_int boot_addr)
#endif /* APIC_IO */
/* examine the MP table for needed info */
x = parse_mp_table();
x = mptable_pass2();
#if !defined(LATE_START)
/* create pages for (address common) cpu APIC and each IO APIC */
pmap_bootstrap_apics();
#endif /* LATE_START */
/* can't process default configs till the CPU APIC is pmapped */
if (x)
@ -375,82 +454,6 @@ search_for_sig(u_int32_t target, int count)
}
#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];
void *pap;
u_char length;
u_char spec_rev;
u_char checksum;
u_char mpfb1;
u_char mpfb2;
u_char mpfb3;
u_char mpfb4;
u_char mpfb5;
} *mpfps_t;
/* MP Configuration Table Header */
typedef struct MPCTH {
char signature[4];
u_short base_table_length;
u_char spec_rev;
u_char checksum;
u_char oem_id[8];
u_char product_id[12];
void *oem_table_pointer;
u_short oem_table_size;
u_short entry_count;
void *apic_address;
u_short extended_table_length;
u_char extended_table_checksum;
u_char reserved;
} *mpcth_t;
typedef struct PROCENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char cpu_flags;
u_long cpu_signature;
u_long feature_flags;
u_long reserved1;
u_long reserved2;
} *proc_entry_ptr;
typedef struct BUSENTRY {
u_char type;
u_char bus_id;
char bus_type[6];
} *bus_entry_ptr;
typedef struct IOAPICENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char apic_flags;
void *apic_address;
} *io_apic_entry_ptr;
typedef struct INTENTRY {
u_char type;
u_char int_type;
u_short int_flags;
u_char src_bus_id;
u_char src_bus_irq;
u_char dst_apic_id;
u_char dst_apic_int;
} *int_entry_ptr;
/* descriptions of MP basetable entries */
typedef struct BASETABLE_ENTRY {
u_char type;
u_char length;
char name[16];
} basetable_entry;
static basetable_entry basetable_entry_types[] =
{
{0, 20, "Processor"},
@ -532,13 +535,23 @@ static int lookup_bus_type __P((char *name));
/*
* parse an Intel MP specification table
* 1st pass on motherboard's Intel MP specification table.
*
* initializes:
* mp_ncpus = 1
*
* determines:
* cpu_apic_address (common to all CPUs)
* io_apic_address[N]
* mp_naps
* mp_nbusses
* mp_napics
* nintrs
*/
static int
preparse_mp_table(void)
mptable_pass1(void)
{
int x;
mpfps_t fps;
mpcth_t cth;
int totalSize;
void* position;
@ -548,24 +561,10 @@ preparse_mp_table(void)
mustpanic = 0;
/* clear physical APIC ID to logical CPU/IO table */
for (x = 0; x < NAPICID; ++x)
ID_TO_IO(x) = -1;
/* clear logical CPU to APIC ID table */
for (x = 0; x < NAPICID; ++x)
CPU_TO_ID(x) = -1;
/* clear logical IO to APIC ID table */
for (x = 0; x < NAPICID; ++x)
IO_TO_ID(x) = -1;
/* clear IO APIC address table */
for (x = 0; x < NAPICID; ++x)
io_apic_address[x] = ~0;
/* local pointer */
fps = (mpfps_t) mpfps;
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
io_apic_address[x] = ~0; /* IO APIC address table */
}
/* init everything to empty */
mp_naps = 0;
@ -574,21 +573,21 @@ preparse_mp_table(void)
nintrs = 0;
/* check for use of 'default' configuration */
if (fps->mpfb1 != 0) {
if (mpfps->mpfb1 != 0) {
/* use default addresses */
cpu_apic_address = DEFAULT_APIC_BASE;
io_apic_address[0] = DEFAULT_IO_APIC_BASE;
/* fill in with defaults */
mp_naps = 1;
mp_nbusses = default_data[fps->mpfb1 - 1][0];
mp_nbusses = default_data[mpfps->mpfb1 - 1][0];
#if defined(APIC_IO)
mp_napics = 1;
nintrs = 16;
#endif /* APIC_IO */
}
else {
if ((cth = fps->pap) == 0)
if ((cth = mpfps->pap) == 0)
panic("MP Configuration Table Header MISSING!");
cpu_apic_address = (vm_offset_t) cth->apic_address;
@ -664,13 +663,20 @@ preparse_mp_table(void)
/*
* parse an Intel MP specification table
* 2nd pass on motherboard's Intel MP specification table.
*
* sets:
* boot_cpu_id
* ID_TO_IO(N), phy APIC ID to log CPU/IO table
* CPU_TO_ID(N), logical CPU to APIC ID table
* IO_TO_ID(N), logical IO to APIC ID table
* bus_data[N]
* io_apic_ints[N]
*/
static int
parse_mp_table(void)
mptable_pass2(void)
{
int x;
mpfps_t fps;
mpcth_t cth;
int totalSize;
void* position;
@ -678,6 +684,13 @@ parse_mp_table(void)
int type;
int apic, bus, cpu, intr;
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
ID_TO_IO(x) = -1; /* phy APIC ID to log CPU/IO table */
CPU_TO_ID(x) = -1; /* logical CPU to APIC ID table */
IO_TO_ID(x) = -1; /* logical IO to APIC ID table */
}
/* clear bus data table */
for (x = 0; x < NBUS; ++x)
bus_data[x].bus_id = 0xff;
@ -689,21 +702,18 @@ parse_mp_table(void)
/* setup the cpu/apic mapping arrays */
boot_cpu_id = -1;
/* local pointer */
fps = (mpfps_t) mpfps;
/* record whether PIC or virtual-wire mode */
picmode = (fps->mpfb2 & 0x80) ? 1 : 0;
picmode = (mpfps->mpfb2 & 0x80) ? 1 : 0;
/* check for use of 'default' configuration */
#if defined(TEST_DEFAULT_CONFIG)
return TEST_DEFAULT_CONFIG;
#else
if (fps->mpfb1 != 0)
return fps->mpfb1; /* return default configuration type */
if (mpfps->mpfb1 != 0)
return mpfps->mpfb1; /* return default configuration type */
#endif /* TEST_DEFAULT_CONFIG */
if ((cth = fps->pap) == 0)
if ((cth = mpfps->pap) == 0)
panic("MP Configuration Table Header MISSING!");
/* walk the table, recording info of interest */
@ -1331,9 +1341,6 @@ default_mp_table(int type)
}
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
/*
* start each AP in our list
*/
@ -1378,11 +1385,8 @@ start_all_aps(u_int boot_addr)
if (!start_ap(x, boot_addr)) {
printf("AP #%d (PHY# %d) failed!\n", x, CPU_TO_ID(x));
CHECK_PRINT("trace"); /* show checkpoints */
/*
* better panic as the AP may be running loose
* somewhere
*/
printf("panic y/n? [n] ");
/* better panic as the AP may be running loose */
printf("panic y/n? [y] ");
if (cngetc() != 'n')
panic("bye-bye");
}

View file

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: smptests.h,v 1.3 1997/04/28 01:08:47 fsmp Exp $
* $Id: smptests.h,v 1.1 1997/05/26 09:11:25 smp Exp smp $
*/
#ifndef _MACHINE_SMPTESTS_H_
@ -33,6 +33,11 @@
* various 'tests in progress'
*/
/*
* attempt to delay MP startup till after malloc & vm is active.
*/
#define LATE_START
/*
* use 'lowest priority' for sending IRQs to CPUs

View file

@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: mp_machdep.c,v 1.11 1997/05/24 18:48:53 fsmp Exp $
* $Id: mp_machdep.c,v 1.5 1997/05/26 09:12:19 smp Exp smp $
*/
#include "opt_smp.h"
@ -44,7 +44,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, LATE_START */
#include <i386/i386/cons.h> /* cngetc() */
@ -67,6 +67,84 @@
#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];
void *pap;
u_char length;
u_char spec_rev;
u_char checksum;
u_char mpfb1;
u_char mpfb2;
u_char mpfb3;
u_char mpfb4;
u_char mpfb5;
} *mpfps_t;
/* MP Configuration Table Header */
typedef struct MPCTH {
char signature[4];
u_short base_table_length;
u_char spec_rev;
u_char checksum;
u_char oem_id[8];
u_char product_id[12];
void *oem_table_pointer;
u_short oem_table_size;
u_short entry_count;
void *apic_address;
u_short extended_table_length;
u_char extended_table_checksum;
u_char reserved;
} *mpcth_t;
typedef struct PROCENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char cpu_flags;
u_long cpu_signature;
u_long feature_flags;
u_long reserved1;
u_long reserved2;
} *proc_entry_ptr;
typedef struct BUSENTRY {
u_char type;
u_char bus_id;
char bus_type[6];
} *bus_entry_ptr;
typedef struct IOAPICENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char apic_flags;
void *apic_address;
} *io_apic_entry_ptr;
typedef struct INTENTRY {
u_char type;
u_char int_type;
u_short int_flags;
u_char src_bus_id;
u_char src_bus_irq;
u_char dst_apic_id;
u_char dst_apic_int;
} *int_entry_ptr;
/* descriptions of MP basetable entries */
typedef struct BASETABLE_ENTRY {
u_char type;
u_char length;
char name[16];
} basetable_entry;
/*
* this code MUST be enabled here and in mpboot.s.
* it follows the very early stages of AP boot by placing values in CMOS ram.
@ -113,12 +191,11 @@ struct proc *SMPcurproc[NCPU];
struct pcb *SMPcurpcb[NCPU];
struct timeval SMPruntime[NCPU];
int mp_ncpus; /* # of CPUs, including BSP */
int mp_naps; /* # of Applications processors */
int mp_nbusses; /* # of busses */
int mp_napics; /* # of IO APICs */
int mpenabled;
int boot_cpu_id; /* designated BSP */
int mp_ncpus; /* # of CPUs, including BSP */
int mp_naps; /* # of Applications processors */
int mp_nbusses; /* # of busses */
int mp_napics; /* # of IO APICs */
int boot_cpu_id; /* designated BSP */
vm_offset_t cpu_apic_address;
vm_offset_t io_apic_address[NAPICID]; /* NAPICID is more than enough */
@ -137,14 +214,21 @@ int apic_id_to_logical[NAPICID];
* look for MP compliant motherboard.
*/
static u_int boot_address;
static u_int base_memory;
static int mp_capable;
static u_int boot_address;
static u_int base_memory;
static int picmode; /* 0: virtual wire mode, 1: PIC mode */
static u_int mpfps;
static int search_for_sig(u_int32_t target, int count);
static int mp_probe(u_int base_top);
static void mp_enable(u_int boot_addr);
static int picmode; /* 0: virtual wire mode, 1: PIC mode */
static mpfps_t mpfps;
static int search_for_sig(u_int32_t target, int count);
static void mp_enable(u_int boot_addr);
static int mptable_pass1(void);
static int mptable_pass2(void);
static void default_mp_table(int type);
static int start_all_aps(u_int boot_addr);
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
/*
@ -163,6 +247,53 @@ mp_bootaddress(u_int basemem)
}
int
mp_probe(void)
{
int x;
u_long segment;
u_int32_t target;
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
target = (u_int32_t) (segment << 4);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
} else {
/* last 1K of base memory, effective 'top of base' passed in */
target = (u_int32_t) (base_memory - 0x400);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
}
/* search the BIOS */
target = (u_int32_t) BIOS_BASE;
if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
goto found;
/* nothing found */
mpfps = (mpfps_t)0;
mp_capable = 0;
return 0;
found: /* please forgive the 'goto'! */
/* calculate needed resources */
mpfps = (mpfps_t)x;
if (mptable_pass1())
panic("you must reconfigure your kernel");
#if defined(LATE_START)
/* create pages for (address common) cpu APIC and each IO APIC */
pmap_bootstrap_apics();
#endif /* LATE_START */
/* flag fact that we are running multiple processors */
mp_capable = 1;
return 1;
}
/*
* startup the SMP processors
*/
@ -170,19 +301,10 @@ void
mp_start(void)
{
/* look for MP capable motherboard */
if (mp_probe(base_memory))
/*
* XXX: mp_probe() now does a 1st pass of the motherboard's MP table, so
* by this point we know how many busses, INTs, etc. exist, as well as
* the addresses of the LOCAL and IO APICs.
* This means we have the info necessary for malloc()ing memory for
* boot-time MP structs, as well as pmapping the APICs to known addrs.
* So when we get private pages working we will probably want to move
* mp_enable() further down in the boot process.
*/
if (mp_capable)
mp_enable(boot_address);
else
panic("MP FPS not found, can't continue!");
panic("MP hardware not found!");
/* finish pmap initialization - turn off V==P mapping at zero */
pmap_bootstrap2();
@ -263,51 +385,6 @@ configure_local_apic(void)
/*******************************************************************
* local functions and data
*/
static int preparse_mp_table(void);
static int parse_mp_table(void);
static void default_mp_table(int type);
static int start_all_aps(u_int boot_addr);
static int
mp_probe(u_int base_top)
{
int x;
u_long segment;
u_int32_t target;
/* see if EBDA exists */
if (segment = (u_long) * (u_short *) (KERNBASE + 0x40e)) {
/* search first 1K of EBDA */
target = (u_int32_t) (segment << 4);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
} else {
/*last 1K of base memory, effective 'top of base' is passed in*/
target = (u_int32_t) (base_top - 0x400);
if ((x = search_for_sig(target, 1024 / 4)) >= 0)
goto found;
}
/* search the BIOS */
target = (u_int32_t) BIOS_BASE;
if ((x = search_for_sig(target, BIOS_COUNT)) >= 0)
goto found;
/* nothing found */
mpfps = mpenabled = 0;
return 0;
found: /* please forgive the 'goto'! */
/* calculate needed resources */
mpfps = x;
if (preparse_mp_table())
panic("you must reconfigure your kernel");
/* flag fact that we are running multiple processors */
mpenabled = 1;
return 1;
}
/*
* start the SMP system
@ -322,10 +399,12 @@ mp_enable(u_int boot_addr)
#endif /* APIC_IO */
/* examine the MP table for needed info */
x = parse_mp_table();
x = mptable_pass2();
#if !defined(LATE_START)
/* create pages for (address common) cpu APIC and each IO APIC */
pmap_bootstrap_apics();
#endif /* LATE_START */
/* can't process default configs till the CPU APIC is pmapped */
if (x)
@ -375,82 +454,6 @@ search_for_sig(u_int32_t target, int count)
}
#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];
void *pap;
u_char length;
u_char spec_rev;
u_char checksum;
u_char mpfb1;
u_char mpfb2;
u_char mpfb3;
u_char mpfb4;
u_char mpfb5;
} *mpfps_t;
/* MP Configuration Table Header */
typedef struct MPCTH {
char signature[4];
u_short base_table_length;
u_char spec_rev;
u_char checksum;
u_char oem_id[8];
u_char product_id[12];
void *oem_table_pointer;
u_short oem_table_size;
u_short entry_count;
void *apic_address;
u_short extended_table_length;
u_char extended_table_checksum;
u_char reserved;
} *mpcth_t;
typedef struct PROCENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char cpu_flags;
u_long cpu_signature;
u_long feature_flags;
u_long reserved1;
u_long reserved2;
} *proc_entry_ptr;
typedef struct BUSENTRY {
u_char type;
u_char bus_id;
char bus_type[6];
} *bus_entry_ptr;
typedef struct IOAPICENTRY {
u_char type;
u_char apic_id;
u_char apic_version;
u_char apic_flags;
void *apic_address;
} *io_apic_entry_ptr;
typedef struct INTENTRY {
u_char type;
u_char int_type;
u_short int_flags;
u_char src_bus_id;
u_char src_bus_irq;
u_char dst_apic_id;
u_char dst_apic_int;
} *int_entry_ptr;
/* descriptions of MP basetable entries */
typedef struct BASETABLE_ENTRY {
u_char type;
u_char length;
char name[16];
} basetable_entry;
static basetable_entry basetable_entry_types[] =
{
{0, 20, "Processor"},
@ -532,13 +535,23 @@ static int lookup_bus_type __P((char *name));
/*
* parse an Intel MP specification table
* 1st pass on motherboard's Intel MP specification table.
*
* initializes:
* mp_ncpus = 1
*
* determines:
* cpu_apic_address (common to all CPUs)
* io_apic_address[N]
* mp_naps
* mp_nbusses
* mp_napics
* nintrs
*/
static int
preparse_mp_table(void)
mptable_pass1(void)
{
int x;
mpfps_t fps;
mpcth_t cth;
int totalSize;
void* position;
@ -548,24 +561,10 @@ preparse_mp_table(void)
mustpanic = 0;
/* clear physical APIC ID to logical CPU/IO table */
for (x = 0; x < NAPICID; ++x)
ID_TO_IO(x) = -1;
/* clear logical CPU to APIC ID table */
for (x = 0; x < NAPICID; ++x)
CPU_TO_ID(x) = -1;
/* clear logical IO to APIC ID table */
for (x = 0; x < NAPICID; ++x)
IO_TO_ID(x) = -1;
/* clear IO APIC address table */
for (x = 0; x < NAPICID; ++x)
io_apic_address[x] = ~0;
/* local pointer */
fps = (mpfps_t) mpfps;
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
io_apic_address[x] = ~0; /* IO APIC address table */
}
/* init everything to empty */
mp_naps = 0;
@ -574,21 +573,21 @@ preparse_mp_table(void)
nintrs = 0;
/* check for use of 'default' configuration */
if (fps->mpfb1 != 0) {
if (mpfps->mpfb1 != 0) {
/* use default addresses */
cpu_apic_address = DEFAULT_APIC_BASE;
io_apic_address[0] = DEFAULT_IO_APIC_BASE;
/* fill in with defaults */
mp_naps = 1;
mp_nbusses = default_data[fps->mpfb1 - 1][0];
mp_nbusses = default_data[mpfps->mpfb1 - 1][0];
#if defined(APIC_IO)
mp_napics = 1;
nintrs = 16;
#endif /* APIC_IO */
}
else {
if ((cth = fps->pap) == 0)
if ((cth = mpfps->pap) == 0)
panic("MP Configuration Table Header MISSING!");
cpu_apic_address = (vm_offset_t) cth->apic_address;
@ -664,13 +663,20 @@ preparse_mp_table(void)
/*
* parse an Intel MP specification table
* 2nd pass on motherboard's Intel MP specification table.
*
* sets:
* boot_cpu_id
* ID_TO_IO(N), phy APIC ID to log CPU/IO table
* CPU_TO_ID(N), logical CPU to APIC ID table
* IO_TO_ID(N), logical IO to APIC ID table
* bus_data[N]
* io_apic_ints[N]
*/
static int
parse_mp_table(void)
mptable_pass2(void)
{
int x;
mpfps_t fps;
mpcth_t cth;
int totalSize;
void* position;
@ -678,6 +684,13 @@ parse_mp_table(void)
int type;
int apic, bus, cpu, intr;
/* clear various tables */
for (x = 0; x < NAPICID; ++x) {
ID_TO_IO(x) = -1; /* phy APIC ID to log CPU/IO table */
CPU_TO_ID(x) = -1; /* logical CPU to APIC ID table */
IO_TO_ID(x) = -1; /* logical IO to APIC ID table */
}
/* clear bus data table */
for (x = 0; x < NBUS; ++x)
bus_data[x].bus_id = 0xff;
@ -689,21 +702,18 @@ parse_mp_table(void)
/* setup the cpu/apic mapping arrays */
boot_cpu_id = -1;
/* local pointer */
fps = (mpfps_t) mpfps;
/* record whether PIC or virtual-wire mode */
picmode = (fps->mpfb2 & 0x80) ? 1 : 0;
picmode = (mpfps->mpfb2 & 0x80) ? 1 : 0;
/* check for use of 'default' configuration */
#if defined(TEST_DEFAULT_CONFIG)
return TEST_DEFAULT_CONFIG;
#else
if (fps->mpfb1 != 0)
return fps->mpfb1; /* return default configuration type */
if (mpfps->mpfb1 != 0)
return mpfps->mpfb1; /* return default configuration type */
#endif /* TEST_DEFAULT_CONFIG */
if ((cth = fps->pap) == 0)
if ((cth = mpfps->pap) == 0)
panic("MP Configuration Table Header MISSING!");
/* walk the table, recording info of interest */
@ -1331,9 +1341,6 @@ default_mp_table(int type)
}
static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
/*
* start each AP in our list
*/
@ -1378,11 +1385,8 @@ start_all_aps(u_int boot_addr)
if (!start_ap(x, boot_addr)) {
printf("AP #%d (PHY# %d) failed!\n", x, CPU_TO_ID(x));
CHECK_PRINT("trace"); /* show checkpoints */
/*
* better panic as the AP may be running loose
* somewhere
*/
printf("panic y/n? [n] ");
/* better panic as the AP may be running loose */
printf("panic y/n? [y] ");
if (cngetc() != 'n')
panic("bye-bye");
}