home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
mitsch75.zip
/
scheme-7_5_17-src.zip
/
scheme-7.5.17
/
src
/
microcode
/
hppacach.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-03-24
|
17KB
|
642 lines
/* -*-C-*-
$Id: hppacach.c,v 1.13 1999/03/24 23:30:12 cph Exp $
Copyright (c) 1990-1999 Massachusetts Institute of Technology
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <math.h>
#include <sys/stat.h>
#include <memory.h>
#include <nlist.h>
#include <unistd.h>
#include <errno.h>
#include "hppacach.h"
#define true 1
#define false 0
#define boolean int
#ifdef DEBUG
#define DEBUGGING(stmt) stmt
#else
#define DEBUGGING(stmt) do \
{ \
} while (0)
#endif
/* File that contains the symbol table for the kernel */
char * kernel_filenames [] =
{
"/hp-ux",
"/stand/vmunix",
0
};
/* File where the kernel image lives */
#define KERNEL_MEMORY_FILE "/dev/kmem"
#define UTSNAME_SYMBOL "utsname"
#define PDC_CACHE_SYMBOL "cache_tlb_parms"
static struct utsname sysinfo;
static char **the_argv;
void
io_error (pname, format, fname)
char * pname;
char * format;
char * fname;
{
char errmsg[MAXPATHLEN + 257];
char errstring[MAXPATHLEN + 257];
sprintf (&errmsg[0], format, fname);
sprintf (&errstring[0], "%s: %s: %s", (the_argv[0]), pname, (&errmsg[0]));
perror (&errstring[0]);
}
void
io_lose (pname, format, fname)
char * pname;
char * format;
char * fname;
{
io_error (pname, format, fname);
exit (1);
}
struct kernel_locations
{
long utsname_location;
long pdc_cache_location;
};
struct nlist nl[] =
{
{ UTSNAME_SYMBOL },
{ PDC_CACHE_SYMBOL },
{ 0 },
};
static char *
choose_kernel_file ()
{
char ** p = kernel_filenames;
while (1)
{
struct stat s;
if ((stat ((*p), (&s))) == 0)
return (*p);
p += 1;
}
fprintf (stderr, "Unable to find kernel.\n");
fflush (stderr);
exit (1);
}
void
read_nlist (kloc)
struct kernel_locations *kloc;
{
char * kernel_filename = (choose_kernel_file ());
DEBUGGING (printf ("reading nlist...\n"));
if ((nlist (kernel_filename, nl)) != 0)
io_lose ("read_nlist", "failed on both %s and %s", kernel_filename);
DEBUGGING (printf ("reading nlist done.\n"));
kloc->utsname_location = nl[0].n_value;
kloc->pdc_cache_location = nl[1].n_value;
DEBUGGING (printf ("utsname location = 0x%x\n", kloc->utsname_location));
DEBUGGING (printf ("pdc_cache location = 0x%x\n", kloc->pdc_cache_location));
}
void
read_parameters (pdc_cache)
struct pdc_cache_dump *pdc_cache;
{
struct kernel_locations kloc;
struct utsname kerninfo;
int kmem = (open (KERNEL_MEMORY_FILE, O_RDONLY));
if (kmem < 0)
io_lose ("read_parameters", "open (%s) failed", KERNEL_MEMORY_FILE);
read_nlist (&kloc);
if ((lseek (kmem, kloc.utsname_location, SEEK_SET)) < 0)
io_lose ("read_parameters", "lseek (%s) failed", KERNEL_MEMORY_FILE);
if ((read (kmem, (&kerninfo), (sizeof (kerninfo)))) !=
(sizeof (kerninfo)))
io_lose ("read_parameters", "read (%s) failed", KERNEL_MEMORY_FILE);
if ((memcmp ((&kerninfo), (&sysinfo), (sizeof (sysinfo)))) != 0)
fprintf (stderr, "read_parameters: uname and %s in %s differ.\n",
kloc.utsname_location, KERNEL_MEMORY_FILE);
strncpy (pdc_cache->hardware, (kerninfo.machine),
(sizeof (kerninfo.machine)));
if ((lseek (kmem, (kloc.pdc_cache_location), SEEK_SET)) < 0)
io_lose ("read_parameters", "lseek (%s) failed", KERNEL_MEMORY_FILE);
if ((read (kmem, &pdc_cache->cache_format,
(sizeof (pdc_cache->cache_format)))) !=
(sizeof (pdc_cache->cache_format)))
io_lose ("read_parameters", "read (%s) failed", KERNEL_MEMORY_FILE);
if ((close (kmem)) < 0)
io_lose ("read_parameters", "close (%s) failed", KERNEL_MEMORY_FILE);
return;
}
void
print_sel (sel, name, pattern, op)
unsigned int sel;
char *name;
char *pattern;
char *op;
{
switch (sel)
{
case 0:
printf ("\n Both ");
printf (pattern, "D");
printf (" and ");
printf (pattern, "I");
printf (" must be used to %s.", op);
break;
case 1:
printf ("\n Only ");
printf (pattern, "D");
printf (" needs to be used to %s.", op);
break;
case 2:
printf ("\n Only ");
printf (pattern, "I");
printf (" needs to be used to %s.", op);
break;
case 3:
printf ("\n Either ");
printf (pattern, "D");
printf (" or ");
printf (pattern, "I");
printf (" can be used to %s.", op);
break;
default:
fprintf (stderr, "\n Bad %s value %d.", name, (sel));
break;
}
return;
}
void
print_cst (cst)
unsigned int cst;
{
switch (cst)
{
case 0:
printf ("\n It does not issue coherent operations.");
break;
case 1:
printf ("\n It issues coherent operations.");
break;
default:
printf ("\n It has a reserved cst value %d.", (cst));
break;
}
return;
}
void
print_cache (info, name, write_only_p)
struct cache_info *info;
char *name;
boolean write_only_p;
{
printf ("\n");
/* First print the user-readable information as a comment. */
printf (" /*\n");
printf (" %s-cache information:\n", name);
printf ("\tsize\t\t%ld bytes (%ld K).\n", info->size, (info->size / 1024));
printf ("\tconf\t\t0x%08lx\n", info->conf.word);
printf ("\tbase\t\t0x%lx\n", info->base);
printf ("\tstride\t\t%ld bytes.\n", info->stride);
printf ("\tcount\t\t%ld entries.\n", info->count);
printf ("\tloop\t\t%ld association%s per entry.\n",
info->loop, ((info->loop == 1) ? "" : "s"));
printf ("\tblock size\t%d line%s.\n",
info->conf.bits.block,
((info->conf.bits.block == 1) ? "" : "s"));
printf ("\tline size\t%d (16-byte units).\n", info->conf.bits.line);
if (write_only_p)
{
printf (" It is a read-only cache.");
}
else if (info->conf.bits.wt == 0)
{
printf (" It is a write-to cache.");
}
else
{
printf (" It is a write-through cache.");
}
print_cst ((info->conf.bits.cst));
print_sel ((info->conf.bits.fsel), "f-sel", "F%sC", "flush");
/* Now print the C-readable information. */
printf ("\n */\n");
printf (" { %ld, 0x%08lx, 0x%lx, %ld, %ld, %ld }",
info->size, info->conf.word, info->base,
info->stride, info->count, info->loop);
return;
}
void
print_tlb (info, name)
struct tlb_info *info;
char *name;
{
printf ("\n");
/* First print the user-readable information as a comment. */
printf (" /*\n");
printf (" %s-TLB information:\n", name);
printf ("\tsize\t\t%ld entries (%ld K).\n",
info->size, (info->size / 1024));
printf ("\tconf\t\t0x%08lx\n", info->conf.word);
printf ("\tsp_base\t\t0x%lx\n", info->sp_base);
printf ("\tsp_stride\t%ld\n", info->sp_stride);
printf ("\tsp_count\t%ld\n", info->sp_count);
printf ("\toff_base\t0x%lx\n", info->off_base);
printf ("\toff_stride\t%ld\n", info->off_stride);
printf ("\toff_count\t%ld\n", info->off_count);
printf ("\tloop\t\t%ld association%s per entry.",
info->loop, ((info->loop == 1) ? "" : "s"));
print_cst ((info->conf.bits.cst));
print_sel ((info->conf.bits.psel), "p-sel", "P%sTLB", "purge");
/* Now print the C-readable information. */
printf ("\n */\n");
printf (" { %ld, 0x%08lx, 0x%lx, %ld, %ld, 0x%lx, %ld, %ld, %ld }",
info->size, info->conf.word,
info->sp_base, info->sp_stride, info->sp_count,
info->off_base, info->off_stride, info->off_count,
info->loop);
return;
}
void
print_parameters (pdc_cache, node_p)
struct pdc_cache_dump *pdc_cache;
int node_p;
{
struct pdc_cache_result *io_arch_format;
if (node_p)
{
printf ("/* Emacs: Use -*- C -*- mode when editting this file. */\n\n");
printf ("{\n /* Cache description for %s, an HP PA %s processor. */\n\n",
sysinfo.nodename,
sysinfo.machine);
}
else
{
printf ("{\n");
}
io_arch_format = ((struct pdc_cache_result *) &(pdc_cache->cache_format));
printf (" \"%s\",\n\n {", pdc_cache->hardware);
print_cache (&(io_arch_format->I_info), "I", true);
printf (",");
print_cache (&(io_arch_format->D_info), "D", false);
printf (",");
print_tlb (&(io_arch_format->IT_info), "I");
printf (",");
print_tlb (&(io_arch_format->DT_info), "D");
printf ("\n");
printf (" }};\n");
return;
}
int
search_pdc_database (fd, pdc_cache, filename)
int fd;
struct pdc_cache_dump * pdc_cache;
char * filename;
{
while (1)
{
int scr =
(read (fd, ((char *) pdc_cache), (sizeof (struct pdc_cache_dump))));
if (scr < 0)
io_lose ("search_pdc_database", "read (%s) failed", filename);
if (scr != (sizeof (struct pdc_cache_dump)))
{
if (scr == 0)
return (0);
fprintf (stderr, "%s: %s: incomplete read (%s)\n",
(the_argv[0]), "search_pdc_database", filename);
fflush (stderr);
exit (1);
}
if ((strcmp ((sysinfo . machine), (pdc_cache -> hardware))) == 0)
return (1);
}
}
#define MODE_ADD 0
#define MODE_REPLACE 1
#define MODE_PRINT 2
void
update_pdc_database (mode, pdc_cache, filename)
int mode;
struct pdc_cache_dump * pdc_cache;
char * filename;
{
int write_p = 1;
int fd = (open (filename, (O_RDWR | O_CREAT), 0666));
if (fd < 0)
{
if (errno != EACCES)
io_lose ("update_pdc_database", "open (%s) failed", filename);
fd = (open (filename, O_RDONLY));
if (fd < 0)
io_lose ("update_pdc_database", "open (%s) failed", filename);
else
{
write_p = 0;
if (mode != MODE_PRINT)
fprintf (stderr, "Data base \"%s\" is write-protected.\n", filename);
}
}
if (! (search_pdc_database (fd, pdc_cache, filename)))
{
read_parameters (pdc_cache);
if (!write_p && (mode != MODE_PRINT))
printf ("Could not write information to data base.\n");
else
{
int scr =
(write (fd, ((char *) pdc_cache), (sizeof (struct pdc_cache_dump))));
if (scr < 0)
io_lose ("update_pdc_database", "write (%s) failed", filename);
if (scr != (sizeof (struct pdc_cache_dump)))
{
fprintf (stderr, "%s: %s: incomplete write (%s)\n",
(the_argv[0]), "update_pdc_database", filename);
fflush (stderr);
exit (1);
}
}
}
else
{
struct pdc_cache_dump new_cache_s, * new_cache;
new_cache = & new_cache_s;
read_parameters (new_cache);
if ((memcmp (new_cache, pdc_cache, (sizeof (struct pdc_cache_dump))))
== 0)
{
if (mode != MODE_PRINT)
printf ("Correct information for model %s is present in data base.\n",
&new_cache->hardware[0]);
}
else
{
printf ("Data base contains different information for model %s.\n",
&new_cache->hardware[0]);
switch (mode)
{
case MODE_REPLACE:
{
if (write_p)
{
printf ("Keeping the new information.\n");
if ((lseek (fd, (- (sizeof (struct pdc_cache_dump))), SEEK_CUR))
== -1)
io_lose ("update_pdc_database", "lseek (%s) failed", filename);
if ((write (fd, new_cache, (sizeof (struct pdc_cache_dump))))
!= (sizeof (struct pdc_cache_dump)))
io_lose ("update_pdc_database", "write (%s) failed", filename);
break;
}
}
case MODE_ADD:
{
printf ("Keeping the old information.\n");
break;
}
case MODE_PRINT:
{
printf ("New information:\n");
print_parameters (new_cache, 1);
printf ("\n\nOld information:\n");
}
default:
fprintf (stderr, "%s error. Unknown mode %d.\n", the_argv[0], mode);
}
}
}
if ((close (fd)) < 0)
io_lose ("update_pdc_database", "close (%s) failed", filename);
return;
}
void
print_pdc_database (filename)
char * filename;
{
struct pdc_cache_dump pdc_cache_s, *pdc_cache;
int fd = (open (filename, (O_RDONLY), 0666));
int first;
if (fd < 0)
io_lose ("print_pdc_database", "open (%s) failed", filename);
pdc_cache = &pdc_cache_s;
first = 1;
while (1)
{
int scr =
(read (fd, ((char *) pdc_cache), (sizeof (struct pdc_cache_dump))));
if (scr < 0)
io_lose ("print_pdc_database", "read (%s) failed", filename);
if (scr != (sizeof (struct pdc_cache_dump)))
{
if (scr == 0)
break;
fprintf (stderr, "%s: %s: incomplete read (%s)\n",
(the_argv[0]), "print_pdc_database", filename);
fflush (stderr);
exit (1);
}
if (first == 0)
{
putchar ('\f');
putchar ('\n');
}
else
{
first = 0;
}
print_parameters (pdc_cache, 0);
}
if ((close (fd)) < 0)
io_lose ("print_pdc_database", "close (%s) failed", filename);
}
void
read_stored_parameters (pdc_cache, filename)
struct pdc_cache_dump * pdc_cache;
char * filename;
{
int fd = (open (filename, (O_RDONLY), 0));
if (fd < 0)
io_lose ("read_stored_parameters", "open (%s) failed", filename);
if (! (search_pdc_database (fd, pdc_cache, filename)))
{
fprintf (stderr, "%s: %s: unable to find entry in models database\n",
(the_argv[0]), "read_stored_parameters");
fflush (stderr);
exit (1);
}
if ((close (fd)) < 0)
io_lose ("read_stored_parameters", "close (%s) failed", filename);
}
void
verify_parameters (new_pdc_cache, old_pdc_cache)
struct pdc_cache_dump *new_pdc_cache, *old_pdc_cache;
{
boolean lose;
lose = false;
if ((strcmp (new_pdc_cache->hardware, old_pdc_cache->hardware)) != 0)
{
lose = true;
printf ("Model differs: old = %s; current = %s.\n",
new_pdc_cache->hardware, old_pdc_cache->hardware);
}
if ((memcmp (&new_pdc_cache->cache_format,
&old_pdc_cache->cache_format,
(sizeof (struct pdc_cache_result)))) != 0)
{
lose = true;
printf ("The stored cache information is incorrect.\n");
}
if (!lose)
{
printf ("The stored cache information is correct.\n");
}
return;
}
void
usage ()
{
fprintf (stderr, "usage: one of:\n");
fprintf (stderr, " %s -add FILENAME\n", (the_argv[0]));
fprintf (stderr, " %s -replace FILENAME\n", (the_argv[0]));
fprintf (stderr, " %s -verify FILENAME\n", (the_argv[0]));
fprintf (stderr, " %s -print FILENAME\n", (the_argv[0]));
fprintf (stderr, " %s -printall FILENAME\n", (the_argv[0]));
fflush (stderr);
exit (1);
}
void
main (argc, argv)
int argc;
char **argv;
{
the_argv = argv;
if ((uname (&sysinfo)) < 0)
io_lose ("main", "uname failed", 0);
if (argc != 3)
usage ();
{
char * keyword = (argv[1]);
char * filename = (argv[2]);
if ((strcmp (keyword, "-add")) == 0)
{
struct pdc_cache_dump pdc_cache;
update_pdc_database (MODE_ADD, (&pdc_cache), filename);
}
else if ((strcmp (keyword, "-replace")) == 0)
{
struct pdc_cache_dump pdc_cache;
update_pdc_database (MODE_REPLACE, (&pdc_cache), filename);
}
else if ((strcmp (keyword, "-print")) == 0)
{
struct pdc_cache_dump pdc_cache;
update_pdc_database (MODE_PRINT, (&pdc_cache), filename);
print_parameters (&pdc_cache, 1);
}
else if ((strcmp (keyword, "-printall")) == 0)
{
print_pdc_database (filename);
}
else if ((strcmp (keyword, "-verify")) == 0)
{
struct pdc_cache_dump old_pdc_cache;
struct pdc_cache_dump new_pdc_cache;
read_stored_parameters ((&old_pdc_cache), filename);
read_parameters (&new_pdc_cache);
verify_parameters ((&new_pdc_cache), (&old_pdc_cache));
}
else
usage ();
}
exit (0);
}