6
6
use igvm_defs:: { MemoryMapEntryType , PAGE_SIZE_4K } ;
7
7
use super :: PartitionInfo ;
8
8
9
- struct DmaLookupStruct {
10
- /// Logical processors for VM.
11
- vp_count : u32 ,
12
- /// Vtl2AddressRangeSize - Vtl2MmioAddressRangeSize.
13
- vtl2_memory_mb : u32 ,
14
- /// DMA hint in MiB.
15
- dma_hint_mb : u32 ,
16
- }
17
-
18
9
/// Lookup table for DMA hint calculation.
19
- const LOOKUP_TABLE : & ' static [ DmaLookupStruct ] = & [
20
- DmaLookupStruct {
21
- vp_count : 2 ,
22
- vtl2_memory_mb : 98 ,
23
- dma_hint_mb : 4 ,
24
- } ,
25
- DmaLookupStruct {
26
- vp_count : 4 ,
27
- vtl2_memory_mb : 110 ,
28
- dma_hint_mb : 6 ,
29
- } ,
30
- DmaLookupStruct {
31
- vp_count : 8 ,
32
- vtl2_memory_mb : 148 ,
33
- dma_hint_mb : 10 ,
34
- } ,
35
- DmaLookupStruct {
36
- vp_count : 16 ,
37
- vtl2_memory_mb : 256 ,
38
- dma_hint_mb : 18 ,
39
- } ,
40
- DmaLookupStruct {
41
- vp_count : 32 ,
42
- vtl2_memory_mb : 516 ,
43
- dma_hint_mb : 36 ,
44
- } ,
45
- DmaLookupStruct {
46
- vp_count : 48 ,
47
- vtl2_memory_mb : 718 ,
48
- dma_hint_mb : 52 ,
49
- } ,
50
- DmaLookupStruct {
51
- vp_count : 64 ,
52
- vtl2_memory_mb : 924 ,
53
- dma_hint_mb : 68 ,
54
- } ,
55
- DmaLookupStruct {
56
- vp_count : 96 ,
57
- vtl2_memory_mb : 1340 ,
58
- dma_hint_mb : 102 ,
59
- } ,
10
+ /// Using tuples instead of structs to keep it readable.
11
+ /// Let's keep the table sorted by VP count, then by assigned memory.
12
+ /// Using u16 to keep the memory req short.
13
+ /// Max VTL2 memory known today is 24838 MiB.
14
+ /// (vp_count, vtl2_memory_mb, dma_hint_mb)
15
+ const LOOKUP_TABLE : & [ ( u16 , u16 , u16 ) ] = & [
16
+ ( 2 , 98 , 4 ) ,
17
+ ( 4 , 110 , 6 ) ,
18
+ ( 8 , 148 , 10 ) ,
19
+ ( 16 , 256 , 18 ) ,
20
+ ( 32 , 516 , 36 ) ,
21
+ ( 48 , 718 , 52 ) ,
22
+ ( 64 , 924 , 68 ) ,
23
+ ( 96 , 1340 , 102 ) ,
60
24
] ;
61
25
62
26
/// Round up to next 2MiB.
@@ -77,34 +41,40 @@ pub fn vtl2_calculate_dma_hint(vp_count: usize, storage: &PartitionInfo) -> u64
77
41
if mem_size > 0 && mem_size < 0xFFFFFFFF00000 {
78
42
let mem_size_mb = ( mem_size / 1048576 ) as u32 ;
79
43
80
- let mut min_vtl2_memory_mb = 1000000 ;
44
+ let mut min_vtl2_memory_mb = 65535 ;
81
45
let mut max_vtl2_memory_mb = 0 ;
82
46
83
47
// To avoid using floats, scale ratios to 1:1000.
84
48
let mut min_ratio_1000th = 100000 ;
85
49
let mut max_ratio_1000th = 1000 ;
86
50
87
- let mut min_vp_count = 1 ;
88
- let mut max_vp_count = vp_count as u32 ;
89
-
90
- for f in LOOKUP_TABLE {
91
- if f. vp_count == vp_count as u32 {
92
- if f. vtl2_memory_mb == mem_size_mb {
93
- // Found exact match.
94
- dma_hint_4k = f. dma_hint_mb as u64 * 1048576 / PAGE_SIZE_4K ;
95
- break ;
96
- } else {
97
- // Prepare for possible extrapolation.
98
- min_vtl2_memory_mb = min_vtl2_memory_mb. min ( f. vtl2_memory_mb ) ;
99
- max_vtl2_memory_mb = max_vtl2_memory_mb. max ( f. vtl2_memory_mb ) ;
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 ) ;
51
+ let mut min_vp_count: u16 = 1 ;
52
+ let mut max_vp_count = vp_count as u16 ;
53
+
54
+ for ( vp_lookup, vtl2_memory_mb, dma_hint_mb) in LOOKUP_TABLE {
55
+ match ( * vp_lookup) . cmp ( & ( vp_count as u16 ) ) {
56
+ core:: cmp:: Ordering :: Less => {
57
+ // Find nearest.
58
+ min_vp_count = min_vp_count. max ( * vp_lookup) ;
59
+ }
60
+ core:: cmp:: Ordering :: Equal => {
61
+ if * vtl2_memory_mb == mem_size_mb as u16 {
62
+ // Found exact match.
63
+ dma_hint_4k = * dma_hint_mb as u64 * 1048576 / PAGE_SIZE_4K ;
64
+ max_vtl2_memory_mb = * vtl2_memory_mb;
65
+ break ;
66
+ } else {
67
+ // Prepare for possible extrapolation.
68
+ min_vtl2_memory_mb = min_vtl2_memory_mb. min ( * vtl2_memory_mb) ;
69
+ max_vtl2_memory_mb = max_vtl2_memory_mb. max ( * vtl2_memory_mb) ;
70
+ min_ratio_1000th = min_ratio_1000th. min ( * vtl2_memory_mb as u32 * 1000 / * dma_hint_mb as u32 ) ;
71
+ max_ratio_1000th = max_ratio_1000th. max ( * vtl2_memory_mb as u32 * 1000 / * dma_hint_mb as u32 ) ;
72
+ }
73
+ }
74
+ core:: cmp:: Ordering :: Greater => {
75
+ // Find nearest.
76
+ max_vp_count = max_vp_count. min ( * vp_lookup) ;
102
77
}
103
- } else if f. vp_count < vp_count as u32 {
104
- // Find the nearest VP counts if exact match is not in the table.
105
- min_vp_count = min_vp_count. max ( f. vp_count ) ;
106
- } else if f. vp_count > vp_count as u32 {
107
- max_vp_count = max_vp_count. min ( f. vp_count ) ;
108
78
}
109
79
}
110
80
@@ -113,17 +83,17 @@ pub fn vtl2_calculate_dma_hint(vp_count: usize, storage: &PartitionInfo) -> u64
113
83
if max_vtl2_memory_mb == 0 {
114
84
LOOKUP_TABLE
115
85
. iter ( )
116
- . filter ( |e| e . vp_count == min_vp_count || e . vp_count == max_vp_count)
117
- . for_each ( |f | {
118
- min_vtl2_memory_mb = min_vtl2_memory_mb. min ( f . vtl2_memory_mb ) ;
119
- max_vtl2_memory_mb = max_vtl2_memory_mb. max ( f . vtl2_memory_mb ) ;
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 ) ;
86
+ . filter ( |( vp_lookup , _ , _ ) | * vp_lookup == min_vp_count || * vp_lookup == max_vp_count)
87
+ . for_each ( |( _ , vtl2_memory_mb , dma_hint_mb ) | {
88
+ min_vtl2_memory_mb = min_vtl2_memory_mb. min ( * vtl2_memory_mb) ;
89
+ max_vtl2_memory_mb = max_vtl2_memory_mb. max ( * vtl2_memory_mb) ;
90
+ min_ratio_1000th = min_ratio_1000th. min ( * vtl2_memory_mb as u32 * 1000 / * dma_hint_mb as u32 ) ;
91
+ max_ratio_1000th = max_ratio_1000th. max ( * vtl2_memory_mb as u32 * 1000 / * dma_hint_mb as u32 ) ;
122
92
} ) ;
123
93
}
124
94
125
95
if dma_hint_4k == 0 {
126
- // If we didn 't find an exact match for our vp_count, try to extrapolate.
96
+ // Didn 't find an exact match for vp_count, try to extrapolate.
127
97
dma_hint_4k = ( mem_size_mb as u64 * 1000u64 * ( 1048576u64 / PAGE_SIZE_4K ) ) /
128
98
( ( min_ratio_1000th + max_ratio_1000th) as u64 / 2u64 ) ;
129
99
0 commit comments