1use std::sync::Arc;
7
8use arc_swap::ArcSwap;
9use vm_memory::{GuestAddress, GuestMemoryMmap};
10
11use crate::{AddressSpaceError, AddressSpaceLayout, AddressSpaceRegion, AddressSpaceRegionType};
12
13#[derive(Clone)]
15pub struct AddressSpaceBase {
16 regions: Vec<Arc<AddressSpaceRegion>>,
17 layout: AddressSpaceLayout,
18}
19
20impl AddressSpaceBase {
21 pub fn from_regions(
32 mut regions: Vec<Arc<AddressSpaceRegion>>,
33 layout: AddressSpaceLayout,
34 ) -> Self {
35 regions.sort_unstable_by_key(|v| v.base);
36 for region in regions.iter() {
37 if !layout.is_region_valid(region) {
38 panic!(
39 "Invalid region {:?} for address space layout {:?}",
40 region, layout
41 );
42 }
43 }
44 for idx in 1..regions.len() {
45 if regions[idx].intersect_with(®ions[idx - 1]) {
46 panic!("address space regions intersect with each other");
47 }
48 }
49 AddressSpaceBase { regions, layout }
50 }
51
52 pub fn insert_region(
57 &mut self,
58 region: Arc<AddressSpaceRegion>,
59 ) -> Result<(), AddressSpaceError> {
60 if !self.layout.is_region_valid(®ion) {
61 return Err(AddressSpaceError::InvalidAddressRange(
62 region.start_addr().0,
63 region.len(),
64 ));
65 }
66 for idx in 0..self.regions.len() {
67 if self.regions[idx].intersect_with(®ion) {
68 return Err(AddressSpaceError::InvalidAddressRange(
69 region.start_addr().0,
70 region.len(),
71 ));
72 }
73 }
74 self.regions.push(region);
75 Ok(())
76 }
77
78 pub fn walk_regions<F>(&self, mut cb: F) -> Result<(), AddressSpaceError>
83 where
84 F: FnMut(&Arc<AddressSpaceRegion>) -> Result<(), AddressSpaceError>,
85 {
86 for reg in self.regions.iter() {
87 cb(reg)?;
88 }
89
90 Ok(())
91 }
92
93 pub fn layout(&self) -> AddressSpaceLayout {
95 self.layout.clone()
96 }
97
98 pub fn last_addr(&self) -> GuestAddress {
100 let mut last_addr = GuestAddress(self.layout.mem_start);
101 for reg in self.regions.iter() {
102 if reg.ty != AddressSpaceRegionType::DAXMemory && reg.last_addr() > last_addr {
103 last_addr = reg.last_addr();
104 }
105 }
106 last_addr
107 }
108
109 pub fn is_dax_region(&self, guest_addr: GuestAddress) -> bool {
114 for reg in self.regions.iter() {
115 if reg.region_type() == AddressSpaceRegionType::DAXMemory
117 && reg.start_addr() <= guest_addr
118 && reg.start_addr().0 + reg.len() > guest_addr.0
119 {
120 return true;
121 }
122 }
123 false
124 }
125
126 pub fn prot_flags(&self, guest_addr: GuestAddress) -> Result<i32, AddressSpaceError> {
131 for reg in self.regions.iter() {
132 if reg.start_addr() <= guest_addr && reg.start_addr().0 + reg.len() > guest_addr.0 {
133 return Ok(reg.prot_flags());
134 }
135 }
136
137 Err(AddressSpaceError::InvalidRegionType)
138 }
139
140 pub fn numa_node_id(&self, gpa: u64) -> Option<u32> {
145 for reg in self.regions.iter() {
146 if gpa >= reg.base.0 && gpa < (reg.base.0 + reg.size) {
147 return reg.host_numa_node_id;
148 }
149 }
150 None
151 }
152}
153
154#[derive(Clone)]
159pub struct AddressSpace {
160 state: Arc<ArcSwap<AddressSpaceBase>>,
161}
162
163impl AddressSpace {
164 pub fn convert_into_vm_as(
166 gm: GuestMemoryMmap,
167 ) -> vm_memory::atomic::GuestMemoryAtomic<GuestMemoryMmap> {
168 vm_memory::atomic::GuestMemoryAtomic::from(Arc::new(gm))
169 }
170
171 pub fn from_regions(regions: Vec<Arc<AddressSpaceRegion>>, layout: AddressSpaceLayout) -> Self {
182 let base = AddressSpaceBase::from_regions(regions, layout);
183
184 AddressSpace {
185 state: Arc::new(ArcSwap::new(Arc::new(base))),
186 }
187 }
188
189 pub fn insert_region(
194 &mut self,
195 region: Arc<AddressSpaceRegion>,
196 ) -> Result<(), AddressSpaceError> {
197 let curr = self.state.load().regions.clone();
198 let layout = self.state.load().layout.clone();
199 let mut base = AddressSpaceBase::from_regions(curr, layout);
200 base.insert_region(region)?;
201 let _old = self.state.swap(Arc::new(base));
202
203 Ok(())
204 }
205
206 pub fn walk_regions<F>(&self, cb: F) -> Result<(), AddressSpaceError>
211 where
212 F: FnMut(&Arc<AddressSpaceRegion>) -> Result<(), AddressSpaceError>,
213 {
214 self.state.load().walk_regions(cb)
215 }
216
217 pub fn layout(&self) -> AddressSpaceLayout {
219 self.state.load().layout()
220 }
221
222 pub fn last_addr(&self) -> GuestAddress {
224 self.state.load().last_addr()
225 }
226
227 pub fn is_dax_region(&self, guest_addr: GuestAddress) -> bool {
232 self.state.load().is_dax_region(guest_addr)
233 }
234
235 pub fn prot_flags(&self, guest_addr: GuestAddress) -> Result<i32, AddressSpaceError> {
240 self.state.load().prot_flags(guest_addr)
241 }
242
243 pub fn numa_node_id(&self, gpa: u64) -> Option<u32> {
248 self.state.load().numa_node_id(gpa)
249 }
250}
251
252#[cfg(test)]
253mod tests {
254 use super::*;
255 use std::io::Write;
256 use vm_memory::GuestUsize;
257 use vmm_sys_util::tempfile::TempFile;
258
259 const GUEST_PHYS_END: u64 = (1 << 46) - 1;
261 const GUEST_MEM_START: u64 = 0;
262 const GUEST_MEM_END: u64 = GUEST_PHYS_END >> 1;
263 const GUEST_DEVICE_START: u64 = GUEST_MEM_END + 1;
264
265 #[test]
266 fn test_address_space_base_from_regions() {
267 let mut file = TempFile::new().unwrap().into_file();
268 let sample_buf = &[1, 2, 3, 4, 5];
269 assert!(file.write_all(sample_buf).is_ok());
270 file.set_len(0x10000).unwrap();
271
272 let reg = Arc::new(
273 AddressSpaceRegion::create_device_region(GuestAddress(GUEST_DEVICE_START), 0x1000)
274 .unwrap(),
275 );
276 let regions = vec![reg];
277 let layout = AddressSpaceLayout::new(GUEST_PHYS_END, GUEST_MEM_START, GUEST_MEM_END);
278 let address_space = AddressSpaceBase::from_regions(regions, layout.clone());
279 assert_eq!(address_space.layout(), layout);
280 }
281
282 #[test]
283 #[should_panic(expected = "Invalid region")]
284 fn test_address_space_base_from_regions_when_region_invalid() {
285 let reg = Arc::new(AddressSpaceRegion::build(
286 AddressSpaceRegionType::DefaultMemory,
287 GuestAddress(0x100),
288 0x1000,
289 None,
290 None,
291 0,
292 0,
293 false,
294 ));
295 let regions = vec![reg];
296 let layout = AddressSpaceLayout::new(0x2000, 0x200, 0x1800);
297 let _address_space = AddressSpaceBase::from_regions(regions, layout);
298 }
299
300 #[test]
301 #[should_panic(expected = "address space regions intersect with each other")]
302 fn test_address_space_base_from_regions_when_region_intersected() {
303 let reg1 = Arc::new(AddressSpaceRegion::build(
304 AddressSpaceRegionType::DefaultMemory,
305 GuestAddress(0x100),
306 0x200,
307 None,
308 None,
309 0,
310 0,
311 false,
312 ));
313 let reg2 = Arc::new(AddressSpaceRegion::build(
314 AddressSpaceRegionType::DefaultMemory,
315 GuestAddress(0x200),
316 0x200,
317 None,
318 None,
319 0,
320 0,
321 false,
322 ));
323 let regions = vec![reg1, reg2];
324 let layout = AddressSpaceLayout::new(0x2000, 0x0, 0x1800);
325 let _address_space = AddressSpaceBase::from_regions(regions, layout);
326 }
327
328 #[test]
329 fn test_address_space_base_insert_region() {
330 let reg1 = Arc::new(AddressSpaceRegion::build(
331 AddressSpaceRegionType::DefaultMemory,
332 GuestAddress(0x100),
333 0x200,
334 None,
335 None,
336 0,
337 0,
338 false,
339 ));
340 let reg2 = Arc::new(AddressSpaceRegion::build(
341 AddressSpaceRegionType::DefaultMemory,
342 GuestAddress(0x300),
343 0x200,
344 None,
345 None,
346 0,
347 0,
348 false,
349 ));
350 let regions = vec![reg1];
351 let layout = AddressSpaceLayout::new(0x2000, 0x100, 0x1800);
352 let mut address_space = AddressSpaceBase::from_regions(regions, layout);
353
354 address_space.insert_region(reg2).unwrap();
356 assert!(!address_space.regions[1].intersect_with(&address_space.regions[0]));
357
358 let invalid_reg = Arc::new(AddressSpaceRegion::build(
360 AddressSpaceRegionType::DefaultMemory,
361 GuestAddress(0x0),
362 0x100,
363 None,
364 None,
365 0,
366 0,
367 false,
368 ));
369 assert_eq!(
370 format!(
371 "{:?}",
372 address_space.insert_region(invalid_reg).err().unwrap()
373 ),
374 format!("InvalidAddressRange({:?}, {:?})", 0x0, 0x100)
375 );
376
377 let intersected_reg = Arc::new(AddressSpaceRegion::build(
380 AddressSpaceRegionType::DefaultMemory,
381 GuestAddress(0x400),
382 0x200,
383 None,
384 None,
385 0,
386 0,
387 false,
388 ));
389 assert_eq!(
390 format!(
391 "{:?}",
392 address_space.insert_region(intersected_reg).err().unwrap()
393 ),
394 format!("InvalidAddressRange({:?}, {:?})", 0x400, 0x200)
395 );
396 }
397
398 #[test]
399 fn test_address_space_base_walk_regions() {
400 let reg1 = Arc::new(AddressSpaceRegion::build(
401 AddressSpaceRegionType::DefaultMemory,
402 GuestAddress(0x100),
403 0x200,
404 None,
405 None,
406 0,
407 0,
408 false,
409 ));
410 let reg2 = Arc::new(AddressSpaceRegion::build(
411 AddressSpaceRegionType::DefaultMemory,
412 GuestAddress(0x300),
413 0x200,
414 None,
415 None,
416 0,
417 0,
418 false,
419 ));
420 let regions = vec![reg1, reg2];
421 let layout = AddressSpaceLayout::new(0x2000, 0x0, 0x1800);
422 let address_space = AddressSpaceBase::from_regions(regions, layout);
423
424 fn do_not_have_hotplug(region: &Arc<AddressSpaceRegion>) -> Result<(), AddressSpaceError> {
427 if region.is_hotplug() {
428 Err(AddressSpaceError::InvalidRegionType) } else {
430 Ok(())
431 }
432 }
433 assert!(matches!(
434 address_space.walk_regions(do_not_have_hotplug).unwrap(),
435 ()
436 ));
437 }
438
439 #[test]
440 fn test_address_space_base_last_addr() {
441 let reg1 = Arc::new(AddressSpaceRegion::build(
442 AddressSpaceRegionType::DefaultMemory,
443 GuestAddress(0x100),
444 0x200,
445 None,
446 None,
447 0,
448 0,
449 false,
450 ));
451 let reg2 = Arc::new(AddressSpaceRegion::build(
452 AddressSpaceRegionType::DefaultMemory,
453 GuestAddress(0x300),
454 0x200,
455 None,
456 None,
457 0,
458 0,
459 false,
460 ));
461 let regions = vec![reg1, reg2];
462 let layout = AddressSpaceLayout::new(0x2000, 0x0, 0x1800);
463 let address_space = AddressSpaceBase::from_regions(regions, layout);
464
465 assert_eq!(address_space.last_addr(), GuestAddress(0x500 - 1));
466 }
467
468 #[test]
469 fn test_address_space_base_is_dax_region() {
470 let page_size = 4096;
471 let address_space_region = vec![
472 Arc::new(AddressSpaceRegion::new(
473 AddressSpaceRegionType::DefaultMemory,
474 GuestAddress(page_size),
475 page_size as GuestUsize,
476 )),
477 Arc::new(AddressSpaceRegion::new(
478 AddressSpaceRegionType::DefaultMemory,
479 GuestAddress(page_size * 2),
480 page_size as GuestUsize,
481 )),
482 Arc::new(AddressSpaceRegion::new(
483 AddressSpaceRegionType::DAXMemory,
484 GuestAddress(GUEST_DEVICE_START),
485 page_size as GuestUsize,
486 )),
487 ];
488 let layout = AddressSpaceLayout::new(GUEST_PHYS_END, GUEST_MEM_START, GUEST_MEM_END);
489 let address_space = AddressSpaceBase::from_regions(address_space_region, layout);
490
491 assert!(!address_space.is_dax_region(GuestAddress(page_size)));
492 assert!(!address_space.is_dax_region(GuestAddress(page_size * 2)));
493 assert!(address_space.is_dax_region(GuestAddress(GUEST_DEVICE_START)));
494 assert!(address_space.is_dax_region(GuestAddress(GUEST_DEVICE_START + 1)));
495 assert!(!address_space.is_dax_region(GuestAddress(GUEST_DEVICE_START + page_size)));
496 assert!(address_space.is_dax_region(GuestAddress(GUEST_DEVICE_START + page_size - 1)));
497 }
498
499 #[test]
500 fn test_address_space_base_prot_flags() {
501 let reg1 = Arc::new(AddressSpaceRegion::build(
502 AddressSpaceRegionType::DefaultMemory,
503 GuestAddress(0x100),
504 0x200,
505 Some(0),
506 None,
507 0,
508 0,
509 false,
510 ));
511 let reg2 = Arc::new(AddressSpaceRegion::new(
512 AddressSpaceRegionType::DefaultMemory,
513 GuestAddress(0x300),
514 0x300,
515 ));
516 let regions = vec![reg1, reg2];
517 let layout = AddressSpaceLayout::new(0x2000, 0x0, 0x1800);
518 let address_space = AddressSpaceBase::from_regions(regions, layout);
519
520 assert_eq!(address_space.prot_flags(GuestAddress(0x200)).unwrap(), 0);
522 assert_eq!(
524 address_space.prot_flags(GuestAddress(0x500)).unwrap(),
525 libc::PROT_READ | libc::PROT_WRITE
526 );
527 assert!(matches!(
529 address_space.prot_flags(GuestAddress(0x600)),
530 Err(AddressSpaceError::InvalidRegionType)
531 ));
532 }
533
534 #[test]
535 fn test_address_space_base_numa_node_id() {
536 let reg1 = Arc::new(AddressSpaceRegion::build(
537 AddressSpaceRegionType::DefaultMemory,
538 GuestAddress(0x100),
539 0x200,
540 Some(0),
541 None,
542 0,
543 0,
544 false,
545 ));
546 let reg2 = Arc::new(AddressSpaceRegion::build(
547 AddressSpaceRegionType::DefaultMemory,
548 GuestAddress(0x300),
549 0x300,
550 None,
551 None,
552 0,
553 0,
554 false,
555 ));
556 let regions = vec![reg1, reg2];
557 let layout = AddressSpaceLayout::new(0x2000, 0x0, 0x1800);
558 let address_space = AddressSpaceBase::from_regions(regions, layout);
559
560 assert_eq!(address_space.numa_node_id(0x200).unwrap(), 0);
562 assert_eq!(address_space.numa_node_id(0x400), None);
564 assert_eq!(address_space.numa_node_id(0x600), None);
566 }
567
568 #[test]
569 fn test_address_space_convert_into_vm_as() {
570 let gmm = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0x0), 0x400)]).unwrap();
572 let _vm = AddressSpace::convert_into_vm_as(gmm);
573 }
574
575 #[test]
576 fn test_address_space_insert_region() {
577 let reg1 = Arc::new(AddressSpaceRegion::build(
578 AddressSpaceRegionType::DefaultMemory,
579 GuestAddress(0x100),
580 0x200,
581 None,
582 None,
583 0,
584 0,
585 false,
586 ));
587 let reg2 = Arc::new(AddressSpaceRegion::build(
588 AddressSpaceRegionType::DefaultMemory,
589 GuestAddress(0x300),
590 0x200,
591 None,
592 None,
593 0,
594 0,
595 false,
596 ));
597 let regions = vec![reg1];
598 let layout = AddressSpaceLayout::new(0x2000, 0x100, 0x1800);
599 let mut address_space = AddressSpace::from_regions(regions, layout);
600
601 assert!(matches!(address_space.insert_region(reg2).unwrap(), ()));
603
604 let invalid_reg = Arc::new(AddressSpaceRegion::build(
606 AddressSpaceRegionType::DefaultMemory,
607 GuestAddress(0x0),
608 0x100,
609 None,
610 None,
611 0,
612 0,
613 false,
614 ));
615 assert_eq!(
616 format!(
617 "{:?}",
618 address_space.insert_region(invalid_reg).err().unwrap()
619 ),
620 format!("InvalidAddressRange({:?}, {:?})", 0x0, 0x100)
621 );
622
623 let intersected_reg = Arc::new(AddressSpaceRegion::build(
626 AddressSpaceRegionType::DefaultMemory,
627 GuestAddress(0x400),
628 0x200,
629 None,
630 None,
631 0,
632 0,
633 false,
634 ));
635 assert_eq!(
636 format!(
637 "{:?}",
638 address_space.insert_region(intersected_reg).err().unwrap()
639 ),
640 format!("InvalidAddressRange({:?}, {:?})", 0x400, 0x200)
641 );
642 }
643
644 #[test]
645 fn test_address_space_walk_regions() {
646 let reg1 = Arc::new(AddressSpaceRegion::build(
647 AddressSpaceRegionType::DefaultMemory,
648 GuestAddress(0x100),
649 0x200,
650 None,
651 None,
652 0,
653 0,
654 false,
655 ));
656 let reg2 = Arc::new(AddressSpaceRegion::build(
657 AddressSpaceRegionType::DefaultMemory,
658 GuestAddress(0x300),
659 0x200,
660 None,
661 None,
662 0,
663 0,
664 false,
665 ));
666 let regions = vec![reg1, reg2];
667 let layout = AddressSpaceLayout::new(0x2000, 0x0, 0x1800);
668 let address_space = AddressSpace::from_regions(regions, layout);
669
670 fn access_all_hotplug_flag(
671 region: &Arc<AddressSpaceRegion>,
672 ) -> Result<(), AddressSpaceError> {
673 region.is_hotplug();
674 Ok(())
675 }
676
677 assert!(matches!(
678 address_space.walk_regions(access_all_hotplug_flag).unwrap(),
679 ()
680 ));
681 }
682
683 #[test]
684 fn test_address_space_layout() {
685 let reg = Arc::new(AddressSpaceRegion::build(
686 AddressSpaceRegionType::DefaultMemory,
687 GuestAddress(0x100),
688 0x1000,
689 None,
690 None,
691 0,
692 0,
693 false,
694 ));
695 let regions = vec![reg];
696 let layout = AddressSpaceLayout::new(0x2000, 0x0, 0x1800);
697 let address_space = AddressSpace::from_regions(regions, layout.clone());
698
699 assert_eq!(layout, address_space.layout());
700 }
701
702 #[test]
703 fn test_address_space_last_addr() {
704 let reg1 = Arc::new(AddressSpaceRegion::build(
705 AddressSpaceRegionType::DefaultMemory,
706 GuestAddress(0x100),
707 0x200,
708 None,
709 None,
710 0,
711 0,
712 false,
713 ));
714 let reg2 = Arc::new(AddressSpaceRegion::build(
715 AddressSpaceRegionType::DefaultMemory,
716 GuestAddress(0x300),
717 0x200,
718 None,
719 None,
720 0,
721 0,
722 false,
723 ));
724 let regions = vec![reg1, reg2];
725 let layout = AddressSpaceLayout::new(0x2000, 0x0, 0x1800);
726 let address_space = AddressSpace::from_regions(regions, layout);
727
728 assert_eq!(address_space.last_addr(), GuestAddress(0x500 - 1));
729 }
730
731 #[test]
732 fn test_address_space_is_dax_region() {
733 let page_size = 4096;
734 let address_space_region = vec![
735 Arc::new(AddressSpaceRegion::new(
736 AddressSpaceRegionType::DefaultMemory,
737 GuestAddress(page_size),
738 page_size as GuestUsize,
739 )),
740 Arc::new(AddressSpaceRegion::new(
741 AddressSpaceRegionType::DefaultMemory,
742 GuestAddress(page_size * 2),
743 page_size as GuestUsize,
744 )),
745 Arc::new(AddressSpaceRegion::new(
746 AddressSpaceRegionType::DAXMemory,
747 GuestAddress(GUEST_DEVICE_START),
748 page_size as GuestUsize,
749 )),
750 ];
751 let layout = AddressSpaceLayout::new(GUEST_PHYS_END, GUEST_MEM_START, GUEST_MEM_END);
752 let address_space = AddressSpace::from_regions(address_space_region, layout);
753
754 assert!(!address_space.is_dax_region(GuestAddress(page_size)));
755 assert!(!address_space.is_dax_region(GuestAddress(page_size * 2)));
756 assert!(address_space.is_dax_region(GuestAddress(GUEST_DEVICE_START)));
757 assert!(address_space.is_dax_region(GuestAddress(GUEST_DEVICE_START + 1)));
758 assert!(!address_space.is_dax_region(GuestAddress(GUEST_DEVICE_START + page_size)));
759 assert!(address_space.is_dax_region(GuestAddress(GUEST_DEVICE_START + page_size - 1)));
760 }
761
762 #[test]
763 fn test_address_space_prot_flags() {
764 let reg1 = Arc::new(AddressSpaceRegion::build(
765 AddressSpaceRegionType::DefaultMemory,
766 GuestAddress(0x100),
767 0x200,
768 Some(0),
769 None,
770 0,
771 0,
772 false,
773 ));
774 let reg2 = Arc::new(AddressSpaceRegion::new(
775 AddressSpaceRegionType::DefaultMemory,
776 GuestAddress(0x300),
777 0x300,
778 ));
779 let regions = vec![reg1, reg2];
780 let layout = AddressSpaceLayout::new(0x2000, 0x0, 0x1800);
781 let address_space = AddressSpace::from_regions(regions, layout);
782
783 assert_eq!(address_space.prot_flags(GuestAddress(0x200)).unwrap(), 0);
785 assert_eq!(
787 address_space.prot_flags(GuestAddress(0x500)).unwrap(),
788 libc::PROT_READ | libc::PROT_WRITE
789 );
790 assert!(matches!(
792 address_space.prot_flags(GuestAddress(0x600)),
793 Err(AddressSpaceError::InvalidRegionType)
794 ));
795 }
796
797 #[test]
798 fn test_address_space_numa_node_id() {
799 let reg1 = Arc::new(AddressSpaceRegion::build(
800 AddressSpaceRegionType::DefaultMemory,
801 GuestAddress(0x100),
802 0x200,
803 Some(0),
804 None,
805 0,
806 0,
807 false,
808 ));
809 let reg2 = Arc::new(AddressSpaceRegion::build(
810 AddressSpaceRegionType::DefaultMemory,
811 GuestAddress(0x300),
812 0x300,
813 None,
814 None,
815 0,
816 0,
817 false,
818 ));
819 let regions = vec![reg1, reg2];
820 let layout = AddressSpaceLayout::new(0x2000, 0x0, 0x1800);
821 let address_space = AddressSpace::from_regions(regions, layout);
822
823 assert_eq!(address_space.numa_node_id(0x200).unwrap(), 0);
825 assert_eq!(address_space.numa_node_id(0x400), None);
827 assert_eq!(address_space.numa_node_id(0x600), None);
829 }
830}