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