* 2.6.0test1 broken /dev/mem mmap ?
@ 2003-07-16 0:22 Dave Jones
0 siblings, 0 replies; only message in thread
From: Dave Jones @ 2003-07-16 0:22 UTC (permalink / raw)
To: Linux Kernel
[-- Attachment #1: Type: text/plain, Size: 155 bytes --]
The attached program works fine on some boxes, but not
all in 2.6.0test1. It also works fine in 2.4, and up
until recently, in all 2.5's.
Ideas?
Dave
[-- Attachment #2: mptable.c --]
[-- Type: text/x-csrc, Size: 9103 bytes --]
/*
* Copyright (c) 1996, by Steve Passe
* All rights reserved.
*
* hacked to make it work in userspace Linux by Ingo Molnar, same copyright
*
* 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.
*/
#define MP_SIG 0x5f504d5f /* _MP_ */
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#define SMP_NO 0
#define SMP_YES 1
typedef unsigned int vm_offset_t;
/* 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
#define PROCENTRY_FLAG_EN 0x01
#define PROCENTRY_FLAG_BP 0x02
#define IOAPICENTRY_FLAG_EN 0x01
#define MAXPNSTR 132
typedef struct TABLE_ENTRY {
u_char type;
u_char length;
char name[32];
} tableEntry;
tableEntry basetableEntryTypes[] =
{
{ 0, 20, "Processor" },
{ 1, 8, "Bus" },
{ 2, 8, "I/O APIC" },
{ 3, 8, "I/O INT" },
{ 4, 8, "Local INT" }
};
/* 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;
static int MPConfigTableHeader(void* pap);
static int readType(void);
static void seekEntry(vm_offset_t addr);
static void readEntry(void* entry, int size);
static void processorEntry(void);
/* global data */
int pfd; /* physical /dev/mem fd */
int busses[16];
int apics[16];
int ncpu;
int nbus;
int napic;
int nintr;
int verbose;
/*
* set PHYSICAL address of MP floating pointer structure
*/
#define NEXT(X) ((X) += 4)
static void apic_probe(vm_offset_t* paddr, int* where)
{
/*
* c rewrite of apic_probe() by Jack F. Vogel
*/
unsigned int x;
u_short segment;
vm_offset_t target;
u_int buffer[ BIOS_SIZE / sizeof(int) ];
/* search Extended Bios Data Area, if present */
seekEntry((vm_offset_t)EBDA_POINTER);
readEntry(&segment, 2);
if (segment) { /* search EBDA */
target = (vm_offset_t)segment << 4;
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;
}
}
}
/* read CMOS for real top of mem */
seekEntry((vm_offset_t)TOPOFMEM_POINTER);
readEntry(&segment, 2);
--segment; /* less ONE_KBYTE */
target = segment * 1024;
seekEntry(target);
/*
* GOES SPLAT HERE ON A 2.6 KERNEL. --davej
*/
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);
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 */
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 */
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;
}
}
/* search additional memory */
target = GROPE_AREA1;
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;
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;
}
int issmp(int *numcpu, int verb)
{
vm_offset_t paddr;
mpfps_t mpfps;
int where;
int defaultConfig;
verbose=verb;
/* open physical memory for access to MP structures */
if ((pfd = open("/dev/mem", O_RDONLY)) < 0) {
fprintf(stderr, "issmp(): /dev/mem: %s\n", strerror(errno));
return -1;
}
/* probe for MP structures */
apic_probe(&paddr, &where);
if (where <= 0) {
if(numcpu)
*numcpu=1;
return SMP_NO;
}
/* read in mpfps structure*/
seekEntry(paddr);
readEntry(&mpfps, sizeof(mpfps_t));
/* check whether an MP config table exists */
if (! (defaultConfig = mpfps.mpfb1))
MPConfigTableHeader(mpfps.pap);
if(numcpu)
*numcpu=ncpu;
return SMP_YES;
}
static int MPConfigTableHeader(void* pap)
{
vm_offset_t paddr;
mpcth_t cth;
int x;
int totalSize, t;
int count, c;
if (pap == 0) {
printf("MP Configuration Table Header MISSING!\n");
return SMP_NO;
}
/* convert physical address to virtual address */
paddr = (vm_offset_t)pap;
/* read in cth structure */
seekEntry(paddr);
readEntry(&cth, sizeof(cth));
totalSize = cth.base_table_length - sizeof(struct MPCTH);
count = cth.entry_count;
/* initialze tables */
for (x = 0; x < 16; ++x)
busses[ x ] = apics[ x ] = 0xff;
ncpu = 0;
nbus = 0;
napic = 0;
nintr = 0;
/* process all the CPUs */
if (verbose)
printf("MP Table:\n#\tAPIC ID\tVersion\tState\t\tFamily\tModel\tStep\tFlags\n");
for (t = totalSize, c = count; c; c--) {
if (readType() == 0)
processorEntry();
totalSize -= basetableEntryTypes[ 0 ].length;
}
if (verbose)
printf ("\n");
return SMP_YES;
}
static int readType(void)
{
u_char type;
if (read(pfd, &type, sizeof(u_char)) != sizeof(u_char)) {
perror("type read");
exit(1);
}
if (lseek(pfd, -1, SEEK_CUR) < 0) {
perror("type seek");
exit(1);
}
return (int)type;
}
static void seekEntry(vm_offset_t addr)
{
if (lseek(pfd, (off_t)addr, SEEK_SET) < 0) {
perror("/dev/mem seek");
exit(1);
}
}
static void readEntry(void* entry, int size)
{
if (read(pfd, entry, size) != size) {
perror("readEntry");
exit(1);
}
}
static void processorEntry(void)
{
ProcEntry entry;
/* read it into local memory */
readEntry(&entry, sizeof(entry));
/* count it */
++ncpu;
if(verbose)
{
printf("#\t%2d", entry.apicID);
printf("\t 0x%2x", entry.apicVersion);
printf("\t %s, %s",
(entry.cpuFlags & PROCENTRY_FLAG_BP) ? "BSP" : "AP",
(entry.cpuFlags & PROCENTRY_FLAG_EN) ? "usable" : "unusable");
printf("\t %ld\t %ld\t %ld",
(entry.cpuSignature >> 8) & 0x0f,
(entry.cpuSignature >> 4) & 0x0f,
entry.cpuSignature & 0x0f);
printf("\t 0x%04lx\n", entry.featureFlags);
}
}
int main()
{
int numcpu, smp;
smp=issmp(&numcpu, 1);
printf("SMP: %d\nCPU: %d\n", smp, numcpu);
return 0;
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2003-07-16 0:07 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-16 0:22 2.6.0test1 broken /dev/mem mmap ? Dave Jones
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).