@@ -17,10 +17,10 @@ pub mod msr;
1717/// Logic for configuring x86_64 registers.
1818pub mod regs;
1919
20- use crate :: { ArchMemoryInfo , InitrdConfig } ;
21- use crate :: x86_64:: layout:: { MMIO_MEM_START , FIRST_ADDR_PAST_32BITS , EBDA_START } ;
20+ use crate :: x86_64:: layout:: { EBDA_START , FIRST_ADDR_PAST_32BITS , MMIO_MEM_START } ;
2221#[ cfg( feature ="tee" ) ]
23- use crate :: x86_64:: layout:: { FIRMWARE_START , FIRMWARE_SIZE } ;
22+ use crate :: x86_64:: layout:: { FIRMWARE_SIZE , FIRMWARE_START } ;
23+ use crate :: { ArchMemoryInfo , InitrdConfig } ;
2424use arch_gen:: x86:: bootparam:: { boot_params, E820_RAM } ;
2525use vm_memory:: Bytes ;
2626use vm_memory:: {
@@ -63,74 +63,91 @@ pub fn arch_memory_regions(
6363kernel_load_addr : Option < u64 > ,
6464kernel_size : usize ,
6565initrd_size : u64 ,
66+ firmware_size : Option < usize > ,
6667) ->( ArchMemoryInfo , Vec < ( GuestAddress , usize ) > ) {
6768let page_size: usize =unsafe { libc:: sysconf ( libc:: _SC_PAGESIZE) . try_into ( ) . unwrap ( ) } ;
6869
6970let size =align_upwards ! ( size, page_size) ;
7071
7172// It's safe to cast MMIO_MEM_START to usize because it fits in a u32 variable
7273// (It points to an address in the 32 bit space).
73- let ( ram_last_addr, shm_start_addr, regions) =match size. checked_sub ( MMIO_MEM_START as usize ) {
74+ let ( ram_last_addr, shm_start_addr, regions, firmware_addr) =match size
75+ . checked_sub ( MMIO_MEM_START as usize )
76+ {
7477// case1: guest memory fits before the gap
7578None |Some ( 0 ) =>{
7679let shm_start_addr =FIRST_ADDR_PAST_32BITS ;
7780
78- if let Some ( kernel_load_addr) = kernel_load_addr{
81+ let ( ram_last_addr , mut regions ) = if let Some ( kernel_load_addr) = kernel_load_addr{
7982if size <( kernel_load_addr + kernel_sizeas u64 ) as usize {
8083panic ! ( "Kernel doesn't fit in RAM" ) ;
8184}
8285
8386let ram_last_addr = kernel_load_addr + kernel_sizeas u64 + sizeas u64 ;
8487(
8588 ram_last_addr,
86- shm_start_addr,
8789vec ! [
8890( GuestAddress ( 0 ) , kernel_load_addras usize ) ,
8991( GuestAddress ( kernel_load_addr + kernel_sizeas u64 ) , size) ,
9092] ,
9193)
9294} else {
9395let ram_last_addr = sizeas u64 ;
94- ( ram_last_addr, shm_start_addr, vec ! [ ( GuestAddress ( 0 ) , size) ] )
95- }
96+ ( ram_last_addr, vec ! [ ( GuestAddress ( 0 ) , size) ] )
97+ } ;
98+
99+ let firmware_addr =if let Some ( firmware_size) = firmware_size{
100+ let firmware_start = layout:: FIRST_ADDR_PAST_32BITS - firmware_sizeas u64 ;
101+ regions. push ( ( GuestAddress ( firmware_start) , firmware_size) ) ;
102+ firmware_start
103+ } else {
104+ 0
105+ } ;
106+
107+ ( ram_last_addr, shm_start_addr, regions, firmware_addr)
96108}
97109
98110// case2: guest memory extends beyond the gap
99111Some ( remaining) =>{
100112let ram_last_addr =FIRST_ADDR_PAST_32BITS + remainingas u64 ;
101113let shm_start_addr =( ( ram_last_addr /0x4000_0000 ) +1 ) * 0x4000_0000 ;
102114
103- if let Some ( kernel_load_addr) = kernel_load_addr{
104- (
105- ram_last_addr,
106- shm_start_addr,
107- vec ! [
108- ( GuestAddress ( 0 ) , kernel_load_addras usize ) ,
109- (
110- GuestAddress ( kernel_load_addr + kernel_sizeas u64 ) ,
111- ( MMIO_MEM_START -( kernel_load_addr + kernel_sizeas u64 ) ) as usize ,
112- ) ,
113- ( GuestAddress ( FIRST_ADDR_PAST_32BITS ) , remaining) ,
114- ] ,
115- )
115+ let mut regions =if let Some ( kernel_load_addr) = kernel_load_addr{
116+ vec ! [
117+ ( GuestAddress ( 0 ) , kernel_load_addras usize ) ,
118+ (
119+ GuestAddress ( kernel_load_addr + kernel_sizeas u64 ) ,
120+ ( MMIO_MEM_START -( kernel_load_addr + kernel_sizeas u64 ) ) as usize ,
121+ ) ,
122+ ( GuestAddress ( FIRST_ADDR_PAST_32BITS ) , remaining) ,
123+ ]
116124} else {
117- (
118- ram_last_addr,
119- shm_start_addr,
120- vec ! [
121- ( GuestAddress ( 0 ) , MMIO_MEM_START as usize ) ,
122- ( GuestAddress ( FIRST_ADDR_PAST_32BITS ) , remaining) ,
123- ] ,
124- )
125- }
125+ vec ! [
126+ ( GuestAddress ( 0 ) , MMIO_MEM_START as usize ) ,
127+ ( GuestAddress ( FIRST_ADDR_PAST_32BITS ) , remaining) ,
128+ ]
129+ } ;
130+
131+ let firmware_addr =if let Some ( firmware_size) = firmware_size{
132+ let firmware_start = layout:: FIRST_ADDR_PAST_32BITS - firmware_sizeas u64 ;
133+ regions. insert (
134+ regions. len ( ) -2 ,
135+ ( GuestAddress ( firmware_start) , firmware_size) ,
136+ ) ;
137+ firmware_start
138+ } else {
139+ 0
140+ } ;
141+
142+ ( ram_last_addr, shm_start_addr, regions, firmware_addr)
126143}
127144} ;
128145let info =ArchMemoryInfo {
129146 ram_last_addr,
130147 shm_start_addr,
131148 page_size,
132149initrd_addr : ram_last_addr - initrd_size,
133- firmware_addr : 0 ,
150+ firmware_addr,
134151} ;
135152( info, regions)
136153}
@@ -146,6 +163,7 @@ pub fn arch_memory_regions(
146163kernel_load_addr : Option < u64 > ,
147164kernel_size : usize ,
148165_initrd_size : u64 ,
166+ _firmware_size : Option < usize > ,
149167) ->( ArchMemoryInfo , Vec < ( GuestAddress , usize ) > ) {
150168let page_size: usize =unsafe { libc:: sysconf ( libc:: _SC_PAGESIZE) . try_into ( ) . unwrap ( ) } ;
151169
@@ -348,7 +366,7 @@ mod tests {
348366#[ test]
349367fn regions_lt_4gb ( ) {
350368let ( _info, regions) =
351- arch_memory_regions ( 1usize <<29 , Some ( KERNEL_LOAD_ADDR ) , KERNEL_SIZE , 0 ) ;
369+ arch_memory_regions ( 1usize <<29 , Some ( KERNEL_LOAD_ADDR ) , KERNEL_SIZE , 0 , None ) ;
352370assert_eq ! ( 2 , regions. len( ) ) ;
353371assert_eq ! ( GuestAddress ( 0 ) , regions[ 0 ] . 0 ) ;
354372assert_eq ! ( KERNEL_LOAD_ADDR as usize , regions[ 0 ] . 1 ) ;
@@ -366,6 +384,7 @@ mod tests {
366384Some ( KERNEL_LOAD_ADDR ) ,
367385KERNEL_SIZE ,
3683860 ,
387+ None ,
369388) ;
370389assert_eq ! ( 3 , regions. len( ) ) ;
371390assert_eq ! ( GuestAddress ( 0 ) , regions[ 0 ] . 0 ) ;
@@ -393,21 +412,21 @@ mod tests {
393412// Now assigning some memory that falls before the 32bit memory hole.
394413let mem_size =128 <<20 ;
395414let ( arch_mem_info, arch_mem_regions) =
396- arch_memory_regions ( mem_size, Some ( KERNEL_LOAD_ADDR ) , KERNEL_SIZE , 0 ) ;
415+ arch_memory_regions ( mem_size, Some ( KERNEL_LOAD_ADDR ) , KERNEL_SIZE , 0 , None ) ;
397416let gm =GuestMemoryMmap :: from_ranges ( & arch_mem_regions) . unwrap ( ) ;
398417configure_system ( & gm, & arch_mem_info, GuestAddress ( 0 ) , 0 , & None , no_vcpus) . unwrap ( ) ;
399418
400419// Now assigning some memory that is equal to the start of the 32bit memory hole.
401420let mem_size =3328 <<20 ;
402421let ( arch_mem_info, arch_mem_regions) =
403- arch_memory_regions ( mem_size, Some ( KERNEL_LOAD_ADDR ) , KERNEL_SIZE , 0 ) ;
422+ arch_memory_regions ( mem_size, Some ( KERNEL_LOAD_ADDR ) , KERNEL_SIZE , 0 , None ) ;
404423let gm =GuestMemoryMmap :: from_ranges ( & arch_mem_regions) . unwrap ( ) ;
405424configure_system ( & gm, & arch_mem_info, GuestAddress ( 0 ) , 0 , & None , no_vcpus) . unwrap ( ) ;
406425
407426// Now assigning some memory that falls after the 32bit memory hole.
408427let mem_size =3330 <<20 ;
409428let ( arch_mem_info, arch_mem_regions) =
410- arch_memory_regions ( mem_size, Some ( KERNEL_LOAD_ADDR ) , KERNEL_SIZE , 0 ) ;
429+ arch_memory_regions ( mem_size, Some ( KERNEL_LOAD_ADDR ) , KERNEL_SIZE , 0 , None ) ;
411430let gm =GuestMemoryMmap :: from_ranges ( & arch_mem_regions) . unwrap ( ) ;
412431configure_system ( & gm, & arch_mem_info, GuestAddress ( 0 ) , 0 , & None , no_vcpus) . unwrap ( ) ;
413432}