1+ use alloc:: vec:: Vec ;
2+
13use axaddrspace:: GuestPhysAddr ;
24use axerrno:: AxResult ;
35
46use axvm:: config:: AxVMCrateConfig ;
7+ use memory_addr:: PhysAddr ;
58
6- #[ cfg( target_arch = "aarch64" ) ]
7- use crate :: utils:: cache:: cache_clean_invalidate_d;
89use crate :: vmm:: VMRef ;
910use crate :: vmm:: config:: config;
1011
1112/// Loads the VM image files.
1213pub fn load_vm_images ( config : AxVMCrateConfig , vm : VMRef ) -> AxResult {
13- match config. kernel . image_location . as_deref ( ) {
14- Some ( "memory" ) => load_vm_images_from_memory ( config, vm) ,
14+ let load_ranges = match config. kernel . image_location . as_deref ( ) {
15+ Some ( "memory" ) => load_vm_images_from_memory ( config, vm. clone ( ) ) ,
1516 #[ cfg( feature = "fs" ) ]
16- Some ( "fs" ) => fs:: load_vm_images_from_filesystem ( config, vm) ,
17+ Some ( "fs" ) => fs:: load_vm_images_from_filesystem ( config, vm. clone ( ) ) ,
1718 _ => unimplemented ! (
1819 "Check your \" image_location\" in config.toml, \" memory\" and \" fs\" are supported,\n NOTE: \" fs\" feature should be enabled if you want to load images from filesystem. (APP_FEATURES=fs)"
1920 ) ,
21+ } ?;
22+ flush_vm_images ( & load_ranges) ;
23+ Ok ( ( ) )
24+ }
25+
26+ fn flush_vm_images ( ls : & [ LoadRange ] ) {
27+ for l in ls {
28+ unsafe {
29+ crate :: utils:: cache:: cache_clean_invalidate_d ( l. start . as_usize ( ) , l. size ) ;
30+ }
2031 }
2132}
2233
34+ struct LoadRange {
35+ start : PhysAddr ,
36+ size : usize ,
37+ }
38+
2339/// Load VM images from memory
2440/// into the guest VM's memory space based on the VM configuration.
25- fn load_vm_images_from_memory ( config : AxVMCrateConfig , vm : VMRef ) -> AxResult {
41+ fn load_vm_images_from_memory ( config : AxVMCrateConfig , vm : VMRef ) -> AxResult < Vec < LoadRange > > {
2642 info ! ( "Loading VM[{}] images from memory" , config. base. id) ;
43+ let mut load_ranges = Vec :: new ( ) ;
2744
2845 let vm_imags = config:: get_memory_images ( )
2946 . iter ( )
3047 . find ( |& v| v. id == config. base . id )
3148 . expect ( "VM images is missed, Perhaps add `VM_CONFIGS=PATH/CONFIGS/FILE` command." ) ;
3249
33- load_vm_image_from_memory ( vm_imags. kernel , config. kernel . kernel_load_addr , vm. clone ( ) )
34- . expect ( "Failed to load VM images" ) ;
50+ load_ranges. append (
51+ & mut load_vm_image_from_memory ( vm_imags. kernel , config. kernel . kernel_load_addr , vm. clone ( ) )
52+ . expect ( "Failed to load VM images" ) ,
53+ ) ;
3554
3655 // Load DTB image
3756 if let Some ( buffer) = vm_imags. dtb {
38- load_vm_image_from_memory ( buffer, config. kernel . dtb_load_addr . unwrap ( ) , vm. clone ( ) )
39- . expect ( "Failed to load DTB images" ) ;
57+ load_ranges. append (
58+ & mut load_vm_image_from_memory (
59+ buffer,
60+ config. kernel . dtb_load_addr . unwrap ( ) ,
61+ vm. clone ( ) ,
62+ )
63+ . expect ( "Failed to load DTB images" ) ,
64+ ) ;
4065 }
4166
4267 // Load BIOS image
4368 if let Some ( buffer) = vm_imags. bios {
44- load_vm_image_from_memory ( buffer, config. kernel . bios_load_addr . unwrap ( ) , vm. clone ( ) )
45- . expect ( "Failed to load BIOS images" ) ;
46- }
47- #[ cfg( target_arch = "aarch64" ) ]
48- {
49- for mem_region in & config. kernel . memory_regions {
50- debug ! (
51- "flush all guest cache GPA: 0x{:x}, Size: 0x{:x}" ,
52- mem_region. gpa, mem_region. size
53- ) ;
54- unsafe {
55- cache_clean_invalidate_d ( mem_region. gpa , mem_region. size ) ;
56- }
57- }
69+ load_ranges. append (
70+ & mut load_vm_image_from_memory (
71+ buffer,
72+ config. kernel . bios_load_addr . unwrap ( ) ,
73+ vm. clone ( ) ,
74+ )
75+ . expect ( "Failed to load BIOS images" ) ,
76+ ) ;
5877 }
5978
60- Ok ( ( ) )
79+ Ok ( load_ranges )
6180}
6281
63- fn load_vm_image_from_memory ( image_buffer : & [ u8 ] , load_addr : usize , vm : VMRef ) -> AxResult {
82+ fn load_vm_image_from_memory (
83+ image_buffer : & [ u8 ] ,
84+ load_addr : usize ,
85+ vm : VMRef ,
86+ ) -> AxResult < Vec < LoadRange > > {
6487 let mut buffer_pos = 0 ;
6588 let image_load_gpa = GuestPhysAddr :: from ( load_addr) ;
89+ let mut load_ranges = alloc:: vec![ ] ;
6690
6791 let image_size = image_buffer. len ( ) ;
6892
@@ -86,7 +110,10 @@ fn load_vm_image_from_memory(image_buffer: &[u8], load_addr: usize, vm: VMRef) -
86110 bytes_to_write,
87111 ) ;
88112 }
89-
113+ load_ranges. push ( LoadRange {
114+ start : ( region. as_ptr ( ) as usize ) . into ( ) ,
115+ size : bytes_to_write,
116+ } ) ;
90117 // Update the position of the buffer.
91118 buffer_pos += bytes_to_write;
92119
@@ -97,7 +124,7 @@ fn load_vm_image_from_memory(image_buffer: &[u8], load_addr: usize, vm: VMRef) -
97124 }
98125 }
99126
100- Ok ( ( ) )
127+ Ok ( load_ranges )
101128}
102129
103130#[ cfg( feature = "fs" ) ]
@@ -112,30 +139,38 @@ mod fs {
112139
113140 /// Loads the VM image files from the filesystem
114141 /// into the guest VM's memory space based on the VM configuration.
115- pub ( crate ) fn load_vm_images_from_filesystem ( config : AxVMCrateConfig , vm : VMRef ) -> AxResult {
142+ pub ( crate ) fn load_vm_images_from_filesystem (
143+ config : AxVMCrateConfig ,
144+ vm : VMRef ,
145+ ) -> AxResult < Vec < LoadRange > > {
116146 info ! ( "Loading VM images from filesystem" ) ;
147+ let mut load_ranges = Vec :: new ( ) ;
117148 // Load kernel image.
118- load_vm_image (
149+ load_ranges . append ( & mut load_vm_image (
119150 config. kernel . kernel_path ,
120151 GuestPhysAddr :: from ( config. kernel . kernel_load_addr ) ,
121152 vm. clone ( ) ,
122- ) ?;
153+ ) ?) ;
123154 // Load BIOS image if needed.
124155 if let Some ( bios_path) = config. kernel . bios_path {
125156 if let Some ( bios_load_addr) = config. kernel . bios_load_addr {
126- load_vm_image ( bios_path, GuestPhysAddr :: from ( bios_load_addr) , vm. clone ( ) ) ?;
157+ load_ranges. append ( & mut load_vm_image (
158+ bios_path,
159+ GuestPhysAddr :: from ( bios_load_addr) ,
160+ vm. clone ( ) ,
161+ ) ?) ;
127162 } else {
128163 return ax_err ! ( NotFound , "BIOS load addr is missed" ) ;
129164 }
130165 } ;
131166 // Load Ramdisk image if needed.
132167 if let Some ( ramdisk_path) = config. kernel . ramdisk_path {
133168 if let Some ( ramdisk_load_addr) = config. kernel . ramdisk_load_addr {
134- load_vm_image (
169+ load_ranges . append ( & mut load_vm_image (
135170 ramdisk_path,
136171 GuestPhysAddr :: from ( ramdisk_load_addr) ,
137172 vm. clone ( ) ,
138- ) ?;
173+ ) ?) ;
139174 } else {
140175 return ax_err ! ( NotFound , "Ramdisk load addr is missed" ) ;
141176 }
@@ -144,22 +179,36 @@ mod fs {
144179 // Todo: generate DTB file for guest VM.
145180 if let Some ( dtb_path) = config. kernel . dtb_path {
146181 if let Some ( dtb_load_addr) = config. kernel . dtb_load_addr {
147- load_vm_image ( dtb_path, GuestPhysAddr :: from ( dtb_load_addr) , vm. clone ( ) ) ?;
182+ load_ranges. append ( & mut load_vm_image (
183+ dtb_path,
184+ GuestPhysAddr :: from ( dtb_load_addr) ,
185+ vm. clone ( ) ,
186+ ) ?) ;
148187 } else {
149188 return ax_err ! ( NotFound , "DTB load addr is missed" ) ;
150189 }
151190 } ;
152- Ok ( ( ) )
191+ Ok ( load_ranges )
153192 }
154193
155- fn load_vm_image ( image_path : String , image_load_gpa : GuestPhysAddr , vm : VMRef ) -> AxResult {
194+ fn load_vm_image (
195+ image_path : String ,
196+ image_load_gpa : GuestPhysAddr ,
197+ vm : VMRef ,
198+ ) -> AxResult < Vec < LoadRange > > {
156199 use std:: io:: { BufReader , Read } ;
157200 let ( image_file, image_size) = open_image_file ( image_path. as_str ( ) ) ?;
158201
159202 let image_load_regions = vm. get_image_load_region ( image_load_gpa, image_size) ?;
203+ let mut load_ranges = Vec :: with_capacity ( image_load_regions. len ( ) ) ;
204+
160205 let mut file = BufReader :: new ( image_file) ;
161206
162207 for buffer in image_load_regions {
208+ load_ranges. push ( LoadRange {
209+ start : ( buffer. as_ptr ( ) as usize ) . into ( ) ,
210+ size : buffer. len ( ) ,
211+ } ) ;
163212 file. read_exact ( buffer) . map_err ( |err| {
164213 ax_err_type ! (
165214 Io ,
@@ -168,7 +217,7 @@ mod fs {
168217 } ) ?
169218 }
170219
171- Ok ( ( ) )
220+ Ok ( load_ranges )
172221 }
173222
174223 fn open_image_file ( file_name : & str ) -> AxResult < ( File , usize ) > {
0 commit comments