239 lines
5.8 KiB
C
239 lines
5.8 KiB
C
/*
|
|
* <Insert copyright here : it must be BSD-like so everyone can use it>
|
|
*
|
|
* Author: Erich Boleyn <erich@uruk.org> http://www.uruk.org/~erich/
|
|
*
|
|
* Header file implementing Intel MultiProcessor Specification (MPS)
|
|
* version 1.1 and 1.4 SMP hardware control for Intel Architecture CPUs,
|
|
* with hooks for running correctly on a standard PC without the hardware.
|
|
*
|
|
* This file was created from information in the Intel MPS version 1.4
|
|
* document, order number 242016-004, which can be ordered from the
|
|
* Intel literature center.
|
|
*/
|
|
|
|
#ifndef _SMP_IMPS_H
|
|
#define _SMP_IMPS_H
|
|
|
|
/* make sure "apic.h" is included */
|
|
#ifndef _APIC_H
|
|
#error Must include "apic.h" before "smp-imps.h"
|
|
#endif /* !_APIC_H */
|
|
|
|
/*
|
|
* Defines used.
|
|
*/
|
|
|
|
#ifdef IMPS_DEBUG
|
|
#define IMPS_DEBUG_PRINT(x) KERNEL_PRINT(x)
|
|
#else /* !IMPS_DEBUG */
|
|
#define IMPS_DEBUG_PRINT(x)
|
|
#endif /* !IMPS_DEBUG */
|
|
|
|
#define IMPS_MAX_CPUS APIC_BROADCAST_ID
|
|
|
|
/*
|
|
* Defines representing limitations on values usable in different
|
|
* situations. This mostly depends on whether the APICs are old
|
|
* (82489DX) or new (SIO or Pentium/Pentium Pro integrated APICs).
|
|
*
|
|
* NOTE: It appears that the APICs must either be all old or all new,
|
|
* or broadcasts won't work right.
|
|
* NOTE #2: Given that, the maximum ID which can be sent to predictably
|
|
* is 14 for new APICs and 254 for old APICs. So, this all implies that
|
|
* a maximum of 15 processors is supported with the new APICs, and a
|
|
* maximum of 255 processors with the old APICs.
|
|
*/
|
|
|
|
#define IMPS_APIC_ID(x) \
|
|
( imps_any_new_apics ? APIC_NEW_ID(x) : APIC_OLD_ID(x) )
|
|
|
|
/*
|
|
* This is the value that must be in the "sig" member of the MP
|
|
* Floating Pointer Structure.
|
|
*/
|
|
#define IMPS_FPS_SIGNATURE ('_' | ('M'<<8) | ('P'<<16) | ('_'<<24))
|
|
#define IMPS_FPS_IMCRP_BIT 0x80
|
|
#define IMPS_FPS_DEFAULT_MAX 7
|
|
|
|
/*
|
|
* This is the value that must be in the "sig" member of the MP
|
|
* Configuration Table Header.
|
|
*/
|
|
#define IMPS_CTH_SIGNATURE ('P' | ('C'<<8) | ('M'<<16) | ('P'<<24))
|
|
|
|
/*
|
|
* These are the "type" values for Base MP Configuration Table entries.
|
|
*/
|
|
#define IMPS_FLAG_ENABLED 1
|
|
#define IMPS_BCT_PROCESSOR 0
|
|
#define IMPS_CPUFLAG_BOOT 2
|
|
#define IMPS_BCT_BUS 1
|
|
#define IMPS_BCT_IOAPIC 2
|
|
#define IMPS_BCT_IO_INTERRUPT 3
|
|
#define IMPS_BCT_LOCAL_INTERRUPT 4
|
|
#define IMPS_INT_INT 0
|
|
#define IMPS_INT_NMI 1
|
|
#define IMPS_INT_SMI 2
|
|
#define IMPS_INT_EXTINT 3
|
|
|
|
|
|
/*
|
|
* Typedefs and data item definitions done here.
|
|
*/
|
|
|
|
typedef struct imps_fps imps_fps; /* MP floating pointer structure */
|
|
typedef struct imps_cth imps_cth; /* MP configuration table header */
|
|
typedef struct imps_processor imps_processor;
|
|
typedef struct imps_bus imps_bus;
|
|
typedef struct imps_ioapic imps_ioapic;
|
|
typedef struct imps_interrupt imps_interrupt;
|
|
|
|
|
|
/*
|
|
* Data structures defined here
|
|
*/
|
|
|
|
/*
|
|
* MP Floating Pointer Structure (fps)
|
|
*
|
|
* Look at page 4-3 of the MP spec for the starting definitions of
|
|
* this structure.
|
|
*/
|
|
struct imps_fps
|
|
{
|
|
unsigned sig;
|
|
imps_cth *cth_ptr;
|
|
unsigned char length;
|
|
unsigned char spec_rev;
|
|
unsigned char checksum;
|
|
unsigned char feature_info[5];
|
|
};
|
|
|
|
/*
|
|
* MP Configuration Table Header (cth)
|
|
*
|
|
* Look at page 4-5 of the MP spec for the starting definitions of
|
|
* this structure.
|
|
*/
|
|
struct imps_cth
|
|
{
|
|
unsigned sig;
|
|
unsigned short base_length;
|
|
unsigned char spec_rev;
|
|
unsigned char checksum;
|
|
char oem_id[8];
|
|
char prod_id[12];
|
|
unsigned oem_table_ptr;
|
|
unsigned short oem_table_size;
|
|
unsigned short entry_count;
|
|
unsigned lapic_addr;
|
|
unsigned short extended_length;
|
|
unsigned char extended_checksum;
|
|
char reserved[1];
|
|
};
|
|
|
|
/*
|
|
* Base MP Configuration Table Types. They are sorted according to
|
|
* type (i.e. all of type 0 come first, etc.). Look on page 4-6 for
|
|
* the start of the descriptions.
|
|
*/
|
|
|
|
struct imps_processor
|
|
{
|
|
unsigned char type; /* must be 0 */
|
|
unsigned char apic_id;
|
|
unsigned char apic_ver;
|
|
unsigned char flags;
|
|
unsigned signature;
|
|
unsigned features;
|
|
char reserved[8];
|
|
};
|
|
|
|
struct imps_bus
|
|
{
|
|
unsigned char type; /* must be 1 */
|
|
unsigned char id;
|
|
char bus_type[6];
|
|
};
|
|
|
|
struct imps_ioapic
|
|
{
|
|
unsigned char type; /* must be 2 */
|
|
unsigned char id;
|
|
unsigned char ver;
|
|
unsigned char flags;
|
|
unsigned addr;
|
|
};
|
|
|
|
struct imps_interrupt
|
|
{
|
|
unsigned char type; /* must be 3 or 4 */
|
|
unsigned char int_type;
|
|
unsigned short flags;
|
|
unsigned char source_bus_id;
|
|
unsigned char source_bus_irq;
|
|
unsigned char dest_apic_id;
|
|
unsigned char dest_apic_intin;
|
|
};
|
|
|
|
|
|
/*
|
|
* Exported globals here.
|
|
*/
|
|
|
|
/*
|
|
* "imps_any_new_apics" is non-zero if any of the APICS (local or I/O)
|
|
* are *not* an 82489DX. This is useful to determine if more than 15
|
|
* CPUs can be supported (true if zero).
|
|
*/
|
|
extern int imps_any_new_apics;
|
|
|
|
/*
|
|
* "imps_enabled" is non-zero if the probe sequence found IMPS
|
|
* information and was successful.
|
|
*/
|
|
extern int imps_enabled;
|
|
|
|
/*
|
|
* This contains the local APIC hardware address.
|
|
*/
|
|
extern unsigned imps_lapic_addr;
|
|
|
|
/*
|
|
* This represents the number of CPUs found.
|
|
*/
|
|
extern int imps_num_cpus;
|
|
|
|
/*
|
|
* These map from virtual cpu numbers to APIC id's and back.
|
|
*/
|
|
extern unsigned char imps_cpu_apic_map[IMPS_MAX_CPUS];
|
|
extern unsigned char imps_apic_cpu_map[IMPS_MAX_CPUS];
|
|
|
|
|
|
/*
|
|
* This is the primary function for probing for Intel MPS 1.1/1.4
|
|
* compatible hardware and BIOS information. While probing the CPUs
|
|
* information returned from the BIOS, this also starts up each CPU
|
|
* and gets it ready for use.
|
|
*
|
|
* Call this during the early stages of OS startup, before memory can
|
|
* be messed up.
|
|
*
|
|
* Returns 1 if IMPS information was found and is valid, else 0.
|
|
*/
|
|
|
|
int imps_probe(void);
|
|
|
|
|
|
/*
|
|
* Defines that use variables
|
|
*/
|
|
|
|
#define IMPS_LAPIC_READ(x) (*((volatile unsigned *) (imps_lapic_addr+(x))))
|
|
#define IMPS_LAPIC_WRITE(x, y) \
|
|
(*((volatile unsigned *) (imps_lapic_addr+(x))) = (y))
|
|
|
|
#endif /* !_SMP_IMPS_H */
|
|
|