]>
Commit | Line | Data |
---|---|---|
beb15981 A |
1 | /* |
2 | * Copyright (c) 2015 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_APACHE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
7 | * you may not use this file except in compliance with the License. | |
8 | * You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, software | |
13 | * distributed under the License is distributed on an "AS IS" BASIS, | |
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 | * See the License for the specific language governing permissions and | |
16 | * limitations under the License. | |
17 | * | |
18 | * @APPLE_APACHE_LICENSE_HEADER_END@ | |
19 | */ | |
20 | ||
21 | #ifndef __FIREHOSE_BUFFER_PRIVATE__ | |
22 | #define __FIREHOSE_BUFFER_PRIVATE__ | |
23 | ||
24 | #if OS_FIREHOSE_SPI | |
25 | #ifdef KERNEL | |
26 | #include <stdint.h> | |
27 | #else | |
28 | #include <os/base.h> | |
29 | #include <os/base_private.h> | |
30 | #include <dispatch/dispatch.h> | |
31 | #endif | |
32 | ||
33 | #define OS_FIREHOSE_SPI_VERSION 20160318 | |
34 | ||
35 | /*! | |
36 | * @group Firehose SPI | |
37 | * SPI intended for logd only | |
38 | * Layout of structs is subject to change without notice | |
39 | */ | |
40 | ||
41 | #define FIREHOSE_BUFFER_CHUNK_SIZE 4096ul | |
42 | #define FIREHOSE_BUFFER_LIBTRACE_HEADER_SIZE 2048ul | |
43 | #define FIREHOSE_BUFFER_KERNEL_CHUNK_COUNT 16 | |
44 | ||
45 | typedef union { | |
46 | uint64_t fbc_atomic_pos; | |
47 | #define FIREHOSE_BUFFER_POS_ENTRY_OFFS_INC (1ULL << 0) | |
48 | #define FIREHOSE_BUFFER_POS_PRIVATE_OFFS_INC (1ULL << 16) | |
49 | #define FIREHOSE_BUFFER_POS_REFCNT_INC (1ULL << 32) | |
50 | #define FIREHOSE_BUFFER_POS_FULL_BIT (1ULL << 56) | |
51 | #define FIREHOSE_BUFFER_POS_USABLE_FOR_STREAM(pos, stream) \ | |
52 | ((((pos).fbc_atomic_pos >> 48) & 0x1ff) == (uint16_t)stream) | |
53 | struct { | |
54 | uint16_t fbc_next_entry_offs; | |
55 | uint16_t fbc_private_offs; | |
56 | uint8_t fbc_refcnt; | |
57 | uint8_t fbc_qos_bits; | |
58 | uint8_t fbc_stream; | |
59 | uint8_t fbc_flag_full : 1; | |
60 | uint8_t fbc_flag_io : 1; | |
61 | uint8_t _fbc_flag_unused : 6; | |
62 | }; | |
63 | } firehose_buffer_pos_u; | |
64 | ||
65 | typedef struct firehose_buffer_chunk_s { | |
66 | uint8_t fbc_start[0]; | |
67 | firehose_buffer_pos_u volatile fbc_pos; | |
68 | uint64_t fbc_timestamp; | |
69 | uint8_t fbc_data[FIREHOSE_BUFFER_CHUNK_SIZE | |
70 | - sizeof(firehose_buffer_pos_u) | |
71 | - sizeof(uint64_t)]; | |
72 | } __attribute__((aligned(8))) *firehose_buffer_chunk_t; | |
73 | ||
74 | typedef struct firehose_buffer_range_s { | |
75 | uint16_t fbr_offset; // offset from the start of the buffer | |
76 | uint16_t fbr_length; | |
77 | } *firehose_buffer_range_t; | |
78 | ||
79 | #ifdef KERNEL | |
80 | ||
81 | // implemented by the kernel | |
82 | extern void __firehose_buffer_push_to_logd(firehose_buffer_t fb, bool for_io); | |
83 | extern void __firehose_critical_region_enter(void); | |
84 | extern void __firehose_critical_region_leave(void); | |
85 | extern void __firehose_allocate(vm_offset_t *addr, vm_size_t size); | |
86 | ||
87 | // exported for the kernel | |
88 | firehose_tracepoint_t | |
89 | __firehose_buffer_tracepoint_reserve(uint64_t stamp, firehose_stream_t stream, | |
90 | uint16_t pubsize, uint16_t privsize, uint8_t **privptr); | |
91 | ||
92 | firehose_tracepoint_t | |
93 | __firehose_buffer_tracepoint_reserve_with_chunk(firehose_buffer_chunk_t fbc, | |
94 | uint64_t stamp, firehose_stream_t stream, | |
95 | uint16_t pubsize, uint16_t privsize, uint8_t **privptr); | |
96 | ||
97 | void | |
98 | __firehose_buffer_tracepoint_flush(firehose_tracepoint_t vat, | |
99 | firehose_tracepoint_id_u vatid); | |
100 | ||
101 | void | |
102 | __firehose_buffer_tracepoint_flush_chunk(firehose_buffer_chunk_t fbc, | |
103 | firehose_tracepoint_t vat, firehose_tracepoint_id_u vatid); | |
104 | ||
105 | firehose_buffer_t | |
106 | __firehose_buffer_create(size_t *size); | |
107 | ||
108 | void | |
109 | __firehose_merge_updates(firehose_push_reply_t update); | |
110 | ||
111 | #else | |
112 | ||
113 | #define __firehose_critical_region_enter() | |
114 | #define __firehose_critical_region_leave() | |
115 | ||
116 | OS_EXPORT | |
117 | const uint32_t _firehose_spi_version; | |
118 | ||
119 | OS_ALWAYS_INLINE | |
120 | static inline const uint8_t * | |
121 | _firehose_tracepoint_reader_init(firehose_buffer_chunk_t fbc, | |
122 | const uint8_t **endptr) | |
123 | { | |
124 | const uint8_t *start = fbc->fbc_data; | |
125 | const uint8_t *end = fbc->fbc_start + fbc->fbc_pos.fbc_next_entry_offs; | |
126 | ||
127 | if (end > fbc->fbc_start + FIREHOSE_BUFFER_CHUNK_SIZE) { | |
128 | end = start; | |
129 | } | |
130 | *endptr = end; | |
131 | return start; | |
132 | } | |
133 | ||
134 | OS_ALWAYS_INLINE | |
135 | static inline firehose_tracepoint_t | |
136 | _firehose_tracepoint_reader_next(const uint8_t **ptr, const uint8_t *end) | |
137 | { | |
138 | const uint16_t ft_size = offsetof(struct firehose_tracepoint_s, ft_data); | |
139 | firehose_tracepoint_t ft; | |
140 | ||
141 | do { | |
142 | ft = (firehose_tracepoint_t)*ptr; | |
143 | if (ft->ft_data >= end) { | |
144 | // reached the end | |
145 | return NULL; | |
146 | } | |
147 | if (!ft->ft_length) { | |
148 | // tracepoint write didn't even start | |
149 | return NULL; | |
150 | } | |
151 | if (ft->ft_length > end - ft->ft_data) { | |
152 | // invalid length | |
153 | return NULL; | |
154 | } | |
155 | *ptr += roundup(ft_size + ft->ft_length, 8); | |
156 | // test whether write of the tracepoint was finished | |
157 | } while (os_unlikely(ft->ft_id.ftid_value == 0)); | |
158 | ||
159 | return ft; | |
160 | } | |
161 | ||
162 | #define firehose_tracepoint_foreach(ft, fbc) \ | |
163 | for (const uint8_t *end, *p = _firehose_tracepoint_reader_init(fbc, &end); \ | |
164 | ((ft) = _firehose_tracepoint_reader_next(&p, end)); ) | |
165 | ||
166 | OS_ALWAYS_INLINE | |
167 | static inline bool | |
168 | firehose_buffer_range_validate(firehose_buffer_chunk_t fbc, | |
169 | firehose_tracepoint_t ft, firehose_buffer_range_t range) | |
170 | { | |
171 | if (range->fbr_offset + range->fbr_length > FIREHOSE_BUFFER_CHUNK_SIZE) { | |
172 | return false; | |
173 | } | |
174 | if (fbc->fbc_start + range->fbr_offset < ft->ft_data + ft->ft_length) { | |
175 | return false; | |
176 | } | |
177 | return true; | |
178 | } | |
179 | ||
180 | #endif // !KERNEL | |
181 | ||
182 | #endif // OS_FIREHOSE_SPI | |
183 | ||
184 | #endif // __FIREHOSE_BUFFER_PRIVATE__ |