Author: jhb
Date: Fri Oct 10 20:47:23 2014
New Revision: 272913
URL: https://svnweb.freebsd.org/changeset/base/272913

Log:
  MFC 270828,271487,271495:
  Add sysctls to export the BIOS SMAP and EFI memory maps along with
  handlers in the sysctl(8) binary to format them.

Modified:
  stable/10/sbin/sysctl/sysctl.c
  stable/10/sys/amd64/amd64/machdep.c
  stable/10/sys/amd64/include/pc/bios.h
  stable/10/sys/i386/i386/machdep.c
  stable/10/sys/i386/include/pc/bios.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sbin/sysctl/sysctl.c
==============================================================================
--- stable/10/sbin/sysctl/sysctl.c      Fri Oct 10 20:37:06 2014        
(r272912)
+++ stable/10/sbin/sysctl/sysctl.c      Fri Oct 10 20:47:23 2014        
(r272913)
@@ -48,6 +48,15 @@ static const char rcsid[] =
 #include <sys/sysctl.h>
 #include <sys/vmmeter.h>
 
+#ifdef __amd64__
+#include <sys/efi.h>
+#include <machine/metadata.h>
+#endif
+
+#if defined(__amd64__) || defined(__i386__)
+#include <machine/pc/bios.h>
+#endif
+
 #include <ctype.h>
 #include <err.h>
 #include <errno.h>
@@ -454,12 +463,12 @@ parsefile(const char *filename)
 /* These functions will dump out various interesting structures. */
 
 static int
-S_clockinfo(int l2, void *p)
+S_clockinfo(size_t l2, void *p)
 {
        struct clockinfo *ci = (struct clockinfo*)p;
 
        if (l2 != sizeof(*ci)) {
-               warnx("S_clockinfo %d != %zu", l2, sizeof(*ci));
+               warnx("S_clockinfo %zu != %zu", l2, sizeof(*ci));
                return (1);
        }
        printf(hflag ? "{ hz = %'d, tick = %'d, profhz = %'d, stathz = %'d }" :
@@ -469,12 +478,12 @@ S_clockinfo(int l2, void *p)
 }
 
 static int
-S_loadavg(int l2, void *p)
+S_loadavg(size_t l2, void *p)
 {
        struct loadavg *tv = (struct loadavg*)p;
 
        if (l2 != sizeof(*tv)) {
-               warnx("S_loadavg %d != %zu", l2, sizeof(*tv));
+               warnx("S_loadavg %zu != %zu", l2, sizeof(*tv));
                return (1);
        }
        printf(hflag ? "{ %'.2f %'.2f %'.2f }" : "{ %.2f %.2f %.2f }",
@@ -485,14 +494,14 @@ S_loadavg(int l2, void *p)
 }
 
 static int
-S_timeval(int l2, void *p)
+S_timeval(size_t l2, void *p)
 {
        struct timeval *tv = (struct timeval*)p;
        time_t tv_sec;
        char *p1, *p2;
 
        if (l2 != sizeof(*tv)) {
-               warnx("S_timeval %d != %zu", l2, sizeof(*tv));
+               warnx("S_timeval %zu != %zu", l2, sizeof(*tv));
                return (1);
        }
        printf(hflag ? "{ sec = %'jd, usec = %'ld } " :
@@ -509,13 +518,13 @@ S_timeval(int l2, void *p)
 }
 
 static int
-S_vmtotal(int l2, void *p)
+S_vmtotal(size_t l2, void *p)
 {
        struct vmtotal *v = (struct vmtotal *)p;
        int pageKilo = getpagesize() / 1024;
 
        if (l2 != sizeof(*v)) {
-               warnx("S_vmtotal %d != %zu", l2, sizeof(*v));
+               warnx("S_vmtotal %zu != %zu", l2, sizeof(*v));
                return (1);
        }
 
@@ -536,10 +545,116 @@ S_vmtotal(int l2, void *p)
            v->t_vmshr * pageKilo, v->t_avmshr * pageKilo);
        printf("Shared Real Memory:\t(Total: %dK Active: %dK)\n",
            v->t_rmshr * pageKilo, v->t_armshr * pageKilo);
-       printf("Free Memory:\t%dK\n", v->t_free * pageKilo);
+       printf("Free Memory:\t%dK", v->t_free * pageKilo);
+
+       return (0);
+}
+
+#ifdef __amd64__
+#define efi_next_descriptor(ptr, size) \
+       ((struct efi_md *)(((uint8_t *) ptr) + size))
+
+static int
+S_efi_map(size_t l2, void *p)
+{
+       struct efi_map_header *efihdr;
+       struct efi_md *map;
+       const char *type;
+       size_t efisz;
+       int ndesc, i;
+
+       static const char *types[] = {
+               "Reserved",
+               "LoaderCode",
+               "LoaderData",
+               "BootServicesCode",
+               "BootServicesData",
+               "RuntimeServicesCode",
+               "RuntimeServicesData",
+               "ConventionalMemory",
+               "UnusableMemory",
+               "ACPIReclaimMemory",
+               "ACPIMemoryNVS",
+               "MemoryMappedIO",
+               "MemoryMappedIOPortSpace",
+               "PalCode"
+       };
+
+       /*
+        * Memory map data provided by UEFI via the GetMemoryMap
+        * Boot Services API.
+        */
+       if (l2 < sizeof(*efihdr)) {
+               warnx("S_efi_map length less than header");
+               return (1);
+       }
+       efihdr = p;
+       efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
+       map = (struct efi_md *)((uint8_t *)efihdr + efisz); 
+
+       if (efihdr->descriptor_size == 0)
+               return (0);
+       if (l2 != efisz + efihdr->memory_size) {
+               warnx("S_efi_map length mismatch %zu vs %zu", l2, efisz +
+                   efihdr->memory_size);
+               return (1);
+       }               
+       ndesc = efihdr->memory_size / efihdr->descriptor_size;
+
+       printf("\n%23s %12s %12s %8s %4s",
+           "Type", "Physical", "Virtual", "#Pages", "Attr");
+
+       for (i = 0; i < ndesc; i++,
+           map = efi_next_descriptor(map, efihdr->descriptor_size)) {
+               if (map->md_type <= EFI_MD_TYPE_PALCODE)
+                       type = types[map->md_type];
+               else
+                       type = "<INVALID>";
+               printf("\n%23s %012lx %12p %08lx ", type, map->md_phys,
+                   map->md_virt, map->md_pages);
+               if (map->md_attr & EFI_MD_ATTR_UC)
+                       printf("UC ");
+               if (map->md_attr & EFI_MD_ATTR_WC)
+                       printf("WC ");
+               if (map->md_attr & EFI_MD_ATTR_WT)
+                       printf("WT ");
+               if (map->md_attr & EFI_MD_ATTR_WB)
+                       printf("WB ");
+               if (map->md_attr & EFI_MD_ATTR_UCE)
+                       printf("UCE ");
+               if (map->md_attr & EFI_MD_ATTR_WP)
+                       printf("WP ");
+               if (map->md_attr & EFI_MD_ATTR_RP)
+                       printf("RP ");
+               if (map->md_attr & EFI_MD_ATTR_XP)
+                       printf("XP ");
+               if (map->md_attr & EFI_MD_ATTR_RT)
+                       printf("RUNTIME");
+       }
+       return (0);
+}
+#endif
+
+#if defined(__amd64__) || defined(__i386__)
+static int
+S_bios_smap_xattr(size_t l2, void *p)
+{
+       struct bios_smap_xattr *smap, *end;
+
+       if (l2 % sizeof(*smap) != 0) {
+               warnx("S_bios_smap_xattr %zu is not a multiple of %zu", l2,
+                   sizeof(*smap));
+               return (1);
+       }
 
+       end = (struct bios_smap_xattr *)((char *)p + l2);
+       for (smap = p; smap < end; smap++)
+               printf("\nSMAP type=%02x, xattr=%02x, base=%016jx, len=%016jx",
+                   smap->type, smap->xattr, (uintmax_t)smap->base,
+                   (uintmax_t)smap->length);
        return (0);
 }
+#endif
 
 static int
 set_IK(const char *str, int *val)
@@ -655,7 +770,7 @@ show_var(int *oid, int nlen)
        size_t intlen;
        size_t j, len;
        u_int kind;
-       int (*func)(int, void *);
+       int (*func)(size_t, void *);
 
        /* Silence GCC. */
        umv = mv = intlen = 0;
@@ -793,6 +908,14 @@ show_var(int *oid, int nlen)
                        func = S_loadavg;
                else if (strcmp(fmt, "S,vmtotal") == 0)
                        func = S_vmtotal;
+#ifdef __amd64__
+               else if (strcmp(fmt, "S,efi_map_header") == 0)
+                       func = S_efi_map;
+#endif
+#if defined(__amd64__) || defined(__i386__)
+               else if (strcmp(fmt, "S,bios_smap_xattr") == 0)
+                       func = S_bios_smap_xattr;
+#endif
                else
                        func = NULL;
                if (func) {

Modified: stable/10/sys/amd64/amd64/machdep.c
==============================================================================
--- stable/10/sys/amd64/amd64/machdep.c Fri Oct 10 20:37:06 2014        
(r272912)
+++ stable/10/sys/amd64/amd64/machdep.c Fri Oct 10 20:47:23 2014        
(r272913)
@@ -2054,6 +2054,62 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpu
        pcpu->pc_acpi_id = 0xffffffff;
 }
 
+static int
+smap_sysctl_handler(SYSCTL_HANDLER_ARGS)
+{
+       struct bios_smap *smapbase;
+       struct bios_smap_xattr smap;
+       caddr_t kmdp;
+       uint32_t *smapattr;
+       int count, error, i;
+
+       /* Retrieve the system memory map from the loader. */
+       kmdp = preload_search_by_type("elf kernel");
+       if (kmdp == NULL)
+               kmdp = preload_search_by_type("elf64 kernel");
+       smapbase = (struct bios_smap *)preload_search_info(kmdp,
+           MODINFO_METADATA | MODINFOMD_SMAP);
+       if (smapbase == NULL)
+               return (0);
+       smapattr = (uint32_t *)preload_search_info(kmdp,
+           MODINFO_METADATA | MODINFOMD_SMAP_XATTR);
+       count = *((uint32_t *)smapbase - 1) / sizeof(*smapbase);
+       error = 0;
+       for (i = 0; i < count; i++) {
+               smap.base = smapbase[i].base;
+               smap.length = smapbase[i].length;
+               smap.type = smapbase[i].type;
+               if (smapattr != NULL)
+                       smap.xattr = smapattr[i];
+               else
+                       smap.xattr = 0;
+               error = SYSCTL_OUT(req, &smap, sizeof(smap));
+       }
+       return (error);
+}
+SYSCTL_PROC(_machdep, OID_AUTO, smap, CTLTYPE_OPAQUE|CTLFLAG_RD, NULL, 0,
+    smap_sysctl_handler, "S,bios_smap_xattr", "Raw BIOS SMAP data");
+
+static int
+efi_map_sysctl_handler(SYSCTL_HANDLER_ARGS)
+{
+       struct efi_map_header *efihdr;
+       caddr_t kmdp;
+       uint32_t efisize;
+
+       kmdp = preload_search_by_type("elf kernel");
+       if (kmdp == NULL)
+               kmdp = preload_search_by_type("elf64 kernel");
+       efihdr = (struct efi_map_header *)preload_search_info(kmdp,
+           MODINFO_METADATA | MODINFOMD_EFI_MAP);
+       if (efihdr == NULL)
+               return (0);
+       efisize = *((uint32_t *)efihdr - 1);
+       return (SYSCTL_OUT(req, efihdr, efisize));
+}
+SYSCTL_PROC(_machdep, OID_AUTO, efi_map, CTLTYPE_OPAQUE|CTLFLAG_RD, NULL, 0,
+    efi_map_sysctl_handler, "S,efi_map_header", "Raw EFI Memory Map");
+
 void
 spinlock_enter(void)
 {

Modified: stable/10/sys/amd64/include/pc/bios.h
==============================================================================
--- stable/10/sys/amd64/include/pc/bios.h       Fri Oct 10 20:37:06 2014        
(r272912)
+++ stable/10/sys/amd64/include/pc/bios.h       Fri Oct 10 20:47:23 2014        
(r272913)
@@ -51,6 +51,14 @@ struct bios_smap {
     u_int32_t  type;
 } __packed;
 
+/* Structure extended to include extended attribute field in ACPI 3.0. */
+struct bios_smap_xattr {
+    u_int64_t  base;
+    u_int64_t  length;
+    u_int32_t  type;
+    u_int32_t  xattr;
+} __packed;
+       
 /*
  * System Management BIOS
  */

Modified: stable/10/sys/i386/i386/machdep.c
==============================================================================
--- stable/10/sys/i386/i386/machdep.c   Fri Oct 10 20:37:06 2014        
(r272912)
+++ stable/10/sys/i386/i386/machdep.c   Fri Oct 10 20:47:23 2014        
(r272913)
@@ -3104,6 +3104,42 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpu
        pcpu->pc_acpi_id = 0xffffffff;
 }
 
+static int
+smap_sysctl_handler(SYSCTL_HANDLER_ARGS)
+{
+       struct bios_smap *smapbase;
+       struct bios_smap_xattr smap;
+       caddr_t kmdp;
+       uint32_t *smapattr;
+       int count, error, i;
+
+       /* Retrieve the system memory map from the loader. */
+       kmdp = preload_search_by_type("elf kernel");
+       if (kmdp == NULL)
+               kmdp = preload_search_by_type("elf32 kernel");
+       smapbase = (struct bios_smap *)preload_search_info(kmdp,
+           MODINFO_METADATA | MODINFOMD_SMAP);
+       if (smapbase == NULL)
+               return (0);
+       smapattr = (uint32_t *)preload_search_info(kmdp,
+           MODINFO_METADATA | MODINFOMD_SMAP_XATTR);
+       count = *((u_int32_t *)smapbase - 1) / sizeof(*smapbase);
+       error = 0;
+       for (i = 0; i < count; i++) {
+               smap.base = smapbase[i].base;
+               smap.length = smapbase[i].length;
+               smap.type = smapbase[i].type;
+               if (smapattr != NULL)
+                       smap.xattr = smapattr[i];
+               else
+                       smap.xattr = 0;
+               error = SYSCTL_OUT(req, &smap, sizeof(smap));
+       }
+       return (error);
+}
+SYSCTL_PROC(_machdep, OID_AUTO, smap, CTLTYPE_OPAQUE|CTLFLAG_RD, NULL, 0,
+    smap_sysctl_handler, "S,bios_smap_xattr", "Raw BIOS SMAP data");
+
 void
 spinlock_enter(void)
 {

Modified: stable/10/sys/i386/include/pc/bios.h
==============================================================================
--- stable/10/sys/i386/include/pc/bios.h        Fri Oct 10 20:37:06 2014        
(r272912)
+++ stable/10/sys/i386/include/pc/bios.h        Fri Oct 10 20:47:23 2014        
(r272913)
@@ -221,6 +221,14 @@ struct bios_smap {
     u_int32_t  type;
 } __packed;
 
+/* Structure extended to include extended attribute field in ACPI 3.0. */
+struct bios_smap_xattr {
+    u_int64_t  base;
+    u_int64_t  length;
+    u_int32_t  type;
+    u_int32_t  xattr;
+} __packed;
+
 /*
  * System Management BIOS
  */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to