1#[cfg(all(test, debug_assertions))]
2mod tests {
3 use atomic::Ordering;
4
5 use crate::util::constants;
6 use crate::util::heap::layout::vm_layout;
7 use crate::util::heap::layout::vm_layout::vm_layout;
8 use crate::util::metadata::side_metadata::spec_defs;
9 use crate::util::metadata::side_metadata::SideMetadataContext;
10 use crate::util::metadata::side_metadata::SideMetadataSpec;
11 use crate::util::metadata::side_metadata::*;
12 use crate::util::test_util::{serial_test, with_cleanup};
13 use crate::util::Address;
14
15 #[cfg(target_pointer_width = "64")]
16 fn local_side_metadata_base_offset() -> usize {
17 side_metadata_offset_after(&spec_defs::LAST_GLOBAL_SIDE_METADATA_SPEC)
18 }
19
20 #[test]
21 fn test_side_metadata_address_to_meta_address() {
22 serial_test(|| {
23 core_test_initialize_side_metadata();
24 let global_base = global_side_metadata_base_address();
25 let mut gspec = SideMetadataSpec {
26 name: "gspec",
27 is_global: true,
28 offset: 0,
29 log_num_of_bits: 0,
30 log_bytes_in_region: 0,
31 };
32 #[cfg(target_pointer_width = "64")]
33 let mut lspec = SideMetadataSpec {
34 name: "lspec",
35 is_global: false,
36 offset: local_side_metadata_base_offset(),
37 log_num_of_bits: 0,
38 log_bytes_in_region: 0,
39 };
40
41 #[cfg(target_pointer_width = "32")]
42 let mut lspec = SideMetadataSpec {
43 name: "lspec",
44 is_global: false,
45 offset: 0,
46 log_num_of_bits: 0,
47 log_bytes_in_region: 0,
48 };
49
50 assert_eq!(
51 address_to_meta_address(&gspec, unsafe { Address::from_usize(0) }),
52 global_base
53 );
54 assert_eq!(
55 address_to_meta_address(&lspec, unsafe { Address::from_usize(0) }),
56 local_side_metadata_base_address()
57 );
58
59 assert_eq!(
60 address_to_meta_address(&gspec, unsafe { Address::from_usize(7) }),
61 global_base
62 );
63 assert_eq!(
64 address_to_meta_address(&lspec, unsafe { Address::from_usize(7) }),
65 local_side_metadata_base_address()
66 );
67
68 assert_eq!(
69 address_to_meta_address(&gspec, unsafe { Address::from_usize(27) }),
70 global_base + 3usize
71 );
72 assert_eq!(
73 address_to_meta_address(&lspec, unsafe { Address::from_usize(129) }),
74 local_side_metadata_base_address() + 16usize
75 );
76
77 gspec.log_bytes_in_region = 2;
78 lspec.log_bytes_in_region = 1;
79
80 assert_eq!(
81 address_to_meta_address(&gspec, unsafe { Address::from_usize(0) }),
82 global_base
83 );
84 assert_eq!(
85 address_to_meta_address(&lspec, unsafe { Address::from_usize(0) }),
86 local_side_metadata_base_address()
87 );
88
89 assert_eq!(
90 address_to_meta_address(&gspec, unsafe { Address::from_usize(32) }),
91 global_base + 1usize
92 );
93 assert_eq!(
94 address_to_meta_address(&lspec, unsafe { Address::from_usize(32) }),
95 local_side_metadata_base_address() + 2usize
96 );
97
98 assert_eq!(
99 address_to_meta_address(&gspec, unsafe { Address::from_usize(316) }),
100 global_base + 9usize
101 );
102 assert_eq!(
103 address_to_meta_address(&lspec, unsafe { Address::from_usize(316) }),
104 local_side_metadata_base_address() + 19usize
105 );
106
107 gspec.log_num_of_bits = 1;
108 lspec.log_num_of_bits = 3;
109
110 assert_eq!(
111 address_to_meta_address(&gspec, unsafe { Address::from_usize(0) }),
112 global_base
113 );
114 assert_eq!(
115 address_to_meta_address(&lspec, unsafe { Address::from_usize(0) }),
116 local_side_metadata_base_address()
117 );
118
119 assert_eq!(
120 address_to_meta_address(&gspec, unsafe { Address::from_usize(32) }),
121 global_base + 2usize
122 );
123 assert_eq!(
124 address_to_meta_address(&lspec, unsafe { Address::from_usize(32) }),
125 local_side_metadata_base_address() + 16usize
126 );
127
128 assert_eq!(
129 address_to_meta_address(&gspec, unsafe { Address::from_usize(316) }),
130 global_base + 19usize
131 );
132 assert_eq!(
133 address_to_meta_address(&lspec, unsafe { Address::from_usize(318) }),
134 local_side_metadata_base_address() + 159usize
135 );
136 });
137 }
138
139 #[test]
140 fn test_side_metadata_runtime_base_address() {
141 serial_test(|| {
142 core_test_initialize_side_metadata();
143 let base = global_side_metadata_base_address();
144 assert!(base.as_usize() != 0);
145 assert!(base.is_aligned_to(crate::MMAPPER.granularity()));
146
147 let global_end = base + global_side_metadata_bytes();
148 #[cfg(target_pointer_width = "64")]
149 {
150 assert_eq!(local_side_metadata_base_address(), global_end);
151 }
152
153 let spec = spec_defs::LAST_GLOBAL_SIDE_METADATA_SPEC;
154 let data_addr = unsafe { Address::from_usize(0) };
155 let meta_addr = address_to_meta_address(&spec, data_addr);
156 assert!(meta_addr >= base);
157 assert!(meta_addr < global_end);
158 });
159 }
160
161 #[test]
162 fn test_side_metadata_meta_byte_mask() {
163 serial_test(|| {
164 let mut spec = SideMetadataSpec {
165 name: "test_spec",
166 is_global: true,
167 offset: 0,
168 log_num_of_bits: 0,
169 log_bytes_in_region: 0,
170 };
171
172 assert_eq!(meta_byte_mask(&spec), 1);
173
174 spec.log_num_of_bits = 1;
175 assert_eq!(meta_byte_mask(&spec), 3);
176 spec.log_num_of_bits = 2;
177 assert_eq!(meta_byte_mask(&spec), 15);
178 spec.log_num_of_bits = 3;
179 assert_eq!(meta_byte_mask(&spec), 255);
180 });
181 }
182
183 #[test]
184 fn test_side_metadata_meta_byte_lshift() {
185 serial_test(|| {
186 let mut spec = SideMetadataSpec {
187 name: "test_spec",
188 is_global: true,
189 offset: 0,
190 log_num_of_bits: 0,
191 log_bytes_in_region: 0,
192 };
193
194 assert_eq!(
195 meta_byte_lshift(&spec, unsafe { Address::from_usize(0) }),
196 0
197 );
198 assert_eq!(
199 meta_byte_lshift(&spec, unsafe { Address::from_usize(5) }),
200 5
201 );
202 assert_eq!(
203 meta_byte_lshift(&spec, unsafe { Address::from_usize(15) }),
204 7
205 );
206
207 spec.log_num_of_bits = 2;
208
209 assert_eq!(
210 meta_byte_lshift(&spec, unsafe { Address::from_usize(0) }),
211 0
212 );
213 assert_eq!(
214 meta_byte_lshift(&spec, unsafe { Address::from_usize(5) }),
215 4
216 );
217 assert_eq!(
218 meta_byte_lshift(&spec, unsafe { Address::from_usize(15) }),
219 4
220 );
221 assert_eq!(
222 meta_byte_lshift(&spec, unsafe { Address::from_usize(0x10010) }),
223 0
224 );
225 });
226 }
227
228 #[test]
229 fn test_side_metadata_try_mmap_metadata() {
230 let heap_start = vm_layout().heap_start;
231 serial_test(|| {
232 with_cleanup(
233 || {
234 core_test_initialize_side_metadata();
235 let mut gspec = SideMetadataSpec {
238 name: "gspec",
239 is_global: true,
240 offset: 0,
241 log_num_of_bits: 1,
242 log_bytes_in_region: 1,
243 };
244 #[cfg(target_pointer_width = "64")]
245 let mut lspec = SideMetadataSpec {
246 name: "lspec",
247 is_global: false,
248 offset: local_side_metadata_base_offset(),
249 log_num_of_bits: 1,
250 log_bytes_in_region: 1,
251 };
252 #[cfg(target_pointer_width = "32")]
253 let mut lspec = SideMetadataSpec {
254 name: "lspec",
255 is_global: false,
256 offset: 0,
257 log_num_of_bits: 1,
258 log_bytes_in_region: 1,
259 };
260
261 let metadata = SideMetadataContext {
262 global: vec![gspec],
263 local: vec![lspec],
264 };
265
266 let mut metadata_sanity = SideMetadataSanity::new();
267 metadata_sanity.verify_metadata_context("NoPolicy", &metadata);
268
269 assert!(metadata
270 .try_map_metadata_space(heap_start, constants::BYTES_IN_PAGE, "test_space")
271 .is_ok());
272
273 gspec.assert_metadata_mapped(heap_start);
274 lspec.assert_metadata_mapped(heap_start);
275 gspec.assert_metadata_mapped(heap_start + constants::BYTES_IN_PAGE - 1);
276 lspec.assert_metadata_mapped(heap_start + constants::BYTES_IN_PAGE - 1);
277
278 metadata.ensure_unmap_metadata_space(heap_start, constants::BYTES_IN_PAGE);
279
280 gspec.log_bytes_in_region = 4;
281 gspec.log_num_of_bits = 4;
282 lspec.log_bytes_in_region = 4;
283 lspec.log_num_of_bits = 4;
284
285 metadata_sanity.reset();
286
287 let metadata = SideMetadataContext {
288 global: vec![gspec],
289 local: vec![lspec],
290 };
291
292 metadata_sanity.verify_metadata_context("NoPolicy", &metadata);
293 metadata_sanity.reset();
294
295 assert!(metadata
296 .try_map_metadata_space(
297 heap_start + vm_layout::BYTES_IN_CHUNK,
298 vm_layout::BYTES_IN_CHUNK,
299 "test_space",
300 )
301 .is_ok());
302
303 gspec.assert_metadata_mapped(heap_start + vm_layout::BYTES_IN_CHUNK);
304 lspec.assert_metadata_mapped(heap_start + vm_layout::BYTES_IN_CHUNK);
305 gspec.assert_metadata_mapped(heap_start + vm_layout::BYTES_IN_CHUNK * 2 - 8);
306 lspec.assert_metadata_mapped(heap_start + vm_layout::BYTES_IN_CHUNK * 2 - 16);
307
308 metadata.ensure_unmap_metadata_space(
309 heap_start + vm_layout::BYTES_IN_CHUNK,
310 vm_layout::BYTES_IN_CHUNK,
311 );
312 },
313 || {
314 sanity::reset();
315 },
316 );
317 })
318 }
319
320 #[test]
321 fn test_side_metadata_atomic_fetch_add_sub_ge8bits() {
322 serial_test(|| {
323 with_cleanup(
324 || {
325 core_test_initialize_side_metadata();
326 let data_addr = vm_layout().heap_start;
329
330 let metadata_1_spec = SideMetadataSpec {
331 name: "metadata_1_spec",
332 is_global: true,
333 offset: 0,
334 log_num_of_bits: 4,
335 log_bytes_in_region: 6,
336 };
337
338 let metadata_2_spec = SideMetadataSpec {
339 name: "metadata_2_spec",
340 is_global: true,
341 offset: side_metadata_offset_after(&metadata_1_spec),
342 log_num_of_bits: 3,
343 log_bytes_in_region: 7,
344 };
345
346 let metadata = SideMetadataContext {
347 global: vec![metadata_1_spec, metadata_2_spec],
348 local: vec![],
349 };
350
351 let mut metadata_sanity = SideMetadataSanity::new();
352 metadata_sanity.verify_metadata_context("NoPolicy", &metadata);
353
354 assert!(metadata
355 .try_map_metadata_space(data_addr, constants::BYTES_IN_PAGE, "test_space",)
356 .is_ok());
357
358 let zero =
359 metadata_1_spec.fetch_add_atomic::<u16>(data_addr, 5, Ordering::SeqCst);
360 assert_eq!(zero, 0);
361
362 let five = metadata_1_spec.load_atomic::<u16>(data_addr, Ordering::SeqCst);
363 assert_eq!(five, 5);
364
365 let zero =
366 metadata_2_spec.fetch_add_atomic::<u8>(data_addr, 5, Ordering::SeqCst);
367 assert_eq!(zero, 0);
368
369 let five = metadata_2_spec.load_atomic::<u8>(data_addr, Ordering::SeqCst);
370 assert_eq!(five, 5);
371
372 let another_five =
373 metadata_1_spec.fetch_sub_atomic::<u16>(data_addr, 2, Ordering::SeqCst);
374 assert_eq!(another_five, 5);
375
376 let three = metadata_1_spec.load_atomic::<u16>(data_addr, Ordering::SeqCst);
377 assert_eq!(three, 3);
378
379 let another_five =
380 metadata_2_spec.fetch_sub_atomic::<u8>(data_addr, 2, Ordering::SeqCst);
381 assert_eq!(another_five, 5);
382
383 let three = metadata_2_spec.load_atomic::<u8>(data_addr, Ordering::SeqCst);
384 assert_eq!(three, 3);
385
386 metadata.ensure_unmap_metadata_space(data_addr, constants::BYTES_IN_PAGE);
387 metadata_sanity.reset();
388 },
389 || {
390 sanity::reset();
391 },
392 );
393 });
394 }
395
396 #[test]
397 fn test_side_metadata_atomic_fetch_add_sub_2bits() {
398 serial_test(|| {
399 with_cleanup(
400 || {
401 core_test_initialize_side_metadata();
402 let data_addr = vm_layout().heap_start + (vm_layout::BYTES_IN_CHUNK << 1) * 2;
405
406 let metadata_1_spec = SideMetadataSpec {
407 name: "metadata_1_spec",
408 is_global: true,
409 offset: 0,
410 log_num_of_bits: 1,
411 log_bytes_in_region: constants::LOG_BYTES_IN_WORD as usize,
412 };
413
414 let metadata = SideMetadataContext {
415 global: vec![metadata_1_spec],
416 local: vec![],
417 };
418
419 let mut metadata_sanity = SideMetadataSanity::new();
420 metadata_sanity.verify_metadata_context("NoPolicy", &metadata);
421
422 assert!(metadata
423 .try_map_metadata_space(data_addr, constants::BYTES_IN_PAGE, "test_space",)
424 .is_ok());
425
426 let zero =
427 metadata_1_spec.fetch_add_atomic::<u8>(data_addr, 2, Ordering::SeqCst);
428 assert_eq!(zero, 0);
429
430 let two = metadata_1_spec.load_atomic::<u8>(data_addr, Ordering::SeqCst);
431 assert_eq!(two, 2);
432
433 let another_two =
434 metadata_1_spec.fetch_sub_atomic::<u8>(data_addr, 1, Ordering::SeqCst);
435 assert_eq!(another_two, 2);
436
437 let one = metadata_1_spec.load_atomic::<u8>(data_addr, Ordering::SeqCst);
438 assert_eq!(one, 1);
439
440 metadata_1_spec.store_atomic::<u8>(data_addr, 0, Ordering::SeqCst);
441
442 metadata.ensure_unmap_metadata_space(data_addr, constants::BYTES_IN_PAGE);
443
444 metadata_sanity.reset();
445 },
446 || {
447 sanity::reset();
448 },
449 );
450 });
451 }
452
453 #[test]
454 fn test_side_metadata_atomic_fetch_and_or_2bits() {
455 serial_test(|| {
456 with_cleanup(
457 || {
458 core_test_initialize_side_metadata();
459 let data_addr =
462 vm_layout::vm_layout().heap_start + (vm_layout::BYTES_IN_CHUNK << 1);
463
464 let metadata_1_spec = SideMetadataSpec {
465 name: "metadata_1_spec",
466 is_global: true,
467 offset: 0,
468 log_num_of_bits: 1,
469 log_bytes_in_region: constants::LOG_BYTES_IN_WORD as usize,
470 };
471
472 let metadata = SideMetadataContext {
473 global: vec![metadata_1_spec],
474 local: vec![],
475 };
476
477 let mut metadata_sanity = SideMetadataSanity::new();
478 metadata_sanity.verify_metadata_context("NoPolicy", &metadata);
479
480 assert!(metadata
481 .try_map_metadata_space(data_addr, constants::BYTES_IN_PAGE, "test_space",)
482 .is_ok());
483
484 let zero =
485 metadata_1_spec.fetch_or_atomic::<u8>(data_addr, 0b11, Ordering::SeqCst);
486 assert_eq!(zero, 0);
487
488 let value_11 = metadata_1_spec.load_atomic::<u8>(data_addr, Ordering::SeqCst);
489 assert_eq!(value_11, 0b11);
490
491 let another_value_11 =
492 metadata_1_spec.fetch_and_atomic::<u8>(data_addr, 0b01, Ordering::SeqCst);
493 assert_eq!(another_value_11, 0b11);
494
495 let value_01 = metadata_1_spec.load_atomic::<u8>(data_addr, Ordering::SeqCst);
496 assert_eq!(value_01, 0b01);
497
498 metadata_1_spec.store_atomic::<u8>(data_addr, 0, Ordering::SeqCst);
499
500 metadata.ensure_unmap_metadata_space(data_addr, constants::BYTES_IN_PAGE);
501
502 metadata_sanity.reset();
503 },
504 || {
505 sanity::reset();
506 },
507 );
508 });
509 }
510
511 #[test]
512 fn test_side_metadata_bzero_metadata() {
513 serial_test(|| {
514 with_cleanup(
515 || {
516 core_test_initialize_side_metadata();
517 let data_addr = vm_layout().heap_start + (vm_layout::BYTES_IN_CHUNK << 2);
520
521 #[cfg(target_pointer_width = "64")]
522 let metadata_1_spec = SideMetadataSpec {
523 name: "metadata_1_spec",
524 is_global: false,
525 offset: local_side_metadata_base_offset(),
526 log_num_of_bits: 4,
527 log_bytes_in_region: 9,
528 };
529 #[cfg(target_pointer_width = "64")]
530 let metadata_2_spec = SideMetadataSpec {
531 name: "metadata_2_spec",
532 is_global: false,
533 offset: side_metadata_offset_after(&metadata_1_spec),
534 log_num_of_bits: 3,
535 log_bytes_in_region: 7,
536 };
537
538 #[cfg(target_pointer_width = "32")]
539 let metadata_1_spec = SideMetadataSpec {
540 name: "metadata_1_spec",
541 is_global: false,
542 offset: 0,
543 log_num_of_bits: 4,
544 log_bytes_in_region: 9,
545 };
546 #[cfg(target_pointer_width = "32")]
547 let metadata_2_spec = SideMetadataSpec {
548 name: "metadata_2_spec",
549 is_global: false,
550 offset: side_metadata_offset_after(&metadata_1_spec),
551 log_num_of_bits: 3,
552 log_bytes_in_region: 7,
553 };
554
555 let metadata = SideMetadataContext {
556 global: vec![],
557 local: vec![metadata_1_spec, metadata_2_spec],
558 };
559
560 let mut metadata_sanity = SideMetadataSanity::new();
561 metadata_sanity.verify_metadata_context("NoPolicy", &metadata);
562
563 assert!(metadata
564 .try_map_metadata_space(data_addr, constants::BYTES_IN_PAGE, "test_space",)
565 .is_ok());
566
567 let zero =
568 metadata_1_spec.fetch_add_atomic::<u16>(data_addr, 5, Ordering::SeqCst);
569 assert_eq!(zero, 0);
570
571 let five = metadata_1_spec.load_atomic::<u16>(data_addr, Ordering::SeqCst);
572 assert_eq!(five, 5);
573
574 let zero =
575 metadata_2_spec.fetch_add_atomic::<u8>(data_addr, 5, Ordering::SeqCst);
576 assert_eq!(zero, 0);
577
578 let five = metadata_2_spec.load_atomic::<u8>(data_addr, Ordering::SeqCst);
579 assert_eq!(five, 5);
580
581 metadata_2_spec.bzero_metadata(data_addr, constants::BYTES_IN_PAGE);
582
583 let five = metadata_1_spec.load_atomic::<u16>(data_addr, Ordering::SeqCst);
584 assert_eq!(five, 5);
585 let five = metadata_2_spec.load_atomic::<u8>(data_addr, Ordering::SeqCst);
586 assert_eq!(five, 0);
587
588 metadata_1_spec.bzero_metadata(data_addr, constants::BYTES_IN_PAGE);
589
590 let five = metadata_1_spec.load_atomic::<u16>(data_addr, Ordering::SeqCst);
591 assert_eq!(five, 0);
592 let five = metadata_2_spec.load_atomic::<u8>(data_addr, Ordering::SeqCst);
593 assert_eq!(five, 0);
594
595 metadata.ensure_unmap_metadata_space(data_addr, constants::BYTES_IN_PAGE);
596
597 metadata_sanity.reset();
598 },
599 || {
600 sanity::reset();
601 },
602 );
603 });
604 }
605
606 #[test]
607 fn test_side_metadata_bzero_by_bytes() {
608 serial_test(|| {
609 with_cleanup(
610 || {
611 core_test_initialize_side_metadata();
612 let data_addr = vm_layout::vm_layout().heap_start;
613
614 let spec = SideMetadataSpec {
616 name: "test spec",
617 is_global: true,
618 offset: 0,
619 log_num_of_bits: 0,
620 log_bytes_in_region: 3,
621 };
622 let region_size: usize = 1 << spec.log_bytes_in_region;
623
624 let metadata = SideMetadataContext {
625 global: vec![spec],
626 local: vec![],
627 };
628
629 let mut metadata_sanity = SideMetadataSanity::new();
630 metadata_sanity.verify_metadata_context("NoPolicy", &metadata);
631
632 assert!(metadata
633 .try_map_metadata_space(data_addr, constants::BYTES_IN_PAGE, "test_space",)
634 .is_ok());
635
636 let regions = (0..9)
638 .map(|i| data_addr + (region_size * i))
639 .collect::<Vec<Address>>();
640 regions
642 .iter()
643 .for_each(|addr| unsafe { spec.store::<u8>(*addr, 1) });
644 regions
645 .iter()
646 .for_each(|addr| assert!(unsafe { spec.load::<u8>(*addr) } == 1));
647
648 spec.bzero_metadata(regions[0], region_size * 8);
650 regions[0..8]
652 .iter()
653 .for_each(|addr| assert!(unsafe { spec.load::<u8>(*addr) } == 0));
654 assert!(unsafe { spec.load::<u8>(regions[8]) } == 1);
656 },
657 || {
658 sanity::reset();
659 },
660 )
661 })
662 }
663
664 #[test]
665 fn test_side_metadata_bzero_by_fraction_of_bytes() {
666 serial_test(|| {
667 with_cleanup(
668 || {
669 core_test_initialize_side_metadata();
670 let data_addr = vm_layout::vm_layout().heap_start;
671
672 let spec = SideMetadataSpec {
674 name: "test spec",
675 is_global: true,
676 offset: 0,
677 log_num_of_bits: 0,
678 log_bytes_in_region: 3,
679 };
680 let region_size: usize = 1 << spec.log_bytes_in_region;
681
682 let metadata = SideMetadataContext {
683 global: vec![spec],
684 local: vec![],
685 };
686
687 let mut metadata_sanity = SideMetadataSanity::new();
688 metadata_sanity.verify_metadata_context("NoPolicy", &metadata);
689
690 assert!(metadata
691 .try_map_metadata_space(data_addr, constants::BYTES_IN_PAGE, "test_space",)
692 .is_ok());
693
694 let regions = (0..9)
696 .map(|i| data_addr + (region_size * i))
697 .collect::<Vec<Address>>();
698 regions
700 .iter()
701 .for_each(|addr| unsafe { spec.store::<u8>(*addr, 1) });
702 regions
703 .iter()
704 .for_each(|addr| assert!(unsafe { spec.load::<u8>(*addr) } == 1));
705
706 spec.bzero_metadata(regions[0], region_size * 4);
708 regions[0..4]
710 .iter()
711 .for_each(|addr| assert!(unsafe { spec.load::<u8>(*addr) } == 0));
712 regions[4..9]
714 .iter()
715 .for_each(|addr| assert!(unsafe { spec.load::<u8>(*addr) } == 1));
716 },
717 || {
718 sanity::reset();
719 },
720 )
721 })
722 }
723
724 #[test]
725 fn test_side_metadata_zero_meta_bits() {
726 serial_test(|| {
727 let size = 4usize;
728 let allocate_u32 = || -> Address {
729 let ptr = unsafe {
730 std::alloc::alloc_zeroed(std::alloc::Layout::from_size_align(size, 4).unwrap())
731 };
732 Address::from_mut_ptr(ptr)
733 };
734 let fill_1 = |addr: Address| unsafe {
735 addr.store(u32::MAX);
736 };
737
738 let start = allocate_u32();
739 let end = start + size;
740
741 fill_1(start);
742 SideMetadataSpec::zero_meta_bits(start, 0, end, 0);
744 assert_eq!(unsafe { start.load::<u32>() }, 0);
745
746 fill_1(start);
747 SideMetadataSpec::zero_meta_bits(start, 0, start, 2);
749 assert_eq!(unsafe { start.load::<u32>() }, 0xFFFF_FFFC); fill_1(start);
752 SideMetadataSpec::zero_meta_bits(end - 1, 6, end, 0);
754 assert_eq!(unsafe { start.load::<u32>() }, 0x3FFF_FFFF); fill_1(start);
757 SideMetadataSpec::zero_meta_bits(start, 2, end - 1, 6);
759 assert_eq!(unsafe { start.load::<u32>() }, 0xC000_0003); });
761 }
762
763 #[test]
764 fn test_side_metadata_bcopy_metadata_contiguous() {
765 serial_test(|| {
766 with_cleanup(
767 || {
768 core_test_initialize_side_metadata();
769 let data_addr = vm_layout().heap_start;
770
771 let log_num_of_bits = 0;
772 let log_bytes_in_region = 3;
773 let num_regions = 0x400; let bytes_per_region = 1 << log_bytes_in_region;
775 let total_size = num_regions * bytes_per_region; let metadata_1_spec = SideMetadataSpec {
778 name: "metadata_1_spec",
779 is_global: true,
780 offset: 0,
781 log_num_of_bits,
782 log_bytes_in_region,
783 };
784
785 let metadata_2_spec = SideMetadataSpec {
786 name: "metadata_2_spec",
787 is_global: true,
788 offset: side_metadata_offset_after(&metadata_1_spec),
789 log_num_of_bits,
790 log_bytes_in_region,
791 };
792
793 let metadata = SideMetadataContext {
795 global: vec![metadata_1_spec, metadata_2_spec],
796 local: vec![],
797 };
798
799 let mut metadata_sanity = SideMetadataSanity::new();
800 metadata_sanity.verify_metadata_context("NoPolicy", &metadata);
801
802 metadata
803 .try_map_metadata_space(data_addr, total_size, "test_space")
804 .unwrap();
805
806 metadata_1_spec.bzero_metadata(data_addr, total_size);
807 metadata_2_spec.bzero_metadata(data_addr, total_size);
808
809 for i in 0..num_regions {
810 metadata_1_spec.store_atomic::<u8>(
811 data_addr + i * bytes_per_region,
812 (i % 2) as u8,
813 Ordering::Relaxed,
814 );
815 }
816
817 let test_copy_region = |begin: usize, end: usize| {
818 metadata_2_spec.bcopy_metadata_contiguous(
820 data_addr + begin * bytes_per_region,
821 (end - begin) * bytes_per_region,
822 &metadata_1_spec,
823 );
824
825 for i in 0..num_regions {
826 let bit = metadata_2_spec.load_atomic::<u8>(
827 data_addr + i * bytes_per_region,
828 Ordering::Relaxed,
829 );
830
831 let expected = if begin <= i && i < end {
832 (i % 2) as u8
833 } else {
834 0
835 };
836 assert_eq!(
837 bit, expected,
838 "Expected: {expected}, actual: {bit}, i: {i}, begin: {begin}, end: {end}"
839 );
840 }
841
842 metadata_2_spec.bzero_metadata(data_addr, total_size);
843 };
844
845 test_copy_region(0x100, 0x200);
847
848 test_copy_region(0x18, 0xcc);
850
851 test_copy_region(0x263, 0x3f0);
853
854 test_copy_region(0x82, 0x1fd);
856
857 metadata_1_spec.bzero_metadata(data_addr, total_size);
858 metadata_2_spec.bzero_metadata(data_addr, total_size);
859
860 metadata_sanity.reset();
861 },
862 || {
863 sanity::reset();
864 },
865 );
866 });
867 }
868}