1c7158ae9Stariq /* 2c7158ae9Stariq * CDDL HEADER START 3c7158ae9Stariq * 4c7158ae9Stariq * The contents of this file are subject to the terms of the 5c7158ae9Stariq * Common Development and Distribution License (the "License"). 6c7158ae9Stariq * You may not use this file except in compliance with the License. 7c7158ae9Stariq * 8c7158ae9Stariq * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9c7158ae9Stariq * or http://www.opensolaris.org/os/licensing. 10c7158ae9Stariq * See the License for the specific language governing permissions 11c7158ae9Stariq * and limitations under the License. 12c7158ae9Stariq * 13c7158ae9Stariq * When distributing Covered Code, include this CDDL HEADER in each 14c7158ae9Stariq * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15c7158ae9Stariq * If applicable, add the following below this CDDL HEADER, with the 16c7158ae9Stariq * fields enclosed by brackets "[]" replaced with your own identifying 17c7158ae9Stariq * information: Portions Copyright [yyyy] [name of copyright owner] 18c7158ae9Stariq * 19c7158ae9Stariq * CDDL HEADER END 20c7158ae9Stariq */ 21c7158ae9Stariq 22c7158ae9Stariq /* 23b9e93c10SJonathan Haslam * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24c7158ae9Stariq * Use is subject to license terms. 25c7158ae9Stariq */ 26c7158ae9Stariq 27c7158ae9Stariq /* 28c7158ae9Stariq * Xen event provider for DTrace 29c7158ae9Stariq * 30c7158ae9Stariq * NOTE: This provider is PRIVATE. It is intended as a short-term solution and 31c7158ae9Stariq * may disappear or be re-implemented at anytime. 32c7158ae9Stariq * 33c7158ae9Stariq * This provider isn't suitable as a general-purpose solution for a number of 34c7158ae9Stariq * reasons. First and foremost, we rely on the Xen tracing mechanism and don't 35c7158ae9Stariq * have any way to gather data other than that collected by the Xen trace 36c7158ae9Stariq * buffers. Further, it does not fit into the DTrace model (see "Interacting 37c7158ae9Stariq * with DTrace" below.) 38c7158ae9Stariq * 39c7158ae9Stariq * 40c7158ae9Stariq * Tracing in Xen 41c7158ae9Stariq * -------------- 42c7158ae9Stariq * 43c7158ae9Stariq * Xen implements a tracing facility for generating and collecting execution 44c7158ae9Stariq * event traces from the hypervisor. When tracing is enabled, compiled in 45c7158ae9Stariq * probes record events in contiguous per-CPU trace buffers. 46c7158ae9Stariq * 47c7158ae9Stariq * +---------+ 48c7158ae9Stariq * +------+ | | 49c7158ae9Stariq * | CPUn |----> | BUFFERn | 50c7158ae9Stariq * +------+ | | 51c7158ae9Stariq * +---------+- tbuf.va + (tbuf.size * n) 52c7158ae9Stariq * : : 53c7158ae9Stariq * +---------+ 54c7158ae9Stariq * +------+ | | 55c7158ae9Stariq * | CPU1 |----> | BUFFER1 | 56c7158ae9Stariq * +------+ | | 57c7158ae9Stariq * +---------+- tbuf.va + tbuf.size 58c7158ae9Stariq * +------+ | | 59c7158ae9Stariq * | CPU0 |----> | BUFFER0 | 60c7158ae9Stariq * +------+ | | 61c7158ae9Stariq * +---------+- tbuf.va 62c7158ae9Stariq * 63c7158ae9Stariq * Each CPU buffer consists of a metadata header followed by the trace records. 64c7158ae9Stariq * The metadata consists of a producer/consumer pair of pointers into the buffer 65c7158ae9Stariq * that point to the next record to be written and the next record to be read 66349b53ddSStuart Maybee * respectively. 67c7158ae9Stariq * 68349b53ddSStuart Maybee * A trace record can be in one of two forms, depending on if the TSC is 69349b53ddSStuart Maybee * included. The record header indicates whether or not the TSC field is 70349b53ddSStuart Maybee * present. 71349b53ddSStuart Maybee * 72349b53ddSStuart Maybee * 1. Trace record without TSC: 73349b53ddSStuart Maybee * +------------------------------------------------------------+ 74349b53ddSStuart Maybee * | HEADER(uint32_t) | DATA FIELDS | 75349b53ddSStuart Maybee * +------------------------------------------------------------+ 76349b53ddSStuart Maybee * 77349b53ddSStuart Maybee * 2. Trace record with TSC: 78c7158ae9Stariq * +--------------------------------------------------------------------------+ 79349b53ddSStuart Maybee * | HEADER(uint32_t) | TSC(uint64_t) | DATA FIELDS | 80c7158ae9Stariq * +--------------------------------------------------------------------------+ 81c7158ae9Stariq * 82349b53ddSStuart Maybee * Where, 83349b53ddSStuart Maybee * 84349b53ddSStuart Maybee * HEADER bit field: 85349b53ddSStuart Maybee * +--------------------------------------------------------------------------+ 86349b53ddSStuart Maybee * | C | NDATA | EVENT | 87349b53ddSStuart Maybee * +--------------------------------------------------------------------------+ 88349b53ddSStuart Maybee * 31 30 28 27 0 89349b53ddSStuart Maybee * 90349b53ddSStuart Maybee * EVENT: Event ID. 91349b53ddSStuart Maybee * NDATA: Number of populated data fields. 92349b53ddSStuart Maybee * C: TSC included. 93349b53ddSStuart Maybee * 94c7158ae9Stariq * DATA FIELDS: 95c7158ae9Stariq * +--------------------------------------------------------------------------+ 96349b53ddSStuart Maybee * | D1(uint32_t) | D2(uint32_t) | D3(uint32_t) | . . . | D7(uint32_t) | 97c7158ae9Stariq * +--------------------------------------------------------------------------+ 98c7158ae9Stariq * 99c7158ae9Stariq * 100c7158ae9Stariq * Interacting with DTrace 101c7158ae9Stariq * ----------------------- 102c7158ae9Stariq * 103c7158ae9Stariq * Every xdt_poll_nsec nano-seconds we poll the trace buffers for data and feed 104c7158ae9Stariq * each entry into dtrace_probe() with the corresponding probe ID for the event. 105c7158ae9Stariq * As a result of this periodic collection implementation probe firings are 106c7158ae9Stariq * asynchronous. This is the only sensible way to implement this form of 107c7158ae9Stariq * provider, but because of its asynchronous nature asking things like 108c7158ae9Stariq * "current CPU" and, more importantly, arbitrary questions about the context 109c7158ae9Stariq * surrounding the probe firing are not meaningful. So, consumers should not 110c7158ae9Stariq * attempt to infer anything beyond what is supplied via the probe arguments. 111c7158ae9Stariq */ 112c7158ae9Stariq 113349b53ddSStuart Maybee #include <sys/xpv_user.h> 114349b53ddSStuart Maybee 115c7158ae9Stariq #include <sys/types.h> 116c7158ae9Stariq #include <sys/sysmacros.h> 117c7158ae9Stariq #include <sys/modctl.h> 118c7158ae9Stariq #include <sys/sunddi.h> 119c7158ae9Stariq #include <sys/ddi.h> 120c7158ae9Stariq #include <sys/conf.h> 121c7158ae9Stariq #include <sys/devops.h> 122c7158ae9Stariq #include <sys/stat.h> 123c7158ae9Stariq #include <sys/cmn_err.h> 124c7158ae9Stariq #include <sys/dtrace.h> 125c7158ae9Stariq #include <sys/sdt.h> 126c7158ae9Stariq #include <sys/cyclic.h> 127c7158ae9Stariq #include <vm/seg_kmem.h> 128c7158ae9Stariq #include <vm/hat_i86.h> 129349b53ddSStuart Maybee 130c7158ae9Stariq #include <sys/hypervisor.h> 131c7158ae9Stariq #include <xen/public/trace.h> 132c7158ae9Stariq #include <xen/public/sched.h> 133c7158ae9Stariq 134c7158ae9Stariq #define XDT_POLL_DEFAULT 100000000 /* default poll interval (ns) */ 135c7158ae9Stariq #define XDT_POLL_MIN 10000000 /* min poll interval (ns) */ 136c7158ae9Stariq #define XDT_TBUF_RETRY 50 /* tbuf disable retry count */ 137c7158ae9Stariq 138c7158ae9Stariq /* 139c7158ae9Stariq * The domid must match IDLE_DOMAIN_ID in xen.hg/xen/include/xen/sched.h 140c7158ae9Stariq * in the xVM gate. 141c7158ae9Stariq */ 142c7158ae9Stariq #define IS_IDLE_DOM(domid) (domid == 0x7FFFU) 143c7158ae9Stariq 144c7158ae9Stariq /* Macros to extract the domid and cpuid from a HVM trace data field */ 145c7158ae9Stariq #define HVM_DOMID(d) (d >> 16) 146c7158ae9Stariq #define HVM_VCPUID(d) (d & 0xFFFF) 147c7158ae9Stariq 148*55f5292cSFrank Van Der Linden /* Flags for shadow page table events */ 149*55f5292cSFrank Van Der Linden #define SH_GUEST_32 0x000 150*55f5292cSFrank Van Der Linden #define SH_GUEST_PAE 0x100 151*55f5292cSFrank Van Der Linden #define SH_GUEST_64 0x200 152*55f5292cSFrank Van Der Linden 153*55f5292cSFrank Van Der Linden #define XDT_PROBE5(event, arg0, arg1, arg2, arg3, arg4) { \ 154c7158ae9Stariq dtrace_id_t id = xdt_probemap[event]; \ 155c7158ae9Stariq if (id) \ 156*55f5292cSFrank Van Der Linden dtrace_probe(id, arg0, arg1, arg2, arg3, arg4); \ 157c7158ae9Stariq } \ 158c7158ae9Stariq 159*55f5292cSFrank Van Der Linden #define XDT_PROBE4(event, arg0, arg1, arg2, arg3) \ 160*55f5292cSFrank Van Der Linden XDT_PROBE5(event, arg0, arg1, arg2, arg3, 0) 161c7158ae9Stariq 162*55f5292cSFrank Van Der Linden #define XDT_PROBE3(event, arg0, arg1, arg2) \ 163*55f5292cSFrank Van Der Linden XDT_PROBE5(event, arg0, arg1, arg2, 0, 0) 164c7158ae9Stariq 165*55f5292cSFrank Van Der Linden #define XDT_PROBE2(event, arg0, arg1) \ 166*55f5292cSFrank Van Der Linden XDT_PROBE5(event, arg0, arg1, 0, 0, 0) 167c7158ae9Stariq 168*55f5292cSFrank Van Der Linden #define XDT_PROBE1(event, arg0) \ 169*55f5292cSFrank Van Der Linden XDT_PROBE5(event, arg0, 0, 0, 0, 0) 170*55f5292cSFrank Van Der Linden 171*55f5292cSFrank Van Der Linden #define XDT_PROBE0(event) \ 172*55f5292cSFrank Van Der Linden XDT_PROBE5(event, 0, 0, 0, 0, 0) 173c7158ae9Stariq 174c7158ae9Stariq /* Probe classes */ 175c7158ae9Stariq #define XDT_SCHED 0 176c7158ae9Stariq #define XDT_MEM 1 177c7158ae9Stariq #define XDT_HVM 2 178349b53ddSStuart Maybee #define XDT_GEN 3 179*55f5292cSFrank Van Der Linden #define XDT_PV 4 180*55f5292cSFrank Van Der Linden #define XDT_SHADOW 5 181*55f5292cSFrank Van Der Linden #define XDT_PM 6 182*55f5292cSFrank Van Der Linden #define XDT_NCLASSES 7 183c7158ae9Stariq 184c7158ae9Stariq /* Probe events */ 185c7158ae9Stariq #define XDT_EVT_INVALID (-(int)1) 186c7158ae9Stariq #define XDT_SCHED_OFF_CPU 0 187c7158ae9Stariq #define XDT_SCHED_ON_CPU 1 188c7158ae9Stariq #define XDT_SCHED_IDLE_OFF_CPU 2 189c7158ae9Stariq #define XDT_SCHED_IDLE_ON_CPU 3 190c7158ae9Stariq #define XDT_SCHED_BLOCK 4 191c7158ae9Stariq #define XDT_SCHED_SLEEP 5 192c7158ae9Stariq #define XDT_SCHED_WAKE 6 193c7158ae9Stariq #define XDT_SCHED_YIELD 7 194c7158ae9Stariq #define XDT_SCHED_SHUTDOWN_POWEROFF 8 195c7158ae9Stariq #define XDT_SCHED_SHUTDOWN_REBOOT 9 196c7158ae9Stariq #define XDT_SCHED_SHUTDOWN_SUSPEND 10 197c7158ae9Stariq #define XDT_SCHED_SHUTDOWN_CRASH 11 198c7158ae9Stariq #define XDT_MEM_PAGE_GRANT_MAP 12 199c7158ae9Stariq #define XDT_MEM_PAGE_GRANT_UNMAP 13 200c7158ae9Stariq #define XDT_MEM_PAGE_GRANT_TRANSFER 14 201c7158ae9Stariq #define XDT_HVM_VMENTRY 15 202c7158ae9Stariq #define XDT_HVM_VMEXIT 16 203349b53ddSStuart Maybee #define XDT_TRC_LOST_RECORDS 17 204*55f5292cSFrank Van Der Linden #define XDT_SCHED_ADD_VCPU 18 205*55f5292cSFrank Van Der Linden #define XDT_SCHED_REM_VCPU 19 /* unused */ 206*55f5292cSFrank Van Der Linden #define XDT_SCHED_CTL 20 /* unused */ 207*55f5292cSFrank Van Der Linden #define XDT_SCHED_ADJDOM 21 208*55f5292cSFrank Van Der Linden #define XDT_SCHED_S_TIMER_FN 22 /* unused */ 209*55f5292cSFrank Van Der Linden #define XDT_SCHED_T_TIMER_FN 23 /* unused */ 210*55f5292cSFrank Van Der Linden #define XDT_SCHED_DOM_TIMER_FN 24 /* unused */ 211*55f5292cSFrank Van Der Linden #define XDT_PV_HYPERCALL 25 212*55f5292cSFrank Van Der Linden #define XDT_PV_TRAP 26 213*55f5292cSFrank Van Der Linden #define XDT_PV_PAGE_FAULT 27 214*55f5292cSFrank Van Der Linden #define XDT_PV_FORCED_INVALID_OP 28 215*55f5292cSFrank Van Der Linden #define XDT_PV_EMULATE_PRIVOP 29 216*55f5292cSFrank Van Der Linden #define XDT_PV_EMULATE_4GB 30 /* unused (32-bit HV only ) */ 217*55f5292cSFrank Van Der Linden #define XDT_PV_MATH_STATE_RESTORE 31 218*55f5292cSFrank Van Der Linden #define XDT_PV_PAGING_FIXUP 32 219*55f5292cSFrank Van Der Linden #define XDT_PV_DT_MAPPING_FAULT 33 220*55f5292cSFrank Van Der Linden #define XDT_PV_PTWR_EMULATION 34 221*55f5292cSFrank Van Der Linden #define XDT_HVM_PF_XEN 35 222*55f5292cSFrank Van Der Linden #define XDT_HVM_PF_INJECT 36 223*55f5292cSFrank Van Der Linden #define XDT_HVM_EXC_INJECT 37 224*55f5292cSFrank Van Der Linden #define XDT_HVM_VIRQ_INJECT 38 225*55f5292cSFrank Van Der Linden #define XDT_HVM_VIRQ_REINJECT 39 226*55f5292cSFrank Van Der Linden #define XDT_HVM_IO_READ 40 /* unused */ 227*55f5292cSFrank Van Der Linden #define XDT_HVM_IO_WRITE 41 /* unused */ 228*55f5292cSFrank Van Der Linden #define XDT_HVM_CR_READ 42 229*55f5292cSFrank Van Der Linden #define XDT_HVM_CR_WRITE 43 230*55f5292cSFrank Van Der Linden #define XDT_HVM_DR_READ 44 /* unused */ 231*55f5292cSFrank Van Der Linden #define XDT_HVM_DR_WRITE 45 /* unused */ 232*55f5292cSFrank Van Der Linden #define XDT_HVM_MSR_READ 46 233*55f5292cSFrank Van Der Linden #define XDT_HVM_MSR_WRITE 47 234*55f5292cSFrank Van Der Linden #define XDT_HVM_CPUID 48 235*55f5292cSFrank Van Der Linden #define XDT_HVM_INTR 49 236*55f5292cSFrank Van Der Linden #define XDT_HVM_INTR_WINDOW 50 237*55f5292cSFrank Van Der Linden #define XDT_HVM_NMI 51 238*55f5292cSFrank Van Der Linden #define XDT_HVM_SMI 52 239*55f5292cSFrank Van Der Linden #define XDT_HVM_VMMCALL 53 240*55f5292cSFrank Van Der Linden #define XDT_HVM_HLT 54 241*55f5292cSFrank Van Der Linden #define XDT_HVM_INVLPG 55 242*55f5292cSFrank Van Der Linden #define XDT_HVM_MCE 56 243*55f5292cSFrank Van Der Linden #define XDT_HVM_IOPORT_READ 57 244*55f5292cSFrank Van Der Linden #define XDT_HVM_IOPORT_WRITE 58 245*55f5292cSFrank Van Der Linden #define XDT_HVM_CLTS 59 246*55f5292cSFrank Van Der Linden #define XDT_HVM_LMSW 60 247*55f5292cSFrank Van Der Linden #define XDT_HVM_IOMEM_READ 61 248*55f5292cSFrank Van Der Linden #define XDT_HVM_IOMEM_WRITE 62 249*55f5292cSFrank Van Der Linden #define XDT_SHADOW_NOT_SHADOW 63 250*55f5292cSFrank Van Der Linden #define XDT_SHADOW_FAST_PROPAGATE 64 251*55f5292cSFrank Van Der Linden #define XDT_SHADOW_FAST_MMIO 65 252*55f5292cSFrank Van Der Linden #define XDT_SHADOW_FALSE_FAST_PATH 66 253*55f5292cSFrank Van Der Linden #define XDT_SHADOW_MMIO 67 254*55f5292cSFrank Van Der Linden #define XDT_SHADOW_FIXUP 68 255*55f5292cSFrank Van Der Linden #define XDT_SHADOW_DOMF_DYING 69 256*55f5292cSFrank Van Der Linden #define XDT_SHADOW_EMULATE 70 257*55f5292cSFrank Van Der Linden #define XDT_SHADOW_EMULATE_UNSHADOW_USER 71 258*55f5292cSFrank Van Der Linden #define XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ 72 259*55f5292cSFrank Van Der Linden #define XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED 73 260*55f5292cSFrank Van Der Linden #define XDT_SHADOW_WRMAP_BF 74 261*55f5292cSFrank Van Der Linden #define XDT_SHADOW_PREALLOC_UNPIN 75 262*55f5292cSFrank Van Der Linden #define XDT_SHADOW_RESYNC_FULL 76 263*55f5292cSFrank Van Der Linden #define XDT_SHADOW_RESYNC_ONLY 77 264*55f5292cSFrank Van Der Linden #define XDT_PM_FREQ_CHANGE 78 265*55f5292cSFrank Van Der Linden #define XDT_PM_IDLE_ENTRY 79 266*55f5292cSFrank Van Der Linden #define XDT_PM_IDLE_EXIT 80 267*55f5292cSFrank Van Der Linden #define XDT_SCHED_RUNSTATE_CHANGE 81 268*55f5292cSFrank Van Der Linden #define XDT_SCHED_CONTINUE_RUNNING 82 269*55f5292cSFrank Van Der Linden #define XDT_NEVENTS 83 270c7158ae9Stariq 271c7158ae9Stariq typedef struct { 272c7158ae9Stariq const char *pr_mod; /* probe module */ 273c7158ae9Stariq const char *pr_name; /* probe name */ 274c7158ae9Stariq int evt_id; /* event id */ 275c7158ae9Stariq uint_t class; /* probe class */ 276c7158ae9Stariq } xdt_probe_t; 277c7158ae9Stariq 278c7158ae9Stariq typedef struct { 279c7158ae9Stariq uint32_t trc_mask; /* trace mask */ 280c7158ae9Stariq uint32_t cnt; /* num enabled probes in class */ 281c7158ae9Stariq } xdt_classinfo_t; 282c7158ae9Stariq 283c7158ae9Stariq typedef struct { 284c7158ae9Stariq ulong_t prev_domid; /* previous dom executed */ 285c7158ae9Stariq ulong_t prev_vcpuid; /* previous vcpu executed */ 286c7158ae9Stariq ulong_t prev_ctime; /* time spent on cpu */ 287c7158ae9Stariq ulong_t next_domid; /* next dom to be scheduled */ 288c7158ae9Stariq ulong_t next_vcpuid; /* next vcpu to be scheduled */ 289c7158ae9Stariq ulong_t next_wtime; /* time spent waiting to get on cpu */ 290c7158ae9Stariq ulong_t next_ts; /* allocated time slice */ 291*55f5292cSFrank Van Der Linden ulong_t cur_domid; /* current dom */ 292*55f5292cSFrank Van Der Linden ulong_t cur_vcpuid; /* current vcpuid */ 293*55f5292cSFrank Van Der Linden int curinfo_valid; /* info is valid */ 294c7158ae9Stariq } xdt_schedinfo_t; 295c7158ae9Stariq 296c7158ae9Stariq static struct { 297c7158ae9Stariq uint_t cnt; /* total num of trace buffers */ 298c7158ae9Stariq size_t size; /* size of each cpu buffer */ 299c7158ae9Stariq mfn_t start_mfn; /* starting mfn of buffers */ 300c7158ae9Stariq caddr_t va; /* va buffers are mapped into */ 301c7158ae9Stariq 302c7158ae9Stariq /* per-cpu buffers */ 303c7158ae9Stariq struct t_buf **meta; /* buffer metadata */ 304c7158ae9Stariq struct t_rec **data; /* buffer data records */ 305c7158ae9Stariq 306c7158ae9Stariq /* statistics */ 307c7158ae9Stariq uint64_t stat_dropped_recs; /* records dropped */ 308c7158ae9Stariq uint64_t stat_spurious_cpu; /* recs with garbage cpuids */ 309c7158ae9Stariq uint64_t stat_spurious_switch; /* inconsistent vcpu switches */ 310c7158ae9Stariq uint64_t stat_unknown_shutdown; /* unknown shutdown code */ 311c7158ae9Stariq uint64_t stat_unknown_recs; /* unknown records */ 312c7158ae9Stariq } tbuf; 313c7158ae9Stariq 314*55f5292cSFrank Van Der Linden static size_t tbuf_data_size; 315*55f5292cSFrank Van Der Linden 316c7158ae9Stariq static char *xdt_stats[] = { 317c7158ae9Stariq "dropped_recs", 318c7158ae9Stariq }; 319c7158ae9Stariq 320c7158ae9Stariq /* 321c7158ae9Stariq * Tunable variables 322c7158ae9Stariq * 323c7158ae9Stariq * The following may be tuned by adding a line to /etc/system that 324c7158ae9Stariq * includes both the name of the module ("xdt") and the name of the variable. 325c7158ae9Stariq * For example: 326c7158ae9Stariq * set xdt:xdt_tbuf_pages = 40 327c7158ae9Stariq */ 328c7158ae9Stariq uint_t xdt_tbuf_pages = 20; /* pages to alloc per-cpu buf */ 329c7158ae9Stariq 330c7158ae9Stariq /* 331c7158ae9Stariq * The following may be tuned by adding a line to 332c7158ae9Stariq * /platform/i86xpv/kernel/drv/xdt.conf. 333c7158ae9Stariq * For example: 334c7158ae9Stariq * xdt_poll_nsec = 200000000; 335c7158ae9Stariq */ 336c7158ae9Stariq static hrtime_t xdt_poll_nsec; /* trace buffer poll interval */ 337c7158ae9Stariq 338c7158ae9Stariq /* 339*55f5292cSFrank Van Der Linden * Another tunable variable: the maximum number of records to process 340*55f5292cSFrank Van Der Linden * in one scan. If it is 0 (e.g. not set in /etc/system), it will 341*55f5292cSFrank Van Der Linden * be set to ncpu * (bufsize / max_rec_size). 342*55f5292cSFrank Van Der Linden * 343*55f5292cSFrank Van Der Linden * Having an upper limit avoids a situation where the scan would loop 344*55f5292cSFrank Van Der Linden * endlessly in case the hypervisor adds records quicker than we 345*55f5292cSFrank Van Der Linden * can process them. It's better to drop records than to loop, obviously. 346*55f5292cSFrank Van Der Linden */ 347*55f5292cSFrank Van Der Linden uint_t xdt_max_recs = 0; 348*55f5292cSFrank Van Der Linden 349*55f5292cSFrank Van Der Linden /* 350c7158ae9Stariq * Internal variables 351c7158ae9Stariq */ 352c7158ae9Stariq static dev_info_t *xdt_devi; 353c7158ae9Stariq static dtrace_provider_id_t xdt_id; 354c7158ae9Stariq static uint_t xdt_ncpus; /* total number of phys CPUs */ 355c7158ae9Stariq static uint32_t cur_trace_mask; /* current trace mask */ 356c7158ae9Stariq static xdt_schedinfo_t *xdt_cpu_schedinfo; /* per-cpu sched info */ 357c7158ae9Stariq dtrace_id_t xdt_probemap[XDT_NEVENTS]; /* map of enabled probes */ 358c7158ae9Stariq dtrace_id_t xdt_prid[XDT_NEVENTS]; /* IDs of registered events */ 359c7158ae9Stariq static cyclic_id_t xdt_cyclic = CYCLIC_NONE; 360c7158ae9Stariq static kstat_t *xdt_kstats; 361c7158ae9Stariq static xdt_classinfo_t xdt_classinfo[XDT_NCLASSES]; 362c7158ae9Stariq 363*55f5292cSFrank Van Der Linden /* 364*55f5292cSFrank Van Der Linden * These provide context when probes fire. They can be accessed 365*55f5292cSFrank Van Der Linden * from xdt dtrace probe (as `xdt_curdom, etc). It's ok for these 366*55f5292cSFrank Van Der Linden * to be global, and not per-cpu, as probes are run strictly in sequence 367*55f5292cSFrank Van Der Linden * as the trace buffers are 368*55f5292cSFrank Van Der Linden */ 369*55f5292cSFrank Van Der Linden uint_t xdt_curdom, xdt_curvcpu, xdt_curpcpu; 370*55f5292cSFrank Van Der Linden uint64_t xdt_timestamp; 371*55f5292cSFrank Van Der Linden 372c7158ae9Stariq static xdt_probe_t xdt_probe[] = { 373c7158ae9Stariq /* Sched probes */ 374c7158ae9Stariq { "sched", "off-cpu", XDT_SCHED_OFF_CPU, XDT_SCHED }, 375c7158ae9Stariq { "sched", "on-cpu", XDT_SCHED_ON_CPU, XDT_SCHED }, 376c7158ae9Stariq { "sched", "idle-off-cpu", XDT_SCHED_IDLE_OFF_CPU, XDT_SCHED }, 377c7158ae9Stariq { "sched", "idle-on-cpu", XDT_SCHED_IDLE_ON_CPU, XDT_SCHED }, 378c7158ae9Stariq { "sched", "block", XDT_SCHED_BLOCK, XDT_SCHED }, 379c7158ae9Stariq { "sched", "sleep", XDT_SCHED_SLEEP, XDT_SCHED }, 380c7158ae9Stariq { "sched", "wake", XDT_SCHED_WAKE, XDT_SCHED }, 381c7158ae9Stariq { "sched", "yield", XDT_SCHED_YIELD, XDT_SCHED }, 382c7158ae9Stariq { "sched", "shutdown-poweroff", XDT_SCHED_SHUTDOWN_POWEROFF, 383c7158ae9Stariq XDT_SCHED }, 384c7158ae9Stariq { "sched", "shutdown-reboot", XDT_SCHED_SHUTDOWN_REBOOT, XDT_SCHED }, 385c7158ae9Stariq { "sched", "shutdown-suspend", XDT_SCHED_SHUTDOWN_SUSPEND, XDT_SCHED }, 386c7158ae9Stariq { "sched", "shutdown-crash", XDT_SCHED_SHUTDOWN_CRASH, XDT_SCHED }, 387*55f5292cSFrank Van Der Linden { "sched", "add", XDT_SCHED_ADD_VCPU, XDT_SCHED }, 388*55f5292cSFrank Van Der Linden { "sched", "runstate-change", XDT_SCHED_RUNSTATE_CHANGE, XDT_SCHED }, 389*55f5292cSFrank Van Der Linden { "sched", "continue-running", XDT_SCHED_CONTINUE_RUNNING, XDT_SCHED }, 390c7158ae9Stariq 391c7158ae9Stariq /* Memory probes */ 392c7158ae9Stariq { "mem", "page-grant-map", XDT_MEM_PAGE_GRANT_MAP, XDT_MEM }, 393c7158ae9Stariq { "mem", "page-grant-unmap", XDT_MEM_PAGE_GRANT_UNMAP, XDT_MEM }, 394c7158ae9Stariq { "mem", "page-grant-transfer", XDT_MEM_PAGE_GRANT_TRANSFER, XDT_MEM }, 395c7158ae9Stariq 396*55f5292cSFrank Van Der Linden {"pv", "hypercall", XDT_PV_HYPERCALL, XDT_PV }, 397*55f5292cSFrank Van Der Linden {"pv", "trap", XDT_PV_TRAP, XDT_PV }, 398*55f5292cSFrank Van Der Linden {"pv", "page-fault", XDT_PV_PAGE_FAULT, XDT_PV }, 399*55f5292cSFrank Van Der Linden {"pv", "forced-invalid-op", XDT_PV_FORCED_INVALID_OP, XDT_PV }, 400*55f5292cSFrank Van Der Linden {"pv", "emulate-priv-op", XDT_PV_EMULATE_PRIVOP, XDT_PV }, 401*55f5292cSFrank Van Der Linden {"pv", "math-state-restore", XDT_PV_MATH_STATE_RESTORE, XDT_PV }, 402*55f5292cSFrank Van Der Linden {"pv", "paging-fixup", XDT_PV_PAGING_FIXUP, XDT_PV }, 403*55f5292cSFrank Van Der Linden {"pv", "dt-mapping-fault", XDT_PV_DT_MAPPING_FAULT, XDT_PV }, 404*55f5292cSFrank Van Der Linden {"pv", "pte-write-emul", XDT_PV_PTWR_EMULATION, XDT_PV }, 405*55f5292cSFrank Van Der Linden 406c7158ae9Stariq /* HVM probes */ 407c7158ae9Stariq { "hvm", "vmentry", XDT_HVM_VMENTRY, XDT_HVM }, 408c7158ae9Stariq { "hvm", "vmexit", XDT_HVM_VMEXIT, XDT_HVM }, 409*55f5292cSFrank Van Der Linden { "hvm", "pagefault-xen", XDT_HVM_PF_XEN, XDT_HVM }, 410*55f5292cSFrank Van Der Linden { "hvm", "pagefault-inject", XDT_HVM_PF_INJECT, XDT_HVM }, 411*55f5292cSFrank Van Der Linden { "hvm", "exception-inject", XDT_HVM_EXC_INJECT, XDT_HVM }, 412*55f5292cSFrank Van Der Linden { "hvm", "virq-inject", XDT_HVM_VIRQ_INJECT, XDT_HVM }, 413*55f5292cSFrank Van Der Linden { "hvm", "cr-read", XDT_HVM_CR_READ, XDT_HVM }, 414*55f5292cSFrank Van Der Linden { "hvm", "cr-write", XDT_HVM_CR_WRITE, XDT_HVM }, 415*55f5292cSFrank Van Der Linden { "hvm", "msr-read", XDT_HVM_MSR_READ, XDT_HVM }, 416*55f5292cSFrank Van Der Linden { "hvm", "msr-write", XDT_HVM_MSR_WRITE, XDT_HVM }, 417*55f5292cSFrank Van Der Linden { "hvm", "cpuid", XDT_HVM_CPUID, XDT_HVM }, 418*55f5292cSFrank Van Der Linden { "hvm", "intr", XDT_HVM_INTR, XDT_HVM }, 419*55f5292cSFrank Van Der Linden { "hvm", "intr-window", XDT_HVM_INTR_WINDOW, XDT_HVM }, 420*55f5292cSFrank Van Der Linden { "hvm", "nmi", XDT_HVM_NMI, XDT_HVM }, 421*55f5292cSFrank Van Der Linden { "hvm", "smi", XDT_HVM_SMI, XDT_HVM }, 422*55f5292cSFrank Van Der Linden { "hvm", "vmmcall", XDT_HVM_VMMCALL, XDT_HVM }, 423*55f5292cSFrank Van Der Linden { "hvm", "hlt", XDT_HVM_HLT, XDT_HVM }, 424*55f5292cSFrank Van Der Linden { "hvm", "invlpg", XDT_HVM_INVLPG, XDT_HVM }, 425*55f5292cSFrank Van Der Linden { "hvm", "mce", XDT_HVM_MCE, XDT_HVM }, 426*55f5292cSFrank Van Der Linden { "hvm", "pio-read", XDT_HVM_IOPORT_READ, XDT_HVM }, 427*55f5292cSFrank Van Der Linden { "hvm", "pio-write", XDT_HVM_IOPORT_WRITE, XDT_HVM }, 428*55f5292cSFrank Van Der Linden { "hvm", "mmio-read", XDT_HVM_IOMEM_READ, XDT_HVM }, 429*55f5292cSFrank Van Der Linden { "hvm", "mmio-write", XDT_HVM_IOMEM_WRITE, XDT_HVM }, 430*55f5292cSFrank Van Der Linden { "hvm", "clts", XDT_HVM_CLTS, XDT_HVM }, 431*55f5292cSFrank Van Der Linden { "hvm", "lmsw", XDT_HVM_LMSW, XDT_HVM }, 432*55f5292cSFrank Van Der Linden 433*55f5292cSFrank Van Der Linden { "shadow", "fault-not-shadow", XDT_SHADOW_NOT_SHADOW, XDT_SHADOW }, 434*55f5292cSFrank Van Der Linden { "shadow", "fast-propagate", XDT_SHADOW_FAST_PROPAGATE, XDT_SHADOW }, 435*55f5292cSFrank Van Der Linden { "shadow", "fast-mmio", XDT_SHADOW_FAST_MMIO, XDT_SHADOW }, 436*55f5292cSFrank Van Der Linden { "shadow", "false-fast-path", XDT_SHADOW_FALSE_FAST_PATH, 437*55f5292cSFrank Van Der Linden XDT_SHADOW }, 438*55f5292cSFrank Van Der Linden { "shadow", "mmio", XDT_SHADOW_MMIO, XDT_SHADOW }, 439*55f5292cSFrank Van Der Linden { "shadow", "fixup", XDT_SHADOW_FIXUP, XDT_SHADOW }, 440*55f5292cSFrank Van Der Linden { "shadow", "domf-dying", XDT_SHADOW_DOMF_DYING, XDT_SHADOW }, 441*55f5292cSFrank Van Der Linden { "shadow", "emulate", XDT_SHADOW_EMULATE, XDT_SHADOW }, 442*55f5292cSFrank Van Der Linden { "shadow", "emulate-unshadow-user", XDT_SHADOW_EMULATE_UNSHADOW_USER, 443*55f5292cSFrank Van Der Linden XDT_SHADOW }, 444*55f5292cSFrank Van Der Linden { "shadow", "emulate-unshadow-evtinj", 445*55f5292cSFrank Van Der Linden XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ, XDT_SHADOW }, 446*55f5292cSFrank Van Der Linden { "shadow", "emulate-unshadow-unhandled", 447*55f5292cSFrank Van Der Linden XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED, XDT_SHADOW }, 448*55f5292cSFrank Van Der Linden { "shadow", "wrmap-bf", XDT_SHADOW_WRMAP_BF, XDT_SHADOW }, 449*55f5292cSFrank Van Der Linden { "shadow", "prealloc-unpin", XDT_SHADOW_PREALLOC_UNPIN, XDT_SHADOW }, 450*55f5292cSFrank Van Der Linden { "shadow", "resync-full", XDT_SHADOW_RESYNC_FULL, XDT_SHADOW }, 451*55f5292cSFrank Van Der Linden { "shadow", "resync-only", XDT_SHADOW_RESYNC_ONLY, XDT_SHADOW }, 452*55f5292cSFrank Van Der Linden 453*55f5292cSFrank Van Der Linden { "pm", "freq-change", XDT_PM_FREQ_CHANGE, XDT_PM }, 454*55f5292cSFrank Van Der Linden { "pm", "idle-entry", XDT_PM_IDLE_ENTRY, XDT_PM }, 455*55f5292cSFrank Van Der Linden { "pm", "idle-exit", XDT_PM_IDLE_EXIT, XDT_PM }, 456c7158ae9Stariq 457349b53ddSStuart Maybee /* Trace buffer related probes */ 458349b53ddSStuart Maybee { "trace", "records-lost", XDT_TRC_LOST_RECORDS, XDT_GEN }, 459349b53ddSStuart Maybee 460c7158ae9Stariq { NULL } 461c7158ae9Stariq }; 462c7158ae9Stariq 463c7158ae9Stariq static inline uint32_t 464c7158ae9Stariq xdt_nr_active_probes() 465c7158ae9Stariq { 466c7158ae9Stariq int i; 467c7158ae9Stariq uint32_t tot = 0; 468c7158ae9Stariq 469c7158ae9Stariq for (i = 0; i < XDT_NCLASSES; i++) 470c7158ae9Stariq tot += xdt_classinfo[i].cnt; 471c7158ae9Stariq 472c7158ae9Stariq return (tot); 473c7158ae9Stariq } 474c7158ae9Stariq 475c7158ae9Stariq static void 476c7158ae9Stariq xdt_init_trace_masks(void) 477c7158ae9Stariq { 478c7158ae9Stariq xdt_classinfo[XDT_SCHED].trc_mask = TRC_SCHED; 479c7158ae9Stariq xdt_classinfo[XDT_MEM].trc_mask = TRC_MEM; 480c7158ae9Stariq xdt_classinfo[XDT_HVM].trc_mask = TRC_HVM; 481349b53ddSStuart Maybee xdt_classinfo[XDT_GEN].trc_mask = TRC_GEN; 482*55f5292cSFrank Van Der Linden xdt_classinfo[XDT_PV].trc_mask = TRC_PV; 483*55f5292cSFrank Van Der Linden xdt_classinfo[XDT_SHADOW].trc_mask = TRC_SHADOW; 484*55f5292cSFrank Van Der Linden xdt_classinfo[XDT_PM].trc_mask = TRC_PM; 485c7158ae9Stariq } 486c7158ae9Stariq 487c7158ae9Stariq static int 488c7158ae9Stariq xdt_kstat_update(kstat_t *ksp, int flag) 489c7158ae9Stariq { 490c7158ae9Stariq kstat_named_t *knp; 491c7158ae9Stariq 492c7158ae9Stariq if (flag != KSTAT_READ) 493c7158ae9Stariq return (EACCES); 494c7158ae9Stariq 495c7158ae9Stariq knp = ksp->ks_data; 496c7158ae9Stariq 497c7158ae9Stariq /* 498c7158ae9Stariq * Assignment order should match that of the names in 499c7158ae9Stariq * xdt_stats. 500c7158ae9Stariq */ 501c7158ae9Stariq (knp++)->value.ui64 = tbuf.stat_dropped_recs; 502c7158ae9Stariq 503c7158ae9Stariq return (0); 504c7158ae9Stariq } 505c7158ae9Stariq 506c7158ae9Stariq static void 507c7158ae9Stariq xdt_kstat_init(void) 508c7158ae9Stariq { 509c7158ae9Stariq int nstats = sizeof (xdt_stats) / sizeof (xdt_stats[0]); 510c7158ae9Stariq char **cp = xdt_stats; 511c7158ae9Stariq kstat_named_t *knp; 512c7158ae9Stariq 513c7158ae9Stariq if ((xdt_kstats = kstat_create("xdt", 0, "trace_statistics", "misc", 514c7158ae9Stariq KSTAT_TYPE_NAMED, nstats, 0)) == NULL) 515c7158ae9Stariq return; 516c7158ae9Stariq 517c7158ae9Stariq xdt_kstats->ks_update = xdt_kstat_update; 518c7158ae9Stariq 519c7158ae9Stariq knp = xdt_kstats->ks_data; 520c7158ae9Stariq while (nstats > 0) { 521c7158ae9Stariq kstat_named_init(knp, *cp, KSTAT_DATA_UINT64); 522c7158ae9Stariq knp++; 523c7158ae9Stariq cp++; 524c7158ae9Stariq nstats--; 525c7158ae9Stariq } 526c7158ae9Stariq 527c7158ae9Stariq kstat_install(xdt_kstats); 528c7158ae9Stariq } 529c7158ae9Stariq 530c7158ae9Stariq static int 531c7158ae9Stariq xdt_sysctl_tbuf(xen_sysctl_tbuf_op_t *tbuf_op) 532c7158ae9Stariq { 533c7158ae9Stariq xen_sysctl_t op; 534c7158ae9Stariq int xerr; 535c7158ae9Stariq 536c7158ae9Stariq op.cmd = XEN_SYSCTL_tbuf_op; 537c7158ae9Stariq op.interface_version = XEN_SYSCTL_INTERFACE_VERSION; 538c7158ae9Stariq op.u.tbuf_op = *tbuf_op; 539c7158ae9Stariq 540c7158ae9Stariq if ((xerr = HYPERVISOR_sysctl(&op)) != 0) 541c7158ae9Stariq return (xen_xlate_errcode(xerr)); 542c7158ae9Stariq 543c7158ae9Stariq *tbuf_op = op.u.tbuf_op; 544c7158ae9Stariq return (0); 545c7158ae9Stariq } 546c7158ae9Stariq 547c7158ae9Stariq static int 548c7158ae9Stariq xdt_map_trace_buffers(mfn_t mfn, caddr_t va, size_t len) 549c7158ae9Stariq { 550c7158ae9Stariq x86pte_t pte; 551c7158ae9Stariq caddr_t const sva = va; 552c7158ae9Stariq caddr_t const eva = va + len; 553c7158ae9Stariq int xerr; 554c7158ae9Stariq 555c7158ae9Stariq ASSERT(mfn != MFN_INVALID); 556c7158ae9Stariq ASSERT(va != NULL); 557c7158ae9Stariq ASSERT(IS_PAGEALIGNED(len)); 558c7158ae9Stariq 559c7158ae9Stariq for (; va < eva; va += MMU_PAGESIZE) { 560c7158ae9Stariq /* 561c7158ae9Stariq * Ask the HAT to load a throwaway mapping to page zero, then 562c7158ae9Stariq * overwrite it with the hypervisor mapping. It gets removed 563c7158ae9Stariq * later via hat_unload(). 564c7158ae9Stariq */ 565c7158ae9Stariq hat_devload(kas.a_hat, va, MMU_PAGESIZE, (pfn_t)0, 566c7158ae9Stariq PROT_READ | HAT_UNORDERED_OK, 567c7158ae9Stariq HAT_LOAD_NOCONSIST | HAT_LOAD); 568c7158ae9Stariq 569c7158ae9Stariq pte = mmu_ptob((x86pte_t)mfn) | PT_VALID | PT_USER 570c7158ae9Stariq | PT_FOREIGN | PT_WRITABLE; 571c7158ae9Stariq 572c7158ae9Stariq xerr = HYPERVISOR_update_va_mapping_otherdomain((ulong_t)va, 573c7158ae9Stariq pte, UVMF_INVLPG | UVMF_LOCAL, DOMID_XEN); 574c7158ae9Stariq 575c7158ae9Stariq if (xerr != 0) { 576c7158ae9Stariq /* unmap pages loaded so far */ 577c7158ae9Stariq size_t ulen = (uintptr_t)(va + MMU_PAGESIZE) - 578c7158ae9Stariq (uintptr_t)sva; 579c7158ae9Stariq hat_unload(kas.a_hat, sva, ulen, HAT_UNLOAD_UNMAP); 580c7158ae9Stariq return (xen_xlate_errcode(xerr)); 581c7158ae9Stariq } 582c7158ae9Stariq 583c7158ae9Stariq mfn++; 584c7158ae9Stariq } 585c7158ae9Stariq 586c7158ae9Stariq return (0); 587c7158ae9Stariq } 588c7158ae9Stariq 589c7158ae9Stariq static int 590c7158ae9Stariq xdt_attach_trace_buffers(void) 591c7158ae9Stariq { 592c7158ae9Stariq xen_sysctl_tbuf_op_t tbuf_op; 593c7158ae9Stariq size_t len; 594c7158ae9Stariq int err; 595c7158ae9Stariq uint_t i; 596c7158ae9Stariq 597411e7d8fSTariq Magdon-Ismail /* 598411e7d8fSTariq Magdon-Ismail * Xen does not support trace buffer re-sizing. If the buffers 599411e7d8fSTariq Magdon-Ismail * have already been allocated we just use them as is. 600411e7d8fSTariq Magdon-Ismail */ 601411e7d8fSTariq Magdon-Ismail tbuf_op.cmd = XEN_SYSCTL_TBUFOP_get_info; 602411e7d8fSTariq Magdon-Ismail if ((err = xdt_sysctl_tbuf(&tbuf_op)) != 0) 603411e7d8fSTariq Magdon-Ismail return (err); 604411e7d8fSTariq Magdon-Ismail 605411e7d8fSTariq Magdon-Ismail if (tbuf_op.size == 0) { 606c7158ae9Stariq /* set trace buffer size */ 607c7158ae9Stariq tbuf_op.cmd = XEN_SYSCTL_TBUFOP_set_size; 608c7158ae9Stariq tbuf_op.size = xdt_tbuf_pages; 609c7158ae9Stariq (void) xdt_sysctl_tbuf(&tbuf_op); 610c7158ae9Stariq 611c7158ae9Stariq /* get trace buffer info */ 612c7158ae9Stariq tbuf_op.cmd = XEN_SYSCTL_TBUFOP_get_info; 613c7158ae9Stariq if ((err = xdt_sysctl_tbuf(&tbuf_op)) != 0) 614c7158ae9Stariq return (err); 615c7158ae9Stariq 616411e7d8fSTariq Magdon-Ismail if (tbuf_op.size == 0) { 617411e7d8fSTariq Magdon-Ismail cmn_err(CE_NOTE, "Couldn't allocate trace buffers."); 618411e7d8fSTariq Magdon-Ismail return (ENOBUFS); 619411e7d8fSTariq Magdon-Ismail } 620411e7d8fSTariq Magdon-Ismail } 621411e7d8fSTariq Magdon-Ismail 622c7158ae9Stariq tbuf.size = tbuf_op.size; 623c7158ae9Stariq tbuf.start_mfn = (mfn_t)tbuf_op.buffer_mfn; 624c7158ae9Stariq tbuf.cnt = xdt_ncpus; 625c7158ae9Stariq 626c7158ae9Stariq ASSERT(tbuf.start_mfn != MFN_INVALID); 627c7158ae9Stariq ASSERT(tbuf.cnt > 0); 628c7158ae9Stariq 629c7158ae9Stariq len = tbuf.size * tbuf.cnt; 630c7158ae9Stariq tbuf.va = vmem_alloc(heap_arena, len, VM_SLEEP); 631c7158ae9Stariq 632c7158ae9Stariq if ((err = xdt_map_trace_buffers(tbuf.start_mfn, tbuf.va, len)) != 0) { 633c7158ae9Stariq vmem_free(heap_arena, tbuf.va, len); 634c7158ae9Stariq tbuf.va = NULL; 635c7158ae9Stariq return (err); 636c7158ae9Stariq } 637c7158ae9Stariq 638c7158ae9Stariq tbuf.meta = (struct t_buf **)kmem_alloc(tbuf.cnt * sizeof (*tbuf.meta), 639c7158ae9Stariq KM_SLEEP); 640c7158ae9Stariq tbuf.data = (struct t_rec **)kmem_alloc(tbuf.cnt * sizeof (*tbuf.data), 641c7158ae9Stariq KM_SLEEP); 642c7158ae9Stariq 643c7158ae9Stariq for (i = 0; i < tbuf.cnt; i++) { 644c7158ae9Stariq void *cpu_buf = (void *)(tbuf.va + (tbuf.size * i)); 645c7158ae9Stariq tbuf.meta[i] = cpu_buf; 646c7158ae9Stariq tbuf.data[i] = (struct t_rec *)((uintptr_t)cpu_buf + 647c7158ae9Stariq sizeof (struct t_buf)); 648c7158ae9Stariq 649c7158ae9Stariq /* throw away stale trace records */ 650c7158ae9Stariq tbuf.meta[i]->cons = tbuf.meta[i]->prod; 651c7158ae9Stariq } 652c7158ae9Stariq 653*55f5292cSFrank Van Der Linden tbuf_data_size = tbuf.size - sizeof (struct t_buf); 654*55f5292cSFrank Van Der Linden if (xdt_max_recs == 0) 655*55f5292cSFrank Van Der Linden xdt_max_recs = (xdt_ncpus * tbuf_data_size) 656*55f5292cSFrank Van Der Linden / sizeof (struct t_rec); 657*55f5292cSFrank Van Der Linden 658c7158ae9Stariq return (0); 659c7158ae9Stariq } 660c7158ae9Stariq 661c7158ae9Stariq static void 662c7158ae9Stariq xdt_detach_trace_buffers(void) 663c7158ae9Stariq { 664c7158ae9Stariq size_t len = tbuf.size * tbuf.cnt; 665c7158ae9Stariq 666c7158ae9Stariq ASSERT(tbuf.va != NULL); 667c7158ae9Stariq 668c7158ae9Stariq hat_unload(kas.a_hat, tbuf.va, len, 669c7158ae9Stariq HAT_UNLOAD_UNMAP | HAT_UNLOAD_UNLOCK); 670c7158ae9Stariq vmem_free(heap_arena, tbuf.va, len); 671c7158ae9Stariq kmem_free(tbuf.meta, tbuf.cnt * sizeof (*tbuf.meta)); 672c7158ae9Stariq kmem_free(tbuf.data, tbuf.cnt * sizeof (*tbuf.data)); 673c7158ae9Stariq } 674c7158ae9Stariq 675*55f5292cSFrank Van Der Linden static void 676*55f5292cSFrank Van Der Linden xdt_update_sched_context(uint_t cpuid, uint_t dom, uint_t vcpu) 677*55f5292cSFrank Van Der Linden { 678*55f5292cSFrank Van Der Linden xdt_schedinfo_t *sp = &xdt_cpu_schedinfo[cpuid]; 679*55f5292cSFrank Van Der Linden 680*55f5292cSFrank Van Der Linden sp->cur_domid = dom; 681*55f5292cSFrank Van Der Linden sp->cur_vcpuid = vcpu; 682*55f5292cSFrank Van Der Linden sp->curinfo_valid = 1; 683*55f5292cSFrank Van Der Linden } 684*55f5292cSFrank Van Der Linden 685*55f5292cSFrank Van Der Linden static void 686*55f5292cSFrank Van Der Linden xdt_update_domain_context(uint_t dom, uint_t vcpu) 687*55f5292cSFrank Van Der Linden { 688*55f5292cSFrank Van Der Linden xdt_curdom = dom; 689*55f5292cSFrank Van Der Linden xdt_curvcpu = vcpu; 690*55f5292cSFrank Van Der Linden } 691*55f5292cSFrank Van Der Linden 692*55f5292cSFrank Van Der Linden static size_t 693c7158ae9Stariq xdt_process_rec(uint_t cpuid, struct t_rec *rec) 694c7158ae9Stariq { 695c7158ae9Stariq xdt_schedinfo_t *sp = &xdt_cpu_schedinfo[cpuid]; 696*55f5292cSFrank Van Der Linden uint_t dom, vcpu; 697c7158ae9Stariq int eid; 698349b53ddSStuart Maybee uint32_t *data; 699*55f5292cSFrank Van Der Linden uint64_t tsc, addr64, rip64, val64, pte64; 700349b53ddSStuart Maybee size_t rec_size; 701c7158ae9Stariq 702c7158ae9Stariq ASSERT(rec != NULL); 703349b53ddSStuart Maybee ASSERT(xdt_ncpus == xpv_nr_phys_cpus()); 704c7158ae9Stariq 705c7158ae9Stariq if (cpuid >= xdt_ncpus) { 706c7158ae9Stariq tbuf.stat_spurious_cpu++; 707349b53ddSStuart Maybee goto done; 708c7158ae9Stariq } 709c7158ae9Stariq 710*55f5292cSFrank Van Der Linden /* 711*55f5292cSFrank Van Der Linden * If our current state isn't valid, and if this is not 712*55f5292cSFrank Van Der Linden * an event that will update our state, skip it. 713*55f5292cSFrank Van Der Linden */ 714*55f5292cSFrank Van Der Linden 715*55f5292cSFrank Van Der Linden if (!sp->curinfo_valid && 716*55f5292cSFrank Van Der Linden rec->event != TRC_SCHED_SWITCH && 717*55f5292cSFrank Van Der Linden rec->event != TRC_LOST_RECORDS) 718*55f5292cSFrank Van Der Linden goto done; 719*55f5292cSFrank Van Der Linden 720*55f5292cSFrank Van Der Linden if (rec->cycles_included) { 721*55f5292cSFrank Van Der Linden data = rec->u.cycles.extra_u32; 722*55f5292cSFrank Van Der Linden tsc = (((uint64_t)rec->u.cycles.cycles_hi) << 32) 723*55f5292cSFrank Van Der Linden | rec->u.cycles.cycles_lo; 724*55f5292cSFrank Van Der Linden } else { 725*55f5292cSFrank Van Der Linden data = rec->u.nocycles.extra_u32; 726*55f5292cSFrank Van Der Linden tsc = 0; 727*55f5292cSFrank Van Der Linden } 728*55f5292cSFrank Van Der Linden 729*55f5292cSFrank Van Der Linden xdt_timestamp = tsc; 730c7158ae9Stariq 731349b53ddSStuart Maybee switch (rec->event) { 732c7158ae9Stariq /* 733c7158ae9Stariq * Sched probes 734c7158ae9Stariq */ 735c7158ae9Stariq case TRC_SCHED_SWITCH_INFPREV: 736c7158ae9Stariq /* 737c7158ae9Stariq * Info on vCPU being de-scheduled 738c7158ae9Stariq * 739349b53ddSStuart Maybee * data[0] = prev domid 740349b53ddSStuart Maybee * data[1] = time spent on pcpu 741c7158ae9Stariq */ 742349b53ddSStuart Maybee sp->prev_domid = data[0]; 743349b53ddSStuart Maybee sp->prev_ctime = data[1]; 744c7158ae9Stariq break; 745c7158ae9Stariq 746c7158ae9Stariq case TRC_SCHED_SWITCH_INFNEXT: 747c7158ae9Stariq /* 748c7158ae9Stariq * Info on next vCPU to be scheduled 749c7158ae9Stariq * 750349b53ddSStuart Maybee * data[0] = next domid 751349b53ddSStuart Maybee * data[1] = time spent waiting to get on cpu 752349b53ddSStuart Maybee * data[2] = time slice 753c7158ae9Stariq */ 754349b53ddSStuart Maybee sp->next_domid = data[0]; 755349b53ddSStuart Maybee sp->next_wtime = data[1]; 756349b53ddSStuart Maybee sp->next_ts = data[2]; 757c7158ae9Stariq break; 758c7158ae9Stariq 759c7158ae9Stariq case TRC_SCHED_SWITCH: 760c7158ae9Stariq /* 761c7158ae9Stariq * vCPU switch 762c7158ae9Stariq * 763349b53ddSStuart Maybee * data[0] = prev domid 764349b53ddSStuart Maybee * data[1] = prev vcpuid 765349b53ddSStuart Maybee * data[2] = next domid 766349b53ddSStuart Maybee * data[3] = next vcpuid 767c7158ae9Stariq */ 768*55f5292cSFrank Van Der Linden 769*55f5292cSFrank Van Der Linden /* 770*55f5292cSFrank Van Der Linden * Provide valid context for this probe if there 771*55f5292cSFrank Van Der Linden * wasn't one. 772*55f5292cSFrank Van Der Linden */ 773*55f5292cSFrank Van Der Linden if (!sp->curinfo_valid) 774*55f5292cSFrank Van Der Linden xdt_update_domain_context(data[0], data[1]); 775*55f5292cSFrank Van Der Linden 776*55f5292cSFrank Van Der Linden xdt_update_sched_context(cpuid, data[0], data[1]); 777*55f5292cSFrank Van Der Linden 778349b53ddSStuart Maybee if (data[0] != sp->prev_domid && 779349b53ddSStuart Maybee data[2] != sp->next_domid) { 780c7158ae9Stariq /* prev and next info don't match doms being sched'd */ 781c7158ae9Stariq tbuf.stat_spurious_switch++; 782*55f5292cSFrank Van Der Linden goto switchdone; 783c7158ae9Stariq } 784c7158ae9Stariq 785349b53ddSStuart Maybee sp->prev_vcpuid = data[1]; 786349b53ddSStuart Maybee sp->next_vcpuid = data[3]; 787c7158ae9Stariq 788c7158ae9Stariq XDT_PROBE3(IS_IDLE_DOM(sp->prev_domid)? 789c7158ae9Stariq XDT_SCHED_IDLE_OFF_CPU:XDT_SCHED_OFF_CPU, 790*55f5292cSFrank Van Der Linden sp->prev_domid, sp->prev_vcpuid, sp->prev_ctime); 791c7158ae9Stariq 792c7158ae9Stariq XDT_PROBE4(IS_IDLE_DOM(sp->next_domid)? 793c7158ae9Stariq XDT_SCHED_IDLE_ON_CPU:XDT_SCHED_ON_CPU, 794*55f5292cSFrank Van Der Linden sp->next_domid, sp->next_vcpuid, sp->next_wtime, 795c7158ae9Stariq sp->next_ts); 796*55f5292cSFrank Van Der Linden switchdone: 797*55f5292cSFrank Van Der Linden xdt_update_sched_context(cpuid, data[2], data[3]); 798*55f5292cSFrank Van Der Linden xdt_update_domain_context(data[2], data[3]); 799*55f5292cSFrank Van Der Linden 800c7158ae9Stariq break; 801c7158ae9Stariq 802c7158ae9Stariq case TRC_SCHED_BLOCK: 803c7158ae9Stariq /* 804c7158ae9Stariq * vCPU blocked 805c7158ae9Stariq * 806349b53ddSStuart Maybee * data[0] = domid 807349b53ddSStuart Maybee * data[1] = vcpuid 808c7158ae9Stariq */ 809*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_SCHED_BLOCK, data[0], data[1]); 810c7158ae9Stariq break; 811c7158ae9Stariq 812c7158ae9Stariq case TRC_SCHED_SLEEP: 813c7158ae9Stariq /* 814c7158ae9Stariq * Put vCPU to sleep 815c7158ae9Stariq * 816349b53ddSStuart Maybee * data[0] = domid 817349b53ddSStuart Maybee * data[1] = vcpuid 818c7158ae9Stariq */ 819*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_SCHED_SLEEP, data[0], data[1]); 820c7158ae9Stariq break; 821c7158ae9Stariq 822c7158ae9Stariq case TRC_SCHED_WAKE: 823c7158ae9Stariq /* 824c7158ae9Stariq * Wake up vCPU 825c7158ae9Stariq * 826349b53ddSStuart Maybee * data[0] = domid 827349b53ddSStuart Maybee * data[1] = vcpuid 828c7158ae9Stariq */ 829*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_SCHED_WAKE, data[0], data[1]); 830c7158ae9Stariq break; 831c7158ae9Stariq 832c7158ae9Stariq case TRC_SCHED_YIELD: 833c7158ae9Stariq /* 834c7158ae9Stariq * vCPU yielded 835c7158ae9Stariq * 836349b53ddSStuart Maybee * data[0] = domid 837349b53ddSStuart Maybee * data[1] = vcpuid 838c7158ae9Stariq */ 839*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_SCHED_YIELD, data[0], data[1]); 840c7158ae9Stariq break; 841c7158ae9Stariq 842c7158ae9Stariq case TRC_SCHED_SHUTDOWN: 843c7158ae9Stariq /* 844c7158ae9Stariq * Guest shutting down 845c7158ae9Stariq * 846349b53ddSStuart Maybee * data[0] = domid 847349b53ddSStuart Maybee * data[1] = initiating vcpu 848349b53ddSStuart Maybee * data[2] = shutdown code 849c7158ae9Stariq */ 850349b53ddSStuart Maybee switch (data[2]) { 851c7158ae9Stariq case SHUTDOWN_poweroff: 852c7158ae9Stariq eid = XDT_SCHED_SHUTDOWN_POWEROFF; 853c7158ae9Stariq break; 854c7158ae9Stariq case SHUTDOWN_reboot: 855c7158ae9Stariq eid = XDT_SCHED_SHUTDOWN_REBOOT; 856c7158ae9Stariq break; 857c7158ae9Stariq case SHUTDOWN_suspend: 858c7158ae9Stariq eid = XDT_SCHED_SHUTDOWN_SUSPEND; 859c7158ae9Stariq break; 860c7158ae9Stariq case SHUTDOWN_crash: 861c7158ae9Stariq eid = XDT_SCHED_SHUTDOWN_CRASH; 862c7158ae9Stariq break; 863c7158ae9Stariq default: 864c7158ae9Stariq tbuf.stat_unknown_shutdown++; 865349b53ddSStuart Maybee goto done; 866c7158ae9Stariq } 867c7158ae9Stariq 868*55f5292cSFrank Van Der Linden XDT_PROBE2(eid, data[0], data[1]); 869c7158ae9Stariq break; 870c7158ae9Stariq 871*55f5292cSFrank Van Der Linden case TRC_SCHED_DOM_REM: 872*55f5292cSFrank Van Der Linden case TRC_SCHED_CTL: 873*55f5292cSFrank Van Der Linden case TRC_SCHED_S_TIMER_FN: 874*55f5292cSFrank Van Der Linden case TRC_SCHED_T_TIMER_FN: 875*55f5292cSFrank Van Der Linden case TRC_SCHED_DOM_TIMER_FN: 876*55f5292cSFrank Van Der Linden /* unused */ 877*55f5292cSFrank Van Der Linden break; 878*55f5292cSFrank Van Der Linden case TRC_SCHED_DOM_ADD: 879*55f5292cSFrank Van Der Linden /* 880*55f5292cSFrank Van Der Linden * Add vcpu to a guest. 881*55f5292cSFrank Van Der Linden * 882*55f5292cSFrank Van Der Linden * data[0] = domid 883*55f5292cSFrank Van Der Linden * data[1] = vcpu 884*55f5292cSFrank Van Der Linden */ 885*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_SCHED_ADD_VCPU, data[0], data[1]); 886*55f5292cSFrank Van Der Linden break; 887*55f5292cSFrank Van Der Linden case TRC_SCHED_ADJDOM: 888*55f5292cSFrank Van Der Linden /* 889*55f5292cSFrank Van Der Linden * Scheduling parameters for a guest 890*55f5292cSFrank Van Der Linden * were modified. 891*55f5292cSFrank Van Der Linden * 892*55f5292cSFrank Van Der Linden * data[0] = domid; 893*55f5292cSFrank Van Der Linden */ 894*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_SCHED_ADJDOM, data[1]); 895*55f5292cSFrank Van Der Linden break; 896*55f5292cSFrank Van Der Linden case TRC_SCHED_RUNSTATE_CHANGE: 897*55f5292cSFrank Van Der Linden /* 898*55f5292cSFrank Van Der Linden * Runstate change for a VCPU. 899*55f5292cSFrank Van Der Linden * 900*55f5292cSFrank Van Der Linden * data[0] = (domain << 16) | vcpu; 901*55f5292cSFrank Van Der Linden * data[1] = oldstate; 902*55f5292cSFrank Van Der Linden * data[2] = newstate; 903*55f5292cSFrank Van Der Linden */ 904*55f5292cSFrank Van Der Linden XDT_PROBE4(XDT_SCHED_RUNSTATE_CHANGE, data[0] >> 16, 905*55f5292cSFrank Van Der Linden data[0] & 0xffff, data[1], data[2]); 906*55f5292cSFrank Van Der Linden break; 907*55f5292cSFrank Van Der Linden case TRC_SCHED_CONTINUE_RUNNING: 908*55f5292cSFrank Van Der Linden /* 909*55f5292cSFrank Van Der Linden * VCPU is back on a physical CPU that it previously 910*55f5292cSFrank Van Der Linden * was also running this VCPU. 911*55f5292cSFrank Van Der Linden * 912*55f5292cSFrank Van Der Linden * data[0] = (domain << 16) | vcpu; 913*55f5292cSFrank Van Der Linden */ 914*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_SCHED_CONTINUE_RUNNING, data[0] >> 16, 915*55f5292cSFrank Van Der Linden data[0] & 0xffff); 916*55f5292cSFrank Van Der Linden break; 917c7158ae9Stariq /* 918c7158ae9Stariq * Mem probes 919c7158ae9Stariq */ 920c7158ae9Stariq case TRC_MEM_PAGE_GRANT_MAP: 921c7158ae9Stariq /* 922c7158ae9Stariq * Guest mapped page grant 923c7158ae9Stariq * 924*55f5292cSFrank Van Der Linden * data[0] = target domid 925c7158ae9Stariq */ 926*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_MEM_PAGE_GRANT_MAP, data[0]); 927c7158ae9Stariq break; 928c7158ae9Stariq 929c7158ae9Stariq case TRC_MEM_PAGE_GRANT_UNMAP: 930c7158ae9Stariq /* 931c7158ae9Stariq * Guest unmapped page grant 932c7158ae9Stariq * 933*55f5292cSFrank Van Der Linden * data[0] = target domid 934c7158ae9Stariq */ 935*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_MEM_PAGE_GRANT_UNMAP, data[0]); 936c7158ae9Stariq break; 937c7158ae9Stariq 938c7158ae9Stariq case TRC_MEM_PAGE_GRANT_TRANSFER: 939c7158ae9Stariq /* 940c7158ae9Stariq * Page grant is being transferred 941c7158ae9Stariq * 942349b53ddSStuart Maybee * data[0] = target domid 943c7158ae9Stariq */ 944*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_MEM_PAGE_GRANT_TRANSFER, data[0]); 945*55f5292cSFrank Van Der Linden break; 946*55f5292cSFrank Van Der Linden 947*55f5292cSFrank Van Der Linden /* 948*55f5292cSFrank Van Der Linden * Probes for PV domains. 949*55f5292cSFrank Van Der Linden */ 950*55f5292cSFrank Van Der Linden case TRC_PV_HYPERCALL: 951*55f5292cSFrank Van Der Linden /* 952*55f5292cSFrank Van Der Linden * Hypercall from a 32-bit PV domain. 953*55f5292cSFrank Van Der Linden * 954*55f5292cSFrank Van Der Linden * data[0] = eip 955*55f5292cSFrank Van Der Linden * data[1] = eax 956*55f5292cSFrank Van Der Linden */ 957*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_PV_HYPERCALL, data[0], data[1]); 958*55f5292cSFrank Van Der Linden break; 959*55f5292cSFrank Van Der Linden case TRC_PV_HYPERCALL | TRC_64_FLAG: 960*55f5292cSFrank Van Der Linden /* 961*55f5292cSFrank Van Der Linden * Hypercall from a 64-bit PV domain. 962*55f5292cSFrank Van Der Linden * 963*55f5292cSFrank Van Der Linden * data[0] = rip(0:31) 964*55f5292cSFrank Van Der Linden * data[1] = rip(32:63) 965*55f5292cSFrank Van Der Linden * data[2] = eax; 966*55f5292cSFrank Van Der Linden */ 967*55f5292cSFrank Van Der Linden rip64 = (((uint64_t)data[1]) << 32) | data[0]; 968*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_PV_HYPERCALL, rip64, data[2]); 969*55f5292cSFrank Van Der Linden break; 970*55f5292cSFrank Van Der Linden case TRC_PV_TRAP: 971*55f5292cSFrank Van Der Linden /* 972*55f5292cSFrank Van Der Linden * Trap in a 32-bit PV domain. 973*55f5292cSFrank Van Der Linden * 974*55f5292cSFrank Van Der Linden * data[0] = eip 975*55f5292cSFrank Van Der Linden * data[1] = trapnr | (error_code_valid << 15) 976*55f5292cSFrank Van Der Linden * | (error_code << 16); 977*55f5292cSFrank Van Der Linden */ 978*55f5292cSFrank Van Der Linden XDT_PROBE4(XDT_PV_TRAP, data[0], data[1] & 0x7fff, 979*55f5292cSFrank Van Der Linden (data[1] >> 15) & 1, data[1] >> 16); 980*55f5292cSFrank Van Der Linden break; 981*55f5292cSFrank Van Der Linden case TRC_PV_TRAP | TRC_64_FLAG: 982*55f5292cSFrank Van Der Linden /* 983*55f5292cSFrank Van Der Linden * Trap in a 64-bit PV domain. 984*55f5292cSFrank Van Der Linden * 985*55f5292cSFrank Van Der Linden * data[0] = rip(0:31) 986*55f5292cSFrank Van Der Linden * data[1] = rip(32:63) 987*55f5292cSFrank Van Der Linden * data[2] = trapnr | (error_code_valid << 15) 988*55f5292cSFrank Van Der Linden * | (error_code << 16); 989*55f5292cSFrank Van Der Linden */ 990*55f5292cSFrank Van Der Linden rip64 = (((uint64_t)data[1]) << 32) | data[2]; 991*55f5292cSFrank Van Der Linden XDT_PROBE4(XDT_PV_TRAP, rip64, data[2] & 0x7fff, 992*55f5292cSFrank Van Der Linden (data[2] >> 15) & 1, data[2] >> 16); 993*55f5292cSFrank Van Der Linden break; 994*55f5292cSFrank Van Der Linden case TRC_PV_PAGE_FAULT: 995*55f5292cSFrank Van Der Linden /* 996*55f5292cSFrank Van Der Linden * Page fault in a 32-bit PV domain. 997*55f5292cSFrank Van Der Linden * 998*55f5292cSFrank Van Der Linden * data[0] = eip 999*55f5292cSFrank Van Der Linden * data[1] = vaddr 1000*55f5292cSFrank Van Der Linden * data[2] = error code 1001*55f5292cSFrank Van Der Linden */ 1002*55f5292cSFrank Van Der Linden XDT_PROBE3(XDT_PV_PAGE_FAULT, data[0], data[1], data[2]); 1003*55f5292cSFrank Van Der Linden break; 1004*55f5292cSFrank Van Der Linden case TRC_PV_PAGE_FAULT | TRC_64_FLAG: 1005*55f5292cSFrank Van Der Linden /* 1006*55f5292cSFrank Van Der Linden * Page fault in a 32-bit PV domain. 1007*55f5292cSFrank Van Der Linden * 1008*55f5292cSFrank Van Der Linden * data[0] = rip(0:31) 1009*55f5292cSFrank Van Der Linden * data[1] = rip(31:63) 1010*55f5292cSFrank Van Der Linden * data[2] = vaddr(0:31) 1011*55f5292cSFrank Van Der Linden * data[3] = vaddr(31:63) 1012*55f5292cSFrank Van Der Linden * data[4] = error code 1013*55f5292cSFrank Van Der Linden */ 1014*55f5292cSFrank Van Der Linden rip64 = (((uint64_t)data[1]) << 32) | data[0]; 1015*55f5292cSFrank Van Der Linden addr64 = (((uint64_t)data[3]) << 32) | data[2]; 1016*55f5292cSFrank Van Der Linden XDT_PROBE3(XDT_PV_PAGE_FAULT, rip64, addr64, data[4]); 1017*55f5292cSFrank Van Der Linden break; 1018*55f5292cSFrank Van Der Linden case TRC_PV_FORCED_INVALID_OP: 1019*55f5292cSFrank Van Der Linden /* 1020*55f5292cSFrank Van Der Linden * Hypervisor emulated a forced invalid op (ud2) 1021*55f5292cSFrank Van Der Linden * in a 32-bit PV domain. 1022*55f5292cSFrank Van Der Linden * 1023*55f5292cSFrank Van Der Linden * data[1] = eip 1024*55f5292cSFrank Van Der Linden */ 1025*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_PV_FORCED_INVALID_OP, data[1]); 1026*55f5292cSFrank Van Der Linden break; 1027*55f5292cSFrank Van Der Linden case TRC_PV_FORCED_INVALID_OP | TRC_64_FLAG: 1028*55f5292cSFrank Van Der Linden /* 1029*55f5292cSFrank Van Der Linden * Hypervisor emulated a forced invalid op (ud2) 1030*55f5292cSFrank Van Der Linden * in a 64-bit PV domain. 1031*55f5292cSFrank Van Der Linden * 1032*55f5292cSFrank Van Der Linden * data[1] = rip(0:31) 1033*55f5292cSFrank Van Der Linden * data[2] = rip(31:63) 1034*55f5292cSFrank Van Der Linden * 1035*55f5292cSFrank Van Der Linden */ 1036*55f5292cSFrank Van Der Linden rip64 = (((uint64_t)data[2]) << 32) | data[1]; 1037*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_PV_FORCED_INVALID_OP, rip64); 1038*55f5292cSFrank Van Der Linden break; 1039*55f5292cSFrank Van Der Linden case TRC_PV_EMULATE_PRIVOP: 1040*55f5292cSFrank Van Der Linden /* 1041*55f5292cSFrank Van Der Linden * Hypervisor emulated a privileged operation 1042*55f5292cSFrank Van Der Linden * in a 32-bit PV domain. 1043*55f5292cSFrank Van Der Linden * 1044*55f5292cSFrank Van Der Linden * data[0] = eip 1045*55f5292cSFrank Van Der Linden */ 1046*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_PV_EMULATE_PRIVOP, data[0]); 1047*55f5292cSFrank Van Der Linden break; 1048*55f5292cSFrank Van Der Linden case TRC_PV_EMULATE_PRIVOP | TRC_64_FLAG: 1049*55f5292cSFrank Van Der Linden /* 1050*55f5292cSFrank Van Der Linden * Hypervisor emulated a privileged operation 1051*55f5292cSFrank Van Der Linden * in a 64-bit PV domain. 1052*55f5292cSFrank Van Der Linden * 1053*55f5292cSFrank Van Der Linden * data[0] = rip(0:31) 1054*55f5292cSFrank Van Der Linden * data[1] = rip(31:63) 1055*55f5292cSFrank Van Der Linden */ 1056*55f5292cSFrank Van Der Linden rip64 = (((uint64_t)data[1]) << 32) | data[0]; 1057*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_PV_EMULATE_PRIVOP, rip64); 1058*55f5292cSFrank Van Der Linden break; 1059*55f5292cSFrank Van Der Linden case TRC_PV_EMULATE_4GB: 1060*55f5292cSFrank Van Der Linden /* unused, 32-bit hypervisor only */ 1061*55f5292cSFrank Van Der Linden break; 1062*55f5292cSFrank Van Der Linden case TRC_PV_MATH_STATE_RESTORE: 1063*55f5292cSFrank Van Der Linden /* 1064*55f5292cSFrank Van Der Linden * Hypervisor restores math state after FP DNA trap. 1065*55f5292cSFrank Van Der Linden * 1066*55f5292cSFrank Van Der Linden * No arguments. 1067*55f5292cSFrank Van Der Linden */ 1068*55f5292cSFrank Van Der Linden XDT_PROBE0(XDT_PV_MATH_STATE_RESTORE); 1069*55f5292cSFrank Van Der Linden break; 1070*55f5292cSFrank Van Der Linden case TRC_PV_PAGING_FIXUP: 1071*55f5292cSFrank Van Der Linden /* 1072*55f5292cSFrank Van Der Linden * Hypervisor fixed up a page fault (e.g. it was 1073*55f5292cSFrank Van Der Linden * a side-effect of hypervisor guest page table 1074*55f5292cSFrank Van Der Linden * bookkeeping, and not propagated to the guest). 1075*55f5292cSFrank Van Der Linden * 1076*55f5292cSFrank Van Der Linden * data[0] = eip 1077*55f5292cSFrank Van Der Linden * data[1] = vaddr 1078*55f5292cSFrank Van Der Linden */ 1079*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_PV_PAGING_FIXUP, data[0], data[2]); 1080*55f5292cSFrank Van Der Linden break; 1081*55f5292cSFrank Van Der Linden case TRC_PV_PAGING_FIXUP | TRC_64_FLAG: 1082*55f5292cSFrank Van Der Linden /* 1083*55f5292cSFrank Van Der Linden * Hypervisor fixed up a page fault (e.g. it was 1084*55f5292cSFrank Van Der Linden * a side-effect of hypervisor guest page table 1085*55f5292cSFrank Van Der Linden * bookkeeping, and not propagated to the guest). 1086*55f5292cSFrank Van Der Linden * 1087*55f5292cSFrank Van Der Linden * data[0] = eip(0:31) 1088*55f5292cSFrank Van Der Linden * data[1] = eip(31:63) 1089*55f5292cSFrank Van Der Linden * data[2] = vaddr(0:31) 1090*55f5292cSFrank Van Der Linden * data[3] = vaddr(31:63) 1091*55f5292cSFrank Van Der Linden */ 1092*55f5292cSFrank Van Der Linden rip64 = (((uint64_t)data[1]) << 32) | data[0]; 1093*55f5292cSFrank Van Der Linden addr64 = (((uint64_t)data[3]) << 32) | data[2]; 1094*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_PV_PAGING_FIXUP, rip64, addr64); 1095*55f5292cSFrank Van Der Linden break; 1096*55f5292cSFrank Van Der Linden case TRC_PV_GDT_LDT_MAPPING_FAULT: 1097*55f5292cSFrank Van Der Linden /* 1098*55f5292cSFrank Van Der Linden * Descriptor table mapping fault in a 32-bit PV domain. 1099*55f5292cSFrank Van Der Linden * data[0] = eip 1100*55f5292cSFrank Van Der Linden * data[1] = offset 1101*55f5292cSFrank Van Der Linden */ 1102*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_PV_DT_MAPPING_FAULT, data[0], data[1]); 1103*55f5292cSFrank Van Der Linden break; 1104*55f5292cSFrank Van Der Linden case TRC_PV_GDT_LDT_MAPPING_FAULT | TRC_64_FLAG: 1105*55f5292cSFrank Van Der Linden /* 1106*55f5292cSFrank Van Der Linden * Descriptor table mapping fault in a 64-bit PV domain. 1107*55f5292cSFrank Van Der Linden * 1108*55f5292cSFrank Van Der Linden * data[0] = eip(0:31) 1109*55f5292cSFrank Van Der Linden * data[1] = eip(31:63) 1110*55f5292cSFrank Van Der Linden * data[2] = offset(0:31) 1111*55f5292cSFrank Van Der Linden * data[3] = offset(31:63) 1112*55f5292cSFrank Van Der Linden */ 1113*55f5292cSFrank Van Der Linden rip64 = (((uint64_t)data[1]) << 32) | data[0]; 1114*55f5292cSFrank Van Der Linden val64 = (((uint64_t)data[3]) << 32) | data[2]; 1115*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_PV_DT_MAPPING_FAULT, rip64, val64); 1116*55f5292cSFrank Van Der Linden break; 1117*55f5292cSFrank Van Der Linden case TRC_PV_PTWR_EMULATION: 1118*55f5292cSFrank Van Der Linden case TRC_PV_PTWR_EMULATION_PAE | TRC_64_FLAG: 1119*55f5292cSFrank Van Der Linden /* 1120*55f5292cSFrank Van Der Linden * Should only happen on 32-bit hypervisor; unused. 1121*55f5292cSFrank Van Der Linden */ 1122*55f5292cSFrank Van Der Linden break; 1123*55f5292cSFrank Van Der Linden case TRC_PV_PTWR_EMULATION_PAE: 1124*55f5292cSFrank Van Der Linden /* 1125*55f5292cSFrank Van Der Linden * PTE write emulation for a 32-bit PV domain. 1126*55f5292cSFrank Van Der Linden * 1127*55f5292cSFrank Van Der Linden * data[0] = pte 1128*55f5292cSFrank Van Der Linden * data[1] = addr 1129*55f5292cSFrank Van Der Linden * data[2] = eip 1130*55f5292cSFrank Van Der Linden */ 1131*55f5292cSFrank Van Der Linden XDT_PROBE3(XDT_PV_PTWR_EMULATION, data[0], data[1], data[2]); 1132*55f5292cSFrank Van Der Linden break; 1133*55f5292cSFrank Van Der Linden case TRC_PV_PTWR_EMULATION | TRC_64_FLAG: 1134*55f5292cSFrank Van Der Linden /* 1135*55f5292cSFrank Van Der Linden * PTE write emulation for a 64-bit PV domain. 1136*55f5292cSFrank Van Der Linden * 1137*55f5292cSFrank Van Der Linden * data[0] = pte(0:31) 1138*55f5292cSFrank Van Der Linden * data[1] = pte(32:63) 1139*55f5292cSFrank Van Der Linden * data[2] = addr(0:31) 1140*55f5292cSFrank Van Der Linden * data[3] = addr(32:63) 1141*55f5292cSFrank Van Der Linden * data[4] = rip(0:31) 1142*55f5292cSFrank Van Der Linden * data[5] = rip(32:63) 1143*55f5292cSFrank Van Der Linden */ 1144*55f5292cSFrank Van Der Linden pte64 = (((uint64_t)data[1]) << 32) | data[0]; 1145*55f5292cSFrank Van Der Linden addr64 = (((uint64_t)data[3]) << 32) | data[2]; 1146*55f5292cSFrank Van Der Linden rip64 = (((uint64_t)data[5]) << 32) | data[4]; 1147*55f5292cSFrank Van Der Linden XDT_PROBE3(XDT_PV_PTWR_EMULATION, pte64, addr64, rip64); 1148c7158ae9Stariq break; 1149c7158ae9Stariq 1150c7158ae9Stariq /* 1151c7158ae9Stariq * HVM probes 1152c7158ae9Stariq */ 1153c7158ae9Stariq case TRC_HVM_VMENTRY: 1154c7158ae9Stariq /* 1155c7158ae9Stariq * Return to guest via vmx_launch/vmrun 1156c7158ae9Stariq * 1157c7158ae9Stariq */ 1158*55f5292cSFrank Van Der Linden XDT_PROBE0(XDT_HVM_VMENTRY); 1159c7158ae9Stariq break; 1160c7158ae9Stariq 1161*55f5292cSFrank Van Der Linden case TRC_HVM_VMEXIT: 1162*55f5292cSFrank Van Der Linden /* 1163*55f5292cSFrank Van Der Linden * Entry into VMEXIT handler from 32-bit HVM domain 1164*55f5292cSFrank Van Der Linden * 1165*55f5292cSFrank Van Der Linden * data[0] = cpu vendor specific exit code 1166*55f5292cSFrank Van Der Linden * data[1] = guest eip 1167*55f5292cSFrank Van Der Linden */ 1168*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_HVM_VMEXIT, data[0], data[1]); 1169*55f5292cSFrank Van Der Linden break; 1170349b53ddSStuart Maybee case TRC_HVM_VMEXIT64: 1171c7158ae9Stariq /* 1172*55f5292cSFrank Van Der Linden * Entry into VMEXIT handler from 64-bit HVM domain 1173c7158ae9Stariq * 1174*55f5292cSFrank Van Der Linden * data[0] = cpu vendor specific exit code 1175*55f5292cSFrank Van Der Linden * data[1] = guest rip(0:31) 1176*55f5292cSFrank Van Der Linden * data[2] = guest rip(32:64) 1177c7158ae9Stariq */ 1178*55f5292cSFrank Van Der Linden rip64 = (((uint64_t)data[2]) << 32) | data[1]; 1179*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_HVM_VMEXIT, data[0], rip64); 1180c7158ae9Stariq break; 1181c7158ae9Stariq 1182*55f5292cSFrank Van Der Linden case TRC_HVM_PF_XEN64: 1183*55f5292cSFrank Van Der Linden /* 1184*55f5292cSFrank Van Der Linden * Pagefault in a guest that is a Xen (e.g. shadow) 1185*55f5292cSFrank Van Der Linden * artifact, and is not injected back into the guest. 1186*55f5292cSFrank Van Der Linden * 1187*55f5292cSFrank Van Der Linden * data[0] = error code 1188*55f5292cSFrank Van Der Linden * data[1] = guest VA(0:31) 1189*55f5292cSFrank Van Der Linden * data[2] = guest VA(32:64) 1190*55f5292cSFrank Van Der Linden */ 1191*55f5292cSFrank Van Der Linden addr64 = (((uint64_t)data[2]) << 32) | data[1]; 1192*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_HVM_PF_XEN, data[0], addr64); 1193*55f5292cSFrank Van Der Linden break; 1194*55f5292cSFrank Van Der Linden 1195*55f5292cSFrank Van Der Linden case TRC_HVM_PF_XEN: 1196*55f5292cSFrank Van Der Linden /* 1197*55f5292cSFrank Van Der Linden * Same as above, but for a 32-bit HVM domain. 1198*55f5292cSFrank Van Der Linden * 1199*55f5292cSFrank Van Der Linden * data[0] = error code 1200*55f5292cSFrank Van Der Linden * data[1] = guest VA 1201*55f5292cSFrank Van Der Linden */ 1202*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_HVM_PF_XEN, data[0], data[1]); 1203*55f5292cSFrank Van Der Linden break; 1204*55f5292cSFrank Van Der Linden 1205*55f5292cSFrank Van Der Linden case TRC_HVM_PF_INJECT: 1206*55f5292cSFrank Van Der Linden /* 1207*55f5292cSFrank Van Der Linden * 32-bit Xen only. 1208*55f5292cSFrank Van Der Linden */ 1209*55f5292cSFrank Van Der Linden break; 1210*55f5292cSFrank Van Der Linden case TRC_HVM_PF_INJECT64: 1211*55f5292cSFrank Van Der Linden /* 1212*55f5292cSFrank Van Der Linden * Pagefault injected back into a guest (e.g. the shadow 1213*55f5292cSFrank Van Der Linden * code found no mapping). 1214*55f5292cSFrank Van Der Linden * 1215*55f5292cSFrank Van Der Linden * data[0] = error code 1216*55f5292cSFrank Van Der Linden * data[1] = guest VA(0:31) 1217*55f5292cSFrank Van Der Linden * data[2] = guest VA(32:64) 1218*55f5292cSFrank Van Der Linden */ 1219*55f5292cSFrank Van Der Linden addr64 = (((uint64_t)data[2]) << 32) | data[1]; 1220*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_HVM_PF_INJECT, data[0], addr64); 1221*55f5292cSFrank Van Der Linden break; 1222*55f5292cSFrank Van Der Linden 1223*55f5292cSFrank Van Der Linden case TRC_HVM_INJ_EXC: 1224*55f5292cSFrank Van Der Linden /* 1225*55f5292cSFrank Van Der Linden * Exception injected into an HVM guest. 1226*55f5292cSFrank Van Der Linden * 1227*55f5292cSFrank Van Der Linden * data[0] = trap 1228*55f5292cSFrank Van Der Linden * data[1] = error code 1229*55f5292cSFrank Van Der Linden */ 1230*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_HVM_EXC_INJECT, data[0], data[1]); 1231*55f5292cSFrank Van Der Linden break; 1232*55f5292cSFrank Van Der Linden case TRC_HVM_INJ_VIRQ: 1233*55f5292cSFrank Van Der Linden /* 1234*55f5292cSFrank Van Der Linden * Interrupt inject into an HVM guest. 1235*55f5292cSFrank Van Der Linden * 1236*55f5292cSFrank Van Der Linden * data[0] = vector 1237*55f5292cSFrank Van Der Linden */ 1238*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_HVM_VIRQ_INJECT, data[0]); 1239*55f5292cSFrank Van Der Linden break; 1240*55f5292cSFrank Van Der Linden case TRC_HVM_REINJ_VIRQ: 1241*55f5292cSFrank Van Der Linden case TRC_HVM_IO_READ: 1242*55f5292cSFrank Van Der Linden case TRC_HVM_IO_WRITE: 1243*55f5292cSFrank Van Der Linden /* unused */ 1244*55f5292cSFrank Van Der Linden break; 1245*55f5292cSFrank Van Der Linden case TRC_HVM_CR_READ64: 1246*55f5292cSFrank Van Der Linden /* 1247*55f5292cSFrank Van Der Linden * Control register read. Intel VMX only. 1248*55f5292cSFrank Van Der Linden * 1249*55f5292cSFrank Van Der Linden * data[0] = control register # 1250*55f5292cSFrank Van Der Linden * data[1] = value(0:31) 1251*55f5292cSFrank Van Der Linden * data[2] = value(32:63) 1252*55f5292cSFrank Van Der Linden */ 1253*55f5292cSFrank Van Der Linden val64 = (((uint64_t)data[2]) << 32) | data[1]; 1254*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_HVM_CR_READ, data[0], val64); 1255*55f5292cSFrank Van Der Linden break; 1256*55f5292cSFrank Van Der Linden case TRC_HVM_CR_READ: 1257*55f5292cSFrank Van Der Linden /* 1258*55f5292cSFrank Van Der Linden * unused (32-bit Xen only) 1259*55f5292cSFrank Van Der Linden */ 1260*55f5292cSFrank Van Der Linden break; 1261*55f5292cSFrank Van Der Linden case TRC_HVM_CR_WRITE64: 1262*55f5292cSFrank Van Der Linden /* 1263*55f5292cSFrank Van Der Linden * Control register write. Intel VMX only. 1264*55f5292cSFrank Van Der Linden * 1265*55f5292cSFrank Van Der Linden * data[0] = control register # 1266*55f5292cSFrank Van Der Linden * data[1] = value(0:31) 1267*55f5292cSFrank Van Der Linden * data[2] = value(32:63) 1268*55f5292cSFrank Van Der Linden */ 1269*55f5292cSFrank Van Der Linden val64 = (((uint64_t)data[2]) << 32) | data[1]; 1270*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_HVM_CR_READ, data[0], val64); 1271*55f5292cSFrank Van Der Linden break; 1272*55f5292cSFrank Van Der Linden case TRC_HVM_CR_WRITE: 1273*55f5292cSFrank Van Der Linden /* 1274*55f5292cSFrank Van Der Linden * unused (32-bit Xen only) 1275*55f5292cSFrank Van Der Linden */ 1276*55f5292cSFrank Van Der Linden break; 1277*55f5292cSFrank Van Der Linden case TRC_HVM_DR_READ: 1278*55f5292cSFrank Van Der Linden /* 1279*55f5292cSFrank Van Der Linden * unused. 1280*55f5292cSFrank Van Der Linden * 1281*55f5292cSFrank Van Der Linden * data[0] = (domid<<16 + vcpuid) 1282*55f5292cSFrank Van Der Linden */ 1283*55f5292cSFrank Van Der Linden break; 1284*55f5292cSFrank Van Der Linden case TRC_HVM_DR_WRITE: 1285*55f5292cSFrank Van Der Linden /* 1286*55f5292cSFrank Van Der Linden * Debug register write. Not too useful; no values, 1287*55f5292cSFrank Van Der Linden * so we ignore this. 1288*55f5292cSFrank Van Der Linden * 1289*55f5292cSFrank Van Der Linden * data[0] = (domid<<16 + vcpuid) 1290*55f5292cSFrank Van Der Linden */ 1291*55f5292cSFrank Van Der Linden break; 1292*55f5292cSFrank Van Der Linden case TRC_HVM_MSR_READ: 1293*55f5292cSFrank Van Der Linden /* 1294*55f5292cSFrank Van Der Linden * MSR read. 1295*55f5292cSFrank Van Der Linden * 1296*55f5292cSFrank Van Der Linden * data[0] = MSR 1297*55f5292cSFrank Van Der Linden * data[1] = value(0:31) 1298*55f5292cSFrank Van Der Linden * data[2] = value(32:63) 1299*55f5292cSFrank Van Der Linden */ 1300*55f5292cSFrank Van Der Linden val64 = (((uint64_t)data[3]) << 32) | data[2]; 1301*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_HVM_MSR_READ, data[0], val64); 1302*55f5292cSFrank Van Der Linden break; 1303*55f5292cSFrank Van Der Linden case TRC_HVM_MSR_WRITE: 1304*55f5292cSFrank Van Der Linden /* 1305*55f5292cSFrank Van Der Linden * MSR write. 1306*55f5292cSFrank Van Der Linden * 1307*55f5292cSFrank Van Der Linden * data[0] = MSR; 1308*55f5292cSFrank Van Der Linden * data[1] = value(0:31) 1309*55f5292cSFrank Van Der Linden * data[2] = value(32:63) 1310*55f5292cSFrank Van Der Linden */ 1311*55f5292cSFrank Van Der Linden val64 = (((uint64_t)data[2]) << 32) | data[1]; 1312*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_HVM_MSR_WRITE, data[0], val64); 1313*55f5292cSFrank Van Der Linden break; 1314*55f5292cSFrank Van Der Linden case TRC_HVM_CPUID: 1315*55f5292cSFrank Van Der Linden /* 1316*55f5292cSFrank Van Der Linden * CPUID insn. 1317*55f5292cSFrank Van Der Linden * 1318*55f5292cSFrank Van Der Linden * data[0] = %eax (input) 1319*55f5292cSFrank Van Der Linden * data[1] = %eax 1320*55f5292cSFrank Van Der Linden * data[2] = %ebx 1321*55f5292cSFrank Van Der Linden * data[3] = %ecx 1322*55f5292cSFrank Van Der Linden * data[4] = %edx 1323*55f5292cSFrank Van Der Linden */ 1324*55f5292cSFrank Van Der Linden XDT_PROBE5(XDT_HVM_CPUID, data[0], data[1], data[2], data[3], 1325*55f5292cSFrank Van Der Linden data[4]); 1326*55f5292cSFrank Van Der Linden break; 1327*55f5292cSFrank Van Der Linden case TRC_HVM_INTR: 1328*55f5292cSFrank Van Der Linden /* 1329*55f5292cSFrank Van Der Linden * VMEXIT because of an interrupt. 1330*55f5292cSFrank Van Der Linden */ 1331*55f5292cSFrank Van Der Linden XDT_PROBE0(XDT_HVM_INTR); 1332*55f5292cSFrank Van Der Linden break; 1333*55f5292cSFrank Van Der Linden case TRC_HVM_INTR_WINDOW: 1334*55f5292cSFrank Van Der Linden /* 1335*55f5292cSFrank Van Der Linden * VMEXIT because of an interrupt window (an interrupt 1336*55f5292cSFrank Van Der Linden * can't be delivered immediately to a HVM guest and must 1337*55f5292cSFrank Van Der Linden * be delayed). 1338*55f5292cSFrank Van Der Linden * 1339*55f5292cSFrank Van Der Linden * data[0] = vector 1340*55f5292cSFrank Van Der Linden * data[1] = source 1341*55f5292cSFrank Van Der Linden * data[2] = info 1342*55f5292cSFrank Van Der Linden */ 1343*55f5292cSFrank Van Der Linden XDT_PROBE3(XDT_HVM_INTR_WINDOW, data[0], data[1], data[2]); 1344*55f5292cSFrank Van Der Linden break; 1345*55f5292cSFrank Van Der Linden case TRC_HVM_NMI: 1346*55f5292cSFrank Van Der Linden /* 1347*55f5292cSFrank Van Der Linden * VMEXIT because of an NMI. 1348*55f5292cSFrank Van Der Linden */ 1349*55f5292cSFrank Van Der Linden XDT_PROBE0(XDT_HVM_NMI); 1350*55f5292cSFrank Van Der Linden break; 1351*55f5292cSFrank Van Der Linden case TRC_HVM_SMI: 1352*55f5292cSFrank Van Der Linden /* 1353*55f5292cSFrank Van Der Linden * VMEXIT because of an SMI 1354*55f5292cSFrank Van Der Linden */ 1355*55f5292cSFrank Van Der Linden XDT_PROBE0(XDT_HVM_SMI); 1356*55f5292cSFrank Van Der Linden break; 1357*55f5292cSFrank Van Der Linden case TRC_HVM_VMMCALL: 1358*55f5292cSFrank Van Der Linden /* 1359*55f5292cSFrank Van Der Linden * VMMCALL insn. 1360*55f5292cSFrank Van Der Linden * 1361*55f5292cSFrank Van Der Linden * data[0] = %eax 1362*55f5292cSFrank Van Der Linden */ 1363*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_HVM_VMMCALL, data[0]); 1364*55f5292cSFrank Van Der Linden break; 1365*55f5292cSFrank Van Der Linden case TRC_HVM_HLT: 1366*55f5292cSFrank Van Der Linden /* 1367*55f5292cSFrank Van Der Linden * HLT insn. 1368*55f5292cSFrank Van Der Linden * 1369*55f5292cSFrank Van Der Linden * data[0] = 1 if VCPU runnable, 0 if not 1370*55f5292cSFrank Van Der Linden */ 1371*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_HVM_HLT, data[0]); 1372*55f5292cSFrank Van Der Linden break; 1373*55f5292cSFrank Van Der Linden case TRC_HVM_INVLPG64: 1374*55f5292cSFrank Van Der Linden /* 1375*55f5292cSFrank Van Der Linden * 1376*55f5292cSFrank Van Der Linden * data[0] = INVLPGA ? 1 : 0 1377*55f5292cSFrank Van Der Linden * data[1] = vaddr(0:31) 1378*55f5292cSFrank Van Der Linden * data[2] = vaddr(32:63) 1379*55f5292cSFrank Van Der Linden */ 1380*55f5292cSFrank Van Der Linden addr64 = (((uint64_t)data[2]) << 32) | data[1]; 1381*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_HVM_INVLPG, data[0], addr64); 1382*55f5292cSFrank Van Der Linden break; 1383*55f5292cSFrank Van Der Linden case TRC_HVM_INVLPG: 1384*55f5292cSFrank Van Der Linden /* 1385*55f5292cSFrank Van Der Linden * unused (32-bit Xen only) 1386*55f5292cSFrank Van Der Linden * 1387*55f5292cSFrank Van Der Linden * data[0] = (domid<<16 + vcpuid) 1388*55f5292cSFrank Van Der Linden */ 1389*55f5292cSFrank Van Der Linden break; 1390*55f5292cSFrank Van Der Linden case TRC_HVM_MCE: 1391*55f5292cSFrank Van Der Linden /* 1392*55f5292cSFrank Van Der Linden * #MCE VMEXIT 1393*55f5292cSFrank Van Der Linden * 1394*55f5292cSFrank Van Der Linden */ 1395*55f5292cSFrank Van Der Linden XDT_PROBE0(XDT_HVM_MCE); 1396*55f5292cSFrank Van Der Linden break; 1397*55f5292cSFrank Van Der Linden case TRC_HVM_IOPORT_READ: 1398*55f5292cSFrank Van Der Linden case TRC_HVM_IOPORT_WRITE: 1399*55f5292cSFrank Van Der Linden case TRC_HVM_IOMEM_READ: 1400*55f5292cSFrank Van Der Linden case TRC_HVM_IOMEM_WRITE: 1401*55f5292cSFrank Van Der Linden /* 1402*55f5292cSFrank Van Der Linden * data[0] = addr(0:31) 1403*55f5292cSFrank Van Der Linden * data[1] = addr(32:63) 1404*55f5292cSFrank Van Der Linden * data[2] = count 1405*55f5292cSFrank Van Der Linden * data[3] = size 1406*55f5292cSFrank Van Der Linden */ 1407*55f5292cSFrank Van Der Linden switch (rec->event) { 1408*55f5292cSFrank Van Der Linden case TRC_HVM_IOPORT_READ: 1409*55f5292cSFrank Van Der Linden eid = XDT_HVM_IOPORT_READ; 1410*55f5292cSFrank Van Der Linden break; 1411*55f5292cSFrank Van Der Linden case TRC_HVM_IOPORT_WRITE: 1412*55f5292cSFrank Van Der Linden eid = XDT_HVM_IOPORT_WRITE; 1413*55f5292cSFrank Van Der Linden break; 1414*55f5292cSFrank Van Der Linden case TRC_HVM_IOMEM_READ: 1415*55f5292cSFrank Van Der Linden eid = XDT_HVM_IOMEM_READ; 1416*55f5292cSFrank Van Der Linden break; 1417*55f5292cSFrank Van Der Linden case TRC_HVM_IOMEM_WRITE: 1418*55f5292cSFrank Van Der Linden eid = XDT_HVM_IOMEM_WRITE; 1419*55f5292cSFrank Van Der Linden break; 1420*55f5292cSFrank Van Der Linden } 1421*55f5292cSFrank Van Der Linden addr64 = (((uint64_t)data[1]) << 32) | data[0]; 1422*55f5292cSFrank Van Der Linden XDT_PROBE3(eid, addr64, data[2], data[3]); 1423*55f5292cSFrank Van Der Linden break; 1424*55f5292cSFrank Van Der Linden case TRC_HVM_CLTS: 1425*55f5292cSFrank Van Der Linden /* 1426*55f5292cSFrank Van Der Linden * CLTS insn (Intel VMX only) 1427*55f5292cSFrank Van Der Linden */ 1428*55f5292cSFrank Van Der Linden XDT_PROBE0(XDT_HVM_CLTS); 1429*55f5292cSFrank Van Der Linden break; 1430*55f5292cSFrank Van Der Linden case TRC_HVM_LMSW64: 1431*55f5292cSFrank Van Der Linden /* 1432*55f5292cSFrank Van Der Linden * LMSW insn. 1433*55f5292cSFrank Van Der Linden * 1434*55f5292cSFrank Van Der Linden * data[0] = value(0:31) 1435*55f5292cSFrank Van Der Linden * data[1] = value(32:63) 1436*55f5292cSFrank Van Der Linden */ 1437*55f5292cSFrank Van Der Linden val64 = (((uint64_t)data[1]) << 32) | data[0]; 1438*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_HVM_LMSW, val64); 1439*55f5292cSFrank Van Der Linden break; 1440*55f5292cSFrank Van Der Linden case TRC_HVM_LMSW: 1441*55f5292cSFrank Van Der Linden /* 1442*55f5292cSFrank Van Der Linden * unused (32-bit Xen only) 1443*55f5292cSFrank Van Der Linden */ 1444*55f5292cSFrank Van Der Linden break; 1445*55f5292cSFrank Van Der Linden 1446*55f5292cSFrank Van Der Linden /* 1447*55f5292cSFrank Van Der Linden * Shadow page table probes (mainly used for HVM domains 1448*55f5292cSFrank Van Der Linden * without hardware paging support). 1449*55f5292cSFrank Van Der Linden */ 1450*55f5292cSFrank Van Der Linden case TRC_SHADOW_NOT_SHADOW | SH_GUEST_32: 1451*55f5292cSFrank Van Der Linden /* 1452*55f5292cSFrank Van Der Linden * data[0] = pte(0:31) 1453*55f5292cSFrank Van Der Linden * data[1] = pte(32:63) 1454*55f5292cSFrank Van Der Linden * data[2] = va 1455*55f5292cSFrank Van Der Linden * data[3] = flags 1456*55f5292cSFrank Van Der Linden */ 1457*55f5292cSFrank Van Der Linden pte64 = ((uint64_t)data[1] << 32) | data[0]; 1458*55f5292cSFrank Van Der Linden XDT_PROBE3(XDT_SHADOW_NOT_SHADOW, pte64, data[2], data[3]); 1459*55f5292cSFrank Van Der Linden break; 1460*55f5292cSFrank Van Der Linden case TRC_SHADOW_NOT_SHADOW | SH_GUEST_PAE: 1461*55f5292cSFrank Van Der Linden case TRC_SHADOW_NOT_SHADOW | SH_GUEST_64: 1462*55f5292cSFrank Van Der Linden /* 1463*55f5292cSFrank Van Der Linden * data[0] = pte(0:31) 1464*55f5292cSFrank Van Der Linden * data[1] = pte(32:63) 1465*55f5292cSFrank Van Der Linden * data[2] = va(0:31) 1466*55f5292cSFrank Van Der Linden * data[3] = va(32:63) 1467*55f5292cSFrank Van Der Linden * data[4] = flags 1468*55f5292cSFrank Van Der Linden */ 1469*55f5292cSFrank Van Der Linden addr64 = ((uint64_t)data[2] << 32) | data[3]; 1470*55f5292cSFrank Van Der Linden pte64 = ((uint64_t)data[1] << 32) | data[0]; 1471*55f5292cSFrank Van Der Linden XDT_PROBE3(XDT_SHADOW_NOT_SHADOW, pte64, addr64, data[4]); 1472*55f5292cSFrank Van Der Linden break; 1473*55f5292cSFrank Van Der Linden case TRC_SHADOW_FAST_PROPAGATE | SH_GUEST_32: 1474*55f5292cSFrank Van Der Linden /* 1475*55f5292cSFrank Van Der Linden * data[0] = va 1476*55f5292cSFrank Van Der Linden */ 1477*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_SHADOW_FAST_PROPAGATE, data[0]); 1478*55f5292cSFrank Van Der Linden break; 1479*55f5292cSFrank Van Der Linden case TRC_SHADOW_FAST_PROPAGATE | SH_GUEST_PAE: 1480*55f5292cSFrank Van Der Linden case TRC_SHADOW_FAST_PROPAGATE | SH_GUEST_64: 1481*55f5292cSFrank Van Der Linden /* 1482*55f5292cSFrank Van Der Linden * data[0] = va(0:31) 1483*55f5292cSFrank Van Der Linden * data[1] = va(32:63) 1484*55f5292cSFrank Van Der Linden */ 1485*55f5292cSFrank Van Der Linden addr64 = ((uint64_t)data[1] << 32) | data[0]; 1486*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_SHADOW_FAST_PROPAGATE, addr64); 1487*55f5292cSFrank Van Der Linden break; 1488*55f5292cSFrank Van Der Linden case TRC_SHADOW_FAST_MMIO | SH_GUEST_32: 1489*55f5292cSFrank Van Der Linden /* 1490*55f5292cSFrank Van Der Linden * data[0] = va 1491*55f5292cSFrank Van Der Linden */ 1492*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_SHADOW_FAST_MMIO, data[0]); 1493*55f5292cSFrank Van Der Linden break; 1494*55f5292cSFrank Van Der Linden case TRC_SHADOW_FAST_MMIO | SH_GUEST_PAE: 1495*55f5292cSFrank Van Der Linden case TRC_SHADOW_FAST_MMIO | SH_GUEST_64: 1496*55f5292cSFrank Van Der Linden /* 1497*55f5292cSFrank Van Der Linden * data[0] = va(0:31) 1498*55f5292cSFrank Van Der Linden * data[1] = va(32:63) 1499*55f5292cSFrank Van Der Linden */ 1500*55f5292cSFrank Van Der Linden addr64 = ((uint64_t)data[1] << 32) | data[0]; 1501*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_SHADOW_FAST_MMIO, addr64); 1502*55f5292cSFrank Van Der Linden break; 1503*55f5292cSFrank Van Der Linden case TRC_SHADOW_FALSE_FAST_PATH | SH_GUEST_32: 1504*55f5292cSFrank Van Der Linden /* 1505*55f5292cSFrank Van Der Linden * data[0] = va 1506*55f5292cSFrank Van Der Linden */ 1507*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_SHADOW_FALSE_FAST_PATH, data[0]); 1508*55f5292cSFrank Van Der Linden break; 1509*55f5292cSFrank Van Der Linden case TRC_SHADOW_FALSE_FAST_PATH | SH_GUEST_PAE: 1510*55f5292cSFrank Van Der Linden case TRC_SHADOW_FALSE_FAST_PATH | SH_GUEST_64: 1511*55f5292cSFrank Van Der Linden /* 1512*55f5292cSFrank Van Der Linden * data[0] = va(0:31) 1513*55f5292cSFrank Van Der Linden * data[1] = va(32:63) 1514*55f5292cSFrank Van Der Linden */ 1515*55f5292cSFrank Van Der Linden addr64 = ((uint64_t)data[1] << 32) | data[0]; 1516*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_SHADOW_FALSE_FAST_PATH, addr64); 1517*55f5292cSFrank Van Der Linden break; 1518*55f5292cSFrank Van Der Linden case TRC_SHADOW_MMIO | SH_GUEST_32: 1519*55f5292cSFrank Van Der Linden /* 1520*55f5292cSFrank Van Der Linden * data[0] = va 1521*55f5292cSFrank Van Der Linden */ 1522*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_SHADOW_MMIO, data[0]); 1523*55f5292cSFrank Van Der Linden break; 1524*55f5292cSFrank Van Der Linden case TRC_SHADOW_MMIO | SH_GUEST_PAE: 1525*55f5292cSFrank Van Der Linden case TRC_SHADOW_MMIO | SH_GUEST_64: 1526*55f5292cSFrank Van Der Linden /* 1527*55f5292cSFrank Van Der Linden * data[0] = va(0:31) 1528*55f5292cSFrank Van Der Linden * data[1] = va(32:63) 1529*55f5292cSFrank Van Der Linden */ 1530*55f5292cSFrank Van Der Linden addr64 = ((uint64_t)data[1] << 32) | data[0]; 1531*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_SHADOW_MMIO, addr64); 1532*55f5292cSFrank Van Der Linden break; 1533*55f5292cSFrank Van Der Linden case TRC_SHADOW_FIXUP | SH_GUEST_32: 1534*55f5292cSFrank Van Der Linden /* 1535*55f5292cSFrank Van Der Linden * data[0] = pte(0:31) 1536*55f5292cSFrank Van Der Linden * data[1] = pte(32:63) 1537*55f5292cSFrank Van Der Linden * data[2] = va 1538*55f5292cSFrank Van Der Linden * data[3] = flags 1539*55f5292cSFrank Van Der Linden */ 1540*55f5292cSFrank Van Der Linden pte64 = ((uint64_t)data[1] << 32) | data[0]; 1541*55f5292cSFrank Van Der Linden XDT_PROBE3(XDT_SHADOW_FIXUP, pte64, data[2], data[3]); 1542*55f5292cSFrank Van Der Linden break; 1543*55f5292cSFrank Van Der Linden case TRC_SHADOW_FIXUP | SH_GUEST_64: 1544*55f5292cSFrank Van Der Linden case TRC_SHADOW_FIXUP | SH_GUEST_PAE: 1545*55f5292cSFrank Van Der Linden /* 1546*55f5292cSFrank Van Der Linden * data[0] = pte(0:31) 1547*55f5292cSFrank Van Der Linden * data[1] = pte(32:63) 1548*55f5292cSFrank Van Der Linden * data[2] = va(0:31) 1549*55f5292cSFrank Van Der Linden * data[3] = va(32:63) 1550*55f5292cSFrank Van Der Linden * data[4] = flags 1551*55f5292cSFrank Van Der Linden */ 1552*55f5292cSFrank Van Der Linden addr64 = ((uint64_t)data[2] << 32) | data[3]; 1553*55f5292cSFrank Van Der Linden pte64 = ((uint64_t)data[1] << 32) | data[0]; 1554*55f5292cSFrank Van Der Linden XDT_PROBE3(XDT_SHADOW_FIXUP, pte64, addr64, data[4]); 1555*55f5292cSFrank Van Der Linden break; 1556*55f5292cSFrank Van Der Linden case TRC_SHADOW_DOMF_DYING | SH_GUEST_32: 1557*55f5292cSFrank Van Der Linden /* 1558*55f5292cSFrank Van Der Linden * data[0] = va 1559*55f5292cSFrank Van Der Linden */ 1560*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_SHADOW_DOMF_DYING, data[0]); 1561*55f5292cSFrank Van Der Linden break; 1562*55f5292cSFrank Van Der Linden case TRC_SHADOW_DOMF_DYING | SH_GUEST_PAE: 1563*55f5292cSFrank Van Der Linden case TRC_SHADOW_DOMF_DYING | SH_GUEST_64: 1564*55f5292cSFrank Van Der Linden /* 1565*55f5292cSFrank Van Der Linden * data[0] = va(0:31) 1566*55f5292cSFrank Van Der Linden * data[1] = va(32:63) 1567*55f5292cSFrank Van Der Linden */ 1568*55f5292cSFrank Van Der Linden addr64 = ((uint64_t)data[1] << 32) | data[0]; 1569*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_SHADOW_DOMF_DYING, addr64); 1570*55f5292cSFrank Van Der Linden break; 1571*55f5292cSFrank Van Der Linden case TRC_SHADOW_EMULATE | SH_GUEST_32: 1572*55f5292cSFrank Van Der Linden /* 1573*55f5292cSFrank Van Der Linden * data[0] = pte(0:31) 1574*55f5292cSFrank Van Der Linden * data[1] = pte(32:63) 1575*55f5292cSFrank Van Der Linden * data[2] = val(0:31) 1576*55f5292cSFrank Van Der Linden * data[3] = val(32:63) 1577*55f5292cSFrank Van Der Linden * data[4] = addr 1578*55f5292cSFrank Van Der Linden * data[5] = flags 1579*55f5292cSFrank Van Der Linden */ 1580*55f5292cSFrank Van Der Linden pte64 = ((uint64_t)data[1] << 32) | data[0]; 1581*55f5292cSFrank Van Der Linden val64 = ((uint64_t)data[3] << 32) | data[2]; 1582*55f5292cSFrank Van Der Linden XDT_PROBE5(XDT_SHADOW_EMULATE, pte64, val64, data[4], 1583*55f5292cSFrank Van Der Linden data[5] & 0x7fffffff, data[5] >> 29); 1584*55f5292cSFrank Van Der Linden break; 1585*55f5292cSFrank Van Der Linden case TRC_SHADOW_EMULATE | SH_GUEST_PAE: 1586*55f5292cSFrank Van Der Linden case TRC_SHADOW_EMULATE | SH_GUEST_64: 1587*55f5292cSFrank Van Der Linden /* 1588*55f5292cSFrank Van Der Linden * data[0] = pte(0:31) 1589*55f5292cSFrank Van Der Linden * data[1] = pte(32:63) 1590*55f5292cSFrank Van Der Linden * data[2] = val(0:31) 1591*55f5292cSFrank Van Der Linden * data[3] = val(32:63) 1592*55f5292cSFrank Van Der Linden * data[4] = addr(0:31) 1593*55f5292cSFrank Van Der Linden * data[5] = addr(32:63) 1594*55f5292cSFrank Van Der Linden * data[6] = flags 1595*55f5292cSFrank Van Der Linden */ 1596*55f5292cSFrank Van Der Linden pte64 = ((uint64_t)data[1] << 32) | data[0]; 1597*55f5292cSFrank Van Der Linden val64 = ((uint64_t)data[3] << 32) | data[2]; 1598*55f5292cSFrank Van Der Linden addr64 = ((uint64_t)data[5] << 32) | data[4]; 1599*55f5292cSFrank Van Der Linden XDT_PROBE5(XDT_SHADOW_EMULATE, pte64, val64, data[4], 1600*55f5292cSFrank Van Der Linden data[6] & 0x7fffffff, data[6] >> 29); 1601*55f5292cSFrank Van Der Linden break; 1602*55f5292cSFrank Van Der Linden case TRC_SHADOW_EMULATE_UNSHADOW_USER | SH_GUEST_32: 1603*55f5292cSFrank Van Der Linden /* 1604*55f5292cSFrank Van Der Linden * data[0] = gfn 1605*55f5292cSFrank Van Der Linden * data[1] = vaddr 1606*55f5292cSFrank Van Der Linden */ 1607*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_USER, data[0], data[1]); 1608*55f5292cSFrank Van Der Linden break; 1609*55f5292cSFrank Van Der Linden case TRC_SHADOW_EMULATE_UNSHADOW_USER | SH_GUEST_PAE: 1610*55f5292cSFrank Van Der Linden case TRC_SHADOW_EMULATE_UNSHADOW_USER | SH_GUEST_64: 1611*55f5292cSFrank Van Der Linden /* 1612*55f5292cSFrank Van Der Linden * data[0] = gfn(0:31) 1613*55f5292cSFrank Van Der Linden * data[1] = gfn(32:63) 1614*55f5292cSFrank Van Der Linden * data[2] = vaddr(0:31) 1615*55f5292cSFrank Van Der Linden * data[3] = vaddr(32:63) 1616*55f5292cSFrank Van Der Linden */ 1617*55f5292cSFrank Van Der Linden val64 = ((uint64_t)data[1] << 32) | data[0]; 1618*55f5292cSFrank Van Der Linden addr64 = ((uint64_t)data[3] << 32) | data[2]; 1619*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_USER, val64, addr64); 1620*55f5292cSFrank Van Der Linden break; 1621*55f5292cSFrank Van Der Linden case TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ | SH_GUEST_32: 1622*55f5292cSFrank Van Der Linden /* 1623*55f5292cSFrank Van Der Linden * data[0] = gfn 1624*55f5292cSFrank Van Der Linden * data[1] = vaddr 1625*55f5292cSFrank Van Der Linden */ 1626*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ, data[0], 1627*55f5292cSFrank Van Der Linden data[1]); 1628*55f5292cSFrank Van Der Linden break; 1629*55f5292cSFrank Van Der Linden case TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ | SH_GUEST_PAE: 1630*55f5292cSFrank Van Der Linden case TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ | SH_GUEST_64: 1631*55f5292cSFrank Van Der Linden /* 1632*55f5292cSFrank Van Der Linden * data[0] = gfn(0:31) 1633*55f5292cSFrank Van Der Linden * data[1] = gfn(32:63) 1634*55f5292cSFrank Van Der Linden * data[2] = vaddr(0:31) 1635*55f5292cSFrank Van Der Linden * data[3] = vaddr(32:63) 1636*55f5292cSFrank Van Der Linden */ 1637*55f5292cSFrank Van Der Linden val64 = ((uint64_t)data[1] << 32) | data[0]; 1638*55f5292cSFrank Van Der Linden addr64 = ((uint64_t)data[3] << 32) | data[2]; 1639*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ, val64, addr64); 1640*55f5292cSFrank Van Der Linden break; 1641*55f5292cSFrank Van Der Linden case TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED | SH_GUEST_32: 1642*55f5292cSFrank Van Der Linden /* 1643*55f5292cSFrank Van Der Linden * data[0] = gfn 1644*55f5292cSFrank Van Der Linden * data[1] = vaddr 1645*55f5292cSFrank Van Der Linden */ 1646*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED, data[0], 1647*55f5292cSFrank Van Der Linden data[1]); 1648*55f5292cSFrank Van Der Linden break; 1649*55f5292cSFrank Van Der Linden case TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED | SH_GUEST_PAE: 1650*55f5292cSFrank Van Der Linden case TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED | SH_GUEST_64: 1651*55f5292cSFrank Van Der Linden /* 1652*55f5292cSFrank Van Der Linden * data[0] = gfn(0:31) 1653*55f5292cSFrank Van Der Linden * data[1] = gfn(32:63) 1654*55f5292cSFrank Van Der Linden * data[2] = vaddr(0:31) 1655*55f5292cSFrank Van Der Linden * data[3] = vaddr(32:63) 1656*55f5292cSFrank Van Der Linden */ 1657*55f5292cSFrank Van Der Linden val64 = ((uint64_t)data[1] << 32) | data[0]; 1658*55f5292cSFrank Van Der Linden addr64 = ((uint64_t)data[3] << 32) | data[2]; 1659*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED, val64, 1660*55f5292cSFrank Van Der Linden addr64); 1661*55f5292cSFrank Van Der Linden break; 1662*55f5292cSFrank Van Der Linden case TRC_SHADOW_WRMAP_BF: 1663*55f5292cSFrank Van Der Linden /* 1664*55f5292cSFrank Van Der Linden * data[0] = gfn(0:31) 1665*55f5292cSFrank Van Der Linden * data[1] = gfn(32:63) 1666*55f5292cSFrank Van Der Linden */ 1667*55f5292cSFrank Van Der Linden val64 = ((uint64_t)data[1] << 32) | data[0]; 1668*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_SHADOW_WRMAP_BF, val64); 1669*55f5292cSFrank Van Der Linden break; 1670*55f5292cSFrank Van Der Linden case TRC_SHADOW_PREALLOC_UNPIN: 1671*55f5292cSFrank Van Der Linden /* 1672*55f5292cSFrank Van Der Linden * data[0] = gfn(0:31) 1673*55f5292cSFrank Van Der Linden * data[1] = gfn(32:63) 1674*55f5292cSFrank Van Der Linden */ 1675*55f5292cSFrank Van Der Linden val64 = ((uint64_t)data[1] << 32) | data[0]; 1676*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_SHADOW_PREALLOC_UNPIN, val64); 1677*55f5292cSFrank Van Der Linden break; 1678*55f5292cSFrank Van Der Linden case TRC_SHADOW_RESYNC_FULL: 1679*55f5292cSFrank Van Der Linden /* 1680*55f5292cSFrank Van Der Linden * data[0] = gmfn(0:31) 1681*55f5292cSFrank Van Der Linden * data[1] = gmfn(32:63) 1682*55f5292cSFrank Van Der Linden */ 1683*55f5292cSFrank Van Der Linden val64 = ((uint64_t)data[1] << 32) | data[0]; 1684*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_SHADOW_RESYNC_FULL, val64); 1685*55f5292cSFrank Van Der Linden break; 1686*55f5292cSFrank Van Der Linden case TRC_SHADOW_RESYNC_ONLY: 1687*55f5292cSFrank Van Der Linden /* 1688*55f5292cSFrank Van Der Linden * data[0] = gmfn(0:31) 1689*55f5292cSFrank Van Der Linden * data[1] = gmfn(32:63) 1690*55f5292cSFrank Van Der Linden */ 1691*55f5292cSFrank Van Der Linden val64 = ((uint64_t)data[1] << 32) | data[0]; 1692*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_SHADOW_RESYNC_ONLY, val64); 1693*55f5292cSFrank Van Der Linden break; 1694*55f5292cSFrank Van Der Linden 1695*55f5292cSFrank Van Der Linden /* 1696*55f5292cSFrank Van Der Linden * Power management probes. 1697*55f5292cSFrank Van Der Linden */ 1698*55f5292cSFrank Van Der Linden case TRC_PM_FREQ_CHANGE: 1699*55f5292cSFrank Van Der Linden /* 1700*55f5292cSFrank Van Der Linden * data[0] = old freq 1701*55f5292cSFrank Van Der Linden * data[1] = new freq 1702*55f5292cSFrank Van Der Linden */ 1703*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_PM_FREQ_CHANGE, data[0], data[1]); 1704*55f5292cSFrank Van Der Linden break; 1705*55f5292cSFrank Van Der Linden case TRC_PM_IDLE_ENTRY: 1706*55f5292cSFrank Van Der Linden /* 1707*55f5292cSFrank Van Der Linden * data[0] = C-state 1708*55f5292cSFrank Van Der Linden * data[1] = time 1709*55f5292cSFrank Van Der Linden */ 1710*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_PM_IDLE_ENTRY, data[0], data[1]); 1711*55f5292cSFrank Van Der Linden break; 1712*55f5292cSFrank Van Der Linden case TRC_PM_IDLE_EXIT: 1713*55f5292cSFrank Van Der Linden /* 1714*55f5292cSFrank Van Der Linden * data[0] = C-state 1715*55f5292cSFrank Van Der Linden * data[1] = time 1716*55f5292cSFrank Van Der Linden */ 1717*55f5292cSFrank Van Der Linden XDT_PROBE2(XDT_PM_IDLE_EXIT, data[0], data[1]); 1718*55f5292cSFrank Van Der Linden break; 1719c7158ae9Stariq case TRC_LOST_RECORDS: 1720*55f5292cSFrank Van Der Linden vcpu = data[1] >> 16; 1721*55f5292cSFrank Van Der Linden dom = data[1] & 0xffff; 1722*55f5292cSFrank Van Der Linden xdt_update_sched_context(cpuid, dom, vcpu); 1723*55f5292cSFrank Van Der Linden xdt_update_domain_context(dom, vcpu); 1724*55f5292cSFrank Van Der Linden XDT_PROBE1(XDT_TRC_LOST_RECORDS, cpuid); 1725c7158ae9Stariq tbuf.stat_dropped_recs++; 1726c7158ae9Stariq break; 1727c7158ae9Stariq 1728c7158ae9Stariq default: 1729c7158ae9Stariq tbuf.stat_unknown_recs++; 1730c7158ae9Stariq break; 1731c7158ae9Stariq } 1732349b53ddSStuart Maybee 1733349b53ddSStuart Maybee done: 1734349b53ddSStuart Maybee rec_size = 4 + (rec->cycles_included ? 8 : 0) + (rec->extra_u32 * 4); 1735349b53ddSStuart Maybee return (rec_size); 1736c7158ae9Stariq } 1737c7158ae9Stariq 1738*55f5292cSFrank Van Der Linden /* 1739*55f5292cSFrank Van Der Linden * Scan all CPU buffers for the record with the lowest timestamp so 1740*55f5292cSFrank Van Der Linden * that the probes will fire in order. 1741*55f5292cSFrank Van Der Linden */ 1742*55f5292cSFrank Van Der Linden static int 1743*55f5292cSFrank Van Der Linden xdt_get_first_rec(uint_t *cpuidp, struct t_rec **recp, uint32_t *consp) 1744c7158ae9Stariq { 1745c7158ae9Stariq uint_t cpuid; 1746*55f5292cSFrank Van Der Linden uint32_t prod, cons, offset; 1747c7158ae9Stariq struct t_rec *rec; 1748*55f5292cSFrank Van Der Linden uint64_t minstamp = ~0ULL, stamp; 1749349b53ddSStuart Maybee uintptr_t data; 1750c7158ae9Stariq 1751c7158ae9Stariq for (cpuid = 0; cpuid < tbuf.cnt; cpuid++) { 1752349b53ddSStuart Maybee cons = tbuf.meta[cpuid]->cons; 1753c7158ae9Stariq prod = tbuf.meta[cpuid]->prod; 1754*55f5292cSFrank Van Der Linden membar_consumer(); 1755349b53ddSStuart Maybee if (prod == cons) 1756349b53ddSStuart Maybee continue; 1757349b53ddSStuart Maybee 1758349b53ddSStuart Maybee offset = cons % tbuf_data_size; 1759349b53ddSStuart Maybee data = (uintptr_t)tbuf.data[cpuid] + offset; 1760349b53ddSStuart Maybee rec = (struct t_rec *)data; 1761*55f5292cSFrank Van Der Linden ASSERT((caddr_t)rec < tbuf.va + (tbuf.size * (cpuid + 1))); 1762*55f5292cSFrank Van Der Linden 1763*55f5292cSFrank Van Der Linden /* 1764*55f5292cSFrank Van Der Linden * All records that we know about have time cycles included. 1765*55f5292cSFrank Van Der Linden * If this record doesn't have them, assume it's a type 1766*55f5292cSFrank Van Der Linden * that we don't handle. Use a 0 time value, which will make 1767*55f5292cSFrank Van Der Linden * it get handled first (it will be thrown away). 1768*55f5292cSFrank Van Der Linden */ 1769*55f5292cSFrank Van Der Linden if (rec->cycles_included) 1770*55f5292cSFrank Van Der Linden stamp = (((uint64_t)rec->u.cycles.cycles_hi) << 32) 1771*55f5292cSFrank Van Der Linden | rec->u.cycles.cycles_lo; 1772*55f5292cSFrank Van Der Linden else 1773*55f5292cSFrank Van Der Linden stamp = 0; 1774*55f5292cSFrank Van Der Linden 1775*55f5292cSFrank Van Der Linden if (stamp < minstamp) { 1776*55f5292cSFrank Van Der Linden minstamp = stamp; 1777*55f5292cSFrank Van Der Linden *cpuidp = cpuid; 1778*55f5292cSFrank Van Der Linden *recp = rec; 1779*55f5292cSFrank Van Der Linden *consp = cons; 1780c7158ae9Stariq } 1781349b53ddSStuart Maybee } 1782349b53ddSStuart Maybee 1783*55f5292cSFrank Van Der Linden if (minstamp != ~0ULL) 1784*55f5292cSFrank Van Der Linden return (1); 1785*55f5292cSFrank Van Der Linden 1786*55f5292cSFrank Van Der Linden return (0); 1787349b53ddSStuart Maybee } 1788349b53ddSStuart Maybee 1789*55f5292cSFrank Van Der Linden /*ARGSUSED*/ 1790*55f5292cSFrank Van Der Linden static void 1791*55f5292cSFrank Van Der Linden xdt_tbuf_scan(void *arg) 1792*55f5292cSFrank Van Der Linden { 1793*55f5292cSFrank Van Der Linden uint32_t bytes_done, cons; 1794*55f5292cSFrank Van Der Linden struct t_rec *rec; 1795*55f5292cSFrank Van Der Linden xdt_schedinfo_t *sp; 1796*55f5292cSFrank Van Der Linden uint_t nrecs, cpuid; 1797*55f5292cSFrank Van Der Linden 1798*55f5292cSFrank Van Der Linden for (nrecs = 0; 1799*55f5292cSFrank Van Der Linden nrecs < xdt_max_recs && xdt_get_first_rec(&cpuid, &rec, &cons) > 0; 1800*55f5292cSFrank Van Der Linden nrecs++) { 1801*55f5292cSFrank Van Der Linden xdt_curpcpu = cpuid; 1802*55f5292cSFrank Van Der Linden sp = &xdt_cpu_schedinfo[cpuid]; 1803*55f5292cSFrank Van Der Linden if (sp->curinfo_valid) 1804*55f5292cSFrank Van Der Linden xdt_update_domain_context(sp->cur_domid, 1805*55f5292cSFrank Van Der Linden sp->cur_vcpuid); 1806*55f5292cSFrank Van Der Linden 1807*55f5292cSFrank Van Der Linden bytes_done = xdt_process_rec(cpuid, rec); 1808*55f5292cSFrank Van Der Linden cons += bytes_done; 1809*55f5292cSFrank Van Der Linden /* 1810*55f5292cSFrank Van Der Linden * cons and prod are incremented modulo (2 * tbuf_data_size). 1811*55f5292cSFrank Van Der Linden * See <xen/public/trace.h>. 1812*55f5292cSFrank Van Der Linden */ 1813*55f5292cSFrank Van Der Linden if (cons >= 2 * tbuf_data_size) 1814*55f5292cSFrank Van Der Linden cons -= 2 * tbuf_data_size; 1815*55f5292cSFrank Van Der Linden membar_exit(); 1816*55f5292cSFrank Van Der Linden tbuf.meta[cpuid]->cons = cons; 1817c7158ae9Stariq } 1818c7158ae9Stariq } 1819c7158ae9Stariq 1820c7158ae9Stariq static void 1821c7158ae9Stariq xdt_cyclic_enable(void) 1822c7158ae9Stariq { 1823c7158ae9Stariq cyc_handler_t hdlr; 1824c7158ae9Stariq cyc_time_t when; 1825c7158ae9Stariq 1826c7158ae9Stariq ASSERT(MUTEX_HELD(&cpu_lock)); 1827c7158ae9Stariq 1828c7158ae9Stariq hdlr.cyh_func = xdt_tbuf_scan; 1829c7158ae9Stariq hdlr.cyh_arg = NULL; 1830c7158ae9Stariq hdlr.cyh_level = CY_LOW_LEVEL; 1831c7158ae9Stariq 1832c7158ae9Stariq when.cyt_interval = xdt_poll_nsec; 1833c7158ae9Stariq when.cyt_when = dtrace_gethrtime() + when.cyt_interval; 1834c7158ae9Stariq 1835c7158ae9Stariq xdt_cyclic = cyclic_add(&hdlr, &when); 1836c7158ae9Stariq } 1837c7158ae9Stariq 1838c7158ae9Stariq static void 1839c7158ae9Stariq xdt_probe_create(xdt_probe_t *p) 1840c7158ae9Stariq { 1841c7158ae9Stariq ASSERT(p != NULL && p->pr_mod != NULL); 1842c7158ae9Stariq 1843c7158ae9Stariq if (dtrace_probe_lookup(xdt_id, p->pr_mod, NULL, p->pr_name) != 0) 1844c7158ae9Stariq return; 1845c7158ae9Stariq 1846c7158ae9Stariq xdt_prid[p->evt_id] = dtrace_probe_create(xdt_id, p->pr_mod, NULL, 1847c7158ae9Stariq p->pr_name, dtrace_mach_aframes(), p); 1848c7158ae9Stariq } 1849c7158ae9Stariq 1850c7158ae9Stariq /*ARGSUSED*/ 1851c7158ae9Stariq static void 1852c7158ae9Stariq xdt_provide(void *arg, const dtrace_probedesc_t *desc) 1853c7158ae9Stariq { 1854c7158ae9Stariq const char *mod, *name; 1855c7158ae9Stariq int i; 1856c7158ae9Stariq 1857c7158ae9Stariq if (desc == NULL) { 1858c7158ae9Stariq for (i = 0; xdt_probe[i].pr_mod != NULL; i++) { 1859c7158ae9Stariq xdt_probe_create(&xdt_probe[i]); 1860c7158ae9Stariq } 1861c7158ae9Stariq } else { 1862c7158ae9Stariq mod = desc->dtpd_mod; 1863c7158ae9Stariq name = desc->dtpd_name; 1864c7158ae9Stariq for (i = 0; xdt_probe[i].pr_mod != NULL; i++) { 1865c7158ae9Stariq int l1 = strlen(xdt_probe[i].pr_name); 1866c7158ae9Stariq int l2 = strlen(xdt_probe[i].pr_mod); 1867c7158ae9Stariq if (strncmp(name, xdt_probe[i].pr_name, l1) == 0 && 1868c7158ae9Stariq strncmp(mod, xdt_probe[i].pr_mod, l2) == 0) 1869c7158ae9Stariq break; 1870c7158ae9Stariq } 1871c7158ae9Stariq 1872c7158ae9Stariq if (xdt_probe[i].pr_mod == NULL) 1873c7158ae9Stariq return; 1874c7158ae9Stariq xdt_probe_create(&xdt_probe[i]); 1875c7158ae9Stariq } 1876c7158ae9Stariq 1877c7158ae9Stariq } 1878c7158ae9Stariq 1879c7158ae9Stariq /*ARGSUSED*/ 1880c7158ae9Stariq static void 1881c7158ae9Stariq xdt_destroy(void *arg, dtrace_id_t id, void *parg) 1882c7158ae9Stariq { 1883c7158ae9Stariq xdt_probe_t *p = parg; 1884c7158ae9Stariq xdt_prid[p->evt_id] = 0; 1885c7158ae9Stariq } 1886c7158ae9Stariq 1887c7158ae9Stariq static void 1888c7158ae9Stariq xdt_set_trace_mask(uint32_t mask) 1889c7158ae9Stariq { 1890c7158ae9Stariq xen_sysctl_tbuf_op_t tbuf_op; 1891c7158ae9Stariq 1892*55f5292cSFrank Van Der Linden /* Always need to trace scheduling, for context */ 1893*55f5292cSFrank Van Der Linden if (mask != 0) 1894*55f5292cSFrank Van Der Linden mask |= TRC_SCHED; 1895c7158ae9Stariq tbuf_op.evt_mask = mask; 1896*55f5292cSFrank Van Der Linden tbuf_op.cmd = XEN_SYSCTL_TBUFOP_set_evt_mask; 1897c7158ae9Stariq (void) xdt_sysctl_tbuf(&tbuf_op); 1898c7158ae9Stariq } 1899c7158ae9Stariq 1900c7158ae9Stariq /*ARGSUSED*/ 1901b9e93c10SJonathan Haslam static int 1902c7158ae9Stariq xdt_enable(void *arg, dtrace_id_t id, void *parg) 1903c7158ae9Stariq { 1904c7158ae9Stariq xdt_probe_t *p = parg; 1905c7158ae9Stariq xen_sysctl_tbuf_op_t tbuf_op; 1906c7158ae9Stariq 1907c7158ae9Stariq ASSERT(MUTEX_HELD(&cpu_lock)); 1908c7158ae9Stariq ASSERT(xdt_prid[p->evt_id] != 0); 1909c7158ae9Stariq 1910c7158ae9Stariq xdt_probemap[p->evt_id] = xdt_prid[p->evt_id]; 1911c7158ae9Stariq xdt_classinfo[p->class].cnt++; 1912c7158ae9Stariq 1913c7158ae9Stariq if (xdt_classinfo[p->class].cnt == 1) { 1914c7158ae9Stariq /* set the trace mask for this class */ 1915c7158ae9Stariq cur_trace_mask |= xdt_classinfo[p->class].trc_mask; 1916c7158ae9Stariq xdt_set_trace_mask(cur_trace_mask); 1917c7158ae9Stariq } 1918c7158ae9Stariq 1919c7158ae9Stariq if (xdt_cyclic == CYCLIC_NONE) { 1920c7158ae9Stariq tbuf_op.cmd = XEN_SYSCTL_TBUFOP_enable; 1921c7158ae9Stariq if (xdt_sysctl_tbuf(&tbuf_op) != 0) { 1922c7158ae9Stariq cmn_err(CE_NOTE, "Couldn't enable hypervisor tracing."); 1923b9e93c10SJonathan Haslam return (-1); 1924c7158ae9Stariq } 1925c7158ae9Stariq 1926c7158ae9Stariq xdt_cyclic_enable(); 1927c7158ae9Stariq } 1928b9e93c10SJonathan Haslam return (0); 1929c7158ae9Stariq } 1930c7158ae9Stariq 1931c7158ae9Stariq /*ARGSUSED*/ 1932c7158ae9Stariq static void 1933c7158ae9Stariq xdt_disable(void *arg, dtrace_id_t id, void *parg) 1934c7158ae9Stariq { 1935c7158ae9Stariq xdt_probe_t *p = parg; 1936c7158ae9Stariq xen_sysctl_tbuf_op_t tbuf_op; 1937c7158ae9Stariq int i, err; 1938c7158ae9Stariq 1939c7158ae9Stariq ASSERT(MUTEX_HELD(&cpu_lock)); 1940c7158ae9Stariq ASSERT(xdt_probemap[p->evt_id] != 0); 1941c7158ae9Stariq ASSERT(xdt_probemap[p->evt_id] == xdt_prid[p->evt_id]); 1942c7158ae9Stariq ASSERT(xdt_classinfo[p->class].cnt > 0); 1943c7158ae9Stariq 1944c7158ae9Stariq /* 1945c7158ae9Stariq * We could be here in the slight window between the cyclic firing and 1946c7158ae9Stariq * a call to dtrace_probe() occurring. We need to be careful if we tear 1947c7158ae9Stariq * down any shared state. 1948c7158ae9Stariq */ 1949c7158ae9Stariq 1950c7158ae9Stariq xdt_probemap[p->evt_id] = 0; 1951c7158ae9Stariq xdt_classinfo[p->class].cnt--; 1952c7158ae9Stariq 1953c7158ae9Stariq if (xdt_nr_active_probes() == 0) { 1954c7158ae9Stariq cur_trace_mask = 0; 1955c7158ae9Stariq 1956c7158ae9Stariq if (xdt_cyclic == CYCLIC_NONE) 1957c7158ae9Stariq return; 1958c7158ae9Stariq 1959*55f5292cSFrank Van Der Linden for (i = 0; i < xdt_ncpus; i++) 1960*55f5292cSFrank Van Der Linden xdt_cpu_schedinfo[i].curinfo_valid = 0; 1961*55f5292cSFrank Van Der Linden 1962c7158ae9Stariq /* 1963c7158ae9Stariq * We will try to disable the trace buffers. If we fail for some 1964c7158ae9Stariq * reason we will try again, up to a count of XDT_TBUF_RETRY. 1965c7158ae9Stariq * If we still aren't successful we try to set the trace mask 1966c7158ae9Stariq * to 0 in order to prevent trace records from being written. 1967c7158ae9Stariq */ 1968c7158ae9Stariq tbuf_op.cmd = XEN_SYSCTL_TBUFOP_disable; 1969c7158ae9Stariq i = 0; 1970c7158ae9Stariq do { 1971c7158ae9Stariq err = xdt_sysctl_tbuf(&tbuf_op); 1972c7158ae9Stariq } while ((err != 0) && (++i < XDT_TBUF_RETRY)); 1973c7158ae9Stariq 1974c7158ae9Stariq if (err != 0) { 1975c7158ae9Stariq cmn_err(CE_NOTE, 1976c7158ae9Stariq "Couldn't disable hypervisor tracing."); 1977c7158ae9Stariq xdt_set_trace_mask(0); 1978c7158ae9Stariq } else { 1979c7158ae9Stariq cyclic_remove(xdt_cyclic); 1980c7158ae9Stariq xdt_cyclic = CYCLIC_NONE; 1981c7158ae9Stariq /* 1982c7158ae9Stariq * We don't bother making the hypercall to set 1983c7158ae9Stariq * the trace mask, since it will be reset when 1984c7158ae9Stariq * tracing is re-enabled. 1985c7158ae9Stariq */ 1986c7158ae9Stariq } 1987c7158ae9Stariq } else if (xdt_classinfo[p->class].cnt == 0) { 1988c7158ae9Stariq cur_trace_mask ^= xdt_classinfo[p->class].trc_mask; 1989c7158ae9Stariq /* other probes are enabled, so add the sub-class mask back */ 1990c7158ae9Stariq cur_trace_mask |= 0xF000; 1991c7158ae9Stariq xdt_set_trace_mask(cur_trace_mask); 1992c7158ae9Stariq } 1993c7158ae9Stariq } 1994c7158ae9Stariq 1995c7158ae9Stariq static dtrace_pattr_t xdt_attr = { 1996c7158ae9Stariq { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM }, 1997c7158ae9Stariq { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM }, 1998c7158ae9Stariq { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, 1999c7158ae9Stariq { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM }, 2000c7158ae9Stariq { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM }, 2001c7158ae9Stariq }; 2002c7158ae9Stariq 2003c7158ae9Stariq static dtrace_pops_t xdt_pops = { 2004c7158ae9Stariq xdt_provide, /* dtps_provide() */ 2005c7158ae9Stariq NULL, /* dtps_provide_module() */ 2006c7158ae9Stariq xdt_enable, /* dtps_enable() */ 2007c7158ae9Stariq xdt_disable, /* dtps_disable() */ 2008c7158ae9Stariq NULL, /* dtps_suspend() */ 2009c7158ae9Stariq NULL, /* dtps_resume() */ 2010c7158ae9Stariq NULL, /* dtps_getargdesc() */ 2011c7158ae9Stariq NULL, /* dtps_getargval() */ 2012c7158ae9Stariq NULL, /* dtps_usermode() */ 2013c7158ae9Stariq xdt_destroy /* dtps_destroy() */ 2014c7158ae9Stariq }; 2015c7158ae9Stariq 2016c7158ae9Stariq static int 2017c7158ae9Stariq xdt_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 2018c7158ae9Stariq { 2019c7158ae9Stariq int val; 2020c7158ae9Stariq 2021c7158ae9Stariq if (!DOMAIN_IS_INITDOMAIN(xen_info)) 2022c7158ae9Stariq return (DDI_FAILURE); 2023c7158ae9Stariq 2024c7158ae9Stariq switch (cmd) { 2025c7158ae9Stariq case DDI_ATTACH: 2026c7158ae9Stariq break; 2027c7158ae9Stariq 2028c7158ae9Stariq case DDI_RESUME: 2029c7158ae9Stariq /* 2030c7158ae9Stariq * We might support proper suspend/resume in the future, so, 2031c7158ae9Stariq * return DDI_FAILURE for now. 2032c7158ae9Stariq */ 2033c7158ae9Stariq return (DDI_FAILURE); 2034c7158ae9Stariq 2035c7158ae9Stariq default: 2036c7158ae9Stariq return (DDI_FAILURE); 2037c7158ae9Stariq } 2038c7158ae9Stariq 2039349b53ddSStuart Maybee xdt_ncpus = xpv_nr_phys_cpus(); 2040c7158ae9Stariq ASSERT(xdt_ncpus > 0); 2041c7158ae9Stariq 2042c7158ae9Stariq if (ddi_create_minor_node(devi, "xdt", S_IFCHR, 0, DDI_PSEUDO, 0) == 2043c7158ae9Stariq DDI_FAILURE || xdt_attach_trace_buffers() != 0 || 2044c7158ae9Stariq dtrace_register("xdt", &xdt_attr, DTRACE_PRIV_KERNEL, NULL, 2045c7158ae9Stariq &xdt_pops, NULL, &xdt_id) != 0) { 2046c7158ae9Stariq if (tbuf.va != NULL) 2047c7158ae9Stariq xdt_detach_trace_buffers(); 2048c7158ae9Stariq ddi_remove_minor_node(devi, NULL); 2049c7158ae9Stariq return (DDI_FAILURE); 2050c7158ae9Stariq } 2051c7158ae9Stariq 2052c7158ae9Stariq val = ddi_getprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, 2053c7158ae9Stariq "xdt_poll_nsec", XDT_POLL_DEFAULT); 2054c7158ae9Stariq xdt_poll_nsec = MAX(val, XDT_POLL_MIN); 2055c7158ae9Stariq 2056*55f5292cSFrank Van Der Linden xdt_cpu_schedinfo = (xdt_schedinfo_t *)kmem_zalloc(xdt_ncpus * 2057c7158ae9Stariq sizeof (xdt_schedinfo_t), KM_SLEEP); 2058c7158ae9Stariq xdt_init_trace_masks(); 2059c7158ae9Stariq xdt_kstat_init(); 2060c7158ae9Stariq 2061c7158ae9Stariq xdt_devi = devi; 2062c7158ae9Stariq ddi_report_dev(devi); 2063c7158ae9Stariq return (DDI_SUCCESS); 2064c7158ae9Stariq } 2065c7158ae9Stariq 2066c7158ae9Stariq static int 2067c7158ae9Stariq xdt_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 2068c7158ae9Stariq { 2069c7158ae9Stariq switch (cmd) { 2070c7158ae9Stariq case DDI_DETACH: 2071c7158ae9Stariq break; 2072c7158ae9Stariq 2073c7158ae9Stariq case DDI_SUSPEND: 2074c7158ae9Stariq /* 2075c7158ae9Stariq * We might support proper suspend/resume in the future. So 2076c7158ae9Stariq * return DDI_FAILURE for now. 2077c7158ae9Stariq */ 2078c7158ae9Stariq return (DDI_FAILURE); 2079c7158ae9Stariq 2080c7158ae9Stariq default: 2081c7158ae9Stariq return (DDI_FAILURE); 2082c7158ae9Stariq } 2083c7158ae9Stariq 2084c7158ae9Stariq if (dtrace_unregister(xdt_id) != 0) 2085c7158ae9Stariq return (DDI_FAILURE); 2086c7158ae9Stariq 2087c7158ae9Stariq xdt_detach_trace_buffers(); 2088c7158ae9Stariq kmem_free(xdt_cpu_schedinfo, xdt_ncpus * sizeof (xdt_schedinfo_t)); 2089c7158ae9Stariq if (xdt_cyclic != CYCLIC_NONE) 2090c7158ae9Stariq cyclic_remove(xdt_cyclic); 2091c7158ae9Stariq if (xdt_kstats != NULL) 2092c7158ae9Stariq kstat_delete(xdt_kstats); 2093c7158ae9Stariq xdt_devi = (void *)0; 2094c7158ae9Stariq ddi_remove_minor_node(devi, NULL); 2095c7158ae9Stariq 2096c7158ae9Stariq return (DDI_SUCCESS); 2097c7158ae9Stariq } 2098c7158ae9Stariq 2099c7158ae9Stariq /*ARGSUSED*/ 2100c7158ae9Stariq static int 2101c7158ae9Stariq xdt_info(dev_info_t *devi, ddi_info_cmd_t infocmd, void *arg, void **result) 2102c7158ae9Stariq { 2103c7158ae9Stariq int error; 2104c7158ae9Stariq 2105c7158ae9Stariq switch (infocmd) { 2106c7158ae9Stariq case DDI_INFO_DEVT2DEVINFO: 2107c7158ae9Stariq *result = xdt_devi; 2108c7158ae9Stariq error = DDI_SUCCESS; 2109c7158ae9Stariq break; 2110c7158ae9Stariq case DDI_INFO_DEVT2INSTANCE: 2111c7158ae9Stariq *result = (void *)0; 2112c7158ae9Stariq error = DDI_SUCCESS; 2113c7158ae9Stariq break; 2114c7158ae9Stariq default: 2115c7158ae9Stariq error = DDI_FAILURE; 2116c7158ae9Stariq } 2117c7158ae9Stariq return (error); 2118c7158ae9Stariq } 2119c7158ae9Stariq 2120c7158ae9Stariq static struct cb_ops xdt_cb_ops = { 2121c7158ae9Stariq nulldev, /* open(9E) */ 2122c7158ae9Stariq nodev, /* close(9E) */ 2123c7158ae9Stariq nodev, /* strategy(9E) */ 2124c7158ae9Stariq nodev, /* print(9E) */ 2125c7158ae9Stariq nodev, /* dump(9E) */ 2126c7158ae9Stariq nodev, /* read(9E) */ 2127c7158ae9Stariq nodev, /* write(9E) */ 2128c7158ae9Stariq nodev, /* ioctl(9E) */ 2129c7158ae9Stariq nodev, /* devmap(9E) */ 2130c7158ae9Stariq nodev, /* mmap(9E) */ 2131c7158ae9Stariq nodev, /* segmap(9E) */ 2132c7158ae9Stariq nochpoll, /* chpoll(9E) */ 2133c7158ae9Stariq ddi_prop_op, /* prop_op(9E) */ 2134c7158ae9Stariq NULL, /* streamtab(9S) */ 2135c7158ae9Stariq D_MP | D_64BIT | D_NEW /* cb_flag */ 2136c7158ae9Stariq }; 2137c7158ae9Stariq 2138c7158ae9Stariq static struct dev_ops xdt_ops = { 2139c7158ae9Stariq DEVO_REV, /* devo_rev */ 2140c7158ae9Stariq 0, /* devo_refcnt */ 2141c7158ae9Stariq xdt_info, /* getinfo(9E) */ 2142c7158ae9Stariq nulldev, /* identify(9E) */ 2143c7158ae9Stariq nulldev, /* probe(9E) */ 2144c7158ae9Stariq xdt_attach, /* attach(9E) */ 2145c7158ae9Stariq xdt_detach, /* detach(9E) */ 2146c7158ae9Stariq nulldev, /* devo_reset */ 2147c7158ae9Stariq &xdt_cb_ops, /* devo_cb_ops */ 2148c7158ae9Stariq NULL, /* devo_bus_ops */ 214919397407SSherry Moore NULL, /* power(9E) */ 215019397407SSherry Moore ddi_quiesce_not_needed, /* devo_quiesce */ 2151c7158ae9Stariq }; 2152c7158ae9Stariq 2153c7158ae9Stariq 2154c7158ae9Stariq static struct modldrv modldrv = { 2155c7158ae9Stariq &mod_driverops, 2156c7158ae9Stariq "Hypervisor event tracing", 2157c7158ae9Stariq &xdt_ops 2158c7158ae9Stariq }; 2159c7158ae9Stariq 2160c7158ae9Stariq static struct modlinkage modlinkage = { 2161c7158ae9Stariq MODREV_1, 2162c7158ae9Stariq &modldrv, 2163c7158ae9Stariq NULL 2164c7158ae9Stariq }; 2165c7158ae9Stariq 2166c7158ae9Stariq int 2167c7158ae9Stariq _init(void) 2168c7158ae9Stariq { 2169c7158ae9Stariq return (mod_install(&modlinkage)); 2170c7158ae9Stariq } 2171c7158ae9Stariq 2172c7158ae9Stariq int 2173c7158ae9Stariq _fini(void) 2174c7158ae9Stariq { 2175c7158ae9Stariq return (mod_remove(&modlinkage)); 2176c7158ae9Stariq } 2177c7158ae9Stariq 2178c7158ae9Stariq int 2179c7158ae9Stariq _info(struct modinfo *modinfop) 2180c7158ae9Stariq { 2181c7158ae9Stariq return (mod_info(&modlinkage, modinfop)); 2182c7158ae9Stariq } 2183