xref: /onnv-gate/usr/src/uts/common/xen/dtrace/xdt.c (revision 11153:dec430d20576)
16670Stariq /*
26670Stariq  * CDDL HEADER START
36670Stariq  *
46670Stariq  * The contents of this file are subject to the terms of the
56670Stariq  * Common Development and Distribution License (the "License").
66670Stariq  * You may not use this file except in compliance with the License.
76670Stariq  *
86670Stariq  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96670Stariq  * or http://www.opensolaris.org/os/licensing.
106670Stariq  * See the License for the specific language governing permissions
116670Stariq  * and limitations under the License.
126670Stariq  *
136670Stariq  * When distributing Covered Code, include this CDDL HEADER in each
146670Stariq  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156670Stariq  * If applicable, add the following below this CDDL HEADER, with the
166670Stariq  * fields enclosed by brackets "[]" replaced with your own identifying
176670Stariq  * information: Portions Copyright [yyyy] [name of copyright owner]
186670Stariq  *
196670Stariq  * CDDL HEADER END
206670Stariq  */
216670Stariq 
226670Stariq /*
238803SJonathan.Haslam@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
246670Stariq  * Use is subject to license terms.
256670Stariq  */
266670Stariq 
276670Stariq /*
286670Stariq  * Xen event provider for DTrace
296670Stariq  *
306670Stariq  * NOTE: This provider is PRIVATE. It is intended as a short-term solution and
316670Stariq  * may disappear or be re-implemented at anytime.
326670Stariq  *
336670Stariq  * This provider isn't suitable as a general-purpose solution for a number of
346670Stariq  * reasons. First and foremost, we rely on the Xen tracing mechanism and don't
356670Stariq  * have any way to gather data other than that collected by the Xen trace
366670Stariq  * buffers. Further, it does not fit into the DTrace model (see "Interacting
376670Stariq  * with DTrace" below.)
386670Stariq  *
396670Stariq  *
406670Stariq  * Tracing in Xen
416670Stariq  * --------------
426670Stariq  *
436670Stariq  * Xen implements a tracing facility for generating and collecting execution
446670Stariq  * event traces from the hypervisor. When tracing is enabled, compiled in
456670Stariq  * probes record events in contiguous per-CPU trace buffers.
466670Stariq  *
476670Stariq  *               +---------+
486670Stariq  * +------+      |         |
496670Stariq  * | CPUn |----> | BUFFERn |
506670Stariq  * +------+      |         |
516670Stariq  *               +---------+- tbuf.va + (tbuf.size * n)
526670Stariq  *               :         :
536670Stariq  *               +---------+
546670Stariq  * +------+      |         |
556670Stariq  * | CPU1 |----> | BUFFER1 |
566670Stariq  * +------+      |         |
576670Stariq  *               +---------+- tbuf.va + tbuf.size
586670Stariq  * +------+      |         |
596670Stariq  * | CPU0 |----> | BUFFER0 |
606670Stariq  * +------+      |         |
616670Stariq  *               +---------+- tbuf.va
626670Stariq  *
636670Stariq  * Each CPU buffer consists of a metadata header followed by the trace records.
646670Stariq  * The metadata consists of a producer/consumer pair of pointers into the buffer
656670Stariq  * that point to the next record to be written and the next record to be read
6610175SStuart.Maybee@Sun.COM  * respectively.
6710175SStuart.Maybee@Sun.COM  *
6810175SStuart.Maybee@Sun.COM  * A trace record can be in one of two forms, depending on if the TSC is
6910175SStuart.Maybee@Sun.COM  * included. The record header indicates whether or not the TSC field is
7010175SStuart.Maybee@Sun.COM  * present.
716670Stariq  *
7210175SStuart.Maybee@Sun.COM  * 1. Trace record without TSC:
7310175SStuart.Maybee@Sun.COM  * +------------------------------------------------------------+
7410175SStuart.Maybee@Sun.COM  * | HEADER(uint32_t) |            DATA FIELDS                  |
7510175SStuart.Maybee@Sun.COM  * +------------------------------------------------------------+
7610175SStuart.Maybee@Sun.COM  *
7710175SStuart.Maybee@Sun.COM  * 2. Trace record with TSC:
786670Stariq  * +--------------------------------------------------------------------------+
7910175SStuart.Maybee@Sun.COM  * | HEADER(uint32_t) | TSC(uint64_t) |              DATA FIELDS              |
8010175SStuart.Maybee@Sun.COM  * +--------------------------------------------------------------------------+
8110175SStuart.Maybee@Sun.COM  *
8210175SStuart.Maybee@Sun.COM  * Where,
8310175SStuart.Maybee@Sun.COM  *
8410175SStuart.Maybee@Sun.COM  * HEADER bit field:
856670Stariq  * +--------------------------------------------------------------------------+
8610175SStuart.Maybee@Sun.COM  * | C |  NDATA  |                        EVENT                               |
8710175SStuart.Maybee@Sun.COM  * +--------------------------------------------------------------------------+
8810175SStuart.Maybee@Sun.COM  *  31  30     28 27                                                         0
8910175SStuart.Maybee@Sun.COM  *
9010175SStuart.Maybee@Sun.COM  * EVENT: Event ID.
9110175SStuart.Maybee@Sun.COM  * NDATA: Number of populated data fields.
9210175SStuart.Maybee@Sun.COM  *     C: TSC included.
936670Stariq  *
946670Stariq  * DATA FIELDS:
956670Stariq  * +--------------------------------------------------------------------------+
9610175SStuart.Maybee@Sun.COM  * | D1(uint32_t) | D2(uint32_t) | D3(uint32_t) |     . . .    | D7(uint32_t) |
976670Stariq  * +--------------------------------------------------------------------------+
986670Stariq  *
996670Stariq  *
1006670Stariq  * Interacting with DTrace
1016670Stariq  * -----------------------
1026670Stariq  *
1036670Stariq  * Every xdt_poll_nsec nano-seconds we poll the trace buffers for data and feed
1046670Stariq  * each entry into dtrace_probe() with the corresponding probe ID for the event.
1056670Stariq  * As a result of this periodic collection implementation probe firings are
1066670Stariq  * asynchronous. This is the only sensible way to implement this form of
1076670Stariq  * provider, but because of its asynchronous nature asking things like
1086670Stariq  * "current CPU" and, more importantly, arbitrary questions about the context
1096670Stariq  * surrounding the probe firing are not meaningful. So, consumers should not
1106670Stariq  * attempt to infer anything beyond what is supplied via the probe arguments.
1116670Stariq  */
1126670Stariq 
11310175SStuart.Maybee@Sun.COM #include <sys/xpv_user.h>
11410175SStuart.Maybee@Sun.COM 
1156670Stariq #include <sys/types.h>
1166670Stariq #include <sys/sysmacros.h>
1176670Stariq #include <sys/modctl.h>
1186670Stariq #include <sys/sunddi.h>
1196670Stariq #include <sys/ddi.h>
1206670Stariq #include <sys/conf.h>
1216670Stariq #include <sys/devops.h>
1226670Stariq #include <sys/stat.h>
1236670Stariq #include <sys/cmn_err.h>
1246670Stariq #include <sys/dtrace.h>
1256670Stariq #include <sys/sdt.h>
1266670Stariq #include <sys/cyclic.h>
1276670Stariq #include <vm/seg_kmem.h>
1286670Stariq #include <vm/hat_i86.h>
12910175SStuart.Maybee@Sun.COM 
1306670Stariq #include <sys/hypervisor.h>
1316670Stariq #include <xen/public/trace.h>
1326670Stariq #include <xen/public/sched.h>
1336670Stariq 
1346670Stariq #define	XDT_POLL_DEFAULT	100000000	/* default poll interval (ns) */
1356670Stariq #define	XDT_POLL_MIN		10000000	/* min poll interval (ns) */
1366670Stariq #define	XDT_TBUF_RETRY		50		/* tbuf disable retry count */
1376670Stariq 
1386670Stariq /*
1396670Stariq  * The domid must match IDLE_DOMAIN_ID in xen.hg/xen/include/xen/sched.h
1406670Stariq  * in the xVM gate.
1416670Stariq  */
1426670Stariq #define	IS_IDLE_DOM(domid)	(domid == 0x7FFFU)
1436670Stariq 
1446670Stariq /* Macros to extract the domid and cpuid from a HVM trace data field */
1456670Stariq #define	HVM_DOMID(d)		(d >> 16)
1466670Stariq #define	HVM_VCPUID(d)		(d & 0xFFFF)
1476670Stariq 
148*11153SFrank.Vanderlinden@Sun.COM /* Flags for shadow page table events */
149*11153SFrank.Vanderlinden@Sun.COM #define	SH_GUEST_32	0x000
150*11153SFrank.Vanderlinden@Sun.COM #define	SH_GUEST_PAE	0x100
151*11153SFrank.Vanderlinden@Sun.COM #define	SH_GUEST_64	0x200
152*11153SFrank.Vanderlinden@Sun.COM 
153*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PROBE5(event, arg0, arg1, arg2, arg3, arg4) {		\
1546670Stariq 	dtrace_id_t id = xdt_probemap[event];				\
1556670Stariq 	if (id)								\
156*11153SFrank.Vanderlinden@Sun.COM 		dtrace_probe(id, arg0, arg1, arg2, arg3, arg4);		\
1576670Stariq }									\
1586670Stariq 
159*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PROBE4(event, arg0, arg1, arg2, arg3) \
160*11153SFrank.Vanderlinden@Sun.COM 	XDT_PROBE5(event, arg0, arg1, arg2, arg3, 0)
1616670Stariq 
162*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PROBE3(event, arg0, arg1, arg2) \
163*11153SFrank.Vanderlinden@Sun.COM 	XDT_PROBE5(event, arg0, arg1, arg2, 0, 0)
1646670Stariq 
165*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PROBE2(event, arg0, arg1) \
166*11153SFrank.Vanderlinden@Sun.COM 	XDT_PROBE5(event, arg0, arg1, 0, 0, 0)
1676670Stariq 
168*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PROBE1(event, arg0) \
169*11153SFrank.Vanderlinden@Sun.COM 	XDT_PROBE5(event, arg0, 0, 0, 0, 0)
170*11153SFrank.Vanderlinden@Sun.COM 
171*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PROBE0(event) \
172*11153SFrank.Vanderlinden@Sun.COM 	XDT_PROBE5(event, 0, 0, 0, 0, 0)
1736670Stariq 
1746670Stariq /* Probe classes */
1756670Stariq #define	XDT_SCHED			0
1766670Stariq #define	XDT_MEM				1
1776670Stariq #define	XDT_HVM				2
17810175SStuart.Maybee@Sun.COM #define	XDT_GEN				3
179*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PV				4
180*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW			5
181*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PM				6
182*11153SFrank.Vanderlinden@Sun.COM #define	XDT_NCLASSES			7
1836670Stariq 
1846670Stariq /* Probe events */
1856670Stariq #define	XDT_EVT_INVALID			(-(int)1)
1866670Stariq #define	XDT_SCHED_OFF_CPU		0
1876670Stariq #define	XDT_SCHED_ON_CPU		1
1886670Stariq #define	XDT_SCHED_IDLE_OFF_CPU		2
1896670Stariq #define	XDT_SCHED_IDLE_ON_CPU		3
1906670Stariq #define	XDT_SCHED_BLOCK			4
1916670Stariq #define	XDT_SCHED_SLEEP			5
1926670Stariq #define	XDT_SCHED_WAKE			6
1936670Stariq #define	XDT_SCHED_YIELD			7
1946670Stariq #define	XDT_SCHED_SHUTDOWN_POWEROFF	8
1956670Stariq #define	XDT_SCHED_SHUTDOWN_REBOOT	9
1966670Stariq #define	XDT_SCHED_SHUTDOWN_SUSPEND	10
1976670Stariq #define	XDT_SCHED_SHUTDOWN_CRASH	11
1986670Stariq #define	XDT_MEM_PAGE_GRANT_MAP		12
1996670Stariq #define	XDT_MEM_PAGE_GRANT_UNMAP	13
2006670Stariq #define	XDT_MEM_PAGE_GRANT_TRANSFER	14
2016670Stariq #define	XDT_HVM_VMENTRY			15
2026670Stariq #define	XDT_HVM_VMEXIT			16
20310175SStuart.Maybee@Sun.COM #define	XDT_TRC_LOST_RECORDS		17
204*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SCHED_ADD_VCPU		18
205*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SCHED_REM_VCPU		19	/* unused */
206*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SCHED_CTL			20	/* unused */
207*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SCHED_ADJDOM		21
208*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SCHED_S_TIMER_FN		22	/* unused */
209*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SCHED_T_TIMER_FN		23	/* unused */
210*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SCHED_DOM_TIMER_FN		24	/* unused */
211*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PV_HYPERCALL		25
212*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PV_TRAP			26
213*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PV_PAGE_FAULT		27
214*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PV_FORCED_INVALID_OP	28
215*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PV_EMULATE_PRIVOP		29
216*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PV_EMULATE_4GB		30	/* unused (32-bit HV only ) */
217*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PV_MATH_STATE_RESTORE	31
218*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PV_PAGING_FIXUP		32
219*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PV_DT_MAPPING_FAULT		33
220*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PV_PTWR_EMULATION		34
221*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_PF_XEN			35
222*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_PF_INJECT		36
223*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_EXC_INJECT		37
224*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_VIRQ_INJECT		38
225*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_VIRQ_REINJECT		39
226*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_IO_READ			40	/* unused */
227*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_IO_WRITE		41	/* unused */
228*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_CR_READ			42
229*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_CR_WRITE		43
230*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_DR_READ			44	/* unused */
231*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_DR_WRITE		45	/* unused */
232*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_MSR_READ		46
233*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_MSR_WRITE		47
234*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_CPUID			48
235*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_INTR			49
236*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_INTR_WINDOW		50
237*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_NMI			51
238*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_SMI			52
239*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_VMMCALL			53
240*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_HLT			54
241*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_INVLPG			55
242*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_MCE			56
243*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_IOPORT_READ		57
244*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_IOPORT_WRITE		58
245*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_CLTS			59
246*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_LMSW			60
247*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_IOMEM_READ		61
248*11153SFrank.Vanderlinden@Sun.COM #define	XDT_HVM_IOMEM_WRITE		62
249*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW_NOT_SHADOW			63
250*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW_FAST_PROPAGATE		64
251*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW_FAST_MMIO			65
252*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW_FALSE_FAST_PATH		66
253*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW_MMIO				67
254*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW_FIXUP			68
255*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW_DOMF_DYING			69
256*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW_EMULATE			70
257*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW_EMULATE_UNSHADOW_USER	71
258*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ	72
259*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED	73
260*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW_WRMAP_BF			74
261*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW_PREALLOC_UNPIN		75
262*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW_RESYNC_FULL			76
263*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SHADOW_RESYNC_ONLY			77
264*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PM_FREQ_CHANGE		78
265*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PM_IDLE_ENTRY		79
266*11153SFrank.Vanderlinden@Sun.COM #define	XDT_PM_IDLE_EXIT		80
267*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SCHED_RUNSTATE_CHANGE	81
268*11153SFrank.Vanderlinden@Sun.COM #define	XDT_SCHED_CONTINUE_RUNNING	82
269*11153SFrank.Vanderlinden@Sun.COM #define	XDT_NEVENTS			83
2706670Stariq 
2716670Stariq typedef struct {
2726670Stariq 	const char	*pr_mod;	/* probe module */
2736670Stariq 	const char	*pr_name;	/* probe name */
2746670Stariq 	int		evt_id;		/* event id */
2756670Stariq 	uint_t		class;		/* probe class */
2766670Stariq } xdt_probe_t;
2776670Stariq 
2786670Stariq typedef struct {
2796670Stariq 	uint32_t	trc_mask;	/* trace mask */
2806670Stariq 	uint32_t	cnt;		/* num enabled probes in class */
2816670Stariq } xdt_classinfo_t;
2826670Stariq 
2836670Stariq typedef struct {
2846670Stariq 	ulong_t prev_domid;		/* previous dom executed */
2856670Stariq 	ulong_t prev_vcpuid;		/* previous vcpu executed */
2866670Stariq 	ulong_t prev_ctime;		/* time spent on cpu */
2876670Stariq 	ulong_t next_domid;		/* next dom to be scheduled */
2886670Stariq 	ulong_t next_vcpuid;		/* next vcpu to be scheduled */
2896670Stariq 	ulong_t next_wtime;		/* time spent waiting to get on cpu */
2906670Stariq 	ulong_t next_ts;		/* allocated time slice */
291*11153SFrank.Vanderlinden@Sun.COM 	ulong_t cur_domid;		/* current dom */
292*11153SFrank.Vanderlinden@Sun.COM 	ulong_t cur_vcpuid;		/* current vcpuid */
293*11153SFrank.Vanderlinden@Sun.COM 	int curinfo_valid;		/* info is valid */
2946670Stariq } xdt_schedinfo_t;
2956670Stariq 
2966670Stariq static struct {
2976670Stariq 	uint_t cnt;			/* total num of trace buffers */
2986670Stariq 	size_t size;			/* size of each cpu buffer */
2996670Stariq 	mfn_t start_mfn;		/* starting mfn of buffers */
3006670Stariq 	caddr_t va;			/* va buffers are mapped into */
3016670Stariq 
3026670Stariq 	/* per-cpu buffers */
3036670Stariq 	struct t_buf **meta;		/* buffer metadata */
3046670Stariq 	struct t_rec **data;		/* buffer data records */
3056670Stariq 
3066670Stariq 	/* statistics */
3076670Stariq 	uint64_t stat_dropped_recs;	/* records dropped */
3086670Stariq 	uint64_t stat_spurious_cpu;	/* recs with garbage cpuids */
3096670Stariq 	uint64_t stat_spurious_switch;	/* inconsistent vcpu switches */
3106670Stariq 	uint64_t stat_unknown_shutdown;	/* unknown shutdown code */
3116670Stariq 	uint64_t stat_unknown_recs;	/* unknown records */
3126670Stariq } tbuf;
3136670Stariq 
314*11153SFrank.Vanderlinden@Sun.COM static size_t tbuf_data_size;
315*11153SFrank.Vanderlinden@Sun.COM 
3166670Stariq static char *xdt_stats[] = {
3176670Stariq 	"dropped_recs",
3186670Stariq };
3196670Stariq 
3206670Stariq /*
3216670Stariq  * Tunable variables
3226670Stariq  *
3236670Stariq  * The following may be tuned by adding a line to /etc/system that
3246670Stariq  * includes both the name of the module ("xdt") and the name of the variable.
3256670Stariq  * For example:
3266670Stariq  *     set xdt:xdt_tbuf_pages = 40
3276670Stariq  */
3286670Stariq uint_t xdt_tbuf_pages = 20;			/* pages to alloc per-cpu buf */
3296670Stariq 
3306670Stariq /*
3316670Stariq  * The following may be tuned by adding a line to
3326670Stariq  * /platform/i86xpv/kernel/drv/xdt.conf.
3336670Stariq  * For example:
3346670Stariq  *     xdt_poll_nsec = 200000000;
3356670Stariq  */
3366670Stariq static hrtime_t xdt_poll_nsec;			/* trace buffer poll interval */
3376670Stariq 
3386670Stariq /*
339*11153SFrank.Vanderlinden@Sun.COM  * Another tunable variable: the maximum number of records to process
340*11153SFrank.Vanderlinden@Sun.COM  * in one scan. If it is 0 (e.g. not set in /etc/system), it will
341*11153SFrank.Vanderlinden@Sun.COM  * be set to ncpu * (bufsize / max_rec_size).
342*11153SFrank.Vanderlinden@Sun.COM  *
343*11153SFrank.Vanderlinden@Sun.COM  * Having an upper limit avoids a situation where the scan would loop
344*11153SFrank.Vanderlinden@Sun.COM  * endlessly in case the hypervisor adds records quicker than we
345*11153SFrank.Vanderlinden@Sun.COM  * can process them. It's better to drop records than to loop, obviously.
346*11153SFrank.Vanderlinden@Sun.COM  */
347*11153SFrank.Vanderlinden@Sun.COM uint_t xdt_max_recs = 0;
348*11153SFrank.Vanderlinden@Sun.COM 
349*11153SFrank.Vanderlinden@Sun.COM /*
3506670Stariq  * Internal variables
3516670Stariq  */
3526670Stariq static dev_info_t *xdt_devi;
3536670Stariq static dtrace_provider_id_t xdt_id;
3546670Stariq static uint_t xdt_ncpus;			/* total number of phys CPUs */
3556670Stariq static uint32_t cur_trace_mask;			/* current trace mask */
3566670Stariq static xdt_schedinfo_t *xdt_cpu_schedinfo;	/* per-cpu sched info */
3576670Stariq dtrace_id_t xdt_probemap[XDT_NEVENTS];		/* map of enabled probes */
3586670Stariq dtrace_id_t xdt_prid[XDT_NEVENTS];		/* IDs of registered events */
3596670Stariq static cyclic_id_t xdt_cyclic = CYCLIC_NONE;
3606670Stariq static kstat_t *xdt_kstats;
3616670Stariq static xdt_classinfo_t xdt_classinfo[XDT_NCLASSES];
3626670Stariq 
363*11153SFrank.Vanderlinden@Sun.COM /*
364*11153SFrank.Vanderlinden@Sun.COM  * These provide context when probes fire. They can be accessed
365*11153SFrank.Vanderlinden@Sun.COM  * from xdt dtrace probe (as `xdt_curdom, etc). It's ok for these
366*11153SFrank.Vanderlinden@Sun.COM  * to be global, and not per-cpu, as probes are run strictly in sequence
367*11153SFrank.Vanderlinden@Sun.COM  * as the trace buffers are
368*11153SFrank.Vanderlinden@Sun.COM  */
369*11153SFrank.Vanderlinden@Sun.COM uint_t xdt_curdom, xdt_curvcpu, xdt_curpcpu;
370*11153SFrank.Vanderlinden@Sun.COM uint64_t xdt_timestamp;
371*11153SFrank.Vanderlinden@Sun.COM 
3726670Stariq static xdt_probe_t xdt_probe[] = {
3736670Stariq 	/* Sched probes */
3746670Stariq 	{ "sched", "off-cpu", XDT_SCHED_OFF_CPU, XDT_SCHED },
3756670Stariq 	{ "sched", "on-cpu", XDT_SCHED_ON_CPU, XDT_SCHED },
3766670Stariq 	{ "sched", "idle-off-cpu", XDT_SCHED_IDLE_OFF_CPU, XDT_SCHED },
3776670Stariq 	{ "sched", "idle-on-cpu", XDT_SCHED_IDLE_ON_CPU, XDT_SCHED },
3786670Stariq 	{ "sched", "block", XDT_SCHED_BLOCK, XDT_SCHED },
3796670Stariq 	{ "sched", "sleep", XDT_SCHED_SLEEP, XDT_SCHED },
3806670Stariq 	{ "sched", "wake", XDT_SCHED_WAKE, XDT_SCHED },
3816670Stariq 	{ "sched", "yield", XDT_SCHED_YIELD, XDT_SCHED },
3826670Stariq 	{ "sched", "shutdown-poweroff", XDT_SCHED_SHUTDOWN_POWEROFF,
3836670Stariq 		XDT_SCHED },
3846670Stariq 	{ "sched", "shutdown-reboot", XDT_SCHED_SHUTDOWN_REBOOT, XDT_SCHED },
3856670Stariq 	{ "sched", "shutdown-suspend", XDT_SCHED_SHUTDOWN_SUSPEND, XDT_SCHED },
3866670Stariq 	{ "sched", "shutdown-crash", XDT_SCHED_SHUTDOWN_CRASH, XDT_SCHED },
387*11153SFrank.Vanderlinden@Sun.COM 	{ "sched", "add", XDT_SCHED_ADD_VCPU, XDT_SCHED },
388*11153SFrank.Vanderlinden@Sun.COM 	{ "sched", "runstate-change", XDT_SCHED_RUNSTATE_CHANGE, XDT_SCHED },
389*11153SFrank.Vanderlinden@Sun.COM 	{ "sched", "continue-running", XDT_SCHED_CONTINUE_RUNNING, XDT_SCHED },
3906670Stariq 
3916670Stariq 	/* Memory probes */
3926670Stariq 	{ "mem", "page-grant-map", XDT_MEM_PAGE_GRANT_MAP, XDT_MEM },
3936670Stariq 	{ "mem", "page-grant-unmap", XDT_MEM_PAGE_GRANT_UNMAP, XDT_MEM },
3946670Stariq 	{ "mem", "page-grant-transfer", XDT_MEM_PAGE_GRANT_TRANSFER, XDT_MEM },
3956670Stariq 
396*11153SFrank.Vanderlinden@Sun.COM 	{"pv", "hypercall", XDT_PV_HYPERCALL, XDT_PV },
397*11153SFrank.Vanderlinden@Sun.COM 	{"pv", "trap", XDT_PV_TRAP, XDT_PV },
398*11153SFrank.Vanderlinden@Sun.COM 	{"pv", "page-fault", XDT_PV_PAGE_FAULT, XDT_PV },
399*11153SFrank.Vanderlinden@Sun.COM 	{"pv", "forced-invalid-op", XDT_PV_FORCED_INVALID_OP, XDT_PV },
400*11153SFrank.Vanderlinden@Sun.COM 	{"pv", "emulate-priv-op", XDT_PV_EMULATE_PRIVOP, XDT_PV },
401*11153SFrank.Vanderlinden@Sun.COM 	{"pv", "math-state-restore", XDT_PV_MATH_STATE_RESTORE, XDT_PV },
402*11153SFrank.Vanderlinden@Sun.COM 	{"pv", "paging-fixup", XDT_PV_PAGING_FIXUP, XDT_PV },
403*11153SFrank.Vanderlinden@Sun.COM 	{"pv", "dt-mapping-fault", XDT_PV_DT_MAPPING_FAULT, XDT_PV },
404*11153SFrank.Vanderlinden@Sun.COM 	{"pv", "pte-write-emul", XDT_PV_PTWR_EMULATION, XDT_PV },
405*11153SFrank.Vanderlinden@Sun.COM 
4066670Stariq 	/* HVM probes */
4076670Stariq 	{ "hvm", "vmentry", XDT_HVM_VMENTRY, XDT_HVM },
4086670Stariq 	{ "hvm", "vmexit", XDT_HVM_VMEXIT, XDT_HVM },
409*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "pagefault-xen", XDT_HVM_PF_XEN, XDT_HVM },
410*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "pagefault-inject", XDT_HVM_PF_INJECT, XDT_HVM },
411*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "exception-inject", XDT_HVM_EXC_INJECT, XDT_HVM },
412*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "virq-inject", XDT_HVM_VIRQ_INJECT, XDT_HVM },
413*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "cr-read", XDT_HVM_CR_READ, XDT_HVM },
414*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "cr-write", XDT_HVM_CR_WRITE, XDT_HVM },
415*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "msr-read", XDT_HVM_MSR_READ, XDT_HVM },
416*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "msr-write", XDT_HVM_MSR_WRITE, XDT_HVM },
417*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "cpuid", XDT_HVM_CPUID, XDT_HVM },
418*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "intr", XDT_HVM_INTR, XDT_HVM },
419*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "intr-window", XDT_HVM_INTR_WINDOW, XDT_HVM },
420*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "nmi", XDT_HVM_NMI, XDT_HVM },
421*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "smi", XDT_HVM_SMI, XDT_HVM },
422*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "vmmcall", XDT_HVM_VMMCALL, XDT_HVM },
423*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "hlt", XDT_HVM_HLT, XDT_HVM },
424*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "invlpg", XDT_HVM_INVLPG, XDT_HVM },
425*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "mce", XDT_HVM_MCE, XDT_HVM },
426*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "pio-read", XDT_HVM_IOPORT_READ, XDT_HVM },
427*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "pio-write", XDT_HVM_IOPORT_WRITE, XDT_HVM },
428*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "mmio-read", XDT_HVM_IOMEM_READ, XDT_HVM },
429*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "mmio-write", XDT_HVM_IOMEM_WRITE, XDT_HVM },
430*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "clts", XDT_HVM_CLTS, XDT_HVM },
431*11153SFrank.Vanderlinden@Sun.COM 	{ "hvm", "lmsw", XDT_HVM_LMSW, XDT_HVM },
432*11153SFrank.Vanderlinden@Sun.COM 
433*11153SFrank.Vanderlinden@Sun.COM 	{ "shadow", "fault-not-shadow", XDT_SHADOW_NOT_SHADOW, XDT_SHADOW },
434*11153SFrank.Vanderlinden@Sun.COM 	{ "shadow", "fast-propagate", XDT_SHADOW_FAST_PROPAGATE, XDT_SHADOW },
435*11153SFrank.Vanderlinden@Sun.COM 	{ "shadow", "fast-mmio", XDT_SHADOW_FAST_MMIO, XDT_SHADOW },
436*11153SFrank.Vanderlinden@Sun.COM 	{ "shadow", "false-fast-path", XDT_SHADOW_FALSE_FAST_PATH,
437*11153SFrank.Vanderlinden@Sun.COM 	    XDT_SHADOW },
438*11153SFrank.Vanderlinden@Sun.COM 	{ "shadow", "mmio", XDT_SHADOW_MMIO, XDT_SHADOW },
439*11153SFrank.Vanderlinden@Sun.COM 	{ "shadow", "fixup", XDT_SHADOW_FIXUP, XDT_SHADOW },
440*11153SFrank.Vanderlinden@Sun.COM 	{ "shadow", "domf-dying", XDT_SHADOW_DOMF_DYING, XDT_SHADOW },
441*11153SFrank.Vanderlinden@Sun.COM 	{ "shadow", "emulate", XDT_SHADOW_EMULATE, XDT_SHADOW },
442*11153SFrank.Vanderlinden@Sun.COM 	{ "shadow", "emulate-unshadow-user", XDT_SHADOW_EMULATE_UNSHADOW_USER,
443*11153SFrank.Vanderlinden@Sun.COM 	    XDT_SHADOW },
444*11153SFrank.Vanderlinden@Sun.COM 	{ "shadow", "emulate-unshadow-evtinj",
445*11153SFrank.Vanderlinden@Sun.COM 	    XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ, XDT_SHADOW },
446*11153SFrank.Vanderlinden@Sun.COM 	{ "shadow", "emulate-unshadow-unhandled",
447*11153SFrank.Vanderlinden@Sun.COM 	    XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED, XDT_SHADOW },
448*11153SFrank.Vanderlinden@Sun.COM 	{ "shadow", "wrmap-bf", XDT_SHADOW_WRMAP_BF, XDT_SHADOW },
449*11153SFrank.Vanderlinden@Sun.COM 	{ "shadow", "prealloc-unpin", XDT_SHADOW_PREALLOC_UNPIN, XDT_SHADOW },
450*11153SFrank.Vanderlinden@Sun.COM 	{ "shadow", "resync-full", XDT_SHADOW_RESYNC_FULL, XDT_SHADOW },
451*11153SFrank.Vanderlinden@Sun.COM 	{ "shadow", "resync-only", XDT_SHADOW_RESYNC_ONLY, XDT_SHADOW },
452*11153SFrank.Vanderlinden@Sun.COM 
453*11153SFrank.Vanderlinden@Sun.COM 	{ "pm", "freq-change", XDT_PM_FREQ_CHANGE, XDT_PM },
454*11153SFrank.Vanderlinden@Sun.COM 	{ "pm", "idle-entry", XDT_PM_IDLE_ENTRY, XDT_PM },
455*11153SFrank.Vanderlinden@Sun.COM 	{ "pm", "idle-exit", XDT_PM_IDLE_EXIT, XDT_PM },
4566670Stariq 
45710175SStuart.Maybee@Sun.COM 	/* Trace buffer related probes */
45810175SStuart.Maybee@Sun.COM 	{ "trace", "records-lost", XDT_TRC_LOST_RECORDS, XDT_GEN },
45910175SStuart.Maybee@Sun.COM 
4606670Stariq 	{ NULL }
4616670Stariq };
4626670Stariq 
4636670Stariq static inline uint32_t
xdt_nr_active_probes()4646670Stariq xdt_nr_active_probes()
4656670Stariq {
4666670Stariq 	int i;
4676670Stariq 	uint32_t tot = 0;
4686670Stariq 
4696670Stariq 	for (i = 0; i < XDT_NCLASSES; i++)
4706670Stariq 		tot += xdt_classinfo[i].cnt;
4716670Stariq 
4726670Stariq 	return (tot);
4736670Stariq }
4746670Stariq 
4756670Stariq static void
xdt_init_trace_masks(void)4766670Stariq xdt_init_trace_masks(void)
4776670Stariq {
4786670Stariq 	xdt_classinfo[XDT_SCHED].trc_mask = TRC_SCHED;
4796670Stariq 	xdt_classinfo[XDT_MEM].trc_mask = TRC_MEM;
4806670Stariq 	xdt_classinfo[XDT_HVM].trc_mask = TRC_HVM;
48110175SStuart.Maybee@Sun.COM 	xdt_classinfo[XDT_GEN].trc_mask = TRC_GEN;
482*11153SFrank.Vanderlinden@Sun.COM 	xdt_classinfo[XDT_PV].trc_mask = TRC_PV;
483*11153SFrank.Vanderlinden@Sun.COM 	xdt_classinfo[XDT_SHADOW].trc_mask = TRC_SHADOW;
484*11153SFrank.Vanderlinden@Sun.COM 	xdt_classinfo[XDT_PM].trc_mask = TRC_PM;
4856670Stariq }
4866670Stariq 
4876670Stariq static int
xdt_kstat_update(kstat_t * ksp,int flag)4886670Stariq xdt_kstat_update(kstat_t *ksp, int flag)
4896670Stariq {
4906670Stariq 	kstat_named_t *knp;
4916670Stariq 
4926670Stariq 	if (flag != KSTAT_READ)
4936670Stariq 		return (EACCES);
4946670Stariq 
4956670Stariq 	knp = ksp->ks_data;
4966670Stariq 
4976670Stariq 	/*
4986670Stariq 	 * Assignment order should match that of the names in
4996670Stariq 	 * xdt_stats.
5006670Stariq 	 */
5016670Stariq 	(knp++)->value.ui64 = tbuf.stat_dropped_recs;
5026670Stariq 
5036670Stariq 	return (0);
5046670Stariq }
5056670Stariq 
5066670Stariq static void
xdt_kstat_init(void)5076670Stariq xdt_kstat_init(void)
5086670Stariq {
5096670Stariq 	int nstats = sizeof (xdt_stats) / sizeof (xdt_stats[0]);
5106670Stariq 	char **cp = xdt_stats;
5116670Stariq 	kstat_named_t *knp;
5126670Stariq 
5136670Stariq 	if ((xdt_kstats = kstat_create("xdt", 0, "trace_statistics", "misc",
5146670Stariq 	    KSTAT_TYPE_NAMED, nstats, 0)) == NULL)
5156670Stariq 		return;
5166670Stariq 
5176670Stariq 	xdt_kstats->ks_update = xdt_kstat_update;
5186670Stariq 
5196670Stariq 	knp = xdt_kstats->ks_data;
5206670Stariq 	while (nstats > 0) {
5216670Stariq 		kstat_named_init(knp, *cp, KSTAT_DATA_UINT64);
5226670Stariq 		knp++;
5236670Stariq 		cp++;
5246670Stariq 		nstats--;
5256670Stariq 	}
5266670Stariq 
5276670Stariq 	kstat_install(xdt_kstats);
5286670Stariq }
5296670Stariq 
5306670Stariq static int
xdt_sysctl_tbuf(xen_sysctl_tbuf_op_t * tbuf_op)5316670Stariq xdt_sysctl_tbuf(xen_sysctl_tbuf_op_t *tbuf_op)
5326670Stariq {
5336670Stariq 	xen_sysctl_t op;
5346670Stariq 	int xerr;
5356670Stariq 
5366670Stariq 	op.cmd = XEN_SYSCTL_tbuf_op;
5376670Stariq 	op.interface_version = XEN_SYSCTL_INTERFACE_VERSION;
5386670Stariq 	op.u.tbuf_op = *tbuf_op;
5396670Stariq 
5406670Stariq 	if ((xerr = HYPERVISOR_sysctl(&op)) != 0)
5416670Stariq 		return (xen_xlate_errcode(xerr));
5426670Stariq 
5436670Stariq 	*tbuf_op = op.u.tbuf_op;
5446670Stariq 	return (0);
5456670Stariq }
5466670Stariq 
5476670Stariq static int
xdt_map_trace_buffers(mfn_t mfn,caddr_t va,size_t len)5486670Stariq xdt_map_trace_buffers(mfn_t mfn, caddr_t va, size_t len)
5496670Stariq {
5506670Stariq 	x86pte_t pte;
5516670Stariq 	caddr_t const sva = va;
5526670Stariq 	caddr_t const eva = va + len;
5536670Stariq 	int xerr;
5546670Stariq 
5556670Stariq 	ASSERT(mfn != MFN_INVALID);
5566670Stariq 	ASSERT(va != NULL);
5576670Stariq 	ASSERT(IS_PAGEALIGNED(len));
5586670Stariq 
5596670Stariq 	for (; va < eva; va += MMU_PAGESIZE) {
5606670Stariq 		/*
5616670Stariq 		 * Ask the HAT to load a throwaway mapping to page zero, then
5626670Stariq 		 * overwrite it with the hypervisor mapping. It gets removed
5636670Stariq 		 * later via hat_unload().
5646670Stariq 		 */
5656670Stariq 		hat_devload(kas.a_hat, va, MMU_PAGESIZE, (pfn_t)0,
5666670Stariq 		    PROT_READ | HAT_UNORDERED_OK,
5676670Stariq 		    HAT_LOAD_NOCONSIST | HAT_LOAD);
5686670Stariq 
5696670Stariq 		pte = mmu_ptob((x86pte_t)mfn) | PT_VALID | PT_USER
5706670Stariq 		    | PT_FOREIGN | PT_WRITABLE;
5716670Stariq 
5726670Stariq 		xerr = HYPERVISOR_update_va_mapping_otherdomain((ulong_t)va,
5736670Stariq 		    pte, UVMF_INVLPG | UVMF_LOCAL, DOMID_XEN);
5746670Stariq 
5756670Stariq 		if (xerr != 0) {
5766670Stariq 			/* unmap pages loaded so far */
5776670Stariq 			size_t ulen = (uintptr_t)(va + MMU_PAGESIZE) -
5786670Stariq 			    (uintptr_t)sva;
5796670Stariq 			hat_unload(kas.a_hat, sva, ulen, HAT_UNLOAD_UNMAP);
5806670Stariq 			return (xen_xlate_errcode(xerr));
5816670Stariq 		}
5826670Stariq 
5836670Stariq 		mfn++;
5846670Stariq 	}
5856670Stariq 
5866670Stariq 	return (0);
5876670Stariq }
5886670Stariq 
5896670Stariq static int
xdt_attach_trace_buffers(void)5906670Stariq xdt_attach_trace_buffers(void)
5916670Stariq {
5926670Stariq 	xen_sysctl_tbuf_op_t tbuf_op;
5936670Stariq 	size_t len;
5946670Stariq 	int err;
5956670Stariq 	uint_t i;
5966670Stariq 
5977401Stariqmi@sun.com 	/*
5987401Stariqmi@sun.com 	 * Xen does not support trace buffer re-sizing. If the buffers
5997401Stariqmi@sun.com 	 * have already been allocated we just use them as is.
6007401Stariqmi@sun.com 	 */
6016670Stariq 	tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_get_info;
6026670Stariq 	if ((err = xdt_sysctl_tbuf(&tbuf_op)) != 0)
6036670Stariq 		return (err);
6046670Stariq 
6057401Stariqmi@sun.com 	if (tbuf_op.size == 0) {
6067401Stariqmi@sun.com 		/* set trace buffer size */
6077401Stariqmi@sun.com 		tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_set_size;
6087401Stariqmi@sun.com 		tbuf_op.size = xdt_tbuf_pages;
6097401Stariqmi@sun.com 		(void) xdt_sysctl_tbuf(&tbuf_op);
6107401Stariqmi@sun.com 
6117401Stariqmi@sun.com 		/* get trace buffer info */
6127401Stariqmi@sun.com 		tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_get_info;
6137401Stariqmi@sun.com 		if ((err = xdt_sysctl_tbuf(&tbuf_op)) != 0)
6147401Stariqmi@sun.com 			return (err);
6157401Stariqmi@sun.com 
6167401Stariqmi@sun.com 		if (tbuf_op.size == 0) {
6177401Stariqmi@sun.com 			cmn_err(CE_NOTE, "Couldn't allocate trace buffers.");
6187401Stariqmi@sun.com 			return (ENOBUFS);
6197401Stariqmi@sun.com 		}
6207401Stariqmi@sun.com 	}
6217401Stariqmi@sun.com 
6226670Stariq 	tbuf.size = tbuf_op.size;
6236670Stariq 	tbuf.start_mfn = (mfn_t)tbuf_op.buffer_mfn;
6246670Stariq 	tbuf.cnt = xdt_ncpus;
6256670Stariq 
6266670Stariq 	ASSERT(tbuf.start_mfn != MFN_INVALID);
6276670Stariq 	ASSERT(tbuf.cnt > 0);
6286670Stariq 
6296670Stariq 	len = tbuf.size * tbuf.cnt;
6306670Stariq 	tbuf.va = vmem_alloc(heap_arena, len, VM_SLEEP);
6316670Stariq 
6326670Stariq 	if ((err = xdt_map_trace_buffers(tbuf.start_mfn, tbuf.va, len)) != 0) {
6336670Stariq 		vmem_free(heap_arena, tbuf.va, len);
6346670Stariq 		tbuf.va = NULL;
6356670Stariq 		return (err);
6366670Stariq 	}
6376670Stariq 
6386670Stariq 	tbuf.meta = (struct t_buf **)kmem_alloc(tbuf.cnt * sizeof (*tbuf.meta),
6396670Stariq 	    KM_SLEEP);
6406670Stariq 	tbuf.data = (struct t_rec **)kmem_alloc(tbuf.cnt * sizeof (*tbuf.data),
6416670Stariq 	    KM_SLEEP);
6426670Stariq 
6436670Stariq 	for (i = 0; i < tbuf.cnt; i++) {
6446670Stariq 		void *cpu_buf = (void *)(tbuf.va + (tbuf.size * i));
6456670Stariq 		tbuf.meta[i] = cpu_buf;
6466670Stariq 		tbuf.data[i] = (struct t_rec *)((uintptr_t)cpu_buf +
6476670Stariq 		    sizeof (struct t_buf));
6486670Stariq 
6496670Stariq 		/* throw away stale trace records */
6506670Stariq 		tbuf.meta[i]->cons = tbuf.meta[i]->prod;
6516670Stariq 	}
6526670Stariq 
653*11153SFrank.Vanderlinden@Sun.COM 	tbuf_data_size = tbuf.size - sizeof (struct t_buf);
654*11153SFrank.Vanderlinden@Sun.COM 	if (xdt_max_recs == 0)
655*11153SFrank.Vanderlinden@Sun.COM 		xdt_max_recs = (xdt_ncpus * tbuf_data_size)
656*11153SFrank.Vanderlinden@Sun.COM 		    / sizeof (struct t_rec);
657*11153SFrank.Vanderlinden@Sun.COM 
6586670Stariq 	return (0);
6596670Stariq }
6606670Stariq 
6616670Stariq static void
xdt_detach_trace_buffers(void)6626670Stariq xdt_detach_trace_buffers(void)
6636670Stariq {
6646670Stariq 	size_t len = tbuf.size * tbuf.cnt;
6656670Stariq 
6666670Stariq 	ASSERT(tbuf.va != NULL);
6676670Stariq 
6686670Stariq 	hat_unload(kas.a_hat, tbuf.va, len,
6696670Stariq 	    HAT_UNLOAD_UNMAP | HAT_UNLOAD_UNLOCK);
6706670Stariq 	vmem_free(heap_arena, tbuf.va, len);
6716670Stariq 	kmem_free(tbuf.meta, tbuf.cnt * sizeof (*tbuf.meta));
6726670Stariq 	kmem_free(tbuf.data, tbuf.cnt * sizeof (*tbuf.data));
6736670Stariq }
6746670Stariq 
675*11153SFrank.Vanderlinden@Sun.COM static void
xdt_update_sched_context(uint_t cpuid,uint_t dom,uint_t vcpu)676*11153SFrank.Vanderlinden@Sun.COM xdt_update_sched_context(uint_t cpuid, uint_t dom, uint_t vcpu)
677*11153SFrank.Vanderlinden@Sun.COM {
678*11153SFrank.Vanderlinden@Sun.COM 	xdt_schedinfo_t *sp = &xdt_cpu_schedinfo[cpuid];
679*11153SFrank.Vanderlinden@Sun.COM 
680*11153SFrank.Vanderlinden@Sun.COM 	sp->cur_domid = dom;
681*11153SFrank.Vanderlinden@Sun.COM 	sp->cur_vcpuid = vcpu;
682*11153SFrank.Vanderlinden@Sun.COM 	sp->curinfo_valid = 1;
683*11153SFrank.Vanderlinden@Sun.COM }
684*11153SFrank.Vanderlinden@Sun.COM 
685*11153SFrank.Vanderlinden@Sun.COM static void
xdt_update_domain_context(uint_t dom,uint_t vcpu)686*11153SFrank.Vanderlinden@Sun.COM xdt_update_domain_context(uint_t dom, uint_t vcpu)
687*11153SFrank.Vanderlinden@Sun.COM {
688*11153SFrank.Vanderlinden@Sun.COM 	xdt_curdom = dom;
689*11153SFrank.Vanderlinden@Sun.COM 	xdt_curvcpu = vcpu;
690*11153SFrank.Vanderlinden@Sun.COM }
691*11153SFrank.Vanderlinden@Sun.COM 
692*11153SFrank.Vanderlinden@Sun.COM static size_t
xdt_process_rec(uint_t cpuid,struct t_rec * rec)6936670Stariq xdt_process_rec(uint_t cpuid, struct t_rec *rec)
6946670Stariq {
6956670Stariq 	xdt_schedinfo_t *sp = &xdt_cpu_schedinfo[cpuid];
696*11153SFrank.Vanderlinden@Sun.COM 	uint_t dom, vcpu;
6976670Stariq 	int eid;
69810175SStuart.Maybee@Sun.COM 	uint32_t *data;
699*11153SFrank.Vanderlinden@Sun.COM 	uint64_t tsc, addr64, rip64, val64, pte64;
70010175SStuart.Maybee@Sun.COM 	size_t rec_size;
7016670Stariq 
7026670Stariq 	ASSERT(rec != NULL);
70310175SStuart.Maybee@Sun.COM 	ASSERT(xdt_ncpus == xpv_nr_phys_cpus());
7046670Stariq 
7056670Stariq 	if (cpuid >= xdt_ncpus) {
7066670Stariq 		tbuf.stat_spurious_cpu++;
70710175SStuart.Maybee@Sun.COM 		goto done;
7086670Stariq 	}
7096670Stariq 
710*11153SFrank.Vanderlinden@Sun.COM 	/*
711*11153SFrank.Vanderlinden@Sun.COM 	 * If our current state isn't valid, and if this is not
712*11153SFrank.Vanderlinden@Sun.COM 	 * an event that will update our state, skip it.
713*11153SFrank.Vanderlinden@Sun.COM 	 */
714*11153SFrank.Vanderlinden@Sun.COM 
715*11153SFrank.Vanderlinden@Sun.COM 	if (!sp->curinfo_valid &&
716*11153SFrank.Vanderlinden@Sun.COM 	    rec->event != TRC_SCHED_SWITCH &&
717*11153SFrank.Vanderlinden@Sun.COM 	    rec->event != TRC_LOST_RECORDS)
718*11153SFrank.Vanderlinden@Sun.COM 		goto done;
719*11153SFrank.Vanderlinden@Sun.COM 
720*11153SFrank.Vanderlinden@Sun.COM 	if (rec->cycles_included) {
721*11153SFrank.Vanderlinden@Sun.COM 		data = rec->u.cycles.extra_u32;
722*11153SFrank.Vanderlinden@Sun.COM 		tsc = (((uint64_t)rec->u.cycles.cycles_hi) << 32)
723*11153SFrank.Vanderlinden@Sun.COM 		    | rec->u.cycles.cycles_lo;
724*11153SFrank.Vanderlinden@Sun.COM 	} else {
725*11153SFrank.Vanderlinden@Sun.COM 		data = rec->u.nocycles.extra_u32;
726*11153SFrank.Vanderlinden@Sun.COM 		tsc = 0;
727*11153SFrank.Vanderlinden@Sun.COM 	}
728*11153SFrank.Vanderlinden@Sun.COM 
729*11153SFrank.Vanderlinden@Sun.COM 	xdt_timestamp = tsc;
73010175SStuart.Maybee@Sun.COM 
7316670Stariq 	switch (rec->event) {
7326670Stariq 	/*
7336670Stariq 	 * Sched probes
7346670Stariq 	 */
7356670Stariq 	case TRC_SCHED_SWITCH_INFPREV:
7366670Stariq 		/*
7376670Stariq 		 * Info on vCPU being de-scheduled
7386670Stariq 		 *
73910175SStuart.Maybee@Sun.COM 		 * data[0] = prev domid
74010175SStuart.Maybee@Sun.COM 		 * data[1] = time spent on pcpu
7416670Stariq 		 */
74210175SStuart.Maybee@Sun.COM 		sp->prev_domid = data[0];
74310175SStuart.Maybee@Sun.COM 		sp->prev_ctime = data[1];
7446670Stariq 		break;
7456670Stariq 
7466670Stariq 	case TRC_SCHED_SWITCH_INFNEXT:
7476670Stariq 		/*
7486670Stariq 		 * Info on next vCPU to be scheduled
7496670Stariq 		 *
75010175SStuart.Maybee@Sun.COM 		 * data[0] = next domid
75110175SStuart.Maybee@Sun.COM 		 * data[1] = time spent waiting to get on cpu
75210175SStuart.Maybee@Sun.COM 		 * data[2] = time slice
7536670Stariq 		 */
75410175SStuart.Maybee@Sun.COM 		sp->next_domid = data[0];
75510175SStuart.Maybee@Sun.COM 		sp->next_wtime = data[1];
75610175SStuart.Maybee@Sun.COM 		sp->next_ts = data[2];
7576670Stariq 		break;
7586670Stariq 
7596670Stariq 	case TRC_SCHED_SWITCH:
7606670Stariq 		/*
7616670Stariq 		 * vCPU switch
7626670Stariq 		 *
76310175SStuart.Maybee@Sun.COM 		 * data[0] = prev domid
76410175SStuart.Maybee@Sun.COM 		 * data[1] = prev vcpuid
76510175SStuart.Maybee@Sun.COM 		 * data[2] = next domid
76610175SStuart.Maybee@Sun.COM 		 * data[3] = next vcpuid
7676670Stariq 		 */
768*11153SFrank.Vanderlinden@Sun.COM 
769*11153SFrank.Vanderlinden@Sun.COM 		/*
770*11153SFrank.Vanderlinden@Sun.COM 		 * Provide valid context for this probe if there
771*11153SFrank.Vanderlinden@Sun.COM 		 * wasn't one.
772*11153SFrank.Vanderlinden@Sun.COM 		 */
773*11153SFrank.Vanderlinden@Sun.COM 		if (!sp->curinfo_valid)
774*11153SFrank.Vanderlinden@Sun.COM 			xdt_update_domain_context(data[0], data[1]);
775*11153SFrank.Vanderlinden@Sun.COM 
776*11153SFrank.Vanderlinden@Sun.COM 		xdt_update_sched_context(cpuid, data[0], data[1]);
777*11153SFrank.Vanderlinden@Sun.COM 
77810175SStuart.Maybee@Sun.COM 		if (data[0] != sp->prev_domid &&
77910175SStuart.Maybee@Sun.COM 		    data[2] != sp->next_domid) {
7806670Stariq 			/* prev and next info don't match doms being sched'd */
7816670Stariq 			tbuf.stat_spurious_switch++;
782*11153SFrank.Vanderlinden@Sun.COM 			goto switchdone;
7836670Stariq 		}
7846670Stariq 
78510175SStuart.Maybee@Sun.COM 		sp->prev_vcpuid = data[1];
78610175SStuart.Maybee@Sun.COM 		sp->next_vcpuid = data[3];
7876670Stariq 
7886670Stariq 		XDT_PROBE3(IS_IDLE_DOM(sp->prev_domid)?
7896670Stariq 		    XDT_SCHED_IDLE_OFF_CPU:XDT_SCHED_OFF_CPU,
790*11153SFrank.Vanderlinden@Sun.COM 		    sp->prev_domid, sp->prev_vcpuid, sp->prev_ctime);
7916670Stariq 
7926670Stariq 		XDT_PROBE4(IS_IDLE_DOM(sp->next_domid)?
7936670Stariq 		    XDT_SCHED_IDLE_ON_CPU:XDT_SCHED_ON_CPU,
794*11153SFrank.Vanderlinden@Sun.COM 		    sp->next_domid, sp->next_vcpuid, sp->next_wtime,
7956670Stariq 		    sp->next_ts);
796*11153SFrank.Vanderlinden@Sun.COM switchdone:
797*11153SFrank.Vanderlinden@Sun.COM 		xdt_update_sched_context(cpuid, data[2], data[3]);
798*11153SFrank.Vanderlinden@Sun.COM 		xdt_update_domain_context(data[2], data[3]);
799*11153SFrank.Vanderlinden@Sun.COM 
8006670Stariq 		break;
8016670Stariq 
8026670Stariq 	case TRC_SCHED_BLOCK:
8036670Stariq 		/*
8046670Stariq 		 * vCPU blocked
8056670Stariq 		 *
80610175SStuart.Maybee@Sun.COM 		 * data[0] = domid
80710175SStuart.Maybee@Sun.COM 		 * data[1] = vcpuid
8086670Stariq 		 */
809*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_SCHED_BLOCK, data[0], data[1]);
8106670Stariq 		break;
8116670Stariq 
8126670Stariq 	case TRC_SCHED_SLEEP:
8136670Stariq 		/*
8146670Stariq 		 * Put vCPU to sleep
8156670Stariq 		 *
81610175SStuart.Maybee@Sun.COM 		 * data[0] = domid
81710175SStuart.Maybee@Sun.COM 		 * data[1] = vcpuid
8186670Stariq 		 */
819*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_SCHED_SLEEP, data[0], data[1]);
8206670Stariq 		break;
8216670Stariq 
8226670Stariq 	case TRC_SCHED_WAKE:
8236670Stariq 		/*
8246670Stariq 		 * Wake up vCPU
8256670Stariq 		 *
82610175SStuart.Maybee@Sun.COM 		 * data[0] = domid
82710175SStuart.Maybee@Sun.COM 		 * data[1] = vcpuid
8286670Stariq 		 */
829*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_SCHED_WAKE, data[0], data[1]);
8306670Stariq 		break;
8316670Stariq 
8326670Stariq 	case TRC_SCHED_YIELD:
8336670Stariq 		/*
8346670Stariq 		 * vCPU yielded
8356670Stariq 		 *
83610175SStuart.Maybee@Sun.COM 		 * data[0] = domid
83710175SStuart.Maybee@Sun.COM 		 * data[1] = vcpuid
8386670Stariq 		 */
839*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_SCHED_YIELD, data[0], data[1]);
8406670Stariq 		break;
8416670Stariq 
8426670Stariq 	case TRC_SCHED_SHUTDOWN:
8436670Stariq 		/*
8446670Stariq 		 * Guest shutting down
8456670Stariq 		 *
84610175SStuart.Maybee@Sun.COM 		 * data[0] = domid
84710175SStuart.Maybee@Sun.COM 		 * data[1] = initiating vcpu
84810175SStuart.Maybee@Sun.COM 		 * data[2] = shutdown code
8496670Stariq 		 */
85010175SStuart.Maybee@Sun.COM 		switch (data[2]) {
8516670Stariq 		case SHUTDOWN_poweroff:
8526670Stariq 			eid = XDT_SCHED_SHUTDOWN_POWEROFF;
8536670Stariq 			break;
8546670Stariq 		case SHUTDOWN_reboot:
8556670Stariq 			eid = XDT_SCHED_SHUTDOWN_REBOOT;
8566670Stariq 			break;
8576670Stariq 		case SHUTDOWN_suspend:
8586670Stariq 			eid = XDT_SCHED_SHUTDOWN_SUSPEND;
8596670Stariq 			break;
8606670Stariq 		case SHUTDOWN_crash:
8616670Stariq 			eid = XDT_SCHED_SHUTDOWN_CRASH;
8626670Stariq 			break;
8636670Stariq 		default:
8646670Stariq 			tbuf.stat_unknown_shutdown++;
86510175SStuart.Maybee@Sun.COM 			goto done;
8666670Stariq 		}
8676670Stariq 
868*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(eid, data[0], data[1]);
8696670Stariq 		break;
8706670Stariq 
871*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SCHED_DOM_REM:
872*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SCHED_CTL:
873*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SCHED_S_TIMER_FN:
874*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SCHED_T_TIMER_FN:
875*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SCHED_DOM_TIMER_FN:
876*11153SFrank.Vanderlinden@Sun.COM 		/* unused */
877*11153SFrank.Vanderlinden@Sun.COM 		break;
878*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SCHED_DOM_ADD:
879*11153SFrank.Vanderlinden@Sun.COM 		/*
880*11153SFrank.Vanderlinden@Sun.COM 		 * Add vcpu to a guest.
881*11153SFrank.Vanderlinden@Sun.COM 		 *
882*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = domid
883*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = vcpu
884*11153SFrank.Vanderlinden@Sun.COM 		 */
885*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_SCHED_ADD_VCPU, data[0], data[1]);
886*11153SFrank.Vanderlinden@Sun.COM 		break;
887*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SCHED_ADJDOM:
888*11153SFrank.Vanderlinden@Sun.COM 		/*
889*11153SFrank.Vanderlinden@Sun.COM 		 * Scheduling parameters for a guest
890*11153SFrank.Vanderlinden@Sun.COM 		 * were modified.
891*11153SFrank.Vanderlinden@Sun.COM 		 *
892*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = domid;
893*11153SFrank.Vanderlinden@Sun.COM 		 */
894*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_SCHED_ADJDOM, data[1]);
895*11153SFrank.Vanderlinden@Sun.COM 		break;
896*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SCHED_RUNSTATE_CHANGE:
897*11153SFrank.Vanderlinden@Sun.COM 		/*
898*11153SFrank.Vanderlinden@Sun.COM 		 * Runstate change for a VCPU.
899*11153SFrank.Vanderlinden@Sun.COM 		 *
900*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = (domain << 16) | vcpu;
901*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = oldstate;
902*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = newstate;
903*11153SFrank.Vanderlinden@Sun.COM 		 */
904*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE4(XDT_SCHED_RUNSTATE_CHANGE, data[0] >> 16,
905*11153SFrank.Vanderlinden@Sun.COM 		    data[0] & 0xffff, data[1], data[2]);
906*11153SFrank.Vanderlinden@Sun.COM 		break;
907*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SCHED_CONTINUE_RUNNING:
908*11153SFrank.Vanderlinden@Sun.COM 		/*
909*11153SFrank.Vanderlinden@Sun.COM 		 * VCPU is back on a physical CPU that it previously
910*11153SFrank.Vanderlinden@Sun.COM 		 * was also running this VCPU.
911*11153SFrank.Vanderlinden@Sun.COM 		 *
912*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = (domain << 16) | vcpu;
913*11153SFrank.Vanderlinden@Sun.COM 		 */
914*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_SCHED_CONTINUE_RUNNING, data[0] >> 16,
915*11153SFrank.Vanderlinden@Sun.COM 		    data[0] & 0xffff);
916*11153SFrank.Vanderlinden@Sun.COM 		break;
9176670Stariq 	/*
9186670Stariq 	 * Mem probes
9196670Stariq 	 */
9206670Stariq 	case TRC_MEM_PAGE_GRANT_MAP:
9216670Stariq 		/*
9226670Stariq 		 * Guest mapped page grant
9236670Stariq 		 *
924*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = target domid
9256670Stariq 		 */
926*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_MEM_PAGE_GRANT_MAP, data[0]);
9276670Stariq 		break;
9286670Stariq 
9296670Stariq 	case TRC_MEM_PAGE_GRANT_UNMAP:
9306670Stariq 		/*
9316670Stariq 		 * Guest unmapped page grant
9326670Stariq 		 *
933*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = target domid
9346670Stariq 		 */
935*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_MEM_PAGE_GRANT_UNMAP, data[0]);
9366670Stariq 		break;
9376670Stariq 
9386670Stariq 	case TRC_MEM_PAGE_GRANT_TRANSFER:
9396670Stariq 		/*
9406670Stariq 		 * Page grant is being transferred
9416670Stariq 		 *
94210175SStuart.Maybee@Sun.COM 		 * data[0] = target domid
9436670Stariq 		 */
944*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_MEM_PAGE_GRANT_TRANSFER, data[0]);
945*11153SFrank.Vanderlinden@Sun.COM 		break;
946*11153SFrank.Vanderlinden@Sun.COM 
947*11153SFrank.Vanderlinden@Sun.COM 	/*
948*11153SFrank.Vanderlinden@Sun.COM 	 * Probes for PV domains.
949*11153SFrank.Vanderlinden@Sun.COM 	 */
950*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_HYPERCALL:
951*11153SFrank.Vanderlinden@Sun.COM 		/*
952*11153SFrank.Vanderlinden@Sun.COM 		 * Hypercall from a 32-bit PV domain.
953*11153SFrank.Vanderlinden@Sun.COM 		 *
954*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = eip
955*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = eax
956*11153SFrank.Vanderlinden@Sun.COM 		 */
957*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_PV_HYPERCALL, data[0], data[1]);
958*11153SFrank.Vanderlinden@Sun.COM 		break;
959*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_HYPERCALL | TRC_64_FLAG:
960*11153SFrank.Vanderlinden@Sun.COM 		/*
961*11153SFrank.Vanderlinden@Sun.COM 		 * Hypercall from a 64-bit PV domain.
962*11153SFrank.Vanderlinden@Sun.COM 		 *
963*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = rip(0:31)
964*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = rip(32:63)
965*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = eax;
966*11153SFrank.Vanderlinden@Sun.COM 		 */
967*11153SFrank.Vanderlinden@Sun.COM 		rip64 = (((uint64_t)data[1]) << 32) | data[0];
968*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_PV_HYPERCALL, rip64, data[2]);
969*11153SFrank.Vanderlinden@Sun.COM 		break;
970*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_TRAP:
971*11153SFrank.Vanderlinden@Sun.COM 		/*
972*11153SFrank.Vanderlinden@Sun.COM 		 * Trap in a 32-bit PV domain.
973*11153SFrank.Vanderlinden@Sun.COM 		 *
974*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = eip
975*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = trapnr | (error_code_valid << 15)
976*11153SFrank.Vanderlinden@Sun.COM 		 * 	| (error_code << 16);
977*11153SFrank.Vanderlinden@Sun.COM 		 */
978*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE4(XDT_PV_TRAP, data[0], data[1] & 0x7fff,
979*11153SFrank.Vanderlinden@Sun.COM 		    (data[1] >> 15) & 1, data[1] >> 16);
980*11153SFrank.Vanderlinden@Sun.COM 		break;
981*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_TRAP | TRC_64_FLAG:
982*11153SFrank.Vanderlinden@Sun.COM 		/*
983*11153SFrank.Vanderlinden@Sun.COM 		 * Trap in a 64-bit PV domain.
984*11153SFrank.Vanderlinden@Sun.COM 		 *
985*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = rip(0:31)
986*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = rip(32:63)
987*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = trapnr | (error_code_valid << 15)
988*11153SFrank.Vanderlinden@Sun.COM 		 * 	| (error_code << 16);
989*11153SFrank.Vanderlinden@Sun.COM 		 */
990*11153SFrank.Vanderlinden@Sun.COM 		rip64 = (((uint64_t)data[1]) << 32) | data[2];
991*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE4(XDT_PV_TRAP, rip64, data[2] & 0x7fff,
992*11153SFrank.Vanderlinden@Sun.COM 		    (data[2] >> 15) & 1, data[2] >> 16);
993*11153SFrank.Vanderlinden@Sun.COM 		break;
994*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_PAGE_FAULT:
995*11153SFrank.Vanderlinden@Sun.COM 		/*
996*11153SFrank.Vanderlinden@Sun.COM 		 * Page fault in a 32-bit PV domain.
997*11153SFrank.Vanderlinden@Sun.COM 		 *
998*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = eip
999*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = vaddr
1000*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = error code
1001*11153SFrank.Vanderlinden@Sun.COM 		 */
1002*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE3(XDT_PV_PAGE_FAULT, data[0], data[1], data[2]);
1003*11153SFrank.Vanderlinden@Sun.COM 		break;
1004*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_PAGE_FAULT | TRC_64_FLAG:
1005*11153SFrank.Vanderlinden@Sun.COM 		/*
1006*11153SFrank.Vanderlinden@Sun.COM 		 * Page fault in a 32-bit PV domain.
1007*11153SFrank.Vanderlinden@Sun.COM 		 *
1008*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = rip(0:31)
1009*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = rip(31:63)
1010*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = vaddr(0:31)
1011*11153SFrank.Vanderlinden@Sun.COM 		 * data[3] = vaddr(31:63)
1012*11153SFrank.Vanderlinden@Sun.COM 		 * data[4] = error code
1013*11153SFrank.Vanderlinden@Sun.COM 		 */
1014*11153SFrank.Vanderlinden@Sun.COM 		rip64 = (((uint64_t)data[1]) << 32) | data[0];
1015*11153SFrank.Vanderlinden@Sun.COM 		addr64 = (((uint64_t)data[3]) << 32) | data[2];
1016*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE3(XDT_PV_PAGE_FAULT, rip64, addr64, data[4]);
1017*11153SFrank.Vanderlinden@Sun.COM 		break;
1018*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_FORCED_INVALID_OP:
1019*11153SFrank.Vanderlinden@Sun.COM 		/*
1020*11153SFrank.Vanderlinden@Sun.COM 		 * Hypervisor emulated a forced invalid op (ud2)
1021*11153SFrank.Vanderlinden@Sun.COM 		 * in a 32-bit PV domain.
1022*11153SFrank.Vanderlinden@Sun.COM 		 *
1023*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = eip
1024*11153SFrank.Vanderlinden@Sun.COM 		 */
1025*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_PV_FORCED_INVALID_OP, data[1]);
1026*11153SFrank.Vanderlinden@Sun.COM 		break;
1027*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_FORCED_INVALID_OP | TRC_64_FLAG:
1028*11153SFrank.Vanderlinden@Sun.COM 		/*
1029*11153SFrank.Vanderlinden@Sun.COM 		 * Hypervisor emulated a forced invalid op (ud2)
1030*11153SFrank.Vanderlinden@Sun.COM 		 * in a 64-bit PV domain.
1031*11153SFrank.Vanderlinden@Sun.COM 		 *
1032*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = rip(0:31)
1033*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = rip(31:63)
1034*11153SFrank.Vanderlinden@Sun.COM 		 *
1035*11153SFrank.Vanderlinden@Sun.COM 		 */
1036*11153SFrank.Vanderlinden@Sun.COM 		rip64 = (((uint64_t)data[2]) << 32) | data[1];
1037*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_PV_FORCED_INVALID_OP, rip64);
1038*11153SFrank.Vanderlinden@Sun.COM 		break;
1039*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_EMULATE_PRIVOP:
1040*11153SFrank.Vanderlinden@Sun.COM 		/*
1041*11153SFrank.Vanderlinden@Sun.COM 		 * Hypervisor emulated a privileged operation
1042*11153SFrank.Vanderlinden@Sun.COM 		 * in a 32-bit PV domain.
1043*11153SFrank.Vanderlinden@Sun.COM 		 *
1044*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = eip
1045*11153SFrank.Vanderlinden@Sun.COM 		 */
1046*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_PV_EMULATE_PRIVOP, data[0]);
1047*11153SFrank.Vanderlinden@Sun.COM 		break;
1048*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_EMULATE_PRIVOP | TRC_64_FLAG:
1049*11153SFrank.Vanderlinden@Sun.COM 		/*
1050*11153SFrank.Vanderlinden@Sun.COM 		 * Hypervisor emulated a privileged operation
1051*11153SFrank.Vanderlinden@Sun.COM 		 * in a 64-bit PV domain.
1052*11153SFrank.Vanderlinden@Sun.COM 		 *
1053*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = rip(0:31)
1054*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = rip(31:63)
1055*11153SFrank.Vanderlinden@Sun.COM 		 */
1056*11153SFrank.Vanderlinden@Sun.COM 		rip64 = (((uint64_t)data[1]) << 32) | data[0];
1057*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_PV_EMULATE_PRIVOP, rip64);
1058*11153SFrank.Vanderlinden@Sun.COM 		break;
1059*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_EMULATE_4GB:
1060*11153SFrank.Vanderlinden@Sun.COM 		/* unused, 32-bit hypervisor only */
1061*11153SFrank.Vanderlinden@Sun.COM 		break;
1062*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_MATH_STATE_RESTORE:
1063*11153SFrank.Vanderlinden@Sun.COM 		/*
1064*11153SFrank.Vanderlinden@Sun.COM 		 * Hypervisor restores math state after FP DNA trap.
1065*11153SFrank.Vanderlinden@Sun.COM 		 *
1066*11153SFrank.Vanderlinden@Sun.COM 		 * No arguments.
1067*11153SFrank.Vanderlinden@Sun.COM 		 */
1068*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE0(XDT_PV_MATH_STATE_RESTORE);
1069*11153SFrank.Vanderlinden@Sun.COM 		break;
1070*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_PAGING_FIXUP:
1071*11153SFrank.Vanderlinden@Sun.COM 		/*
1072*11153SFrank.Vanderlinden@Sun.COM 		 * Hypervisor fixed up a page fault (e.g. it was
1073*11153SFrank.Vanderlinden@Sun.COM 		 * a side-effect of hypervisor guest page table
1074*11153SFrank.Vanderlinden@Sun.COM 		 * bookkeeping, and not propagated to the guest).
1075*11153SFrank.Vanderlinden@Sun.COM 		 *
1076*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = eip
1077*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = vaddr
1078*11153SFrank.Vanderlinden@Sun.COM 		 */
1079*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_PV_PAGING_FIXUP, data[0], data[2]);
1080*11153SFrank.Vanderlinden@Sun.COM 		break;
1081*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_PAGING_FIXUP | TRC_64_FLAG:
1082*11153SFrank.Vanderlinden@Sun.COM 		/*
1083*11153SFrank.Vanderlinden@Sun.COM 		 * Hypervisor fixed up a page fault (e.g. it was
1084*11153SFrank.Vanderlinden@Sun.COM 		 * a side-effect of hypervisor guest page table
1085*11153SFrank.Vanderlinden@Sun.COM 		 * bookkeeping, and not propagated to the guest).
1086*11153SFrank.Vanderlinden@Sun.COM 		 *
1087*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = eip(0:31)
1088*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = eip(31:63)
1089*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = vaddr(0:31)
1090*11153SFrank.Vanderlinden@Sun.COM 		 * data[3] = vaddr(31:63)
1091*11153SFrank.Vanderlinden@Sun.COM 		 */
1092*11153SFrank.Vanderlinden@Sun.COM 		rip64 = (((uint64_t)data[1]) << 32) | data[0];
1093*11153SFrank.Vanderlinden@Sun.COM 		addr64 = (((uint64_t)data[3]) << 32) | data[2];
1094*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_PV_PAGING_FIXUP, rip64, addr64);
1095*11153SFrank.Vanderlinden@Sun.COM 		break;
1096*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_GDT_LDT_MAPPING_FAULT:
1097*11153SFrank.Vanderlinden@Sun.COM 		/*
1098*11153SFrank.Vanderlinden@Sun.COM 		 * Descriptor table mapping fault in a 32-bit PV domain.
1099*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = eip
1100*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = offset
1101*11153SFrank.Vanderlinden@Sun.COM 		 */
1102*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_PV_DT_MAPPING_FAULT, data[0], data[1]);
1103*11153SFrank.Vanderlinden@Sun.COM 		break;
1104*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_GDT_LDT_MAPPING_FAULT | TRC_64_FLAG:
1105*11153SFrank.Vanderlinden@Sun.COM 		/*
1106*11153SFrank.Vanderlinden@Sun.COM 		 * Descriptor table mapping fault in a 64-bit PV domain.
1107*11153SFrank.Vanderlinden@Sun.COM 		 *
1108*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = eip(0:31)
1109*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = eip(31:63)
1110*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = offset(0:31)
1111*11153SFrank.Vanderlinden@Sun.COM 		 * data[3] = offset(31:63)
1112*11153SFrank.Vanderlinden@Sun.COM 		 */
1113*11153SFrank.Vanderlinden@Sun.COM 		rip64 = (((uint64_t)data[1]) << 32) | data[0];
1114*11153SFrank.Vanderlinden@Sun.COM 		val64 = (((uint64_t)data[3]) << 32) | data[2];
1115*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_PV_DT_MAPPING_FAULT, rip64, val64);
1116*11153SFrank.Vanderlinden@Sun.COM 		break;
1117*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_PTWR_EMULATION:
1118*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_PTWR_EMULATION_PAE | TRC_64_FLAG:
1119*11153SFrank.Vanderlinden@Sun.COM 		/*
1120*11153SFrank.Vanderlinden@Sun.COM 		 * Should only happen on 32-bit hypervisor; unused.
1121*11153SFrank.Vanderlinden@Sun.COM 		 */
1122*11153SFrank.Vanderlinden@Sun.COM 		break;
1123*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_PTWR_EMULATION_PAE:
1124*11153SFrank.Vanderlinden@Sun.COM 		/*
1125*11153SFrank.Vanderlinden@Sun.COM 		 * PTE write emulation for a 32-bit PV domain.
1126*11153SFrank.Vanderlinden@Sun.COM 		 *
1127*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = pte
1128*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = addr
1129*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = eip
1130*11153SFrank.Vanderlinden@Sun.COM 		 */
1131*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE3(XDT_PV_PTWR_EMULATION, data[0], data[1], data[2]);
1132*11153SFrank.Vanderlinden@Sun.COM 		break;
1133*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PV_PTWR_EMULATION | TRC_64_FLAG:
1134*11153SFrank.Vanderlinden@Sun.COM 		/*
1135*11153SFrank.Vanderlinden@Sun.COM 		 * PTE write emulation for a 64-bit PV domain.
1136*11153SFrank.Vanderlinden@Sun.COM 		 *
1137*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = pte(0:31)
1138*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = pte(32:63)
1139*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = addr(0:31)
1140*11153SFrank.Vanderlinden@Sun.COM 		 * data[3] = addr(32:63)
1141*11153SFrank.Vanderlinden@Sun.COM 		 * data[4] = rip(0:31)
1142*11153SFrank.Vanderlinden@Sun.COM 		 * data[5] = rip(32:63)
1143*11153SFrank.Vanderlinden@Sun.COM 		 */
1144*11153SFrank.Vanderlinden@Sun.COM 		pte64 = (((uint64_t)data[1]) << 32) | data[0];
1145*11153SFrank.Vanderlinden@Sun.COM 		addr64 = (((uint64_t)data[3]) << 32) | data[2];
1146*11153SFrank.Vanderlinden@Sun.COM 		rip64 = (((uint64_t)data[5]) << 32) | data[4];
1147*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE3(XDT_PV_PTWR_EMULATION, pte64, addr64, rip64);
11486670Stariq 		break;
11496670Stariq 
11506670Stariq 	/*
11516670Stariq 	 * HVM probes
11526670Stariq 	 */
11536670Stariq 	case TRC_HVM_VMENTRY:
11546670Stariq 		/*
11556670Stariq 		 * Return to guest via vmx_launch/vmrun
11566670Stariq 		 *
1157*11153SFrank.Vanderlinden@Sun.COM 		 */
1158*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE0(XDT_HVM_VMENTRY);
1159*11153SFrank.Vanderlinden@Sun.COM 		break;
1160*11153SFrank.Vanderlinden@Sun.COM 
1161*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_VMEXIT:
1162*11153SFrank.Vanderlinden@Sun.COM 		/*
1163*11153SFrank.Vanderlinden@Sun.COM 		 * Entry into VMEXIT handler from 32-bit HVM domain
1164*11153SFrank.Vanderlinden@Sun.COM 		 *
1165*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = cpu vendor specific exit code
1166*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = guest eip
1167*11153SFrank.Vanderlinden@Sun.COM 		 */
1168*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_HVM_VMEXIT, data[0], data[1]);
1169*11153SFrank.Vanderlinden@Sun.COM 		break;
1170*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_VMEXIT64:
1171*11153SFrank.Vanderlinden@Sun.COM 		/*
1172*11153SFrank.Vanderlinden@Sun.COM 		 * Entry into VMEXIT handler from 64-bit HVM domain
1173*11153SFrank.Vanderlinden@Sun.COM 		 *
1174*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = cpu vendor specific exit code
1175*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = guest rip(0:31)
1176*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = guest rip(32:64)
1177*11153SFrank.Vanderlinden@Sun.COM 		 */
1178*11153SFrank.Vanderlinden@Sun.COM 		rip64 = (((uint64_t)data[2]) << 32) | data[1];
1179*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_HVM_VMEXIT, data[0], rip64);
1180*11153SFrank.Vanderlinden@Sun.COM 		break;
1181*11153SFrank.Vanderlinden@Sun.COM 
1182*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_PF_XEN64:
1183*11153SFrank.Vanderlinden@Sun.COM 		/*
1184*11153SFrank.Vanderlinden@Sun.COM 		 * Pagefault in a guest that is a Xen (e.g. shadow)
1185*11153SFrank.Vanderlinden@Sun.COM 		 * artifact, and is not injected back into the guest.
1186*11153SFrank.Vanderlinden@Sun.COM 		 *
1187*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = error code
1188*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = guest VA(0:31)
1189*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = guest VA(32:64)
1190*11153SFrank.Vanderlinden@Sun.COM 		 */
1191*11153SFrank.Vanderlinden@Sun.COM 		addr64 = (((uint64_t)data[2]) << 32) | data[1];
1192*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_HVM_PF_XEN, data[0], addr64);
1193*11153SFrank.Vanderlinden@Sun.COM 		break;
1194*11153SFrank.Vanderlinden@Sun.COM 
1195*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_PF_XEN:
1196*11153SFrank.Vanderlinden@Sun.COM 		/*
1197*11153SFrank.Vanderlinden@Sun.COM 		 * Same as above, but for a 32-bit HVM domain.
1198*11153SFrank.Vanderlinden@Sun.COM 		 *
1199*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = error code
1200*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = guest VA
1201*11153SFrank.Vanderlinden@Sun.COM 		 */
1202*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_HVM_PF_XEN, data[0], data[1]);
1203*11153SFrank.Vanderlinden@Sun.COM 		break;
1204*11153SFrank.Vanderlinden@Sun.COM 
1205*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_PF_INJECT:
1206*11153SFrank.Vanderlinden@Sun.COM 		/*
1207*11153SFrank.Vanderlinden@Sun.COM 		 * 32-bit Xen only.
1208*11153SFrank.Vanderlinden@Sun.COM 		 */
1209*11153SFrank.Vanderlinden@Sun.COM 		break;
1210*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_PF_INJECT64:
1211*11153SFrank.Vanderlinden@Sun.COM 		/*
1212*11153SFrank.Vanderlinden@Sun.COM 		 * Pagefault injected back into a guest (e.g. the shadow
1213*11153SFrank.Vanderlinden@Sun.COM 		 * code found no mapping).
1214*11153SFrank.Vanderlinden@Sun.COM 		 *
1215*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = error code
1216*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = guest VA(0:31)
1217*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = guest VA(32:64)
1218*11153SFrank.Vanderlinden@Sun.COM 		 */
1219*11153SFrank.Vanderlinden@Sun.COM 		addr64 = (((uint64_t)data[2]) << 32) | data[1];
1220*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_HVM_PF_INJECT, data[0], addr64);
1221*11153SFrank.Vanderlinden@Sun.COM 		break;
1222*11153SFrank.Vanderlinden@Sun.COM 
1223*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_INJ_EXC:
1224*11153SFrank.Vanderlinden@Sun.COM 		/*
1225*11153SFrank.Vanderlinden@Sun.COM 		 * Exception injected into an HVM guest.
1226*11153SFrank.Vanderlinden@Sun.COM 		 *
1227*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = trap
1228*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = error code
1229*11153SFrank.Vanderlinden@Sun.COM 		 */
1230*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_HVM_EXC_INJECT, data[0], data[1]);
1231*11153SFrank.Vanderlinden@Sun.COM 		break;
1232*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_INJ_VIRQ:
1233*11153SFrank.Vanderlinden@Sun.COM 		/*
1234*11153SFrank.Vanderlinden@Sun.COM 		 * Interrupt inject into an HVM guest.
1235*11153SFrank.Vanderlinden@Sun.COM 		 *
1236*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = vector
1237*11153SFrank.Vanderlinden@Sun.COM 		 */
1238*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_HVM_VIRQ_INJECT, data[0]);
1239*11153SFrank.Vanderlinden@Sun.COM 		break;
1240*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_REINJ_VIRQ:
1241*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_IO_READ:
1242*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_IO_WRITE:
1243*11153SFrank.Vanderlinden@Sun.COM 		/* unused */
1244*11153SFrank.Vanderlinden@Sun.COM 		break;
1245*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_CR_READ64:
1246*11153SFrank.Vanderlinden@Sun.COM 		/*
1247*11153SFrank.Vanderlinden@Sun.COM 		 * Control register read. Intel VMX only.
1248*11153SFrank.Vanderlinden@Sun.COM 		 *
1249*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = control register #
1250*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = value(0:31)
1251*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = value(32:63)
1252*11153SFrank.Vanderlinden@Sun.COM 		 */
1253*11153SFrank.Vanderlinden@Sun.COM 		val64 = (((uint64_t)data[2]) << 32) | data[1];
1254*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_HVM_CR_READ, data[0], val64);
1255*11153SFrank.Vanderlinden@Sun.COM 		break;
1256*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_CR_READ:
1257*11153SFrank.Vanderlinden@Sun.COM 		/*
1258*11153SFrank.Vanderlinden@Sun.COM 		 * unused (32-bit Xen only)
1259*11153SFrank.Vanderlinden@Sun.COM 		 */
1260*11153SFrank.Vanderlinden@Sun.COM 		break;
1261*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_CR_WRITE64:
1262*11153SFrank.Vanderlinden@Sun.COM 		/*
1263*11153SFrank.Vanderlinden@Sun.COM 		 * Control register write. Intel VMX only.
1264*11153SFrank.Vanderlinden@Sun.COM 		 *
1265*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = control register #
1266*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = value(0:31)
1267*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = value(32:63)
1268*11153SFrank.Vanderlinden@Sun.COM 		 */
1269*11153SFrank.Vanderlinden@Sun.COM 		val64 = (((uint64_t)data[2]) << 32) | data[1];
1270*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_HVM_CR_READ, data[0], val64);
1271*11153SFrank.Vanderlinden@Sun.COM 		break;
1272*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_CR_WRITE:
1273*11153SFrank.Vanderlinden@Sun.COM 		/*
1274*11153SFrank.Vanderlinden@Sun.COM 		 * unused (32-bit Xen only)
1275*11153SFrank.Vanderlinden@Sun.COM 		 */
1276*11153SFrank.Vanderlinden@Sun.COM 		break;
1277*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_DR_READ:
1278*11153SFrank.Vanderlinden@Sun.COM 		/*
1279*11153SFrank.Vanderlinden@Sun.COM 		 * unused.
1280*11153SFrank.Vanderlinden@Sun.COM 		 *
128110175SStuart.Maybee@Sun.COM 		 * data[0] = (domid<<16 + vcpuid)
12826670Stariq 		 */
1283*11153SFrank.Vanderlinden@Sun.COM 		break;
1284*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_DR_WRITE:
1285*11153SFrank.Vanderlinden@Sun.COM 		/*
1286*11153SFrank.Vanderlinden@Sun.COM 		 * Debug register write. Not too useful; no values,
1287*11153SFrank.Vanderlinden@Sun.COM 		 * so we ignore this.
1288*11153SFrank.Vanderlinden@Sun.COM 		 *
1289*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = (domid<<16 + vcpuid)
1290*11153SFrank.Vanderlinden@Sun.COM 		 */
1291*11153SFrank.Vanderlinden@Sun.COM 		break;
1292*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_MSR_READ:
1293*11153SFrank.Vanderlinden@Sun.COM 		/*
1294*11153SFrank.Vanderlinden@Sun.COM 		 * MSR read.
1295*11153SFrank.Vanderlinden@Sun.COM 		 *
1296*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = MSR
1297*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = value(0:31)
1298*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = value(32:63)
1299*11153SFrank.Vanderlinden@Sun.COM 		 */
1300*11153SFrank.Vanderlinden@Sun.COM 		val64 = (((uint64_t)data[3]) << 32) | data[2];
1301*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_HVM_MSR_READ, data[0], val64);
1302*11153SFrank.Vanderlinden@Sun.COM 		break;
1303*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_MSR_WRITE:
1304*11153SFrank.Vanderlinden@Sun.COM 		/*
1305*11153SFrank.Vanderlinden@Sun.COM 		 * MSR write.
1306*11153SFrank.Vanderlinden@Sun.COM 		 *
1307*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = MSR;
1308*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = value(0:31)
1309*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = value(32:63)
1310*11153SFrank.Vanderlinden@Sun.COM 		 */
1311*11153SFrank.Vanderlinden@Sun.COM 		val64 = (((uint64_t)data[2]) << 32) | data[1];
1312*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_HVM_MSR_WRITE, data[0], val64);
1313*11153SFrank.Vanderlinden@Sun.COM 		break;
1314*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_CPUID:
1315*11153SFrank.Vanderlinden@Sun.COM 		/*
1316*11153SFrank.Vanderlinden@Sun.COM 		 * CPUID insn.
1317*11153SFrank.Vanderlinden@Sun.COM 		 *
1318*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = %eax (input)
1319*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = %eax
1320*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = %ebx
1321*11153SFrank.Vanderlinden@Sun.COM 		 * data[3] = %ecx
1322*11153SFrank.Vanderlinden@Sun.COM 		 * data[4] = %edx
1323*11153SFrank.Vanderlinden@Sun.COM 		 */
1324*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE5(XDT_HVM_CPUID, data[0], data[1], data[2], data[3],
1325*11153SFrank.Vanderlinden@Sun.COM 		    data[4]);
1326*11153SFrank.Vanderlinden@Sun.COM 		break;
1327*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_INTR:
1328*11153SFrank.Vanderlinden@Sun.COM 		/*
1329*11153SFrank.Vanderlinden@Sun.COM 		 * VMEXIT because of an interrupt.
1330*11153SFrank.Vanderlinden@Sun.COM 		 */
1331*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE0(XDT_HVM_INTR);
13326670Stariq 		break;
1333*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_INTR_WINDOW:
1334*11153SFrank.Vanderlinden@Sun.COM 		/*
1335*11153SFrank.Vanderlinden@Sun.COM 		 * VMEXIT because of an interrupt window (an interrupt
1336*11153SFrank.Vanderlinden@Sun.COM 		 * can't be delivered immediately to a HVM guest and must
1337*11153SFrank.Vanderlinden@Sun.COM 		 * be delayed).
1338*11153SFrank.Vanderlinden@Sun.COM 		 *
1339*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = vector
1340*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = source
1341*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = info
1342*11153SFrank.Vanderlinden@Sun.COM 		 */
1343*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE3(XDT_HVM_INTR_WINDOW, data[0], data[1], data[2]);
1344*11153SFrank.Vanderlinden@Sun.COM 		break;
1345*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_NMI:
1346*11153SFrank.Vanderlinden@Sun.COM 		/*
1347*11153SFrank.Vanderlinden@Sun.COM 		 * VMEXIT because of an NMI.
1348*11153SFrank.Vanderlinden@Sun.COM 		 */
1349*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE0(XDT_HVM_NMI);
1350*11153SFrank.Vanderlinden@Sun.COM 		break;
1351*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_SMI:
1352*11153SFrank.Vanderlinden@Sun.COM 		/*
1353*11153SFrank.Vanderlinden@Sun.COM 		 * VMEXIT because of an SMI
1354*11153SFrank.Vanderlinden@Sun.COM 		 */
1355*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE0(XDT_HVM_SMI);
1356*11153SFrank.Vanderlinden@Sun.COM 		break;
1357*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_VMMCALL:
13586670Stariq 		/*
1359*11153SFrank.Vanderlinden@Sun.COM 		 * VMMCALL insn.
1360*11153SFrank.Vanderlinden@Sun.COM 		 *
1361*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = %eax
1362*11153SFrank.Vanderlinden@Sun.COM 		 */
1363*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_HVM_VMMCALL, data[0]);
1364*11153SFrank.Vanderlinden@Sun.COM 		break;
1365*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_HLT:
1366*11153SFrank.Vanderlinden@Sun.COM 		/*
1367*11153SFrank.Vanderlinden@Sun.COM 		 * HLT insn.
1368*11153SFrank.Vanderlinden@Sun.COM 		 *
1369*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = 1 if VCPU runnable, 0 if not
1370*11153SFrank.Vanderlinden@Sun.COM 		 */
1371*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_HVM_HLT, data[0]);
1372*11153SFrank.Vanderlinden@Sun.COM 		break;
1373*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_INVLPG64:
1374*11153SFrank.Vanderlinden@Sun.COM 		/*
1375*11153SFrank.Vanderlinden@Sun.COM 		 *
1376*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = INVLPGA ? 1 : 0
1377*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = vaddr(0:31)
1378*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = vaddr(32:63)
1379*11153SFrank.Vanderlinden@Sun.COM 		 */
1380*11153SFrank.Vanderlinden@Sun.COM 		addr64 = (((uint64_t)data[2]) << 32) | data[1];
1381*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_HVM_INVLPG, data[0], addr64);
1382*11153SFrank.Vanderlinden@Sun.COM 		break;
1383*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_INVLPG:
1384*11153SFrank.Vanderlinden@Sun.COM 		/*
1385*11153SFrank.Vanderlinden@Sun.COM 		 * unused (32-bit Xen only)
13866670Stariq 		 *
138710175SStuart.Maybee@Sun.COM 		 * data[0] = (domid<<16 + vcpuid)
1388*11153SFrank.Vanderlinden@Sun.COM 		 */
1389*11153SFrank.Vanderlinden@Sun.COM 		break;
1390*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_MCE:
1391*11153SFrank.Vanderlinden@Sun.COM 		/*
1392*11153SFrank.Vanderlinden@Sun.COM 		 * #MCE VMEXIT
1393*11153SFrank.Vanderlinden@Sun.COM 		 *
1394*11153SFrank.Vanderlinden@Sun.COM 		 */
1395*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE0(XDT_HVM_MCE);
1396*11153SFrank.Vanderlinden@Sun.COM 		break;
1397*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_IOPORT_READ:
1398*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_IOPORT_WRITE:
1399*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_IOMEM_READ:
1400*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_IOMEM_WRITE:
1401*11153SFrank.Vanderlinden@Sun.COM 		/*
1402*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = addr(0:31)
1403*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = addr(32:63)
1404*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = count
1405*11153SFrank.Vanderlinden@Sun.COM 		 * data[3] = size
14066670Stariq 		 */
1407*11153SFrank.Vanderlinden@Sun.COM 		switch (rec->event) {
1408*11153SFrank.Vanderlinden@Sun.COM 		case TRC_HVM_IOPORT_READ:
1409*11153SFrank.Vanderlinden@Sun.COM 			eid = XDT_HVM_IOPORT_READ;
1410*11153SFrank.Vanderlinden@Sun.COM 			break;
1411*11153SFrank.Vanderlinden@Sun.COM 		case TRC_HVM_IOPORT_WRITE:
1412*11153SFrank.Vanderlinden@Sun.COM 			eid = XDT_HVM_IOPORT_WRITE;
1413*11153SFrank.Vanderlinden@Sun.COM 			break;
1414*11153SFrank.Vanderlinden@Sun.COM 		case TRC_HVM_IOMEM_READ:
1415*11153SFrank.Vanderlinden@Sun.COM 			eid = XDT_HVM_IOMEM_READ;
1416*11153SFrank.Vanderlinden@Sun.COM 			break;
1417*11153SFrank.Vanderlinden@Sun.COM 		case TRC_HVM_IOMEM_WRITE:
1418*11153SFrank.Vanderlinden@Sun.COM 			eid = XDT_HVM_IOMEM_WRITE;
1419*11153SFrank.Vanderlinden@Sun.COM 			break;
1420*11153SFrank.Vanderlinden@Sun.COM 		}
1421*11153SFrank.Vanderlinden@Sun.COM 		addr64 = (((uint64_t)data[1]) << 32) | data[0];
1422*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE3(eid, addr64, data[2], data[3]);
1423*11153SFrank.Vanderlinden@Sun.COM 		break;
1424*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_CLTS:
1425*11153SFrank.Vanderlinden@Sun.COM 		/*
1426*11153SFrank.Vanderlinden@Sun.COM 		 * CLTS insn (Intel VMX only)
1427*11153SFrank.Vanderlinden@Sun.COM 		 */
1428*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE0(XDT_HVM_CLTS);
1429*11153SFrank.Vanderlinden@Sun.COM 		break;
1430*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_LMSW64:
1431*11153SFrank.Vanderlinden@Sun.COM 		/*
1432*11153SFrank.Vanderlinden@Sun.COM 		 * LMSW insn.
1433*11153SFrank.Vanderlinden@Sun.COM 		 *
1434*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = value(0:31)
1435*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = value(32:63)
1436*11153SFrank.Vanderlinden@Sun.COM 		 */
1437*11153SFrank.Vanderlinden@Sun.COM 		val64 = (((uint64_t)data[1]) << 32) | data[0];
1438*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_HVM_LMSW, val64);
1439*11153SFrank.Vanderlinden@Sun.COM 		break;
1440*11153SFrank.Vanderlinden@Sun.COM 	case TRC_HVM_LMSW:
1441*11153SFrank.Vanderlinden@Sun.COM 		/*
1442*11153SFrank.Vanderlinden@Sun.COM 		 * unused (32-bit Xen only)
1443*11153SFrank.Vanderlinden@Sun.COM 		 */
14446670Stariq 		break;
14456670Stariq 
1446*11153SFrank.Vanderlinden@Sun.COM 	/*
1447*11153SFrank.Vanderlinden@Sun.COM 	 * Shadow page table probes (mainly used for HVM domains
1448*11153SFrank.Vanderlinden@Sun.COM 	 * without hardware paging support).
1449*11153SFrank.Vanderlinden@Sun.COM 	 */
1450*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_NOT_SHADOW | SH_GUEST_32:
1451*11153SFrank.Vanderlinden@Sun.COM 		/*
1452*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = pte(0:31)
1453*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = pte(32:63)
1454*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = va
1455*11153SFrank.Vanderlinden@Sun.COM 		 * data[3] = flags
1456*11153SFrank.Vanderlinden@Sun.COM 		 */
1457*11153SFrank.Vanderlinden@Sun.COM 		pte64 = ((uint64_t)data[1] << 32) | data[0];
1458*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE3(XDT_SHADOW_NOT_SHADOW, pte64, data[2], data[3]);
1459*11153SFrank.Vanderlinden@Sun.COM 		break;
1460*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_NOT_SHADOW | SH_GUEST_PAE:
1461*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_NOT_SHADOW | SH_GUEST_64:
1462*11153SFrank.Vanderlinden@Sun.COM 		/*
1463*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = pte(0:31)
1464*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = pte(32:63)
1465*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = va(0:31)
1466*11153SFrank.Vanderlinden@Sun.COM 		 * data[3] = va(32:63)
1467*11153SFrank.Vanderlinden@Sun.COM 		 * data[4] = flags
1468*11153SFrank.Vanderlinden@Sun.COM 		 */
1469*11153SFrank.Vanderlinden@Sun.COM 		addr64 = ((uint64_t)data[2] << 32) | data[3];
1470*11153SFrank.Vanderlinden@Sun.COM 		pte64 = ((uint64_t)data[1] << 32) | data[0];
1471*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE3(XDT_SHADOW_NOT_SHADOW, pte64, addr64, data[4]);
1472*11153SFrank.Vanderlinden@Sun.COM 		break;
1473*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_FAST_PROPAGATE | SH_GUEST_32:
1474*11153SFrank.Vanderlinden@Sun.COM 		/*
1475*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = va
1476*11153SFrank.Vanderlinden@Sun.COM 		 */
1477*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_SHADOW_FAST_PROPAGATE, data[0]);
1478*11153SFrank.Vanderlinden@Sun.COM 		break;
1479*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_FAST_PROPAGATE | SH_GUEST_PAE:
1480*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_FAST_PROPAGATE | SH_GUEST_64:
1481*11153SFrank.Vanderlinden@Sun.COM 		/*
1482*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = va(0:31)
1483*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = va(32:63)
1484*11153SFrank.Vanderlinden@Sun.COM 		 */
1485*11153SFrank.Vanderlinden@Sun.COM 		addr64 = ((uint64_t)data[1] << 32) | data[0];
1486*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_SHADOW_FAST_PROPAGATE, addr64);
1487*11153SFrank.Vanderlinden@Sun.COM 		break;
1488*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_FAST_MMIO | SH_GUEST_32:
1489*11153SFrank.Vanderlinden@Sun.COM 		/*
1490*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = va
1491*11153SFrank.Vanderlinden@Sun.COM 		 */
1492*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_SHADOW_FAST_MMIO, data[0]);
1493*11153SFrank.Vanderlinden@Sun.COM 		break;
1494*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_FAST_MMIO | SH_GUEST_PAE:
1495*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_FAST_MMIO | SH_GUEST_64:
1496*11153SFrank.Vanderlinden@Sun.COM 		/*
1497*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = va(0:31)
1498*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = va(32:63)
1499*11153SFrank.Vanderlinden@Sun.COM 		 */
1500*11153SFrank.Vanderlinden@Sun.COM 		addr64 = ((uint64_t)data[1] << 32) | data[0];
1501*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_SHADOW_FAST_MMIO, addr64);
1502*11153SFrank.Vanderlinden@Sun.COM 		break;
1503*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_FALSE_FAST_PATH | SH_GUEST_32:
1504*11153SFrank.Vanderlinden@Sun.COM 		/*
1505*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = va
1506*11153SFrank.Vanderlinden@Sun.COM 		 */
1507*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_SHADOW_FALSE_FAST_PATH, data[0]);
1508*11153SFrank.Vanderlinden@Sun.COM 		break;
1509*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_FALSE_FAST_PATH | SH_GUEST_PAE:
1510*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_FALSE_FAST_PATH | SH_GUEST_64:
1511*11153SFrank.Vanderlinden@Sun.COM 		/*
1512*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = va(0:31)
1513*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = va(32:63)
1514*11153SFrank.Vanderlinden@Sun.COM 		 */
1515*11153SFrank.Vanderlinden@Sun.COM 		addr64 = ((uint64_t)data[1] << 32) | data[0];
1516*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_SHADOW_FALSE_FAST_PATH, addr64);
1517*11153SFrank.Vanderlinden@Sun.COM 		break;
1518*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_MMIO | SH_GUEST_32:
1519*11153SFrank.Vanderlinden@Sun.COM 		/*
1520*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = va
1521*11153SFrank.Vanderlinden@Sun.COM 		 */
1522*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_SHADOW_MMIO, data[0]);
1523*11153SFrank.Vanderlinden@Sun.COM 		break;
1524*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_MMIO | SH_GUEST_PAE:
1525*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_MMIO | SH_GUEST_64:
1526*11153SFrank.Vanderlinden@Sun.COM 		/*
1527*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = va(0:31)
1528*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = va(32:63)
1529*11153SFrank.Vanderlinden@Sun.COM 		 */
1530*11153SFrank.Vanderlinden@Sun.COM 		addr64 = ((uint64_t)data[1] << 32) | data[0];
1531*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_SHADOW_MMIO, addr64);
1532*11153SFrank.Vanderlinden@Sun.COM 		break;
1533*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_FIXUP | SH_GUEST_32:
1534*11153SFrank.Vanderlinden@Sun.COM 		/*
1535*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = pte(0:31)
1536*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = pte(32:63)
1537*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = va
1538*11153SFrank.Vanderlinden@Sun.COM 		 * data[3] = flags
1539*11153SFrank.Vanderlinden@Sun.COM 		 */
1540*11153SFrank.Vanderlinden@Sun.COM 		pte64 = ((uint64_t)data[1] << 32) | data[0];
1541*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE3(XDT_SHADOW_FIXUP, pte64, data[2], data[3]);
1542*11153SFrank.Vanderlinden@Sun.COM 		break;
1543*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_FIXUP | SH_GUEST_64:
1544*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_FIXUP | SH_GUEST_PAE:
1545*11153SFrank.Vanderlinden@Sun.COM 		/*
1546*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = pte(0:31)
1547*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = pte(32:63)
1548*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = va(0:31)
1549*11153SFrank.Vanderlinden@Sun.COM 		 * data[3] = va(32:63)
1550*11153SFrank.Vanderlinden@Sun.COM 		 * data[4] = flags
1551*11153SFrank.Vanderlinden@Sun.COM 		 */
1552*11153SFrank.Vanderlinden@Sun.COM 		addr64 = ((uint64_t)data[2] << 32) | data[3];
1553*11153SFrank.Vanderlinden@Sun.COM 		pte64 = ((uint64_t)data[1] << 32) | data[0];
1554*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE3(XDT_SHADOW_FIXUP, pte64, addr64, data[4]);
1555*11153SFrank.Vanderlinden@Sun.COM 		break;
1556*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_DOMF_DYING | SH_GUEST_32:
1557*11153SFrank.Vanderlinden@Sun.COM 		/*
1558*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = va
1559*11153SFrank.Vanderlinden@Sun.COM 		 */
1560*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_SHADOW_DOMF_DYING, data[0]);
1561*11153SFrank.Vanderlinden@Sun.COM 		break;
1562*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_DOMF_DYING | SH_GUEST_PAE:
1563*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_DOMF_DYING | SH_GUEST_64:
1564*11153SFrank.Vanderlinden@Sun.COM 		/*
1565*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = va(0:31)
1566*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = va(32:63)
1567*11153SFrank.Vanderlinden@Sun.COM 		 */
1568*11153SFrank.Vanderlinden@Sun.COM 		addr64 = ((uint64_t)data[1] << 32) | data[0];
1569*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_SHADOW_DOMF_DYING, addr64);
1570*11153SFrank.Vanderlinden@Sun.COM 		break;
1571*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_EMULATE | SH_GUEST_32:
1572*11153SFrank.Vanderlinden@Sun.COM 		/*
1573*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = pte(0:31)
1574*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = pte(32:63)
1575*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = val(0:31)
1576*11153SFrank.Vanderlinden@Sun.COM 		 * data[3] = val(32:63)
1577*11153SFrank.Vanderlinden@Sun.COM 		 * data[4] = addr
1578*11153SFrank.Vanderlinden@Sun.COM 		 * data[5] = flags
1579*11153SFrank.Vanderlinden@Sun.COM 		 */
1580*11153SFrank.Vanderlinden@Sun.COM 		pte64 = ((uint64_t)data[1] << 32) | data[0];
1581*11153SFrank.Vanderlinden@Sun.COM 		val64 = ((uint64_t)data[3] << 32) | data[2];
1582*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE5(XDT_SHADOW_EMULATE, pte64, val64, data[4],
1583*11153SFrank.Vanderlinden@Sun.COM 		    data[5] & 0x7fffffff, data[5] >> 29);
1584*11153SFrank.Vanderlinden@Sun.COM 		break;
1585*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_EMULATE | SH_GUEST_PAE:
1586*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_EMULATE | SH_GUEST_64:
1587*11153SFrank.Vanderlinden@Sun.COM 		/*
1588*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = pte(0:31)
1589*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = pte(32:63)
1590*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = val(0:31)
1591*11153SFrank.Vanderlinden@Sun.COM 		 * data[3] = val(32:63)
1592*11153SFrank.Vanderlinden@Sun.COM 		 * data[4] = addr(0:31)
1593*11153SFrank.Vanderlinden@Sun.COM 		 * data[5] = addr(32:63)
1594*11153SFrank.Vanderlinden@Sun.COM 		 * data[6] = flags
1595*11153SFrank.Vanderlinden@Sun.COM 		 */
1596*11153SFrank.Vanderlinden@Sun.COM 		pte64 = ((uint64_t)data[1] << 32) | data[0];
1597*11153SFrank.Vanderlinden@Sun.COM 		val64 = ((uint64_t)data[3] << 32) | data[2];
1598*11153SFrank.Vanderlinden@Sun.COM 		addr64 = ((uint64_t)data[5] << 32) | data[4];
1599*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE5(XDT_SHADOW_EMULATE, pte64, val64, data[4],
1600*11153SFrank.Vanderlinden@Sun.COM 		    data[6] & 0x7fffffff, data[6] >> 29);
1601*11153SFrank.Vanderlinden@Sun.COM 		break;
1602*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_EMULATE_UNSHADOW_USER | SH_GUEST_32:
1603*11153SFrank.Vanderlinden@Sun.COM 		/*
1604*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = gfn
1605*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = vaddr
1606*11153SFrank.Vanderlinden@Sun.COM 		 */
1607*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_USER, data[0], data[1]);
1608*11153SFrank.Vanderlinden@Sun.COM 		break;
1609*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_EMULATE_UNSHADOW_USER | SH_GUEST_PAE:
1610*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_EMULATE_UNSHADOW_USER | SH_GUEST_64:
1611*11153SFrank.Vanderlinden@Sun.COM 		/*
1612*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = gfn(0:31)
1613*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = gfn(32:63)
1614*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = vaddr(0:31)
1615*11153SFrank.Vanderlinden@Sun.COM 		 * data[3] = vaddr(32:63)
1616*11153SFrank.Vanderlinden@Sun.COM 		 */
1617*11153SFrank.Vanderlinden@Sun.COM 		val64 = ((uint64_t)data[1] << 32) | data[0];
1618*11153SFrank.Vanderlinden@Sun.COM 		addr64 = ((uint64_t)data[3] << 32) | data[2];
1619*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_USER, val64, addr64);
1620*11153SFrank.Vanderlinden@Sun.COM 		break;
1621*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ | SH_GUEST_32:
1622*11153SFrank.Vanderlinden@Sun.COM 		/*
1623*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = gfn
1624*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = vaddr
1625*11153SFrank.Vanderlinden@Sun.COM 		 */
1626*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ, data[0],
1627*11153SFrank.Vanderlinden@Sun.COM 		    data[1]);
1628*11153SFrank.Vanderlinden@Sun.COM 		break;
1629*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ | SH_GUEST_PAE:
1630*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ | SH_GUEST_64:
1631*11153SFrank.Vanderlinden@Sun.COM 		/*
1632*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = gfn(0:31)
1633*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = gfn(32:63)
1634*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = vaddr(0:31)
1635*11153SFrank.Vanderlinden@Sun.COM 		 * data[3] = vaddr(32:63)
1636*11153SFrank.Vanderlinden@Sun.COM 		 */
1637*11153SFrank.Vanderlinden@Sun.COM 		val64 = ((uint64_t)data[1] << 32) | data[0];
1638*11153SFrank.Vanderlinden@Sun.COM 		addr64 = ((uint64_t)data[3] << 32) | data[2];
1639*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ, val64, addr64);
1640*11153SFrank.Vanderlinden@Sun.COM 		break;
1641*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED | SH_GUEST_32:
1642*11153SFrank.Vanderlinden@Sun.COM 		/*
1643*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = gfn
1644*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = vaddr
1645*11153SFrank.Vanderlinden@Sun.COM 		 */
1646*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED, data[0],
1647*11153SFrank.Vanderlinden@Sun.COM 		    data[1]);
1648*11153SFrank.Vanderlinden@Sun.COM 		break;
1649*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED | SH_GUEST_PAE:
1650*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED | SH_GUEST_64:
1651*11153SFrank.Vanderlinden@Sun.COM 		/*
1652*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = gfn(0:31)
1653*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = gfn(32:63)
1654*11153SFrank.Vanderlinden@Sun.COM 		 * data[2] = vaddr(0:31)
1655*11153SFrank.Vanderlinden@Sun.COM 		 * data[3] = vaddr(32:63)
1656*11153SFrank.Vanderlinden@Sun.COM 		 */
1657*11153SFrank.Vanderlinden@Sun.COM 		val64 = ((uint64_t)data[1] << 32) | data[0];
1658*11153SFrank.Vanderlinden@Sun.COM 		addr64 = ((uint64_t)data[3] << 32) | data[2];
1659*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED, val64,
1660*11153SFrank.Vanderlinden@Sun.COM 		    addr64);
1661*11153SFrank.Vanderlinden@Sun.COM 		break;
1662*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_WRMAP_BF:
1663*11153SFrank.Vanderlinden@Sun.COM 		/*
1664*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = gfn(0:31)
1665*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = gfn(32:63)
1666*11153SFrank.Vanderlinden@Sun.COM 		 */
1667*11153SFrank.Vanderlinden@Sun.COM 		val64 = ((uint64_t)data[1] << 32) | data[0];
1668*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_SHADOW_WRMAP_BF, val64);
1669*11153SFrank.Vanderlinden@Sun.COM 		break;
1670*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_PREALLOC_UNPIN:
1671*11153SFrank.Vanderlinden@Sun.COM 		/*
1672*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = gfn(0:31)
1673*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = gfn(32:63)
1674*11153SFrank.Vanderlinden@Sun.COM 		 */
1675*11153SFrank.Vanderlinden@Sun.COM 		val64 = ((uint64_t)data[1] << 32) | data[0];
1676*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_SHADOW_PREALLOC_UNPIN, val64);
1677*11153SFrank.Vanderlinden@Sun.COM 		break;
1678*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_RESYNC_FULL:
1679*11153SFrank.Vanderlinden@Sun.COM 		/*
1680*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = gmfn(0:31)
1681*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = gmfn(32:63)
1682*11153SFrank.Vanderlinden@Sun.COM 		 */
1683*11153SFrank.Vanderlinden@Sun.COM 		val64 = ((uint64_t)data[1] << 32) | data[0];
1684*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_SHADOW_RESYNC_FULL, val64);
1685*11153SFrank.Vanderlinden@Sun.COM 		break;
1686*11153SFrank.Vanderlinden@Sun.COM 	case TRC_SHADOW_RESYNC_ONLY:
1687*11153SFrank.Vanderlinden@Sun.COM 		/*
1688*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = gmfn(0:31)
1689*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = gmfn(32:63)
1690*11153SFrank.Vanderlinden@Sun.COM 		 */
1691*11153SFrank.Vanderlinden@Sun.COM 		val64 = ((uint64_t)data[1] << 32) | data[0];
1692*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_SHADOW_RESYNC_ONLY, val64);
1693*11153SFrank.Vanderlinden@Sun.COM 		break;
1694*11153SFrank.Vanderlinden@Sun.COM 
1695*11153SFrank.Vanderlinden@Sun.COM 	/*
1696*11153SFrank.Vanderlinden@Sun.COM 	 * Power management probes.
1697*11153SFrank.Vanderlinden@Sun.COM 	 */
1698*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PM_FREQ_CHANGE:
1699*11153SFrank.Vanderlinden@Sun.COM 		/*
1700*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = old freq
1701*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = new freq
1702*11153SFrank.Vanderlinden@Sun.COM 		 */
1703*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_PM_FREQ_CHANGE, data[0], data[1]);
1704*11153SFrank.Vanderlinden@Sun.COM 		break;
1705*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PM_IDLE_ENTRY:
1706*11153SFrank.Vanderlinden@Sun.COM 		/*
1707*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = C-state
1708*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = time
1709*11153SFrank.Vanderlinden@Sun.COM 		 */
1710*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_PM_IDLE_ENTRY, data[0], data[1]);
1711*11153SFrank.Vanderlinden@Sun.COM 		break;
1712*11153SFrank.Vanderlinden@Sun.COM 	case TRC_PM_IDLE_EXIT:
1713*11153SFrank.Vanderlinden@Sun.COM 		/*
1714*11153SFrank.Vanderlinden@Sun.COM 		 * data[0] = C-state
1715*11153SFrank.Vanderlinden@Sun.COM 		 * data[1] = time
1716*11153SFrank.Vanderlinden@Sun.COM 		 */
1717*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE2(XDT_PM_IDLE_EXIT, data[0], data[1]);
1718*11153SFrank.Vanderlinden@Sun.COM 		break;
17196670Stariq 	case TRC_LOST_RECORDS:
1720*11153SFrank.Vanderlinden@Sun.COM 		vcpu = data[1] >> 16;
1721*11153SFrank.Vanderlinden@Sun.COM 		dom = data[1] & 0xffff;
1722*11153SFrank.Vanderlinden@Sun.COM 		xdt_update_sched_context(cpuid, dom, vcpu);
1723*11153SFrank.Vanderlinden@Sun.COM 		xdt_update_domain_context(dom, vcpu);
1724*11153SFrank.Vanderlinden@Sun.COM 		XDT_PROBE1(XDT_TRC_LOST_RECORDS, cpuid);
17256670Stariq 		tbuf.stat_dropped_recs++;
17266670Stariq 		break;
17276670Stariq 
17286670Stariq 	default:
17296670Stariq 		tbuf.stat_unknown_recs++;
17306670Stariq 		break;
17316670Stariq 	}
173210175SStuart.Maybee@Sun.COM 
173310175SStuart.Maybee@Sun.COM done:
173410175SStuart.Maybee@Sun.COM 	rec_size = 4 + (rec->cycles_included ? 8 : 0) + (rec->extra_u32 * 4);
173510175SStuart.Maybee@Sun.COM 	return (rec_size);
17366670Stariq }
17376670Stariq 
1738*11153SFrank.Vanderlinden@Sun.COM /*
1739*11153SFrank.Vanderlinden@Sun.COM  * Scan all CPU buffers for the record with the lowest timestamp so
1740*11153SFrank.Vanderlinden@Sun.COM  * that the probes will fire in order.
1741*11153SFrank.Vanderlinden@Sun.COM  */
1742*11153SFrank.Vanderlinden@Sun.COM static int
xdt_get_first_rec(uint_t * cpuidp,struct t_rec ** recp,uint32_t * consp)1743*11153SFrank.Vanderlinden@Sun.COM xdt_get_first_rec(uint_t *cpuidp, struct t_rec **recp, uint32_t *consp)
1744*11153SFrank.Vanderlinden@Sun.COM {
1745*11153SFrank.Vanderlinden@Sun.COM 	uint_t cpuid;
1746*11153SFrank.Vanderlinden@Sun.COM 	uint32_t prod, cons, offset;
1747*11153SFrank.Vanderlinden@Sun.COM 	struct t_rec *rec;
1748*11153SFrank.Vanderlinden@Sun.COM 	uint64_t minstamp = ~0ULL, stamp;
1749*11153SFrank.Vanderlinden@Sun.COM 	uintptr_t data;
1750*11153SFrank.Vanderlinden@Sun.COM 
1751*11153SFrank.Vanderlinden@Sun.COM 	for (cpuid = 0; cpuid < tbuf.cnt; cpuid++) {
1752*11153SFrank.Vanderlinden@Sun.COM 		cons = tbuf.meta[cpuid]->cons;
1753*11153SFrank.Vanderlinden@Sun.COM 		prod = tbuf.meta[cpuid]->prod;
1754*11153SFrank.Vanderlinden@Sun.COM 		membar_consumer();
1755*11153SFrank.Vanderlinden@Sun.COM 		if (prod == cons)
1756*11153SFrank.Vanderlinden@Sun.COM 			continue;
1757*11153SFrank.Vanderlinden@Sun.COM 
1758*11153SFrank.Vanderlinden@Sun.COM 		offset = cons % tbuf_data_size;
1759*11153SFrank.Vanderlinden@Sun.COM 		data = (uintptr_t)tbuf.data[cpuid] + offset;
1760*11153SFrank.Vanderlinden@Sun.COM 		rec = (struct t_rec *)data;
1761*11153SFrank.Vanderlinden@Sun.COM 		ASSERT((caddr_t)rec < tbuf.va + (tbuf.size * (cpuid + 1)));
1762*11153SFrank.Vanderlinden@Sun.COM 
1763*11153SFrank.Vanderlinden@Sun.COM 		/*
1764*11153SFrank.Vanderlinden@Sun.COM 		 * All records that we know about have time cycles included.
1765*11153SFrank.Vanderlinden@Sun.COM 		 * If this record doesn't have them, assume it's a type
1766*11153SFrank.Vanderlinden@Sun.COM 		 * that we don't handle. Use a 0 time value, which will make
1767*11153SFrank.Vanderlinden@Sun.COM 		 * it get handled first (it will be thrown away).
1768*11153SFrank.Vanderlinden@Sun.COM 		 */
1769*11153SFrank.Vanderlinden@Sun.COM 		if (rec->cycles_included)
1770*11153SFrank.Vanderlinden@Sun.COM 			stamp = (((uint64_t)rec->u.cycles.cycles_hi) << 32)
1771*11153SFrank.Vanderlinden@Sun.COM 			    | rec->u.cycles.cycles_lo;
1772*11153SFrank.Vanderlinden@Sun.COM 		else
1773*11153SFrank.Vanderlinden@Sun.COM 			stamp = 0;
1774*11153SFrank.Vanderlinden@Sun.COM 
1775*11153SFrank.Vanderlinden@Sun.COM 		if (stamp < minstamp) {
1776*11153SFrank.Vanderlinden@Sun.COM 			minstamp = stamp;
1777*11153SFrank.Vanderlinden@Sun.COM 			*cpuidp = cpuid;
1778*11153SFrank.Vanderlinden@Sun.COM 			*recp = rec;
1779*11153SFrank.Vanderlinden@Sun.COM 			*consp = cons;
1780*11153SFrank.Vanderlinden@Sun.COM 		}
1781*11153SFrank.Vanderlinden@Sun.COM 	}
1782*11153SFrank.Vanderlinden@Sun.COM 
1783*11153SFrank.Vanderlinden@Sun.COM 	if (minstamp != ~0ULL)
1784*11153SFrank.Vanderlinden@Sun.COM 		return (1);
1785*11153SFrank.Vanderlinden@Sun.COM 
1786*11153SFrank.Vanderlinden@Sun.COM 	return (0);
1787*11153SFrank.Vanderlinden@Sun.COM }
1788*11153SFrank.Vanderlinden@Sun.COM 
17896670Stariq /*ARGSUSED*/
17906670Stariq static void
xdt_tbuf_scan(void * arg)17916670Stariq xdt_tbuf_scan(void *arg)
17926670Stariq {
1793*11153SFrank.Vanderlinden@Sun.COM 	uint32_t bytes_done, cons;
17946670Stariq 	struct t_rec *rec;
1795*11153SFrank.Vanderlinden@Sun.COM 	xdt_schedinfo_t *sp;
1796*11153SFrank.Vanderlinden@Sun.COM 	uint_t nrecs, cpuid;
179710175SStuart.Maybee@Sun.COM 
1798*11153SFrank.Vanderlinden@Sun.COM 	for (nrecs = 0;
1799*11153SFrank.Vanderlinden@Sun.COM 	    nrecs < xdt_max_recs && xdt_get_first_rec(&cpuid, &rec, &cons) > 0;
1800*11153SFrank.Vanderlinden@Sun.COM 	    nrecs++) {
1801*11153SFrank.Vanderlinden@Sun.COM 		xdt_curpcpu = cpuid;
1802*11153SFrank.Vanderlinden@Sun.COM 		sp = &xdt_cpu_schedinfo[cpuid];
1803*11153SFrank.Vanderlinden@Sun.COM 		if (sp->curinfo_valid)
1804*11153SFrank.Vanderlinden@Sun.COM 			xdt_update_domain_context(sp->cur_domid,
1805*11153SFrank.Vanderlinden@Sun.COM 			    sp->cur_vcpuid);
180610175SStuart.Maybee@Sun.COM 
1807*11153SFrank.Vanderlinden@Sun.COM 		bytes_done = xdt_process_rec(cpuid, rec);
1808*11153SFrank.Vanderlinden@Sun.COM 		cons += bytes_done;
1809*11153SFrank.Vanderlinden@Sun.COM 		/*
1810*11153SFrank.Vanderlinden@Sun.COM 		 * cons and prod are incremented modulo (2 * tbuf_data_size).
1811*11153SFrank.Vanderlinden@Sun.COM 		 * See <xen/public/trace.h>.
1812*11153SFrank.Vanderlinden@Sun.COM 		 */
1813*11153SFrank.Vanderlinden@Sun.COM 		if (cons >= 2 * tbuf_data_size)
1814*11153SFrank.Vanderlinden@Sun.COM 			cons -= 2 * tbuf_data_size;
1815*11153SFrank.Vanderlinden@Sun.COM 		membar_exit();
1816*11153SFrank.Vanderlinden@Sun.COM 		tbuf.meta[cpuid]->cons = cons;
18176670Stariq 	}
18186670Stariq }
18196670Stariq 
18206670Stariq static void
xdt_cyclic_enable(void)18216670Stariq xdt_cyclic_enable(void)
18226670Stariq {
18236670Stariq 	cyc_handler_t hdlr;
18246670Stariq 	cyc_time_t when;
18256670Stariq 
18266670Stariq 	ASSERT(MUTEX_HELD(&cpu_lock));
18276670Stariq 
18286670Stariq 	hdlr.cyh_func = xdt_tbuf_scan;
18296670Stariq 	hdlr.cyh_arg = NULL;
18306670Stariq 	hdlr.cyh_level = CY_LOW_LEVEL;
18316670Stariq 
18326670Stariq 	when.cyt_interval = xdt_poll_nsec;
18336670Stariq 	when.cyt_when = dtrace_gethrtime() + when.cyt_interval;
18346670Stariq 
18356670Stariq 	xdt_cyclic = cyclic_add(&hdlr, &when);
18366670Stariq }
18376670Stariq 
18386670Stariq static void
xdt_probe_create(xdt_probe_t * p)18396670Stariq xdt_probe_create(xdt_probe_t *p)
18406670Stariq {
18416670Stariq 	ASSERT(p != NULL && p->pr_mod != NULL);
18426670Stariq 
18436670Stariq 	if (dtrace_probe_lookup(xdt_id, p->pr_mod, NULL, p->pr_name) != 0)
18446670Stariq 		return;
18456670Stariq 
18466670Stariq 	xdt_prid[p->evt_id] = dtrace_probe_create(xdt_id, p->pr_mod, NULL,
18476670Stariq 	    p->pr_name, dtrace_mach_aframes(), p);
18486670Stariq }
18496670Stariq 
18506670Stariq /*ARGSUSED*/
18516670Stariq static void
xdt_provide(void * arg,const dtrace_probedesc_t * desc)18526670Stariq xdt_provide(void *arg, const dtrace_probedesc_t *desc)
18536670Stariq {
18546670Stariq 	const char *mod, *name;
18556670Stariq 	int i;
18566670Stariq 
18576670Stariq 	if (desc == NULL) {
18586670Stariq 		for (i = 0; xdt_probe[i].pr_mod != NULL; i++) {
18596670Stariq 			xdt_probe_create(&xdt_probe[i]);
18606670Stariq 		}
18616670Stariq 	} else {
18626670Stariq 		mod = desc->dtpd_mod;
18636670Stariq 		name = desc->dtpd_name;
18646670Stariq 		for (i = 0; xdt_probe[i].pr_mod != NULL; i++) {
18656670Stariq 			int l1 = strlen(xdt_probe[i].pr_name);
18666670Stariq 			int l2 = strlen(xdt_probe[i].pr_mod);
18676670Stariq 			if (strncmp(name, xdt_probe[i].pr_name, l1) == 0 &&
18686670Stariq 			    strncmp(mod, xdt_probe[i].pr_mod, l2) == 0)
18696670Stariq 				break;
18706670Stariq 		}
18716670Stariq 
18726670Stariq 		if (xdt_probe[i].pr_mod == NULL)
18736670Stariq 			return;
18746670Stariq 		xdt_probe_create(&xdt_probe[i]);
18756670Stariq 	}
18766670Stariq 
18776670Stariq }
18786670Stariq 
18796670Stariq /*ARGSUSED*/
18806670Stariq static void
xdt_destroy(void * arg,dtrace_id_t id,void * parg)18816670Stariq xdt_destroy(void *arg, dtrace_id_t id, void *parg)
18826670Stariq {
18836670Stariq 	xdt_probe_t *p = parg;
18846670Stariq 	xdt_prid[p->evt_id] = 0;
18856670Stariq }
18866670Stariq 
18876670Stariq static void
xdt_set_trace_mask(uint32_t mask)18886670Stariq xdt_set_trace_mask(uint32_t mask)
18896670Stariq {
18906670Stariq 	xen_sysctl_tbuf_op_t tbuf_op;
18916670Stariq 
1892*11153SFrank.Vanderlinden@Sun.COM 	/* Always need to trace scheduling, for context */
1893*11153SFrank.Vanderlinden@Sun.COM 	if (mask != 0)
1894*11153SFrank.Vanderlinden@Sun.COM 		mask |= TRC_SCHED;
1895*11153SFrank.Vanderlinden@Sun.COM 	tbuf_op.evt_mask = mask;
18966670Stariq 	tbuf_op.cmd  = XEN_SYSCTL_TBUFOP_set_evt_mask;
18976670Stariq 	(void) xdt_sysctl_tbuf(&tbuf_op);
18986670Stariq }
18996670Stariq 
19006670Stariq /*ARGSUSED*/
19018803SJonathan.Haslam@Sun.COM static int
xdt_enable(void * arg,dtrace_id_t id,void * parg)19026670Stariq xdt_enable(void *arg, dtrace_id_t id, void *parg)
19036670Stariq {
19046670Stariq 	xdt_probe_t *p = parg;
19056670Stariq 	xen_sysctl_tbuf_op_t tbuf_op;
19066670Stariq 
19076670Stariq 	ASSERT(MUTEX_HELD(&cpu_lock));
19086670Stariq 	ASSERT(xdt_prid[p->evt_id] != 0);
19096670Stariq 
19106670Stariq 	xdt_probemap[p->evt_id] = xdt_prid[p->evt_id];
19116670Stariq 	xdt_classinfo[p->class].cnt++;
19126670Stariq 
19136670Stariq 	if (xdt_classinfo[p->class].cnt == 1) {
19146670Stariq 		/* set the trace mask for this class */
19156670Stariq 		cur_trace_mask |= xdt_classinfo[p->class].trc_mask;
19166670Stariq 		xdt_set_trace_mask(cur_trace_mask);
19176670Stariq 	}
19186670Stariq 
19196670Stariq 	if (xdt_cyclic == CYCLIC_NONE) {
19206670Stariq 		tbuf_op.cmd = XEN_SYSCTL_TBUFOP_enable;
19216670Stariq 		if (xdt_sysctl_tbuf(&tbuf_op) != 0) {
19226670Stariq 			cmn_err(CE_NOTE, "Couldn't enable hypervisor tracing.");
19238803SJonathan.Haslam@Sun.COM 			return (-1);
19246670Stariq 		}
19256670Stariq 
19266670Stariq 		xdt_cyclic_enable();
19276670Stariq 	}
19288803SJonathan.Haslam@Sun.COM 	return (0);
19296670Stariq }
19306670Stariq 
19316670Stariq /*ARGSUSED*/
19326670Stariq static void
xdt_disable(void * arg,dtrace_id_t id,void * parg)19336670Stariq xdt_disable(void *arg, dtrace_id_t id, void *parg)
19346670Stariq {
19356670Stariq 	xdt_probe_t *p = parg;
19366670Stariq 	xen_sysctl_tbuf_op_t tbuf_op;
19376670Stariq 	int i, err;
19386670Stariq 
19396670Stariq 	ASSERT(MUTEX_HELD(&cpu_lock));
19406670Stariq 	ASSERT(xdt_probemap[p->evt_id] != 0);
19416670Stariq 	ASSERT(xdt_probemap[p->evt_id] == xdt_prid[p->evt_id]);
19426670Stariq 	ASSERT(xdt_classinfo[p->class].cnt > 0);
19436670Stariq 
19446670Stariq 	/*
19456670Stariq 	 * We could be here in the slight window between the cyclic firing and
19466670Stariq 	 * a call to dtrace_probe() occurring. We need to be careful if we tear
19476670Stariq 	 * down any shared state.
19486670Stariq 	 */
19496670Stariq 
19506670Stariq 	xdt_probemap[p->evt_id] = 0;
19516670Stariq 	xdt_classinfo[p->class].cnt--;
19526670Stariq 
19536670Stariq 	if (xdt_nr_active_probes() == 0) {
19546670Stariq 		cur_trace_mask = 0;
19556670Stariq 
19566670Stariq 		if (xdt_cyclic == CYCLIC_NONE)
19576670Stariq 			return;
19586670Stariq 
1959*11153SFrank.Vanderlinden@Sun.COM 		for (i = 0; i < xdt_ncpus; i++)
1960*11153SFrank.Vanderlinden@Sun.COM 			xdt_cpu_schedinfo[i].curinfo_valid = 0;
1961*11153SFrank.Vanderlinden@Sun.COM 
19626670Stariq 		/*
19636670Stariq 		 * We will try to disable the trace buffers. If we fail for some
19646670Stariq 		 * reason we will try again, up to a count of XDT_TBUF_RETRY.
19656670Stariq 		 * If we still aren't successful we try to set the trace mask
19666670Stariq 		 * to 0 in order to prevent trace records from being written.
19676670Stariq 		 */
19686670Stariq 		tbuf_op.cmd = XEN_SYSCTL_TBUFOP_disable;
19696670Stariq 		i = 0;
19706670Stariq 		do {
19716670Stariq 			err = xdt_sysctl_tbuf(&tbuf_op);
19726670Stariq 		} while ((err != 0) && (++i < XDT_TBUF_RETRY));
19736670Stariq 
19746670Stariq 		if (err != 0) {
19756670Stariq 			cmn_err(CE_NOTE,
19766670Stariq 			    "Couldn't disable hypervisor tracing.");
19776670Stariq 			xdt_set_trace_mask(0);
19786670Stariq 		} else {
19796670Stariq 			cyclic_remove(xdt_cyclic);
19806670Stariq 			xdt_cyclic = CYCLIC_NONE;
19816670Stariq 			/*
19826670Stariq 			 * We don't bother making the hypercall to set
19836670Stariq 			 * the trace mask, since it will be reset when
19846670Stariq 			 * tracing is re-enabled.
19856670Stariq 			 */
19866670Stariq 		}
19876670Stariq 	} else if (xdt_classinfo[p->class].cnt == 0) {
19886670Stariq 		cur_trace_mask ^= xdt_classinfo[p->class].trc_mask;
19896670Stariq 		/* other probes are enabled, so add the sub-class mask back */
19906670Stariq 		cur_trace_mask |= 0xF000;
19916670Stariq 		xdt_set_trace_mask(cur_trace_mask);
19926670Stariq 	}
19936670Stariq }
19946670Stariq 
19956670Stariq static dtrace_pattr_t xdt_attr = {
19966670Stariq { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM },
19976670Stariq { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM },
19986670Stariq { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
19996670Stariq { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM },
20006670Stariq { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM },
20016670Stariq };
20026670Stariq 
20036670Stariq static dtrace_pops_t xdt_pops = {
20046670Stariq 	xdt_provide,		/* dtps_provide() */
20056670Stariq 	NULL,			/* dtps_provide_module() */
20066670Stariq 	xdt_enable,		/* dtps_enable() */
20076670Stariq 	xdt_disable,		/* dtps_disable() */
20086670Stariq 	NULL,			/* dtps_suspend() */
20096670Stariq 	NULL,			/* dtps_resume() */
20106670Stariq 	NULL,			/* dtps_getargdesc() */
20116670Stariq 	NULL,			/* dtps_getargval() */
20126670Stariq 	NULL,			/* dtps_usermode() */
20136670Stariq 	xdt_destroy		/* dtps_destroy() */
20146670Stariq };
20156670Stariq 
20166670Stariq static int
xdt_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)20176670Stariq xdt_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
20186670Stariq {
20196670Stariq 	int val;
20206670Stariq 
20216670Stariq 	if (!DOMAIN_IS_INITDOMAIN(xen_info))
20226670Stariq 		return (DDI_FAILURE);
20236670Stariq 
20246670Stariq 	switch (cmd) {
20256670Stariq 	case DDI_ATTACH:
20266670Stariq 		break;
20276670Stariq 
20286670Stariq 	case DDI_RESUME:
20296670Stariq 		/*
20306670Stariq 		 * We might support proper suspend/resume in the future, so,
20316670Stariq 		 * return DDI_FAILURE for now.
20326670Stariq 		 */
20336670Stariq 		return (DDI_FAILURE);
20346670Stariq 
20356670Stariq 	default:
20366670Stariq 		return (DDI_FAILURE);
20376670Stariq 	}
20386670Stariq 
203910175SStuart.Maybee@Sun.COM 	xdt_ncpus = xpv_nr_phys_cpus();
20406670Stariq 	ASSERT(xdt_ncpus > 0);
20416670Stariq 
20426670Stariq 	if (ddi_create_minor_node(devi, "xdt", S_IFCHR, 0, DDI_PSEUDO, 0) ==
20436670Stariq 	    DDI_FAILURE || xdt_attach_trace_buffers() != 0 ||
20446670Stariq 	    dtrace_register("xdt", &xdt_attr, DTRACE_PRIV_KERNEL, NULL,
20456670Stariq 	    &xdt_pops, NULL, &xdt_id) != 0) {
20466670Stariq 		if (tbuf.va != NULL)
20476670Stariq 			xdt_detach_trace_buffers();
20486670Stariq 		ddi_remove_minor_node(devi, NULL);
20496670Stariq 		return (DDI_FAILURE);
20506670Stariq 	}
20516670Stariq 
20526670Stariq 	val = ddi_getprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
20536670Stariq 	    "xdt_poll_nsec", XDT_POLL_DEFAULT);
20546670Stariq 	xdt_poll_nsec = MAX(val, XDT_POLL_MIN);
20556670Stariq 
2056*11153SFrank.Vanderlinden@Sun.COM 	xdt_cpu_schedinfo = (xdt_schedinfo_t *)kmem_zalloc(xdt_ncpus *
20576670Stariq 	    sizeof (xdt_schedinfo_t), KM_SLEEP);
20586670Stariq 	xdt_init_trace_masks();
20596670Stariq 	xdt_kstat_init();
20606670Stariq 
20616670Stariq 	xdt_devi = devi;
20626670Stariq 	ddi_report_dev(devi);
20636670Stariq 	return (DDI_SUCCESS);
20646670Stariq }
20656670Stariq 
20666670Stariq static int
xdt_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)20676670Stariq xdt_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
20686670Stariq {
20696670Stariq 	switch (cmd) {
20706670Stariq 	case DDI_DETACH:
20716670Stariq 		break;
20726670Stariq 
20736670Stariq 	case DDI_SUSPEND:
20746670Stariq 		/*
20756670Stariq 		 * We might support proper suspend/resume in the future. So
20766670Stariq 		 * return DDI_FAILURE for now.
20776670Stariq 		 */
20786670Stariq 		return (DDI_FAILURE);
20796670Stariq 
20806670Stariq 	default:
20816670Stariq 		return (DDI_FAILURE);
20826670Stariq 	}
20836670Stariq 
20846670Stariq 	if (dtrace_unregister(xdt_id) != 0)
20856670Stariq 		return (DDI_FAILURE);
20866670Stariq 
20876670Stariq 	xdt_detach_trace_buffers();
20886670Stariq 	kmem_free(xdt_cpu_schedinfo, xdt_ncpus * sizeof (xdt_schedinfo_t));
20896670Stariq 	if (xdt_cyclic != CYCLIC_NONE)
20906670Stariq 		cyclic_remove(xdt_cyclic);
20916670Stariq 	if (xdt_kstats != NULL)
20926670Stariq 		kstat_delete(xdt_kstats);
20936670Stariq 	xdt_devi = (void *)0;
20946670Stariq 	ddi_remove_minor_node(devi, NULL);
20956670Stariq 
20966670Stariq 	return (DDI_SUCCESS);
20976670Stariq }
20986670Stariq 
20996670Stariq /*ARGSUSED*/
21006670Stariq static int
xdt_info(dev_info_t * devi,ddi_info_cmd_t infocmd,void * arg,void ** result)21016670Stariq xdt_info(dev_info_t *devi, ddi_info_cmd_t infocmd, void *arg, void **result)
21026670Stariq {
21036670Stariq 	int error;
21046670Stariq 
21056670Stariq 	switch (infocmd) {
21066670Stariq 	case DDI_INFO_DEVT2DEVINFO:
21076670Stariq 		*result = xdt_devi;
21086670Stariq 		error = DDI_SUCCESS;
21096670Stariq 		break;
21106670Stariq 	case DDI_INFO_DEVT2INSTANCE:
21116670Stariq 		*result = (void *)0;
21126670Stariq 		error = DDI_SUCCESS;
21136670Stariq 		break;
21146670Stariq 	default:
21156670Stariq 		error = DDI_FAILURE;
21166670Stariq 	}
21176670Stariq 	return (error);
21186670Stariq }
21196670Stariq 
21206670Stariq static struct cb_ops xdt_cb_ops = {
21216670Stariq 	nulldev,		/* open(9E) */
21226670Stariq 	nodev,			/* close(9E) */
21236670Stariq 	nodev,			/* strategy(9E) */
21246670Stariq 	nodev,			/* print(9E) */
21256670Stariq 	nodev,			/* dump(9E) */
21266670Stariq 	nodev,			/* read(9E) */
21276670Stariq 	nodev,			/* write(9E) */
21286670Stariq 	nodev,			/* ioctl(9E) */
21296670Stariq 	nodev,			/* devmap(9E) */
21306670Stariq 	nodev,			/* mmap(9E) */
21316670Stariq 	nodev,			/* segmap(9E) */
21326670Stariq 	nochpoll,		/* chpoll(9E) */
21336670Stariq 	ddi_prop_op,		/* prop_op(9E) */
21346670Stariq 	NULL,			/* streamtab(9S) */
21356670Stariq 	D_MP | D_64BIT | D_NEW	/* cb_flag */
21366670Stariq };
21376670Stariq 
21386670Stariq static struct dev_ops xdt_ops = {
21396670Stariq 	DEVO_REV,		/* devo_rev */
21406670Stariq 	0,			/* devo_refcnt */
21416670Stariq 	xdt_info,		/* getinfo(9E) */
21426670Stariq 	nulldev,		/* identify(9E) */
21436670Stariq 	nulldev,		/* probe(9E) */
21446670Stariq 	xdt_attach,		/* attach(9E) */
21456670Stariq 	xdt_detach,		/* detach(9E) */
21466670Stariq 	nulldev,		/* devo_reset */
21476670Stariq 	&xdt_cb_ops,		/* devo_cb_ops */
21486670Stariq 	NULL,			/* devo_bus_ops */
21497656SSherry.Moore@Sun.COM 	NULL,			/* power(9E) */
215010175SStuart.Maybee@Sun.COM 	ddi_quiesce_not_needed,	/* devo_quiesce */
21516670Stariq };
21526670Stariq 
21536670Stariq 
21546670Stariq static struct modldrv modldrv = {
21556670Stariq 	&mod_driverops,
21566670Stariq 	"Hypervisor event tracing",
21576670Stariq 	&xdt_ops
21586670Stariq };
21596670Stariq 
21606670Stariq static struct modlinkage modlinkage = {
21616670Stariq 	MODREV_1,
21626670Stariq 	&modldrv,
21636670Stariq 	NULL
21646670Stariq };
21656670Stariq 
21666670Stariq int
_init(void)21676670Stariq _init(void)
21686670Stariq {
21696670Stariq 	return (mod_install(&modlinkage));
21706670Stariq }
21716670Stariq 
21726670Stariq int
_fini(void)21736670Stariq _fini(void)
21746670Stariq {
21756670Stariq 	return (mod_remove(&modlinkage));
21766670Stariq }
21776670Stariq 
21786670Stariq int
_info(struct modinfo * modinfop)21796670Stariq _info(struct modinfo *modinfop)
21806670Stariq {
21816670Stariq 	return (mod_info(&modlinkage, modinfop));
21826670Stariq }
2183