xref: /xnu-10002.61.3/bsd/kern/kdebug_common.c (revision 0f4c859e951fba394238ab619495c4e1d54d0f34)
1*0f4c859eSApple OSS Distributions /*
2*0f4c859eSApple OSS Distributions  * Copyright (c) 2000-2021 Apple Inc. All rights reserved.
3*0f4c859eSApple OSS Distributions  *
4*0f4c859eSApple OSS Distributions  * @Apple_LICENSE_HEADER_START@
5*0f4c859eSApple OSS Distributions  *
6*0f4c859eSApple OSS Distributions  * The contents of this file constitute Original Code as defined in and
7*0f4c859eSApple OSS Distributions  * are subject to the Apple Public Source License Version 1.1 (the
8*0f4c859eSApple OSS Distributions  * "License").  You may not use this file except in compliance with the
9*0f4c859eSApple OSS Distributions  * License.  Please obtain a copy of the License at
10*0f4c859eSApple OSS Distributions  * http://www.apple.com/publicsource and read it before using this file.
11*0f4c859eSApple OSS Distributions  *
12*0f4c859eSApple OSS Distributions  * This Original Code and all software distributed under the License are
13*0f4c859eSApple OSS Distributions  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14*0f4c859eSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15*0f4c859eSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16*0f4c859eSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17*0f4c859eSApple OSS Distributions  * License for the specific language governing rights and limitations
18*0f4c859eSApple OSS Distributions  * under the License.
19*0f4c859eSApple OSS Distributions  *
20*0f4c859eSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
21*0f4c859eSApple OSS Distributions  */
22*0f4c859eSApple OSS Distributions 
23*0f4c859eSApple OSS Distributions #include <sys/kdebug_common.h>
24*0f4c859eSApple OSS Distributions 
25*0f4c859eSApple OSS Distributions LCK_GRP_DECLARE(kdebug_lck_grp, "kdebug");
26*0f4c859eSApple OSS Distributions int kdbg_debug = 0;
27*0f4c859eSApple OSS Distributions 
28*0f4c859eSApple OSS Distributions extern struct kd_control kd_control_trace, kd_control_triage;
29*0f4c859eSApple OSS Distributions 
30*0f4c859eSApple OSS Distributions int
kdebug_storage_lock(struct kd_control * kd_ctrl_page)31*0f4c859eSApple OSS Distributions kdebug_storage_lock(struct kd_control *kd_ctrl_page)
32*0f4c859eSApple OSS Distributions {
33*0f4c859eSApple OSS Distributions 	int intrs_en = ml_set_interrupts_enabled(false);
34*0f4c859eSApple OSS Distributions 	lck_spin_lock_grp(&kd_ctrl_page->kdc_storage_lock, &kdebug_lck_grp);
35*0f4c859eSApple OSS Distributions 	return intrs_en;
36*0f4c859eSApple OSS Distributions }
37*0f4c859eSApple OSS Distributions 
38*0f4c859eSApple OSS Distributions void
kdebug_storage_unlock(struct kd_control * kd_ctrl_page,int intrs_en)39*0f4c859eSApple OSS Distributions kdebug_storage_unlock(struct kd_control *kd_ctrl_page, int intrs_en)
40*0f4c859eSApple OSS Distributions {
41*0f4c859eSApple OSS Distributions 	lck_spin_unlock(&kd_ctrl_page->kdc_storage_lock);
42*0f4c859eSApple OSS Distributions 	ml_set_interrupts_enabled(intrs_en);
43*0f4c859eSApple OSS Distributions }
44*0f4c859eSApple OSS Distributions 
45*0f4c859eSApple OSS Distributions // Turn on boot tracing and set the number of events.
46*0f4c859eSApple OSS Distributions static TUNABLE(unsigned int, new_nkdbufs, "trace", 0);
47*0f4c859eSApple OSS Distributions // Enable wrapping during boot tracing.
48*0f4c859eSApple OSS Distributions TUNABLE(unsigned int, trace_wrap, "trace_wrap", 0);
49*0f4c859eSApple OSS Distributions // The filter description to apply to boot tracing.
50*0f4c859eSApple OSS Distributions static TUNABLE_STR(trace_typefilter, 256, "trace_typefilter", "");
51*0f4c859eSApple OSS Distributions 
52*0f4c859eSApple OSS Distributions // Turn on wake tracing and set the number of events.
53*0f4c859eSApple OSS Distributions TUNABLE(unsigned int, wake_nkdbufs, "trace_wake", 0);
54*0f4c859eSApple OSS Distributions // Write trace events to a file in the event of a panic.
55*0f4c859eSApple OSS Distributions TUNABLE(unsigned int, write_trace_on_panic, "trace_panic", 0);
56*0f4c859eSApple OSS Distributions 
57*0f4c859eSApple OSS Distributions // Obsolete leak logging system.
58*0f4c859eSApple OSS Distributions TUNABLE(int, log_leaks, "-l", 0);
59*0f4c859eSApple OSS Distributions 
60*0f4c859eSApple OSS Distributions void
kdebug_startup(void)61*0f4c859eSApple OSS Distributions kdebug_startup(void)
62*0f4c859eSApple OSS Distributions {
63*0f4c859eSApple OSS Distributions 	lck_spin_init(&kd_control_trace.kdc_storage_lock, &kdebug_lck_grp, LCK_ATTR_NULL);
64*0f4c859eSApple OSS Distributions 	lck_spin_init(&kd_control_triage.kdc_storage_lock, &kdebug_lck_grp, LCK_ATTR_NULL);
65*0f4c859eSApple OSS Distributions 	kdebug_init(new_nkdbufs, trace_typefilter,
66*0f4c859eSApple OSS Distributions 	    (trace_wrap ? KDOPT_WRAPPING : 0) | KDOPT_ATBOOT);
67*0f4c859eSApple OSS Distributions 	create_buffers_triage();
68*0f4c859eSApple OSS Distributions }
69*0f4c859eSApple OSS Distributions 
70*0f4c859eSApple OSS Distributions uint32_t
kdbg_cpu_count(void)71*0f4c859eSApple OSS Distributions kdbg_cpu_count(void)
72*0f4c859eSApple OSS Distributions {
73*0f4c859eSApple OSS Distributions #if defined(__x86_64__)
74*0f4c859eSApple OSS Distributions 	return ml_early_cpu_max_number() + 1;
75*0f4c859eSApple OSS Distributions #else // defined(__x86_64__)
76*0f4c859eSApple OSS Distributions 	return ml_get_cpu_count();
77*0f4c859eSApple OSS Distributions #endif // !defined(__x86_64__)
78*0f4c859eSApple OSS Distributions }
79*0f4c859eSApple OSS Distributions 
80*0f4c859eSApple OSS Distributions /*
81*0f4c859eSApple OSS Distributions  * Both kdebug_timestamp and kdebug_using_continuous_time are known
82*0f4c859eSApple OSS Distributions  * to kexts. And going forward we always want to use mach_continuous_time().
83*0f4c859eSApple OSS Distributions  * So we keep these 2 routines as-is to keep the TRACE mode use outside
84*0f4c859eSApple OSS Distributions  * the kernel intact. TRIAGE mode will explicitly only use mach_continuous_time()
85*0f4c859eSApple OSS Distributions  * for its timestamp.
86*0f4c859eSApple OSS Distributions  */
87*0f4c859eSApple OSS Distributions bool
kdebug_using_continuous_time(void)88*0f4c859eSApple OSS Distributions kdebug_using_continuous_time(void)
89*0f4c859eSApple OSS Distributions {
90*0f4c859eSApple OSS Distributions 	return kd_control_trace.kdc_flags & KDBG_CONTINUOUS_TIME;
91*0f4c859eSApple OSS Distributions }
92*0f4c859eSApple OSS Distributions 
93*0f4c859eSApple OSS Distributions uint64_t
kdebug_timestamp(void)94*0f4c859eSApple OSS Distributions kdebug_timestamp(void)
95*0f4c859eSApple OSS Distributions {
96*0f4c859eSApple OSS Distributions 	if (kdebug_using_continuous_time()) {
97*0f4c859eSApple OSS Distributions 		return mach_continuous_time();
98*0f4c859eSApple OSS Distributions 	} else {
99*0f4c859eSApple OSS Distributions 		return mach_absolute_time();
100*0f4c859eSApple OSS Distributions 	}
101*0f4c859eSApple OSS Distributions }
102*0f4c859eSApple OSS Distributions 
103*0f4c859eSApple OSS Distributions int
create_buffers(struct kd_control * kd_ctrl_page,struct kd_buffer * kd_data_page,vm_tag_t tag)104*0f4c859eSApple OSS Distributions create_buffers(
105*0f4c859eSApple OSS Distributions 	struct kd_control *kd_ctrl_page,
106*0f4c859eSApple OSS Distributions 	struct kd_buffer *kd_data_page,
107*0f4c859eSApple OSS Distributions 	vm_tag_t tag)
108*0f4c859eSApple OSS Distributions {
109*0f4c859eSApple OSS Distributions 	unsigned int i;
110*0f4c859eSApple OSS Distributions 	unsigned int p_buffer_size;
111*0f4c859eSApple OSS Distributions 	unsigned int f_buffer_size;
112*0f4c859eSApple OSS Distributions 	unsigned int f_buffers;
113*0f4c859eSApple OSS Distributions 	int error = 0;
114*0f4c859eSApple OSS Distributions 	int ncpus, count_storage_units = 0;
115*0f4c859eSApple OSS Distributions 
116*0f4c859eSApple OSS Distributions 	struct kd_bufinfo *kdbip = NULL;
117*0f4c859eSApple OSS Distributions 	struct kd_region *kd_bufs = NULL;
118*0f4c859eSApple OSS Distributions 	int kdb_storage_count = kd_data_page->kdb_storage_count;
119*0f4c859eSApple OSS Distributions 
120*0f4c859eSApple OSS Distributions 	ncpus = kd_ctrl_page->alloc_cpus;
121*0f4c859eSApple OSS Distributions 
122*0f4c859eSApple OSS Distributions 	kdbip = kalloc_type_tag(struct kd_bufinfo, ncpus, Z_WAITOK | Z_ZERO, tag);
123*0f4c859eSApple OSS Distributions 	if (kdbip == NULL) {
124*0f4c859eSApple OSS Distributions 		error = ENOSPC;
125*0f4c859eSApple OSS Distributions 		goto out;
126*0f4c859eSApple OSS Distributions 	}
127*0f4c859eSApple OSS Distributions 	kd_data_page->kdb_info = kdbip;
128*0f4c859eSApple OSS Distributions 
129*0f4c859eSApple OSS Distributions 	f_buffers = kdb_storage_count / N_STORAGE_UNITS_PER_BUFFER;
130*0f4c859eSApple OSS Distributions 	kd_data_page->kdb_region_count = f_buffers;
131*0f4c859eSApple OSS Distributions 
132*0f4c859eSApple OSS Distributions 	f_buffer_size = N_STORAGE_UNITS_PER_BUFFER * sizeof(struct kd_storage);
133*0f4c859eSApple OSS Distributions 	p_buffer_size = (kdb_storage_count % N_STORAGE_UNITS_PER_BUFFER) * sizeof(struct kd_storage);
134*0f4c859eSApple OSS Distributions 
135*0f4c859eSApple OSS Distributions 	if (p_buffer_size) {
136*0f4c859eSApple OSS Distributions 		kd_data_page->kdb_region_count++;
137*0f4c859eSApple OSS Distributions 	}
138*0f4c859eSApple OSS Distributions 
139*0f4c859eSApple OSS Distributions 	if (kd_data_page->kdcopybuf == 0) {
140*0f4c859eSApple OSS Distributions 		if (kmem_alloc(kernel_map, (vm_offset_t *)&kd_data_page->kdcopybuf,
141*0f4c859eSApple OSS Distributions 		    (vm_size_t) kd_ctrl_page->kdebug_kdcopybuf_size,
142*0f4c859eSApple OSS Distributions 		    KMA_DATA | KMA_ZERO, tag) != KERN_SUCCESS) {
143*0f4c859eSApple OSS Distributions 			error = ENOSPC;
144*0f4c859eSApple OSS Distributions 			goto out;
145*0f4c859eSApple OSS Distributions 		}
146*0f4c859eSApple OSS Distributions 	}
147*0f4c859eSApple OSS Distributions 
148*0f4c859eSApple OSS Distributions 	kd_bufs = kalloc_type_tag(struct kd_region, kd_data_page->kdb_region_count,
149*0f4c859eSApple OSS Distributions 	    Z_WAITOK | Z_ZERO, tag);
150*0f4c859eSApple OSS Distributions 	if (kd_bufs == NULL) {
151*0f4c859eSApple OSS Distributions 		error = ENOSPC;
152*0f4c859eSApple OSS Distributions 		goto out;
153*0f4c859eSApple OSS Distributions 	}
154*0f4c859eSApple OSS Distributions 	kd_data_page->kd_bufs = kd_bufs;
155*0f4c859eSApple OSS Distributions 
156*0f4c859eSApple OSS Distributions 	for (i = 0; i < f_buffers; i++) {
157*0f4c859eSApple OSS Distributions 		if (kmem_alloc(kernel_map, (vm_offset_t *)&kd_bufs[i].kdr_addr,
158*0f4c859eSApple OSS Distributions 		    (vm_size_t)f_buffer_size, KMA_DATA | KMA_ZERO, tag) != KERN_SUCCESS) {
159*0f4c859eSApple OSS Distributions 			error = ENOSPC;
160*0f4c859eSApple OSS Distributions 			goto out;
161*0f4c859eSApple OSS Distributions 		}
162*0f4c859eSApple OSS Distributions 
163*0f4c859eSApple OSS Distributions 		kd_bufs[i].kdr_size = f_buffer_size;
164*0f4c859eSApple OSS Distributions 	}
165*0f4c859eSApple OSS Distributions 	if (p_buffer_size) {
166*0f4c859eSApple OSS Distributions 		if (kmem_alloc(kernel_map, (vm_offset_t *)&kd_bufs[i].kdr_addr,
167*0f4c859eSApple OSS Distributions 		    (vm_size_t)p_buffer_size, KMA_DATA | KMA_ZERO, tag) != KERN_SUCCESS) {
168*0f4c859eSApple OSS Distributions 			error = ENOSPC;
169*0f4c859eSApple OSS Distributions 			goto out;
170*0f4c859eSApple OSS Distributions 		}
171*0f4c859eSApple OSS Distributions 
172*0f4c859eSApple OSS Distributions 		kd_bufs[i].kdr_size = p_buffer_size;
173*0f4c859eSApple OSS Distributions 	}
174*0f4c859eSApple OSS Distributions 
175*0f4c859eSApple OSS Distributions 	count_storage_units = 0;
176*0f4c859eSApple OSS Distributions 	for (i = 0; i < kd_data_page->kdb_region_count; i++) {
177*0f4c859eSApple OSS Distributions 		struct kd_storage *kds;
178*0f4c859eSApple OSS Distributions 		uint16_t n_elements;
179*0f4c859eSApple OSS Distributions 		static_assert(N_STORAGE_UNITS_PER_BUFFER <= UINT16_MAX);
180*0f4c859eSApple OSS Distributions 		assert(kd_bufs[i].kdr_size <= N_STORAGE_UNITS_PER_BUFFER *
181*0f4c859eSApple OSS Distributions 		    sizeof(struct kd_storage));
182*0f4c859eSApple OSS Distributions 
183*0f4c859eSApple OSS Distributions 		n_elements = kd_bufs[i].kdr_size / sizeof(struct kd_storage);
184*0f4c859eSApple OSS Distributions 		kds = kd_bufs[i].kdr_addr;
185*0f4c859eSApple OSS Distributions 
186*0f4c859eSApple OSS Distributions 		for (uint16_t n = 0; n < n_elements; n++) {
187*0f4c859eSApple OSS Distributions 			kds[n].kds_next.buffer_index = kd_ctrl_page->kds_free_list.buffer_index;
188*0f4c859eSApple OSS Distributions 			kds[n].kds_next.offset = kd_ctrl_page->kds_free_list.offset;
189*0f4c859eSApple OSS Distributions 
190*0f4c859eSApple OSS Distributions 			kd_ctrl_page->kds_free_list.buffer_index = i;
191*0f4c859eSApple OSS Distributions 			kd_ctrl_page->kds_free_list.offset = n;
192*0f4c859eSApple OSS Distributions 		}
193*0f4c859eSApple OSS Distributions 		count_storage_units += n_elements;
194*0f4c859eSApple OSS Distributions 	}
195*0f4c859eSApple OSS Distributions 
196*0f4c859eSApple OSS Distributions 	kd_data_page->kdb_storage_count = count_storage_units;
197*0f4c859eSApple OSS Distributions 
198*0f4c859eSApple OSS Distributions 	for (i = 0; i < ncpus; i++) {
199*0f4c859eSApple OSS Distributions 		kdbip[i].kd_list_head.raw = KDS_PTR_NULL;
200*0f4c859eSApple OSS Distributions 		kdbip[i].kd_list_tail.raw = KDS_PTR_NULL;
201*0f4c859eSApple OSS Distributions 		kdbip[i].kd_lostevents = false;
202*0f4c859eSApple OSS Distributions 		kdbip[i].num_bufs = 0;
203*0f4c859eSApple OSS Distributions 	}
204*0f4c859eSApple OSS Distributions 
205*0f4c859eSApple OSS Distributions 	kd_ctrl_page->kdc_flags |= KDBG_BUFINIT;
206*0f4c859eSApple OSS Distributions 
207*0f4c859eSApple OSS Distributions 	kd_ctrl_page->kdc_storage_used = 0;
208*0f4c859eSApple OSS Distributions out:
209*0f4c859eSApple OSS Distributions 	if (error) {
210*0f4c859eSApple OSS Distributions 		delete_buffers(kd_ctrl_page, kd_data_page);
211*0f4c859eSApple OSS Distributions 	}
212*0f4c859eSApple OSS Distributions 
213*0f4c859eSApple OSS Distributions 	return error;
214*0f4c859eSApple OSS Distributions }
215*0f4c859eSApple OSS Distributions 
216*0f4c859eSApple OSS Distributions void
delete_buffers(struct kd_control * kd_ctrl_page,struct kd_buffer * kd_data_page)217*0f4c859eSApple OSS Distributions delete_buffers(struct kd_control *kd_ctrl_page,
218*0f4c859eSApple OSS Distributions     struct kd_buffer *kd_data_page)
219*0f4c859eSApple OSS Distributions {
220*0f4c859eSApple OSS Distributions 	unsigned int i;
221*0f4c859eSApple OSS Distributions 	int kdb_region_count = kd_data_page->kdb_region_count;
222*0f4c859eSApple OSS Distributions 
223*0f4c859eSApple OSS Distributions 	struct kd_bufinfo *kdbip = kd_data_page->kdb_info;
224*0f4c859eSApple OSS Distributions 	struct kd_region *kd_bufs = kd_data_page->kd_bufs;
225*0f4c859eSApple OSS Distributions 
226*0f4c859eSApple OSS Distributions 	if (kd_bufs) {
227*0f4c859eSApple OSS Distributions 		for (i = 0; i < kdb_region_count; i++) {
228*0f4c859eSApple OSS Distributions 			if (kd_bufs[i].kdr_addr) {
229*0f4c859eSApple OSS Distributions 				kmem_free(kernel_map, (vm_offset_t)kd_bufs[i].kdr_addr, (vm_size_t)kd_bufs[i].kdr_size);
230*0f4c859eSApple OSS Distributions 			}
231*0f4c859eSApple OSS Distributions 		}
232*0f4c859eSApple OSS Distributions 		kfree_type(struct kd_region, kdb_region_count, kd_bufs);
233*0f4c859eSApple OSS Distributions 
234*0f4c859eSApple OSS Distributions 		kd_data_page->kd_bufs = NULL;
235*0f4c859eSApple OSS Distributions 		kd_data_page->kdb_region_count = 0;
236*0f4c859eSApple OSS Distributions 	}
237*0f4c859eSApple OSS Distributions 	if (kd_data_page->kdcopybuf) {
238*0f4c859eSApple OSS Distributions 		kmem_free(kernel_map, (vm_offset_t)kd_data_page->kdcopybuf, kd_ctrl_page->kdebug_kdcopybuf_size);
239*0f4c859eSApple OSS Distributions 
240*0f4c859eSApple OSS Distributions 		kd_data_page->kdcopybuf = NULL;
241*0f4c859eSApple OSS Distributions 	}
242*0f4c859eSApple OSS Distributions 	kd_ctrl_page->kds_free_list.raw = KDS_PTR_NULL;
243*0f4c859eSApple OSS Distributions 
244*0f4c859eSApple OSS Distributions 	if (kdbip) {
245*0f4c859eSApple OSS Distributions 		kfree_type(struct kd_bufinfo, kd_ctrl_page->alloc_cpus, kdbip);
246*0f4c859eSApple OSS Distributions 		kd_data_page->kdb_info = NULL;
247*0f4c859eSApple OSS Distributions 	}
248*0f4c859eSApple OSS Distributions 	kd_ctrl_page->kdc_coprocs = NULL;
249*0f4c859eSApple OSS Distributions 	kd_ctrl_page->kdebug_cpus = 0;
250*0f4c859eSApple OSS Distributions 	kd_ctrl_page->alloc_cpus = 0;
251*0f4c859eSApple OSS Distributions 	kd_ctrl_page->kdc_flags &= ~KDBG_BUFINIT;
252*0f4c859eSApple OSS Distributions }
253*0f4c859eSApple OSS Distributions 
254*0f4c859eSApple OSS Distributions static bool
allocate_storage_unit(struct kd_control * kd_ctrl_page,struct kd_buffer * kd_data_page,int cpu)255*0f4c859eSApple OSS Distributions allocate_storage_unit(struct kd_control *kd_ctrl_page,
256*0f4c859eSApple OSS Distributions     struct kd_buffer *kd_data_page, int cpu)
257*0f4c859eSApple OSS Distributions {
258*0f4c859eSApple OSS Distributions 	union kds_ptr kdsp;
259*0f4c859eSApple OSS Distributions 	struct kd_storage *kdsp_actual, *kdsp_next_actual;
260*0f4c859eSApple OSS Distributions 	struct kd_bufinfo *kdbip, *kdbp, *kdbp_vict, *kdbp_try;
261*0f4c859eSApple OSS Distributions 	uint64_t oldest_ts, ts;
262*0f4c859eSApple OSS Distributions 	bool retval = true;
263*0f4c859eSApple OSS Distributions 	struct kd_region *kd_bufs;
264*0f4c859eSApple OSS Distributions 
265*0f4c859eSApple OSS Distributions 	int intrs_en = kdebug_storage_lock(kd_ctrl_page);
266*0f4c859eSApple OSS Distributions 
267*0f4c859eSApple OSS Distributions 	kdbp = &kd_data_page->kdb_info[cpu];
268*0f4c859eSApple OSS Distributions 	kd_bufs = kd_data_page->kd_bufs;
269*0f4c859eSApple OSS Distributions 	kdbip = kd_data_page->kdb_info;
270*0f4c859eSApple OSS Distributions 
271*0f4c859eSApple OSS Distributions 	/* If someone beat us to the allocate, return success */
272*0f4c859eSApple OSS Distributions 	if (kdbp->kd_list_tail.raw != KDS_PTR_NULL) {
273*0f4c859eSApple OSS Distributions 		kdsp_actual = POINTER_FROM_KDS_PTR(kd_bufs, kdbp->kd_list_tail);
274*0f4c859eSApple OSS Distributions 
275*0f4c859eSApple OSS Distributions 		if (kdsp_actual->kds_bufindx < kd_ctrl_page->kdebug_events_per_storage_unit) {
276*0f4c859eSApple OSS Distributions 			goto out;
277*0f4c859eSApple OSS Distributions 		}
278*0f4c859eSApple OSS Distributions 	}
279*0f4c859eSApple OSS Distributions 
280*0f4c859eSApple OSS Distributions 	if ((kdsp = kd_ctrl_page->kds_free_list).raw != KDS_PTR_NULL) {
281*0f4c859eSApple OSS Distributions 		/*
282*0f4c859eSApple OSS Distributions 		 * If there's a free page, grab it from the free list.
283*0f4c859eSApple OSS Distributions 		 */
284*0f4c859eSApple OSS Distributions 		kdsp_actual = POINTER_FROM_KDS_PTR(kd_bufs, kdsp);
285*0f4c859eSApple OSS Distributions 		kd_ctrl_page->kds_free_list = kdsp_actual->kds_next;
286*0f4c859eSApple OSS Distributions 
287*0f4c859eSApple OSS Distributions 		kd_ctrl_page->kdc_storage_used++;
288*0f4c859eSApple OSS Distributions 	} else {
289*0f4c859eSApple OSS Distributions 		/*
290*0f4c859eSApple OSS Distributions 		 * Otherwise, we're going to lose events and repurpose the oldest
291*0f4c859eSApple OSS Distributions 		 * storage unit we can find.
292*0f4c859eSApple OSS Distributions 		 */
293*0f4c859eSApple OSS Distributions 		if (kd_ctrl_page->kdc_live_flags & KDBG_NOWRAP) {
294*0f4c859eSApple OSS Distributions 			kd_ctrl_page->kdc_emit = KDEMIT_DISABLE;
295*0f4c859eSApple OSS Distributions 			kd_ctrl_page->kdc_live_flags |= KDBG_WRAPPED;
296*0f4c859eSApple OSS Distributions 			kdebug_enable = 0;
297*0f4c859eSApple OSS Distributions 			kd_ctrl_page->enabled = 0;
298*0f4c859eSApple OSS Distributions 			commpage_update_kdebug_state();
299*0f4c859eSApple OSS Distributions 			kdbp->kd_lostevents = true;
300*0f4c859eSApple OSS Distributions 			retval = false;
301*0f4c859eSApple OSS Distributions 			goto out;
302*0f4c859eSApple OSS Distributions 		}
303*0f4c859eSApple OSS Distributions 		kdbp_vict = NULL;
304*0f4c859eSApple OSS Distributions 		oldest_ts = UINT64_MAX;
305*0f4c859eSApple OSS Distributions 
306*0f4c859eSApple OSS Distributions 		for (kdbp_try = &kdbip[0]; kdbp_try < &kdbip[kd_ctrl_page->kdebug_cpus]; kdbp_try++) {
307*0f4c859eSApple OSS Distributions 			if (kdbp_try->kd_list_head.raw == KDS_PTR_NULL) {
308*0f4c859eSApple OSS Distributions 				/*
309*0f4c859eSApple OSS Distributions 				 * no storage unit to steal
310*0f4c859eSApple OSS Distributions 				 */
311*0f4c859eSApple OSS Distributions 				continue;
312*0f4c859eSApple OSS Distributions 			}
313*0f4c859eSApple OSS Distributions 
314*0f4c859eSApple OSS Distributions 			kdsp_actual = POINTER_FROM_KDS_PTR(kd_bufs, kdbp_try->kd_list_head);
315*0f4c859eSApple OSS Distributions 
316*0f4c859eSApple OSS Distributions 			if (kdsp_actual->kds_bufcnt < kd_ctrl_page->kdebug_events_per_storage_unit) {
317*0f4c859eSApple OSS Distributions 				/*
318*0f4c859eSApple OSS Distributions 				 * make sure we don't steal the storage unit
319*0f4c859eSApple OSS Distributions 				 * being actively recorded to...  need to
320*0f4c859eSApple OSS Distributions 				 * move on because we don't want an out-of-order
321*0f4c859eSApple OSS Distributions 				 * set of events showing up later
322*0f4c859eSApple OSS Distributions 				 */
323*0f4c859eSApple OSS Distributions 				continue;
324*0f4c859eSApple OSS Distributions 			}
325*0f4c859eSApple OSS Distributions 
326*0f4c859eSApple OSS Distributions 			/*
327*0f4c859eSApple OSS Distributions 			 * When wrapping, steal the storage unit with the
328*0f4c859eSApple OSS Distributions 			 * earliest timestamp on its last event, instead of the
329*0f4c859eSApple OSS Distributions 			 * earliest timestamp on the first event.  This allows a
330*0f4c859eSApple OSS Distributions 			 * storage unit with more recent events to be preserved,
331*0f4c859eSApple OSS Distributions 			 * even if the storage unit contains events that are
332*0f4c859eSApple OSS Distributions 			 * older than those found in other CPUs.
333*0f4c859eSApple OSS Distributions 			 */
334*0f4c859eSApple OSS Distributions 			ts = kdbg_get_timestamp(&kdsp_actual->kds_records[kd_ctrl_page->kdebug_events_per_storage_unit - 1]);
335*0f4c859eSApple OSS Distributions 			if (ts < oldest_ts) {
336*0f4c859eSApple OSS Distributions 				oldest_ts = ts;
337*0f4c859eSApple OSS Distributions 				kdbp_vict = kdbp_try;
338*0f4c859eSApple OSS Distributions 			}
339*0f4c859eSApple OSS Distributions 		}
340*0f4c859eSApple OSS Distributions 		if (kdbp_vict == NULL && kd_ctrl_page->mode == KDEBUG_MODE_TRACE) {
341*0f4c859eSApple OSS Distributions 			kd_ctrl_page->kdc_emit = KDEMIT_DISABLE;
342*0f4c859eSApple OSS Distributions 			kdebug_enable = 0;
343*0f4c859eSApple OSS Distributions 			kd_ctrl_page->enabled = 0;
344*0f4c859eSApple OSS Distributions 			commpage_update_kdebug_state();
345*0f4c859eSApple OSS Distributions 			retval = false;
346*0f4c859eSApple OSS Distributions 			goto out;
347*0f4c859eSApple OSS Distributions 		}
348*0f4c859eSApple OSS Distributions 		kdsp = kdbp_vict->kd_list_head;
349*0f4c859eSApple OSS Distributions 		kdsp_actual = POINTER_FROM_KDS_PTR(kd_bufs, kdsp);
350*0f4c859eSApple OSS Distributions 		kdbp_vict->kd_list_head = kdsp_actual->kds_next;
351*0f4c859eSApple OSS Distributions 
352*0f4c859eSApple OSS Distributions 		if (kdbp_vict->kd_list_head.raw != KDS_PTR_NULL) {
353*0f4c859eSApple OSS Distributions 			kdsp_next_actual = POINTER_FROM_KDS_PTR(kd_bufs, kdbp_vict->kd_list_head);
354*0f4c859eSApple OSS Distributions 			kdsp_next_actual->kds_lostevents = true;
355*0f4c859eSApple OSS Distributions 		} else {
356*0f4c859eSApple OSS Distributions 			kdbp_vict->kd_lostevents = true;
357*0f4c859eSApple OSS Distributions 		}
358*0f4c859eSApple OSS Distributions 
359*0f4c859eSApple OSS Distributions 		if (kd_ctrl_page->kdc_oldest_time < oldest_ts) {
360*0f4c859eSApple OSS Distributions 			kd_ctrl_page->kdc_oldest_time = oldest_ts;
361*0f4c859eSApple OSS Distributions 		}
362*0f4c859eSApple OSS Distributions 		kd_ctrl_page->kdc_live_flags |= KDBG_WRAPPED;
363*0f4c859eSApple OSS Distributions 	}
364*0f4c859eSApple OSS Distributions 
365*0f4c859eSApple OSS Distributions 	if (kd_ctrl_page->mode == KDEBUG_MODE_TRACE) {
366*0f4c859eSApple OSS Distributions 		kdsp_actual->kds_timestamp = kdebug_timestamp();
367*0f4c859eSApple OSS Distributions 	} else {
368*0f4c859eSApple OSS Distributions 		kdsp_actual->kds_timestamp = mach_continuous_time();
369*0f4c859eSApple OSS Distributions 	}
370*0f4c859eSApple OSS Distributions 
371*0f4c859eSApple OSS Distributions 	kdsp_actual->kds_next.raw = KDS_PTR_NULL;
372*0f4c859eSApple OSS Distributions 	kdsp_actual->kds_bufcnt   = 0;
373*0f4c859eSApple OSS Distributions 	kdsp_actual->kds_readlast = 0;
374*0f4c859eSApple OSS Distributions 
375*0f4c859eSApple OSS Distributions 	kdsp_actual->kds_lostevents = kdbp->kd_lostevents;
376*0f4c859eSApple OSS Distributions 	kdbp->kd_lostevents = false;
377*0f4c859eSApple OSS Distributions 	kdsp_actual->kds_bufindx = 0;
378*0f4c859eSApple OSS Distributions 
379*0f4c859eSApple OSS Distributions 	if (kdbp->kd_list_head.raw == KDS_PTR_NULL) {
380*0f4c859eSApple OSS Distributions 		kdbp->kd_list_head = kdsp;
381*0f4c859eSApple OSS Distributions 	} else {
382*0f4c859eSApple OSS Distributions 		POINTER_FROM_KDS_PTR(kd_bufs, kdbp->kd_list_tail)->kds_next = kdsp;
383*0f4c859eSApple OSS Distributions 	}
384*0f4c859eSApple OSS Distributions 	kdbp->kd_list_tail = kdsp;
385*0f4c859eSApple OSS Distributions out:
386*0f4c859eSApple OSS Distributions 	kdebug_storage_unlock(kd_ctrl_page, intrs_en);
387*0f4c859eSApple OSS Distributions 
388*0f4c859eSApple OSS Distributions 	return retval;
389*0f4c859eSApple OSS Distributions }
390*0f4c859eSApple OSS Distributions 
391*0f4c859eSApple OSS Distributions static void
release_storage_unit(struct kd_control * kd_ctrl_page,struct kd_buffer * kd_data_page,int cpu,uint32_t kdsp_raw)392*0f4c859eSApple OSS Distributions release_storage_unit(struct kd_control *kd_ctrl_page, struct kd_buffer *kd_data_page, int cpu, uint32_t kdsp_raw)
393*0f4c859eSApple OSS Distributions {
394*0f4c859eSApple OSS Distributions 	struct  kd_storage *kdsp_actual;
395*0f4c859eSApple OSS Distributions 	struct kd_bufinfo *kdbp;
396*0f4c859eSApple OSS Distributions 	union kds_ptr kdsp;
397*0f4c859eSApple OSS Distributions 
398*0f4c859eSApple OSS Distributions 	kdbp = &kd_data_page->kdb_info[cpu];
399*0f4c859eSApple OSS Distributions 
400*0f4c859eSApple OSS Distributions 	kdsp.raw = kdsp_raw;
401*0f4c859eSApple OSS Distributions 
402*0f4c859eSApple OSS Distributions 	int intrs_en = kdebug_storage_lock(kd_ctrl_page);
403*0f4c859eSApple OSS Distributions 
404*0f4c859eSApple OSS Distributions 	if (kdsp.raw == kdbp->kd_list_head.raw) {
405*0f4c859eSApple OSS Distributions 		/*
406*0f4c859eSApple OSS Distributions 		 * it's possible for the storage unit pointed to
407*0f4c859eSApple OSS Distributions 		 * by kdsp to have already been stolen... so
408*0f4c859eSApple OSS Distributions 		 * check to see if it's still the head of the list
409*0f4c859eSApple OSS Distributions 		 * now that we're behind the lock that protects
410*0f4c859eSApple OSS Distributions 		 * adding and removing from the queue...
411*0f4c859eSApple OSS Distributions 		 * since we only ever release and steal units from
412*0f4c859eSApple OSS Distributions 		 * that position, if it's no longer the head
413*0f4c859eSApple OSS Distributions 		 * we having nothing to do in this context
414*0f4c859eSApple OSS Distributions 		 */
415*0f4c859eSApple OSS Distributions 		kdsp_actual = POINTER_FROM_KDS_PTR(kd_data_page->kd_bufs, kdsp);
416*0f4c859eSApple OSS Distributions 		kdbp->kd_list_head = kdsp_actual->kds_next;
417*0f4c859eSApple OSS Distributions 
418*0f4c859eSApple OSS Distributions 		kdsp_actual->kds_next = kd_ctrl_page->kds_free_list;
419*0f4c859eSApple OSS Distributions 		kd_ctrl_page->kds_free_list = kdsp;
420*0f4c859eSApple OSS Distributions 
421*0f4c859eSApple OSS Distributions 		kd_ctrl_page->kdc_storage_used--;
422*0f4c859eSApple OSS Distributions 	}
423*0f4c859eSApple OSS Distributions 
424*0f4c859eSApple OSS Distributions 	kdebug_storage_unlock(kd_ctrl_page, intrs_en);
425*0f4c859eSApple OSS Distributions }
426*0f4c859eSApple OSS Distributions 
427*0f4c859eSApple OSS Distributions bool
kdebug_disable_wrap(struct kd_control * ctl,kdebug_emit_filter_t * old_emit,kdebug_live_flags_t * old_live)428*0f4c859eSApple OSS Distributions kdebug_disable_wrap(struct kd_control *ctl,
429*0f4c859eSApple OSS Distributions     kdebug_emit_filter_t *old_emit, kdebug_live_flags_t *old_live)
430*0f4c859eSApple OSS Distributions {
431*0f4c859eSApple OSS Distributions 	int intrs_en = kdebug_storage_lock(ctl);
432*0f4c859eSApple OSS Distributions 
433*0f4c859eSApple OSS Distributions 	*old_emit = ctl->kdc_emit;
434*0f4c859eSApple OSS Distributions 	*old_live = ctl->kdc_live_flags;
435*0f4c859eSApple OSS Distributions 
436*0f4c859eSApple OSS Distributions 	bool wrapped = ctl->kdc_live_flags & KDBG_WRAPPED;
437*0f4c859eSApple OSS Distributions 	ctl->kdc_live_flags &= ~KDBG_WRAPPED;
438*0f4c859eSApple OSS Distributions 	ctl->kdc_live_flags |= KDBG_NOWRAP;
439*0f4c859eSApple OSS Distributions 
440*0f4c859eSApple OSS Distributions 	kdebug_storage_unlock(ctl, intrs_en);
441*0f4c859eSApple OSS Distributions 
442*0f4c859eSApple OSS Distributions 	return wrapped;
443*0f4c859eSApple OSS Distributions }
444*0f4c859eSApple OSS Distributions 
445*0f4c859eSApple OSS Distributions static void
_enable_wrap(struct kd_control * kd_ctrl_page,kdebug_emit_filter_t emit)446*0f4c859eSApple OSS Distributions _enable_wrap(struct kd_control *kd_ctrl_page, kdebug_emit_filter_t emit)
447*0f4c859eSApple OSS Distributions {
448*0f4c859eSApple OSS Distributions 	int intrs_en = kdebug_storage_lock(kd_ctrl_page);
449*0f4c859eSApple OSS Distributions 	kd_ctrl_page->kdc_live_flags &= ~KDBG_NOWRAP;
450*0f4c859eSApple OSS Distributions 	if (emit) {
451*0f4c859eSApple OSS Distributions 		kd_ctrl_page->kdc_emit = emit;
452*0f4c859eSApple OSS Distributions 	}
453*0f4c859eSApple OSS Distributions 	kdebug_storage_unlock(kd_ctrl_page, intrs_en);
454*0f4c859eSApple OSS Distributions }
455*0f4c859eSApple OSS Distributions 
456*0f4c859eSApple OSS Distributions __attribute__((always_inline))
457*0f4c859eSApple OSS Distributions void
kernel_debug_write(struct kd_control * kd_ctrl_page,struct kd_buffer * kd_data_page,struct kd_record kd_rec)458*0f4c859eSApple OSS Distributions kernel_debug_write(struct kd_control *kd_ctrl_page,
459*0f4c859eSApple OSS Distributions     struct kd_buffer *kd_data_page,
460*0f4c859eSApple OSS Distributions     struct kd_record      kd_rec)
461*0f4c859eSApple OSS Distributions {
462*0f4c859eSApple OSS Distributions 	uint64_t now = 0;
463*0f4c859eSApple OSS Distributions 	uint32_t bindx;
464*0f4c859eSApple OSS Distributions 	kd_buf *kd;
465*0f4c859eSApple OSS Distributions 	int cpu;
466*0f4c859eSApple OSS Distributions 	struct kd_bufinfo *kdbp;
467*0f4c859eSApple OSS Distributions 	struct kd_storage *kdsp_actual;
468*0f4c859eSApple OSS Distributions 	union kds_ptr kds_raw;
469*0f4c859eSApple OSS Distributions 
470*0f4c859eSApple OSS Distributions 	disable_preemption();
471*0f4c859eSApple OSS Distributions 
472*0f4c859eSApple OSS Distributions 	if (kd_ctrl_page->enabled == 0) {
473*0f4c859eSApple OSS Distributions 		goto out;
474*0f4c859eSApple OSS Distributions 	}
475*0f4c859eSApple OSS Distributions 
476*0f4c859eSApple OSS Distributions 	if (kd_rec.cpu == -1) {
477*0f4c859eSApple OSS Distributions 		cpu = cpu_number();
478*0f4c859eSApple OSS Distributions 	} else {
479*0f4c859eSApple OSS Distributions 		cpu = kd_rec.cpu;
480*0f4c859eSApple OSS Distributions 	}
481*0f4c859eSApple OSS Distributions 
482*0f4c859eSApple OSS Distributions 	kdbp = &kd_data_page->kdb_info[cpu];
483*0f4c859eSApple OSS Distributions 
484*0f4c859eSApple OSS Distributions 	bool timestamp_is_continuous = kdbp->continuous_timestamps;
485*0f4c859eSApple OSS Distributions 
486*0f4c859eSApple OSS Distributions 	if (kd_rec.timestamp != -1) {
487*0f4c859eSApple OSS Distributions 		if (kdebug_using_continuous_time()) {
488*0f4c859eSApple OSS Distributions 			if (!timestamp_is_continuous) {
489*0f4c859eSApple OSS Distributions 				kd_rec.timestamp = absolutetime_to_continuoustime(kd_rec.timestamp);
490*0f4c859eSApple OSS Distributions 			}
491*0f4c859eSApple OSS Distributions 		} else {
492*0f4c859eSApple OSS Distributions 			if (timestamp_is_continuous) {
493*0f4c859eSApple OSS Distributions 				kd_rec.timestamp = continuoustime_to_absolutetime(kd_rec.timestamp);
494*0f4c859eSApple OSS Distributions 			}
495*0f4c859eSApple OSS Distributions 		}
496*0f4c859eSApple OSS Distributions 		kd_rec.timestamp &= KDBG_TIMESTAMP_MASK;
497*0f4c859eSApple OSS Distributions 		if (kd_rec.timestamp < kd_ctrl_page->kdc_oldest_time) {
498*0f4c859eSApple OSS Distributions 			if (kdbp->latest_past_event_timestamp < kd_rec.timestamp) {
499*0f4c859eSApple OSS Distributions 				kdbp->latest_past_event_timestamp = kd_rec.timestamp;
500*0f4c859eSApple OSS Distributions 			}
501*0f4c859eSApple OSS Distributions 			goto out;
502*0f4c859eSApple OSS Distributions 		}
503*0f4c859eSApple OSS Distributions 	}
504*0f4c859eSApple OSS Distributions 
505*0f4c859eSApple OSS Distributions retry_q:
506*0f4c859eSApple OSS Distributions 	kds_raw = kdbp->kd_list_tail;
507*0f4c859eSApple OSS Distributions 
508*0f4c859eSApple OSS Distributions 	if (kds_raw.raw != KDS_PTR_NULL) {
509*0f4c859eSApple OSS Distributions 		kdsp_actual = POINTER_FROM_KDS_PTR(kd_data_page->kd_bufs, kds_raw);
510*0f4c859eSApple OSS Distributions 		bindx = kdsp_actual->kds_bufindx;
511*0f4c859eSApple OSS Distributions 	} else {
512*0f4c859eSApple OSS Distributions 		kdsp_actual = NULL;
513*0f4c859eSApple OSS Distributions 		bindx = kd_ctrl_page->kdebug_events_per_storage_unit;
514*0f4c859eSApple OSS Distributions 	}
515*0f4c859eSApple OSS Distributions 
516*0f4c859eSApple OSS Distributions 	if (kdsp_actual == NULL || bindx >= kd_ctrl_page->kdebug_events_per_storage_unit) {
517*0f4c859eSApple OSS Distributions 		if (allocate_storage_unit(kd_ctrl_page, kd_data_page, cpu) == false) {
518*0f4c859eSApple OSS Distributions 			/*
519*0f4c859eSApple OSS Distributions 			 * this can only happen if wrapping
520*0f4c859eSApple OSS Distributions 			 * has been disabled
521*0f4c859eSApple OSS Distributions 			 */
522*0f4c859eSApple OSS Distributions 			goto out;
523*0f4c859eSApple OSS Distributions 		}
524*0f4c859eSApple OSS Distributions 		goto retry_q;
525*0f4c859eSApple OSS Distributions 	}
526*0f4c859eSApple OSS Distributions 
527*0f4c859eSApple OSS Distributions 	if (kd_rec.timestamp != -1) {
528*0f4c859eSApple OSS Distributions 		/*
529*0f4c859eSApple OSS Distributions 		 * IOP entries can be allocated before xnu allocates and inits the buffer
530*0f4c859eSApple OSS Distributions 		 * And, Intel uses a special 0 value as a early tracing timestamp sentinel
531*0f4c859eSApple OSS Distributions 		 * to set the start of trace-time-start-of-interest.
532*0f4c859eSApple OSS Distributions 		 */
533*0f4c859eSApple OSS Distributions 		if (kd_rec.timestamp < kdsp_actual->kds_timestamp) {
534*0f4c859eSApple OSS Distributions 			kdsp_actual->kds_timestamp = kd_rec.timestamp;
535*0f4c859eSApple OSS Distributions 		}
536*0f4c859eSApple OSS Distributions 		now = kd_rec.timestamp;
537*0f4c859eSApple OSS Distributions 	} else {
538*0f4c859eSApple OSS Distributions 		if (kd_ctrl_page->mode == KDEBUG_MODE_TRACE) {
539*0f4c859eSApple OSS Distributions 			now = kdebug_timestamp() & KDBG_TIMESTAMP_MASK;
540*0f4c859eSApple OSS Distributions 		} else {
541*0f4c859eSApple OSS Distributions 			now = mach_continuous_time() & KDBG_TIMESTAMP_MASK;
542*0f4c859eSApple OSS Distributions 		}
543*0f4c859eSApple OSS Distributions 	}
544*0f4c859eSApple OSS Distributions 
545*0f4c859eSApple OSS Distributions 	if (!OSCompareAndSwap(bindx, bindx + 1, &kdsp_actual->kds_bufindx)) {
546*0f4c859eSApple OSS Distributions 		goto retry_q;
547*0f4c859eSApple OSS Distributions 	}
548*0f4c859eSApple OSS Distributions 
549*0f4c859eSApple OSS Distributions 	kd = &kdsp_actual->kds_records[bindx];
550*0f4c859eSApple OSS Distributions 
551*0f4c859eSApple OSS Distributions 	if (kd_ctrl_page->kdc_flags & KDBG_DEBUGID_64) {
552*0f4c859eSApple OSS Distributions 		/*DebugID has been passed in arg 4*/
553*0f4c859eSApple OSS Distributions 		kd->debugid = 0;
554*0f4c859eSApple OSS Distributions 	} else {
555*0f4c859eSApple OSS Distributions 		kd->debugid = kd_rec.debugid;
556*0f4c859eSApple OSS Distributions 	}
557*0f4c859eSApple OSS Distributions 
558*0f4c859eSApple OSS Distributions 	kd->arg1 = kd_rec.arg1;
559*0f4c859eSApple OSS Distributions 	kd->arg2 = kd_rec.arg2;
560*0f4c859eSApple OSS Distributions 	kd->arg3 = kd_rec.arg3;
561*0f4c859eSApple OSS Distributions 	kd->arg4 = kd_rec.arg4;
562*0f4c859eSApple OSS Distributions 	kd->arg5 = kd_rec.arg5;
563*0f4c859eSApple OSS Distributions 
564*0f4c859eSApple OSS Distributions 	kdbg_set_timestamp_and_cpu(kd, now, cpu);
565*0f4c859eSApple OSS Distributions 
566*0f4c859eSApple OSS Distributions 	OSAddAtomic(1, &kdsp_actual->kds_bufcnt);
567*0f4c859eSApple OSS Distributions 
568*0f4c859eSApple OSS Distributions out:
569*0f4c859eSApple OSS Distributions 	enable_preemption();
570*0f4c859eSApple OSS Distributions }
571*0f4c859eSApple OSS Distributions 
572*0f4c859eSApple OSS Distributions // Read events from kdebug storage units into a user space buffer or file.
573*0f4c859eSApple OSS Distributions //
574*0f4c859eSApple OSS Distributions // This code runs while events are emitted -- storage unit allocation and
575*0f4c859eSApple OSS Distributions // deallocation wll synchronize with the emitters.  Only one reader per control
576*0f4c859eSApple OSS Distributions // structure is allowed.
577*0f4c859eSApple OSS Distributions int
kernel_debug_read(struct kd_control * kd_ctrl_page,struct kd_buffer * kd_data_page,user_addr_t buffer,size_t * number,vnode_t vp,vfs_context_t ctx,uint32_t file_version)578*0f4c859eSApple OSS Distributions kernel_debug_read(struct kd_control *kd_ctrl_page,
579*0f4c859eSApple OSS Distributions     struct kd_buffer *kd_data_page, user_addr_t buffer, size_t *number,
580*0f4c859eSApple OSS Distributions     vnode_t vp, vfs_context_t ctx, uint32_t file_version)
581*0f4c859eSApple OSS Distributions {
582*0f4c859eSApple OSS Distributions 	size_t count;
583*0f4c859eSApple OSS Distributions 	unsigned int cpu, min_cpu;
584*0f4c859eSApple OSS Distributions 	uint64_t barrier_min = 0, barrier_max = 0, t, earliest_time;
585*0f4c859eSApple OSS Distributions 	int error = 0;
586*0f4c859eSApple OSS Distributions 	kd_buf *tempbuf;
587*0f4c859eSApple OSS Distributions 	uint32_t rcursor;
588*0f4c859eSApple OSS Distributions 	kd_buf lostevent;
589*0f4c859eSApple OSS Distributions 	union kds_ptr kdsp;
590*0f4c859eSApple OSS Distributions 	bool traced_retrograde = false;
591*0f4c859eSApple OSS Distributions 	struct kd_storage *kdsp_actual;
592*0f4c859eSApple OSS Distributions 	struct kd_bufinfo *kdbp;
593*0f4c859eSApple OSS Distributions 	struct kd_bufinfo *min_kdbp;
594*0f4c859eSApple OSS Distributions 	size_t tempbuf_count;
595*0f4c859eSApple OSS Distributions 	uint32_t tempbuf_number;
596*0f4c859eSApple OSS Distributions 	kdebug_emit_filter_t old_emit;
597*0f4c859eSApple OSS Distributions 	uint32_t old_live_flags;
598*0f4c859eSApple OSS Distributions 	bool out_of_events = false;
599*0f4c859eSApple OSS Distributions 	bool wrapped = false;
600*0f4c859eSApple OSS Distributions 	bool set_preempt = true;
601*0f4c859eSApple OSS Distributions 	bool should_disable = false;
602*0f4c859eSApple OSS Distributions 
603*0f4c859eSApple OSS Distributions 	struct kd_bufinfo *kdbip = kd_data_page->kdb_info;
604*0f4c859eSApple OSS Distributions 	struct kd_region *kd_bufs = kd_data_page->kd_bufs;
605*0f4c859eSApple OSS Distributions 
606*0f4c859eSApple OSS Distributions 	assert(number != NULL);
607*0f4c859eSApple OSS Distributions 	count = *number / sizeof(kd_buf);
608*0f4c859eSApple OSS Distributions 	*number = 0;
609*0f4c859eSApple OSS Distributions 
610*0f4c859eSApple OSS Distributions 	if (count == 0 || !(kd_ctrl_page->kdc_flags & KDBG_BUFINIT) || kd_data_page->kdcopybuf == 0) {
611*0f4c859eSApple OSS Distributions 		return EINVAL;
612*0f4c859eSApple OSS Distributions 	}
613*0f4c859eSApple OSS Distributions 
614*0f4c859eSApple OSS Distributions 	if (kd_ctrl_page->mode == KDEBUG_MODE_TRIAGE) {
615*0f4c859eSApple OSS Distributions 		/*
616*0f4c859eSApple OSS Distributions 		 * A corpse can be created due to 'TASK_HAS_TOO_MANY_THREADS'
617*0f4c859eSApple OSS Distributions 		 * and that can be handled by a callout thread that already
618*0f4c859eSApple OSS Distributions 		 * has the eager-preemption set.
619*0f4c859eSApple OSS Distributions 		 * So check to see if we are dealing with one such thread.
620*0f4c859eSApple OSS Distributions 		 */
621*0f4c859eSApple OSS Distributions 		set_preempt = !(thread_is_eager_preempt(current_thread()));
622*0f4c859eSApple OSS Distributions 	}
623*0f4c859eSApple OSS Distributions 
624*0f4c859eSApple OSS Distributions 	if (set_preempt) {
625*0f4c859eSApple OSS Distributions 		thread_set_eager_preempt(current_thread());
626*0f4c859eSApple OSS Distributions 	}
627*0f4c859eSApple OSS Distributions 
628*0f4c859eSApple OSS Distributions 	memset(&lostevent, 0, sizeof(lostevent));
629*0f4c859eSApple OSS Distributions 	lostevent.debugid = TRACE_LOST_EVENTS;
630*0f4c859eSApple OSS Distributions 
631*0f4c859eSApple OSS Distributions 	/*
632*0f4c859eSApple OSS Distributions 	 * Capture the current time.  Only sort events that have occured
633*0f4c859eSApple OSS Distributions 	 * before now.  Since the IOPs are being flushed here, it is possible
634*0f4c859eSApple OSS Distributions 	 * that events occur on the AP while running live tracing.
635*0f4c859eSApple OSS Distributions 	 */
636*0f4c859eSApple OSS Distributions 	if (kd_ctrl_page->mode == KDEBUG_MODE_TRACE) {
637*0f4c859eSApple OSS Distributions 		barrier_max = kdebug_timestamp() & KDBG_TIMESTAMP_MASK;
638*0f4c859eSApple OSS Distributions 	} else {
639*0f4c859eSApple OSS Distributions 		barrier_max = mach_continuous_time() & KDBG_TIMESTAMP_MASK;
640*0f4c859eSApple OSS Distributions 	}
641*0f4c859eSApple OSS Distributions 
642*0f4c859eSApple OSS Distributions 	/*
643*0f4c859eSApple OSS Distributions 	 * Disable wrap so storage units cannot be stolen out from underneath us
644*0f4c859eSApple OSS Distributions 	 * while merging events.
645*0f4c859eSApple OSS Distributions 	 *
646*0f4c859eSApple OSS Distributions 	 * Because we hold ktrace_lock, no other control threads can be playing
647*0f4c859eSApple OSS Distributions 	 * with kdc_flags.  The code that emits new events could be running,
648*0f4c859eSApple OSS Distributions 	 * but it grabs kdc_storage_lock if it needs to acquire a new storage
649*0f4c859eSApple OSS Distributions 	 * chunk, which is where it examines kdc_flags.  If it is adding to
650*0f4c859eSApple OSS Distributions 	 * the same chunk we're reading from, check for that below.
651*0f4c859eSApple OSS Distributions 	 */
652*0f4c859eSApple OSS Distributions 	wrapped = kdebug_disable_wrap(kd_ctrl_page, &old_emit, &old_live_flags);
653*0f4c859eSApple OSS Distributions 
654*0f4c859eSApple OSS Distributions 	if (count > kd_data_page->kdb_event_count) {
655*0f4c859eSApple OSS Distributions 		count = kd_data_page->kdb_event_count;
656*0f4c859eSApple OSS Distributions 	}
657*0f4c859eSApple OSS Distributions 
658*0f4c859eSApple OSS Distributions 	if ((tempbuf_count = count) > kd_ctrl_page->kdebug_kdcopybuf_count) {
659*0f4c859eSApple OSS Distributions 		tempbuf_count = kd_ctrl_page->kdebug_kdcopybuf_count;
660*0f4c859eSApple OSS Distributions 	}
661*0f4c859eSApple OSS Distributions 
662*0f4c859eSApple OSS Distributions 	/*
663*0f4c859eSApple OSS Distributions 	 * If the buffers have wrapped, do not emit additional lost events for the
664*0f4c859eSApple OSS Distributions 	 * oldest storage units.
665*0f4c859eSApple OSS Distributions 	 */
666*0f4c859eSApple OSS Distributions 	if (wrapped) {
667*0f4c859eSApple OSS Distributions 		kd_ctrl_page->kdc_live_flags &= ~KDBG_WRAPPED;
668*0f4c859eSApple OSS Distributions 
669*0f4c859eSApple OSS Distributions 		for (cpu = 0, kdbp = &kdbip[0]; cpu < kd_ctrl_page->kdebug_cpus; cpu++, kdbp++) {
670*0f4c859eSApple OSS Distributions 			if ((kdsp = kdbp->kd_list_head).raw == KDS_PTR_NULL) {
671*0f4c859eSApple OSS Distributions 				continue;
672*0f4c859eSApple OSS Distributions 			}
673*0f4c859eSApple OSS Distributions 			kdsp_actual = POINTER_FROM_KDS_PTR(kd_bufs, kdsp);
674*0f4c859eSApple OSS Distributions 			kdsp_actual->kds_lostevents = false;
675*0f4c859eSApple OSS Distributions 		}
676*0f4c859eSApple OSS Distributions 	}
677*0f4c859eSApple OSS Distributions 
678*0f4c859eSApple OSS Distributions 	if (kd_ctrl_page->mode == KDEBUG_MODE_TRIAGE) {
679*0f4c859eSApple OSS Distributions 		/*
680*0f4c859eSApple OSS Distributions 		 * In TRIAGE mode we want to extract all the current
681*0f4c859eSApple OSS Distributions 		 * records regardless of where we stopped reading last
682*0f4c859eSApple OSS Distributions 		 * time so that we have the best shot at getting older
683*0f4c859eSApple OSS Distributions 		 * records for threads before the buffers are wrapped.
684*0f4c859eSApple OSS Distributions 		 * So set:-
685*0f4c859eSApple OSS Distributions 		 * a) kd_prev_timebase to 0 so we (re-)consider older records
686*0f4c859eSApple OSS Distributions 		 * b) readlast to 0 to initiate the search from the
687*0f4c859eSApple OSS Distributions 		 * 1st record.
688*0f4c859eSApple OSS Distributions 		 */
689*0f4c859eSApple OSS Distributions 		for (cpu = 0, kdbp = &kdbip[0]; cpu < kd_ctrl_page->kdebug_cpus; cpu++, kdbp++) {
690*0f4c859eSApple OSS Distributions 			kdbp->kd_prev_timebase = 0;
691*0f4c859eSApple OSS Distributions 			if ((kdsp = kdbp->kd_list_head).raw == KDS_PTR_NULL) {
692*0f4c859eSApple OSS Distributions 				continue;
693*0f4c859eSApple OSS Distributions 			}
694*0f4c859eSApple OSS Distributions 			kdsp_actual = POINTER_FROM_KDS_PTR(kd_bufs, kdsp);
695*0f4c859eSApple OSS Distributions 			kdsp_actual->kds_readlast = 0;
696*0f4c859eSApple OSS Distributions 		}
697*0f4c859eSApple OSS Distributions 	}
698*0f4c859eSApple OSS Distributions 
699*0f4c859eSApple OSS Distributions 	/*
700*0f4c859eSApple OSS Distributions 	 * Capture the earliest time where there are events for all CPUs and don't
701*0f4c859eSApple OSS Distributions 	 * emit events with timestamps prior.
702*0f4c859eSApple OSS Distributions 	 */
703*0f4c859eSApple OSS Distributions 	barrier_min = kd_ctrl_page->kdc_oldest_time;
704*0f4c859eSApple OSS Distributions 
705*0f4c859eSApple OSS Distributions 	while (count) {
706*0f4c859eSApple OSS Distributions 		tempbuf = kd_data_page->kdcopybuf;
707*0f4c859eSApple OSS Distributions 		tempbuf_number = 0;
708*0f4c859eSApple OSS Distributions 
709*0f4c859eSApple OSS Distributions 		if (wrapped) {
710*0f4c859eSApple OSS Distributions 			/*
711*0f4c859eSApple OSS Distributions 			 * Emit a lost events tracepoint to indicate that previous events
712*0f4c859eSApple OSS Distributions 			 * were lost -- the thread map cannot be trusted.  A new one must
713*0f4c859eSApple OSS Distributions 			 * be taken so tools can analyze the trace in a backwards-facing
714*0f4c859eSApple OSS Distributions 			 * fashion.
715*0f4c859eSApple OSS Distributions 			 */
716*0f4c859eSApple OSS Distributions 			kdbg_set_timestamp_and_cpu(&lostevent, barrier_min, 0);
717*0f4c859eSApple OSS Distributions 			*tempbuf = lostevent;
718*0f4c859eSApple OSS Distributions 			wrapped = false;
719*0f4c859eSApple OSS Distributions 			goto nextevent;
720*0f4c859eSApple OSS Distributions 		}
721*0f4c859eSApple OSS Distributions 
722*0f4c859eSApple OSS Distributions 		/* While space left in merged events scratch buffer. */
723*0f4c859eSApple OSS Distributions 		while (tempbuf_count) {
724*0f4c859eSApple OSS Distributions 			bool lostevents = false;
725*0f4c859eSApple OSS Distributions 			int lostcpu = 0;
726*0f4c859eSApple OSS Distributions 			earliest_time = UINT64_MAX;
727*0f4c859eSApple OSS Distributions 			min_kdbp = NULL;
728*0f4c859eSApple OSS Distributions 			min_cpu = 0;
729*0f4c859eSApple OSS Distributions 
730*0f4c859eSApple OSS Distributions 			/* Check each CPU's buffers for the earliest event. */
731*0f4c859eSApple OSS Distributions 			for (cpu = 0, kdbp = &kdbip[0]; cpu < kd_ctrl_page->kdebug_cpus; cpu++, kdbp++) {
732*0f4c859eSApple OSS Distributions 				/* Skip CPUs without data in their oldest storage unit. */
733*0f4c859eSApple OSS Distributions 				if ((kdsp = kdbp->kd_list_head).raw == KDS_PTR_NULL) {
734*0f4c859eSApple OSS Distributions next_cpu:
735*0f4c859eSApple OSS Distributions 					continue;
736*0f4c859eSApple OSS Distributions 				}
737*0f4c859eSApple OSS Distributions 				/* From CPU data to buffer header to buffer. */
738*0f4c859eSApple OSS Distributions 				kdsp_actual = POINTER_FROM_KDS_PTR(kd_bufs, kdsp);
739*0f4c859eSApple OSS Distributions 
740*0f4c859eSApple OSS Distributions next_event:
741*0f4c859eSApple OSS Distributions 				/* The next event to be read from this buffer. */
742*0f4c859eSApple OSS Distributions 				rcursor = kdsp_actual->kds_readlast;
743*0f4c859eSApple OSS Distributions 
744*0f4c859eSApple OSS Distributions 				/* Skip this buffer if there are no events left. */
745*0f4c859eSApple OSS Distributions 				if (rcursor == kdsp_actual->kds_bufindx) {
746*0f4c859eSApple OSS Distributions 					continue;
747*0f4c859eSApple OSS Distributions 				}
748*0f4c859eSApple OSS Distributions 
749*0f4c859eSApple OSS Distributions 				if (kd_ctrl_page->mode == KDEBUG_MODE_TRIAGE) {
750*0f4c859eSApple OSS Distributions 					/*
751*0f4c859eSApple OSS Distributions 					 * TRIAGE mode record keeping doesn't (currently)
752*0f4c859eSApple OSS Distributions 					 * use lostevent markers. It also doesn't want to
753*0f4c859eSApple OSS Distributions 					 * call release_storage_unit() in this read call.
754*0f4c859eSApple OSS Distributions 					 * It expects the buffers to wrap and records reclaimed
755*0f4c859eSApple OSS Distributions 					 * in that way solely.
756*0f4c859eSApple OSS Distributions 					 */
757*0f4c859eSApple OSS Distributions 					t = kdbg_get_timestamp(&kdsp_actual->kds_records[rcursor]);
758*0f4c859eSApple OSS Distributions 					goto skip_record_checks;
759*0f4c859eSApple OSS Distributions 				}
760*0f4c859eSApple OSS Distributions 
761*0f4c859eSApple OSS Distributions 				/*
762*0f4c859eSApple OSS Distributions 				 * Check that this storage unit wasn't stolen and events were
763*0f4c859eSApple OSS Distributions 				 * lost.  This must have happened while wrapping was disabled
764*0f4c859eSApple OSS Distributions 				 * in this function.
765*0f4c859eSApple OSS Distributions 				 */
766*0f4c859eSApple OSS Distributions 				if (kdsp_actual->kds_lostevents) {
767*0f4c859eSApple OSS Distributions 					lostevents = true;
768*0f4c859eSApple OSS Distributions 					kdsp_actual->kds_lostevents = false;
769*0f4c859eSApple OSS Distributions 
770*0f4c859eSApple OSS Distributions 					/*
771*0f4c859eSApple OSS Distributions 					 * The earliest event we can trust is the first one in this
772*0f4c859eSApple OSS Distributions 					 * stolen storage unit.
773*0f4c859eSApple OSS Distributions 					 */
774*0f4c859eSApple OSS Distributions 					uint64_t lost_time =
775*0f4c859eSApple OSS Distributions 					    kdbg_get_timestamp(&kdsp_actual->kds_records[0]);
776*0f4c859eSApple OSS Distributions 					if (kd_ctrl_page->kdc_oldest_time < lost_time) {
777*0f4c859eSApple OSS Distributions 						/*
778*0f4c859eSApple OSS Distributions 						 * If this is the first time we've seen lost events for
779*0f4c859eSApple OSS Distributions 						 * this gap, record its timestamp as the oldest
780*0f4c859eSApple OSS Distributions 						 * timestamp we're willing to merge for the lost events
781*0f4c859eSApple OSS Distributions 						 * tracepoint.
782*0f4c859eSApple OSS Distributions 						 */
783*0f4c859eSApple OSS Distributions 						kd_ctrl_page->kdc_oldest_time = barrier_min = lost_time;
784*0f4c859eSApple OSS Distributions 						lostcpu = cpu;
785*0f4c859eSApple OSS Distributions 					}
786*0f4c859eSApple OSS Distributions 				}
787*0f4c859eSApple OSS Distributions 
788*0f4c859eSApple OSS Distributions 				t = kdbg_get_timestamp(&kdsp_actual->kds_records[rcursor]);
789*0f4c859eSApple OSS Distributions 
790*0f4c859eSApple OSS Distributions 				if (t > barrier_max) {
791*0f4c859eSApple OSS Distributions 					goto next_cpu;
792*0f4c859eSApple OSS Distributions 				}
793*0f4c859eSApple OSS Distributions 				if (t < kdsp_actual->kds_timestamp) {
794*0f4c859eSApple OSS Distributions 					/*
795*0f4c859eSApple OSS Distributions 					 * This indicates the event emitter hasn't completed
796*0f4c859eSApple OSS Distributions 					 * filling in the event (becuase we're looking at the
797*0f4c859eSApple OSS Distributions 					 * buffer that the record head is using).  The max barrier
798*0f4c859eSApple OSS Distributions 					 * timestamp should have saved us from seeing these kinds
799*0f4c859eSApple OSS Distributions 					 * of things, but other CPUs might be slow on the up-take.
800*0f4c859eSApple OSS Distributions 					 *
801*0f4c859eSApple OSS Distributions 					 * Bail out so we don't get out-of-order events by
802*0f4c859eSApple OSS Distributions 					 * continuing to read events from other CPUs' events.
803*0f4c859eSApple OSS Distributions 					 */
804*0f4c859eSApple OSS Distributions 					out_of_events = true;
805*0f4c859eSApple OSS Distributions 					break;
806*0f4c859eSApple OSS Distributions 				}
807*0f4c859eSApple OSS Distributions 
808*0f4c859eSApple OSS Distributions 				/*
809*0f4c859eSApple OSS Distributions 				 * Ignore events that have aged out due to wrapping or storage
810*0f4c859eSApple OSS Distributions 				 * unit exhaustion while merging events.
811*0f4c859eSApple OSS Distributions 				 */
812*0f4c859eSApple OSS Distributions 				if (t < barrier_min) {
813*0f4c859eSApple OSS Distributions 					kdsp_actual->kds_readlast++;
814*0f4c859eSApple OSS Distributions 					if (kdsp_actual->kds_readlast >= kd_ctrl_page->kdebug_events_per_storage_unit) {
815*0f4c859eSApple OSS Distributions 						release_storage_unit(kd_ctrl_page, kd_data_page, cpu, kdsp.raw);
816*0f4c859eSApple OSS Distributions 
817*0f4c859eSApple OSS Distributions 						if ((kdsp = kdbp->kd_list_head).raw == KDS_PTR_NULL) {
818*0f4c859eSApple OSS Distributions 							goto next_cpu;
819*0f4c859eSApple OSS Distributions 						}
820*0f4c859eSApple OSS Distributions 						kdsp_actual = POINTER_FROM_KDS_PTR(kd_bufs, kdsp);
821*0f4c859eSApple OSS Distributions 					}
822*0f4c859eSApple OSS Distributions 					goto next_event;
823*0f4c859eSApple OSS Distributions 				}
824*0f4c859eSApple OSS Distributions 
825*0f4c859eSApple OSS Distributions 				/*
826*0f4c859eSApple OSS Distributions 				 * Don't worry about merging any events -- just walk through
827*0f4c859eSApple OSS Distributions 				 * the CPUs and find the latest timestamp of lost events.
828*0f4c859eSApple OSS Distributions 				 */
829*0f4c859eSApple OSS Distributions 				if (lostevents) {
830*0f4c859eSApple OSS Distributions 					continue;
831*0f4c859eSApple OSS Distributions 				}
832*0f4c859eSApple OSS Distributions skip_record_checks:
833*0f4c859eSApple OSS Distributions 				if (t < earliest_time) {
834*0f4c859eSApple OSS Distributions 					earliest_time = t;
835*0f4c859eSApple OSS Distributions 					min_kdbp = kdbp;
836*0f4c859eSApple OSS Distributions 					min_cpu = cpu;
837*0f4c859eSApple OSS Distributions 				}
838*0f4c859eSApple OSS Distributions 			}
839*0f4c859eSApple OSS Distributions 			if (lostevents) {
840*0f4c859eSApple OSS Distributions 				/*
841*0f4c859eSApple OSS Distributions 				 * If any lost events were hit in the buffers, emit an event
842*0f4c859eSApple OSS Distributions 				 * with the latest timestamp.
843*0f4c859eSApple OSS Distributions 				 */
844*0f4c859eSApple OSS Distributions 				kdbg_set_timestamp_and_cpu(&lostevent, barrier_min, lostcpu);
845*0f4c859eSApple OSS Distributions 				*tempbuf = lostevent;
846*0f4c859eSApple OSS Distributions 				tempbuf->arg1 = 1;
847*0f4c859eSApple OSS Distributions 				goto nextevent;
848*0f4c859eSApple OSS Distributions 			}
849*0f4c859eSApple OSS Distributions 			if (min_kdbp == NULL) {
850*0f4c859eSApple OSS Distributions 				/* All buffers ran empty. */
851*0f4c859eSApple OSS Distributions 				out_of_events = true;
852*0f4c859eSApple OSS Distributions 			}
853*0f4c859eSApple OSS Distributions 			if (out_of_events) {
854*0f4c859eSApple OSS Distributions 				break;
855*0f4c859eSApple OSS Distributions 			}
856*0f4c859eSApple OSS Distributions 
857*0f4c859eSApple OSS Distributions 			kdsp = min_kdbp->kd_list_head;
858*0f4c859eSApple OSS Distributions 			kdsp_actual = POINTER_FROM_KDS_PTR(kd_bufs, kdsp);
859*0f4c859eSApple OSS Distributions 
860*0f4c859eSApple OSS Distributions 			if (min_kdbp->latest_past_event_timestamp != 0) {
861*0f4c859eSApple OSS Distributions 				if (kdbg_debug) {
862*0f4c859eSApple OSS Distributions 					printf("kdebug: PAST EVENT: debugid %#8x: "
863*0f4c859eSApple OSS Distributions 					    "time %lld from CPU %u "
864*0f4c859eSApple OSS Distributions 					    "(barrier at time %lld)\n",
865*0f4c859eSApple OSS Distributions 					    kdsp_actual->kds_records[rcursor].debugid,
866*0f4c859eSApple OSS Distributions 					    t, cpu, barrier_min);
867*0f4c859eSApple OSS Distributions 				}
868*0f4c859eSApple OSS Distributions 
869*0f4c859eSApple OSS Distributions 				kdbg_set_timestamp_and_cpu(tempbuf, earliest_time, min_cpu);
870*0f4c859eSApple OSS Distributions 				tempbuf->arg1 = (kd_buf_argtype)min_kdbp->latest_past_event_timestamp;
871*0f4c859eSApple OSS Distributions 				tempbuf->arg2 = 0;
872*0f4c859eSApple OSS Distributions 				tempbuf->arg3 = 0;
873*0f4c859eSApple OSS Distributions 				tempbuf->arg4 = 0;
874*0f4c859eSApple OSS Distributions 				tempbuf->debugid = TRACE_PAST_EVENTS;
875*0f4c859eSApple OSS Distributions 				min_kdbp->latest_past_event_timestamp = 0;
876*0f4c859eSApple OSS Distributions 				goto nextevent;
877*0f4c859eSApple OSS Distributions 			}
878*0f4c859eSApple OSS Distributions 
879*0f4c859eSApple OSS Distributions 			/* Copy earliest event into merged events scratch buffer. */
880*0f4c859eSApple OSS Distributions 			*tempbuf = kdsp_actual->kds_records[kdsp_actual->kds_readlast++];
881*0f4c859eSApple OSS Distributions 			kd_buf *earliest_event = tempbuf;
882*0f4c859eSApple OSS Distributions 			if (kd_control_trace.kdc_flags & KDBG_MATCH_DISABLE) {
883*0f4c859eSApple OSS Distributions 				kd_event_matcher *match = &kd_control_trace.disable_event_match;
884*0f4c859eSApple OSS Distributions 				kd_event_matcher *mask = &kd_control_trace.disable_event_mask;
885*0f4c859eSApple OSS Distributions 				if ((earliest_event->debugid & mask->kem_debugid) == match->kem_debugid &&
886*0f4c859eSApple OSS Distributions 				    (earliest_event->arg1 & mask->kem_args[0]) == match->kem_args[0] &&
887*0f4c859eSApple OSS Distributions 				    (earliest_event->arg2 & mask->kem_args[1]) == match->kem_args[1] &&
888*0f4c859eSApple OSS Distributions 				    (earliest_event->arg3 & mask->kem_args[2]) == match->kem_args[2] &&
889*0f4c859eSApple OSS Distributions 				    (earliest_event->arg4 & mask->kem_args[3]) == match->kem_args[3]) {
890*0f4c859eSApple OSS Distributions 					should_disable = true;
891*0f4c859eSApple OSS Distributions 				}
892*0f4c859eSApple OSS Distributions 			}
893*0f4c859eSApple OSS Distributions 
894*0f4c859eSApple OSS Distributions 			if (kd_ctrl_page->mode == KDEBUG_MODE_TRACE) {
895*0f4c859eSApple OSS Distributions 				if (kdsp_actual->kds_readlast == kd_ctrl_page->kdebug_events_per_storage_unit) {
896*0f4c859eSApple OSS Distributions 					release_storage_unit(kd_ctrl_page, kd_data_page, min_cpu, kdsp.raw);
897*0f4c859eSApple OSS Distributions 				}
898*0f4c859eSApple OSS Distributions 			}
899*0f4c859eSApple OSS Distributions 
900*0f4c859eSApple OSS Distributions 			/*
901*0f4c859eSApple OSS Distributions 			 * Watch for out of order timestamps (from IOPs).
902*0f4c859eSApple OSS Distributions 			 */
903*0f4c859eSApple OSS Distributions 			if (earliest_time < min_kdbp->kd_prev_timebase) {
904*0f4c859eSApple OSS Distributions 				/*
905*0f4c859eSApple OSS Distributions 				 * If we haven't already, emit a retrograde events event.
906*0f4c859eSApple OSS Distributions 				 * Otherwise, ignore this event.
907*0f4c859eSApple OSS Distributions 				 */
908*0f4c859eSApple OSS Distributions 				if (traced_retrograde) {
909*0f4c859eSApple OSS Distributions 					continue;
910*0f4c859eSApple OSS Distributions 				}
911*0f4c859eSApple OSS Distributions 				if (kdbg_debug) {
912*0f4c859eSApple OSS Distributions 					printf("kdebug: RETRO EVENT: debugid %#8x: "
913*0f4c859eSApple OSS Distributions 					    "time %lld from CPU %u "
914*0f4c859eSApple OSS Distributions 					    "(barrier at time %lld)\n",
915*0f4c859eSApple OSS Distributions 					    kdsp_actual->kds_records[rcursor].debugid,
916*0f4c859eSApple OSS Distributions 					    t, cpu, barrier_min);
917*0f4c859eSApple OSS Distributions 				}
918*0f4c859eSApple OSS Distributions 
919*0f4c859eSApple OSS Distributions 				kdbg_set_timestamp_and_cpu(tempbuf, min_kdbp->kd_prev_timebase,
920*0f4c859eSApple OSS Distributions 				    kdbg_get_cpu(tempbuf));
921*0f4c859eSApple OSS Distributions 				tempbuf->arg1 = tempbuf->debugid;
922*0f4c859eSApple OSS Distributions 				tempbuf->arg2 = (kd_buf_argtype)earliest_time;
923*0f4c859eSApple OSS Distributions 				tempbuf->arg3 = 0;
924*0f4c859eSApple OSS Distributions 				tempbuf->arg4 = 0;
925*0f4c859eSApple OSS Distributions 				tempbuf->debugid = TRACE_RETROGRADE_EVENTS;
926*0f4c859eSApple OSS Distributions 				traced_retrograde = true;
927*0f4c859eSApple OSS Distributions 			} else {
928*0f4c859eSApple OSS Distributions 				min_kdbp->kd_prev_timebase = earliest_time;
929*0f4c859eSApple OSS Distributions 			}
930*0f4c859eSApple OSS Distributions nextevent:
931*0f4c859eSApple OSS Distributions 			tempbuf_count--;
932*0f4c859eSApple OSS Distributions 			tempbuf_number++;
933*0f4c859eSApple OSS Distributions 			tempbuf++;
934*0f4c859eSApple OSS Distributions 
935*0f4c859eSApple OSS Distributions 			if (kd_ctrl_page->mode == KDEBUG_MODE_TRACE &&
936*0f4c859eSApple OSS Distributions 			    (RAW_file_written += sizeof(kd_buf)) >= RAW_FLUSH_SIZE) {
937*0f4c859eSApple OSS Distributions 				break;
938*0f4c859eSApple OSS Distributions 			}
939*0f4c859eSApple OSS Distributions 		}
940*0f4c859eSApple OSS Distributions 
941*0f4c859eSApple OSS Distributions 		if (tempbuf_number) {
942*0f4c859eSApple OSS Distributions 			/*
943*0f4c859eSApple OSS Distributions 			 * Remember the latest timestamp of events that we've merged so we
944*0f4c859eSApple OSS Distributions 			 * don't think we've lost events later.
945*0f4c859eSApple OSS Distributions 			 */
946*0f4c859eSApple OSS Distributions 			uint64_t latest_time = kdbg_get_timestamp(tempbuf - 1);
947*0f4c859eSApple OSS Distributions 			if (kd_ctrl_page->kdc_oldest_time < latest_time) {
948*0f4c859eSApple OSS Distributions 				kd_ctrl_page->kdc_oldest_time = latest_time;
949*0f4c859eSApple OSS Distributions 			}
950*0f4c859eSApple OSS Distributions 
951*0f4c859eSApple OSS Distributions 			if (kd_ctrl_page->mode == KDEBUG_MODE_TRACE) {
952*0f4c859eSApple OSS Distributions 				extern int kernel_debug_trace_write_to_file(user_addr_t *buffer,
953*0f4c859eSApple OSS Distributions 				    size_t *number, size_t *count, size_t tempbuf_number,
954*0f4c859eSApple OSS Distributions 				    vnode_t vp, vfs_context_t ctx, uint32_t file_version);
955*0f4c859eSApple OSS Distributions 				error = kernel_debug_trace_write_to_file(&buffer, number,
956*0f4c859eSApple OSS Distributions 				    &count, tempbuf_number, vp, ctx, file_version);
957*0f4c859eSApple OSS Distributions 			} else if (kd_ctrl_page->mode == KDEBUG_MODE_TRIAGE) {
958*0f4c859eSApple OSS Distributions 				memcpy((void*)buffer, kd_data_page->kdcopybuf,
959*0f4c859eSApple OSS Distributions 				    tempbuf_number * sizeof(kd_buf));
960*0f4c859eSApple OSS Distributions 				buffer += tempbuf_number * sizeof(kd_buf);
961*0f4c859eSApple OSS Distributions 			} else {
962*0f4c859eSApple OSS Distributions 				panic("kdebug: invalid kdebug mode %d", kd_ctrl_page->mode);
963*0f4c859eSApple OSS Distributions 			}
964*0f4c859eSApple OSS Distributions 			if (error) {
965*0f4c859eSApple OSS Distributions 				*number = 0;
966*0f4c859eSApple OSS Distributions 				error = EINVAL;
967*0f4c859eSApple OSS Distributions 				break;
968*0f4c859eSApple OSS Distributions 			}
969*0f4c859eSApple OSS Distributions 			count   -= tempbuf_number;
970*0f4c859eSApple OSS Distributions 			*number += tempbuf_number;
971*0f4c859eSApple OSS Distributions 		}
972*0f4c859eSApple OSS Distributions 		if (out_of_events) {
973*0f4c859eSApple OSS Distributions 			break;
974*0f4c859eSApple OSS Distributions 		}
975*0f4c859eSApple OSS Distributions 
976*0f4c859eSApple OSS Distributions 		if ((tempbuf_count = count) > kd_ctrl_page->kdebug_kdcopybuf_count) {
977*0f4c859eSApple OSS Distributions 			tempbuf_count = kd_ctrl_page->kdebug_kdcopybuf_count;
978*0f4c859eSApple OSS Distributions 		}
979*0f4c859eSApple OSS Distributions 	}
980*0f4c859eSApple OSS Distributions 	if ((old_live_flags & KDBG_NOWRAP) == 0) {
981*0f4c859eSApple OSS Distributions 		_enable_wrap(kd_ctrl_page, old_emit);
982*0f4c859eSApple OSS Distributions 	}
983*0f4c859eSApple OSS Distributions 
984*0f4c859eSApple OSS Distributions 	if (set_preempt) {
985*0f4c859eSApple OSS Distributions 		thread_clear_eager_preempt(current_thread());
986*0f4c859eSApple OSS Distributions 	}
987*0f4c859eSApple OSS Distributions 
988*0f4c859eSApple OSS Distributions 	if (should_disable) {
989*0f4c859eSApple OSS Distributions 		kernel_debug_disable();
990*0f4c859eSApple OSS Distributions 	}
991*0f4c859eSApple OSS Distributions 
992*0f4c859eSApple OSS Distributions 	return error;
993*0f4c859eSApple OSS Distributions }
994