3
3
4
4
//! Calculate DMA hint value if not provided by host.
5
5
6
- use crate :: log;
7
6
use igvm_defs:: { MemoryMapEntryType , PAGE_SIZE_4K } ;
8
7
use super :: PartitionInfo ;
9
8
@@ -60,10 +59,14 @@ const LOOKUP_TABLE: &'static [DmaLookupStruct] = &[
60
59
} ,
61
60
] ;
62
61
62
+ /// Round up to next 2MiB.
63
+ fn round_up_to_2mb ( pages_4k : u64 ) -> u64 {
64
+ ( pages_4k + 511 ) & !( 511 )
65
+ }
66
+
63
67
/// Returns calculated DMA hint value, in 4k pages.
64
68
pub fn vtl2_calculate_dma_hint ( vp_count : usize , storage : & PartitionInfo ) -> u64 {
65
69
let mut dma_hint_4k = 0 ;
66
- log ! ( "YSP: vp_count = {}" , vp_count) ;
67
70
let mem_size = storage
68
71
. vtl2_ram
69
72
. iter ( )
@@ -73,16 +76,16 @@ pub fn vtl2_calculate_dma_hint(vp_count: usize, storage: &PartitionInfo) -> u64
73
76
// Sanity check for the calculated memory size.
74
77
if mem_size > 0 && mem_size < 0xFFFFFFFF00000 {
75
78
let mem_size_mb = ( mem_size / 1048576 ) as u32 ;
76
- log ! ( "YSP: mem_size_mb = {}" , mem_size_mb) ;
77
79
78
80
let mut min_vtl2_memory_mb = 1000000 ;
79
81
let mut max_vtl2_memory_mb = 0 ;
80
- // TODO: If we won't allow floats in boot-shim, replace with scaled integers
81
- let mut min_ratio: f32 = 0.1 ;
82
- let mut max_ratio: f32 = 0.01 ;
82
+
83
+ // To avoid using floats, scale ratios to 1:1000.
84
+ let mut min_ratio_1000th = 100000 ;
85
+ let mut max_ratio_1000th = 1000 ;
83
86
84
87
let mut min_vp_count = 1 ;
85
- let mut max_vp_count = 4096 ;
88
+ let mut max_vp_count = vp_count as u32 ;
86
89
87
90
for f in LOOKUP_TABLE {
88
91
if f. vp_count == vp_count as u32 {
@@ -94,8 +97,8 @@ pub fn vtl2_calculate_dma_hint(vp_count: usize, storage: &PartitionInfo) -> u64
94
97
// Prepare for possible extrapolation.
95
98
min_vtl2_memory_mb = min_vtl2_memory_mb. min ( f. vtl2_memory_mb ) ;
96
99
max_vtl2_memory_mb = max_vtl2_memory_mb. max ( f. vtl2_memory_mb ) ;
97
- min_ratio = min_ratio . min ( f. dma_hint_mb as f32 / f. vtl2_memory_mb as f32 ) ;
98
- max_ratio = max_ratio . max ( f. dma_hint_mb as f32 / f. vtl2_memory_mb as f32 ) ;
100
+ min_ratio_1000th = min_ratio_1000th . min ( f. vtl2_memory_mb as u32 * 1000 / f. dma_hint_mb as u32 ) ;
101
+ max_ratio_1000th = max_ratio_1000th . max ( f. vtl2_memory_mb as u32 * 1000 / f. dma_hint_mb as u32 ) ;
99
102
}
100
103
} else if f. vp_count < vp_count as u32 {
101
104
// Find the nearest VP counts if exact match is not in the table.
@@ -112,19 +115,20 @@ pub fn vtl2_calculate_dma_hint(vp_count: usize, storage: &PartitionInfo) -> u64
112
115
. iter ( )
113
116
. filter ( |e| e. vp_count == min_vp_count || e. vp_count == max_vp_count)
114
117
. for_each ( |f| {
115
- // Prepare for possible extrapolation.
116
118
min_vtl2_memory_mb = min_vtl2_memory_mb. min ( f. vtl2_memory_mb ) ;
117
119
max_vtl2_memory_mb = max_vtl2_memory_mb. max ( f. vtl2_memory_mb ) ;
118
- min_ratio = min_ratio . min ( f. dma_hint_mb as f32 / f. vtl2_memory_mb as f32 ) ;
119
- max_ratio = max_ratio . max ( f. dma_hint_mb as f32 / f. vtl2_memory_mb as f32 ) ;
120
+ min_ratio_1000th = min_ratio_1000th . min ( f. vtl2_memory_mb as u32 * 1000 / f. dma_hint_mb as u32 ) ;
121
+ max_ratio_1000th = max_ratio_1000th . max ( f. vtl2_memory_mb as u32 * 1000 / f. dma_hint_mb as u32 ) ;
120
122
} ) ;
121
123
}
122
-
124
+
123
125
if dma_hint_4k == 0 {
124
126
// If we didn't find an exact match for our vp_count, try to extrapolate.
125
- dma_hint_4k = ( mem_size_mb as f32 * ( ( min_ratio + max_ratio) / 2.0 ) ) as u64 *
126
- 1048576 /
127
- PAGE_SIZE_4K ;
127
+ dma_hint_4k = ( mem_size_mb as u64 * 1000u64 * ( 1048576u64 / PAGE_SIZE_4K ) ) /
128
+ ( ( min_ratio_1000th + max_ratio_1000th) as u64 / 2u64 ) ;
129
+
130
+ // And then round up to 2MiB.
131
+ dma_hint_4k = round_up_to_2mb ( dma_hint_4k) ;
128
132
}
129
133
}
130
134
@@ -136,6 +140,7 @@ mod test {
136
140
use super :: * ;
137
141
use crate :: host_params:: MemoryEntry ;
138
142
use crate :: MemoryRange ;
143
+ use test_with_tracing:: test;
139
144
140
145
#[ test]
141
146
fn test_vtl2_calculate_dma_hint ( ) {
@@ -164,7 +169,23 @@ mod test {
164
169
mem_type : MemoryMapEntryType :: VTL2_PROTECTABLE ,
165
170
vnode : 0 ,
166
171
} ) ;
167
- // TODO: Unfinished, maybe the return value is incorrect.
168
- assert_eq ! ( vtl2_calculate_dma_hint( 112 , & storage) , 2048 ) ;
172
+ assert_eq ! ( vtl2_calculate_dma_hint( 112 , & storage) , 2560 ) ;
173
+
174
+ // Test unusual VP count.
175
+ storage. vtl2_ram . clear ( ) ;
176
+ storage. vtl2_ram . push ( MemoryEntry {
177
+ range : MemoryRange :: new ( 0x0 ..0x6000000 ) ,
178
+ mem_type : MemoryMapEntryType :: VTL2_PROTECTABLE ,
179
+ vnode : 0 ,
180
+ } ) ;
181
+ assert_eq ! ( vtl2_calculate_dma_hint( 52 , & storage) , 2048 ) ;
182
+
183
+ storage. vtl2_ram . clear ( ) ;
184
+ storage. vtl2_ram . push ( MemoryEntry {
185
+ range : MemoryRange :: new ( 0x0 ..0x8000000 ) ,
186
+ mem_type : MemoryMapEntryType :: VTL2_PROTECTABLE ,
187
+ vnode : 0 ,
188
+ } ) ;
189
+ assert_eq ! ( vtl2_calculate_dma_hint( 52 , & storage) , 2560 ) ;
169
190
}
170
191
}
0 commit comments