summaryrefslogtreecommitdiffstats
path: root/perl-install/c/smp.c
diff options
context:
space:
mode:
authorChmouel Boudjnah <chmouel@mandriva.org>2001-04-22 17:03:21 +0000
committerChmouel Boudjnah <chmouel@mandriva.org>2001-04-22 17:03:21 +0000
commitba1e42fb594a99bcffc71740d84fdec58fdb70b7 (patch)
treea575131e654a33706e2189cbf95a7beb9c0af5c5 /perl-install/c/smp.c
parentd66e41161e51fc4073dfe0e6bdb3d5e2cefc16cf (diff)
downloaddrakx-backup-do-not-use-ba1e42fb594a99bcffc71740d84fdec58fdb70b7.tar
drakx-backup-do-not-use-ba1e42fb594a99bcffc71740d84fdec58fdb70b7.tar.gz
drakx-backup-do-not-use-ba1e42fb594a99bcffc71740d84fdec58fdb70b7.tar.bz2
drakx-backup-do-not-use-ba1e42fb594a99bcffc71740d84fdec58fdb70b7.tar.xz
drakx-backup-do-not-use-ba1e42fb594a99bcffc71740d84fdec58fdb70b7.zip
Merge SMP from Red Hat anaconda-7.1.
Diffstat (limited to 'perl-install/c/smp.c')
-rw-r--r--perl-install/c/smp.c629
1 files changed, 366 insertions, 263 deletions
diff --git a/perl-install/c/smp.c b/perl-install/c/smp.c
index e54cac62f..34303759e 100644
--- a/perl-install/c/smp.c
+++ b/perl-install/c/smp.c
@@ -50,7 +50,7 @@ int sparcDetectSMP(void)
char buff[1024];
while (fgets (buff, 1024, f) != NULL) {
- if (!strncmp (buff, "ncpus active\t: ", 15)) {
+ if (!strncmp (buff, "ncpus probed\t: ", 15)) {
if (strtoul (buff + 15, NULL, 0) > 1)
issmp = 1;
break;
@@ -64,293 +64,385 @@ int sparcDetectSMP(void)
}
#endif /* __sparc__ */
-/* I'm sure this is not right - but don't know what to look for at
-this point - before adding this a machine that was definitely NOT
-SMP was identified as such Feb 12, 2001 sbenedict */
-
-#ifdef __powerpc__
-int ppcDetectSMP(void)
-{
- int issmp = 0;
- FILE *f;
-
- f = fopen("/proc/cpuinfo", "r");
- if (f) {
- char buff[1024];
-
- while (fgets (buff, 1024, f) != NULL) {
- if (!strncmp (buff, "ncpus active\t: ", 15)) {
- if (strtoul (buff + 15, NULL, 0) > 1)
- issmp = 1;
- break;
- }
- }
- fclose(f);
- } else
- return -1;
-
- return issmp;
-}
-#endif /* __powerpc__ */
-
#ifdef __i386__
-#define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_')
+/*
+ * Copyright (c) 1996, by Steve Passe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the developer may NOT be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id$
+ */
-struct intel_mp_floating
-{
- char mpf_signature[4]; /* "_MP_" */
- unsigned long mpf_physptr; /* Configuration table address */
- unsigned char mpf_length; /* Our length (paragraphs) */
- unsigned char mpf_specification;/* Specification version */
- unsigned char mpf_checksum; /* Checksum (makes sum 0) */
- unsigned char mpf_feature1; /* Standard or configuration ? */
- unsigned char mpf_feature2; /* Bit7 set for IMCR|PIC */
- unsigned char mpf_feature3; /* Unused (0) */
- unsigned char mpf_feature4; /* Unused (0) */
- unsigned char mpf_feature5; /* Unused (0) */
-};
-
-struct mp_config_table
-{
- char mpc_signature[4];
-#define MPC_SIGNATURE "PCMP"
- unsigned short mpc_length; /* Size of table */
- char mpc_spec; /* 0x01 */
- char mpc_checksum;
- char mpc_oem[8];
- char mpc_productid[12];
- unsigned long mpc_oemptr; /* 0 if not present */
- unsigned short mpc_oemsize; /* 0 if not present */
- unsigned short mpc_oemcount;
- unsigned long mpc_lapic; /* APIC address */
- unsigned long reserved;
-};
-
-/* Followed by entries */
-
-#define MP_PROCESSOR 0
-#define MP_BUS 1
-#define MP_IOAPIC 2
-#define MP_INTSRC 3
-#define MP_LINTSRC 4
-
-struct mpc_config_processor
-{
- unsigned char mpc_type;
- unsigned char mpc_apicid; /* Local APIC number */
- unsigned char mpc_apicver; /* Its versions */
- unsigned char mpc_cpuflag;
-#define CPU_ENABLED 1 /* Processor is available */
-#define CPU_BOOTPROCESSOR 2 /* Processor is the BP */
- unsigned long mpc_cpufeature;
-#define CPU_STEPPING_MASK 0x0F
-#define CPU_MODEL_MASK 0xF0
-#define CPU_FAMILY_MASK 0xF00
- unsigned long mpc_featureflag; /* CPUID feature value */
- unsigned long mpc_reserved[2];
-};
-
-struct mpc_config_bus
-{
- unsigned char mpc_type;
- unsigned char mpc_busid;
- unsigned char mpc_bustype[6] __attribute((packed));
-};
-
-#define BUSTYPE_EISA "EISA"
-#define BUSTYPE_ISA "ISA"
-#define BUSTYPE_INTERN "INTERN" /* Internal BUS */
-#define BUSTYPE_MCA "MCA"
-#define BUSTYPE_VL "VL" /* Local bus */
-#define BUSTYPE_PCI "PCI"
-#define BUSTYPE_PCMCIA "PCMCIA"
-
-/* We don't understand the others */
-
-struct mpc_config_ioapic
-{
- unsigned char mpc_type;
- unsigned char mpc_apicid;
- unsigned char mpc_apicver;
- unsigned char mpc_flags;
-#define MPC_APIC_USABLE 0x01
- unsigned long mpc_apicaddr;
-};
-
-struct mpc_config_intsrc
-{
- unsigned char mpc_type;
- unsigned char mpc_irqtype;
- unsigned short mpc_irqflag;
- unsigned char mpc_srcbus;
- unsigned char mpc_srcbusirq;
- unsigned char mpc_dstapic;
- unsigned char mpc_dstirq;
-};
-
-#define MP_INT_VECTORED 0
-#define MP_INT_NMI 1
-#define MP_INT_SMI 2
-#define MP_INT_EXTINT 3
-
-#define MP_IRQDIR_DEFAULT 0
-#define MP_IRQDIR_HIGH 1
-#define MP_IRQDIR_LOW 3
-
-
-struct mpc_config_intlocal
-{
- unsigned char mpc_type;
- unsigned char mpc_irqtype;
- unsigned short mpc_irqflag;
- unsigned char mpc_srcbusid;
- unsigned char mpc_srcbusirq;
- unsigned char mpc_destapic;
-#define MP_APIC_ALL 0xFF
- unsigned char mpc_destapiclint;
-};
+/*
+ * mptable.c
+ */
+#define VMAJOR 2
+#define VMINOR 0
+#define VDELTA 12
/*
- * Default configurations
+ * this will cause the raw mp table to be dumped to /tmp/mpdump
*
- * 1 2 CPU ISA 82489DX
- * 2 2 CPU EISA 82489DX no IRQ 8 or timer chaining
- * 3 2 CPU EISA 82489DX
- * 4 2 CPU MCA 82489DX
- * 5 2 CPU ISA+PCI
- * 6 2 CPU EISA+PCI
- * 7 2 CPU MCA+PCI
+#define RAW_DUMP
*/
+#define MP_SIG 0x5f504d5f /* _MP_ */
+#define EXTENDED_PROCESSING_READY
+#define OEM_PROCESSING_READY_NOT
-static int smp_found_config=0;
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
-/*
- * Checksum an MP configuration block.
- */
+#define LINUX 1
+#if LINUX
+typedef unsigned int vm_offset_t;
+#else
+#include <machine/types.h>
+#endif
-static int mpf_checksum(unsigned char *mp, int len)
+/* EBDA is @ 40:0e in real-mode terms */
+#define EBDA_POINTER 0x040e /* location of EBDA pointer */
+
+/* CMOS 'top of mem' is @ 40:13 in real-mode terms */
+#define TOPOFMEM_POINTER 0x0413 /* BIOS: base memory size */
+
+#define DEFAULT_TOPOFMEM 0xa0000
+
+#define BIOS_BASE 0xf0000
+#define BIOS_BASE2 0xe0000
+#define BIOS_SIZE 0x10000
+#define ONE_KBYTE 1024
+
+#define GROPE_AREA1 0x80000
+#define GROPE_AREA2 0x90000
+#define GROPE_SIZE 0x10000
+
+/* 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 apicID;
+ u_char apicVersion;
+ u_char cpuFlags;
+ u_long cpuSignature;
+ u_long featureFlags;
+ u_long reserved1;
+ u_long reserved2;
+} ProcEntry;
+
+#define PROCENTRY_FLAG_EN 0x01
+
+static void seekEntry( vm_offset_t addr );
+static void apic_probe( vm_offset_t* paddr, int* where );
+static void readEntry( void* entry, int size );
+
+/* global data */
+static int pfd; /* physical /dev/mem fd */
+static int verbose = 0;
+static int grope = 0;
+
+static int
+readType()
{
- int sum=0;
- while(len--)
- sum+=*mp++;
- return sum&0xFF;
+ u_char type;
+
+ if ( read( pfd, &type, sizeof( u_char ) ) != sizeof( u_char ) ) {
+ perror( "type read" );
+ fprintf( stderr, "\npfd: %d", pfd );
+ fflush( stderr );
+ exit( 1 );
+ }
+
+ if ( lseek( pfd, -1, SEEK_CUR ) < 0 ) {
+ perror( "type seek" );
+ exit( 1 );
+ }
+
+ return (int)type;
}
-static int do_smp_scan_config(unsigned long *bp, unsigned long length)
+static int intelDetectSMP(void)
{
- struct intel_mp_floating *mpf;
+ vm_offset_t paddr;
+ int where;
+ mpfps_t mpfps;
+ int rc = 0;
+ int ncpus = 0;
+
+ /* open physical memory for access to MP structures */
+ if ( (pfd = open( "/dev/mem", O_RDONLY )) < 0 ) {
+ return 0;
+ }
-/*
- if (sizeof(*mpf)!=16)
- logMessage("Error: MPF size\n");
-*/
+ /* probe for MP structures */
+ apic_probe( &paddr, &where );
+ if ( where <= 0 )
+ return 0;
- while (length>0)
- {
- if (*bp==SMP_MAGIC_IDENT)
- {
- mpf=(struct intel_mp_floating *)bp;
- if (mpf->mpf_length==1 &&
- !mpf_checksum((unsigned char *)bp,16) &&
- (mpf->mpf_specification == 1
- || mpf->mpf_specification == 4) )
- {
- /*logMessage("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
- if (mpf->mpf_feature2&(1<<7))
- logMessage(" IMCR and PIC compatibility mode.\n");
- else
- logMessage(" Virtual Wire compatibility mode.\n");
-*/
- smp_found_config=1;
- return 1;
- }
- }
- bp+=4;
- length-=16;
+ seekEntry( paddr );
+ readEntry( &mpfps, sizeof( mpfps_t ) );
+
+ if (mpfps.mpfb1)
+ /* old style */
+ rc = 1;
+ else {
+ /* go to the config table */
+ mpcth_t cth;
+ int count, i;
+
+ paddr = (vm_offset_t) mpfps.pap;
+ seekEntry( paddr );
+ readEntry( &cth, sizeof( cth ) );
+ /* if we don't have any entries, the kernel sure
+ won't be able to set up mp. Needs at least one entry
+ for smp kernel */
+ if (cth.entry_count <= 1) {
+ close (pfd);
+ return 0;
}
+ count = cth.entry_count;
+ for (i = 0; i < count; i++) {
+ if ( readType() == 0 ) {
+ ProcEntry entry;
+ readEntry( &entry, sizeof( entry ) );
+ if (entry.cpuFlags & PROCENTRY_FLAG_EN)
+ ncpus++;
+ }
+ }
+ if (ncpus > 1)
+ rc = 1;
+ }
- return 0;
+ close (pfd);
+ return rc;
}
-static int smp_scan_config(int mem_fd, unsigned long base,
- unsigned long length)
+/*
+ * set PHYSICAL address of MP floating pointer structure
+ */
+#define NEXT(X) ((X) += 4)
+static void
+apic_probe( vm_offset_t* paddr, int* where )
{
- void *p;
- int o;
-
- o=base&0xFFF;
- base-=o;
- length+=o;
-
- p=mmap(0, (length+4095)&0xFFFFF000, PROT_READ, MAP_SHARED,
- mem_fd, (base&0xFFFF0000));
- if(p==MAP_FAILED)
- {
- /*logMessage("SMP Probe error: mmap: %s", strerror(errno));*/
- return 1;
- }
- do_smp_scan_config(p+o, length-o);
- munmap(p, (length+4095)&0xFFFFF000);
- return 0;
+ /*
+ * c rewrite of apic_probe() by Jack F. Vogel
+ */
+
+ int x;
+ u_short segment;
+ vm_offset_t target;
+ u_int buffer[ BIOS_SIZE / sizeof( int ) ];
+
+ if ( verbose )
+ printf( "\n" );
+
+ /* search Extended Bios Data Area, if present */
+ if ( verbose )
+ printf( " looking for EBDA pointer @ 0x%04x, ", EBDA_POINTER );
+ seekEntry( (vm_offset_t)EBDA_POINTER );
+ readEntry( &segment, 2 );
+ if ( segment ) { /* search EBDA */
+ target = (vm_offset_t)segment << 4;
+ if ( verbose )
+ printf( "found, searching EBDA @ 0x%08x\n", target );
+ seekEntry( target );
+ readEntry( buffer, ONE_KBYTE );
+
+ for ( x = 0; x < ONE_KBYTE / sizeof ( unsigned int ); NEXT(x) ) {
+ if ( buffer[ x ] == MP_SIG ) {
+ *where = 1;
+ *paddr = (x * sizeof( unsigned int )) + target;
+ return;
+ }
+ }
+ }
+ else {
+ if ( verbose )
+ printf( "NOT found\n" );
+ }
+
+ /* read CMOS for real top of mem */
+ seekEntry( (vm_offset_t)TOPOFMEM_POINTER );
+ readEntry( &segment, 2 );
+ --segment; /* less ONE_KBYTE */
+ target = segment * 1024;
+ if ( verbose )
+ printf( " searching CMOS 'top of mem' @ 0x%08x (%dK)\n",
+ target, segment );
+ seekEntry( target );
+ readEntry( buffer, ONE_KBYTE );
+
+ for ( x = 0; x < ONE_KBYTE / sizeof ( unsigned int ); NEXT(x) ) {
+ if ( buffer[ x ] == MP_SIG ) {
+ *where = 2;
+ *paddr = (x * sizeof( unsigned int )) + target;
+ return;
+ }
+ }
+
+ /* we don't necessarily believe CMOS, check base of the last 1K of 640K */
+ if ( target != (DEFAULT_TOPOFMEM - 1024)) {
+ target = (DEFAULT_TOPOFMEM - 1024);
+ if ( verbose )
+ printf( " searching default 'top of mem' @ 0x%08x (%dK)\n",
+ target, (target / 1024) );
+ seekEntry( target );
+ readEntry( buffer, ONE_KBYTE );
+
+ for ( x = 0; x < ONE_KBYTE / sizeof ( unsigned int ); NEXT(x) ) {
+ if ( buffer[ x ] == MP_SIG ) {
+ *where = 3;
+ *paddr = (x * sizeof( unsigned int )) + target;
+ return;
+ }
+ }
+ }
+
+ /* search the BIOS */
+ if ( verbose )
+ printf( " searching BIOS @ 0x%08x\n", BIOS_BASE );
+ seekEntry( BIOS_BASE );
+ readEntry( buffer, BIOS_SIZE );
+
+ for ( x = 0; x < BIOS_SIZE / sizeof( unsigned int ); NEXT(x) ) {
+ if ( buffer[ x ] == MP_SIG ) {
+ *where = 4;
+ *paddr = (x * sizeof( unsigned int )) + BIOS_BASE;
+ return;
+ }
+ }
+
+ /* search the extended BIOS */
+ if ( verbose )
+ printf( " searching extended BIOS @ 0x%08x\n", BIOS_BASE2 );
+ seekEntry( BIOS_BASE2 );
+ readEntry( buffer, BIOS_SIZE );
+
+ for ( x = 0; x < BIOS_SIZE / sizeof( unsigned int ); NEXT(x) ) {
+ if ( buffer[ x ] == MP_SIG ) {
+ *where = 5;
+ *paddr = (x * sizeof( unsigned int )) + BIOS_BASE2;
+ return;
+ }
+ }
+
+ if ( grope ) {
+ /* search additional memory */
+ target = GROPE_AREA1;
+ if ( verbose )
+ printf( " groping memory @ 0x%08x\n", target );
+ seekEntry( target );
+ readEntry( buffer, GROPE_SIZE );
+
+ for ( x = 0; x < GROPE_SIZE / sizeof( unsigned int ); NEXT(x) ) {
+ if ( buffer[ x ] == MP_SIG ) {
+ *where = 6;
+ *paddr = (x * sizeof( unsigned int )) + GROPE_AREA1;
+ return;
+ }
+ }
+
+ target = GROPE_AREA2;
+ if ( verbose )
+ printf( " groping memory @ 0x%08x\n", target );
+ seekEntry( target );
+ readEntry( buffer, GROPE_SIZE );
+
+ for ( x = 0; x < GROPE_SIZE / sizeof( unsigned int ); NEXT(x) ) {
+ if ( buffer[ x ] == MP_SIG ) {
+ *where = 7;
+ *paddr = (x * sizeof( unsigned int )) + GROPE_AREA2;
+ return;
+ }
+ }
+ }
+
+ *where = 0;
+ *paddr = (vm_offset_t)0;
}
-static int intelDetectSMP(void)
+
+/*
+ *
+ */
+static void
+seekEntry( vm_offset_t addr )
{
- int mem_fd;
-
- mem_fd=open("/dev/mem", O_RDONLY);
-
- if(mem_fd==-1)
- {
- /*logMessage("Error detecting SMP: /dev/mem: %s", strerror(errno));*/
- }
-
- /*
- * FIXME: Linux assumes you have 640K of base ram..
- * this continues the error...
- *
- * 1) Scan the bottom 1K for a signature
- * 2) Scan the top 1K of base RAM
- * 3) Scan the 64K of bios
- */
- if (!smp_scan_config(mem_fd, 0x0, 0x400) &&
- !smp_scan_config(mem_fd, 639*0x400,0x400) &&
- !smp_scan_config(mem_fd, 0xF0000,0x10000)) {
-#if 0
+ if ( lseek( pfd, (off_t)addr, SEEK_SET ) < 0 ) {
+ return;
+ perror( "/dev/mem seek" );
+ exit( 1 );
+ }
+}
+
- /*
- * If it is an SMP machine we should know now, unless the
- * configuration is in an EISA/MCA bus machine with an
- * extended bios data area.
- *
- * there is a real-mode segmented pointer pointing to the
- * 4K EBDA area at 0x40E, calculate and scan it here.
- *
- * NOTE! There are Linux loaders that will corrupt the EBDA
- * area, and as such this kind of SMP config may be less
- * trustworthy, simply because the SMP table may have been
- * stomped on during early boot. These loaders are buggy and
- * should be fixed.
- */
- unsigned int address;
-
- address = *(unsigned short *)phys_to_virt(0x40E);
- address<<=4;
- smp_scan_config(mem_fd, address, 0x1000);
- if (smp_found_config)
- /*logMessage("WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.rutgers.edu if you experience SMP problems!\n");*/
-#endif
- }
/*
- if(smp_found_config)
- logMessage("Detected SMP capable motherboard\n");
- else
- logMessage("Detected non SMP capable motherboard\n");
-*/
- return smp_found_config;
+ *
+ */
+static void
+readEntry( void* entry, int size )
+{
+ if ( read( pfd, entry, size ) != size ) {
+ return;
+ perror( "readEntry" );
+ exit( 1 );
+ }
}
+
+
#endif /* __i386__ */
int detectSMP(void)
@@ -366,8 +458,19 @@ int detectSMP(void)
return isSMP = sparcDetectSMP();
#elif __alpha__
return isSMP = alphaDetectSMP();
-#elif __powerpc__
- return isSMP = ppcDetectSMP();
+#elif __ia64__
+ return isSMP = 1;
+#else
+ #error unknown architecture
#endif
}
-
+
+#if 0
+main() {
+ if (detectSMP())
+ printf("has smp\n");
+ else
+ printf("no smp\n");
+}
+
+#endif