xref: /illumos-gate/usr/src/uts/common/xen/dtrace/xdt.c (revision 2a9992ec)
1c7158ae9Stariq /*
2c7158ae9Stariq  * CDDL HEADER START
3c7158ae9Stariq  *
4c7158ae9Stariq  * The contents of this file are subject to the terms of the
5c7158ae9Stariq  * Common Development and Distribution License (the "License").
6c7158ae9Stariq  * You may not use this file except in compliance with the License.
7c7158ae9Stariq  *
8c7158ae9Stariq  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9c7158ae9Stariq  * or http://www.opensolaris.org/os/licensing.
10c7158ae9Stariq  * See the License for the specific language governing permissions
11c7158ae9Stariq  * and limitations under the License.
12c7158ae9Stariq  *
13c7158ae9Stariq  * When distributing Covered Code, include this CDDL HEADER in each
14c7158ae9Stariq  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15c7158ae9Stariq  * If applicable, add the following below this CDDL HEADER, with the
16c7158ae9Stariq  * fields enclosed by brackets "[]" replaced with your own identifying
17c7158ae9Stariq  * information: Portions Copyright [yyyy] [name of copyright owner]
18c7158ae9Stariq  *
19c7158ae9Stariq  * CDDL HEADER END
20c7158ae9Stariq  */
21c7158ae9Stariq 
22c7158ae9Stariq /*
23b9e93c10SJonathan Haslam  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24c7158ae9Stariq  * Use is subject to license terms.
25c7158ae9Stariq  */
26c7158ae9Stariq 
27c7158ae9Stariq /*
28c7158ae9Stariq  * Xen event provider for DTrace
29c7158ae9Stariq  *
30c7158ae9Stariq  * NOTE: This provider is PRIVATE. It is intended as a short-term solution and
31c7158ae9Stariq  * may disappear or be re-implemented at anytime.
32c7158ae9Stariq  *
33c7158ae9Stariq  * This provider isn't suitable as a general-purpose solution for a number of
34c7158ae9Stariq  * reasons. First and foremost, we rely on the Xen tracing mechanism and don't
35c7158ae9Stariq  * have any way to gather data other than that collected by the Xen trace
36c7158ae9Stariq  * buffers. Further, it does not fit into the DTrace model (see "Interacting
37c7158ae9Stariq  * with DTrace" below.)
38c7158ae9Stariq  *
39c7158ae9Stariq  *
40c7158ae9Stariq  * Tracing in Xen
41c7158ae9Stariq  * --------------
42c7158ae9Stariq  *
43c7158ae9Stariq  * Xen implements a tracing facility for generating and collecting execution
44c7158ae9Stariq  * event traces from the hypervisor. When tracing is enabled, compiled in
45c7158ae9Stariq  * probes record events in contiguous per-CPU trace buffers.
46c7158ae9Stariq  *
47c7158ae9Stariq  *               +---------+
48c7158ae9Stariq  * +------+      |         |
49c7158ae9Stariq  * | CPUn |----> | BUFFERn |
50c7158ae9Stariq  * +------+      |         |
51c7158ae9Stariq  *               +---------+- tbuf.va + (tbuf.size * n)
52c7158ae9Stariq  *               :         :
53c7158ae9Stariq  *               +---------+
54c7158ae9Stariq  * +------+      |         |
55c7158ae9Stariq  * | CPU1 |----> | BUFFER1 |
56c7158ae9Stariq  * +------+      |         |
57c7158ae9Stariq  *               +---------+- tbuf.va + tbuf.size
58c7158ae9Stariq  * +------+      |         |
59c7158ae9Stariq  * | CPU0 |----> | BUFFER0 |
60c7158ae9Stariq  * +------+      |         |
61c7158ae9Stariq  *               +---------+- tbuf.va
62c7158ae9Stariq  *
63c7158ae9Stariq  * Each CPU buffer consists of a metadata header followed by the trace records.
64c7158ae9Stariq  * The metadata consists of a producer/consumer pair of pointers into the buffer
65c7158ae9Stariq  * that point to the next record to be written and the next record to be read
66349b53ddSStuart Maybee  * respectively.
67c7158ae9Stariq  *
68349b53ddSStuart Maybee  * A trace record can be in one of two forms, depending on if the TSC is
69349b53ddSStuart Maybee  * included. The record header indicates whether or not the TSC field is
70349b53ddSStuart Maybee  * present.
71349b53ddSStuart Maybee  *
72349b53ddSStuart Maybee  * 1. Trace record without TSC:
73349b53ddSStuart Maybee  * +------------------------------------------------------------+
74349b53ddSStuart Maybee  * | HEADER(uint32_t) |            DATA FIELDS                  |
75349b53ddSStuart Maybee  * +------------------------------------------------------------+
76349b53ddSStuart Maybee  *
77349b53ddSStuart Maybee  * 2. Trace record with TSC:
78349b53ddSStuart Maybee  * +--------------------------------------------------------------------------+
79349b53ddSStuart Maybee  * | HEADER(uint32_t) | TSC(uint64_t) |              DATA FIELDS              |
80349b53ddSStuart Maybee  * +--------------------------------------------------------------------------+
81349b53ddSStuart Maybee  *
82349b53ddSStuart Maybee  * Where,
83349b53ddSStuart Maybee  *
84349b53ddSStuart Maybee  * HEADER bit field:
85c7158ae9Stariq  * +--------------------------------------------------------------------------+
86349b53ddSStuart Maybee  * | C |  NDATA  |                        EVENT                               |
87c7158ae9Stariq  * +--------------------------------------------------------------------------+
88349b53ddSStuart Maybee  *  31  30     28 27                                                         0
89349b53ddSStuart Maybee  *
90349b53ddSStuart Maybee  * EVENT: Event ID.
91349b53ddSStuart Maybee  * NDATA: Number of populated data fields.
92349b53ddSStuart Maybee  *     C: TSC included.
93c7158ae9Stariq  *
94c7158ae9Stariq  * DATA FIELDS:
95c7158ae9Stariq  * +--------------------------------------------------------------------------+
96349b53ddSStuart Maybee  * | D1(uint32_t) | D2(uint32_t) | D3(uint32_t) |     . . .    | D7(uint32_t) |
97c7158ae9Stariq  * +--------------------------------------------------------------------------+
98c7158ae9Stariq  *
99c7158ae9Stariq  *
100c7158ae9Stariq  * Interacting with DTrace
101c7158ae9Stariq  * -----------------------
102c7158ae9Stariq  *
103c7158ae9Stariq  * Every xdt_poll_nsec nano-seconds we poll the trace buffers for data and feed
104c7158ae9Stariq  * each entry into dtrace_probe() with the corresponding probe ID for the event.
105c7158ae9Stariq  * As a result of this periodic collection implementation probe firings are
106c7158ae9Stariq  * asynchronous. This is the only sensible way to implement this form of
107c7158ae9Stariq  * provider, but because of its asynchronous nature asking things like
108c7158ae9Stariq  * "current CPU" and, more importantly, arbitrary questions about the context
109c7158ae9Stariq  * surrounding the probe firing are not meaningful. So, consumers should not
110c7158ae9Stariq  * attempt to infer anything beyond what is supplied via the probe arguments.
111c7158ae9Stariq  */
112c7158ae9Stariq 
113349b53ddSStuart Maybee #include <sys/xpv_user.h>
114349b53ddSStuart Maybee 
115c7158ae9Stariq #include <sys/types.h>
116c7158ae9Stariq #include <sys/sysmacros.h>
117c7158ae9Stariq #include <sys/modctl.h>
118c7158ae9Stariq #include <sys/sunddi.h>
119c7158ae9Stariq #include <sys/ddi.h>
120c7158ae9Stariq #include <sys/conf.h>
121c7158ae9Stariq #include <sys/devops.h>
122c7158ae9Stariq #include <sys/stat.h>
123c7158ae9Stariq #include <sys/cmn_err.h>
124c7158ae9Stariq #include <sys/dtrace.h>
125c7158ae9Stariq #include <sys/sdt.h>
126c7158ae9Stariq #include <sys/cyclic.h>
127c7158ae9Stariq #include <vm/seg_kmem.h>
128c7158ae9Stariq #include <vm/hat_i86.h>
129349b53ddSStuart Maybee 
130c7158ae9Stariq #include <sys/hypervisor.h>
131c7158ae9Stariq #include <xen/public/trace.h>
132c7158ae9Stariq #include <xen/public/sched.h>
133c7158ae9Stariq 
134c7158ae9Stariq #define	XDT_POLL_DEFAULT	100000000	/* default poll interval (ns) */
135c7158ae9Stariq #define	XDT_POLL_MIN		10000000	/* min poll interval (ns) */
136c7158ae9Stariq #define	XDT_TBUF_RETRY		50		/* tbuf disable retry count */
137c7158ae9Stariq 
138c7158ae9Stariq /*
139c7158ae9Stariq  * The domid must match IDLE_DOMAIN_ID in xen.hg/xen/include/xen/sched.h
140c7158ae9Stariq  * in the xVM gate.
141c7158ae9Stariq  */
142c7158ae9Stariq #define	IS_IDLE_DOM(domid)	(domid == 0x7FFFU)
143c7158ae9Stariq 
144c7158ae9Stariq /* Macros to extract the domid and cpuid from a HVM trace data field */
145c7158ae9Stariq #define	HVM_DOMID(d)		(d >> 16)
146c7158ae9Stariq #define	HVM_VCPUID(d)		(d & 0xFFFF)
147c7158ae9Stariq 
14855f5292cSFrank Van Der Linden /* Flags for shadow page table events */
14955f5292cSFrank Van Der Linden #define	SH_GUEST_32	0x000
15055f5292cSFrank Van Der Linden #define	SH_GUEST_PAE	0x100
15155f5292cSFrank Van Der Linden #define	SH_GUEST_64	0x200
15255f5292cSFrank Van Der Linden 
15355f5292cSFrank Van Der Linden #define	XDT_PROBE5(event, arg0, arg1, arg2, arg3, arg4) {		\
154c7158ae9Stariq 	dtrace_id_t id = xdt_probemap[event];				\
155c7158ae9Stariq 	if (id)								\
15655f5292cSFrank Van Der Linden 		dtrace_probe(id, arg0, arg1, arg2, arg3, arg4);		\
157c7158ae9Stariq }									\
158c7158ae9Stariq 
15955f5292cSFrank Van Der Linden #define	XDT_PROBE4(event, arg0, arg1, arg2, arg3) \
16055f5292cSFrank Van Der Linden 	XDT_PROBE5(event, arg0, arg1, arg2, arg3, 0)
16155f5292cSFrank Van Der Linden 
16255f5292cSFrank Van Der Linden #define	XDT_PROBE3(event, arg0, arg1, arg2) \
16355f5292cSFrank Van Der Linden 	XDT_PROBE5(event, arg0, arg1, arg2, 0, 0)
164c7158ae9Stariq 
16555f5292cSFrank Van Der Linden #define	XDT_PROBE2(event, arg0, arg1) \
16655f5292cSFrank Van Der Linden 	XDT_PROBE5(event, arg0, arg1, 0, 0, 0)
167c7158ae9Stariq 
16855f5292cSFrank Van Der Linden #define	XDT_PROBE1(event, arg0) \
16955f5292cSFrank Van Der Linden 	XDT_PROBE5(event, arg0, 0, 0, 0, 0)
170c7158ae9Stariq 
17155f5292cSFrank Van Der Linden #define	XDT_PROBE0(event) \
17255f5292cSFrank Van Der Linden 	XDT_PROBE5(event, 0, 0, 0, 0, 0)
173c7158ae9Stariq 
174c7158ae9Stariq /* Probe classes */
175c7158ae9Stariq #define	XDT_SCHED			0
176c7158ae9Stariq #define	XDT_MEM				1
177c7158ae9Stariq #define	XDT_HVM				2
178349b53ddSStuart Maybee #define	XDT_GEN				3
17955f5292cSFrank Van Der Linden #define	XDT_PV				4
18055f5292cSFrank Van Der Linden #define	XDT_SHADOW			5
18155f5292cSFrank Van Der Linden #define	XDT_PM				6
18255f5292cSFrank Van Der Linden #define	XDT_NCLASSES			7
183c7158ae9Stariq 
184c7158ae9Stariq /* Probe events */
185c7158ae9Stariq #define	XDT_EVT_INVALID			(-(int)1)
186c7158ae9Stariq #define	XDT_SCHED_OFF_CPU		0
187c7158ae9Stariq #define	XDT_SCHED_ON_CPU		1
188c7158ae9Stariq #define	XDT_SCHED_IDLE_OFF_CPU		2
189c7158ae9Stariq #define	XDT_SCHED_IDLE_ON_CPU		3
190c7158ae9Stariq #define	XDT_SCHED_BLOCK			4
191c7158ae9Stariq #define	XDT_SCHED_SLEEP			5
192c7158ae9Stariq #define	XDT_SCHED_WAKE			6
193c7158ae9Stariq #define	XDT_SCHED_YIELD			7
194c7158ae9Stariq #define	XDT_SCHED_SHUTDOWN_POWEROFF	8
195c7158ae9Stariq #define	XDT_SCHED_SHUTDOWN_REBOOT	9
196c7158ae9Stariq #define	XDT_SCHED_SHUTDOWN_SUSPEND	10
197c7158ae9Stariq #define	XDT_SCHED_SHUTDOWN_CRASH	11
198c7158ae9Stariq #define	XDT_MEM_PAGE_GRANT_MAP		12
199c7158ae9Stariq #define	XDT_MEM_PAGE_GRANT_UNMAP	13
200c7158ae9Stariq #define	XDT_MEM_PAGE_GRANT_TRANSFER	14
201c7158ae9Stariq #define	XDT_HVM_VMENTRY			15
202c7158ae9Stariq #define	XDT_HVM_VMEXIT			16
203349b53ddSStuart Maybee #define	XDT_TRC_LOST_RECORDS		17
20455f5292cSFrank Van Der Linden #define	XDT_SCHED_ADD_VCPU		18
20555f5292cSFrank Van Der Linden #define	XDT_SCHED_REM_VCPU		19	/* unused */
20655f5292cSFrank Van Der Linden #define	XDT_SCHED_CTL			20	/* unused */
20755f5292cSFrank Van Der Linden #define	XDT_SCHED_ADJDOM		21
20855f5292cSFrank Van Der Linden #define	XDT_SCHED_S_TIMER_FN		22	/* unused */
20955f5292cSFrank Van Der Linden #define	XDT_SCHED_T_TIMER_FN		23	/* unused */
21055f5292cSFrank Van Der Linden #define	XDT_SCHED_DOM_TIMER_FN		24	/* unused */
21155f5292cSFrank Van Der Linden #define	XDT_PV_HYPERCALL		25
21255f5292cSFrank Van Der Linden #define	XDT_PV_TRAP			26
21355f5292cSFrank Van Der Linden #define	XDT_PV_PAGE_FAULT		27
21455f5292cSFrank Van Der Linden #define	XDT_PV_FORCED_INVALID_OP	28
21555f5292cSFrank Van Der Linden #define	XDT_PV_EMULATE_PRIVOP		29
21655f5292cSFrank Van Der Linden #define	XDT_PV_EMULATE_4GB		30	/* unused (32-bit HV only ) */
21755f5292cSFrank Van Der Linden #define	XDT_PV_MATH_STATE_RESTORE	31
21855f5292cSFrank Van Der Linden #define	XDT_PV_PAGING_FIXUP		32
21955f5292cSFrank Van Der Linden #define	XDT_PV_DT_MAPPING_FAULT		33
22055f5292cSFrank Van Der Linden #define	XDT_PV_PTWR_EMULATION		34
22155f5292cSFrank Van Der Linden #define	XDT_HVM_PF_XEN			35
22255f5292cSFrank Van Der Linden #define	XDT_HVM_PF_INJECT		36
22355f5292cSFrank Van Der Linden #define	XDT_HVM_EXC_INJECT		37
22455f5292cSFrank Van Der Linden #define	XDT_HVM_VIRQ_INJECT		38
22555f5292cSFrank Van Der Linden #define	XDT_HVM_VIRQ_REINJECT		39
22655f5292cSFrank Van Der Linden #define	XDT_HVM_IO_READ			40	/* unused */
22755f5292cSFrank Van Der Linden #define	XDT_HVM_IO_WRITE		41	/* unused */
22855f5292cSFrank Van Der Linden #define	XDT_HVM_CR_READ			42
22955f5292cSFrank Van Der Linden #define	XDT_HVM_CR_WRITE		43
23055f5292cSFrank Van Der Linden #define	XDT_HVM_DR_READ			44	/* unused */
23155f5292cSFrank Van Der Linden #define	XDT_HVM_DR_WRITE		45	/* unused */
23255f5292cSFrank Van Der Linden #define	XDT_HVM_MSR_READ		46
23355f5292cSFrank Van Der Linden #define	XDT_HVM_MSR_WRITE		47
23455f5292cSFrank Van Der Linden #define	XDT_HVM_CPUID			48
23555f5292cSFrank Van Der Linden #define	XDT_HVM_INTR			49
23655f5292cSFrank Van Der Linden #define	XDT_HVM_INTR_WINDOW		50
23755f5292cSFrank Van Der Linden #define	XDT_HVM_NMI			51
23855f5292cSFrank Van Der Linden #define	XDT_HVM_SMI			52
23955f5292cSFrank Van Der Linden #define	XDT_HVM_VMMCALL			53
24055f5292cSFrank Van Der Linden #define	XDT_HVM_HLT			54
24155f5292cSFrank Van Der Linden #define	XDT_HVM_INVLPG			55
24255f5292cSFrank Van Der Linden #define	XDT_HVM_MCE			56
24355f5292cSFrank Van Der Linden #define	XDT_HVM_IOPORT_READ		57
24455f5292cSFrank Van Der Linden #define	XDT_HVM_IOPORT_WRITE		58
24555f5292cSFrank Van Der Linden #define	XDT_HVM_CLTS			59
24655f5292cSFrank Van Der Linden #define	XDT_HVM_LMSW			60
24755f5292cSFrank Van Der Linden #define	XDT_HVM_IOMEM_READ		61
24855f5292cSFrank Van Der Linden #define	XDT_HVM_IOMEM_WRITE		62
24955f5292cSFrank Van Der Linden #define	XDT_SHADOW_NOT_SHADOW			63
25055f5292cSFrank Van Der Linden #define	XDT_SHADOW_FAST_PROPAGATE		64
25155f5292cSFrank Van Der Linden #define	XDT_SHADOW_FAST_MMIO			65
25255f5292cSFrank Van Der Linden #define	XDT_SHADOW_FALSE_FAST_PATH		66
25355f5292cSFrank Van Der Linden #define	XDT_SHADOW_MMIO				67
25455f5292cSFrank Van Der Linden #define	XDT_SHADOW_FIXUP			68
25555f5292cSFrank Van Der Linden #define	XDT_SHADOW_DOMF_DYING			69
25655f5292cSFrank Van Der Linden #define	XDT_SHADOW_EMULATE			70
25755f5292cSFrank Van Der Linden #define	XDT_SHADOW_EMULATE_UNSHADOW_USER	71
25855f5292cSFrank Van Der Linden #define	XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ	72
25955f5292cSFrank Van Der Linden #define	XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED	73
26055f5292cSFrank Van Der Linden #define	XDT_SHADOW_WRMAP_BF			74
26155f5292cSFrank Van Der Linden #define	XDT_SHADOW_PREALLOC_UNPIN		75
26255f5292cSFrank Van Der Linden #define	XDT_SHADOW_RESYNC_FULL			76
26355f5292cSFrank Van Der Linden #define	XDT_SHADOW_RESYNC_ONLY			77
26455f5292cSFrank Van Der Linden #define	XDT_PM_FREQ_CHANGE		78
26555f5292cSFrank Van Der Linden #define	XDT_PM_IDLE_ENTRY		79
26655f5292cSFrank Van Der Linden #define	XDT_PM_IDLE_EXIT		80
26755f5292cSFrank Van Der Linden #define	XDT_SCHED_RUNSTATE_CHANGE	81
26855f5292cSFrank Van Der Linden #define	XDT_SCHED_CONTINUE_RUNNING	82
26955f5292cSFrank Van Der Linden #define	XDT_NEVENTS			83
270c7158ae9Stariq 
271c7158ae9Stariq typedef struct {
272c7158ae9Stariq 	const char	*pr_mod;	/* probe module */
273c7158ae9Stariq 	const char	*pr_name;	/* probe name */
274c7158ae9Stariq 	int		evt_id;		/* event id */
275c7158ae9Stariq 	uint_t		class;		/* probe class */
276c7158ae9Stariq } xdt_probe_t;
277c7158ae9Stariq 
278c7158ae9Stariq typedef struct {
279c7158ae9Stariq 	uint32_t	trc_mask;	/* trace mask */
280c7158ae9Stariq 	uint32_t	cnt;		/* num enabled probes in class */
281c7158ae9Stariq } xdt_classinfo_t;
282c7158ae9Stariq 
283c7158ae9Stariq typedef struct {
284c7158ae9Stariq 	ulong_t prev_domid;		/* previous dom executed */
285c7158ae9Stariq 	ulong_t prev_vcpuid;		/* previous vcpu executed */
286c7158ae9Stariq 	ulong_t prev_ctime;		/* time spent on cpu */
287c7158ae9Stariq 	ulong_t next_domid;		/* next dom to be scheduled */
288c7158ae9Stariq 	ulong_t next_vcpuid;		/* next vcpu to be scheduled */
289c7158ae9Stariq 	ulong_t next_wtime;		/* time spent waiting to get on cpu */
290c7158ae9Stariq 	ulong_t next_ts;		/* allocated time slice */
29155f5292cSFrank Van Der Linden 	ulong_t cur_domid;		/* current dom */
29255f5292cSFrank Van Der Linden 	ulong_t cur_vcpuid;		/* current vcpuid */
29355f5292cSFrank Van Der Linden 	int curinfo_valid;		/* info is valid */
294c7158ae9Stariq } xdt_schedinfo_t;
295c7158ae9Stariq 
296c7158ae9Stariq static struct {
297c7158ae9Stariq 	uint_t cnt;			/* total num of trace buffers */
298c7158ae9Stariq 	size_t size;			/* size of each cpu buffer */
299c7158ae9Stariq 	mfn_t start_mfn;		/* starting mfn of buffers */
300c7158ae9Stariq 	caddr_t va;			/* va buffers are mapped into */
301c7158ae9Stariq 
302c7158ae9Stariq 	/* per-cpu buffers */
303c7158ae9Stariq 	struct t_buf **meta;		/* buffer metadata */
304c7158ae9Stariq 	struct t_rec **data;		/* buffer data records */
305c7158ae9Stariq 
306c7158ae9Stariq 	/* statistics */
307c7158ae9Stariq 	uint64_t stat_dropped_recs;	/* records dropped */
308c7158ae9Stariq 	uint64_t stat_spurious_cpu;	/* recs with garbage cpuids */
309c7158ae9Stariq 	uint64_t stat_spurious_switch;	/* inconsistent vcpu switches */
310c7158ae9Stariq 	uint64_t stat_unknown_shutdown;	/* unknown shutdown code */
311c7158ae9Stariq 	uint64_t stat_unknown_recs;	/* unknown records */
312c7158ae9Stariq } tbuf;
313c7158ae9Stariq 
31455f5292cSFrank Van Der Linden static size_t tbuf_data_size;
31555f5292cSFrank Van Der Linden 
316c7158ae9Stariq static char *xdt_stats[] = {
317c7158ae9Stariq 	"dropped_recs",
318c7158ae9Stariq };
319c7158ae9Stariq 
320c7158ae9Stariq /*
321c7158ae9Stariq  * Tunable variables
322c7158ae9Stariq  *
323c7158ae9Stariq  * The following may be tuned by adding a line to /etc/system that
324c7158ae9Stariq  * includes both the name of the module ("xdt") and the name of the variable.
325c7158ae9Stariq  * For example:
326c7158ae9Stariq  *     set xdt:xdt_tbuf_pages = 40
327c7158ae9Stariq  */
328c7158ae9Stariq uint_t xdt_tbuf_pages = 20;			/* pages to alloc per-cpu buf */
329c7158ae9Stariq 
330c7158ae9Stariq /*
331c7158ae9Stariq  * The following may be tuned by adding a line to
332c7158ae9Stariq  * /platform/i86xpv/kernel/drv/xdt.conf.
333c7158ae9Stariq  * For example:
334c7158ae9Stariq  *     xdt_poll_nsec = 200000000;
335c7158ae9Stariq  */
336c7158ae9Stariq static hrtime_t xdt_poll_nsec;			/* trace buffer poll interval */
337c7158ae9Stariq 
33855f5292cSFrank Van Der Linden /*
33955f5292cSFrank Van Der Linden  * Another tunable variable: the maximum number of records to process
34055f5292cSFrank Van Der Linden  * in one scan. If it is 0 (e.g. not set in /etc/system), it will
34155f5292cSFrank Van Der Linden  * be set to ncpu * (bufsize / max_rec_size).
34255f5292cSFrank Van Der Linden  *
34355f5292cSFrank Van Der Linden  * Having an upper limit avoids a situation where the scan would loop
34455f5292cSFrank Van Der Linden  * endlessly in case the hypervisor adds records quicker than we
34555f5292cSFrank Van Der Linden  * can process them. It's better to drop records than to loop, obviously.
34655f5292cSFrank Van Der Linden  */
34755f5292cSFrank Van Der Linden uint_t xdt_max_recs = 0;
34855f5292cSFrank Van Der Linden 
349c7158ae9Stariq /*
350c7158ae9Stariq  * Internal variables
351c7158ae9Stariq  */
352c7158ae9Stariq static dev_info_t *xdt_devi;
353c7158ae9Stariq static dtrace_provider_id_t xdt_id;
354c7158ae9Stariq static uint_t xdt_ncpus;			/* total number of phys CPUs */
355c7158ae9Stariq static uint32_t cur_trace_mask;			/* current trace mask */
356c7158ae9Stariq static xdt_schedinfo_t *xdt_cpu_schedinfo;	/* per-cpu sched info */
357c7158ae9Stariq dtrace_id_t xdt_probemap[XDT_NEVENTS];		/* map of enabled probes */
358c7158ae9Stariq dtrace_id_t xdt_prid[XDT_NEVENTS];		/* IDs of registered events */
359c7158ae9Stariq static cyclic_id_t xdt_cyclic = CYCLIC_NONE;
360c7158ae9Stariq static kstat_t *xdt_kstats;
361c7158ae9Stariq static xdt_classinfo_t xdt_classinfo[XDT_NCLASSES];
362c7158ae9Stariq 
36355f5292cSFrank Van Der Linden /*
36455f5292cSFrank Van Der Linden  * These provide context when probes fire. They can be accessed
36555f5292cSFrank Van Der Linden  * from xdt dtrace probe (as `xdt_curdom, etc). It's ok for these
36655f5292cSFrank Van Der Linden  * to be global, and not per-cpu, as probes are run strictly in sequence
36755f5292cSFrank Van Der Linden  * as the trace buffers are
36855f5292cSFrank Van Der Linden  */
36955f5292cSFrank Van Der Linden uint_t xdt_curdom, xdt_curvcpu, xdt_curpcpu;
37055f5292cSFrank Van Der Linden uint64_t xdt_timestamp;
37155f5292cSFrank Van Der Linden 
372c7158ae9Stariq static xdt_probe_t xdt_probe[] = {
373c7158ae9Stariq 	/* Sched probes */
374c7158ae9Stariq 	{ "sched", "off-cpu", XDT_SCHED_OFF_CPU, XDT_SCHED },
375c7158ae9Stariq 	{ "sched", "on-cpu", XDT_SCHED_ON_CPU, XDT_SCHED },
376c7158ae9Stariq 	{ "sched", "idle-off-cpu", XDT_SCHED_IDLE_OFF_CPU, XDT_SCHED },
377c7158ae9Stariq 	{ "sched", "idle-on-cpu", XDT_SCHED_IDLE_ON_CPU, XDT_SCHED },
378c7158ae9Stariq 	{ "sched", "block", XDT_SCHED_BLOCK, XDT_SCHED },
379c7158ae9Stariq 	{ "sched", "sleep", XDT_SCHED_SLEEP, XDT_SCHED },
380c7158ae9Stariq 	{ "sched", "wake", XDT_SCHED_WAKE, XDT_SCHED },
381c7158ae9Stariq 	{ "sched", "yield", XDT_SCHED_YIELD, XDT_SCHED },
382c7158ae9Stariq 	{ "sched", "shutdown-poweroff", XDT_SCHED_SHUTDOWN_POWEROFF,
383c7158ae9Stariq 		XDT_SCHED },
384c7158ae9Stariq 	{ "sched", "shutdown-reboot", XDT_SCHED_SHUTDOWN_REBOOT, XDT_SCHED },
385c7158ae9Stariq 	{ "sched", "shutdown-suspend", XDT_SCHED_SHUTDOWN_SUSPEND, XDT_SCHED },
386c7158ae9Stariq 	{ "sched", "shutdown-crash", XDT_SCHED_SHUTDOWN_CRASH, XDT_SCHED },
38755f5292cSFrank Van Der Linden 	{ "sched", "add", XDT_SCHED_ADD_VCPU, XDT_SCHED },
38855f5292cSFrank Van Der Linden 	{ "sched", "runstate-change", XDT_SCHED_RUNSTATE_CHANGE, XDT_SCHED },
38955f5292cSFrank Van Der Linden 	{ "sched", "continue-running", XDT_SCHED_CONTINUE_RUNNING, XDT_SCHED },
390c7158ae9Stariq 
391c7158ae9Stariq 	/* Memory probes */
392c7158ae9Stariq 	{ "mem", "page-grant-map", XDT_MEM_PAGE_GRANT_MAP, XDT_MEM },
393c7158ae9Stariq 	{ "mem", "page-grant-unmap", XDT_MEM_PAGE_GRANT_UNMAP, XDT_MEM },
394c7158ae9Stariq 	{ "mem", "page-grant-transfer", XDT_MEM_PAGE_GRANT_TRANSFER, XDT_MEM },
395c7158ae9Stariq 
39655f5292cSFrank Van Der Linden 	{"pv", "hypercall", XDT_PV_HYPERCALL, XDT_PV },
39755f5292cSFrank Van Der Linden 	{"pv", "trap", XDT_PV_TRAP, XDT_PV },
39855f5292cSFrank Van Der Linden 	{"pv", "page-fault", XDT_PV_PAGE_FAULT, XDT_PV },
39955f5292cSFrank Van Der Linden 	{"pv", "forced-invalid-op", XDT_PV_FORCED_INVALID_OP, XDT_PV },
40055f5292cSFrank Van Der Linden 	{"pv", "emulate-priv-op", XDT_PV_EMULATE_PRIVOP, XDT_PV },
40155f5292cSFrank Van Der Linden 	{"pv", "math-state-restore", XDT_PV_MATH_STATE_RESTORE, XDT_PV },
40255f5292cSFrank Van Der Linden 	{"pv", "paging-fixup", XDT_PV_PAGING_FIXUP, XDT_PV },
40355f5292cSFrank Van Der Linden 	{"pv", "dt-mapping-fault", XDT_PV_DT_MAPPING_FAULT, XDT_PV },
40455f5292cSFrank Van Der Linden 	{"pv", "pte-write-emul", XDT_PV_PTWR_EMULATION, XDT_PV },
40555f5292cSFrank Van Der Linden 
406c7158ae9Stariq 	/* HVM probes */
407c7158ae9Stariq 	{ "hvm", "vmentry", XDT_HVM_VMENTRY, XDT_HVM },
408c7158ae9Stariq 	{ "hvm", "vmexit", XDT_HVM_VMEXIT, XDT_HVM },
40955f5292cSFrank Van Der Linden 	{ "hvm", "pagefault-xen", XDT_HVM_PF_XEN, XDT_HVM },
41055f5292cSFrank Van Der Linden 	{ "hvm", "pagefault-inject", XDT_HVM_PF_INJECT, XDT_HVM },
41155f5292cSFrank Van Der Linden 	{ "hvm", "exception-inject", XDT_HVM_EXC_INJECT, XDT_HVM },
41255f5292cSFrank Van Der Linden 	{ "hvm", "virq-inject", XDT_HVM_VIRQ_INJECT, XDT_HVM },
41355f5292cSFrank Van Der Linden 	{ "hvm", "cr-read", XDT_HVM_CR_READ, XDT_HVM },
41455f5292cSFrank Van Der Linden 	{ "hvm", "cr-write", XDT_HVM_CR_WRITE, XDT_HVM },
41555f5292cSFrank Van Der Linden 	{ "hvm", "msr-read", XDT_HVM_MSR_READ, XDT_HVM },
41655f5292cSFrank Van Der Linden 	{ "hvm", "msr-write", XDT_HVM_MSR_WRITE, XDT_HVM },
41755f5292cSFrank Van Der Linden 	{ "hvm", "cpuid", XDT_HVM_CPUID, XDT_HVM },
41855f5292cSFrank Van Der Linden 	{ "hvm", "intr", XDT_HVM_INTR, XDT_HVM },
41955f5292cSFrank Van Der Linden 	{ "hvm", "intr-window", XDT_HVM_INTR_WINDOW, XDT_HVM },
42055f5292cSFrank Van Der Linden 	{ "hvm", "nmi", XDT_HVM_NMI, XDT_HVM },
42155f5292cSFrank Van Der Linden 	{ "hvm", "smi", XDT_HVM_SMI, XDT_HVM },
42255f5292cSFrank Van Der Linden 	{ "hvm", "vmmcall", XDT_HVM_VMMCALL, XDT_HVM },
42355f5292cSFrank Van Der Linden 	{ "hvm", "hlt", XDT_HVM_HLT, XDT_HVM },
42455f5292cSFrank Van Der Linden 	{ "hvm", "invlpg", XDT_HVM_INVLPG, XDT_HVM },
42555f5292cSFrank Van Der Linden 	{ "hvm", "mce", XDT_HVM_MCE, XDT_HVM },
42655f5292cSFrank Van Der Linden 	{ "hvm", "pio-read", XDT_HVM_IOPORT_READ, XDT_HVM },
42755f5292cSFrank Van Der Linden 	{ "hvm", "pio-write", XDT_HVM_IOPORT_WRITE, XDT_HVM },
42855f5292cSFrank Van Der Linden 	{ "hvm", "mmio-read", XDT_HVM_IOMEM_READ, XDT_HVM },
42955f5292cSFrank Van Der Linden 	{ "hvm", "mmio-write", XDT_HVM_IOMEM_WRITE, XDT_HVM },
43055f5292cSFrank Van Der Linden 	{ "hvm", "clts", XDT_HVM_CLTS, XDT_HVM },
43155f5292cSFrank Van Der Linden 	{ "hvm", "lmsw", XDT_HVM_LMSW, XDT_HVM },
43255f5292cSFrank Van Der Linden 
43355f5292cSFrank Van Der Linden 	{ "shadow", "fault-not-shadow", XDT_SHADOW_NOT_SHADOW, XDT_SHADOW },
43455f5292cSFrank Van Der Linden 	{ "shadow", "fast-propagate", XDT_SHADOW_FAST_PROPAGATE, XDT_SHADOW },
43555f5292cSFrank Van Der Linden 	{ "shadow", "fast-mmio", XDT_SHADOW_FAST_MMIO, XDT_SHADOW },
43655f5292cSFrank Van Der Linden 	{ "shadow", "false-fast-path", XDT_SHADOW_FALSE_FAST_PATH,
43755f5292cSFrank Van Der Linden 	    XDT_SHADOW },
43855f5292cSFrank Van Der Linden 	{ "shadow", "mmio", XDT_SHADOW_MMIO, XDT_SHADOW },
43955f5292cSFrank Van Der Linden 	{ "shadow", "fixup", XDT_SHADOW_FIXUP, XDT_SHADOW },
44055f5292cSFrank Van Der Linden 	{ "shadow", "domf-dying", XDT_SHADOW_DOMF_DYING, XDT_SHADOW },
44155f5292cSFrank Van Der Linden 	{ "shadow", "emulate", XDT_SHADOW_EMULATE, XDT_SHADOW },
44255f5292cSFrank Van Der Linden 	{ "shadow", "emulate-unshadow-user", XDT_SHADOW_EMULATE_UNSHADOW_USER,
44355f5292cSFrank Van Der Linden 	    XDT_SHADOW },
44455f5292cSFrank Van Der Linden 	{ "shadow", "emulate-unshadow-evtinj",
44555f5292cSFrank Van Der Linden 	    XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ, XDT_SHADOW },
44655f5292cSFrank Van Der Linden 	{ "shadow", "emulate-unshadow-unhandled",
44755f5292cSFrank Van Der Linden 	    XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED, XDT_SHADOW },
44855f5292cSFrank Van Der Linden 	{ "shadow", "wrmap-bf", XDT_SHADOW_WRMAP_BF, XDT_SHADOW },
44955f5292cSFrank Van Der Linden 	{ "shadow", "prealloc-unpin", XDT_SHADOW_PREALLOC_UNPIN, XDT_SHADOW },
45055f5292cSFrank Van Der Linden 	{ "shadow", "resync-full", XDT_SHADOW_RESYNC_FULL, XDT_SHADOW },
45155f5292cSFrank Van Der Linden 	{ "shadow", "resync-only", XDT_SHADOW_RESYNC_ONLY, XDT_SHADOW },
45255f5292cSFrank Van Der Linden 
45355f5292cSFrank Van Der Linden 	{ "pm", "freq-change", XDT_PM_FREQ_CHANGE, XDT_PM },
45455f5292cSFrank Van Der Linden 	{ "pm", "idle-entry", XDT_PM_IDLE_ENTRY, XDT_PM },
45555f5292cSFrank Van Der Linden 	{ "pm", "idle-exit", XDT_PM_IDLE_EXIT, XDT_PM },
456c7158ae9Stariq 
457349b53ddSStuart Maybee 	/* Trace buffer related probes */
458349b53ddSStuart Maybee 	{ "trace", "records-lost", XDT_TRC_LOST_RECORDS, XDT_GEN },
459349b53ddSStuart Maybee 
460c7158ae9Stariq 	{ NULL }
461c7158ae9Stariq };
462c7158ae9Stariq 
463c7158ae9Stariq static inline uint32_t
xdt_nr_active_probes()464c7158ae9Stariq xdt_nr_active_probes()
465c7158ae9Stariq {
466c7158ae9Stariq 	int i;
467c7158ae9Stariq 	uint32_t tot = 0;
468c7158ae9Stariq 
469c7158ae9Stariq 	for (i = 0; i < XDT_NCLASSES; i++)
470c7158ae9Stariq 		tot += xdt_classinfo[i].cnt;
471c7158ae9Stariq 
472c7158ae9Stariq 	return (tot);
473c7158ae9Stariq }
474c7158ae9Stariq 
475c7158ae9Stariq static void
xdt_init_trace_masks(void)476c7158ae9Stariq xdt_init_trace_masks(void)
477c7158ae9Stariq {
478c7158ae9Stariq 	xdt_classinfo[XDT_SCHED].trc_mask = TRC_SCHED;
479c7158ae9Stariq 	xdt_classinfo[XDT_MEM].trc_mask = TRC_MEM;
480c7158ae9Stariq 	xdt_classinfo[XDT_HVM].trc_mask = TRC_HVM;
481349b53ddSStuart Maybee 	xdt_classinfo[XDT_GEN].trc_mask = TRC_GEN;
48255f5292cSFrank Van Der Linden 	xdt_classinfo[XDT_PV].trc_mask = TRC_PV;
48355f5292cSFrank Van Der Linden 	xdt_classinfo[XDT_SHADOW].trc_mask = TRC_SHADOW;
48455f5292cSFrank Van Der Linden 	xdt_classinfo[XDT_PM].trc_mask = TRC_PM;
485c7158ae9Stariq }
486c7158ae9Stariq 
487c7158ae9Stariq static int
xdt_kstat_update(kstat_t * ksp,int flag)488c7158ae9Stariq xdt_kstat_update(kstat_t *ksp, int flag)
489c7158ae9Stariq {
490c7158ae9Stariq 	kstat_named_t *knp;
491c7158ae9Stariq 
492c7158ae9Stariq 	if (flag != KSTAT_READ)
493c7158ae9Stariq 		return (EACCES);
494c7158ae9Stariq 
495c7158ae9Stariq 	knp = ksp->ks_data;
496c7158ae9Stariq 
497c7158ae9Stariq 	/*
498c7158ae9Stariq 	 * Assignment order should match that of the names in
499c7158ae9Stariq 	 * xdt_stats.
500c7158ae9Stariq 	 */
501c7158ae9Stariq 	(knp++)->value.ui64 = tbuf.stat_dropped_recs;
502c7158ae9Stariq 
503c7158ae9Stariq 	return (0);
504c7158ae9Stariq }
505c7158ae9Stariq 
506c7158ae9Stariq static void
xdt_kstat_init(void)507c7158ae9Stariq xdt_kstat_init(void)
508c7158ae9Stariq {
509c7158ae9Stariq 	int nstats = sizeof (xdt_stats) / sizeof (xdt_stats[0]);
510c7158ae9Stariq 	char **cp = xdt_stats;
511c7158ae9Stariq 	kstat_named_t *knp;
512c7158ae9Stariq 
513c7158ae9Stariq 	if ((xdt_kstats = kstat_create("xdt", 0, "trace_statistics", "misc",
514c7158ae9Stariq 	    KSTAT_TYPE_NAMED, nstats, 0)) == NULL)
515c7158ae9Stariq 		return;
516c7158ae9Stariq 
517c7158ae9Stariq 	xdt_kstats->ks_update = xdt_kstat_update;
518c7158ae9Stariq 
519c7158ae9Stariq 	knp = xdt_kstats->ks_data;
520c7158ae9Stariq 	while (nstats > 0) {
521c7158ae9Stariq 		kstat_named_init(knp, *cp, KSTAT_DATA_UINT64);
522c7158ae9Stariq 		knp++;
523c7158ae9Stariq 		cp++;
524c7158ae9Stariq 		nstats--;
525c7158ae9Stariq 	}
526c7158ae9Stariq 
527c7158ae9Stariq 	kstat_install(xdt_kstats);
528c7158ae9Stariq }
529c7158ae9Stariq 
530c7158ae9Stariq static int
xdt_sysctl_tbuf(xen_sysctl_tbuf_op_t * tbuf_op)531c7158ae9Stariq xdt_sysctl_tbuf(xen_sysctl_tbuf_op_t *tbuf_op)
532c7158ae9Stariq {
533c7158ae9Stariq 	xen_sysctl_t op;
534c7158ae9Stariq 	int xerr;
535c7158ae9Stariq 
536c7158ae9Stariq 	op.cmd = XEN_SYSCTL_tbuf_op;
537c7158ae9Stariq 	op.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
538c7158ae9Stariq 	op.u.tbuf_op = *tbuf_op;
539c7158ae9Stariq 
540c7158ae9Stariq 	if ((xerr = HYPERVISOR_sysctl(&op)) != 0)
541c7158ae9Stariq 		return (xen_xlate_errcode(xerr));
542c7158ae9Stariq 
543c7158ae9Stariq 	*tbuf_op = op.u.tbuf_op;
544c7158ae9Stariq 	return (0);
545c7158ae9Stariq }
546c7158ae9Stariq 
547c7158ae9Stariq static int
xdt_map_trace_buffers(mfn_t mfn,caddr_t va,size_t len)548c7158ae9Stariq xdt_map_trace_buffers(mfn_t mfn, caddr_t va, size_t len)
549c7158ae9Stariq {
550c7158ae9Stariq 	x86pte_t pte;
551c7158ae9Stariq 	caddr_t const sva = va;
552c7158ae9Stariq 	caddr_t const eva = va + len;
553c7158ae9Stariq 	int xerr;
554c7158ae9Stariq 
555c7158ae9Stariq 	ASSERT(mfn != MFN_INVALID);
556c7158ae9Stariq 	ASSERT(va != NULL);
557c7158ae9Stariq 	ASSERT(IS_PAGEALIGNED(len));
558c7158ae9Stariq 
559c7158ae9Stariq 	for (; va < eva; va += MMU_PAGESIZE) {
560c7158ae9Stariq 		/*
561c7158ae9Stariq 		 * Ask the HAT to load a throwaway mapping to page zero, then
562c7158ae9Stariq 		 * overwrite it with the hypervisor mapping. It gets removed
563c7158ae9Stariq 		 * later via hat_unload().
564c7158ae9Stariq 		 */
565c7158ae9Stariq 		hat_devload(kas.a_hat, va, MMU_PAGESIZE, (pfn_t)0,
566c7158ae9Stariq 		    PROT_READ | HAT_UNORDERED_OK,
567c7158ae9Stariq 		    HAT_LOAD_NOCONSIST | HAT_LOAD);
568c7158ae9Stariq 
569c7158ae9Stariq 		pte = mmu_ptob((x86pte_t)mfn) | PT_VALID | PT_USER
570c7158ae9Stariq 		    | PT_FOREIGN | PT_WRITABLE;
571c7158ae9Stariq 
572c7158ae9Stariq 		xerr = HYPERVISOR_update_va_mapping_otherdomain((ulong_t)va,
573c7158ae9Stariq 		    pte, UVMF_INVLPG | UVMF_LOCAL, DOMID_XEN);
574c7158ae9Stariq 
575c7158ae9Stariq 		if (xerr != 0) {
576c7158ae9Stariq 			/* unmap pages loaded so far */
577c7158ae9Stariq 			size_t ulen = (uintptr_t)(va + MMU_PAGESIZE) -
578c7158ae9Stariq 			    (uintptr_t)sva;
579c7158ae9Stariq 			hat_unload(kas.a_hat, sva, ulen, HAT_UNLOAD_UNMAP);
580c7158ae9Stariq 			return (xen_xlate_errcode(xerr));
581c7158ae9Stariq 		}
582c7158ae9Stariq 
583c7158ae9Stariq 		mfn++;
584c7158ae9Stariq 	}
585c7158ae9Stariq 
586c7158ae9Stariq 	return (0);
587c7158ae9Stariq }
588c7158ae9Stariq 
589c7158ae9Stariq static int
xdt_attach_trace_buffers(void)590c7158ae9Stariq xdt_attach_trace_buffers(void)
591c7158ae9Stariq {
592c7158ae9Stariq 	xen_sysctl_tbuf_op_t tbuf_op;
593c7158ae9Stariq 	size_t len;
594c7158ae9Stariq 	int err;
595c7158ae9Stariq 	uint_t i;
596c7158ae9Stariq 
597411e7d8fSTariq Magdon-Ismail 	/*
598411e7d8fSTariq Magdon-Ismail 	 * Xen does not support trace buffer re-sizing. If the buffers
599411e7d8fSTariq Magdon-Ismail 	 * have already been allocated we just use them as is.
600411e7d8fSTariq Magdon-Ismail 	 */
601c7158ae9Stariq 	tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_get_info;
602c7158ae9Stariq 	if ((err = xdt_sysctl_tbuf(&tbuf_op)) != 0)
603c7158ae9Stariq 		return (err);
604c7158ae9Stariq 
605411e7d8fSTariq Magdon-Ismail 	if (tbuf_op.size == 0) {
606411e7d8fSTariq Magdon-Ismail 		/* set trace buffer size */
607411e7d8fSTariq Magdon-Ismail 		tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_set_size;
608411e7d8fSTariq Magdon-Ismail 		tbuf_op.size = xdt_tbuf_pages;
609411e7d8fSTariq Magdon-Ismail 		(void) xdt_sysctl_tbuf(&tbuf_op);
610411e7d8fSTariq Magdon-Ismail 
611411e7d8fSTariq Magdon-Ismail 		/* get trace buffer info */
612411e7d8fSTariq Magdon-Ismail 		tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_get_info;
613411e7d8fSTariq Magdon-Ismail 		if ((err = xdt_sysctl_tbuf(&tbuf_op)) != 0)
614411e7d8fSTariq Magdon-Ismail 			return (err);
615411e7d8fSTariq Magdon-Ismail 
616411e7d8fSTariq Magdon-Ismail 		if (tbuf_op.size == 0) {
617411e7d8fSTariq Magdon-Ismail 			cmn_err(CE_NOTE, "Couldn't allocate trace buffers.");
618411e7d8fSTariq Magdon-Ismail 			return (ENOBUFS);
619411e7d8fSTariq Magdon-Ismail 		}
620411e7d8fSTariq Magdon-Ismail 	}
621411e7d8fSTariq Magdon-Ismail 
622c7158ae9Stariq 	tbuf.size = tbuf_op.size;
623c7158ae9Stariq 	tbuf.start_mfn = (mfn_t)tbuf_op.buffer_mfn;
624c7158ae9Stariq 	tbuf.cnt = xdt_ncpus;
625c7158ae9Stariq 
626c7158ae9Stariq 	ASSERT(tbuf.start_mfn != MFN_INVALID);
627c7158ae9Stariq 	ASSERT(tbuf.cnt > 0);
628c7158ae9Stariq 
629c7158ae9Stariq 	len = tbuf.size * tbuf.cnt;
630c7158ae9Stariq 	tbuf.va = vmem_alloc(heap_arena, len, VM_SLEEP);
631c7158ae9Stariq 
632c7158ae9Stariq 	if ((err = xdt_map_trace_buffers(tbuf.start_mfn, tbuf.va, len)) != 0) {
633c7158ae9Stariq 		vmem_free(heap_arena, tbuf.va, len);
634c7158ae9Stariq 		tbuf.va = NULL;
635c7158ae9Stariq 		return (err);
636c7158ae9Stariq 	}
637c7158ae9Stariq 
638c7158ae9Stariq 	tbuf.meta = (struct t_buf **)kmem_alloc(tbuf.cnt * sizeof (*tbuf.meta),
639c7158ae9Stariq 	    KM_SLEEP);
640c7158ae9Stariq 	tbuf.data = (struct t_rec **)kmem_alloc(tbuf.cnt * sizeof (*tbuf.data),
641c7158ae9Stariq 	    KM_SLEEP);
642c7158ae9Stariq 
643c7158ae9Stariq 	for (i = 0; i < tbuf.cnt; i++) {
644c7158ae9Stariq 		void *cpu_buf = (void *)(tbuf.va + (tbuf.size * i));
645c7158ae9Stariq 		tbuf.meta[i] = cpu_buf;
646c7158ae9Stariq 		tbuf.data[i] = (struct t_rec *)((uintptr_t)cpu_buf +
647c7158ae9Stariq 		    sizeof (struct t_buf));
648c7158ae9Stariq 
649c7158ae9Stariq 		/* throw away stale trace records */
650c7158ae9Stariq 		tbuf.meta[i]->cons = tbuf.meta[i]->prod;
651c7158ae9Stariq 	}
652c7158ae9Stariq 
65355f5292cSFrank Van Der Linden 	tbuf_data_size = tbuf.size - sizeof (struct t_buf);
65455f5292cSFrank Van Der Linden 	if (xdt_max_recs == 0)
65555f5292cSFrank Van Der Linden 		xdt_max_recs = (xdt_ncpus * tbuf_data_size)
65655f5292cSFrank Van Der Linden 		    / sizeof (struct t_rec);
65755f5292cSFrank Van Der Linden 
658c7158ae9Stariq 	return (0);
659c7158ae9Stariq }
660c7158ae9Stariq 
661c7158ae9Stariq static void
xdt_detach_trace_buffers(void)662c7158ae9Stariq xdt_detach_trace_buffers(void)
663c7158ae9Stariq {
664c7158ae9Stariq 	size_t len = tbuf.size * tbuf.cnt;
665c7158ae9Stariq 
666c7158ae9Stariq 	ASSERT(tbuf.va != NULL);
667c7158ae9Stariq 
668c7158ae9Stariq 	hat_unload(kas.a_hat, tbuf.va, len,
669c7158ae9Stariq 	    HAT_UNLOAD_UNMAP | HAT_UNLOAD_UNLOCK);
670c7158ae9Stariq 	vmem_free(heap_arena, tbuf.va, len);
671c7158ae9Stariq 	kmem_free(tbuf.meta, tbuf.cnt * sizeof (*tbuf.meta));
672c7158ae9Stariq 	kmem_free(tbuf.data, tbuf.cnt * sizeof (*tbuf.data));
673c7158ae9Stariq }
674c7158ae9Stariq 
67555f5292cSFrank Van Der Linden static void
xdt_update_sched_context(uint_t cpuid,uint_t dom,uint_t vcpu)67655f5292cSFrank Van Der Linden xdt_update_sched_context(uint_t cpuid, uint_t dom, uint_t vcpu)
67755f5292cSFrank Van Der Linden {
67855f5292cSFrank Van Der Linden 	xdt_schedinfo_t *sp = &xdt_cpu_schedinfo[cpuid];
67955f5292cSFrank Van Der Linden 
68055f5292cSFrank Van Der Linden 	sp->cur_domid = dom;
68155f5292cSFrank Van Der Linden 	sp->cur_vcpuid = vcpu;
68255f5292cSFrank Van Der Linden 	sp->curinfo_valid = 1;
68355f5292cSFrank Van Der Linden }
68455f5292cSFrank Van Der Linden 
68555f5292cSFrank Van Der Linden static void
xdt_update_domain_context(uint_t dom,uint_t vcpu)68655f5292cSFrank Van Der Linden xdt_update_domain_context(uint_t dom, uint_t vcpu)
68755f5292cSFrank Van Der Linden {
68855f5292cSFrank Van Der Linden 	xdt_curdom = dom;
68955f5292cSFrank Van Der Linden 	xdt_curvcpu = vcpu;
69055f5292cSFrank Van Der Linden }
69155f5292cSFrank Van Der Linden 
69255f5292cSFrank Van Der Linden static size_t
xdt_process_rec(uint_t cpuid,struct t_rec * rec)693c7158ae9Stariq xdt_process_rec(uint_t cpuid, struct t_rec *rec)
694c7158ae9Stariq {
695c7158ae9Stariq 	xdt_schedinfo_t *sp = &xdt_cpu_schedinfo[cpuid];
69655f5292cSFrank Van Der Linden 	uint_t dom, vcpu;
697c7158ae9Stariq 	int eid;
698349b53ddSStuart Maybee 	uint32_t *data;
69955f5292cSFrank Van Der Linden 	uint64_t tsc, addr64, rip64, val64, pte64;
700349b53ddSStuart Maybee 	size_t rec_size;
701c7158ae9Stariq 
702c7158ae9Stariq 	ASSERT(rec != NULL);
703349b53ddSStuart Maybee 	ASSERT(xdt_ncpus == xpv_nr_phys_cpus());
704c7158ae9Stariq 
705*2a9992ecSToomas Soome 	eid = 0;
706c7158ae9Stariq 	if (cpuid >= xdt_ncpus) {
707c7158ae9Stariq 		tbuf.stat_spurious_cpu++;
708349b53ddSStuart Maybee 		goto done;
709c7158ae9Stariq 	}
710c7158ae9Stariq 
71155f5292cSFrank Van Der Linden 	/*
71255f5292cSFrank Van Der Linden 	 * If our current state isn't valid, and if this is not
71355f5292cSFrank Van Der Linden 	 * an event that will update our state, skip it.
71455f5292cSFrank Van Der Linden 	 */
71555f5292cSFrank Van Der Linden 
71655f5292cSFrank Van Der Linden 	if (!sp->curinfo_valid &&
71755f5292cSFrank Van Der Linden 	    rec->event != TRC_SCHED_SWITCH &&
71855f5292cSFrank Van Der Linden 	    rec->event != TRC_LOST_RECORDS)
71955f5292cSFrank Van Der Linden 		goto done;
72055f5292cSFrank Van Der Linden 
72155f5292cSFrank Van Der Linden 	if (rec->cycles_included) {
72255f5292cSFrank Van Der Linden 		data = rec->u.cycles.extra_u32;
72355f5292cSFrank Van Der Linden 		tsc = (((uint64_t)rec->u.cycles.cycles_hi) << 32)
72455f5292cSFrank Van Der Linden 		    | rec->u.cycles.cycles_lo;
72555f5292cSFrank Van Der Linden 	} else {
72655f5292cSFrank Van Der Linden 		data = rec->u.nocycles.extra_u32;
72755f5292cSFrank Van Der Linden 		tsc = 0;
72855f5292cSFrank Van Der Linden 	}
72955f5292cSFrank Van Der Linden 
73055f5292cSFrank Van Der Linden 	xdt_timestamp = tsc;
731c7158ae9Stariq 
732349b53ddSStuart Maybee 	switch (rec->event) {
733c7158ae9Stariq 	/*
734c7158ae9Stariq 	 * Sched probes
735c7158ae9Stariq 	 */
736c7158ae9Stariq 	case TRC_SCHED_SWITCH_INFPREV:
737c7158ae9Stariq 		/*
738c7158ae9Stariq 		 * Info on vCPU being de-scheduled
739c7158ae9Stariq 		 *
740349b53ddSStuart Maybee 		 * data[0] = prev domid
741349b53ddSStuart Maybee 		 * data[1] = time spent on pcpu
742c7158ae9Stariq 		 */
743349b53ddSStuart Maybee 		sp->prev_domid = data[0];
744349b53ddSStuart Maybee 		sp->prev_ctime = data[1];
745c7158ae9Stariq 		break;
746c7158ae9Stariq 
747c7158ae9Stariq 	case TRC_SCHED_SWITCH_INFNEXT:
748c7158ae9Stariq 		/*
749c7158ae9Stariq 		 * Info on next vCPU to be scheduled
750c7158ae9Stariq 		 *
751349b53ddSStuart Maybee 		 * data[0] = next domid
752349b53ddSStuart Maybee 		 * data[1] = time spent waiting to get on cpu
753349b53ddSStuart Maybee 		 * data[2] = time slice
754c7158ae9Stariq 		 */
755349b53ddSStuart Maybee 		sp->next_domid = data[0];
756349b53ddSStuart Maybee 		sp->next_wtime = data[1];
757349b53ddSStuart Maybee 		sp->next_ts = data[2];
758c7158ae9Stariq 		break;
759c7158ae9Stariq 
760c7158ae9Stariq 	case TRC_SCHED_SWITCH:
761c7158ae9Stariq 		/*
762c7158ae9Stariq 		 * vCPU switch
763c7158ae9Stariq 		 *
764349b53ddSStuart Maybee 		 * data[0] = prev domid
765349b53ddSStuart Maybee 		 * data[1] = prev vcpuid
766349b53ddSStuart Maybee 		 * data[2] = next domid
767349b53ddSStuart Maybee 		 * data[3] = next vcpuid
768c7158ae9Stariq 		 */
76955f5292cSFrank Van Der Linden 
77055f5292cSFrank Van Der Linden 		/*
77155f5292cSFrank Van Der Linden 		 * Provide valid context for this probe if there
77255f5292cSFrank Van Der Linden 		 * wasn't one.
77355f5292cSFrank Van Der Linden 		 */
77455f5292cSFrank Van Der Linden 		if (!sp->curinfo_valid)
77555f5292cSFrank Van Der Linden 			xdt_update_domain_context(data[0], data[1]);
77655f5292cSFrank Van Der Linden 
77755f5292cSFrank Van Der Linden 		xdt_update_sched_context(cpuid, data[0], data[1]);
77855f5292cSFrank Van Der Linden 
779349b53ddSStuart Maybee 		if (data[0] != sp->prev_domid &&
780349b53ddSStuart Maybee 		    data[2] != sp->next_domid) {
781c7158ae9Stariq 			/* prev and next info don't match doms being sched'd */
782c7158ae9Stariq 			tbuf.stat_spurious_switch++;
78355f5292cSFrank Van Der Linden 			goto switchdone;
784c7158ae9Stariq 		}
785c7158ae9Stariq 
786349b53ddSStuart Maybee 		sp->prev_vcpuid = data[1];
787349b53ddSStuart Maybee 		sp->next_vcpuid = data[3];
788c7158ae9Stariq 
789c7158ae9Stariq 		XDT_PROBE3(IS_IDLE_DOM(sp->prev_domid)?
790c7158ae9Stariq 		    XDT_SCHED_IDLE_OFF_CPU:XDT_SCHED_OFF_CPU,
79155f5292cSFrank Van Der Linden 		    sp->prev_domid, sp->prev_vcpuid, sp->prev_ctime);
792c7158ae9Stariq 
793c7158ae9Stariq 		XDT_PROBE4(IS_IDLE_DOM(sp->next_domid)?
794c7158ae9Stariq 		    XDT_SCHED_IDLE_ON_CPU:XDT_SCHED_ON_CPU,
79555f5292cSFrank Van Der Linden 		    sp->next_domid, sp->next_vcpuid, sp->next_wtime,
796c7158ae9Stariq 		    sp->next_ts);
79755f5292cSFrank Van Der Linden switchdone:
79855f5292cSFrank Van Der Linden 		xdt_update_sched_context(cpuid, data[2], data[3]);
79955f5292cSFrank Van Der Linden 		xdt_update_domain_context(data[2], data[3]);
80055f5292cSFrank Van Der Linden 
801c7158ae9Stariq 		break;
802c7158ae9Stariq 
803c7158ae9Stariq 	case TRC_SCHED_BLOCK:
804c7158ae9Stariq 		/*
805c7158ae9Stariq 		 * vCPU blocked
806c7158ae9Stariq 		 *
807349b53ddSStuart Maybee 		 * data[0] = domid
808349b53ddSStuart Maybee 		 * data[1] = vcpuid
809c7158ae9Stariq 		 */
81055f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_SCHED_BLOCK, data[0], data[1]);
811c7158ae9Stariq 		break;
812c7158ae9Stariq 
813c7158ae9Stariq 	case TRC_SCHED_SLEEP:
814c7158ae9Stariq 		/*
815c7158ae9Stariq 		 * Put vCPU to sleep
816c7158ae9Stariq 		 *
817349b53ddSStuart Maybee 		 * data[0] = domid
818349b53ddSStuart Maybee 		 * data[1] = vcpuid
819c7158ae9Stariq 		 */
82055f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_SCHED_SLEEP, data[0], data[1]);
821c7158ae9Stariq 		break;
822c7158ae9Stariq 
823c7158ae9Stariq 	case TRC_SCHED_WAKE:
824c7158ae9Stariq 		/*
825c7158ae9Stariq 		 * Wake up vCPU
826c7158ae9Stariq 		 *
827349b53ddSStuart Maybee 		 * data[0] = domid
828349b53ddSStuart Maybee 		 * data[1] = vcpuid
829c7158ae9Stariq 		 */
83055f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_SCHED_WAKE, data[0], data[1]);
831c7158ae9Stariq 		break;
832c7158ae9Stariq 
833c7158ae9Stariq 	case TRC_SCHED_YIELD:
834c7158ae9Stariq 		/*
835c7158ae9Stariq 		 * vCPU yielded
836c7158ae9Stariq 		 *
837349b53ddSStuart Maybee 		 * data[0] = domid
838349b53ddSStuart Maybee 		 * data[1] = vcpuid
839c7158ae9Stariq 		 */
84055f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_SCHED_YIELD, data[0], data[1]);
841c7158ae9Stariq 		break;
842c7158ae9Stariq 
843c7158ae9Stariq 	case TRC_SCHED_SHUTDOWN:
844c7158ae9Stariq 		/*
845c7158ae9Stariq 		 * Guest shutting down
846c7158ae9Stariq 		 *
847349b53ddSStuart Maybee 		 * data[0] = domid
848349b53ddSStuart Maybee 		 * data[1] = initiating vcpu
849349b53ddSStuart Maybee 		 * data[2] = shutdown code
850c7158ae9Stariq 		 */
851349b53ddSStuart Maybee 		switch (data[2]) {
852c7158ae9Stariq 		case SHUTDOWN_poweroff:
853c7158ae9Stariq 			eid = XDT_SCHED_SHUTDOWN_POWEROFF;
854c7158ae9Stariq 			break;
855c7158ae9Stariq 		case SHUTDOWN_reboot:
856c7158ae9Stariq 			eid = XDT_SCHED_SHUTDOWN_REBOOT;
857c7158ae9Stariq 			break;
858c7158ae9Stariq 		case SHUTDOWN_suspend:
859c7158ae9Stariq 			eid = XDT_SCHED_SHUTDOWN_SUSPEND;
860c7158ae9Stariq 			break;
861c7158ae9Stariq 		case SHUTDOWN_crash:
862c7158ae9Stariq 			eid = XDT_SCHED_SHUTDOWN_CRASH;
863c7158ae9Stariq 			break;
864c7158ae9Stariq 		default:
865c7158ae9Stariq 			tbuf.stat_unknown_shutdown++;
866349b53ddSStuart Maybee 			goto done;
867c7158ae9Stariq 		}
868c7158ae9Stariq 
86955f5292cSFrank Van Der Linden 		XDT_PROBE2(eid, data[0], data[1]);
870c7158ae9Stariq 		break;
871c7158ae9Stariq 
87255f5292cSFrank Van Der Linden 	case TRC_SCHED_DOM_REM:
87355f5292cSFrank Van Der Linden 	case TRC_SCHED_CTL:
87455f5292cSFrank Van Der Linden 	case TRC_SCHED_S_TIMER_FN:
87555f5292cSFrank Van Der Linden 	case TRC_SCHED_T_TIMER_FN:
87655f5292cSFrank Van Der Linden 	case TRC_SCHED_DOM_TIMER_FN:
87755f5292cSFrank Van Der Linden 		/* unused */
87855f5292cSFrank Van Der Linden 		break;
87955f5292cSFrank Van Der Linden 	case TRC_SCHED_DOM_ADD:
88055f5292cSFrank Van Der Linden 		/*
88155f5292cSFrank Van Der Linden 		 * Add vcpu to a guest.
88255f5292cSFrank Van Der Linden 		 *
88355f5292cSFrank Van Der Linden 		 * data[0] = domid
88455f5292cSFrank Van Der Linden 		 * data[1] = vcpu
88555f5292cSFrank Van Der Linden 		 */
88655f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_SCHED_ADD_VCPU, data[0], data[1]);
88755f5292cSFrank Van Der Linden 		break;
88855f5292cSFrank Van Der Linden 	case TRC_SCHED_ADJDOM:
88955f5292cSFrank Van Der Linden 		/*
89055f5292cSFrank Van Der Linden 		 * Scheduling parameters for a guest
89155f5292cSFrank Van Der Linden 		 * were modified.
89255f5292cSFrank Van Der Linden 		 *
89355f5292cSFrank Van Der Linden 		 * data[0] = domid;
89455f5292cSFrank Van Der Linden 		 */
89555f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_SCHED_ADJDOM, data[1]);
89655f5292cSFrank Van Der Linden 		break;
89755f5292cSFrank Van Der Linden 	case TRC_SCHED_RUNSTATE_CHANGE:
89855f5292cSFrank Van Der Linden 		/*
89955f5292cSFrank Van Der Linden 		 * Runstate change for a VCPU.
90055f5292cSFrank Van Der Linden 		 *
90155f5292cSFrank Van Der Linden 		 * data[0] = (domain << 16) | vcpu;
90255f5292cSFrank Van Der Linden 		 * data[1] = oldstate;
90355f5292cSFrank Van Der Linden 		 * data[2] = newstate;
90455f5292cSFrank Van Der Linden 		 */
90555f5292cSFrank Van Der Linden 		XDT_PROBE4(XDT_SCHED_RUNSTATE_CHANGE, data[0] >> 16,
90655f5292cSFrank Van Der Linden 		    data[0] & 0xffff, data[1], data[2]);
90755f5292cSFrank Van Der Linden 		break;
90855f5292cSFrank Van Der Linden 	case TRC_SCHED_CONTINUE_RUNNING:
90955f5292cSFrank Van Der Linden 		/*
91055f5292cSFrank Van Der Linden 		 * VCPU is back on a physical CPU that it previously
91155f5292cSFrank Van Der Linden 		 * was also running this VCPU.
91255f5292cSFrank Van Der Linden 		 *
91355f5292cSFrank Van Der Linden 		 * data[0] = (domain << 16) | vcpu;
91455f5292cSFrank Van Der Linden 		 */
91555f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_SCHED_CONTINUE_RUNNING, data[0] >> 16,
91655f5292cSFrank Van Der Linden 		    data[0] & 0xffff);
91755f5292cSFrank Van Der Linden 		break;
918c7158ae9Stariq 	/*
919c7158ae9Stariq 	 * Mem probes
920c7158ae9Stariq 	 */
921c7158ae9Stariq 	case TRC_MEM_PAGE_GRANT_MAP:
922c7158ae9Stariq 		/*
923c7158ae9Stariq 		 * Guest mapped page grant
924c7158ae9Stariq 		 *
92555f5292cSFrank Van Der Linden 		 * data[0] = target domid
926c7158ae9Stariq 		 */
92755f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_MEM_PAGE_GRANT_MAP, data[0]);
928c7158ae9Stariq 		break;
929c7158ae9Stariq 
930c7158ae9Stariq 	case TRC_MEM_PAGE_GRANT_UNMAP:
931c7158ae9Stariq 		/*
932c7158ae9Stariq 		 * Guest unmapped page grant
933c7158ae9Stariq 		 *
93455f5292cSFrank Van Der Linden 		 * data[0] = target domid
935c7158ae9Stariq 		 */
93655f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_MEM_PAGE_GRANT_UNMAP, data[0]);
937c7158ae9Stariq 		break;
938c7158ae9Stariq 
939c7158ae9Stariq 	case TRC_MEM_PAGE_GRANT_TRANSFER:
940c7158ae9Stariq 		/*
941c7158ae9Stariq 		 * Page grant is being transferred
942c7158ae9Stariq 		 *
943349b53ddSStuart Maybee 		 * data[0] = target domid
944c7158ae9Stariq 		 */
94555f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_MEM_PAGE_GRANT_TRANSFER, data[0]);
94655f5292cSFrank Van Der Linden 		break;
94755f5292cSFrank Van Der Linden 
94855f5292cSFrank Van Der Linden 	/*
94955f5292cSFrank Van Der Linden 	 * Probes for PV domains.
95055f5292cSFrank Van Der Linden 	 */
95155f5292cSFrank Van Der Linden 	case TRC_PV_HYPERCALL:
95255f5292cSFrank Van Der Linden 		/*
95355f5292cSFrank Van Der Linden 		 * Hypercall from a 32-bit PV domain.
95455f5292cSFrank Van Der Linden 		 *
95555f5292cSFrank Van Der Linden 		 * data[0] = eip
95655f5292cSFrank Van Der Linden 		 * data[1] = eax
95755f5292cSFrank Van Der Linden 		 */
95855f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_PV_HYPERCALL, data[0], data[1]);
95955f5292cSFrank Van Der Linden 		break;
96055f5292cSFrank Van Der Linden 	case TRC_PV_HYPERCALL | TRC_64_FLAG:
96155f5292cSFrank Van Der Linden 		/*
96255f5292cSFrank Van Der Linden 		 * Hypercall from a 64-bit PV domain.
96355f5292cSFrank Van Der Linden 		 *
96455f5292cSFrank Van Der Linden 		 * data[0] = rip(0:31)
96555f5292cSFrank Van Der Linden 		 * data[1] = rip(32:63)
96655f5292cSFrank Van Der Linden 		 * data[2] = eax;
96755f5292cSFrank Van Der Linden 		 */
96855f5292cSFrank Van Der Linden 		rip64 = (((uint64_t)data[1]) << 32) | data[0];
96955f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_PV_HYPERCALL, rip64, data[2]);
97055f5292cSFrank Van Der Linden 		break;
97155f5292cSFrank Van Der Linden 	case TRC_PV_TRAP:
97255f5292cSFrank Van Der Linden 		/*
97355f5292cSFrank Van Der Linden 		 * Trap in a 32-bit PV domain.
97455f5292cSFrank Van Der Linden 		 *
97555f5292cSFrank Van Der Linden 		 * data[0] = eip
97655f5292cSFrank Van Der Linden 		 * data[1] = trapnr | (error_code_valid << 15)
977*2a9992ecSToomas Soome 		 *	| (error_code << 16);
97855f5292cSFrank Van Der Linden 		 */
97955f5292cSFrank Van Der Linden 		XDT_PROBE4(XDT_PV_TRAP, data[0], data[1] & 0x7fff,
98055f5292cSFrank Van Der Linden 		    (data[1] >> 15) & 1, data[1] >> 16);
98155f5292cSFrank Van Der Linden 		break;
98255f5292cSFrank Van Der Linden 	case TRC_PV_TRAP | TRC_64_FLAG:
98355f5292cSFrank Van Der Linden 		/*
98455f5292cSFrank Van Der Linden 		 * Trap in a 64-bit PV domain.
98555f5292cSFrank Van Der Linden 		 *
98655f5292cSFrank Van Der Linden 		 * data[0] = rip(0:31)
98755f5292cSFrank Van Der Linden 		 * data[1] = rip(32:63)
98855f5292cSFrank Van Der Linden 		 * data[2] = trapnr | (error_code_valid << 15)
989*2a9992ecSToomas Soome 		 *	| (error_code << 16);
99055f5292cSFrank Van Der Linden 		 */
99155f5292cSFrank Van Der Linden 		rip64 = (((uint64_t)data[1]) << 32) | data[2];
99255f5292cSFrank Van Der Linden 		XDT_PROBE4(XDT_PV_TRAP, rip64, data[2] & 0x7fff,
99355f5292cSFrank Van Der Linden 		    (data[2] >> 15) & 1, data[2] >> 16);
99455f5292cSFrank Van Der Linden 		break;
99555f5292cSFrank Van Der Linden 	case TRC_PV_PAGE_FAULT:
99655f5292cSFrank Van Der Linden 		/*
99755f5292cSFrank Van Der Linden 		 * Page fault in a 32-bit PV domain.
99855f5292cSFrank Van Der Linden 		 *
99955f5292cSFrank Van Der Linden 		 * data[0] = eip
100055f5292cSFrank Van Der Linden 		 * data[1] = vaddr
100155f5292cSFrank Van Der Linden 		 * data[2] = error code
100255f5292cSFrank Van Der Linden 		 */
100355f5292cSFrank Van Der Linden 		XDT_PROBE3(XDT_PV_PAGE_FAULT, data[0], data[1], data[2]);
100455f5292cSFrank Van Der Linden 		break;
100555f5292cSFrank Van Der Linden 	case TRC_PV_PAGE_FAULT | TRC_64_FLAG:
100655f5292cSFrank Van Der Linden 		/*
100755f5292cSFrank Van Der Linden 		 * Page fault in a 32-bit PV domain.
100855f5292cSFrank Van Der Linden 		 *
100955f5292cSFrank Van Der Linden 		 * data[0] = rip(0:31)
101055f5292cSFrank Van Der Linden 		 * data[1] = rip(31:63)
101155f5292cSFrank Van Der Linden 		 * data[2] = vaddr(0:31)
101255f5292cSFrank Van Der Linden 		 * data[3] = vaddr(31:63)
101355f5292cSFrank Van Der Linden 		 * data[4] = error code
101455f5292cSFrank Van Der Linden 		 */
101555f5292cSFrank Van Der Linden 		rip64 = (((uint64_t)data[1]) << 32) | data[0];
101655f5292cSFrank Van Der Linden 		addr64 = (((uint64_t)data[3]) << 32) | data[2];
101755f5292cSFrank Van Der Linden 		XDT_PROBE3(XDT_PV_PAGE_FAULT, rip64, addr64, data[4]);
101855f5292cSFrank Van Der Linden 		break;
101955f5292cSFrank Van Der Linden 	case TRC_PV_FORCED_INVALID_OP:
102055f5292cSFrank Van Der Linden 		/*
102155f5292cSFrank Van Der Linden 		 * Hypervisor emulated a forced invalid op (ud2)
102255f5292cSFrank Van Der Linden 		 * in a 32-bit PV domain.
102355f5292cSFrank Van Der Linden 		 *
102455f5292cSFrank Van Der Linden 		 * data[1] = eip
102555f5292cSFrank Van Der Linden 		 */
102655f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_PV_FORCED_INVALID_OP, data[1]);
102755f5292cSFrank Van Der Linden 		break;
102855f5292cSFrank Van Der Linden 	case TRC_PV_FORCED_INVALID_OP | TRC_64_FLAG:
102955f5292cSFrank Van Der Linden 		/*
103055f5292cSFrank Van Der Linden 		 * Hypervisor emulated a forced invalid op (ud2)
103155f5292cSFrank Van Der Linden 		 * in a 64-bit PV domain.
103255f5292cSFrank Van Der Linden 		 *
103355f5292cSFrank Van Der Linden 		 * data[1] = rip(0:31)
103455f5292cSFrank Van Der Linden 		 * data[2] = rip(31:63)
103555f5292cSFrank Van Der Linden 		 *
103655f5292cSFrank Van Der Linden 		 */
103755f5292cSFrank Van Der Linden 		rip64 = (((uint64_t)data[2]) << 32) | data[1];
103855f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_PV_FORCED_INVALID_OP, rip64);
103955f5292cSFrank Van Der Linden 		break;
104055f5292cSFrank Van Der Linden 	case TRC_PV_EMULATE_PRIVOP:
104155f5292cSFrank Van Der Linden 		/*
104255f5292cSFrank Van Der Linden 		 * Hypervisor emulated a privileged operation
104355f5292cSFrank Van Der Linden 		 * in a 32-bit PV domain.
104455f5292cSFrank Van Der Linden 		 *
104555f5292cSFrank Van Der Linden 		 * data[0] = eip
104655f5292cSFrank Van Der Linden 		 */
104755f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_PV_EMULATE_PRIVOP, data[0]);
104855f5292cSFrank Van Der Linden 		break;
104955f5292cSFrank Van Der Linden 	case TRC_PV_EMULATE_PRIVOP | TRC_64_FLAG:
105055f5292cSFrank Van Der Linden 		/*
105155f5292cSFrank Van Der Linden 		 * Hypervisor emulated a privileged operation
105255f5292cSFrank Van Der Linden 		 * in a 64-bit PV domain.
105355f5292cSFrank Van Der Linden 		 *
105455f5292cSFrank Van Der Linden 		 * data[0] = rip(0:31)
105555f5292cSFrank Van Der Linden 		 * data[1] = rip(31:63)
105655f5292cSFrank Van Der Linden 		 */
105755f5292cSFrank Van Der Linden 		rip64 = (((uint64_t)data[1]) << 32) | data[0];
105855f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_PV_EMULATE_PRIVOP, rip64);
105955f5292cSFrank Van Der Linden 		break;
106055f5292cSFrank Van Der Linden 	case TRC_PV_EMULATE_4GB:
106155f5292cSFrank Van Der Linden 		/* unused, 32-bit hypervisor only */
106255f5292cSFrank Van Der Linden 		break;
106355f5292cSFrank Van Der Linden 	case TRC_PV_MATH_STATE_RESTORE:
106455f5292cSFrank Van Der Linden 		/*
106555f5292cSFrank Van Der Linden 		 * Hypervisor restores math state after FP DNA trap.
106655f5292cSFrank Van Der Linden 		 *
106755f5292cSFrank Van Der Linden 		 * No arguments.
106855f5292cSFrank Van Der Linden 		 */
106955f5292cSFrank Van Der Linden 		XDT_PROBE0(XDT_PV_MATH_STATE_RESTORE);
107055f5292cSFrank Van Der Linden 		break;
107155f5292cSFrank Van Der Linden 	case TRC_PV_PAGING_FIXUP:
107255f5292cSFrank Van Der Linden 		/*
107355f5292cSFrank Van Der Linden 		 * Hypervisor fixed up a page fault (e.g. it was
107455f5292cSFrank Van Der Linden 		 * a side-effect of hypervisor guest page table
107555f5292cSFrank Van Der Linden 		 * bookkeeping, and not propagated to the guest).
107655f5292cSFrank Van Der Linden 		 *
107755f5292cSFrank Van Der Linden 		 * data[0] = eip
107855f5292cSFrank Van Der Linden 		 * data[1] = vaddr
107955f5292cSFrank Van Der Linden 		 */
108055f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_PV_PAGING_FIXUP, data[0], data[2]);
108155f5292cSFrank Van Der Linden 		break;
108255f5292cSFrank Van Der Linden 	case TRC_PV_PAGING_FIXUP | TRC_64_FLAG:
108355f5292cSFrank Van Der Linden 		/*
108455f5292cSFrank Van Der Linden 		 * Hypervisor fixed up a page fault (e.g. it was
108555f5292cSFrank Van Der Linden 		 * a side-effect of hypervisor guest page table
108655f5292cSFrank Van Der Linden 		 * bookkeeping, and not propagated to the guest).
108755f5292cSFrank Van Der Linden 		 *
108855f5292cSFrank Van Der Linden 		 * data[0] = eip(0:31)
108955f5292cSFrank Van Der Linden 		 * data[1] = eip(31:63)
109055f5292cSFrank Van Der Linden 		 * data[2] = vaddr(0:31)
109155f5292cSFrank Van Der Linden 		 * data[3] = vaddr(31:63)
109255f5292cSFrank Van Der Linden 		 */
109355f5292cSFrank Van Der Linden 		rip64 = (((uint64_t)data[1]) << 32) | data[0];
109455f5292cSFrank Van Der Linden 		addr64 = (((uint64_t)data[3]) << 32) | data[2];
109555f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_PV_PAGING_FIXUP, rip64, addr64);
109655f5292cSFrank Van Der Linden 		break;
109755f5292cSFrank Van Der Linden 	case TRC_PV_GDT_LDT_MAPPING_FAULT:
109855f5292cSFrank Van Der Linden 		/*
109955f5292cSFrank Van Der Linden 		 * Descriptor table mapping fault in a 32-bit PV domain.
110055f5292cSFrank Van Der Linden 		 * data[0] = eip
110155f5292cSFrank Van Der Linden 		 * data[1] = offset
110255f5292cSFrank Van Der Linden 		 */
110355f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_PV_DT_MAPPING_FAULT, data[0], data[1]);
110455f5292cSFrank Van Der Linden 		break;
110555f5292cSFrank Van Der Linden 	case TRC_PV_GDT_LDT_MAPPING_FAULT | TRC_64_FLAG:
110655f5292cSFrank Van Der Linden 		/*
110755f5292cSFrank Van Der Linden 		 * Descriptor table mapping fault in a 64-bit PV domain.
110855f5292cSFrank Van Der Linden 		 *
110955f5292cSFrank Van Der Linden 		 * data[0] = eip(0:31)
111055f5292cSFrank Van Der Linden 		 * data[1] = eip(31:63)
111155f5292cSFrank Van Der Linden 		 * data[2] = offset(0:31)
111255f5292cSFrank Van Der Linden 		 * data[3] = offset(31:63)
111355f5292cSFrank Van Der Linden 		 */
111455f5292cSFrank Van Der Linden 		rip64 = (((uint64_t)data[1]) << 32) | data[0];
111555f5292cSFrank Van Der Linden 		val64 = (((uint64_t)data[3]) << 32) | data[2];
111655f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_PV_DT_MAPPING_FAULT, rip64, val64);
111755f5292cSFrank Van Der Linden 		break;
111855f5292cSFrank Van Der Linden 	case TRC_PV_PTWR_EMULATION:
111955f5292cSFrank Van Der Linden 	case TRC_PV_PTWR_EMULATION_PAE | TRC_64_FLAG:
112055f5292cSFrank Van Der Linden 		/*
112155f5292cSFrank Van Der Linden 		 * Should only happen on 32-bit hypervisor; unused.
112255f5292cSFrank Van Der Linden 		 */
112355f5292cSFrank Van Der Linden 		break;
112455f5292cSFrank Van Der Linden 	case TRC_PV_PTWR_EMULATION_PAE:
112555f5292cSFrank Van Der Linden 		/*
112655f5292cSFrank Van Der Linden 		 * PTE write emulation for a 32-bit PV domain.
112755f5292cSFrank Van Der Linden 		 *
112855f5292cSFrank Van Der Linden 		 * data[0] = pte
112955f5292cSFrank Van Der Linden 		 * data[1] = addr
113055f5292cSFrank Van Der Linden 		 * data[2] = eip
113155f5292cSFrank Van Der Linden 		 */
113255f5292cSFrank Van Der Linden 		XDT_PROBE3(XDT_PV_PTWR_EMULATION, data[0], data[1], data[2]);
113355f5292cSFrank Van Der Linden 		break;
113455f5292cSFrank Van Der Linden 	case TRC_PV_PTWR_EMULATION | TRC_64_FLAG:
113555f5292cSFrank Van Der Linden 		/*
113655f5292cSFrank Van Der Linden 		 * PTE write emulation for a 64-bit PV domain.
113755f5292cSFrank Van Der Linden 		 *
113855f5292cSFrank Van Der Linden 		 * data[0] = pte(0:31)
113955f5292cSFrank Van Der Linden 		 * data[1] = pte(32:63)
114055f5292cSFrank Van Der Linden 		 * data[2] = addr(0:31)
114155f5292cSFrank Van Der Linden 		 * data[3] = addr(32:63)
114255f5292cSFrank Van Der Linden 		 * data[4] = rip(0:31)
114355f5292cSFrank Van Der Linden 		 * data[5] = rip(32:63)
114455f5292cSFrank Van Der Linden 		 */
114555f5292cSFrank Van Der Linden 		pte64 = (((uint64_t)data[1]) << 32) | data[0];
114655f5292cSFrank Van Der Linden 		addr64 = (((uint64_t)data[3]) << 32) | data[2];
114755f5292cSFrank Van Der Linden 		rip64 = (((uint64_t)data[5]) << 32) | data[4];
114855f5292cSFrank Van Der Linden 		XDT_PROBE3(XDT_PV_PTWR_EMULATION, pte64, addr64, rip64);
1149c7158ae9Stariq 		break;
1150c7158ae9Stariq 
1151c7158ae9Stariq 	/*
1152c7158ae9Stariq 	 * HVM probes
1153c7158ae9Stariq 	 */
1154c7158ae9Stariq 	case TRC_HVM_VMENTRY:
1155c7158ae9Stariq 		/*
1156c7158ae9Stariq 		 * Return to guest via vmx_launch/vmrun
1157c7158ae9Stariq 		 *
1158c7158ae9Stariq 		 */
115955f5292cSFrank Van Der Linden 		XDT_PROBE0(XDT_HVM_VMENTRY);
1160c7158ae9Stariq 		break;
1161c7158ae9Stariq 
116255f5292cSFrank Van Der Linden 	case TRC_HVM_VMEXIT:
116355f5292cSFrank Van Der Linden 		/*
116455f5292cSFrank Van Der Linden 		 * Entry into VMEXIT handler from 32-bit HVM domain
116555f5292cSFrank Van Der Linden 		 *
116655f5292cSFrank Van Der Linden 		 * data[0] = cpu vendor specific exit code
116755f5292cSFrank Van Der Linden 		 * data[1] = guest eip
116855f5292cSFrank Van Der Linden 		 */
116955f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_HVM_VMEXIT, data[0], data[1]);
117055f5292cSFrank Van Der Linden 		break;
1171349b53ddSStuart Maybee 	case TRC_HVM_VMEXIT64:
1172c7158ae9Stariq 		/*
117355f5292cSFrank Van Der Linden 		 * Entry into VMEXIT handler from 64-bit HVM domain
117455f5292cSFrank Van Der Linden 		 *
117555f5292cSFrank Van Der Linden 		 * data[0] = cpu vendor specific exit code
117655f5292cSFrank Van Der Linden 		 * data[1] = guest rip(0:31)
117755f5292cSFrank Van Der Linden 		 * data[2] = guest rip(32:64)
117855f5292cSFrank Van Der Linden 		 */
117955f5292cSFrank Van Der Linden 		rip64 = (((uint64_t)data[2]) << 32) | data[1];
118055f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_HVM_VMEXIT, data[0], rip64);
118155f5292cSFrank Van Der Linden 		break;
118255f5292cSFrank Van Der Linden 
118355f5292cSFrank Van Der Linden 	case TRC_HVM_PF_XEN64:
118455f5292cSFrank Van Der Linden 		/*
118555f5292cSFrank Van Der Linden 		 * Pagefault in a guest that is a Xen (e.g. shadow)
118655f5292cSFrank Van Der Linden 		 * artifact, and is not injected back into the guest.
118755f5292cSFrank Van Der Linden 		 *
118855f5292cSFrank Van Der Linden 		 * data[0] = error code
118955f5292cSFrank Van Der Linden 		 * data[1] = guest VA(0:31)
119055f5292cSFrank Van Der Linden 		 * data[2] = guest VA(32:64)
119155f5292cSFrank Van Der Linden 		 */
119255f5292cSFrank Van Der Linden 		addr64 = (((uint64_t)data[2]) << 32) | data[1];
119355f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_HVM_PF_XEN, data[0], addr64);
119455f5292cSFrank Van Der Linden 		break;
119555f5292cSFrank Van Der Linden 
119655f5292cSFrank Van Der Linden 	case TRC_HVM_PF_XEN:
119755f5292cSFrank Van Der Linden 		/*
119855f5292cSFrank Van Der Linden 		 * Same as above, but for a 32-bit HVM domain.
119955f5292cSFrank Van Der Linden 		 *
120055f5292cSFrank Van Der Linden 		 * data[0] = error code
120155f5292cSFrank Van Der Linden 		 * data[1] = guest VA
120255f5292cSFrank Van Der Linden 		 */
120355f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_HVM_PF_XEN, data[0], data[1]);
120455f5292cSFrank Van Der Linden 		break;
120555f5292cSFrank Van Der Linden 
120655f5292cSFrank Van Der Linden 	case TRC_HVM_PF_INJECT:
120755f5292cSFrank Van Der Linden 		/*
120855f5292cSFrank Van Der Linden 		 * 32-bit Xen only.
120955f5292cSFrank Van Der Linden 		 */
121055f5292cSFrank Van Der Linden 		break;
121155f5292cSFrank Van Der Linden 	case TRC_HVM_PF_INJECT64:
121255f5292cSFrank Van Der Linden 		/*
121355f5292cSFrank Van Der Linden 		 * Pagefault injected back into a guest (e.g. the shadow
121455f5292cSFrank Van Der Linden 		 * code found no mapping).
121555f5292cSFrank Van Der Linden 		 *
121655f5292cSFrank Van Der Linden 		 * data[0] = error code
121755f5292cSFrank Van Der Linden 		 * data[1] = guest VA(0:31)
121855f5292cSFrank Van Der Linden 		 * data[2] = guest VA(32:64)
121955f5292cSFrank Van Der Linden 		 */
122055f5292cSFrank Van Der Linden 		addr64 = (((uint64_t)data[2]) << 32) | data[1];
122155f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_HVM_PF_INJECT, data[0], addr64);
122255f5292cSFrank Van Der Linden 		break;
122355f5292cSFrank Van Der Linden 
122455f5292cSFrank Van Der Linden 	case TRC_HVM_INJ_EXC:
122555f5292cSFrank Van Der Linden 		/*
122655f5292cSFrank Van Der Linden 		 * Exception injected into an HVM guest.
122755f5292cSFrank Van Der Linden 		 *
122855f5292cSFrank Van Der Linden 		 * data[0] = trap
122955f5292cSFrank Van Der Linden 		 * data[1] = error code
123055f5292cSFrank Van Der Linden 		 */
123155f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_HVM_EXC_INJECT, data[0], data[1]);
123255f5292cSFrank Van Der Linden 		break;
123355f5292cSFrank Van Der Linden 	case TRC_HVM_INJ_VIRQ:
123455f5292cSFrank Van Der Linden 		/*
123555f5292cSFrank Van Der Linden 		 * Interrupt inject into an HVM guest.
123655f5292cSFrank Van Der Linden 		 *
123755f5292cSFrank Van Der Linden 		 * data[0] = vector
123855f5292cSFrank Van Der Linden 		 */
123955f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_HVM_VIRQ_INJECT, data[0]);
124055f5292cSFrank Van Der Linden 		break;
124155f5292cSFrank Van Der Linden 	case TRC_HVM_REINJ_VIRQ:
124255f5292cSFrank Van Der Linden 	case TRC_HVM_IO_READ:
124355f5292cSFrank Van Der Linden 	case TRC_HVM_IO_WRITE:
124455f5292cSFrank Van Der Linden 		/* unused */
124555f5292cSFrank Van Der Linden 		break;
124655f5292cSFrank Van Der Linden 	case TRC_HVM_CR_READ64:
124755f5292cSFrank Van Der Linden 		/*
124855f5292cSFrank Van Der Linden 		 * Control register read. Intel VMX only.
124955f5292cSFrank Van Der Linden 		 *
125055f5292cSFrank Van Der Linden 		 * data[0] = control register #
125155f5292cSFrank Van Der Linden 		 * data[1] = value(0:31)
125255f5292cSFrank Van Der Linden 		 * data[2] = value(32:63)
125355f5292cSFrank Van Der Linden 		 */
125455f5292cSFrank Van Der Linden 		val64 = (((uint64_t)data[2]) << 32) | data[1];
125555f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_HVM_CR_READ, data[0], val64);
125655f5292cSFrank Van Der Linden 		break;
125755f5292cSFrank Van Der Linden 	case TRC_HVM_CR_READ:
125855f5292cSFrank Van Der Linden 		/*
125955f5292cSFrank Van Der Linden 		 * unused (32-bit Xen only)
126055f5292cSFrank Van Der Linden 		 */
126155f5292cSFrank Van Der Linden 		break;
126255f5292cSFrank Van Der Linden 	case TRC_HVM_CR_WRITE64:
126355f5292cSFrank Van Der Linden 		/*
126455f5292cSFrank Van Der Linden 		 * Control register write. Intel VMX only.
126555f5292cSFrank Van Der Linden 		 *
126655f5292cSFrank Van Der Linden 		 * data[0] = control register #
126755f5292cSFrank Van Der Linden 		 * data[1] = value(0:31)
126855f5292cSFrank Van Der Linden 		 * data[2] = value(32:63)
126955f5292cSFrank Van Der Linden 		 */
127055f5292cSFrank Van Der Linden 		val64 = (((uint64_t)data[2]) << 32) | data[1];
127155f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_HVM_CR_READ, data[0], val64);
127255f5292cSFrank Van Der Linden 		break;
127355f5292cSFrank Van Der Linden 	case TRC_HVM_CR_WRITE:
127455f5292cSFrank Van Der Linden 		/*
127555f5292cSFrank Van Der Linden 		 * unused (32-bit Xen only)
127655f5292cSFrank Van Der Linden 		 */
127755f5292cSFrank Van Der Linden 		break;
127855f5292cSFrank Van Der Linden 	case TRC_HVM_DR_READ:
127955f5292cSFrank Van Der Linden 		/*
128055f5292cSFrank Van Der Linden 		 * unused.
1281c7158ae9Stariq 		 *
1282349b53ddSStuart Maybee 		 * data[0] = (domid<<16 + vcpuid)
1283c7158ae9Stariq 		 */
128455f5292cSFrank Van Der Linden 		break;
128555f5292cSFrank Van Der Linden 	case TRC_HVM_DR_WRITE:
128655f5292cSFrank Van Der Linden 		/*
128755f5292cSFrank Van Der Linden 		 * Debug register write. Not too useful; no values,
128855f5292cSFrank Van Der Linden 		 * so we ignore this.
128955f5292cSFrank Van Der Linden 		 *
129055f5292cSFrank Van Der Linden 		 * data[0] = (domid<<16 + vcpuid)
129155f5292cSFrank Van Der Linden 		 */
129255f5292cSFrank Van Der Linden 		break;
129355f5292cSFrank Van Der Linden 	case TRC_HVM_MSR_READ:
129455f5292cSFrank Van Der Linden 		/*
129555f5292cSFrank Van Der Linden 		 * MSR read.
129655f5292cSFrank Van Der Linden 		 *
129755f5292cSFrank Van Der Linden 		 * data[0] = MSR
129855f5292cSFrank Van Der Linden 		 * data[1] = value(0:31)
129955f5292cSFrank Van Der Linden 		 * data[2] = value(32:63)
130055f5292cSFrank Van Der Linden 		 */
130155f5292cSFrank Van Der Linden 		val64 = (((uint64_t)data[3]) << 32) | data[2];
130255f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_HVM_MSR_READ, data[0], val64);
130355f5292cSFrank Van Der Linden 		break;
130455f5292cSFrank Van Der Linden 	case TRC_HVM_MSR_WRITE:
130555f5292cSFrank Van Der Linden 		/*
130655f5292cSFrank Van Der Linden 		 * MSR write.
130755f5292cSFrank Van Der Linden 		 *
130855f5292cSFrank Van Der Linden 		 * data[0] = MSR;
130955f5292cSFrank Van Der Linden 		 * data[1] = value(0:31)
131055f5292cSFrank Van Der Linden 		 * data[2] = value(32:63)
131155f5292cSFrank Van Der Linden 		 */
131255f5292cSFrank Van Der Linden 		val64 = (((uint64_t)data[2]) << 32) | data[1];
131355f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_HVM_MSR_WRITE, data[0], val64);
131455f5292cSFrank Van Der Linden 		break;
131555f5292cSFrank Van Der Linden 	case TRC_HVM_CPUID:
131655f5292cSFrank Van Der Linden 		/*
131755f5292cSFrank Van Der Linden 		 * CPUID insn.
131855f5292cSFrank Van Der Linden 		 *
131955f5292cSFrank Van Der Linden 		 * data[0] = %eax (input)
132055f5292cSFrank Van Der Linden 		 * data[1] = %eax
132155f5292cSFrank Van Der Linden 		 * data[2] = %ebx
132255f5292cSFrank Van Der Linden 		 * data[3] = %ecx
132355f5292cSFrank Van Der Linden 		 * data[4] = %edx
132455f5292cSFrank Van Der Linden 		 */
132555f5292cSFrank Van Der Linden 		XDT_PROBE5(XDT_HVM_CPUID, data[0], data[1], data[2], data[3],
132655f5292cSFrank Van Der Linden 		    data[4]);
132755f5292cSFrank Van Der Linden 		break;
132855f5292cSFrank Van Der Linden 	case TRC_HVM_INTR:
132955f5292cSFrank Van Der Linden 		/*
133055f5292cSFrank Van Der Linden 		 * VMEXIT because of an interrupt.
133155f5292cSFrank Van Der Linden 		 */
133255f5292cSFrank Van Der Linden 		XDT_PROBE0(XDT_HVM_INTR);
133355f5292cSFrank Van Der Linden 		break;
133455f5292cSFrank Van Der Linden 	case TRC_HVM_INTR_WINDOW:
133555f5292cSFrank Van Der Linden 		/*
133655f5292cSFrank Van Der Linden 		 * VMEXIT because of an interrupt window (an interrupt
133755f5292cSFrank Van Der Linden 		 * can't be delivered immediately to a HVM guest and must
133855f5292cSFrank Van Der Linden 		 * be delayed).
133955f5292cSFrank Van Der Linden 		 *
134055f5292cSFrank Van Der Linden 		 * data[0] = vector
134155f5292cSFrank Van Der Linden 		 * data[1] = source
134255f5292cSFrank Van Der Linden 		 * data[2] = info
134355f5292cSFrank Van Der Linden 		 */
134455f5292cSFrank Van Der Linden 		XDT_PROBE3(XDT_HVM_INTR_WINDOW, data[0], data[1], data[2]);
134555f5292cSFrank Van Der Linden 		break;
134655f5292cSFrank Van Der Linden 	case TRC_HVM_NMI:
134755f5292cSFrank Van Der Linden 		/*
134855f5292cSFrank Van Der Linden 		 * VMEXIT because of an NMI.
134955f5292cSFrank Van Der Linden 		 */
135055f5292cSFrank Van Der Linden 		XDT_PROBE0(XDT_HVM_NMI);
135155f5292cSFrank Van Der Linden 		break;
135255f5292cSFrank Van Der Linden 	case TRC_HVM_SMI:
135355f5292cSFrank Van Der Linden 		/*
135455f5292cSFrank Van Der Linden 		 * VMEXIT because of an SMI
135555f5292cSFrank Van Der Linden 		 */
135655f5292cSFrank Van Der Linden 		XDT_PROBE0(XDT_HVM_SMI);
135755f5292cSFrank Van Der Linden 		break;
135855f5292cSFrank Van Der Linden 	case TRC_HVM_VMMCALL:
135955f5292cSFrank Van Der Linden 		/*
136055f5292cSFrank Van Der Linden 		 * VMMCALL insn.
136155f5292cSFrank Van Der Linden 		 *
136255f5292cSFrank Van Der Linden 		 * data[0] = %eax
136355f5292cSFrank Van Der Linden 		 */
136455f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_HVM_VMMCALL, data[0]);
136555f5292cSFrank Van Der Linden 		break;
136655f5292cSFrank Van Der Linden 	case TRC_HVM_HLT:
136755f5292cSFrank Van Der Linden 		/*
136855f5292cSFrank Van Der Linden 		 * HLT insn.
136955f5292cSFrank Van Der Linden 		 *
137055f5292cSFrank Van Der Linden 		 * data[0] = 1 if VCPU runnable, 0 if not
137155f5292cSFrank Van Der Linden 		 */
137255f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_HVM_HLT, data[0]);
137355f5292cSFrank Van Der Linden 		break;
137455f5292cSFrank Van Der Linden 	case TRC_HVM_INVLPG64:
137555f5292cSFrank Van Der Linden 		/*
137655f5292cSFrank Van Der Linden 		 *
137755f5292cSFrank Van Der Linden 		 * data[0] = INVLPGA ? 1 : 0
137855f5292cSFrank Van Der Linden 		 * data[1] = vaddr(0:31)
137955f5292cSFrank Van Der Linden 		 * data[2] = vaddr(32:63)
138055f5292cSFrank Van Der Linden 		 */
138155f5292cSFrank Van Der Linden 		addr64 = (((uint64_t)data[2]) << 32) | data[1];
138255f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_HVM_INVLPG, data[0], addr64);
138355f5292cSFrank Van Der Linden 		break;
138455f5292cSFrank Van Der Linden 	case TRC_HVM_INVLPG:
138555f5292cSFrank Van Der Linden 		/*
138655f5292cSFrank Van Der Linden 		 * unused (32-bit Xen only)
138755f5292cSFrank Van Der Linden 		 *
138855f5292cSFrank Van Der Linden 		 * data[0] = (domid<<16 + vcpuid)
138955f5292cSFrank Van Der Linden 		 */
139055f5292cSFrank Van Der Linden 		break;
139155f5292cSFrank Van Der Linden 	case TRC_HVM_MCE:
139255f5292cSFrank Van Der Linden 		/*
139355f5292cSFrank Van Der Linden 		 * #MCE VMEXIT
139455f5292cSFrank Van Der Linden 		 *
139555f5292cSFrank Van Der Linden 		 */
139655f5292cSFrank Van Der Linden 		XDT_PROBE0(XDT_HVM_MCE);
139755f5292cSFrank Van Der Linden 		break;
139855f5292cSFrank Van Der Linden 	case TRC_HVM_IOPORT_READ:
139955f5292cSFrank Van Der Linden 	case TRC_HVM_IOPORT_WRITE:
140055f5292cSFrank Van Der Linden 	case TRC_HVM_IOMEM_READ:
140155f5292cSFrank Van Der Linden 	case TRC_HVM_IOMEM_WRITE:
140255f5292cSFrank Van Der Linden 		/*
140355f5292cSFrank Van Der Linden 		 * data[0] = addr(0:31)
140455f5292cSFrank Van Der Linden 		 * data[1] = addr(32:63)
140555f5292cSFrank Van Der Linden 		 * data[2] = count
140655f5292cSFrank Van Der Linden 		 * data[3] = size
140755f5292cSFrank Van Der Linden 		 */
140855f5292cSFrank Van Der Linden 		switch (rec->event) {
140955f5292cSFrank Van Der Linden 		case TRC_HVM_IOPORT_READ:
141055f5292cSFrank Van Der Linden 			eid = XDT_HVM_IOPORT_READ;
141155f5292cSFrank Van Der Linden 			break;
141255f5292cSFrank Van Der Linden 		case TRC_HVM_IOPORT_WRITE:
141355f5292cSFrank Van Der Linden 			eid = XDT_HVM_IOPORT_WRITE;
141455f5292cSFrank Van Der Linden 			break;
141555f5292cSFrank Van Der Linden 		case TRC_HVM_IOMEM_READ:
141655f5292cSFrank Van Der Linden 			eid = XDT_HVM_IOMEM_READ;
141755f5292cSFrank Van Der Linden 			break;
141855f5292cSFrank Van Der Linden 		case TRC_HVM_IOMEM_WRITE:
141955f5292cSFrank Van Der Linden 			eid = XDT_HVM_IOMEM_WRITE;
142055f5292cSFrank Van Der Linden 			break;
142155f5292cSFrank Van Der Linden 		}
142255f5292cSFrank Van Der Linden 		addr64 = (((uint64_t)data[1]) << 32) | data[0];
142355f5292cSFrank Van Der Linden 		XDT_PROBE3(eid, addr64, data[2], data[3]);
142455f5292cSFrank Van Der Linden 		break;
142555f5292cSFrank Van Der Linden 	case TRC_HVM_CLTS:
142655f5292cSFrank Van Der Linden 		/*
142755f5292cSFrank Van Der Linden 		 * CLTS insn (Intel VMX only)
142855f5292cSFrank Van Der Linden 		 */
142955f5292cSFrank Van Der Linden 		XDT_PROBE0(XDT_HVM_CLTS);
143055f5292cSFrank Van Der Linden 		break;
143155f5292cSFrank Van Der Linden 	case TRC_HVM_LMSW64:
143255f5292cSFrank Van Der Linden 		/*
143355f5292cSFrank Van Der Linden 		 * LMSW insn.
143455f5292cSFrank Van Der Linden 		 *
143555f5292cSFrank Van Der Linden 		 * data[0] = value(0:31)
143655f5292cSFrank Van Der Linden 		 * data[1] = value(32:63)
143755f5292cSFrank Van Der Linden 		 */
143855f5292cSFrank Van Der Linden 		val64 = (((uint64_t)data[1]) << 32) | data[0];
143955f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_HVM_LMSW, val64);
144055f5292cSFrank Van Der Linden 		break;
144155f5292cSFrank Van Der Linden 	case TRC_HVM_LMSW:
144255f5292cSFrank Van Der Linden 		/*
144355f5292cSFrank Van Der Linden 		 * unused (32-bit Xen only)
144455f5292cSFrank Van Der Linden 		 */
1445c7158ae9Stariq 		break;
1446c7158ae9Stariq 
144755f5292cSFrank Van Der Linden 	/*
144855f5292cSFrank Van Der Linden 	 * Shadow page table probes (mainly used for HVM domains
144955f5292cSFrank Van Der Linden 	 * without hardware paging support).
145055f5292cSFrank Van Der Linden 	 */
145155f5292cSFrank Van Der Linden 	case TRC_SHADOW_NOT_SHADOW | SH_GUEST_32:
145255f5292cSFrank Van Der Linden 		/*
145355f5292cSFrank Van Der Linden 		 * data[0] = pte(0:31)
145455f5292cSFrank Van Der Linden 		 * data[1] = pte(32:63)
145555f5292cSFrank Van Der Linden 		 * data[2] = va
145655f5292cSFrank Van Der Linden 		 * data[3] = flags
145755f5292cSFrank Van Der Linden 		 */
145855f5292cSFrank Van Der Linden 		pte64 = ((uint64_t)data[1] << 32) | data[0];
145955f5292cSFrank Van Der Linden 		XDT_PROBE3(XDT_SHADOW_NOT_SHADOW, pte64, data[2], data[3]);
146055f5292cSFrank Van Der Linden 		break;
146155f5292cSFrank Van Der Linden 	case TRC_SHADOW_NOT_SHADOW | SH_GUEST_PAE:
146255f5292cSFrank Van Der Linden 	case TRC_SHADOW_NOT_SHADOW | SH_GUEST_64:
146355f5292cSFrank Van Der Linden 		/*
146455f5292cSFrank Van Der Linden 		 * data[0] = pte(0:31)
146555f5292cSFrank Van Der Linden 		 * data[1] = pte(32:63)
146655f5292cSFrank Van Der Linden 		 * data[2] = va(0:31)
146755f5292cSFrank Van Der Linden 		 * data[3] = va(32:63)
146855f5292cSFrank Van Der Linden 		 * data[4] = flags
146955f5292cSFrank Van Der Linden 		 */
147055f5292cSFrank Van Der Linden 		addr64 = ((uint64_t)data[2] << 32) | data[3];
147155f5292cSFrank Van Der Linden 		pte64 = ((uint64_t)data[1] << 32) | data[0];
147255f5292cSFrank Van Der Linden 		XDT_PROBE3(XDT_SHADOW_NOT_SHADOW, pte64, addr64, data[4]);
147355f5292cSFrank Van Der Linden 		break;
147455f5292cSFrank Van Der Linden 	case TRC_SHADOW_FAST_PROPAGATE | SH_GUEST_32:
147555f5292cSFrank Van Der Linden 		/*
147655f5292cSFrank Van Der Linden 		 * data[0] = va
147755f5292cSFrank Van Der Linden 		 */
147855f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_SHADOW_FAST_PROPAGATE, data[0]);
147955f5292cSFrank Van Der Linden 		break;
148055f5292cSFrank Van Der Linden 	case TRC_SHADOW_FAST_PROPAGATE | SH_GUEST_PAE:
148155f5292cSFrank Van Der Linden 	case TRC_SHADOW_FAST_PROPAGATE | SH_GUEST_64:
148255f5292cSFrank Van Der Linden 		/*
148355f5292cSFrank Van Der Linden 		 * data[0] = va(0:31)
148455f5292cSFrank Van Der Linden 		 * data[1] = va(32:63)
148555f5292cSFrank Van Der Linden 		 */
148655f5292cSFrank Van Der Linden 		addr64 = ((uint64_t)data[1] << 32) | data[0];
148755f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_SHADOW_FAST_PROPAGATE, addr64);
148855f5292cSFrank Van Der Linden 		break;
148955f5292cSFrank Van Der Linden 	case TRC_SHADOW_FAST_MMIO | SH_GUEST_32:
149055f5292cSFrank Van Der Linden 		/*
149155f5292cSFrank Van Der Linden 		 * data[0] = va
149255f5292cSFrank Van Der Linden 		 */
149355f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_SHADOW_FAST_MMIO, data[0]);
149455f5292cSFrank Van Der Linden 		break;
149555f5292cSFrank Van Der Linden 	case TRC_SHADOW_FAST_MMIO | SH_GUEST_PAE:
149655f5292cSFrank Van Der Linden 	case TRC_SHADOW_FAST_MMIO | SH_GUEST_64:
149755f5292cSFrank Van Der Linden 		/*
149855f5292cSFrank Van Der Linden 		 * data[0] = va(0:31)
149955f5292cSFrank Van Der Linden 		 * data[1] = va(32:63)
150055f5292cSFrank Van Der Linden 		 */
150155f5292cSFrank Van Der Linden 		addr64 = ((uint64_t)data[1] << 32) | data[0];
150255f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_SHADOW_FAST_MMIO, addr64);
150355f5292cSFrank Van Der Linden 		break;
150455f5292cSFrank Van Der Linden 	case TRC_SHADOW_FALSE_FAST_PATH | SH_GUEST_32:
150555f5292cSFrank Van Der Linden 		/*
150655f5292cSFrank Van Der Linden 		 * data[0] = va
150755f5292cSFrank Van Der Linden 		 */
150855f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_SHADOW_FALSE_FAST_PATH, data[0]);
150955f5292cSFrank Van Der Linden 		break;
151055f5292cSFrank Van Der Linden 	case TRC_SHADOW_FALSE_FAST_PATH | SH_GUEST_PAE:
151155f5292cSFrank Van Der Linden 	case TRC_SHADOW_FALSE_FAST_PATH | SH_GUEST_64:
151255f5292cSFrank Van Der Linden 		/*
151355f5292cSFrank Van Der Linden 		 * data[0] = va(0:31)
151455f5292cSFrank Van Der Linden 		 * data[1] = va(32:63)
151555f5292cSFrank Van Der Linden 		 */
151655f5292cSFrank Van Der Linden 		addr64 = ((uint64_t)data[1] << 32) | data[0];
151755f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_SHADOW_FALSE_FAST_PATH, addr64);
151855f5292cSFrank Van Der Linden 		break;
151955f5292cSFrank Van Der Linden 	case TRC_SHADOW_MMIO | SH_GUEST_32:
152055f5292cSFrank Van Der Linden 		/*
152155f5292cSFrank Van Der Linden 		 * data[0] = va
152255f5292cSFrank Van Der Linden 		 */
152355f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_SHADOW_MMIO, data[0]);
152455f5292cSFrank Van Der Linden 		break;
152555f5292cSFrank Van Der Linden 	case TRC_SHADOW_MMIO | SH_GUEST_PAE:
152655f5292cSFrank Van Der Linden 	case TRC_SHADOW_MMIO | SH_GUEST_64:
152755f5292cSFrank Van Der Linden 		/*
152855f5292cSFrank Van Der Linden 		 * data[0] = va(0:31)
152955f5292cSFrank Van Der Linden 		 * data[1] = va(32:63)
153055f5292cSFrank Van Der Linden 		 */
153155f5292cSFrank Van Der Linden 		addr64 = ((uint64_t)data[1] << 32) | data[0];
153255f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_SHADOW_MMIO, addr64);
153355f5292cSFrank Van Der Linden 		break;
153455f5292cSFrank Van Der Linden 	case TRC_SHADOW_FIXUP | SH_GUEST_32:
153555f5292cSFrank Van Der Linden 		/*
153655f5292cSFrank Van Der Linden 		 * data[0] = pte(0:31)
153755f5292cSFrank Van Der Linden 		 * data[1] = pte(32:63)
153855f5292cSFrank Van Der Linden 		 * data[2] = va
153955f5292cSFrank Van Der Linden 		 * data[3] = flags
154055f5292cSFrank Van Der Linden 		 */
154155f5292cSFrank Van Der Linden 		pte64 = ((uint64_t)data[1] << 32) | data[0];
154255f5292cSFrank Van Der Linden 		XDT_PROBE3(XDT_SHADOW_FIXUP, pte64, data[2], data[3]);
154355f5292cSFrank Van Der Linden 		break;
154455f5292cSFrank Van Der Linden 	case TRC_SHADOW_FIXUP | SH_GUEST_64:
154555f5292cSFrank Van Der Linden 	case TRC_SHADOW_FIXUP | SH_GUEST_PAE:
154655f5292cSFrank Van Der Linden 		/*
154755f5292cSFrank Van Der Linden 		 * data[0] = pte(0:31)
154855f5292cSFrank Van Der Linden 		 * data[1] = pte(32:63)
154955f5292cSFrank Van Der Linden 		 * data[2] = va(0:31)
155055f5292cSFrank Van Der Linden 		 * data[3] = va(32:63)
155155f5292cSFrank Van Der Linden 		 * data[4] = flags
155255f5292cSFrank Van Der Linden 		 */
155355f5292cSFrank Van Der Linden 		addr64 = ((uint64_t)data[2] << 32) | data[3];
155455f5292cSFrank Van Der Linden 		pte64 = ((uint64_t)data[1] << 32) | data[0];
155555f5292cSFrank Van Der Linden 		XDT_PROBE3(XDT_SHADOW_FIXUP, pte64, addr64, data[4]);
155655f5292cSFrank Van Der Linden 		break;
155755f5292cSFrank Van Der Linden 	case TRC_SHADOW_DOMF_DYING | SH_GUEST_32:
155855f5292cSFrank Van Der Linden 		/*
155955f5292cSFrank Van Der Linden 		 * data[0] = va
156055f5292cSFrank Van Der Linden 		 */
156155f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_SHADOW_DOMF_DYING, data[0]);
156255f5292cSFrank Van Der Linden 		break;
156355f5292cSFrank Van Der Linden 	case TRC_SHADOW_DOMF_DYING | SH_GUEST_PAE:
156455f5292cSFrank Van Der Linden 	case TRC_SHADOW_DOMF_DYING | SH_GUEST_64:
156555f5292cSFrank Van Der Linden 		/*
156655f5292cSFrank Van Der Linden 		 * data[0] = va(0:31)
156755f5292cSFrank Van Der Linden 		 * data[1] = va(32:63)
156855f5292cSFrank Van Der Linden 		 */
156955f5292cSFrank Van Der Linden 		addr64 = ((uint64_t)data[1] << 32) | data[0];
157055f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_SHADOW_DOMF_DYING, addr64);
157155f5292cSFrank Van Der Linden 		break;
157255f5292cSFrank Van Der Linden 	case TRC_SHADOW_EMULATE | SH_GUEST_32:
157355f5292cSFrank Van Der Linden 		/*
157455f5292cSFrank Van Der Linden 		 * data[0] = pte(0:31)
157555f5292cSFrank Van Der Linden 		 * data[1] = pte(32:63)
157655f5292cSFrank Van Der Linden 		 * data[2] = val(0:31)
157755f5292cSFrank Van Der Linden 		 * data[3] = val(32:63)
157855f5292cSFrank Van Der Linden 		 * data[4] = addr
157955f5292cSFrank Van Der Linden 		 * data[5] = flags
158055f5292cSFrank Van Der Linden 		 */
158155f5292cSFrank Van Der Linden 		pte64 = ((uint64_t)data[1] << 32) | data[0];
158255f5292cSFrank Van Der Linden 		val64 = ((uint64_t)data[3] << 32) | data[2];
158355f5292cSFrank Van Der Linden 		XDT_PROBE5(XDT_SHADOW_EMULATE, pte64, val64, data[4],
158455f5292cSFrank Van Der Linden 		    data[5] & 0x7fffffff, data[5] >> 29);
158555f5292cSFrank Van Der Linden 		break;
158655f5292cSFrank Van Der Linden 	case TRC_SHADOW_EMULATE | SH_GUEST_PAE:
158755f5292cSFrank Van Der Linden 	case TRC_SHADOW_EMULATE | SH_GUEST_64:
158855f5292cSFrank Van Der Linden 		/*
158955f5292cSFrank Van Der Linden 		 * data[0] = pte(0:31)
159055f5292cSFrank Van Der Linden 		 * data[1] = pte(32:63)
159155f5292cSFrank Van Der Linden 		 * data[2] = val(0:31)
159255f5292cSFrank Van Der Linden 		 * data[3] = val(32:63)
159355f5292cSFrank Van Der Linden 		 * data[4] = addr(0:31)
159455f5292cSFrank Van Der Linden 		 * data[5] = addr(32:63)
159555f5292cSFrank Van Der Linden 		 * data[6] = flags
159655f5292cSFrank Van Der Linden 		 */
159755f5292cSFrank Van Der Linden 		pte64 = ((uint64_t)data[1] << 32) | data[0];
159855f5292cSFrank Van Der Linden 		val64 = ((uint64_t)data[3] << 32) | data[2];
159955f5292cSFrank Van Der Linden 		addr64 = ((uint64_t)data[5] << 32) | data[4];
160055f5292cSFrank Van Der Linden 		XDT_PROBE5(XDT_SHADOW_EMULATE, pte64, val64, data[4],
160155f5292cSFrank Van Der Linden 		    data[6] & 0x7fffffff, data[6] >> 29);
160255f5292cSFrank Van Der Linden 		break;
160355f5292cSFrank Van Der Linden 	case TRC_SHADOW_EMULATE_UNSHADOW_USER | SH_GUEST_32:
160455f5292cSFrank Van Der Linden 		/*
160555f5292cSFrank Van Der Linden 		 * data[0] = gfn
160655f5292cSFrank Van Der Linden 		 * data[1] = vaddr
160755f5292cSFrank Van Der Linden 		 */
160855f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_USER, data[0], data[1]);
160955f5292cSFrank Van Der Linden 		break;
161055f5292cSFrank Van Der Linden 	case TRC_SHADOW_EMULATE_UNSHADOW_USER | SH_GUEST_PAE:
161155f5292cSFrank Van Der Linden 	case TRC_SHADOW_EMULATE_UNSHADOW_USER | SH_GUEST_64:
161255f5292cSFrank Van Der Linden 		/*
161355f5292cSFrank Van Der Linden 		 * data[0] = gfn(0:31)
161455f5292cSFrank Van Der Linden 		 * data[1] = gfn(32:63)
161555f5292cSFrank Van Der Linden 		 * data[2] = vaddr(0:31)
161655f5292cSFrank Van Der Linden 		 * data[3] = vaddr(32:63)
161755f5292cSFrank Van Der Linden 		 */
161855f5292cSFrank Van Der Linden 		val64 = ((uint64_t)data[1] << 32) | data[0];
161955f5292cSFrank Van Der Linden 		addr64 = ((uint64_t)data[3] << 32) | data[2];
162055f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_USER, val64, addr64);
162155f5292cSFrank Van Der Linden 		break;
162255f5292cSFrank Van Der Linden 	case TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ | SH_GUEST_32:
162355f5292cSFrank Van Der Linden 		/*
162455f5292cSFrank Van Der Linden 		 * data[0] = gfn
162555f5292cSFrank Van Der Linden 		 * data[1] = vaddr
162655f5292cSFrank Van Der Linden 		 */
162755f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ, data[0],
162855f5292cSFrank Van Der Linden 		    data[1]);
162955f5292cSFrank Van Der Linden 		break;
163055f5292cSFrank Van Der Linden 	case TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ | SH_GUEST_PAE:
163155f5292cSFrank Van Der Linden 	case TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ | SH_GUEST_64:
163255f5292cSFrank Van Der Linden 		/*
163355f5292cSFrank Van Der Linden 		 * data[0] = gfn(0:31)
163455f5292cSFrank Van Der Linden 		 * data[1] = gfn(32:63)
163555f5292cSFrank Van Der Linden 		 * data[2] = vaddr(0:31)
163655f5292cSFrank Van Der Linden 		 * data[3] = vaddr(32:63)
163755f5292cSFrank Van Der Linden 		 */
163855f5292cSFrank Van Der Linden 		val64 = ((uint64_t)data[1] << 32) | data[0];
163955f5292cSFrank Van Der Linden 		addr64 = ((uint64_t)data[3] << 32) | data[2];
164055f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ, val64, addr64);
164155f5292cSFrank Van Der Linden 		break;
164255f5292cSFrank Van Der Linden 	case TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED | SH_GUEST_32:
164355f5292cSFrank Van Der Linden 		/*
164455f5292cSFrank Van Der Linden 		 * data[0] = gfn
164555f5292cSFrank Van Der Linden 		 * data[1] = vaddr
164655f5292cSFrank Van Der Linden 		 */
164755f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED, data[0],
164855f5292cSFrank Van Der Linden 		    data[1]);
164955f5292cSFrank Van Der Linden 		break;
165055f5292cSFrank Van Der Linden 	case TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED | SH_GUEST_PAE:
165155f5292cSFrank Van Der Linden 	case TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED | SH_GUEST_64:
165255f5292cSFrank Van Der Linden 		/*
165355f5292cSFrank Van Der Linden 		 * data[0] = gfn(0:31)
165455f5292cSFrank Van Der Linden 		 * data[1] = gfn(32:63)
165555f5292cSFrank Van Der Linden 		 * data[2] = vaddr(0:31)
165655f5292cSFrank Van Der Linden 		 * data[3] = vaddr(32:63)
165755f5292cSFrank Van Der Linden 		 */
165855f5292cSFrank Van Der Linden 		val64 = ((uint64_t)data[1] << 32) | data[0];
165955f5292cSFrank Van Der Linden 		addr64 = ((uint64_t)data[3] << 32) | data[2];
166055f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED, val64,
166155f5292cSFrank Van Der Linden 		    addr64);
166255f5292cSFrank Van Der Linden 		break;
166355f5292cSFrank Van Der Linden 	case TRC_SHADOW_WRMAP_BF:
166455f5292cSFrank Van Der Linden 		/*
166555f5292cSFrank Van Der Linden 		 * data[0] = gfn(0:31)
166655f5292cSFrank Van Der Linden 		 * data[1] = gfn(32:63)
166755f5292cSFrank Van Der Linden 		 */
166855f5292cSFrank Van Der Linden 		val64 = ((uint64_t)data[1] << 32) | data[0];
166955f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_SHADOW_WRMAP_BF, val64);
167055f5292cSFrank Van Der Linden 		break;
167155f5292cSFrank Van Der Linden 	case TRC_SHADOW_PREALLOC_UNPIN:
167255f5292cSFrank Van Der Linden 		/*
167355f5292cSFrank Van Der Linden 		 * data[0] = gfn(0:31)
167455f5292cSFrank Van Der Linden 		 * data[1] = gfn(32:63)
167555f5292cSFrank Van Der Linden 		 */
167655f5292cSFrank Van Der Linden 		val64 = ((uint64_t)data[1] << 32) | data[0];
167755f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_SHADOW_PREALLOC_UNPIN, val64);
167855f5292cSFrank Van Der Linden 		break;
167955f5292cSFrank Van Der Linden 	case TRC_SHADOW_RESYNC_FULL:
168055f5292cSFrank Van Der Linden 		/*
168155f5292cSFrank Van Der Linden 		 * data[0] = gmfn(0:31)
168255f5292cSFrank Van Der Linden 		 * data[1] = gmfn(32:63)
168355f5292cSFrank Van Der Linden 		 */
168455f5292cSFrank Van Der Linden 		val64 = ((uint64_t)data[1] << 32) | data[0];
168555f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_SHADOW_RESYNC_FULL, val64);
168655f5292cSFrank Van Der Linden 		break;
168755f5292cSFrank Van Der Linden 	case TRC_SHADOW_RESYNC_ONLY:
168855f5292cSFrank Van Der Linden 		/*
168955f5292cSFrank Van Der Linden 		 * data[0] = gmfn(0:31)
169055f5292cSFrank Van Der Linden 		 * data[1] = gmfn(32:63)
169155f5292cSFrank Van Der Linden 		 */
169255f5292cSFrank Van Der Linden 		val64 = ((uint64_t)data[1] << 32) | data[0];
169355f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_SHADOW_RESYNC_ONLY, val64);
169455f5292cSFrank Van Der Linden 		break;
169555f5292cSFrank Van Der Linden 
169655f5292cSFrank Van Der Linden 	/*
169755f5292cSFrank Van Der Linden 	 * Power management probes.
169855f5292cSFrank Van Der Linden 	 */
169955f5292cSFrank Van Der Linden 	case TRC_PM_FREQ_CHANGE:
170055f5292cSFrank Van Der Linden 		/*
170155f5292cSFrank Van Der Linden 		 * data[0] = old freq
170255f5292cSFrank Van Der Linden 		 * data[1] = new freq
170355f5292cSFrank Van Der Linden 		 */
170455f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_PM_FREQ_CHANGE, data[0], data[1]);
170555f5292cSFrank Van Der Linden 		break;
170655f5292cSFrank Van Der Linden 	case TRC_PM_IDLE_ENTRY:
170755f5292cSFrank Van Der Linden 		/*
170855f5292cSFrank Van Der Linden 		 * data[0] = C-state
170955f5292cSFrank Van Der Linden 		 * data[1] = time
171055f5292cSFrank Van Der Linden 		 */
171155f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_PM_IDLE_ENTRY, data[0], data[1]);
171255f5292cSFrank Van Der Linden 		break;
171355f5292cSFrank Van Der Linden 	case TRC_PM_IDLE_EXIT:
171455f5292cSFrank Van Der Linden 		/*
171555f5292cSFrank Van Der Linden 		 * data[0] = C-state
171655f5292cSFrank Van Der Linden 		 * data[1] = time
171755f5292cSFrank Van Der Linden 		 */
171855f5292cSFrank Van Der Linden 		XDT_PROBE2(XDT_PM_IDLE_EXIT, data[0], data[1]);
171955f5292cSFrank Van Der Linden 		break;
1720c7158ae9Stariq 	case TRC_LOST_RECORDS:
172155f5292cSFrank Van Der Linden 		vcpu = data[1] >> 16;
172255f5292cSFrank Van Der Linden 		dom = data[1] & 0xffff;
172355f5292cSFrank Van Der Linden 		xdt_update_sched_context(cpuid, dom, vcpu);
172455f5292cSFrank Van Der Linden 		xdt_update_domain_context(dom, vcpu);
172555f5292cSFrank Van Der Linden 		XDT_PROBE1(XDT_TRC_LOST_RECORDS, cpuid);
1726c7158ae9Stariq 		tbuf.stat_dropped_recs++;
1727c7158ae9Stariq 		break;
1728c7158ae9Stariq 
1729c7158ae9Stariq 	default:
1730c7158ae9Stariq 		tbuf.stat_unknown_recs++;
1731c7158ae9Stariq 		break;
1732c7158ae9Stariq 	}
1733349b53ddSStuart Maybee 
1734349b53ddSStuart Maybee done:
1735349b53ddSStuart Maybee 	rec_size = 4 + (rec->cycles_included ? 8 : 0) + (rec->extra_u32 * 4);
1736349b53ddSStuart Maybee 	return (rec_size);
1737c7158ae9Stariq }
1738c7158ae9Stariq 
173955f5292cSFrank Van Der Linden /*
174055f5292cSFrank Van Der Linden  * Scan all CPU buffers for the record with the lowest timestamp so
174155f5292cSFrank Van Der Linden  * that the probes will fire in order.
174255f5292cSFrank Van Der Linden  */
174355f5292cSFrank Van Der Linden static int
xdt_get_first_rec(uint_t * cpuidp,struct t_rec ** recp,uint32_t * consp)174455f5292cSFrank Van Der Linden xdt_get_first_rec(uint_t *cpuidp, struct t_rec **recp, uint32_t *consp)
1745c7158ae9Stariq {
1746c7158ae9Stariq 	uint_t cpuid;
174755f5292cSFrank Van Der Linden 	uint32_t prod, cons, offset;
1748c7158ae9Stariq 	struct t_rec *rec;
174955f5292cSFrank Van Der Linden 	uint64_t minstamp = ~0ULL, stamp;
1750349b53ddSStuart Maybee 	uintptr_t data;
1751c7158ae9Stariq 
1752c7158ae9Stariq 	for (cpuid = 0; cpuid < tbuf.cnt; cpuid++) {
1753349b53ddSStuart Maybee 		cons = tbuf.meta[cpuid]->cons;
1754c7158ae9Stariq 		prod = tbuf.meta[cpuid]->prod;
175555f5292cSFrank Van Der Linden 		membar_consumer();
1756349b53ddSStuart Maybee 		if (prod == cons)
1757349b53ddSStuart Maybee 			continue;
1758349b53ddSStuart Maybee 
1759349b53ddSStuart Maybee 		offset = cons % tbuf_data_size;
176055f5292cSFrank Van Der Linden 		data = (uintptr_t)tbuf.data[cpuid] + offset;
176155f5292cSFrank Van Der Linden 		rec = (struct t_rec *)data;
176255f5292cSFrank Van Der Linden 		ASSERT((caddr_t)rec < tbuf.va + (tbuf.size * (cpuid + 1)));
1763349b53ddSStuart Maybee 
176455f5292cSFrank Van Der Linden 		/*
176555f5292cSFrank Van Der Linden 		 * All records that we know about have time cycles included.
176655f5292cSFrank Van Der Linden 		 * If this record doesn't have them, assume it's a type
176755f5292cSFrank Van Der Linden 		 * that we don't handle. Use a 0 time value, which will make
176855f5292cSFrank Van Der Linden 		 * it get handled first (it will be thrown away).
176955f5292cSFrank Van Der Linden 		 */
177055f5292cSFrank Van Der Linden 		if (rec->cycles_included)
177155f5292cSFrank Van Der Linden 			stamp = (((uint64_t)rec->u.cycles.cycles_hi) << 32)
177255f5292cSFrank Van Der Linden 			    | rec->u.cycles.cycles_lo;
177355f5292cSFrank Van Der Linden 		else
177455f5292cSFrank Van Der Linden 			stamp = 0;
177555f5292cSFrank Van Der Linden 
177655f5292cSFrank Van Der Linden 		if (stamp < minstamp) {
177755f5292cSFrank Van Der Linden 			minstamp = stamp;
177855f5292cSFrank Van Der Linden 			*cpuidp = cpuid;
177955f5292cSFrank Van Der Linden 			*recp = rec;
178055f5292cSFrank Van Der Linden 			*consp = cons;
1781349b53ddSStuart Maybee 		}
178255f5292cSFrank Van Der Linden 	}
1783349b53ddSStuart Maybee 
178455f5292cSFrank Van Der Linden 	if (minstamp != ~0ULL)
178555f5292cSFrank Van Der Linden 		return (1);
178655f5292cSFrank Van Der Linden 
178755f5292cSFrank Van Der Linden 	return (0);
178855f5292cSFrank Van Der Linden }
178955f5292cSFrank Van Der Linden 
179055f5292cSFrank Van Der Linden /*ARGSUSED*/
179155f5292cSFrank Van Der Linden static void
xdt_tbuf_scan(void * arg)179255f5292cSFrank Van Der Linden xdt_tbuf_scan(void *arg)
179355f5292cSFrank Van Der Linden {
179455f5292cSFrank Van Der Linden 	uint32_t bytes_done, cons;
179555f5292cSFrank Van Der Linden 	struct t_rec *rec;
179655f5292cSFrank Van Der Linden 	xdt_schedinfo_t *sp;
179755f5292cSFrank Van Der Linden 	uint_t nrecs, cpuid;
179855f5292cSFrank Van Der Linden 
179955f5292cSFrank Van Der Linden 	for (nrecs = 0;
180055f5292cSFrank Van Der Linden 	    nrecs < xdt_max_recs && xdt_get_first_rec(&cpuid, &rec, &cons) > 0;
180155f5292cSFrank Van Der Linden 	    nrecs++) {
180255f5292cSFrank Van Der Linden 		xdt_curpcpu = cpuid;
180355f5292cSFrank Van Der Linden 		sp = &xdt_cpu_schedinfo[cpuid];
180455f5292cSFrank Van Der Linden 		if (sp->curinfo_valid)
180555f5292cSFrank Van Der Linden 			xdt_update_domain_context(sp->cur_domid,
180655f5292cSFrank Van Der Linden 			    sp->cur_vcpuid);
180755f5292cSFrank Van Der Linden 
180855f5292cSFrank Van Der Linden 		bytes_done = xdt_process_rec(cpuid, rec);
180955f5292cSFrank Van Der Linden 		cons += bytes_done;
181055f5292cSFrank Van Der Linden 		/*
181155f5292cSFrank Van Der Linden 		 * cons and prod are incremented modulo (2 * tbuf_data_size).
181255f5292cSFrank Van Der Linden 		 * See <xen/public/trace.h>.
181355f5292cSFrank Van Der Linden 		 */
181455f5292cSFrank Van Der Linden 		if (cons >= 2 * tbuf_data_size)
181555f5292cSFrank Van Der Linden 			cons -= 2 * tbuf_data_size;
181655f5292cSFrank Van Der Linden 		membar_exit();
181755f5292cSFrank Van Der Linden 		tbuf.meta[cpuid]->cons = cons;
1818c7158ae9Stariq 	}
1819c7158ae9Stariq }
1820c7158ae9Stariq 
1821c7158ae9Stariq static void
xdt_cyclic_enable(void)1822c7158ae9Stariq xdt_cyclic_enable(void)
1823c7158ae9Stariq {
1824c7158ae9Stariq 	cyc_handler_t hdlr;
1825c7158ae9Stariq 	cyc_time_t when;
1826c7158ae9Stariq 
1827c7158ae9Stariq 	ASSERT(MUTEX_HELD(&cpu_lock));
1828c7158ae9Stariq 
1829c7158ae9Stariq 	hdlr.cyh_func = xdt_tbuf_scan;
1830c7158ae9Stariq 	hdlr.cyh_arg = NULL;
1831c7158ae9Stariq 	hdlr.cyh_level = CY_LOW_LEVEL;
1832c7158ae9Stariq 
1833c7158ae9Stariq 	when.cyt_interval = xdt_poll_nsec;
1834c7158ae9Stariq 	when.cyt_when = dtrace_gethrtime() + when.cyt_interval;
1835c7158ae9Stariq 
1836c7158ae9Stariq 	xdt_cyclic = cyclic_add(&hdlr, &when);
1837c7158ae9Stariq }
1838c7158ae9Stariq 
1839c7158ae9Stariq static void
xdt_probe_create(xdt_probe_t * p)1840c7158ae9Stariq xdt_probe_create(xdt_probe_t *p)
1841c7158ae9Stariq {
1842c7158ae9Stariq 	ASSERT(p != NULL && p->pr_mod != NULL);
1843c7158ae9Stariq 
1844c7158ae9Stariq 	if (dtrace_probe_lookup(xdt_id, p->pr_mod, NULL, p->pr_name) != 0)
1845c7158ae9Stariq 		return;
1846c7158ae9Stariq 
1847c7158ae9Stariq 	xdt_prid[p->evt_id] = dtrace_probe_create(xdt_id, p->pr_mod, NULL,
1848c7158ae9Stariq 	    p->pr_name, dtrace_mach_aframes(), p);
1849c7158ae9Stariq }
1850c7158ae9Stariq 
1851c7158ae9Stariq /*ARGSUSED*/
1852c7158ae9Stariq static void
xdt_provide(void * arg,const dtrace_probedesc_t * desc)1853c7158ae9Stariq xdt_provide(void *arg, const dtrace_probedesc_t *desc)
1854c7158ae9Stariq {
1855c7158ae9Stariq 	const char *mod, *name;
1856c7158ae9Stariq 	int i;
1857c7158ae9Stariq 
1858c7158ae9Stariq 	if (desc == NULL) {
1859c7158ae9Stariq 		for (i = 0; xdt_probe[i].pr_mod != NULL; i++) {
1860c7158ae9Stariq 			xdt_probe_create(&xdt_probe[i]);
1861c7158ae9Stariq 		}
1862c7158ae9Stariq 	} else {
1863c7158ae9Stariq 		mod = desc->dtpd_mod;
1864c7158ae9Stariq 		name = desc->dtpd_name;
1865c7158ae9Stariq 		for (i = 0; xdt_probe[i].pr_mod != NULL; i++) {
1866c7158ae9Stariq 			int l1 = strlen(xdt_probe[i].pr_name);
1867c7158ae9Stariq 			int l2 = strlen(xdt_probe[i].pr_mod);
1868c7158ae9Stariq 			if (strncmp(name, xdt_probe[i].pr_name, l1) == 0 &&
1869c7158ae9Stariq 			    strncmp(mod, xdt_probe[i].pr_mod, l2) == 0)
1870c7158ae9Stariq 				break;
1871c7158ae9Stariq 		}
1872c7158ae9Stariq 
1873c7158ae9Stariq 		if (xdt_probe[i].pr_mod == NULL)
1874c7158ae9Stariq 			return;
1875c7158ae9Stariq 		xdt_probe_create(&xdt_probe[i]);
1876c7158ae9Stariq 	}
1877c7158ae9Stariq 
1878c7158ae9Stariq }
1879c7158ae9Stariq 
1880c7158ae9Stariq /*ARGSUSED*/
1881c7158ae9Stariq static void
xdt_destroy(void * arg,dtrace_id_t id,void * parg)1882c7158ae9Stariq xdt_destroy(void *arg, dtrace_id_t id, void *parg)
1883c7158ae9Stariq {
1884c7158ae9Stariq 	xdt_probe_t *p = parg;
1885c7158ae9Stariq 	xdt_prid[p->evt_id] = 0;
1886c7158ae9Stariq }
1887c7158ae9Stariq 
1888c7158ae9Stariq static void
xdt_set_trace_mask(uint32_t mask)1889c7158ae9Stariq xdt_set_trace_mask(uint32_t mask)
1890c7158ae9Stariq {
1891c7158ae9Stariq 	xen_sysctl_tbuf_op_t tbuf_op;
1892c7158ae9Stariq 
189355f5292cSFrank Van Der Linden 	/* Always need to trace scheduling, for context */
189455f5292cSFrank Van Der Linden 	if (mask != 0)
189555f5292cSFrank Van Der Linden 		mask |= TRC_SCHED;
1896c7158ae9Stariq 	tbuf_op.evt_mask = mask;
189755f5292cSFrank Van Der Linden 	tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_set_evt_mask;
1898c7158ae9Stariq 	(void) xdt_sysctl_tbuf(&tbuf_op);
1899c7158ae9Stariq }
1900c7158ae9Stariq 
1901c7158ae9Stariq /*ARGSUSED*/
1902b9e93c10SJonathan Haslam static int
xdt_enable(void * arg,dtrace_id_t id,void * parg)1903c7158ae9Stariq xdt_enable(void *arg, dtrace_id_t id, void *parg)
1904c7158ae9Stariq {
1905c7158ae9Stariq 	xdt_probe_t *p = parg;
1906c7158ae9Stariq 	xen_sysctl_tbuf_op_t tbuf_op;
1907c7158ae9Stariq 
1908c7158ae9Stariq 	ASSERT(MUTEX_HELD(&cpu_lock));
1909c7158ae9Stariq 	ASSERT(xdt_prid[p->evt_id] != 0);
1910c7158ae9Stariq 
1911c7158ae9Stariq 	xdt_probemap[p->evt_id] = xdt_prid[p->evt_id];
1912c7158ae9Stariq 	xdt_classinfo[p->class].cnt++;
1913c7158ae9Stariq 
1914c7158ae9Stariq 	if (xdt_classinfo[p->class].cnt == 1) {
1915c7158ae9Stariq 		/* set the trace mask for this class */
1916c7158ae9Stariq 		cur_trace_mask |= xdt_classinfo[p->class].trc_mask;
1917c7158ae9Stariq 		xdt_set_trace_mask(cur_trace_mask);
1918c7158ae9Stariq 	}
1919c7158ae9Stariq 
1920c7158ae9Stariq 	if (xdt_cyclic == CYCLIC_NONE) {
1921c7158ae9Stariq 		tbuf_op.cmd = XEN_SYSCTL_TBUFOP_enable;
1922c7158ae9Stariq 		if (xdt_sysctl_tbuf(&tbuf_op) != 0) {
1923c7158ae9Stariq 			cmn_err(CE_NOTE, "Couldn't enable hypervisor tracing.");
1924b9e93c10SJonathan Haslam 			return (-1);
1925c7158ae9Stariq 		}
1926c7158ae9Stariq 
1927c7158ae9Stariq 		xdt_cyclic_enable();
1928c7158ae9Stariq 	}
1929b9e93c10SJonathan Haslam 	return (0);
1930c7158ae9Stariq }
1931c7158ae9Stariq 
1932c7158ae9Stariq /*ARGSUSED*/
1933c7158ae9Stariq static void
xdt_disable(void * arg,dtrace_id_t id,void * parg)1934c7158ae9Stariq xdt_disable(void *arg, dtrace_id_t id, void *parg)
1935c7158ae9Stariq {
1936c7158ae9Stariq 	xdt_probe_t *p = parg;
1937c7158ae9Stariq 	xen_sysctl_tbuf_op_t tbuf_op;
1938c7158ae9Stariq 	int i, err;
1939c7158ae9Stariq 
1940c7158ae9Stariq 	ASSERT(MUTEX_HELD(&cpu_lock));
1941c7158ae9Stariq 	ASSERT(xdt_probemap[p->evt_id] != 0);
1942c7158ae9Stariq 	ASSERT(xdt_probemap[p->evt_id] == xdt_prid[p->evt_id]);
1943c7158ae9Stariq 	ASSERT(xdt_classinfo[p->class].cnt > 0);
1944c7158ae9Stariq 
1945c7158ae9Stariq 	/*
1946c7158ae9Stariq 	 * We could be here in the slight window between the cyclic firing and
1947c7158ae9Stariq 	 * a call to dtrace_probe() occurring. We need to be careful if we tear
1948c7158ae9Stariq 	 * down any shared state.
1949c7158ae9Stariq 	 */
1950c7158ae9Stariq 
1951c7158ae9Stariq 	xdt_probemap[p->evt_id] = 0;
1952c7158ae9Stariq 	xdt_classinfo[p->class].cnt--;
1953c7158ae9Stariq 
1954c7158ae9Stariq 	if (xdt_nr_active_probes() == 0) {
1955c7158ae9Stariq 		cur_trace_mask = 0;
1956c7158ae9Stariq 
1957c7158ae9Stariq 		if (xdt_cyclic == CYCLIC_NONE)
1958c7158ae9Stariq 			return;
1959c7158ae9Stariq 
196055f5292cSFrank Van Der Linden 		for (i = 0; i < xdt_ncpus; i++)
196155f5292cSFrank Van Der Linden 			xdt_cpu_schedinfo[i].curinfo_valid = 0;
196255f5292cSFrank Van Der Linden 
1963c7158ae9Stariq 		/*
1964c7158ae9Stariq 		 * We will try to disable the trace buffers. If we fail for some
1965c7158ae9Stariq 		 * reason we will try again, up to a count of XDT_TBUF_RETRY.
1966c7158ae9Stariq 		 * If we still aren't successful we try to set the trace mask
1967c7158ae9Stariq 		 * to 0 in order to prevent trace records from being written.
1968c7158ae9Stariq 		 */
1969c7158ae9Stariq 		tbuf_op.cmd = XEN_SYSCTL_TBUFOP_disable;
1970c7158ae9Stariq 		i = 0;
1971c7158ae9Stariq 		do {
1972c7158ae9Stariq 			err = xdt_sysctl_tbuf(&tbuf_op);
1973c7158ae9Stariq 		} while ((err != 0) && (++i < XDT_TBUF_RETRY));
1974c7158ae9Stariq 
1975c7158ae9Stariq 		if (err != 0) {
1976c7158ae9Stariq 			cmn_err(CE_NOTE,
1977c7158ae9Stariq 			    "Couldn't disable hypervisor tracing.");
1978c7158ae9Stariq 			xdt_set_trace_mask(0);
1979c7158ae9Stariq 		} else {
1980c7158ae9Stariq 			cyclic_remove(xdt_cyclic);
1981c7158ae9Stariq 			xdt_cyclic = CYCLIC_NONE;
1982c7158ae9Stariq 			/*
1983c7158ae9Stariq 			 * We don't bother making the hypercall to set
1984c7158ae9Stariq 			 * the trace mask, since it will be reset when
1985c7158ae9Stariq 			 * tracing is re-enabled.
1986c7158ae9Stariq 			 */
1987c7158ae9Stariq 		}
1988c7158ae9Stariq 	} else if (xdt_classinfo[p->class].cnt == 0) {
1989c7158ae9Stariq 		cur_trace_mask ^= xdt_classinfo[p->class].trc_mask;
1990c7158ae9Stariq 		/* other probes are enabled, so add the sub-class mask back */
1991c7158ae9Stariq 		cur_trace_mask |= 0xF000;
1992c7158ae9Stariq 		xdt_set_trace_mask(cur_trace_mask);
1993c7158ae9Stariq 	}
1994c7158ae9Stariq }
1995c7158ae9Stariq 
1996c7158ae9Stariq static dtrace_pattr_t xdt_attr = {
1997c7158ae9Stariq { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM },
1998c7158ae9Stariq { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM },
1999c7158ae9Stariq { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
2000c7158ae9Stariq { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM },
2001c7158ae9Stariq { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM },
2002c7158ae9Stariq };
2003c7158ae9Stariq 
2004c7158ae9Stariq static dtrace_pops_t xdt_pops = {
2005c7158ae9Stariq 	xdt_provide,		/* dtps_provide() */
2006c7158ae9Stariq 	NULL,			/* dtps_provide_module() */
2007c7158ae9Stariq 	xdt_enable,		/* dtps_enable() */
2008c7158ae9Stariq 	xdt_disable,		/* dtps_disable() */
2009c7158ae9Stariq 	NULL,			/* dtps_suspend() */
2010c7158ae9Stariq 	NULL,			/* dtps_resume() */
2011c7158ae9Stariq 	NULL,			/* dtps_getargdesc() */
2012c7158ae9Stariq 	NULL,			/* dtps_getargval() */
2013c7158ae9Stariq 	NULL,			/* dtps_usermode() */
2014c7158ae9Stariq 	xdt_destroy		/* dtps_destroy() */
2015c7158ae9Stariq };
2016c7158ae9Stariq 
2017c7158ae9Stariq static int
xdt_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)2018c7158ae9Stariq xdt_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
2019c7158ae9Stariq {
2020c7158ae9Stariq 	int val;
2021c7158ae9Stariq 
2022c7158ae9Stariq 	if (!DOMAIN_IS_INITDOMAIN(xen_info))
2023c7158ae9Stariq 		return (DDI_FAILURE);
2024c7158ae9Stariq 
2025c7158ae9Stariq 	switch (cmd) {
2026c7158ae9Stariq 	case DDI_ATTACH:
2027c7158ae9Stariq 		break;
2028c7158ae9Stariq 
2029c7158ae9Stariq 	case DDI_RESUME:
2030c7158ae9Stariq 		/*
2031c7158ae9Stariq 		 * We might support proper suspend/resume in the future, so,
2032c7158ae9Stariq 		 * return DDI_FAILURE for now.
2033c7158ae9Stariq 		 */
2034c7158ae9Stariq 		return (DDI_FAILURE);
2035c7158ae9Stariq 
2036c7158ae9Stariq 	default:
2037c7158ae9Stariq 		return (DDI_FAILURE);
2038c7158ae9Stariq 	}
2039c7158ae9Stariq 
2040349b53ddSStuart Maybee 	xdt_ncpus = xpv_nr_phys_cpus();
2041c7158ae9Stariq 	ASSERT(xdt_ncpus > 0);
2042c7158ae9Stariq 
2043c7158ae9Stariq 	if (ddi_create_minor_node(devi, "xdt", S_IFCHR, 0, DDI_PSEUDO, 0) ==
2044c7158ae9Stariq 	    DDI_FAILURE || xdt_attach_trace_buffers() != 0 ||
2045c7158ae9Stariq 	    dtrace_register("xdt", &xdt_attr, DTRACE_PRIV_KERNEL, NULL,
2046c7158ae9Stariq 	    &xdt_pops, NULL, &xdt_id) != 0) {
2047c7158ae9Stariq 		if (tbuf.va != NULL)
2048c7158ae9Stariq 			xdt_detach_trace_buffers();
2049c7158ae9Stariq 		ddi_remove_minor_node(devi, NULL);
2050c7158ae9Stariq 		return (DDI_FAILURE);
2051c7158ae9Stariq 	}
2052c7158ae9Stariq 
2053c7158ae9Stariq 	val = ddi_getprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
2054c7158ae9Stariq 	    "xdt_poll_nsec", XDT_POLL_DEFAULT);
2055c7158ae9Stariq 	xdt_poll_nsec = MAX(val, XDT_POLL_MIN);
2056c7158ae9Stariq 
205755f5292cSFrank Van Der Linden 	xdt_cpu_schedinfo = (xdt_schedinfo_t *)kmem_zalloc(xdt_ncpus *
2058c7158ae9Stariq 	    sizeof (xdt_schedinfo_t), KM_SLEEP);
2059c7158ae9Stariq 	xdt_init_trace_masks();
2060c7158ae9Stariq 	xdt_kstat_init();
2061c7158ae9Stariq 
2062c7158ae9Stariq 	xdt_devi = devi;
2063c7158ae9Stariq 	ddi_report_dev(devi);
2064c7158ae9Stariq 	return (DDI_SUCCESS);
2065c7158ae9Stariq }
2066c7158ae9Stariq 
2067c7158ae9Stariq static int
xdt_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)2068c7158ae9Stariq xdt_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
2069c7158ae9Stariq {
2070c7158ae9Stariq 	switch (cmd) {
2071c7158ae9Stariq 	case DDI_DETACH:
2072c7158ae9Stariq 		break;
2073c7158ae9Stariq 
2074c7158ae9Stariq 	case DDI_SUSPEND:
2075c7158ae9Stariq 		/*
2076c7158ae9Stariq 		 * We might support proper suspend/resume in the future. So
2077c7158ae9Stariq 		 * return DDI_FAILURE for now.
2078c7158ae9Stariq 		 */
2079c7158ae9Stariq 		return (DDI_FAILURE);
2080c7158ae9Stariq 
2081c7158ae9Stariq 	default:
2082c7158ae9Stariq 		return (DDI_FAILURE);
2083c7158ae9Stariq 	}
2084c7158ae9Stariq 
2085c7158ae9Stariq 	if (dtrace_unregister(xdt_id) != 0)
2086c7158ae9Stariq 		return (DDI_FAILURE);
2087c7158ae9Stariq 
2088c7158ae9Stariq 	xdt_detach_trace_buffers();
2089c7158ae9Stariq 	kmem_free(xdt_cpu_schedinfo, xdt_ncpus * sizeof (xdt_schedinfo_t));
2090c7158ae9Stariq 	if (xdt_cyclic != CYCLIC_NONE)
2091c7158ae9Stariq 		cyclic_remove(xdt_cyclic);
2092c7158ae9Stariq 	if (xdt_kstats != NULL)
2093c7158ae9Stariq 		kstat_delete(xdt_kstats);
2094c7158ae9Stariq 	xdt_devi = (void *)0;
2095c7158ae9Stariq 	ddi_remove_minor_node(devi, NULL);
2096c7158ae9Stariq 
2097c7158ae9Stariq 	return (DDI_SUCCESS);
2098c7158ae9Stariq }
2099c7158ae9Stariq 
2100c7158ae9Stariq /*ARGSUSED*/
2101c7158ae9Stariq static int
xdt_info(dev_info_t * devi,ddi_info_cmd_t infocmd,void * arg,void ** result)2102c7158ae9Stariq xdt_info(dev_info_t *devi, ddi_info_cmd_t infocmd, void *arg, void **result)
2103c7158ae9Stariq {
2104c7158ae9Stariq 	int error;
2105c7158ae9Stariq 
2106c7158ae9Stariq 	switch (infocmd) {
2107c7158ae9Stariq 	case DDI_INFO_DEVT2DEVINFO:
2108c7158ae9Stariq 		*result = xdt_devi;
2109c7158ae9Stariq 		error = DDI_SUCCESS;
2110c7158ae9Stariq 		break;
2111c7158ae9Stariq 	case DDI_INFO_DEVT2INSTANCE:
2112c7158ae9Stariq 		*result = (void *)0;
2113c7158ae9Stariq 		error = DDI_SUCCESS;
2114c7158ae9Stariq 		break;
2115c7158ae9Stariq 	default:
2116c7158ae9Stariq 		error = DDI_FAILURE;
2117c7158ae9Stariq 	}
2118c7158ae9Stariq 	return (error);
2119c7158ae9Stariq }
2120c7158ae9Stariq 
2121c7158ae9Stariq static struct cb_ops xdt_cb_ops = {
2122c7158ae9Stariq 	nulldev,		/* open(9E) */
2123c7158ae9Stariq 	nodev,			/* close(9E) */
2124c7158ae9Stariq 	nodev,			/* strategy(9E) */
2125c7158ae9Stariq 	nodev,			/* print(9E) */
2126c7158ae9Stariq 	nodev,			/* dump(9E) */
2127c7158ae9Stariq 	nodev,			/* read(9E) */
2128c7158ae9Stariq 	nodev,			/* write(9E) */
2129c7158ae9Stariq 	nodev,			/* ioctl(9E) */
2130c7158ae9Stariq 	nodev,			/* devmap(9E) */
2131c7158ae9Stariq 	nodev,			/* mmap(9E) */
2132c7158ae9Stariq 	nodev,			/* segmap(9E) */
2133c7158ae9Stariq 	nochpoll,		/* chpoll(9E) */
2134c7158ae9Stariq 	ddi_prop_op,		/* prop_op(9E) */
2135c7158ae9Stariq 	NULL,			/* streamtab(9S) */
2136c7158ae9Stariq 	D_MP | D_64BIT | D_NEW	/* cb_flag */
2137c7158ae9Stariq };
2138c7158ae9Stariq 
2139c7158ae9Stariq static struct dev_ops xdt_ops = {
2140c7158ae9Stariq 	DEVO_REV,		/* devo_rev */
2141c7158ae9Stariq 	0,			/* devo_refcnt */
2142c7158ae9Stariq 	xdt_info,		/* getinfo(9E) */
2143c7158ae9Stariq 	nulldev,		/* identify(9E) */
2144c7158ae9Stariq 	nulldev,		/* probe(9E) */
2145c7158ae9Stariq 	xdt_attach,		/* attach(9E) */
2146c7158ae9Stariq 	xdt_detach,		/* detach(9E) */
2147c7158ae9Stariq 	nulldev,		/* devo_reset */
2148c7158ae9Stariq 	&xdt_cb_ops,		/* devo_cb_ops */
2149c7158ae9Stariq 	NULL,			/* devo_bus_ops */
215019397407SSherry Moore 	NULL,			/* power(9E) */
2151349b53ddSStuart Maybee 	ddi_quiesce_not_needed,	/* devo_quiesce */
2152c7158ae9Stariq };
2153c7158ae9Stariq 
2154c7158ae9Stariq 
2155c7158ae9Stariq static struct modldrv modldrv = {
2156c7158ae9Stariq 	&mod_driverops,
2157c7158ae9Stariq 	"Hypervisor event tracing",
2158c7158ae9Stariq 	&xdt_ops
2159c7158ae9Stariq };
2160c7158ae9Stariq 
2161c7158ae9Stariq static struct modlinkage modlinkage = {
2162c7158ae9Stariq 	MODREV_1,
2163c7158ae9Stariq 	&modldrv,
2164c7158ae9Stariq 	NULL
2165c7158ae9Stariq };
2166c7158ae9Stariq 
2167c7158ae9Stariq int
_init(void)2168c7158ae9Stariq _init(void)
2169c7158ae9Stariq {
2170c7158ae9Stariq 	return (mod_install(&modlinkage));
2171c7158ae9Stariq }
2172c7158ae9Stariq 
2173c7158ae9Stariq int
_fini(void)2174c7158ae9Stariq _fini(void)
2175c7158ae9Stariq {
2176c7158ae9Stariq 	return (mod_remove(&modlinkage));
2177c7158ae9Stariq }
2178c7158ae9Stariq 
2179c7158ae9Stariq int
_info(struct modinfo * modinfop)2180c7158ae9Stariq _info(struct modinfo *modinfop)
2181c7158ae9Stariq {
2182c7158ae9Stariq 	return (mod_info(&modlinkage, modinfop));
2183c7158ae9Stariq }
2184