]>
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> | |
6b746eb4 | 29 | #include <os/availability.h> |
beb15981 A |
30 | #include <os/base_private.h> |
31 | #include <dispatch/dispatch.h> | |
32 | #endif | |
33 | ||
6b746eb4 | 34 | #define OS_FIREHOSE_SPI_VERSION 20170222 |
beb15981 A |
35 | |
36 | /*! | |
37 | * @group Firehose SPI | |
38 | * SPI intended for logd only | |
39 | * Layout of structs is subject to change without notice | |
40 | */ | |
41 | ||
beb15981 A |
42 | #define FIREHOSE_BUFFER_LIBTRACE_HEADER_SIZE 2048ul |
43 | #define FIREHOSE_BUFFER_KERNEL_CHUNK_COUNT 16 | |
44 | ||
beb15981 A |
45 | typedef struct firehose_buffer_range_s { |
46 | uint16_t fbr_offset; // offset from the start of the buffer | |
47 | uint16_t fbr_length; | |
48 | } *firehose_buffer_range_t; | |
49 | ||
50 | #ifdef KERNEL | |
51 | ||
fa22f35b A |
52 | typedef struct firehose_chunk_s *firehose_chunk_t; |
53 | ||
beb15981 A |
54 | // implemented by the kernel |
55 | extern void __firehose_buffer_push_to_logd(firehose_buffer_t fb, bool for_io); | |
56 | extern void __firehose_critical_region_enter(void); | |
57 | extern void __firehose_critical_region_leave(void); | |
58 | extern void __firehose_allocate(vm_offset_t *addr, vm_size_t size); | |
59 | ||
60 | // exported for the kernel | |
61 | firehose_tracepoint_t | |
62 | __firehose_buffer_tracepoint_reserve(uint64_t stamp, firehose_stream_t stream, | |
63 | uint16_t pubsize, uint16_t privsize, uint8_t **privptr); | |
64 | ||
beb15981 A |
65 | void |
66 | __firehose_buffer_tracepoint_flush(firehose_tracepoint_t vat, | |
67 | firehose_tracepoint_id_u vatid); | |
68 | ||
beb15981 A |
69 | firehose_buffer_t |
70 | __firehose_buffer_create(size_t *size); | |
71 | ||
72 | void | |
73 | __firehose_merge_updates(firehose_push_reply_t update); | |
74 | ||
75 | #else | |
76 | ||
77 | #define __firehose_critical_region_enter() | |
78 | #define __firehose_critical_region_leave() | |
79 | ||
80 | OS_EXPORT | |
81 | const uint32_t _firehose_spi_version; | |
82 | ||
83 | OS_ALWAYS_INLINE | |
84 | static inline const uint8_t * | |
fa22f35b | 85 | _firehose_tracepoint_reader_init(firehose_chunk_t fc, const uint8_t **endptr) |
beb15981 | 86 | { |
fa22f35b A |
87 | const uint8_t *start = fc->fc_data; |
88 | const uint8_t *end = fc->fc_start + fc->fc_pos.fcp_next_entry_offs; | |
beb15981 | 89 | |
fa22f35b | 90 | if (end > fc->fc_start + FIREHOSE_CHUNK_SIZE) { |
beb15981 A |
91 | end = start; |
92 | } | |
93 | *endptr = end; | |
94 | return start; | |
95 | } | |
96 | ||
97 | OS_ALWAYS_INLINE | |
98 | static inline firehose_tracepoint_t | |
99 | _firehose_tracepoint_reader_next(const uint8_t **ptr, const uint8_t *end) | |
100 | { | |
101 | const uint16_t ft_size = offsetof(struct firehose_tracepoint_s, ft_data); | |
fa22f35b A |
102 | struct ft_unaligned_s { |
103 | struct firehose_tracepoint_s ft; | |
104 | } __attribute__((packed, aligned(1))) *uft; | |
beb15981 A |
105 | |
106 | do { | |
fa22f35b A |
107 | uft = (struct ft_unaligned_s *)*ptr; |
108 | if (uft->ft.ft_data >= end) { | |
beb15981 A |
109 | // reached the end |
110 | return NULL; | |
111 | } | |
fa22f35b | 112 | if (!uft->ft.ft_length) { |
beb15981 A |
113 | // tracepoint write didn't even start |
114 | return NULL; | |
115 | } | |
fa22f35b | 116 | if (uft->ft.ft_length > end - uft->ft.ft_data) { |
beb15981 A |
117 | // invalid length |
118 | return NULL; | |
119 | } | |
fa22f35b | 120 | *ptr += roundup(ft_size + uft->ft.ft_length, 8); |
beb15981 | 121 | // test whether write of the tracepoint was finished |
fa22f35b | 122 | } while (os_unlikely(uft->ft.ft_id.ftid_value == 0)); |
beb15981 | 123 | |
fa22f35b | 124 | return (firehose_tracepoint_t)uft; |
beb15981 A |
125 | } |
126 | ||
127 | #define firehose_tracepoint_foreach(ft, fbc) \ | |
128 | for (const uint8_t *end, *p = _firehose_tracepoint_reader_init(fbc, &end); \ | |
129 | ((ft) = _firehose_tracepoint_reader_next(&p, end)); ) | |
130 | ||
131 | OS_ALWAYS_INLINE | |
132 | static inline bool | |
fa22f35b A |
133 | firehose_buffer_range_validate(firehose_chunk_t fc, firehose_tracepoint_t ft, |
134 | firehose_buffer_range_t range) | |
beb15981 | 135 | { |
fa22f35b | 136 | if (range->fbr_offset + range->fbr_length > FIREHOSE_CHUNK_SIZE) { |
beb15981 A |
137 | return false; |
138 | } | |
fa22f35b | 139 | if (fc->fc_start + range->fbr_offset < ft->ft_data + ft->ft_length) { |
beb15981 A |
140 | return false; |
141 | } | |
142 | return true; | |
143 | } | |
144 | ||
145 | #endif // !KERNEL | |
146 | ||
147 | #endif // OS_FIREHOSE_SPI | |
148 | ||
149 | #endif // __FIREHOSE_BUFFER_PRIVATE__ |