@@ -29,12 +29,12 @@ int big_alloc1(void *ctx)
2929 if (!page1 )
3030 return 1 ;
3131 * page1 = 1 ;
32- page2 = bpf_arena_alloc_pages (& arena , base + ARENA_SIZE - PAGE_SIZE ,
32+ page2 = bpf_arena_alloc_pages (& arena , base + ARENA_SIZE - PAGE_SIZE * 2 ,
3333 1 , NUMA_NO_NODE , 0 );
3434 if (!page2 )
3535 return 2 ;
3636 * page2 = 2 ;
37- no_page = bpf_arena_alloc_pages (& arena , base + ARENA_SIZE ,
37+ no_page = bpf_arena_alloc_pages (& arena , base + ARENA_SIZE - PAGE_SIZE ,
3838 1 , NUMA_NO_NODE , 0 );
3939 if (no_page )
4040 return 3 ;
@@ -66,4 +66,110 @@ int big_alloc1(void *ctx)
6666#endif
6767 return 0 ;
6868}
69+
70+ #if defined(__BPF_FEATURE_ADDR_SPACE_CAST )
71+ #define PAGE_CNT 100
72+ __u8 __arena * __arena page [PAGE_CNT ]; /* occupies the first page */
73+ __u8 __arena * base ;
74+
75+ /*
76+ * Check that arena's range_tree algorithm allocates pages sequentially
77+ * on the first pass and then fills in all gaps on the second pass.
78+ */
79+ __noinline int alloc_pages (int page_cnt , int pages_atonce , bool first_pass ,
80+ int max_idx , int step )
81+ {
82+ __u8 __arena * pg ;
83+ int i , pg_idx ;
84+
85+ for (i = 0 ; i < page_cnt ; i ++ ) {
86+ pg = bpf_arena_alloc_pages (& arena , NULL , pages_atonce ,
87+ NUMA_NO_NODE , 0 );
88+ if (!pg )
89+ return step ;
90+ pg_idx = (pg - base ) / PAGE_SIZE ;
91+ if (first_pass ) {
92+ /* Pages must be allocated sequentially */
93+ if (pg_idx != i )
94+ return step + 100 ;
95+ } else {
96+ /* Allocator must fill into gaps */
97+ if (pg_idx >= max_idx || (pg_idx & 1 ))
98+ return step + 200 ;
99+ }
100+ * pg = pg_idx ;
101+ page [pg_idx ] = pg ;
102+ cond_break ;
103+ }
104+ return 0 ;
105+ }
106+
107+ SEC ("syscall" )
108+ __success __retval (0 )
109+ int big_alloc2 (void * ctx )
110+ {
111+ __u8 __arena * pg ;
112+ int i , err ;
113+
114+ base = bpf_arena_alloc_pages (& arena , NULL , 1 , NUMA_NO_NODE , 0 );
115+ if (!base )
116+ return 1 ;
117+ bpf_arena_free_pages (& arena , (void __arena * )base , 1 );
118+
119+ err = alloc_pages (PAGE_CNT , 1 , true, PAGE_CNT , 2 );
120+ if (err )
121+ return err ;
122+
123+ /* Clear all even pages */
124+ for (i = 0 ; i < PAGE_CNT ; i += 2 ) {
125+ pg = page [i ];
126+ if (* pg != i )
127+ return 3 ;
128+ bpf_arena_free_pages (& arena , (void __arena * )pg , 1 );
129+ page [i ] = NULL ;
130+ cond_break ;
131+ }
132+
133+ /* Allocate into freed gaps */
134+ err = alloc_pages (PAGE_CNT / 2 , 1 , false, PAGE_CNT , 4 );
135+ if (err )
136+ return err ;
137+
138+ /* Free pairs of pages */
139+ for (i = 0 ; i < PAGE_CNT ; i += 4 ) {
140+ pg = page [i ];
141+ if (* pg != i )
142+ return 5 ;
143+ bpf_arena_free_pages (& arena , (void __arena * )pg , 2 );
144+ page [i ] = NULL ;
145+ page [i + 1 ] = NULL ;
146+ cond_break ;
147+ }
148+
149+ /* Allocate 2 pages at a time into freed gaps */
150+ err = alloc_pages (PAGE_CNT / 4 , 2 , false, PAGE_CNT , 6 );
151+ if (err )
152+ return err ;
153+
154+ /* Check pages without freeing */
155+ for (i = 0 ; i < PAGE_CNT ; i += 2 ) {
156+ pg = page [i ];
157+ if (* pg != i )
158+ return 7 ;
159+ cond_break ;
160+ }
161+
162+ pg = bpf_arena_alloc_pages (& arena , NULL , 1 , NUMA_NO_NODE , 0 );
163+
164+ if (!pg )
165+ return 8 ;
166+ /*
167+ * The first PAGE_CNT pages are occupied. The new page
168+ * must be above.
169+ */
170+ if ((pg - base ) / PAGE_SIZE < PAGE_CNT )
171+ return 9 ;
172+ return 0 ;
173+ }
174+ #endif
69175char _license [] SEC ("license" ) = "GPL" ;
0 commit comments