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 >
C/C++ Source or Header  |  1999-03-24  |  17KB  |  642 lines

  1. /* -*-C-*-
  2.  
  3. $Id: hppacach.c,v 1.13 1999/03/24 23:30:12 cph Exp $
  4.  
  5. Copyright (c) 1990-1999 Massachusetts Institute of Technology
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #include <stdio.h>
  23. #include <math.h>
  24. #include <sys/stat.h>
  25. #include <memory.h>
  26. #include <nlist.h>
  27. #include <unistd.h>
  28. #include <errno.h>
  29.  
  30. #include "hppacach.h"
  31.  
  32. #define true            1
  33. #define false            0
  34. #define boolean            int
  35.  
  36. #ifdef DEBUG
  37.  
  38. #define DEBUGGING(stmt) stmt
  39.  
  40. #else
  41.  
  42. #define DEBUGGING(stmt) do                        \
  43. {                                    \
  44. } while (0)
  45.  
  46. #endif
  47.  
  48. /* File that contains the symbol table for the kernel */
  49.  
  50. char * kernel_filenames [] =
  51. {
  52.   "/hp-ux",
  53.   "/stand/vmunix",
  54.   0
  55. };
  56.  
  57. /* File where the kernel image lives */
  58.  
  59. #define KERNEL_MEMORY_FILE    "/dev/kmem"
  60.  
  61. #define UTSNAME_SYMBOL        "utsname"
  62. #define PDC_CACHE_SYMBOL    "cache_tlb_parms"
  63.  
  64. static struct utsname sysinfo;
  65. static char **the_argv;
  66.  
  67. void
  68. io_error (pname, format, fname)
  69.      char * pname;
  70.      char * format;
  71.      char * fname;
  72. {
  73.   char errmsg[MAXPATHLEN + 257];
  74.   char errstring[MAXPATHLEN + 257];
  75.  
  76.   sprintf (&errmsg[0], format, fname);
  77.   sprintf (&errstring[0], "%s: %s: %s", (the_argv[0]), pname, (&errmsg[0]));
  78.   perror (&errstring[0]);
  79. }
  80.  
  81. void
  82. io_lose (pname, format, fname)
  83.      char * pname;
  84.      char * format;
  85.      char * fname;
  86. {
  87.   io_error (pname, format, fname);
  88.   exit (1);
  89. }
  90.  
  91. struct kernel_locations
  92. {
  93.   long utsname_location;
  94.   long pdc_cache_location;
  95. };
  96.  
  97. struct nlist nl[] =
  98. {
  99.   { UTSNAME_SYMBOL },
  100.   { PDC_CACHE_SYMBOL },
  101.   { 0 },
  102. };
  103.  
  104. static char *
  105. choose_kernel_file ()
  106. {
  107.   char ** p = kernel_filenames;
  108.   while (1)
  109.     {
  110.       struct stat s;
  111.       if ((stat ((*p), (&s))) == 0)
  112.     return (*p);
  113.       p += 1;
  114.     }
  115.   fprintf (stderr, "Unable to find kernel.\n");
  116.   fflush (stderr);
  117.   exit (1);
  118. }
  119.  
  120. void
  121. read_nlist (kloc)
  122.      struct kernel_locations *kloc;
  123. {
  124.   char * kernel_filename = (choose_kernel_file ());
  125.   DEBUGGING (printf ("reading nlist...\n"));
  126.  
  127.   if ((nlist (kernel_filename, nl)) != 0)
  128.     io_lose ("read_nlist", "failed on both %s and %s", kernel_filename);
  129.  
  130.   DEBUGGING (printf ("reading nlist done.\n"));
  131.  
  132.   kloc->utsname_location = nl[0].n_value;
  133.   kloc->pdc_cache_location = nl[1].n_value;
  134.  
  135.   DEBUGGING (printf ("utsname location = 0x%x\n", kloc->utsname_location));
  136.   DEBUGGING (printf ("pdc_cache location = 0x%x\n", kloc->pdc_cache_location));
  137. }
  138.  
  139. void
  140. read_parameters (pdc_cache)
  141.      struct pdc_cache_dump *pdc_cache;
  142. {
  143.   struct kernel_locations kloc;
  144.   struct utsname kerninfo;
  145.   int kmem = (open (KERNEL_MEMORY_FILE, O_RDONLY));
  146.   if (kmem < 0)
  147.     io_lose ("read_parameters", "open (%s) failed", KERNEL_MEMORY_FILE);
  148.   read_nlist (&kloc);
  149.   if ((lseek (kmem, kloc.utsname_location, SEEK_SET)) < 0)
  150.     io_lose ("read_parameters", "lseek (%s) failed", KERNEL_MEMORY_FILE);
  151.   if ((read (kmem, (&kerninfo), (sizeof (kerninfo)))) !=
  152.       (sizeof (kerninfo)))
  153.     io_lose ("read_parameters", "read (%s) failed", KERNEL_MEMORY_FILE);
  154.   if ((memcmp ((&kerninfo), (&sysinfo), (sizeof (sysinfo)))) != 0)
  155.     fprintf (stderr, "read_parameters: uname and %s in %s differ.\n",
  156.          kloc.utsname_location, KERNEL_MEMORY_FILE);
  157.   strncpy (pdc_cache->hardware, (kerninfo.machine),
  158.        (sizeof (kerninfo.machine)));
  159.   if ((lseek (kmem, (kloc.pdc_cache_location), SEEK_SET)) < 0)
  160.     io_lose ("read_parameters", "lseek (%s) failed", KERNEL_MEMORY_FILE);
  161.   if ((read (kmem, &pdc_cache->cache_format,
  162.          (sizeof (pdc_cache->cache_format)))) !=
  163.       (sizeof (pdc_cache->cache_format)))
  164.     io_lose ("read_parameters", "read (%s) failed", KERNEL_MEMORY_FILE);
  165.   if ((close (kmem)) < 0)
  166.     io_lose ("read_parameters", "close (%s) failed", KERNEL_MEMORY_FILE);
  167.   return;
  168. }
  169.  
  170. void
  171. print_sel (sel, name, pattern, op)
  172.      unsigned int sel;
  173.      char *name;
  174.      char *pattern;
  175.      char *op;
  176. {
  177.   switch (sel)
  178.   {
  179.     case 0:
  180.       printf ("\n      Both ");
  181.       printf (pattern, "D");
  182.       printf (" and ");
  183.       printf (pattern, "I");
  184.       printf (" must be used to %s.", op);
  185.       break;
  186.  
  187.     case 1:
  188.       printf ("\n      Only ");
  189.       printf (pattern, "D");
  190.       printf (" needs to be used to %s.", op);
  191.       break;
  192.  
  193.     case 2:
  194.       printf ("\n      Only ");
  195.       printf (pattern, "I");
  196.       printf (" needs to be used to %s.", op);
  197.       break;
  198.  
  199.     case 3:
  200.       printf ("\n      Either ");
  201.       printf (pattern, "D");
  202.       printf (" or ");
  203.       printf (pattern, "I");
  204.       printf (" can be used to %s.", op);
  205.       break;
  206.  
  207.     default:
  208.       fprintf (stderr, "\n      Bad %s value %d.", name, (sel));
  209.       break;
  210.   }
  211.  
  212.   return;
  213. }
  214.  
  215. void
  216. print_cst (cst)
  217.      unsigned int cst;
  218. {
  219.   switch (cst)
  220.   {
  221.     case 0:
  222.       printf ("\n      It does not issue coherent operations.");
  223.       break;
  224.  
  225.     case 1:
  226.       printf ("\n      It issues coherent operations.");
  227.       break;
  228.  
  229.     default:
  230.       printf ("\n      It has a reserved cst value %d.", (cst));
  231.       break;
  232.   }
  233.   return;
  234. }
  235.  
  236. void
  237. print_cache (info, name, write_only_p)
  238.      struct cache_info *info;
  239.      char *name;
  240.      boolean write_only_p;
  241. {
  242.   printf ("\n");
  243.  
  244.   /* First print the user-readable information as a comment. */
  245.  
  246.   printf ("    /*\n");
  247.   printf ("      %s-cache information:\n", name);
  248.  
  249.   printf ("\tsize\t\t%ld bytes (%ld K).\n", info->size, (info->size / 1024));
  250.   printf ("\tconf\t\t0x%08lx\n", info->conf.word);
  251.   printf ("\tbase\t\t0x%lx\n", info->base);
  252.   printf ("\tstride\t\t%ld bytes.\n", info->stride);
  253.   printf ("\tcount\t\t%ld entries.\n", info->count);
  254.   printf ("\tloop\t\t%ld association%s per entry.\n",
  255.       info->loop, ((info->loop == 1) ? "" : "s"));
  256.  
  257.   printf ("\tblock size\t%d line%s.\n",
  258.       info->conf.bits.block,
  259.       ((info->conf.bits.block == 1) ? "" : "s"));
  260.   printf ("\tline size\t%d (16-byte units).\n", info->conf.bits.line);
  261.  
  262.   if (write_only_p)
  263.   {
  264.     printf ("      It is a read-only cache.");
  265.   }
  266.   else if (info->conf.bits.wt == 0)
  267.   {
  268.     printf ("      It is a write-to cache.");
  269.   }
  270.   else
  271.   {
  272.     printf ("      It is a write-through cache.");
  273.   }
  274.  
  275.   print_cst ((info->conf.bits.cst));
  276.   print_sel ((info->conf.bits.fsel), "f-sel", "F%sC", "flush");
  277.  
  278.   /* Now print the C-readable information. */
  279.  
  280.   printf ("\n    */\n");
  281.   printf ("    { %ld, 0x%08lx, 0x%lx, %ld, %ld, %ld }",
  282.       info->size, info->conf.word, info->base,
  283.       info->stride, info->count, info->loop);
  284.  
  285.   return;
  286. }
  287.  
  288. void
  289. print_tlb (info, name)
  290.      struct tlb_info *info;
  291.      char *name;
  292. {
  293.   printf ("\n");
  294.  
  295.   /* First print the user-readable information as a comment. */
  296.  
  297.   printf ("    /*\n");
  298.   printf ("      %s-TLB information:\n", name);
  299.  
  300.   printf ("\tsize\t\t%ld entries (%ld K).\n",
  301.       info->size, (info->size / 1024));
  302.   printf ("\tconf\t\t0x%08lx\n", info->conf.word);
  303.   printf ("\tsp_base\t\t0x%lx\n", info->sp_base);
  304.   printf ("\tsp_stride\t%ld\n", info->sp_stride);
  305.   printf ("\tsp_count\t%ld\n", info->sp_count);
  306.   printf ("\toff_base\t0x%lx\n", info->off_base);
  307.   printf ("\toff_stride\t%ld\n", info->off_stride);
  308.   printf ("\toff_count\t%ld\n", info->off_count);
  309.   printf ("\tloop\t\t%ld association%s per entry.",
  310.       info->loop, ((info->loop == 1) ? "" : "s"));
  311.   
  312.   print_cst ((info->conf.bits.cst));
  313.   print_sel ((info->conf.bits.psel), "p-sel", "P%sTLB", "purge");
  314.  
  315.   /* Now print the C-readable information. */
  316.  
  317.   printf ("\n    */\n");
  318.   printf ("    { %ld, 0x%08lx, 0x%lx, %ld, %ld, 0x%lx, %ld, %ld, %ld }",
  319.       info->size, info->conf.word,
  320.       info->sp_base, info->sp_stride, info->sp_count,
  321.       info->off_base, info->off_stride, info->off_count,
  322.       info->loop);
  323.  
  324.   return;  
  325. }
  326.  
  327. void
  328. print_parameters (pdc_cache, node_p)
  329.      struct pdc_cache_dump *pdc_cache;
  330.      int node_p;
  331. {
  332.   struct pdc_cache_result *io_arch_format;
  333.  
  334.   if (node_p)
  335.   {
  336.     printf ("/* Emacs: Use -*- C -*- mode when editting this file. */\n\n");
  337.     printf ("{\n  /* Cache description for %s, an HP PA %s processor. */\n\n",
  338.         sysinfo.nodename,
  339.         sysinfo.machine);
  340.   }
  341.   else
  342.   {
  343.     printf ("{\n");
  344.   }
  345.  
  346.   io_arch_format = ((struct pdc_cache_result *) &(pdc_cache->cache_format));
  347.  
  348.   printf ("  \"%s\",\n\n  {", pdc_cache->hardware);
  349.  
  350.   print_cache (&(io_arch_format->I_info), "I", true);
  351.   printf (",");
  352.   print_cache (&(io_arch_format->D_info), "D", false);
  353.   printf (",");
  354.  
  355.   print_tlb (&(io_arch_format->IT_info), "I");
  356.   printf (",");
  357.   print_tlb (&(io_arch_format->DT_info), "D");
  358.   printf ("\n");
  359.  
  360.   printf ("  }};\n");
  361.   return;
  362. }
  363.  
  364. int
  365. search_pdc_database (fd, pdc_cache, filename)
  366.      int fd;
  367.      struct pdc_cache_dump * pdc_cache;
  368.      char * filename;
  369. {
  370.   while (1)
  371.     {
  372.       int scr =
  373.     (read (fd, ((char *) pdc_cache), (sizeof (struct pdc_cache_dump))));
  374.       if (scr < 0)
  375.     io_lose ("search_pdc_database", "read (%s) failed", filename);
  376.       if (scr != (sizeof (struct pdc_cache_dump)))
  377.     {
  378.       if (scr == 0)
  379.         return (0);
  380.       fprintf (stderr, "%s: %s: incomplete read (%s)\n",
  381.            (the_argv[0]), "search_pdc_database", filename);
  382.       fflush (stderr);
  383.       exit (1);
  384.     }
  385.       if ((strcmp ((sysinfo . machine), (pdc_cache -> hardware))) == 0)
  386.     return (1);
  387.     }
  388. }
  389.  
  390. #define MODE_ADD    0
  391. #define MODE_REPLACE    1
  392. #define MODE_PRINT    2
  393.  
  394. void
  395. update_pdc_database (mode, pdc_cache, filename)
  396.      int mode;
  397.      struct pdc_cache_dump * pdc_cache;
  398.      char * filename;
  399. {
  400.   int write_p = 1;
  401.   int fd = (open (filename, (O_RDWR | O_CREAT), 0666));
  402.   if (fd < 0)
  403.   {
  404.     if (errno != EACCES)
  405.       io_lose ("update_pdc_database", "open (%s) failed", filename);
  406.     fd = (open (filename, O_RDONLY));
  407.     if (fd < 0)
  408.       io_lose ("update_pdc_database", "open (%s) failed", filename);
  409.     else
  410.     {
  411.       write_p = 0;
  412.       if (mode != MODE_PRINT)
  413.     fprintf (stderr, "Data base \"%s\" is write-protected.\n", filename);
  414.     }
  415.   }
  416.   if (! (search_pdc_database (fd, pdc_cache, filename)))
  417.     {
  418.       read_parameters (pdc_cache);
  419.       if (!write_p && (mode != MODE_PRINT))
  420.     printf ("Could not write information to data base.\n");
  421.       else
  422.       {
  423.     int scr =
  424.       (write (fd, ((char *) pdc_cache), (sizeof (struct pdc_cache_dump))));
  425.     if (scr < 0)
  426.       io_lose ("update_pdc_database", "write (%s) failed", filename);
  427.     if (scr != (sizeof (struct pdc_cache_dump)))
  428.       {
  429.         fprintf (stderr, "%s: %s: incomplete write (%s)\n",
  430.              (the_argv[0]), "update_pdc_database", filename);
  431.         fflush (stderr);
  432.         exit (1);
  433.       }
  434.       }
  435.     }
  436.   else
  437.   {
  438.     struct pdc_cache_dump new_cache_s, * new_cache;
  439.  
  440.     new_cache = & new_cache_s;
  441.     read_parameters (new_cache);
  442.     if ((memcmp (new_cache, pdc_cache, (sizeof (struct pdc_cache_dump))))
  443.     == 0)
  444.     {
  445.       if (mode != MODE_PRINT)
  446.     printf ("Correct information for model %s is present in data base.\n",
  447.         &new_cache->hardware[0]);
  448.     }
  449.     else
  450.     {
  451.       printf ("Data base contains different information for model %s.\n",
  452.           &new_cache->hardware[0]);
  453.       switch (mode)
  454.       {
  455.     case MODE_REPLACE:
  456.         {
  457.       if (write_p)
  458.       {
  459.         printf ("Keeping the new information.\n");
  460.         if ((lseek (fd, (- (sizeof (struct pdc_cache_dump))), SEEK_CUR))
  461.         == -1)
  462.           io_lose ("update_pdc_database", "lseek (%s) failed", filename);
  463.         if ((write (fd, new_cache, (sizeof (struct pdc_cache_dump))))
  464.         != (sizeof (struct pdc_cache_dump)))
  465.           io_lose ("update_pdc_database", "write (%s) failed", filename);
  466.         break;
  467.       }
  468.     }
  469.  
  470.     case MODE_ADD:
  471.         {
  472.       printf ("Keeping the old information.\n");
  473.       break;
  474.     }
  475.  
  476.     case MODE_PRINT:
  477.         {
  478.       printf ("New information:\n");
  479.       print_parameters (new_cache, 1);
  480.       printf ("\n\nOld information:\n");
  481.     }
  482.     default:
  483.       fprintf (stderr, "%s error.  Unknown mode %d.\n", the_argv[0], mode);
  484.       }
  485.     }
  486.   }
  487.   if ((close (fd)) < 0)
  488.     io_lose ("update_pdc_database", "close (%s) failed", filename);
  489.   return;
  490. }
  491.  
  492. void
  493. print_pdc_database (filename)
  494.      char * filename;
  495. {
  496.   struct pdc_cache_dump pdc_cache_s, *pdc_cache;
  497.   int fd = (open (filename, (O_RDONLY), 0666));
  498.   int first;
  499.  
  500.   if (fd < 0)
  501.     io_lose ("print_pdc_database", "open (%s) failed", filename);
  502.  
  503.   pdc_cache = &pdc_cache_s;
  504.   first = 1;
  505.   while (1)
  506.   {
  507.     int scr =
  508.       (read (fd, ((char *) pdc_cache), (sizeof (struct pdc_cache_dump))));
  509.     if (scr < 0)
  510.       io_lose ("print_pdc_database", "read (%s) failed", filename);
  511.     if (scr != (sizeof (struct pdc_cache_dump)))
  512.     {
  513.       if (scr == 0)
  514.     break;
  515.       fprintf (stderr, "%s: %s: incomplete read (%s)\n",
  516.            (the_argv[0]), "print_pdc_database", filename);
  517.       fflush (stderr);
  518.       exit (1);
  519.     }
  520.  
  521.     if (first == 0)
  522.     {
  523.       putchar ('\f');
  524.       putchar ('\n');
  525.     }
  526.     else
  527.     {
  528.       first = 0;
  529.     }
  530.     print_parameters (pdc_cache, 0);
  531.   }
  532.  
  533.   if ((close (fd)) < 0)
  534.     io_lose ("print_pdc_database", "close (%s) failed", filename);
  535. }
  536.  
  537. void
  538. read_stored_parameters (pdc_cache, filename)
  539.      struct pdc_cache_dump * pdc_cache;
  540.      char * filename;
  541. {
  542.   int fd = (open (filename, (O_RDONLY), 0));
  543.   if (fd < 0)
  544.     io_lose ("read_stored_parameters", "open (%s) failed", filename);
  545.   if (! (search_pdc_database (fd, pdc_cache, filename)))
  546.     {
  547.       fprintf (stderr, "%s: %s: unable to find entry in models database\n",
  548.            (the_argv[0]), "read_stored_parameters");
  549.       fflush (stderr);
  550.       exit (1);
  551.     }
  552.   if ((close (fd)) < 0)
  553.     io_lose ("read_stored_parameters", "close (%s) failed", filename);
  554. }
  555.  
  556. void
  557. verify_parameters (new_pdc_cache, old_pdc_cache)
  558.      struct pdc_cache_dump *new_pdc_cache, *old_pdc_cache;
  559. {
  560.   boolean lose;
  561.  
  562.   lose = false;
  563.   if ((strcmp (new_pdc_cache->hardware, old_pdc_cache->hardware)) != 0)
  564.   {
  565.     lose = true;
  566.     printf ("Model differs: old = %s; current = %s.\n",
  567.         new_pdc_cache->hardware, old_pdc_cache->hardware);
  568.   }
  569.   if ((memcmp (&new_pdc_cache->cache_format,
  570.            &old_pdc_cache->cache_format,
  571.            (sizeof (struct pdc_cache_result)))) != 0)
  572.   {
  573.     lose = true;
  574.     printf ("The stored cache information is incorrect.\n");
  575.   }
  576.   if (!lose)
  577.   {
  578.     printf ("The stored cache information is correct.\n");
  579.   }
  580.   return;
  581. }
  582.  
  583. void
  584. usage ()
  585. {
  586.   fprintf (stderr, "usage: one of:\n");
  587.   fprintf (stderr, " %s -add FILENAME\n", (the_argv[0]));
  588.   fprintf (stderr, " %s -replace FILENAME\n", (the_argv[0]));
  589.   fprintf (stderr, " %s -verify FILENAME\n", (the_argv[0]));
  590.   fprintf (stderr, " %s -print FILENAME\n", (the_argv[0]));
  591.   fprintf (stderr, " %s -printall FILENAME\n", (the_argv[0]));
  592.   fflush (stderr);
  593.   exit (1);
  594. }
  595.  
  596. void
  597. main (argc, argv)
  598.      int argc;
  599.      char **argv;
  600. {
  601.   the_argv = argv;
  602.   if ((uname (&sysinfo)) < 0)
  603.     io_lose ("main", "uname failed", 0);
  604.   if (argc != 3)
  605.     usage ();
  606.   {
  607.     char * keyword = (argv[1]);
  608.     char * filename = (argv[2]);
  609.     if ((strcmp (keyword, "-add")) == 0)
  610.       {
  611.     struct pdc_cache_dump pdc_cache;
  612.     update_pdc_database (MODE_ADD, (&pdc_cache), filename);
  613.       }
  614.     else if ((strcmp (keyword, "-replace")) == 0)
  615.       {
  616.     struct pdc_cache_dump pdc_cache;
  617.     update_pdc_database (MODE_REPLACE, (&pdc_cache), filename);
  618.       }
  619.     else if ((strcmp (keyword, "-print")) == 0)
  620.       {
  621.     struct pdc_cache_dump pdc_cache;
  622.     update_pdc_database (MODE_PRINT, (&pdc_cache), filename);
  623.     print_parameters (&pdc_cache, 1);
  624.       }
  625.     else if ((strcmp (keyword, "-printall")) == 0)
  626.       {
  627.     print_pdc_database (filename);
  628.       }
  629.     else if ((strcmp (keyword, "-verify")) == 0)
  630.       {
  631.     struct pdc_cache_dump old_pdc_cache;
  632.     struct pdc_cache_dump new_pdc_cache;
  633.     read_stored_parameters ((&old_pdc_cache), filename);
  634.     read_parameters (&new_pdc_cache);
  635.     verify_parameters ((&new_pdc_cache), (&old_pdc_cache));
  636.       }
  637.     else
  638.       usage ();
  639.   }
  640.   exit (0);
  641. }
  642.