--- /dev/null
+/* -*-C-*-
+
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/hppacach.c,v 1.1 1990/08/08 20:21:12 jinx Exp $
+
+Copyright (c) 1990 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science. Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. */
+
+#include <stdio.h>
+#include <math.h>
+
+#include <sys/stat.h>
+#include <memory.h>
+
+#include <nlist.h>
+
+#include "hppacache.h"
+
+#define true 1
+#define false 0
+#define boolean int
+
+#ifdef DEBUG
+
+#define DEBUGGING(stmt) stmt
+
+#else
+
+#define DEBUGGING(stmt) \
+do { \
+}while (0)
+
+#endif
+\f
+/* File that contains the symbol table for the kernel */
+
+#define KERNEL_FILE "/hp-ux"
+
+/* File where the kernel image lives */
+
+#define KERNEL_MEMORY_FILE "/dev/kmem"
+
+#define UTSNAME_SYMBOL "utsname"
+#define PDC_CACHE_SYMBOL "cache_tlb_parms"
+
+/* File where cached locations (to avoid nlist search) live */
+
+#define LOCATIONS_CACHE_FILE "/tmp/hppa.cache"
+
+/* Operating system name */
+
+#define SYSNAME "HP-UX"
+
+static struct utsname sysinfo;
+static char **the_argv;
+\f
+void
+io_error (format, fname)
+ char *format, *fname;
+{
+ char errmsg[MAXPATHLEN + 257];
+ char errstring[MAXPATHLEN + 257];
+
+ sprintf (&errmsg[0], format, fname);
+ sprintf (&errstring[0], "%s: %s", (the_argv[0]), (&errmsg[0]));
+ perror (&errstring[0]);
+ return;
+}
+
+void
+io_lose (format, fname)
+ char *format, *fname;
+{
+ io_error (format, fname);
+ exit (1);
+}
+
+struct kernel_locations
+{
+ long utsname_location;
+ long pdc_cache_location;
+};
+
+struct nlist nl[] =
+{
+ { UTSNAME_SYMBOL },
+ { PDC_CACHE_SYMBOL },
+ { 0 },
+};
+
+int
+read_nlist (kloc)
+ struct kernel_locations *kloc;
+{
+ DEBUGGING (printf ("reading nlist...\n"));
+
+ if ((nlist (KERNEL_FILE, nl)) != 0)
+ {
+ io_error ("nlist: failed on %s", KERNEL_FILE);
+ return (-1);
+ }
+
+ 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));
+
+ return (0);
+}
+\f
+void
+read_model (pdc_cache)
+ struct pdc_cache_dump *pdc_cache;
+{
+ int fd, read_result;
+ static char filename[MAXPATHLEN + 1];
+
+ sprintf ((&filename[0]),
+ MODELS_FILENAME,
+ CACHE_FILENAME_PATH);
+ fprintf (stderr, "%s:\n", (the_argv[0]));
+ fprintf (stderr,
+ "\tReading cache information from the model-based database (%s).\n",
+ (&filename[0]));
+ fd = (open ((&filename[0]), O_RDONLY));
+ if (fd < 0)
+ {
+ io_lose ("read_model: open (%s) failed", (&filename[0]));
+ }
+
+ while (true)
+ {
+ read_result = (read (fd, ((char *) pdc_cache), (sizeof (struct pdc_cache_dump))));
+ if (read_result != (sizeof (struct pdc_cache_dump)))
+ {
+ break;
+ }
+ if ((strcmp (sysinfo.machine, pdc_cache->hardware)) == 0)
+ {
+ close (fd);
+ fprintf (stderr,
+ "\tFound information for model %s in %s.\n",
+ sysinfo.machine, (&filename[0]));
+ return;
+ }
+ }
+ close (fd);
+ fprintf (stderr,
+ "\tCould not find information for model %s in %s.\n",
+ sysinfo.machine, (&filename[0]));
+ exit (1);
+}
+\f
+void
+read_parameters (pdc_cache)
+ struct pdc_cache_dump *pdc_cache;
+{
+ int kmem;
+
+ struct kernel_locations kloc;
+ struct utsname kerninfo;
+
+ if ((read_nlist (&kloc)) < 0)
+ {
+ read_model (pdc_cache);
+ return;
+ }
+ kmem = (open (KERNEL_MEMORY_FILE, O_RDONLY));
+ if (kmem < 0)
+ {
+ io_error ("read_parameters: open (%s) failed", KERNEL_MEMORY_FILE);
+ read_model (pdc_cache);
+ return;
+ }
+ else
+ {
+ if ((lseek (kmem, kloc.utsname_location, 0)) < 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), 0)) < 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;
+}
+\f
+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 it.", op);
+ break;
+
+ case 1:
+ printf ("\n Only ");
+ printf (pattern, "D");
+ printf (" needs to be used to %s it.", op);
+ break;
+
+ case 2:
+ printf ("\n Only ");
+ printf (pattern, "I");
+ printf (" needs to be used to %s it.", op);
+ break;
+
+ case 3:
+ printf ("\n Either ");
+ printf (pattern, "D");
+ printf (" or ");
+ printf (pattern, "I");
+ printf (" can be used to %s it.", 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;
+}
+\f
+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;
+}
+\f
+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 bytes (%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)
+ struct pdc_cache_dump *pdc_cache;
+{
+ struct pdc_cache_result *io_arch_format;
+
+ 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);
+
+ 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;
+}
+\f
+static char dumpname[MAXPATHLEN + 1];
+
+void
+dump_parameters (pdc_cache)
+ struct pdc_cache_dump *pdc_cache;
+{
+ int file;
+
+ sprintf (&dumpname[0],
+ CACHE_FILENAME,
+ CACHE_FILENAME_PATH,
+ sysinfo.nodename,
+ sysinfo.machine);
+
+ file = open (&dumpname[0], (O_WRONLY | O_CREAT | O_TRUNC), 0664);
+ if (file < 0)
+ {
+ io_lose ("dump_parameters: open (%s) failed", dumpname);
+ }
+ if ((write (file, pdc_cache, (sizeof (struct pdc_cache_dump)))) !=
+ (sizeof (struct pdc_cache_dump)))
+ {
+ io_lose ("dump_parameters: write (%s) failed", dumpname);
+ }
+ if ((close (file)) != 0)
+ {
+ io_lose ("dump_parameters: close (%s) failed", dumpname);
+ }
+ return;
+}
+
+void
+read_stored_parameters (old_pdc_cache)
+ struct pdc_cache_dump *old_pdc_cache;
+{
+ int file;
+
+ sprintf (&dumpname[0],
+ CACHE_FILENAME,
+ CACHE_FILENAME_PATH,
+ sysinfo.nodename,
+ sysinfo.machine);
+
+ file = open (&dumpname[0], (O_RDONLY), 0);
+ if (file < 0)
+ {
+ io_lose ("read_stored_parameters: open (%s) failed", dumpname);
+ }
+ if ((read (file, old_pdc_cache, (sizeof (struct pdc_cache_dump)))) !=
+ (sizeof (struct pdc_cache_dump)))
+ {
+ io_lose ("read_stored_parameters: read (%s) failed", dumpname);
+ }
+ if ((close (file)) != 0)
+ {
+ io_lose ("read_stored_parameters: close (%s) failed", dumpname);
+ }
+ return;
+}
+
+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;
+}
+\f
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int
+ count,
+ uname_result;
+ struct pdc_cache_dump
+ new_pdc_cache_s, old_pdc_cache_s,
+ *new_pdc_cache, *old_pdc_cache;
+
+ the_argv = argv;
+ new_pdc_cache = ((struct pdc_cache_dump *) NULL);
+ old_pdc_cache = ((struct pdc_cache_dump *) NULL);
+
+ uname_result = (uname (&sysinfo));
+ if (uname_result < 0)
+ {
+ fprintf (stderr, "%s: uname failed.\n", argv[0]);
+ exit (1);
+ }
+
+ if (argc <= 1)
+ {
+ if (new_pdc_cache == ((struct pdc_cache_dump *) NULL))
+ {
+ read_parameters (&new_pdc_cache_s);
+ new_pdc_cache = &new_pdc_cache_s;
+ }
+ dump_parameters (new_pdc_cache);
+ }
+ else
+ {
+ for (count = 1; count < argc; count++)
+ {
+ if ((strcmp ((argv[count]), "-printnew")) == 0)
+ {
+ if (new_pdc_cache == ((struct pdc_cache_dump *) NULL))
+ {
+ read_parameters (&new_pdc_cache_s);
+ new_pdc_cache = &new_pdc_cache_s;
+ }
+ print_parameters (new_pdc_cache);
+ }
+ else if ((strcmp ((argv[count]), "-printold")) == 0)
+ {
+ if (old_pdc_cache == ((struct pdc_cache_dump *) NULL))
+ {
+ read_stored_parameters (&old_pdc_cache_s);
+ old_pdc_cache = &old_pdc_cache_s;
+ }
+ print_parameters (old_pdc_cache);
+ }
+ else if ((strcmp ((argv[count]), "-dump")) == 0)
+ {
+ if (new_pdc_cache == ((struct pdc_cache_dump *) NULL))
+ {
+ read_parameters (&new_pdc_cache_s);
+ new_pdc_cache = &new_pdc_cache_s;
+ }
+ dump_parameters (new_pdc_cache);
+ }
+ else if ((strcmp ((argv[count]), "-verify")) == 0)
+ {
+ if (new_pdc_cache == ((struct pdc_cache_dump *) NULL))
+ {
+ read_parameters (&new_pdc_cache_s);
+ new_pdc_cache = &new_pdc_cache_s;
+ }
+ if (old_pdc_cache == ((struct pdc_cache_dump *) NULL))
+ {
+ read_stored_parameters (&old_pdc_cache_s);
+ old_pdc_cache = &old_pdc_cache_s;
+ }
+ verify_parameters (new_pdc_cache, old_pdc_cache);
+ }
+ else
+ {
+ fprintf (stderr, "usage: %s [-dump] [-verify] [-printnew] [-printold]\n",
+ argv[0]);
+ exit (1);
+ }
+ }
+ }
+ exit (0);
+}
--- /dev/null
+/* -*-C-*-
+
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/hppacach.h,v 1.1 1990/08/08 20:20:56 jinx Exp $
+
+Copyright (c) 1990 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science. Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. */
+
+#ifndef HPPACACHE_H /* Prevent multiple inclusion */
+
+#define HPPACACHE_H
+
+#ifdef C_SCHEME
+#include "paths.h"
+#define CACHE_FILENAME_PATH SCHEME_SOURCES_PATH
+#define MODELS_FILENAME "HPPAmodels"
+#endif
+
+/*
+ Format strings used to determine the name of the file
+ where to store (and examine) the cache description.
+
+ The strings are used as in
+ printf (CACHE_FILENAME, CACHE_FILENAME_PATH, hostname_string, model_string);
+
+ The default value (below) would generate the file name
+ /tmp/altdorf.cache
+ when running on a machine named altdorf.
+
+ To ignore a string parameter, use the %.0s format.
+ */
+
+#ifndef CACHE_FILENAME_PATH
+#define CACHE_FILENAME_PATH "/tmp/"
+#endif
+
+#ifndef CACHE_FILENAME
+#define CACHE_FILENAME "%s%s.cache"
+#endif /* CACHE_FILENAME */
+
+#ifndef MODELS_FILENAME
+#define MODELS_FILENAME "%shppamodels"
+#endif
+\f
+#define I_CACHE 1
+#define D_CACHE 2
+
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <machine/cpu.h>
+#include <machine/pdc_rqsts.h>
+#include <fcntl.h>
+
+/* PDC_CACHE (processor dependent code cache information call)
+ return data destructuring.
+
+ This is the same information as in machine/pdc_rqsts.h
+ pdc_cache_rtn_block, but with fields as defined in the PDC_CACHE
+ section of the I/O Architecture Manual.
+
+ The main difference is the cache configuration field.
+ Which is correct?
+ */
+
+union cache_conf
+{
+ unsigned long word;
+ struct
+ {
+ unsigned block: 8;
+ unsigned line: 3;
+ unsigned res1: 2;
+ unsigned wt: 1;
+ unsigned fsel: 2;
+ unsigned cst: 3;
+ unsigned res2: 11;
+ unsigned hv: 2;
+ } bits;
+};
+
+struct cache_info
+{
+ unsigned long size; /* in bytes */
+ union cache_conf conf; /* format description */
+ unsigned long base; /* start address */
+ unsigned long stride; /* in bytes */
+ unsigned long count; /* number of entries */
+ unsigned long loop; /* set associativity */
+};
+
+union tlb_conf
+{
+ unsigned long word;
+ struct
+ {
+ unsigned res1: 12;
+ unsigned psel: 2;
+ unsigned hv1: 1;
+ unsigned res2: 1;
+ unsigned cst: 3;
+ unsigned res3: 11;
+ unsigned hv2: 2;
+ } bits;
+};
+
+struct tlb_info
+{
+ unsigned long size; /* number of entries */
+ union tlb_conf conf; /* format description */
+ unsigned long sp_base; /* space parameters */
+ unsigned long sp_stride;
+ unsigned long sp_count;
+ unsigned long off_base; /* offset parameters */
+ unsigned long off_stride;
+ unsigned long off_count;
+ unsigned long loop; /* set associativity */
+};
+
+struct pdc_cache_result
+{
+ struct cache_info I_info;
+ struct cache_info D_info;
+ struct tlb_info IT_info;
+ struct tlb_info DT_info;
+};
+
+struct pdc_cache_dump
+{
+ char hardware[sizeof (utsname.machine)];
+ struct pdc_cache_rtn_block cache_format;
+};
+
+#endif /* HPPACACHE_H */