All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dave Jones <davej@codemonkey.org.uk>
To: Linux Kernel <linux-kernel@vger.kernel.org>
Subject: 2.6.0test1 broken /dev/mem mmap ?
Date: Wed, 16 Jul 2003 01:22:08 +0100	[thread overview]
Message-ID: <20030716002208.GA446@suse.de> (raw)

[-- 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;
}

                 reply	other threads:[~2003-07-16  0:07 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20030716002208.GA446@suse.de \
    --to=davej@codemonkey.org.uk \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.