[DTrace-devel] [PATCH 53/61] Add support for aggregation keys

eugene.loh at oracle.com eugene.loh at oracle.com
Fri Jul 8 14:45:37 UTC 2022


From: Eugene Loh <eugene.loh at oracle.com>

In the DTrace port to BPF, the initial support for aggregations
had the kernel maintaining aggregations in a per-CPU BPF map that
was statically allocated and managed.  Each aggregation had its
own region of per-CPU memory.  That is, run-time aggregation keys
were not supported.

To support aggregation keys, switch to a per-CPU BPF hash map.
The hash map key comprises:

*)  the aggregation variable ID

*)  the aggregation keys (if any)

*)  a 64-bit zero (to conform to dynamic variable "tuples")

On the producer (dt_cg.c) side:

*)  Use the existing dt_cg_arglist() to process the
    aggregation keys and produce the BPF hash map key.

*)  Call the new dt_get_agg() to get a pointer to the
    aggregation data in the BPF hash map.  The function call
    will create the element if needed, increment the data
    counter, and advance the pointer to the actual data.

*)  Push this pointer to the stack.

*)  Call the aggregation function: compute the value
    to be aggregated and pop the stack for the pointer
    to where the aggregation data is.

*)  Record the aggregation description (e.g., sizes of
    keys and data) if not already done.  This step is
    performed during code generation, though it does not
    generate code per se.

On the consumer (dt_aggregate.c) side, to snapshot aggregation data:

*)  Use dt_bpf_map_next_key() to walk the keys of the
    BPF hash map.

*)  For each hash map key, read the aggregation data on all CPUs.

*)  For each CPU with a nonzero data counter value, check
    dt_aggregate's user-space hash table for this key-specific
    aggregation.  Initialize or aggregate the user-space data
    accordingly.

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
 bpf/Build                                     |   1 +
 bpf/get_agg.c                                 |  42 +++
 include/dtrace/faults_defines.h               |   1 +
 libdtrace/dt_aggregate.c                      | 256 ++++++++----------
 libdtrace/dt_bpf.c                            |  34 ++-
 libdtrace/dt_cg.c                             | 129 +++++----
 libdtrace/dt_dctx.h                           |   1 -
 libdtrace/dt_error.c                          |   1 +
 libdtrace/dt_impl.h                           |   2 +-
 test/demo/intro/countdown-multiple.d          |   3 +-
 test/demo/intro/countdown-quant.d             |   3 +-
 test/demo/out/printa.d                        |   3 +-
 test/demo/script/syscall.d                    |   3 +-
 test/demo/user/libc.d                         |   3 +-
 test/stress/buffering/err.resize2.d           |   1 -
 .../actions/printa/err.D_PRINTA_AGGKEY.d      |   3 +-
 .../actions/printa/err.D_PRINTA_AGGPROTO.d    |   3 +-
 test/unittest/aggs/tst.count2.d               |   3 +-
 test/unittest/aggs/tst.count3.d               |   3 +-
 test/unittest/aggs/tst.denormalizeonly.d      |   3 +-
 test/unittest/aggs/tst.fmtnormalize.d         |   3 +-
 test/unittest/aggs/tst.forms.d                |   3 +-
 test/unittest/aggs/tst.keysort.d              |   3 +-
 test/unittest/aggs/tst.lquantize.d            |   3 +-
 test/unittest/aggs/tst.lquantrange.d          |   3 +-
 test/unittest/aggs/tst.lquantzero.d           |   4 +-
 test/unittest/aggs/tst.multiaggs1.d           |   3 +-
 test/unittest/aggs/tst.multinormalize.d       |   3 +-
 test/unittest/aggs/tst.neglquant.d            |   1 -
 test/unittest/aggs/tst.negorder.d             |   3 +-
 test/unittest/aggs/tst.negquant.d             |   1 -
 test/unittest/aggs/tst.order.d                |   3 +-
 test/unittest/aggs/tst.quantize.d             |   3 +-
 test/unittest/aggs/tst.quantmany.d            |   3 +-
 test/unittest/aggs/tst.quantzero.d            |   4 +-
 test/unittest/aggs/tst.signedkeyspos.d        |   3 +-
 test/unittest/aggs/tst.valsortkeypos.d        |   3 +-
 test/unittest/funcs/substr/tst.substrminate.d |   1 -
 test/unittest/grammar/tst.stmts.d             |   3 +-
 test/unittest/misc/tst.haslam.d               |   3 +-
 test/unittest/multiaggs/err.D_PRINTA_AGGKEY.d |   4 +-
 .../multiaggs/err.D_PRINTA_AGGPROTO.d         |   4 +-
 test/unittest/multiaggs/tst.many.d            |   3 +-
 test/unittest/multiaggs/tst.sort.d            |   3 +-
 test/unittest/multiaggs/tst.sortpos.d         |   3 +-
 test/unittest/multiaggs/tst.zero.d            |   3 +-
 test/unittest/multiaggs/tst.zero2.d           |   3 +-
 test/unittest/multiaggs/tst.zero3.d           |   3 +-
 test/unittest/printa/tst.dynwidth.d           |   3 +-
 test/unittest/printa/tst.tuple.d              |   3 +-
 50 files changed, 294 insertions(+), 292 deletions(-)
 create mode 100644 bpf/get_agg.c

diff --git a/bpf/Build b/bpf/Build
index b29f4b91..41de1bb8 100644
--- a/bpf/Build
+++ b/bpf/Build
@@ -25,6 +25,7 @@ bpf_dlib_SOURCES = \
 	agg_lqbin.c agg_qbin.c \
 	basename.S \
 	dirname.S \
+	get_agg.c \
 	get_bvar.c \
 	get_dvar.c \
 	index.S \
diff --git a/bpf/get_agg.c b/bpf/get_agg.c
new file mode 100644
index 00000000..dc3f8443
--- /dev/null
+++ b/bpf/get_agg.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ */
+#include <linux/bpf.h>
+#include <stdint.h>
+#include <bpf-helpers.h>
+
+#ifndef noinline
+# define noinline	__attribute__((noinline))
+#endif
+
+extern struct bpf_map_def aggs;
+
+noinline uint64_t *dt_get_agg(const char *key, const uint64_t *zer, uint64_t val)
+{
+	uint64_t	*valp;
+
+	/* try to look up the key */
+	valp = bpf_map_lookup_elem(&aggs, key);
+
+	/* if not found, create it */
+	if (valp == 0) {
+		/* start with all zeroes */
+		if (bpf_map_update_elem(&aggs, key, zer, BPF_ANY) < 0)
+			return 0;
+		valp = bpf_map_lookup_elem(&aggs, key);
+		if (valp == 0)
+			return 0;
+
+		/* val is nonzero only for min() and max() */
+		valp[1] = val;
+	}
+
+	/* increment the data counter */
+	valp[0] += 1;
+
+	/* advance past the data counter */
+	valp += 1;
+
+	return valp;
+}
diff --git a/include/dtrace/faults_defines.h b/include/dtrace/faults_defines.h
index 3cefb0ee..f671f341 100644
--- a/include/dtrace/faults_defines.h
+++ b/include/dtrace/faults_defines.h
@@ -33,6 +33,7 @@
 #define DTRACEFLT_TUPOFLOW		8	/* Tuple stack overflow */
 #define DTRACEFLT_BADSTACK		9	/* Bad stack */
 #define DTRACEFLT_BADSIZE		10	/* Bad size */
+#define DTRACEFLT_NOAGGS		11	/* Out of aggregations space */
 
 #define DTRACEFLT_LIBRARY		1000	/* Library-level fault */
 
diff --git a/libdtrace/dt_aggregate.c b/libdtrace/dt_aggregate.c
index 10df98da..bfb32b02 100644
--- a/libdtrace/dt_aggregate.c
+++ b/libdtrace/dt_aggregate.c
@@ -409,13 +409,6 @@ dt_aggregate_aggid(dt_ahashent_t *ent)
 typedef void (*agg_cpu_f)(dt_ident_t *aid,
     int64_t *dst, int64_t *src, uint_t realsz);
 
-typedef struct dt_snapstate {
-	dtrace_hdl_t	*dtp;
-	processorid_t	cpu;
-	char		*buf;
-	dt_aggregate_t	*agp;
-} dt_snapstate_t;
-
 static void
 dt_agg_one_agg(uint_t act, int64_t *dst, int64_t *src, uint_t realsz)
 {
@@ -440,29 +433,27 @@ dt_agg_one_agg(uint_t act, int64_t *dst, int64_t *src, uint_t realsz)
 }
 
 static int
-dt_aggregate_snap_one(dt_idhash_t *dhp, dt_ident_t *aid, dt_snapstate_t *st)
+dt_aggregate_snap_one(dtrace_hdl_t *dtp, dt_ident_t *aid, char *key, int64_t *src, int cpu)
 {
-	dt_ahash_t		*agh = &st->agp->dtat_hash;
+	dt_ahash_t		*agh = &dtp->dt_aggregate.dtat_hash;
 	dt_ahashent_t		*h;
 	dtrace_aggdesc_t	*agg;
 	dtrace_aggdata_t	*agd;
 	dtrace_recdesc_t	*rec;
-	uint64_t		hval = aid->di_id;
+	uint64_t		hval = aid->di_id;  /* FIXME: need better hash value */
 	size_t			ndx = hval % agh->dtah_size;
 	int			rval;
 	uint_t			i, datasz;
-	int64_t			*src;
-	int			nrecs;
+	int			irec, nrecs;
+	caddr_t			data;
+	size_t			roffs;
 
-	rval = dt_aggid_lookup(st->dtp, aid->di_id, &agg);
+	rval = dt_aggid_lookup(dtp, aid->di_id, &agg);
 	if (rval != 0)
 		return rval;
 
 	nrecs = agg->dtagd_nrecs;
 
-	/* point to the data counter */
-	src = (int64_t *)(st->buf + aid->di_offset);
-
 	/* skip it if data counter is 0 */
 	if (*src == 0)
 		return 0;
@@ -478,76 +469,95 @@ dt_aggregate_snap_one(dt_idhash_t *dhp, dt_ident_t *aid, dt_snapstate_t *st)
 
 		if (h->dtahe_hval != hval || h->dtahe_size != agg->dtagd_size)
 			continue;
+		agd = &h->dtahe_data;
+		data = agd->dtada_data;
+
+		/* compare the non-data records */
+		for (irec = 0; irec < nrecs - 1; irec++) {
+			rec = &agg->dtagd_recs[irec];
+			roffs = rec->dtrd_offset;
+
+			if (memcmp(&key[roffs], &data[roffs], rec->dtrd_size))
+				goto hashnext;
+		}
 
 		/* Entry found - process the data. */
-		agd = &h->dtahe_data;
 		act = ((dt_ident_t *)aid->di_iarg)->di_id;
-
 		rec = &agg->dtagd_recs[nrecs - 1];
-		dt_agg_one_agg(act, (int64_t *)(agd->dtada_data + rec->dtrd_offset),
-			       src, datasz);
+		roffs = rec->dtrd_offset;
+		dt_agg_one_agg(act, (int64_t *)&data[roffs], src, datasz);
 
 		/* If we keep per-CPU data - process that as well. */
 		if (agd->dtada_percpu != NULL)
-			dt_agg_one_agg(act, (int64_t *)agd->dtada_percpu[st->cpu],
+			dt_agg_one_agg(act, (int64_t *)agd->dtada_percpu[cpu],
 			    src, datasz);
 
 		return 0;
+
+hashnext:
+		continue;
 	}
 
 	/* add it to the hash table */
-	h = dt_zalloc(st->dtp, sizeof(dt_ahashent_t));
+	h = dt_zalloc(dtp, sizeof(dt_ahashent_t));
 	if (h == NULL)
-		return dt_set_errno(st->dtp, EDT_NOMEM);
+		return dt_set_errno(dtp, EDT_NOMEM);
 
 	agd = &h->dtahe_data;
-	agd->dtada_data = dt_alloc(st->dtp, agg->dtagd_size);
-	if (agd->dtada_data == NULL) {
-		dt_free(st->dtp, h);
-		return dt_set_errno(st->dtp, EDT_NOMEM);
+	data = dt_alloc(dtp, agg->dtagd_size);
+	if (data == NULL) {
+		dt_free(dtp, h);
+		return dt_set_errno(dtp, EDT_NOMEM);
 	}
+	agd->dtada_data = data;
 
 	/* initialize the variable ID */
-	*((long *)agd->dtada_data) = agg->dtagd_varid;
+	*((long *)data) = agg->dtagd_varid;
 
-	/* FIXME: initialize the keys */
+	/* initialize the non-data records */
+	for (irec = 0; irec < nrecs - 1; irec++) {
+		rec = &agg->dtagd_recs[irec];
+		roffs = rec->dtrd_offset;
+		memcpy(&data[roffs], &key[roffs], rec->dtrd_size);
+	}
 
 	/* copy the data */
 	rec = &agg->dtagd_recs[nrecs - 1];
-	memcpy(agd->dtada_data + rec->dtrd_offset, src, datasz);
+	roffs = rec->dtrd_offset;
+	memcpy(&data[roffs], src, datasz);
 
 	agd->dtada_size = agg->dtagd_size;
 	agd->dtada_desc = agg;
-	agd->dtada_hdl = st->dtp;
+	agd->dtada_hdl = dtp;
 
 	h->dtahe_hval = hval;
 	h->dtahe_size = agg->dtagd_size;
 
-	if (st->agp->dtat_flags & DTRACE_A_PERCPU) {
-		char	**percpu = dt_calloc(st->dtp,
-					     st->dtp->dt_conf.max_cpuid + 1,
+	if (dtp->dt_aggregate.dtat_flags & DTRACE_A_PERCPU) {
+		char	**percpu = dt_calloc(dtp,
+					     dtp->dt_conf.max_cpuid + 1,
 					     sizeof(char *));
 
 		if (percpu == NULL) {
-			dt_free(st->dtp, agd->dtada_data);
-			dt_free(st->dtp, h);
+			dt_free(dtp, data);
+			dt_free(dtp, h);
 
-			dt_set_errno(st->dtp, EDT_NOMEM);
+			dt_set_errno(dtp, EDT_NOMEM);
 		}
 
-		for (i = 0; i <= st->dtp->dt_conf.max_cpuid; i++) {
-			percpu[i] = dt_zalloc(st->dtp, datasz);
+		for (i = 0; i <= dtp->dt_conf.max_cpuid; i++) {
+			percpu[i] = dt_zalloc(dtp, datasz);
 			if (percpu[i] == NULL) {
 				while (--i >= 0)
-					dt_free(st->dtp, percpu[i]);
-				dt_free(st->dtp, agd->dtada_data);
-				dt_free(st->dtp, h);
+					dt_free(dtp, percpu[i]);
+				dt_free(dtp, data);
+				dt_free(dtp, h);
 
-				dt_set_errno(st->dtp, EDT_NOMEM);
+				dt_set_errno(dtp, EDT_NOMEM);
 			}
 		}
 
-		memcpy(percpu[st->cpu], src, datasz);
+		memcpy(percpu[cpu], src, datasz);
 		agd->dtada_percpu = percpu;
 	}
 
@@ -567,22 +577,6 @@ dt_aggregate_snap_one(dt_idhash_t *dhp, dt_ident_t *aid, dt_snapstate_t *st)
 	return 0;
 }
 
-static int
-dt_aggregate_snap_cpu(dtrace_hdl_t *dtp, processorid_t cpu)
-{
-	dt_aggregate_t	*agp = &dtp->dt_aggregate;
-	char		*buf = agp->dtat_cpu_buf[cpu];
-	dt_snapstate_t	st;
-
-	st.dtp = dtp;
-	st.cpu = cpu;
-	st.buf = buf;
-	st.agp = agp;
-
-	return dt_idhash_iter(dtp->dt_aggs,
-			      (dt_idhash_f *)dt_aggregate_snap_one, &st);
-}
-
 /*
  * Retrieve all aggregation data for the enabled CPUs and aggregate it.
  */
@@ -590,28 +584,62 @@ int
 dtrace_aggregate_snap(dtrace_hdl_t *dtp)
 {
 	dt_aggregate_t	*agp = &dtp->dt_aggregate;
-	uint32_t	key = 0;
-	int		i, rval;
+	int		i, fd = dtp->dt_aggmap_fd;
+	uint_t		keysiz = dtp->dt_maxtuplesize;
+	uint_t		valsiz = dtp->dt_aggsiz;
+	char		*buf = agp->dtat_buf;
+	char		*key = buf;
+	char		*nxt = agp->dtat_nextkey;
+	int64_t		*val = (int64_t *)(buf + keysiz);
+	uint32_t	*varID_ptr = (uint32_t *)key;
+
+	if (buf == NULL)
+		return 0;
+
+	dtrace_aggregate_clear(dtp);
 
 	/*
-	 * If we do not have a buffer initialized, we will not be processing
-	 * aggregations, so there is nothing to be done here.
+	 * To start the iteration over BPF hash map keys,
+	 * we need a key that will not be recognized.
+	 * Just set its varID to an unrecognized value.
 	 */
-	if (agp->dtat_cpu_buf == NULL)
-		return 0;
+	*varID_ptr = DTRACE_AGGIDNONE;
+
+	/* now iterate over BPF hash map keys */
+	while (dt_bpf_map_next_key(fd, key, nxt) == 0) {
+		uint32_t varID;
+		dt_ident_t *aid;
+
+		/* get next value */
+		memcpy(key, nxt, keysiz);
+		if (dt_bpf_map_lookup(fd, key, val) == -1) {
+			printf("FAIL to look up\n");
+			return 1;
+		}
 
-	dtrace_aggregate_clear(dtp);
+		/* read the key's var ID */
+		varID = *varID_ptr;
 
-	rval = dt_bpf_map_lookup(dtp->dt_aggmap_fd, &key, agp->dtat_buf);
-	if (rval != 0)
-		return dt_set_errno(dtp, -rval);
+		/* get the aid */
+		aid = dt_idhash_lookup(dtp->dt_aggs, dtp->dt_adesc[varID]->dtagd_name);
 
-	for (i = 0; i < dtp->dt_conf.num_online_cpus; i++) {
-		rval = dt_aggregate_snap_cpu(dtp, dtp->dt_conf.cpus[i].cpu_id);
-		if (rval != 0)
-			return rval;
+		/* look for on-line CPUs */
+		for (i = 0; i < dtp->dt_conf.num_online_cpus; i++) {
+			int cpu = dtp->dt_conf.cpus[i].cpu_id;
+			int64_t *data = (int64_t*) (((char *)val) + cpu * valsiz);
+
+			/* look for non-zero data counters */
+			if (*data == 0)
+				continue;
+
+			/* process it */
+			dt_aggregate_snap_one(dtp, aid, key, data, cpu);
+		}
 	}
 
+	/* check for normal end of iteration */
+	assert(errno == ENOENT);
+
 	return 0;
 }
 
@@ -974,49 +1002,14 @@ dt_aggregate_bundlecmp(const void *lhs, const void *rhs)
 	}
 }
 
-/*
- * Callback for initializing the min() and max() aggregation functions.
- * The minimum 64 bit value is set for max() and the maximum 64 bit value is
- * set for min(), so that any other value fed to the functions will register
- * properly.
- *
- * The data counter of the first aggregation is used as a flag to
- * indicate whether an initial value was stored for any aggregation.
- */
-static int
-init_minmax(dt_idhash_t *dhp, dt_ident_t *aid, char *buf)
-{
-	dt_ident_t *fid = aid->di_iarg;
-	int64_t *ptr;
-	int64_t value;
-
-	assert(aid->di_kind == DT_IDENT_AGG);
-	assert(fid);
-
-	if (fid->di_id == DT_AGG_MIN)
-		value = INT64_MAX;
-	else if (fid->di_id == DT_AGG_MAX)
-		value = INT64_MIN;
-	else
-		return 0;
-
-	/* Indicate that we are setting initial values. */
-	*(int64_t *)buf = 1;
-
-	/* skip ptr[0], it is the data counter */
-	ptr = (int64_t *)(buf + aid->di_offset);
-	ptr[1] = value;
-
-	return 0;
-}
-
 int
 dt_aggregate_go(dtrace_hdl_t *dtp)
 {
 	dt_aggregate_t	*agp = &dtp->dt_aggregate;
 	dt_ahash_t	*agh = &agp->dtat_hash;
-	int		aggsz, i;
-	uint32_t	key = 0;
+	int		aggsz;
+	uint_t		keysiz = dtp->dt_maxtuplesize;
+	uint_t		valsiz = dtp->dt_aggsiz;
 
 	/* If there are no aggregations there is nothing to do. */
 	aggsz = dt_idhash_datasize(dtp->dt_aggs);
@@ -1025,53 +1018,27 @@ dt_aggregate_go(dtrace_hdl_t *dtp)
 
 	/*
 	 * Allocate a buffer to hold the aggregation data for all possible
-	 * CPUs, and initialize the per-CPU data pointers for CPUs that are
-	 * currently enabled.
+	 * CPUs.  Allocate a buffer to hold the next key in the BPF map.
 	 */
-	agp->dtat_buf = dt_zalloc(dtp, dtp->dt_conf.num_possible_cpus * aggsz);
+	agp->dtat_buf = dt_zalloc(dtp, keysiz + dtp->dt_conf.num_possible_cpus * valsiz);
 	if (agp->dtat_buf == NULL)
 		return dt_set_errno(dtp, EDT_NOMEM);
-
-	agp->dtat_cpu_buf = dt_calloc(dtp, dtp->dt_conf.max_cpuid + 1,
-				      sizeof(char *));
-	if (agp->dtat_cpu_buf == NULL) {
+	agp->dtat_nextkey = dt_zalloc(dtp, keysiz);
+	if (agp->dtat_nextkey == NULL) {
 		dt_free(dtp, agp->dtat_buf);
 		return dt_set_errno(dtp, EDT_NOMEM);
 	}
 
-	for (i = 0; i < dtp->dt_conf.num_online_cpus; i++) {
-		int	cpu = dtp->dt_conf.cpus[i].cpu_id;
-
-		agp->dtat_cpu_buf[cpu] = agp->dtat_buf + cpu * aggsz;
-	}
-
 	/* Create the aggregation hash. */
 	agh->dtah_size = DTRACE_AHASHSIZE;
 	agh->dtah_hash = dt_zalloc(dtp,
 				   agh->dtah_size * sizeof(dt_ahashent_t *));
 	if (agh->dtah_hash == NULL) {
-		dt_free(dtp, agp->dtat_cpu_buf);
+		dt_free(dtp, agp->dtat_nextkey);
 		dt_free(dtp, agp->dtat_buf);
 		return dt_set_errno(dtp, EDT_NOMEM);
 	}
 
-	/* Initialize the starting values for min() and max() aggregations.  */
-	dt_idhash_iter(dtp->dt_aggs, (dt_idhash_f *) init_minmax,
-		       agp->dtat_buf);
-	if (*(int64_t *)agp->dtat_buf == 0)
-		return 0;
-	*(int64_t *)agp->dtat_buf = 0;  /* clear the flag */
-	for (i = 0; i < dtp->dt_conf.num_online_cpus; i++) {
-		int	cpu = dtp->dt_conf.cpus[i].cpu_id;
-
-		/* Data for CPU 0 was populated, so skip it. */
-		if (cpu == 0)
-			continue;
-
-		memcpy(agp->dtat_cpu_buf[cpu], agp->dtat_buf, aggsz);
-	}
-	dt_bpf_map_update(dtp->dt_aggmap_fd, &key, agp->dtat_buf);
-
 	return 0;
 }
 
@@ -1845,7 +1812,6 @@ dt_aggregate_destroy(dtrace_hdl_t *dtp)
 		hash->dtah_all = NULL;
 		hash->dtah_size = 0;
 	}
-
-	dt_free(dtp, agp->dtat_cpu_buf);
+	dt_free(dtp, agp->dtat_nextkey);
 	dt_free(dtp, agp->dtat_buf);
 }
diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index 8d7f38f2..107b65a6 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -194,9 +194,7 @@ populate_probes_map(dtrace_hdl_t *dtp, int fd)
  * - state:	DTrace session state, used to communicate state between BPF
  *		programs and userspace.  The content of the map is defined in
  *		dt_state.h.
- * - aggs:	Aggregation data buffer map, associated with each CPU.  The
- *		map is implemented as a global per-CPU map with a singleton
- *		element (key 0).
+ * - aggs:	Aggregation data buffer map, a per-CPU hash.
  * - specs:	Map associating speculation IDs with a dt_bpf_specs_t struct
  *		giving the number of buffers speculated into for this
  *		speculation, and the number drained by userspace.
@@ -271,11 +269,18 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
 	/*
 	 * Check if there is aggregation data to be collected.
 	 */
-	sz = dt_idhash_datasize(dtp->dt_aggs);
-	if (sz > 0) {
+	if (dtp->dt_aggsiz > 0) {
+		/* FIXME: need a better model for BPF map size */
+		size_t nelems = dtp->dt_options[DTRACEOPT_AGGSIZE]
+				/ (dtp->dt_conf.max_cpuid + 1)
+				/ (dtp->dt_maxtuplesize + dtp->dt_aggsiz);
+
+		/* create the map */
 		dtp->dt_aggmap_fd = create_gmap(dtp, "aggs",
-						BPF_MAP_TYPE_PERCPU_ARRAY,
-						sizeof(uint32_t), sz, 1);
+						BPF_MAP_TYPE_PERCPU_HASH,
+						dtp->dt_maxtuplesize,
+						dtp->dt_aggsiz,
+						nelems);
 		if (dtp->dt_aggmap_fd == -1)
 			return -1;	/* dt_errno is set for us */
 	}
@@ -367,6 +372,8 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
 	/* figure out how big the region of zeroes should be */
 	if (dtp->dt_zerosize < dtp->dt_maxtuplesize)
 		dtp->dt_zerosize = dtp->dt_maxtuplesize;
+	if (dtp->dt_zerosize < dtp->dt_aggsiz)
+		dtp->dt_zerosize = dtp->dt_aggsiz;
 
 	/* global variables, including a region of zeroes */
 	dtp->dt_zerooffset = P2ROUNDUP(dt_idhash_datasize(dtp->dt_globals), 8);
@@ -403,7 +410,18 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
 		dt_bpf_map_update(fd, &key, &dflt);
 	}
 
-	if (dtp->dt_maxtuplesize > 0 &&
+	/*
+	 * Note:
+	 *
+	 * - dt_maxtuplesize>0 can mean we are using the tuples map
+	 *   *OR* that we are using aggregations
+	 *
+	 * - dvarc!=0 can mean we are using the tuples map
+	 *   *OR* that we are using keyless dvars (e.g., "self->x")
+	 *
+	 * So check both conditions before creating a "tuples" map.
+	 */
+	if (dtp->dt_maxtuplesize > 0 && dvarc != 0 &&
 	    create_gmap(dtp, "tuples", BPF_MAP_TYPE_HASH,
 			dtp->dt_maxtuplesize, sizeof(uint64_t), dvarc) == -1)
 		return -1;		/* dt_errno is set for us */
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 5a74f5ad..257af074 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -206,8 +206,6 @@ dt_cg_tramp_prologue_act(dt_pcb_t *pcb, dt_activity_t act)
 	DT_CG_STORE_MAP_PTR("strtab", DCTX_STRTAB);
 	if (dtp->dt_options[DTRACEOPT_SCRATCHSIZE] > 0)
 		DT_CG_STORE_MAP_PTR("scratchmem", DCTX_SCRATCHMEM);
-	if (dt_idhash_datasize(dtp->dt_aggs) > 0)
-		DT_CG_STORE_MAP_PTR("aggs", DCTX_AGG);
 	if (dt_idhash_datasize(dtp->dt_globals) > 0 || dtp->dt_zerosize > 0)
 		DT_CG_STORE_MAP_PTR("gvars", DCTX_GVARS);
 	if (dtp->dt_maxlvaralloc > 0)
@@ -2623,9 +2621,31 @@ dt_cg_push_stack(dt_irlist_t *dlp, dt_regset_t *drp, int reg)
 	dt_regset_free(drp, tmp);
 }
 
+static int
+dt_cg_pop_stack(dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	int reg;
+	int tmp;
+
+	if ((reg = dt_regset_alloc(drp)) == -1)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+	if ((tmp = dt_regset_alloc(drp)) == -1)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+	emit(dlp, BPF_LOAD(BPF_DW, tmp, BPF_REG_FP, DT_STK_SP));
+	emit(dlp, BPF_ALU64_IMM(BPF_ADD, tmp, DT_STK_SLOT_SZ));
+	emit(dlp, BPF_LOAD(BPF_DW, reg, tmp, 0));
+	emit(dlp, BPF_STORE(BPF_DW, BPF_REG_FP, DT_STK_SP, tmp));
+	dt_regset_free(drp, tmp);
+
+	return reg;
+}
+
 /*
  * Generate code to push the specified argument list on to the tuple stack.
- * We use this routine for handling the index tuple for associative arrays.
+ * We use this routine for handling the index tuple for associative arrays
+ * as well as keys for aggregations.
+ *
  * We must first generate code for all subexpressions because any subexpression
  * could itself require the use of the tuple assembly area and we only provide
  * one.
@@ -5449,60 +5469,13 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 					     sizeof(uint64_t) + (sz)); \
 	} while (0)
 
-/*
- * Return a register that holds a pointer to the aggregation data to be
- * updated.
- *
- * We update the data counter (first value in the aggregation) to
- * signal that the aggregation has data.  The location of data for the
- * given aggregation is stored in the register returned from this function.
- */
-static int
-dt_cg_agg_buf_prepare(dt_ident_t *aid, int size, dt_irlist_t *dlp,
-		      dt_regset_t *drp)
-{
-	int		rptr;
-
-	TRACE_REGSET("            Prep: Begin");
-
-	dt_regset_xalloc(drp, BPF_REG_0);
-	rptr = dt_regset_alloc(drp);
-	assert(rptr != -1);
-
-	/*
-	 *	ptr = dctx->agg;	// lddw %rptr, [%fp + DT_STK_DCTX]
-	 *				// lddw %rptr, [%rptr + DCTX_AGG]
-	 */
-	emit(dlp, BPF_LOAD(BPF_DW, rptr, BPF_REG_FP, DT_STK_DCTX));
-	emit(dlp, BPF_LOAD(BPF_DW, rptr, rptr, DCTX_AGG));
-
-	/*
-	 *	*((uint64_t *)(ptr + aid->di_offset))++;
-	 *				// mov %r0, 1
-	 *				// xadd [%rptr + aid->di_offset], %r0
-	 *      ptr += aid->di_offset + sizeof(uint64_t);
-	 *				// add %rptr, aid->di_offset +
-	 *				//	      sizeof(uint64_t)
-	 */
-	emit(dlp, BPF_MOV_IMM(BPF_REG_0, 1));
-	emit(dlp, BPF_XADD_REG(BPF_DW, rptr, aid->di_offset, BPF_REG_0));
-	emit(dlp, BPF_ALU64_IMM(BPF_ADD, rptr, aid->di_offset + sizeof(uint64_t)));
-
-	dt_regset_free(drp, BPF_REG_0);
-
-	TRACE_REGSET("            Prep: End  ");
-
-	return rptr;
-}
-
 #define DT_CG_AGG_IMPL(aid, sz, dlp, drp, f, ...) \
 	do {								\
 		int	dreg;						\
 									\
 		TRACE_REGSET("        Upd: Begin ");			\
 									\
-		dreg = dt_cg_agg_buf_prepare((aid), (sz), (dlp), (drp));\
-									\
+		dreg = dt_cg_pop_stack((dlp), (drp));			\
 		(f)((dlp), (drp), dreg, ## __VA_ARGS__);		\
 		dt_regset_free((drp), dreg);				\
 									\
@@ -6524,8 +6497,11 @@ dt_cg_agg(dt_pcb_t *pcb, dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 	dtrace_hdl_t	*dtp = pcb->pcb_hdl;
 	dt_ident_t	*aid, *fid;
 	dt_cg_aggfunc_f	*aggfp;
-	int		nrecs, off;
+	int		nrecs, off, tup;
 	dt_node_t	*d;
+	dt_ident_t	*zero_off = dt_dlib_get_var(dtp, "ZERO_OFF");
+	dt_ident_t	*idp;
+	uint_t		Lgot_agg;
 
 	/*
 	 * If the aggregation has no aggregating function applied to it, then
@@ -6543,17 +6519,56 @@ dt_cg_agg(dt_pcb_t *pcb, dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 		dnerror(dnp->dn_aggfun, D_AGG_SCALAR, "%s( ) argument #1 must "
 			"be of scalar type\n", fid->di_name);
 
-	/* FIXME */
-	if (dnp->dn_aggtup != NULL)
-		dnerror(dnp->dn_aggtup, D_ARR_BADREF, "indexing is not "
-			"supported yet: @%s\n", dnp->dn_ident->di_name);
-
 	assert(fid->di_id >= DT_AGG_BASE && fid->di_id < DT_AGG_HIGHEST);
 
 	dt_cg_clsflags(pcb, DTRACEACT_AGGREGATION, dnp);
 	aggfp = _dt_cg_agg[DT_AGG_IDX(fid->di_id)];
 	assert(aggfp != NULL);
 
+	/* generate BPF code for keys (if any) */
+	tup = dt_cg_arglist(aid, dnp->dn_aggtup, dlp, drp);
+
+	/* insert the aggregation var ID in the lead, 4-byte slot */
+	emit(dlp,  BPF_STORE_IMM(BPF_W, tup, 0, aid->di_id));
+
+	/* call dt_get_agg() to get the agg data pointer */
+
+	if (dt_regset_xalloc_args(drp) == -1)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+	emit(dlp,  BPF_MOV_REG(BPF_REG_1, tup));
+	dt_regset_free(drp, tup);
+	emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_2, BPF_REG_FP, DT_STK_DCTX));
+	emit(dlp,  BPF_LOAD(BPF_DW, BPF_REG_2, BPF_REG_2, DCTX_GVARS));
+	emite(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -1), zero_off);
+
+	switch (fid->di_id) {
+	case DT_AGG_MAX:
+		dt_cg_setx(dlp, BPF_REG_3, INT64_MIN);
+		break;
+	case DT_AGG_MIN:
+		dt_cg_setx(dlp, BPF_REG_3, INT64_MAX);
+		break;
+	default:
+		emit(dlp, BPF_MOV_IMM(BPF_REG_3, 0));
+		break;
+	}
+
+	dt_regset_xalloc(drp, BPF_REG_0);
+	idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_get_agg");
+	assert(idp != NULL);
+	emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
+	dt_regset_free_args(drp);
+	Lgot_agg = dt_irlist_label(dlp);
+	emit(dlp,  BPF_BRANCH_IMM(BPF_JNE, BPF_REG_0, 0, Lgot_agg));
+	dt_cg_probe_error(yypcb, DTRACEFLT_NOAGGS, DT_ISIMM, 0);
+	emitl(dlp, Lgot_agg,
+		   BPF_NOP());
+
+	/* push agg data pointer onto the stack */
+
+	dt_cg_push_stack(dlp, drp, BPF_REG_0);
+
+	/* evaluate aggregation */
 	(*aggfp)(pcb, aid, dnp, dlp, drp);
 
 	/* add this agg id if we are seeing it for the first time */
diff --git a/libdtrace/dt_dctx.h b/libdtrace/dt_dctx.h
index c93fff2b..fe084d2e 100644
--- a/libdtrace/dt_dctx.h
+++ b/libdtrace/dt_dctx.h
@@ -66,7 +66,6 @@ typedef struct dt_dctx {
 #define DCTX_MEM	offsetof(dt_dctx_t, mem)
 #define DCTX_SCRATCHMEM	offsetof(dt_dctx_t, scratchmem)
 #define DCTX_STRTAB	offsetof(dt_dctx_t, strtab)
-#define DCTX_AGG	offsetof(dt_dctx_t, agg)
 #define DCTX_GVARS	offsetof(dt_dctx_t, gvars)
 #define DCTX_LVARS	offsetof(dt_dctx_t, lvars)
 
diff --git a/libdtrace/dt_error.c b/libdtrace/dt_error.c
index 576b1199..b9e19014 100644
--- a/libdtrace/dt_error.c
+++ b/libdtrace/dt_error.c
@@ -207,6 +207,7 @@ dtrace_faultstr(dtrace_hdl_t *dtp, int fault)
 		{ DTRACEFLT_TUPOFLOW,	"tuple stack overflow" },
 		{ DTRACEFLT_BADSTACK,	"bad stack" },
 		{ DTRACEFLT_BADSIZE,	"invalid size" },
+		{ DTRACEFLT_NOAGGS,	"out of aggregations space" },
 		{ DTRACEFLT_LIBRARY,	"library-level fault" },
 		{ 0,			NULL }
 	};
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index be2b0121..85e2b878 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -206,7 +206,7 @@ typedef struct dt_tstring {
 } dt_tstring_t;
 
 typedef struct dt_aggregate {
-	char **dtat_cpu_buf;		/* per-CPU agg snapshot buffers */
+	char *dtat_nextkey;		/* buffer for next key */
 	char *dtat_buf;			/* aggregation snapshot buffer */
 	int dtat_flags;			/* aggregate flags */
 	dt_ahash_t dtat_hash;		/* aggregate hash table */
diff --git a/test/demo/intro/countdown-multiple.d b/test/demo/intro/countdown-multiple.d
index 03db541e..e98f41ee 100644
--- a/test/demo/intro/countdown-multiple.d
+++ b/test/demo/intro/countdown-multiple.d
@@ -1,11 +1,10 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
 
-/* @@xfail: dtv2 */
 /* @@trigger: none */
 
 /* @@tags: unstable */
diff --git a/test/demo/intro/countdown-quant.d b/test/demo/intro/countdown-quant.d
index 2ab29b78..6a4b92a6 100644
--- a/test/demo/intro/countdown-quant.d
+++ b/test/demo/intro/countdown-quant.d
@@ -1,11 +1,10 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
 
-/* @@xfail: dtv2 */
 /* @@trigger: none */
 
 dtrace:::BEGIN
diff --git a/test/demo/out/printa.d b/test/demo/out/printa.d
index 28ba2175..ae63cfc6 100644
--- a/test/demo/out/printa.d
+++ b/test/demo/out/printa.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 profile:::tick-997
 {
diff --git a/test/demo/script/syscall.d b/test/demo/script/syscall.d
index 69091aa5..0b73d45b 100644
--- a/test/demo/script/syscall.d
+++ b/test/demo/script/syscall.d
@@ -1,11 +1,10 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
 
-/* @@xfail: dtv2 */
 /* @@runtest-opts: -c /bin/true */
 /* @@trigger: none */
 
diff --git a/test/demo/user/libc.d b/test/demo/user/libc.d
index 99e7a51c..dad274b8 100644
--- a/test/demo/user/libc.d
+++ b/test/demo/user/libc.d
@@ -1,11 +1,10 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
 
-/* @@xfail: dtv2 */
 /* @@runtest-opts: -c /usr/bin/date */
 
 pid$target:libc.so::entry
diff --git a/test/stress/buffering/err.resize2.d b/test/stress/buffering/err.resize2.d
index 277ec6cc..9b408958 100644
--- a/test/stress/buffering/err.resize2.d
+++ b/test/stress/buffering/err.resize2.d
@@ -5,7 +5,6 @@
  * http://oss.oracle.com/licenses/upl.
  */
 /* @@timeout: 500 */
-/* @@xfail: need support for aggregation keys */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/actions/printa/err.D_PRINTA_AGGKEY.d b/test/unittest/actions/printa/err.D_PRINTA_AGGKEY.d
index c6014316..23859ebe 100644
--- a/test/unittest/actions/printa/err.D_PRINTA_AGGKEY.d
+++ b/test/unittest/actions/printa/err.D_PRINTA_AGGKEY.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 /*
  * ASSERTION: printa() requires aggregation arguments to have matching key
  *	signatures
diff --git a/test/unittest/actions/printa/err.D_PRINTA_AGGPROTO.d b/test/unittest/actions/printa/err.D_PRINTA_AGGPROTO.d
index d327a9c5..4be6fb45 100644
--- a/test/unittest/actions/printa/err.D_PRINTA_AGGPROTO.d
+++ b/test/unittest/actions/printa/err.D_PRINTA_AGGPROTO.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 /*
  * ASSERTION: printa() requires aggregation arguments to have matching key
  *	signatures (matching key component types)
diff --git a/test/unittest/aggs/tst.count2.d b/test/unittest/aggs/tst.count2.d
index b03c5cc2..b59a16b5 100644
--- a/test/unittest/aggs/tst.count2.d
+++ b/test/unittest/aggs/tst.count2.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/aggs/tst.count3.d b/test/unittest/aggs/tst.count3.d
index 4595fc74..a1884bac 100644
--- a/test/unittest/aggs/tst.count3.d
+++ b/test/unittest/aggs/tst.count3.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/aggs/tst.denormalizeonly.d b/test/unittest/aggs/tst.denormalizeonly.d
index c4e15141..d232f95e 100644
--- a/test/unittest/aggs/tst.denormalizeonly.d
+++ b/test/unittest/aggs/tst.denormalizeonly.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/aggs/tst.fmtnormalize.d b/test/unittest/aggs/tst.fmtnormalize.d
index 5b5b4154..a08f7368 100644
--- a/test/unittest/aggs/tst.fmtnormalize.d
+++ b/test/unittest/aggs/tst.fmtnormalize.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/aggs/tst.forms.d b/test/unittest/aggs/tst.forms.d
index ef129556..06e3996e 100644
--- a/test/unittest/aggs/tst.forms.d
+++ b/test/unittest/aggs/tst.forms.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/aggs/tst.keysort.d b/test/unittest/aggs/tst.keysort.d
index 9c157c3d..a8213bf2 100644
--- a/test/unittest/aggs/tst.keysort.d
+++ b/test/unittest/aggs/tst.keysort.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
diff --git a/test/unittest/aggs/tst.lquantize.d b/test/unittest/aggs/tst.lquantize.d
index e09214a9..e1764238 100644
--- a/test/unittest/aggs/tst.lquantize.d
+++ b/test/unittest/aggs/tst.lquantize.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/aggs/tst.lquantrange.d b/test/unittest/aggs/tst.lquantrange.d
index 4b42d566..cd0a3fab 100644
--- a/test/unittest/aggs/tst.lquantrange.d
+++ b/test/unittest/aggs/tst.lquantrange.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
diff --git a/test/unittest/aggs/tst.lquantzero.d b/test/unittest/aggs/tst.lquantzero.d
index 1b869ebb..8f69d9a9 100644
--- a/test/unittest/aggs/tst.lquantzero.d
+++ b/test/unittest/aggs/tst.lquantzero.d
@@ -1,14 +1,12 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
-
 BEGIN
 {
 	a = 7;
diff --git a/test/unittest/aggs/tst.multiaggs1.d b/test/unittest/aggs/tst.multiaggs1.d
index 371aa720..c9afd225 100644
--- a/test/unittest/aggs/tst.multiaggs1.d
+++ b/test/unittest/aggs/tst.multiaggs1.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/aggs/tst.multinormalize.d b/test/unittest/aggs/tst.multinormalize.d
index 90b8a32d..6abf76c2 100644
--- a/test/unittest/aggs/tst.multinormalize.d
+++ b/test/unittest/aggs/tst.multinormalize.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/aggs/tst.neglquant.d b/test/unittest/aggs/tst.neglquant.d
index 6629438b..63e3796b 100644
--- a/test/unittest/aggs/tst.neglquant.d
+++ b/test/unittest/aggs/tst.neglquant.d
@@ -4,7 +4,6 @@
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
diff --git a/test/unittest/aggs/tst.negorder.d b/test/unittest/aggs/tst.negorder.d
index c6b2bba1..4d5e6386 100644
--- a/test/unittest/aggs/tst.negorder.d
+++ b/test/unittest/aggs/tst.negorder.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
diff --git a/test/unittest/aggs/tst.negquant.d b/test/unittest/aggs/tst.negquant.d
index 78fa96ba..b9dff159 100644
--- a/test/unittest/aggs/tst.negquant.d
+++ b/test/unittest/aggs/tst.negquant.d
@@ -4,7 +4,6 @@
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
diff --git a/test/unittest/aggs/tst.order.d b/test/unittest/aggs/tst.order.d
index e8a8b469..9777cab6 100644
--- a/test/unittest/aggs/tst.order.d
+++ b/test/unittest/aggs/tst.order.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
diff --git a/test/unittest/aggs/tst.quantize.d b/test/unittest/aggs/tst.quantize.d
index db7b4190..3ae31449 100644
--- a/test/unittest/aggs/tst.quantize.d
+++ b/test/unittest/aggs/tst.quantize.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/aggs/tst.quantmany.d b/test/unittest/aggs/tst.quantmany.d
index b58f5326..de7d5635 100644
--- a/test/unittest/aggs/tst.quantmany.d
+++ b/test/unittest/aggs/tst.quantmany.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
diff --git a/test/unittest/aggs/tst.quantzero.d b/test/unittest/aggs/tst.quantzero.d
index 8fc80b41..0b7d9fdf 100644
--- a/test/unittest/aggs/tst.quantzero.d
+++ b/test/unittest/aggs/tst.quantzero.d
@@ -1,14 +1,12 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
-
 BEGIN
 {
 	a = 7;
diff --git a/test/unittest/aggs/tst.signedkeyspos.d b/test/unittest/aggs/tst.signedkeyspos.d
index 93803a7e..9530ab5c 100644
--- a/test/unittest/aggs/tst.signedkeyspos.d
+++ b/test/unittest/aggs/tst.signedkeyspos.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/aggs/tst.valsortkeypos.d b/test/unittest/aggs/tst.valsortkeypos.d
index 9f8fe0dd..d1de72b4 100644
--- a/test/unittest/aggs/tst.valsortkeypos.d
+++ b/test/unittest/aggs/tst.valsortkeypos.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
diff --git a/test/unittest/funcs/substr/tst.substrminate.d b/test/unittest/funcs/substr/tst.substrminate.d
index 84aa60c7..573a2076 100644
--- a/test/unittest/funcs/substr/tst.substrminate.d
+++ b/test/unittest/funcs/substr/tst.substrminate.d
@@ -4,7 +4,6 @@
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 #pragma D option aggsortkey
diff --git a/test/unittest/grammar/tst.stmts.d b/test/unittest/grammar/tst.stmts.d
index 18ed60b2..919c3166 100644
--- a/test/unittest/grammar/tst.stmts.d
+++ b/test/unittest/grammar/tst.stmts.d
@@ -1,6 +1,6 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
@@ -13,7 +13,6 @@
  *
  */
 
-/* @@xfail: dtv2 */
 /* @@timeout: 25 */
 
 BEGIN
diff --git a/test/unittest/misc/tst.haslam.d b/test/unittest/misc/tst.haslam.d
index 997d22df..406a9ead 100644
--- a/test/unittest/misc/tst.haslam.d
+++ b/test/unittest/misc/tst.haslam.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION: test for off-by-one error in the format lookup code
diff --git a/test/unittest/multiaggs/err.D_PRINTA_AGGKEY.d b/test/unittest/multiaggs/err.D_PRINTA_AGGKEY.d
index a5b5c522..a9ea789b 100644
--- a/test/unittest/multiaggs/err.D_PRINTA_AGGKEY.d
+++ b/test/unittest/multiaggs/err.D_PRINTA_AGGKEY.d
@@ -1,10 +1,10 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
+
 #pragma D option quiet
 
 BEGIN
diff --git a/test/unittest/multiaggs/err.D_PRINTA_AGGPROTO.d b/test/unittest/multiaggs/err.D_PRINTA_AGGPROTO.d
index 238421f4..b8887e81 100644
--- a/test/unittest/multiaggs/err.D_PRINTA_AGGPROTO.d
+++ b/test/unittest/multiaggs/err.D_PRINTA_AGGPROTO.d
@@ -1,10 +1,10 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
+
 #pragma D option quiet
 
 BEGIN
diff --git a/test/unittest/multiaggs/tst.many.d b/test/unittest/multiaggs/tst.many.d
index 5c94d2da..168cca13 100644
--- a/test/unittest/multiaggs/tst.many.d
+++ b/test/unittest/multiaggs/tst.many.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option destructive
 #pragma D option quiet
diff --git a/test/unittest/multiaggs/tst.sort.d b/test/unittest/multiaggs/tst.sort.d
index c61e2c1a..f9be92df 100644
--- a/test/unittest/multiaggs/tst.sort.d
+++ b/test/unittest/multiaggs/tst.sort.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
diff --git a/test/unittest/multiaggs/tst.sortpos.d b/test/unittest/multiaggs/tst.sortpos.d
index f6adb378..36763186 100644
--- a/test/unittest/multiaggs/tst.sortpos.d
+++ b/test/unittest/multiaggs/tst.sortpos.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
diff --git a/test/unittest/multiaggs/tst.zero.d b/test/unittest/multiaggs/tst.zero.d
index acfb99e1..197949cd 100644
--- a/test/unittest/multiaggs/tst.zero.d
+++ b/test/unittest/multiaggs/tst.zero.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
diff --git a/test/unittest/multiaggs/tst.zero2.d b/test/unittest/multiaggs/tst.zero2.d
index 28cd4cbf..cba509bc 100644
--- a/test/unittest/multiaggs/tst.zero2.d
+++ b/test/unittest/multiaggs/tst.zero2.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
diff --git a/test/unittest/multiaggs/tst.zero3.d b/test/unittest/multiaggs/tst.zero3.d
index 31b41acc..6dd3763f 100644
--- a/test/unittest/multiaggs/tst.zero3.d
+++ b/test/unittest/multiaggs/tst.zero3.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
diff --git a/test/unittest/printa/tst.dynwidth.d b/test/unittest/printa/tst.dynwidth.d
index 06051ae1..d6039ca3 100644
--- a/test/unittest/printa/tst.dynwidth.d
+++ b/test/unittest/printa/tst.dynwidth.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 #pragma D option quiet
 
diff --git a/test/unittest/printa/tst.tuple.d b/test/unittest/printa/tst.tuple.d
index 4fc05e6a..2996edaa 100644
--- a/test/unittest/printa/tst.tuple.d
+++ b/test/unittest/printa/tst.tuple.d
@@ -1,10 +1,9 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  */
-/* @@xfail: dtv2 */
 
 /*
  * ASSERTION:
-- 
2.18.4




More information about the DTrace-devel mailing list