xref: /openbmc/linux/tools/testing/selftests/bpf/progs/verifier_scalar_ids.c (revision 16f6ccde74a6f8538c62f127f17207c75f4dba7a)
1dec02028SEduard Zingerman // SPDX-License-Identifier: GPL-2.0
2dec02028SEduard Zingerman 
3dec02028SEduard Zingerman #include <linux/bpf.h>
4dec02028SEduard Zingerman #include <bpf/bpf_helpers.h>
5dec02028SEduard Zingerman #include "bpf_misc.h"
6dec02028SEduard Zingerman 
7dec02028SEduard Zingerman /* Check that precision marks propagate through scalar IDs.
8dec02028SEduard Zingerman  * Registers r{0,1,2} have the same scalar ID at the moment when r0 is
9dec02028SEduard Zingerman  * marked to be precise, this mark is immediately propagated to r{1,2}.
10dec02028SEduard Zingerman  */
11dec02028SEduard Zingerman SEC("socket")
12dec02028SEduard Zingerman __success __log_level(2)
13dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r2 stack= before 4: (bf) r3 = r10")
14dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r2 stack= before 3: (bf) r2 = r0")
15dec02028SEduard Zingerman __msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
16dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
17dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 0: (85) call bpf_ktime_get_ns")
__flag(BPF_F_TEST_STATE_FREQ)18dec02028SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
19dec02028SEduard Zingerman __naked void precision_same_state(void)
20dec02028SEduard Zingerman {
21dec02028SEduard Zingerman 	asm volatile (
22dec02028SEduard Zingerman 	/* r0 = random number up to 0xff */
23dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
24dec02028SEduard Zingerman 	"r0 &= 0xff;"
25dec02028SEduard Zingerman 	/* tie r0.id == r1.id == r2.id */
26dec02028SEduard Zingerman 	"r1 = r0;"
27dec02028SEduard Zingerman 	"r2 = r0;"
28dec02028SEduard Zingerman 	/* force r0 to be precise, this immediately marks r1 and r2 as
29dec02028SEduard Zingerman 	 * precise as well because of shared IDs
30dec02028SEduard Zingerman 	 */
31dec02028SEduard Zingerman 	"r3 = r10;"
32dec02028SEduard Zingerman 	"r3 += r0;"
33dec02028SEduard Zingerman 	"r0 = 0;"
34dec02028SEduard Zingerman 	"exit;"
35dec02028SEduard Zingerman 	:
36dec02028SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
37dec02028SEduard Zingerman 	: __clobber_all);
38dec02028SEduard Zingerman }
39dec02028SEduard Zingerman 
40dec02028SEduard Zingerman /* Same as precision_same_state, but mark propagates through state /
41dec02028SEduard Zingerman  * parent state boundary.
42dec02028SEduard Zingerman  */
43dec02028SEduard Zingerman SEC("socket")
44dec02028SEduard Zingerman __success __log_level(2)
45dec02028SEduard Zingerman __msg("frame0: last_idx 6 first_idx 5 subseq_idx -1")
46dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r2 stack= before 5: (bf) r3 = r10")
47dec02028SEduard Zingerman __msg("frame0: parent state regs=r0,r1,r2 stack=:")
48dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r2 stack= before 4: (05) goto pc+0")
49dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r2 stack= before 3: (bf) r2 = r0")
50dec02028SEduard Zingerman __msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
51dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
52dec02028SEduard Zingerman __msg("frame0: parent state regs=r0 stack=:")
53dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 0: (85) call bpf_ktime_get_ns")
__flag(BPF_F_TEST_STATE_FREQ)54dec02028SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
55dec02028SEduard Zingerman __naked void precision_cross_state(void)
56dec02028SEduard Zingerman {
57dec02028SEduard Zingerman 	asm volatile (
58dec02028SEduard Zingerman 	/* r0 = random number up to 0xff */
59dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
60dec02028SEduard Zingerman 	"r0 &= 0xff;"
61dec02028SEduard Zingerman 	/* tie r0.id == r1.id == r2.id */
62dec02028SEduard Zingerman 	"r1 = r0;"
63dec02028SEduard Zingerman 	"r2 = r0;"
64dec02028SEduard Zingerman 	/* force checkpoint */
65dec02028SEduard Zingerman 	"goto +0;"
66dec02028SEduard Zingerman 	/* force r0 to be precise, this immediately marks r1 and r2 as
67dec02028SEduard Zingerman 	 * precise as well because of shared IDs
68dec02028SEduard Zingerman 	 */
69dec02028SEduard Zingerman 	"r3 = r10;"
70dec02028SEduard Zingerman 	"r3 += r0;"
71dec02028SEduard Zingerman 	"r0 = 0;"
72dec02028SEduard Zingerman 	"exit;"
73dec02028SEduard Zingerman 	:
74dec02028SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
75dec02028SEduard Zingerman 	: __clobber_all);
76dec02028SEduard Zingerman }
77dec02028SEduard Zingerman 
78dec02028SEduard Zingerman /* Same as precision_same_state, but break one of the
79dec02028SEduard Zingerman  * links, note that r1 is absent from regs=... in __msg below.
80dec02028SEduard Zingerman  */
81dec02028SEduard Zingerman SEC("socket")
82dec02028SEduard Zingerman __success __log_level(2)
83dec02028SEduard Zingerman __msg("frame0: regs=r0,r2 stack= before 5: (bf) r3 = r10")
84dec02028SEduard Zingerman __msg("frame0: regs=r0,r2 stack= before 4: (b7) r1 = 0")
85dec02028SEduard Zingerman __msg("frame0: regs=r0,r2 stack= before 3: (bf) r2 = r0")
86dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 2: (bf) r1 = r0")
87dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
88dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 0: (85) call bpf_ktime_get_ns")
__flag(BPF_F_TEST_STATE_FREQ)89dec02028SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
90dec02028SEduard Zingerman __naked void precision_same_state_broken_link(void)
91dec02028SEduard Zingerman {
92dec02028SEduard Zingerman 	asm volatile (
93dec02028SEduard Zingerman 	/* r0 = random number up to 0xff */
94dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
95dec02028SEduard Zingerman 	"r0 &= 0xff;"
96dec02028SEduard Zingerman 	/* tie r0.id == r1.id == r2.id */
97dec02028SEduard Zingerman 	"r1 = r0;"
98dec02028SEduard Zingerman 	"r2 = r0;"
99dec02028SEduard Zingerman 	/* break link for r1, this is the only line that differs
100dec02028SEduard Zingerman 	 * compared to the previous test
101dec02028SEduard Zingerman 	 */
102dec02028SEduard Zingerman 	"r1 = 0;"
103dec02028SEduard Zingerman 	/* force r0 to be precise, this immediately marks r1 and r2 as
104dec02028SEduard Zingerman 	 * precise as well because of shared IDs
105dec02028SEduard Zingerman 	 */
106dec02028SEduard Zingerman 	"r3 = r10;"
107dec02028SEduard Zingerman 	"r3 += r0;"
108dec02028SEduard Zingerman 	"r0 = 0;"
109dec02028SEduard Zingerman 	"exit;"
110dec02028SEduard Zingerman 	:
111dec02028SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
112dec02028SEduard Zingerman 	: __clobber_all);
113dec02028SEduard Zingerman }
114dec02028SEduard Zingerman 
115dec02028SEduard Zingerman /* Same as precision_same_state_broken_link, but with state /
116dec02028SEduard Zingerman  * parent state boundary.
117dec02028SEduard Zingerman  */
118dec02028SEduard Zingerman SEC("socket")
119dec02028SEduard Zingerman __success __log_level(2)
120dec02028SEduard Zingerman __msg("frame0: regs=r0,r2 stack= before 6: (bf) r3 = r10")
121dec02028SEduard Zingerman __msg("frame0: regs=r0,r2 stack= before 5: (b7) r1 = 0")
122dec02028SEduard Zingerman __msg("frame0: parent state regs=r0,r2 stack=:")
123dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r2 stack= before 4: (05) goto pc+0")
124dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r2 stack= before 3: (bf) r2 = r0")
125dec02028SEduard Zingerman __msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
126dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
127dec02028SEduard Zingerman __msg("frame0: parent state regs=r0 stack=:")
128dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 0: (85) call bpf_ktime_get_ns")
__flag(BPF_F_TEST_STATE_FREQ)129dec02028SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
130dec02028SEduard Zingerman __naked void precision_cross_state_broken_link(void)
131dec02028SEduard Zingerman {
132dec02028SEduard Zingerman 	asm volatile (
133dec02028SEduard Zingerman 	/* r0 = random number up to 0xff */
134dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
135dec02028SEduard Zingerman 	"r0 &= 0xff;"
136dec02028SEduard Zingerman 	/* tie r0.id == r1.id == r2.id */
137dec02028SEduard Zingerman 	"r1 = r0;"
138dec02028SEduard Zingerman 	"r2 = r0;"
139dec02028SEduard Zingerman 	/* force checkpoint, although link between r1 and r{0,2} is
140dec02028SEduard Zingerman 	 * broken by the next statement current precision tracking
141dec02028SEduard Zingerman 	 * algorithm can't react to it and propagates mark for r1 to
142dec02028SEduard Zingerman 	 * the parent state.
143dec02028SEduard Zingerman 	 */
144dec02028SEduard Zingerman 	"goto +0;"
145dec02028SEduard Zingerman 	/* break link for r1, this is the only line that differs
146dec02028SEduard Zingerman 	 * compared to precision_cross_state()
147dec02028SEduard Zingerman 	 */
148dec02028SEduard Zingerman 	"r1 = 0;"
149dec02028SEduard Zingerman 	/* force r0 to be precise, this immediately marks r1 and r2 as
150dec02028SEduard Zingerman 	 * precise as well because of shared IDs
151dec02028SEduard Zingerman 	 */
152dec02028SEduard Zingerman 	"r3 = r10;"
153dec02028SEduard Zingerman 	"r3 += r0;"
154dec02028SEduard Zingerman 	"r0 = 0;"
155dec02028SEduard Zingerman 	"exit;"
156dec02028SEduard Zingerman 	:
157dec02028SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
158dec02028SEduard Zingerman 	: __clobber_all);
159dec02028SEduard Zingerman }
160dec02028SEduard Zingerman 
161dec02028SEduard Zingerman /* Check that precision marks propagate through scalar IDs.
162dec02028SEduard Zingerman  * Use the same scalar ID in multiple stack frames, check that
163dec02028SEduard Zingerman  * precision information is propagated up the call stack.
164dec02028SEduard Zingerman  */
165dec02028SEduard Zingerman SEC("socket")
166dec02028SEduard Zingerman __success __log_level(2)
167dec02028SEduard Zingerman __msg("11: (0f) r2 += r1")
168dec02028SEduard Zingerman /* Current state */
169dec02028SEduard Zingerman __msg("frame2: last_idx 11 first_idx 10 subseq_idx -1")
170dec02028SEduard Zingerman __msg("frame2: regs=r1 stack= before 10: (bf) r2 = r10")
171dec02028SEduard Zingerman __msg("frame2: parent state regs=r1 stack=")
172dec02028SEduard Zingerman /* frame1.r{6,7} are marked because mark_precise_scalar_ids()
173dec02028SEduard Zingerman  * looks for all registers with frame2.r1.id in the current state
174dec02028SEduard Zingerman  */
175dec02028SEduard Zingerman __msg("frame1: parent state regs=r6,r7 stack=")
176dec02028SEduard Zingerman __msg("frame0: parent state regs=r6 stack=")
177dec02028SEduard Zingerman /* Parent state */
178dec02028SEduard Zingerman __msg("frame2: last_idx 8 first_idx 8 subseq_idx 10")
179dec02028SEduard Zingerman __msg("frame2: regs=r1 stack= before 8: (85) call pc+1")
180dec02028SEduard Zingerman /* frame1.r1 is marked because of backtracking of call instruction */
181dec02028SEduard Zingerman __msg("frame1: parent state regs=r1,r6,r7 stack=")
182dec02028SEduard Zingerman __msg("frame0: parent state regs=r6 stack=")
183dec02028SEduard Zingerman /* Parent state */
184dec02028SEduard Zingerman __msg("frame1: last_idx 7 first_idx 6 subseq_idx 8")
185dec02028SEduard Zingerman __msg("frame1: regs=r1,r6,r7 stack= before 7: (bf) r7 = r1")
186dec02028SEduard Zingerman __msg("frame1: regs=r1,r6 stack= before 6: (bf) r6 = r1")
187dec02028SEduard Zingerman __msg("frame1: parent state regs=r1 stack=")
188dec02028SEduard Zingerman __msg("frame0: parent state regs=r6 stack=")
189dec02028SEduard Zingerman /* Parent state */
190dec02028SEduard Zingerman __msg("frame1: last_idx 4 first_idx 4 subseq_idx 6")
191dec02028SEduard Zingerman __msg("frame1: regs=r1 stack= before 4: (85) call pc+1")
192dec02028SEduard Zingerman __msg("frame0: parent state regs=r1,r6 stack=")
193dec02028SEduard Zingerman /* Parent state */
194dec02028SEduard Zingerman __msg("frame0: last_idx 3 first_idx 1 subseq_idx 4")
195dec02028SEduard Zingerman __msg("frame0: regs=r0,r1,r6 stack= before 3: (bf) r6 = r0")
196dec02028SEduard Zingerman __msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
197dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
__flag(BPF_F_TEST_STATE_FREQ)198dec02028SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
199dec02028SEduard Zingerman __naked void precision_many_frames(void)
200dec02028SEduard Zingerman {
201dec02028SEduard Zingerman 	asm volatile (
202dec02028SEduard Zingerman 	/* r0 = random number up to 0xff */
203dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
204dec02028SEduard Zingerman 	"r0 &= 0xff;"
205dec02028SEduard Zingerman 	/* tie r0.id == r1.id == r6.id */
206dec02028SEduard Zingerman 	"r1 = r0;"
207dec02028SEduard Zingerman 	"r6 = r0;"
208dec02028SEduard Zingerman 	"call precision_many_frames__foo;"
209dec02028SEduard Zingerman 	"exit;"
210dec02028SEduard Zingerman 	:
211dec02028SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
212dec02028SEduard Zingerman 	: __clobber_all);
213dec02028SEduard Zingerman }
214dec02028SEduard Zingerman 
215dec02028SEduard Zingerman static __naked __noinline __used
precision_many_frames__foo(void)216dec02028SEduard Zingerman void precision_many_frames__foo(void)
217dec02028SEduard Zingerman {
218dec02028SEduard Zingerman 	asm volatile (
219dec02028SEduard Zingerman 	/* conflate one of the register numbers (r6) with outer frame,
220dec02028SEduard Zingerman 	 * to verify that those are tracked independently
221dec02028SEduard Zingerman 	 */
222dec02028SEduard Zingerman 	"r6 = r1;"
223dec02028SEduard Zingerman 	"r7 = r1;"
224dec02028SEduard Zingerman 	"call precision_many_frames__bar;"
225dec02028SEduard Zingerman 	"exit"
226dec02028SEduard Zingerman 	::: __clobber_all);
227dec02028SEduard Zingerman }
228dec02028SEduard Zingerman 
229dec02028SEduard Zingerman static __naked __noinline __used
precision_many_frames__bar(void)230dec02028SEduard Zingerman void precision_many_frames__bar(void)
231dec02028SEduard Zingerman {
232dec02028SEduard Zingerman 	asm volatile (
233dec02028SEduard Zingerman 	/* force r1 to be precise, this immediately marks:
234dec02028SEduard Zingerman 	 * - bar frame r1
235dec02028SEduard Zingerman 	 * - foo frame r{1,6,7}
236dec02028SEduard Zingerman 	 * - main frame r{1,6}
237dec02028SEduard Zingerman 	 */
238dec02028SEduard Zingerman 	"r2 = r10;"
239dec02028SEduard Zingerman 	"r2 += r1;"
240dec02028SEduard Zingerman 	"r0 = 0;"
241dec02028SEduard Zingerman 	"exit;"
242dec02028SEduard Zingerman 	::: __clobber_all);
243dec02028SEduard Zingerman }
244dec02028SEduard Zingerman 
245dec02028SEduard Zingerman /* Check that scalars with the same IDs are marked precise on stack as
246dec02028SEduard Zingerman  * well as in registers.
247dec02028SEduard Zingerman  */
248dec02028SEduard Zingerman SEC("socket")
249dec02028SEduard Zingerman __success __log_level(2)
250dec02028SEduard Zingerman /* foo frame */
251dec02028SEduard Zingerman __msg("frame1: regs=r1 stack=-8,-16 before 9: (bf) r2 = r10")
252dec02028SEduard Zingerman __msg("frame1: regs=r1 stack=-8,-16 before 8: (7b) *(u64 *)(r10 -16) = r1")
253dec02028SEduard Zingerman __msg("frame1: regs=r1 stack=-8 before 7: (7b) *(u64 *)(r10 -8) = r1")
254dec02028SEduard Zingerman __msg("frame1: regs=r1 stack= before 4: (85) call pc+2")
255dec02028SEduard Zingerman /* main frame */
256dec02028SEduard Zingerman __msg("frame0: regs=r0,r1 stack=-8 before 3: (7b) *(u64 *)(r10 -8) = r1")
257dec02028SEduard Zingerman __msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
258dec02028SEduard Zingerman __msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
__flag(BPF_F_TEST_STATE_FREQ)259dec02028SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
260dec02028SEduard Zingerman __naked void precision_stack(void)
261dec02028SEduard Zingerman {
262dec02028SEduard Zingerman 	asm volatile (
263dec02028SEduard Zingerman 	/* r0 = random number up to 0xff */
264dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
265dec02028SEduard Zingerman 	"r0 &= 0xff;"
266dec02028SEduard Zingerman 	/* tie r0.id == r1.id == fp[-8].id */
267dec02028SEduard Zingerman 	"r1 = r0;"
268dec02028SEduard Zingerman 	"*(u64*)(r10 - 8) = r1;"
269dec02028SEduard Zingerman 	"call precision_stack__foo;"
270dec02028SEduard Zingerman 	"r0 = 0;"
271dec02028SEduard Zingerman 	"exit;"
272dec02028SEduard Zingerman 	:
273dec02028SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
274dec02028SEduard Zingerman 	: __clobber_all);
275dec02028SEduard Zingerman }
276dec02028SEduard Zingerman 
277dec02028SEduard Zingerman static __naked __noinline __used
precision_stack__foo(void)278dec02028SEduard Zingerman void precision_stack__foo(void)
279dec02028SEduard Zingerman {
280dec02028SEduard Zingerman 	asm volatile (
281dec02028SEduard Zingerman 	/* conflate one of the register numbers (r6) with outer frame,
282dec02028SEduard Zingerman 	 * to verify that those are tracked independently
283dec02028SEduard Zingerman 	 */
284dec02028SEduard Zingerman 	"*(u64*)(r10 - 8) = r1;"
285dec02028SEduard Zingerman 	"*(u64*)(r10 - 16) = r1;"
286dec02028SEduard Zingerman 	/* force r1 to be precise, this immediately marks:
287dec02028SEduard Zingerman 	 * - foo frame r1,fp{-8,-16}
288dec02028SEduard Zingerman 	 * - main frame r1,fp{-8}
289dec02028SEduard Zingerman 	 */
290dec02028SEduard Zingerman 	"r2 = r10;"
291dec02028SEduard Zingerman 	"r2 += r1;"
292dec02028SEduard Zingerman 	"exit"
293dec02028SEduard Zingerman 	::: __clobber_all);
294dec02028SEduard Zingerman }
295dec02028SEduard Zingerman 
296dec02028SEduard Zingerman /* Use two separate scalar IDs to check that these are propagated
297dec02028SEduard Zingerman  * independently.
298dec02028SEduard Zingerman  */
299dec02028SEduard Zingerman SEC("socket")
300dec02028SEduard Zingerman __success __log_level(2)
301dec02028SEduard Zingerman /* r{6,7} */
302dec02028SEduard Zingerman __msg("11: (0f) r3 += r7")
303dec02028SEduard Zingerman __msg("frame0: regs=r6,r7 stack= before 10: (bf) r3 = r10")
304dec02028SEduard Zingerman /* ... skip some insns ... */
305dec02028SEduard Zingerman __msg("frame0: regs=r6,r7 stack= before 3: (bf) r7 = r0")
306dec02028SEduard Zingerman __msg("frame0: regs=r0,r6 stack= before 2: (bf) r6 = r0")
307dec02028SEduard Zingerman /* r{8,9} */
308dec02028SEduard Zingerman __msg("12: (0f) r3 += r9")
309dec02028SEduard Zingerman __msg("frame0: regs=r8,r9 stack= before 11: (0f) r3 += r7")
310dec02028SEduard Zingerman /* ... skip some insns ... */
311dec02028SEduard Zingerman __msg("frame0: regs=r8,r9 stack= before 7: (bf) r9 = r0")
312dec02028SEduard Zingerman __msg("frame0: regs=r0,r8 stack= before 6: (bf) r8 = r0")
__flag(BPF_F_TEST_STATE_FREQ)313dec02028SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
314dec02028SEduard Zingerman __naked void precision_two_ids(void)
315dec02028SEduard Zingerman {
316dec02028SEduard Zingerman 	asm volatile (
317dec02028SEduard Zingerman 	/* r6 = random number up to 0xff
318dec02028SEduard Zingerman 	 * r6.id == r7.id
319dec02028SEduard Zingerman 	 */
320dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
321dec02028SEduard Zingerman 	"r0 &= 0xff;"
322dec02028SEduard Zingerman 	"r6 = r0;"
323dec02028SEduard Zingerman 	"r7 = r0;"
324dec02028SEduard Zingerman 	/* same, but for r{8,9} */
325dec02028SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
326dec02028SEduard Zingerman 	"r0 &= 0xff;"
327dec02028SEduard Zingerman 	"r8 = r0;"
328dec02028SEduard Zingerman 	"r9 = r0;"
329dec02028SEduard Zingerman 	/* clear r0 id */
330dec02028SEduard Zingerman 	"r0 = 0;"
331dec02028SEduard Zingerman 	/* force checkpoint */
332dec02028SEduard Zingerman 	"goto +0;"
333dec02028SEduard Zingerman 	"r3 = r10;"
334dec02028SEduard Zingerman 	/* force r7 to be precise, this also marks r6 */
335dec02028SEduard Zingerman 	"r3 += r7;"
336dec02028SEduard Zingerman 	/* force r9 to be precise, this also marks r8 */
337dec02028SEduard Zingerman 	"r3 += r9;"
338dec02028SEduard Zingerman 	"exit;"
339dec02028SEduard Zingerman 	:
340dec02028SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
341dec02028SEduard Zingerman 	: __clobber_all);
342dec02028SEduard Zingerman }
343dec02028SEduard Zingerman 
34418b89265SEduard Zingerman /* Verify that check_ids() is used by regsafe() for scalars.
34518b89265SEduard Zingerman  *
34618b89265SEduard Zingerman  * r9 = ... some pointer with range X ...
34718b89265SEduard Zingerman  * r6 = ... unbound scalar ID=a ...
34818b89265SEduard Zingerman  * r7 = ... unbound scalar ID=b ...
34918b89265SEduard Zingerman  * if (r6 > r7) goto +1
35018b89265SEduard Zingerman  * r7 = r6
35118b89265SEduard Zingerman  * if (r7 > X) goto exit
35218b89265SEduard Zingerman  * r9 += r6
35318b89265SEduard Zingerman  * ... access memory using r9 ...
35418b89265SEduard Zingerman  *
35518b89265SEduard Zingerman  * The memory access is safe only if r7 is bounded,
35618b89265SEduard Zingerman  * which is true for one branch and not true for another.
35718b89265SEduard Zingerman  */
35818b89265SEduard Zingerman SEC("socket")
35918b89265SEduard Zingerman __failure __msg("register with unbounded min value")
__flag(BPF_F_TEST_STATE_FREQ)36018b89265SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
36118b89265SEduard Zingerman __naked void check_ids_in_regsafe(void)
36218b89265SEduard Zingerman {
36318b89265SEduard Zingerman 	asm volatile (
36418b89265SEduard Zingerman 	/* Bump allocated stack */
36518b89265SEduard Zingerman 	"r1 = 0;"
36618b89265SEduard Zingerman 	"*(u64*)(r10 - 8) = r1;"
36718b89265SEduard Zingerman 	/* r9 = pointer to stack */
36818b89265SEduard Zingerman 	"r9 = r10;"
36918b89265SEduard Zingerman 	"r9 += -8;"
37018b89265SEduard Zingerman 	/* r7 = ktime_get_ns() */
37118b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
37218b89265SEduard Zingerman 	"r7 = r0;"
37318b89265SEduard Zingerman 	/* r6 = ktime_get_ns() */
37418b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
37518b89265SEduard Zingerman 	"r6 = r0;"
37618b89265SEduard Zingerman 	/* if r6 > r7 is an unpredictable jump */
37718b89265SEduard Zingerman 	"if r6 > r7 goto l1_%=;"
37818b89265SEduard Zingerman 	"r7 = r6;"
37918b89265SEduard Zingerman "l1_%=:"
38018b89265SEduard Zingerman 	/* if r7 > 4 ...; transfers range to r6 on one execution path
38118b89265SEduard Zingerman 	 * but does not transfer on another
38218b89265SEduard Zingerman 	 */
38318b89265SEduard Zingerman 	"if r7 > 4 goto l2_%=;"
38418b89265SEduard Zingerman 	/* Access memory at r9[r6], r6 is not always bounded */
38518b89265SEduard Zingerman 	"r9 += r6;"
38618b89265SEduard Zingerman 	"r0 = *(u8*)(r9 + 0);"
38718b89265SEduard Zingerman "l2_%=:"
38818b89265SEduard Zingerman 	"r0 = 0;"
38918b89265SEduard Zingerman 	"exit;"
39018b89265SEduard Zingerman 	:
39118b89265SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
39218b89265SEduard Zingerman 	: __clobber_all);
39318b89265SEduard Zingerman }
39418b89265SEduard Zingerman 
39518b89265SEduard Zingerman /* Similar to check_ids_in_regsafe.
39618b89265SEduard Zingerman  * The l0 could be reached in two states:
39718b89265SEduard Zingerman  *
39818b89265SEduard Zingerman  *   (1) r6{.id=A}, r7{.id=A}, r8{.id=B}
39918b89265SEduard Zingerman  *   (2) r6{.id=B}, r7{.id=A}, r8{.id=B}
40018b89265SEduard Zingerman  *
40118b89265SEduard Zingerman  * Where (2) is not safe, as "r7 > 4" check won't propagate range for it.
40218b89265SEduard Zingerman  * This example would be considered safe without changes to
40318b89265SEduard Zingerman  * mark_chain_precision() to track scalar values with equal IDs.
40418b89265SEduard Zingerman  */
40518b89265SEduard Zingerman SEC("socket")
40618b89265SEduard Zingerman __failure __msg("register with unbounded min value")
__flag(BPF_F_TEST_STATE_FREQ)40718b89265SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
40818b89265SEduard Zingerman __naked void check_ids_in_regsafe_2(void)
40918b89265SEduard Zingerman {
41018b89265SEduard Zingerman 	asm volatile (
41118b89265SEduard Zingerman 	/* Bump allocated stack */
41218b89265SEduard Zingerman 	"r1 = 0;"
41318b89265SEduard Zingerman 	"*(u64*)(r10 - 8) = r1;"
41418b89265SEduard Zingerman 	/* r9 = pointer to stack */
41518b89265SEduard Zingerman 	"r9 = r10;"
41618b89265SEduard Zingerman 	"r9 += -8;"
41718b89265SEduard Zingerman 	/* r8 = ktime_get_ns() */
41818b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
41918b89265SEduard Zingerman 	"r8 = r0;"
42018b89265SEduard Zingerman 	/* r7 = ktime_get_ns() */
42118b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
42218b89265SEduard Zingerman 	"r7 = r0;"
42318b89265SEduard Zingerman 	/* r6 = ktime_get_ns() */
42418b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
42518b89265SEduard Zingerman 	"r6 = r0;"
42618b89265SEduard Zingerman 	/* scratch .id from r0 */
42718b89265SEduard Zingerman 	"r0 = 0;"
42818b89265SEduard Zingerman 	/* if r6 > r7 is an unpredictable jump */
42918b89265SEduard Zingerman 	"if r6 > r7 goto l1_%=;"
43018b89265SEduard Zingerman 	/* tie r6 and r7 .id */
43118b89265SEduard Zingerman 	"r6 = r7;"
43218b89265SEduard Zingerman "l0_%=:"
43318b89265SEduard Zingerman 	/* if r7 > 4 exit(0) */
43418b89265SEduard Zingerman 	"if r7 > 4 goto l2_%=;"
43518b89265SEduard Zingerman 	/* Access memory at r9[r6] */
43618b89265SEduard Zingerman 	"r9 += r6;"
43718b89265SEduard Zingerman 	"r0 = *(u8*)(r9 + 0);"
43818b89265SEduard Zingerman "l2_%=:"
43918b89265SEduard Zingerman 	"r0 = 0;"
44018b89265SEduard Zingerman 	"exit;"
44118b89265SEduard Zingerman "l1_%=:"
44218b89265SEduard Zingerman 	/* tie r6 and r8 .id */
44318b89265SEduard Zingerman 	"r6 = r8;"
44418b89265SEduard Zingerman 	"goto l0_%=;"
44518b89265SEduard Zingerman 	:
44618b89265SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
44718b89265SEduard Zingerman 	: __clobber_all);
44818b89265SEduard Zingerman }
44918b89265SEduard Zingerman 
45018b89265SEduard Zingerman /* Check that scalar IDs *are not* generated on register to register
45118b89265SEduard Zingerman  * assignments if source register is a constant.
45218b89265SEduard Zingerman  *
45318b89265SEduard Zingerman  * If such IDs *are* generated the 'l1' below would be reached in
45418b89265SEduard Zingerman  * two states:
45518b89265SEduard Zingerman  *
45618b89265SEduard Zingerman  *   (1) r1{.id=A}, r2{.id=A}
45718b89265SEduard Zingerman  *   (2) r1{.id=C}, r2{.id=C}
45818b89265SEduard Zingerman  *
45918b89265SEduard Zingerman  * Thus forcing 'if r1 == r2' verification twice.
46018b89265SEduard Zingerman  */
46118b89265SEduard Zingerman SEC("socket")
46218b89265SEduard Zingerman __success __log_level(2)
46318b89265SEduard Zingerman __msg("11: (1d) if r3 == r4 goto pc+0")
46418b89265SEduard Zingerman __msg("frame 0: propagating r3,r4")
46518b89265SEduard Zingerman __msg("11: safe")
46618b89265SEduard Zingerman __msg("processed 15 insns")
__flag(BPF_F_TEST_STATE_FREQ)46718b89265SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
46818b89265SEduard Zingerman __naked void no_scalar_id_for_const(void)
46918b89265SEduard Zingerman {
47018b89265SEduard Zingerman 	asm volatile (
47118b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
47218b89265SEduard Zingerman 	/* unpredictable jump */
47318b89265SEduard Zingerman 	"if r0 > 7 goto l0_%=;"
47418b89265SEduard Zingerman 	/* possibly generate same scalar ids for r3 and r4 */
47518b89265SEduard Zingerman 	"r1 = 0;"
47618b89265SEduard Zingerman 	"r1 = r1;"
47718b89265SEduard Zingerman 	"r3 = r1;"
47818b89265SEduard Zingerman 	"r4 = r1;"
47918b89265SEduard Zingerman 	"goto l1_%=;"
48018b89265SEduard Zingerman "l0_%=:"
48118b89265SEduard Zingerman 	/* possibly generate different scalar ids for r3 and r4 */
48218b89265SEduard Zingerman 	"r1 = 0;"
48318b89265SEduard Zingerman 	"r2 = 0;"
48418b89265SEduard Zingerman 	"r3 = r1;"
48518b89265SEduard Zingerman 	"r4 = r2;"
48618b89265SEduard Zingerman "l1_%=:"
48718b89265SEduard Zingerman 	/* predictable jump, marks r3 and r4 precise */
48818b89265SEduard Zingerman 	"if r3 == r4 goto +0;"
48918b89265SEduard Zingerman 	"r0 = 0;"
49018b89265SEduard Zingerman 	"exit;"
49118b89265SEduard Zingerman 	:
49218b89265SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
49318b89265SEduard Zingerman 	: __clobber_all);
49418b89265SEduard Zingerman }
49518b89265SEduard Zingerman 
49618b89265SEduard Zingerman /* Same as no_scalar_id_for_const() but for 32-bit values */
49718b89265SEduard Zingerman SEC("socket")
49818b89265SEduard Zingerman __success __log_level(2)
49918b89265SEduard Zingerman __msg("11: (1e) if w3 == w4 goto pc+0")
50018b89265SEduard Zingerman __msg("frame 0: propagating r3,r4")
50118b89265SEduard Zingerman __msg("11: safe")
50218b89265SEduard Zingerman __msg("processed 15 insns")
__flag(BPF_F_TEST_STATE_FREQ)50318b89265SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
50418b89265SEduard Zingerman __naked void no_scalar_id_for_const32(void)
50518b89265SEduard Zingerman {
50618b89265SEduard Zingerman 	asm volatile (
50718b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
50818b89265SEduard Zingerman 	/* unpredictable jump */
50918b89265SEduard Zingerman 	"if r0 > 7 goto l0_%=;"
51018b89265SEduard Zingerman 	/* possibly generate same scalar ids for r3 and r4 */
51118b89265SEduard Zingerman 	"w1 = 0;"
51218b89265SEduard Zingerman 	"w1 = w1;"
51318b89265SEduard Zingerman 	"w3 = w1;"
51418b89265SEduard Zingerman 	"w4 = w1;"
51518b89265SEduard Zingerman 	"goto l1_%=;"
51618b89265SEduard Zingerman "l0_%=:"
51718b89265SEduard Zingerman 	/* possibly generate different scalar ids for r3 and r4 */
51818b89265SEduard Zingerman 	"w1 = 0;"
51918b89265SEduard Zingerman 	"w2 = 0;"
52018b89265SEduard Zingerman 	"w3 = w1;"
52118b89265SEduard Zingerman 	"w4 = w2;"
52218b89265SEduard Zingerman "l1_%=:"
52318b89265SEduard Zingerman 	/* predictable jump, marks r1 and r2 precise */
52418b89265SEduard Zingerman 	"if w3 == w4 goto +0;"
52518b89265SEduard Zingerman 	"r0 = 0;"
52618b89265SEduard Zingerman 	"exit;"
52718b89265SEduard Zingerman 	:
52818b89265SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
52918b89265SEduard Zingerman 	: __clobber_all);
53018b89265SEduard Zingerman }
53118b89265SEduard Zingerman 
53218b89265SEduard Zingerman /* Check that unique scalar IDs are ignored when new verifier state is
53318b89265SEduard Zingerman  * compared to cached verifier state. For this test:
53418b89265SEduard Zingerman  * - cached state has no id on r1
53518b89265SEduard Zingerman  * - new state has a unique id on r1
53618b89265SEduard Zingerman  */
53718b89265SEduard Zingerman SEC("socket")
53818b89265SEduard Zingerman __success __log_level(2)
53918b89265SEduard Zingerman __msg("6: (25) if r6 > 0x7 goto pc+1")
54018b89265SEduard Zingerman __msg("7: (57) r1 &= 255")
54118b89265SEduard Zingerman __msg("8: (bf) r2 = r10")
54218b89265SEduard Zingerman __msg("from 6 to 8: safe")
54318b89265SEduard Zingerman __msg("processed 12 insns")
__flag(BPF_F_TEST_STATE_FREQ)54418b89265SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
54518b89265SEduard Zingerman __naked void ignore_unique_scalar_ids_cur(void)
54618b89265SEduard Zingerman {
54718b89265SEduard Zingerman 	asm volatile (
54818b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
54918b89265SEduard Zingerman 	"r6 = r0;"
55018b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
55118b89265SEduard Zingerman 	"r0 &= 0xff;"
55218b89265SEduard Zingerman 	/* r1.id == r0.id */
55318b89265SEduard Zingerman 	"r1 = r0;"
55418b89265SEduard Zingerman 	/* make r1.id unique */
55518b89265SEduard Zingerman 	"r0 = 0;"
55618b89265SEduard Zingerman 	"if r6 > 7 goto l0_%=;"
55718b89265SEduard Zingerman 	/* clear r1 id, but keep the range compatible */
55818b89265SEduard Zingerman 	"r1 &= 0xff;"
55918b89265SEduard Zingerman "l0_%=:"
56018b89265SEduard Zingerman 	/* get here in two states:
56118b89265SEduard Zingerman 	 * - first: r1 has no id (cached state)
56218b89265SEduard Zingerman 	 * - second: r1 has a unique id (should be considered equivalent)
56318b89265SEduard Zingerman 	 */
56418b89265SEduard Zingerman 	"r2 = r10;"
56518b89265SEduard Zingerman 	"r2 += r1;"
56618b89265SEduard Zingerman 	"exit;"
56718b89265SEduard Zingerman 	:
56818b89265SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
56918b89265SEduard Zingerman 	: __clobber_all);
57018b89265SEduard Zingerman }
57118b89265SEduard Zingerman 
57218b89265SEduard Zingerman /* Check that unique scalar IDs are ignored when new verifier state is
57318b89265SEduard Zingerman  * compared to cached verifier state. For this test:
57418b89265SEduard Zingerman  * - cached state has a unique id on r1
57518b89265SEduard Zingerman  * - new state has no id on r1
57618b89265SEduard Zingerman  */
57718b89265SEduard Zingerman SEC("socket")
57818b89265SEduard Zingerman __success __log_level(2)
57918b89265SEduard Zingerman __msg("6: (25) if r6 > 0x7 goto pc+1")
58018b89265SEduard Zingerman __msg("7: (05) goto pc+1")
58118b89265SEduard Zingerman __msg("9: (bf) r2 = r10")
58218b89265SEduard Zingerman __msg("9: safe")
58318b89265SEduard Zingerman __msg("processed 13 insns")
__flag(BPF_F_TEST_STATE_FREQ)58418b89265SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
58518b89265SEduard Zingerman __naked void ignore_unique_scalar_ids_old(void)
58618b89265SEduard Zingerman {
58718b89265SEduard Zingerman 	asm volatile (
58818b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
58918b89265SEduard Zingerman 	"r6 = r0;"
59018b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
59118b89265SEduard Zingerman 	"r0 &= 0xff;"
59218b89265SEduard Zingerman 	/* r1.id == r0.id */
59318b89265SEduard Zingerman 	"r1 = r0;"
59418b89265SEduard Zingerman 	/* make r1.id unique */
59518b89265SEduard Zingerman 	"r0 = 0;"
59618b89265SEduard Zingerman 	"if r6 > 7 goto l1_%=;"
59718b89265SEduard Zingerman 	"goto l0_%=;"
59818b89265SEduard Zingerman "l1_%=:"
59918b89265SEduard Zingerman 	/* clear r1 id, but keep the range compatible */
60018b89265SEduard Zingerman 	"r1 &= 0xff;"
60118b89265SEduard Zingerman "l0_%=:"
60218b89265SEduard Zingerman 	/* get here in two states:
60318b89265SEduard Zingerman 	 * - first: r1 has a unique id (cached state)
60418b89265SEduard Zingerman 	 * - second: r1 has no id (should be considered equivalent)
60518b89265SEduard Zingerman 	 */
60618b89265SEduard Zingerman 	"r2 = r10;"
60718b89265SEduard Zingerman 	"r2 += r1;"
60818b89265SEduard Zingerman 	"exit;"
60918b89265SEduard Zingerman 	:
61018b89265SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
61118b89265SEduard Zingerman 	: __clobber_all);
61218b89265SEduard Zingerman }
61318b89265SEduard Zingerman 
61418b89265SEduard Zingerman /* Check that two different scalar IDs in a verified state can't be
61518b89265SEduard Zingerman  * mapped to the same scalar ID in current state.
61618b89265SEduard Zingerman  */
61718b89265SEduard Zingerman SEC("socket")
61818b89265SEduard Zingerman __success __log_level(2)
61918b89265SEduard Zingerman /* The exit instruction should be reachable from two states,
62018b89265SEduard Zingerman  * use two matches and "processed .. insns" to ensure this.
62118b89265SEduard Zingerman  */
62218b89265SEduard Zingerman __msg("13: (95) exit")
62318b89265SEduard Zingerman __msg("13: (95) exit")
62418b89265SEduard Zingerman __msg("processed 18 insns")
__flag(BPF_F_TEST_STATE_FREQ)62518b89265SEduard Zingerman __flag(BPF_F_TEST_STATE_FREQ)
62618b89265SEduard Zingerman __naked void two_old_ids_one_cur_id(void)
62718b89265SEduard Zingerman {
62818b89265SEduard Zingerman 	asm volatile (
62918b89265SEduard Zingerman 	/* Give unique scalar IDs to r{6,7} */
63018b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
63118b89265SEduard Zingerman 	"r0 &= 0xff;"
63218b89265SEduard Zingerman 	"r6 = r0;"
63318b89265SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
63418b89265SEduard Zingerman 	"r0 &= 0xff;"
63518b89265SEduard Zingerman 	"r7 = r0;"
63618b89265SEduard Zingerman 	"r0 = 0;"
63718b89265SEduard Zingerman 	/* Maybe make r{6,7} IDs identical */
63818b89265SEduard Zingerman 	"if r6 > r7 goto l0_%=;"
63918b89265SEduard Zingerman 	"goto l1_%=;"
64018b89265SEduard Zingerman "l0_%=:"
64118b89265SEduard Zingerman 	"r6 = r7;"
64218b89265SEduard Zingerman "l1_%=:"
64318b89265SEduard Zingerman 	/* Mark r{6,7} precise.
64418b89265SEduard Zingerman 	 * Get here in two states:
64518b89265SEduard Zingerman 	 * - first:  r6{.id=A}, r7{.id=B} (cached state)
64618b89265SEduard Zingerman 	 * - second: r6{.id=A}, r7{.id=A}
64718b89265SEduard Zingerman 	 * Currently we don't want to consider such states equivalent.
64818b89265SEduard Zingerman 	 * Thus "exit;" would be verified twice.
64918b89265SEduard Zingerman 	 */
65018b89265SEduard Zingerman 	"r2 = r10;"
65118b89265SEduard Zingerman 	"r2 += r6;"
65218b89265SEduard Zingerman 	"r2 += r7;"
65318b89265SEduard Zingerman 	"exit;"
65418b89265SEduard Zingerman 	:
65518b89265SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
65618b89265SEduard Zingerman 	: __clobber_all);
65718b89265SEduard Zingerman }
65818b89265SEduard Zingerman 
659*68ec5395SEduard Zingerman SEC("socket")
660*68ec5395SEduard Zingerman /* Note the flag, see verifier.c:opt_subreg_zext_lo32_rnd_hi32() */
__flag(BPF_F_TEST_RND_HI32)661*68ec5395SEduard Zingerman __flag(BPF_F_TEST_RND_HI32)
662*68ec5395SEduard Zingerman __success
663*68ec5395SEduard Zingerman /* This test was added because of a bug in verifier.c:sync_linked_regs(),
664*68ec5395SEduard Zingerman  * upon range propagation it destroyed subreg_def marks for registers.
665*68ec5395SEduard Zingerman  * The subreg_def mark is used to decide whether zero extension instructions
666*68ec5395SEduard Zingerman  * are needed when register is read. When BPF_F_TEST_RND_HI32 is set it
667*68ec5395SEduard Zingerman  * also causes generation of statements to randomize upper halves of
668*68ec5395SEduard Zingerman  * read registers.
669*68ec5395SEduard Zingerman  *
670*68ec5395SEduard Zingerman  * The test is written in a way to return an upper half of a register
671*68ec5395SEduard Zingerman  * that is affected by range propagation and must have it's subreg_def
672*68ec5395SEduard Zingerman  * preserved. This gives a return value of 0 and leads to undefined
673*68ec5395SEduard Zingerman  * return value if subreg_def mark is not preserved.
674*68ec5395SEduard Zingerman  */
675*68ec5395SEduard Zingerman __retval(0)
676*68ec5395SEduard Zingerman /* Check that verifier believes r1/r0 are zero at exit */
677*68ec5395SEduard Zingerman __log_level(2)
678*68ec5395SEduard Zingerman __msg("4: (77) r1 >>= 32                     ; R1_w=0")
679*68ec5395SEduard Zingerman __msg("5: (bf) r0 = r1                       ; R0_w=0 R1_w=0")
680*68ec5395SEduard Zingerman __msg("6: (95) exit")
681*68ec5395SEduard Zingerman __msg("from 3 to 4")
682*68ec5395SEduard Zingerman __msg("4: (77) r1 >>= 32                     ; R1_w=0")
683*68ec5395SEduard Zingerman __msg("5: (bf) r0 = r1                       ; R0_w=0 R1_w=0")
684*68ec5395SEduard Zingerman __msg("6: (95) exit")
685*68ec5395SEduard Zingerman __naked void linked_regs_and_subreg_def(void)
686*68ec5395SEduard Zingerman {
687*68ec5395SEduard Zingerman 	asm volatile (
688*68ec5395SEduard Zingerman 	"call %[bpf_ktime_get_ns];"
689*68ec5395SEduard Zingerman 	/* make sure r0 is in 32-bit range, otherwise w1 = w0 won't
690*68ec5395SEduard Zingerman 	 * assign same IDs to registers.
691*68ec5395SEduard Zingerman 	 */
692*68ec5395SEduard Zingerman 	"r0 &= 0x7fffffff;"
693*68ec5395SEduard Zingerman 	/* link w1 and w0 via ID */
694*68ec5395SEduard Zingerman 	"w1 = w0;"
695*68ec5395SEduard Zingerman 	/* 'if' statement propagates range info from w0 to w1,
696*68ec5395SEduard Zingerman 	 * but should not affect w1->subreg_def property.
697*68ec5395SEduard Zingerman 	 */
698*68ec5395SEduard Zingerman 	"if w0 < 10 goto +0;"
699*68ec5395SEduard Zingerman 	/* r1 is read here, on archs that require subreg zero
700*68ec5395SEduard Zingerman 	 * extension this would cause zext patch generation.
701*68ec5395SEduard Zingerman 	 */
702*68ec5395SEduard Zingerman 	"r1 >>= 32;"
703*68ec5395SEduard Zingerman 	"r0 = r1;"
704*68ec5395SEduard Zingerman 	"exit;"
705*68ec5395SEduard Zingerman 	:
706*68ec5395SEduard Zingerman 	: __imm(bpf_ktime_get_ns)
707*68ec5395SEduard Zingerman 	: __clobber_all);
708*68ec5395SEduard Zingerman }
709*68ec5395SEduard Zingerman 
710dec02028SEduard Zingerman char _license[] SEC("license") = "GPL";
711