svn commit: r290129 - in head: sys/dev/ioat tools/tools/ioat

Conrad E. Meyer cem at FreeBSD.org
Thu Oct 29 04:16:18 UTC 2015


Author: cem
Date: Thu Oct 29 04:16:16 2015
New Revision: 290129
URL: https://svnweb.freebsd.org/changeset/base/290129

Log:
  ioatcontrol(8): Add and document "raw" testing mode
  
  Allows DMA from/to arbitrary KVA or physical address.  /dev/ioat_test
  must be enabled by root and is only R/W root, so this is approximately
  as dangerous as /dev/mem and /dev/kmem.
  
  Sponsored by:	EMC / Isilon Storage Division

Modified:
  head/sys/dev/ioat/ioat_test.c
  head/sys/dev/ioat/ioat_test.h
  head/tools/tools/ioat/ioatcontrol.8
  head/tools/tools/ioat/ioatcontrol.c

Modified: head/sys/dev/ioat/ioat_test.c
==============================================================================
--- head/sys/dev/ioat/ioat_test.c	Thu Oct 29 03:28:28 2015	(r290128)
+++ head/sys/dev/ioat/ioat_test.c	Thu Oct 29 04:16:16 2015	(r290129)
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
 #include <machine/resource.h>
 #include <machine/stdarg.h>
 #include <vm/vm.h>
+#include <vm/vm_param.h>
 #include <vm/pmap.h>
 
 #include "ioat.h"
@@ -120,6 +121,18 @@ test_transaction *ioat_test_transaction_
 	return (tx);
 }
 
+static void
+dump_hex(void *p, size_t chunks)
+{
+	size_t i, j;
+
+	for (i = 0; i < chunks; i++) {
+		for (j = 0; j < 8; j++)
+			printf("%08x ", ((uint32_t *)p)[i * 8 + j]);
+		printf("\n");
+	}
+}
+
 static bool
 ioat_compare_ok(struct test_transaction *tx)
 {
@@ -140,9 +153,14 @@ ioat_compare_ok(struct test_transaction 
 				    != 0)
 					return (false);
 			}
-		} else if (test->testkind == IOAT_TEST_DMA)
+		} else if (test->testkind == IOAT_TEST_DMA) {
 			if (memcmp(src, dst, tx->length) != 0)
 				return (false);
+		} else if (test->testkind == IOAT_TEST_RAW_DMA) {
+			if (test->raw_write)
+				dst = test->raw_vtarget;
+			dump_hex(dst, tx->length / 32);
+		}
 	}
 	return (true);
 }
@@ -242,6 +260,13 @@ ioat_test_submit_1_tx(struct ioat_test *
 		src = vtophys((vm_offset_t)tx->buf[2*i]);
 		dest = vtophys((vm_offset_t)tx->buf[2*i+1]);
 
+		if (test->testkind == IOAT_TEST_RAW_DMA) {
+			if (test->raw_write)
+				dest = test->raw_target;
+			else
+				src = test->raw_target;
+		}
+
 		if (i == tx->depth - 1) {
 			cb = ioat_dma_test_callback;
 			flags = DMA_INT_EN;
@@ -250,7 +275,8 @@ ioat_test_submit_1_tx(struct ioat_test *
 			flags = 0;
 		}
 
-		if (test->testkind == IOAT_TEST_DMA)
+		if (test->testkind == IOAT_TEST_DMA ||
+		    test->testkind == IOAT_TEST_RAW_DMA)
 			desc = ioat_copy(dma, dest, src, tx->length, cb, tx,
 			    flags);
 		else if (test->testkind == IOAT_TEST_FILL) {
@@ -328,6 +354,16 @@ ioat_dma_test(void *arg)
 		goto out;
 	}
 
+	if (test->testkind == IOAT_TEST_RAW_DMA) {
+		if (test->raw_is_virtual) {
+			test->raw_vtarget = (void *)test->raw_target;
+			test->raw_target = vtophys(test->raw_vtarget);
+		} else {
+			test->raw_vtarget = pmap_mapdev(test->raw_target,
+			    test->buffer_size);
+		}
+	}
+
 	index = g_thread_index++;
 	TAILQ_INIT(&test->free_q);
 	TAILQ_INIT(&test->pend_q);
@@ -373,6 +409,9 @@ ioat_dma_test(void *arg)
 
 	ioat_test_release_memory(test);
 out:
+	if (test->testkind == IOAT_TEST_RAW_DMA && !test->raw_is_virtual)
+		pmap_unmapdev((vm_offset_t)test->raw_vtarget,
+		    test->buffer_size);
 	ioat_put_dmaengine(dmaengine);
 }
 

Modified: head/sys/dev/ioat/ioat_test.h
==============================================================================
--- head/sys/dev/ioat/ioat_test.h	Thu Oct 29 03:28:28 2015	(r290128)
+++ head/sys/dev/ioat/ioat_test.h	Thu Oct 29 04:16:16 2015	(r290129)
@@ -41,6 +41,7 @@ enum ioat_res {
 enum ioat_test_kind {
 	IOAT_TEST_FILL = 0,
 	IOAT_TEST_DMA,
+	IOAT_TEST_RAW_DMA,
 	IOAT_NUM_TESTKINDS
 };
 
@@ -66,6 +67,12 @@ struct ioat_test {
 	/* If true, check for miscompares after a copy. */
 	bool verify;
 
+	/* DMA directly to/from some memory address */
+	uint64_t raw_target;
+	void *raw_vtarget;
+	bool raw_write;
+	bool raw_is_virtual;
+
 	/* Internal usage -- not test inputs */
 	TAILQ_HEAD(, test_transaction) free_q;
 	TAILQ_HEAD(, test_transaction) pend_q;

Modified: head/tools/tools/ioat/ioatcontrol.8
==============================================================================
--- head/tools/tools/ioat/ioatcontrol.8	Thu Oct 29 03:28:28 2015	(r290128)
+++ head/tools/tools/ioat/ioatcontrol.8	Thu Oct 29 04:16:16 2015	(r290129)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd October 26, 2015
+.Dd October 28, 2015
 .Dt IOATCONTROL 8
 .Os
 .Sh NAME
@@ -40,6 +40,14 @@
 .Ar [ bufsize
 .Ar [ chain-len
 .Ar [ duration ] ] ]
+.Nm
+.Fl r
+.Op Fl v
+.Op Fl V
+.Op Fl w
+.Ar channel_number
+.Ar address
+.Ar [ bufsize ]
 .Sh DESCRIPTION
 .Nm
 allows one to issue some number of test operations to the
@@ -55,6 +63,29 @@ tests copy)
 Verify copies/fills for accuracy
 .El
 .Pp
+Alternatively one can use
+.Nm
+.Fl r
+to issue DMA to or from a specific
+.Ar address .
+The arguments in "raw" mode are:
+.Bl -tag -width Ds
+.It Fl v
+.Ar address
+is a kernel virtual address (by default,
+.Ar address
+is assumed to be a physical address)
+.It Fl V
+Dump the resulting hex to syslog
+.It Fl w
+Write to the specified
+.Ar address
+(by default,
+.Nm
+.Fl r
+reads)
+.El
+.Pp
 .Nm
 operates in one of two modes; if the
 .Ar duration
@@ -77,6 +108,7 @@ argument determines the size of buffers 
 .Fn ioat_copy
 invocation.
 The default is 256 KB.
+In raw mode, the default is 4 KB.
 .Pp
 The
 .Ar chain-len

Modified: head/tools/tools/ioat/ioatcontrol.c
==============================================================================
--- head/tools/tools/ioat/ioatcontrol.c	Thu Oct 29 03:28:28 2015	(r290128)
+++ head/tools/tools/ioat/ioatcontrol.c	Thu Oct 29 04:16:16 2015	(r290129)
@@ -50,24 +50,72 @@ usage(void)
 
 	printf("Usage: %s [-fV] <channel #> <txns> [<bufsize> "
 	    "[<chain-len> [duration]]]\n", getprogname());
+	printf("       %s -r [-vV] <channel #> <addr> [<bufsize>]\n",
+	    getprogname());
 	exit(EX_USAGE);
 }
 
+static void
+main_raw(struct ioat_test *t, int argc, char **argv)
+{
+	int fd;
+
+	/* Raw DMA defaults */
+	t->testkind = IOAT_TEST_RAW_DMA;
+	t->transactions = 1;
+	t->chain_depth = 1;
+	t->buffer_size = 4 * 1024;
+
+	t->raw_target = strtoull(argv[1], NULL, 0);
+	if (t->raw_target == 0) {
+		printf("Target shoudln't be NULL\n");
+		exit(EX_USAGE);
+	}
+
+	if (argc >= 3) {
+		t->buffer_size = atoi(argv[2]);
+		if (t->buffer_size == 0) {
+			printf("Buffer size must be greater than zero\n");
+			exit(EX_USAGE);
+		}
+	}
+
+	fd = open("/dev/ioat_test", O_RDWR);
+	if (fd < 0) {
+		printf("Cannot open /dev/ioat_test\n");
+		exit(EX_UNAVAILABLE);
+	}
+
+	(void)ioctl(fd, IOAT_DMATEST, t);
+	close(fd);
+
+	exit(prettyprint(t));
+}
+
 int
 main(int argc, char **argv)
 {
 	struct ioat_test t;
 	int fd, ch;
-	bool fflag;
+	bool fflag, rflag;
 
-	while ((ch = getopt(argc, argv, "fV")) != -1) {
+	while ((ch = getopt(argc, argv, "rfvVw")) != -1) {
 		switch (ch) {
 		case 'f':
 			fflag = true;
 			break;
+		case 'r':
+			rflag = true;
+			break;
+		case 'v':
+			t.raw_is_virtual = true;
+			break;
 		case 'V':
 			t.verify = true;
 			break;
+		case 'w':
+			t.raw_write = true;
+			break;
 		default:
 			usage();
 		}
@@ -78,6 +126,11 @@ main(int argc, char **argv)
 	if (argc < 2)
 		usage();
 
+	if (rflag && fflag) {
+		printf("Invalid: -r and -f\n");
+		usage();
+	}
+
 	/* Defaults for optional args */
 	t.buffer_size = 256 * 1024;
 	t.chain_depth = 2;
@@ -93,6 +146,11 @@ main(int argc, char **argv)
 		return (EX_USAGE);
 	}
 
+	if (rflag) {
+		main_raw(&t, argc, argv);
+		return (EX_OK);
+	}
+
 	t.transactions = atoi(argv[1]);
 
 	if (argc >= 3) {


More information about the svn-src-all mailing list