Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 10 Oct 2014 20:47:23 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r272913 - in stable/10: sbin/sysctl sys/amd64/amd64 sys/amd64/include/pc sys/i386/i386 sys/i386/include/pc
Message-ID:  <201410102047.s9AKlNFc089811@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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
  */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201410102047.s9AKlNFc089811>