@@ -10,8 +10,7 @@ use crate::Vcpu;
10
10
use crate :: acpi:: x86_64:: {
11
11
apic_addr, rsdp_addr, setup_arch_dsdt, setup_arch_fadt, setup_interrupt_controllers,
12
12
} ;
13
- use crate :: device_manager:: acpi:: ACPIDeviceManager ;
14
- use crate :: device_manager:: mmio:: MMIODeviceManager ;
13
+ use crate :: device_manager:: DeviceManager ;
15
14
use crate :: device_manager:: resources:: ResourceAllocator ;
16
15
use crate :: vstate:: memory:: { GuestAddress , GuestMemoryMmap } ;
17
16
@@ -45,19 +44,22 @@ pub enum AcpiError {
45
44
/// allocator for allocating space for the tables
46
45
struct AcpiTableWriter < ' a > {
47
46
mem : & ' a GuestMemoryMmap ,
48
- resource_allocator : & ' a mut ResourceAllocator ,
49
47
}
50
48
51
49
impl AcpiTableWriter < ' _ > {
52
50
/// Write a table in guest memory
53
51
///
54
52
/// This will allocate enough space inside guest memory and write the table in the allocated
55
53
/// buffer. It returns the address in which it wrote the table.
56
- fn write_acpi_table < S > ( & mut self , table : & mut S ) -> Result < u64 , AcpiError >
54
+ fn write_acpi_table < S > (
55
+ & mut self ,
56
+ resource_allocator : & mut ResourceAllocator ,
57
+ table : & mut S ,
58
+ ) -> Result < u64 , AcpiError >
57
59
where
58
60
S : Sdt ,
59
61
{
60
- let addr = self . resource_allocator . allocate_system_memory (
62
+ let addr = resource_allocator. allocate_system_memory (
61
63
table. len ( ) . try_into ( ) . unwrap ( ) ,
62
64
1 ,
63
65
AllocPolicy :: FirstMatch ,
@@ -77,65 +79,76 @@ impl AcpiTableWriter<'_> {
77
79
}
78
80
79
81
/// Build the DSDT table for the guest
80
- fn build_dsdt (
81
- & mut self ,
82
- mmio_device_manager : & MMIODeviceManager ,
83
- acpi_device_manager : & ACPIDeviceManager ,
84
- ) -> Result < u64 , AcpiError > {
82
+ fn build_dsdt ( & mut self , device_manager : & mut DeviceManager ) -> Result < u64 , AcpiError > {
85
83
let mut dsdt_data = Vec :: new ( ) ;
86
84
87
85
// Virtio-devices DSDT data
88
- dsdt_data. extend_from_slice ( & mmio_device_manager . dsdt_data ) ;
86
+ dsdt_data. extend_from_slice ( & device_manager . mmio_devices . dsdt_data ) ;
89
87
90
88
// Add GED and VMGenID AML data.
91
- acpi_device_manager. append_aml_bytes ( & mut dsdt_data) ?;
89
+ device_manager
90
+ . acpi_devices
91
+ . append_aml_bytes ( & mut dsdt_data) ?;
92
92
93
93
// Architecture specific DSDT data
94
94
setup_arch_dsdt ( & mut dsdt_data) ?;
95
95
96
96
let mut dsdt = Dsdt :: new ( OEM_ID , * b"FCVMDSDT" , OEM_REVISION , dsdt_data) ;
97
- self . write_acpi_table ( & mut dsdt)
97
+ self . write_acpi_table ( & mut device_manager . resource_allocator , & mut dsdt)
98
98
}
99
99
100
100
/// Build the FADT table for the guest
101
101
///
102
102
/// This includes a pointer with the location of the DSDT in guest memory
103
- fn build_fadt ( & mut self , dsdt_addr : u64 ) -> Result < u64 , AcpiError > {
103
+ fn build_fadt (
104
+ & mut self ,
105
+ resource_allocator : & mut ResourceAllocator ,
106
+ dsdt_addr : u64 ,
107
+ ) -> Result < u64 , AcpiError > {
104
108
let mut fadt = Fadt :: new ( OEM_ID , * b"FCVMFADT" , OEM_REVISION ) ;
105
109
fadt. set_hypervisor_vendor_id ( HYPERVISOR_VENDOR_ID ) ;
106
110
fadt. set_x_dsdt ( dsdt_addr) ;
107
111
fadt. set_flags (
108
112
( 1 << FADT_F_HW_REDUCED_ACPI ) | ( 1 << FADT_F_PWR_BUTTON ) | ( 1 << FADT_F_SLP_BUTTON ) ,
109
113
) ;
110
114
setup_arch_fadt ( & mut fadt) ;
111
- self . write_acpi_table ( & mut fadt)
115
+ self . write_acpi_table ( resource_allocator , & mut fadt)
112
116
}
113
117
114
118
/// Build the MADT table for the guest
115
119
///
116
120
/// This includes information about the interrupt controllers supported in the platform
117
- fn build_madt ( & mut self , nr_vcpus : u8 ) -> Result < u64 , AcpiError > {
121
+ fn build_madt (
122
+ & mut self ,
123
+ resource_allocator : & mut ResourceAllocator ,
124
+ nr_vcpus : u8 ,
125
+ ) -> Result < u64 , AcpiError > {
118
126
let mut madt = Madt :: new (
119
127
OEM_ID ,
120
128
* b"FCVMMADT" ,
121
129
OEM_REVISION ,
122
130
apic_addr ( ) ,
123
131
setup_interrupt_controllers ( nr_vcpus) ,
124
132
) ;
125
- self . write_acpi_table ( & mut madt)
133
+ self . write_acpi_table ( resource_allocator , & mut madt)
126
134
}
127
135
128
136
/// Build the XSDT table for the guest
129
137
///
130
138
/// Currently, we pass to the guest just FADT and MADT tables.
131
- fn build_xsdt ( & mut self , fadt_addr : u64 , madt_addr : u64 ) -> Result < u64 , AcpiError > {
139
+ fn build_xsdt (
140
+ & mut self ,
141
+ resource_allocator : & mut ResourceAllocator ,
142
+ fadt_addr : u64 ,
143
+ madt_addr : u64 ,
144
+ ) -> Result < u64 , AcpiError > {
132
145
let mut xsdt = Xsdt :: new (
133
146
OEM_ID ,
134
147
* b"FCMVXSDT" ,
135
148
OEM_REVISION ,
136
149
vec ! [ fadt_addr, madt_addr] ,
137
150
) ;
138
- self . write_acpi_table ( & mut xsdt)
151
+ self . write_acpi_table ( resource_allocator , & mut xsdt)
139
152
}
140
153
141
154
/// Build the RSDP pointer for the guest.
@@ -163,20 +176,19 @@ impl AcpiTableWriter<'_> {
163
176
/// such as interrupt controllers, vCPUs and VirtIO devices.
164
177
pub ( crate ) fn create_acpi_tables (
165
178
mem : & GuestMemoryMmap ,
166
- resource_allocator : & mut ResourceAllocator ,
167
- mmio_device_manager : & MMIODeviceManager ,
168
- acpi_device_manager : & ACPIDeviceManager ,
179
+ device_manager : & mut DeviceManager ,
169
180
vcpus : & [ Vcpu ] ,
170
181
) -> Result < ( ) , AcpiError > {
171
- let mut writer = AcpiTableWriter {
172
- mem,
173
- resource_allocator,
174
- } ;
175
-
176
- let dsdt_addr = writer. build_dsdt ( mmio_device_manager, acpi_device_manager) ?;
177
- let fadt_addr = writer. build_fadt ( dsdt_addr) ?;
178
- let madt_addr = writer. build_madt ( vcpus. len ( ) . try_into ( ) . unwrap ( ) ) ?;
179
- let xsdt_addr = writer. build_xsdt ( fadt_addr, madt_addr) ?;
182
+ let mut writer = AcpiTableWriter { mem } ;
183
+
184
+ let dsdt_addr = writer. build_dsdt ( device_manager) ?;
185
+ let fadt_addr = writer. build_fadt ( & mut device_manager. resource_allocator , dsdt_addr) ?;
186
+ let madt_addr = writer. build_madt (
187
+ & mut device_manager. resource_allocator ,
188
+ vcpus. len ( ) . try_into ( ) . unwrap ( ) ,
189
+ ) ?;
190
+ let xsdt_addr =
191
+ writer. build_xsdt ( & mut device_manager. resource_allocator , fadt_addr, madt_addr) ?;
180
192
writer. build_rsdp ( xsdt_addr)
181
193
}
182
194
@@ -218,17 +230,20 @@ mod tests {
218
230
let mut vmm = default_vmm ( ) ;
219
231
let mut writer = AcpiTableWriter {
220
232
mem : vmm. vm . guest_memory ( ) ,
221
- resource_allocator : & mut vmm. resource_allocator ,
222
233
} ;
223
234
224
235
// This should succeed
225
236
let mut sdt = MockSdt ( vec ! [ 0 ; 4096 ] ) ;
226
- let addr = writer. write_acpi_table ( & mut sdt) . unwrap ( ) ;
237
+ let addr = writer
238
+ . write_acpi_table ( & mut vmm. device_manager . resource_allocator , & mut sdt)
239
+ . unwrap ( ) ;
227
240
assert_eq ! ( addr, SYSTEM_MEM_START ) ;
228
241
229
242
// Let's try to write two 4K pages plus one byte
230
243
let mut sdt = MockSdt ( vec ! [ 0 ; usize :: try_from( SYSTEM_MEM_SIZE + 1 ) . unwrap( ) ] ) ;
231
- let err = writer. write_acpi_table ( & mut sdt) . unwrap_err ( ) ;
244
+ let err = writer
245
+ . write_acpi_table ( & mut vmm. device_manager . resource_allocator , & mut sdt)
246
+ . unwrap_err ( ) ;
232
247
assert ! (
233
248
matches!(
234
249
err,
@@ -241,19 +256,29 @@ mod tests {
241
256
// We are allocating memory for tables with alignment of 1 byte. All of these should
242
257
// succeed.
243
258
let mut sdt = MockSdt ( vec ! [ 0 ; 5 ] ) ;
244
- let addr = writer. write_acpi_table ( & mut sdt) . unwrap ( ) ;
259
+ let addr = writer
260
+ . write_acpi_table ( & mut vmm. device_manager . resource_allocator , & mut sdt)
261
+ . unwrap ( ) ;
245
262
assert_eq ! ( addr, SYSTEM_MEM_START + 4096 ) ;
246
263
let mut sdt = MockSdt ( vec ! [ 0 ; 2 ] ) ;
247
- let addr = writer. write_acpi_table ( & mut sdt) . unwrap ( ) ;
264
+ let addr = writer
265
+ . write_acpi_table ( & mut vmm. device_manager . resource_allocator , & mut sdt)
266
+ . unwrap ( ) ;
248
267
assert_eq ! ( addr, SYSTEM_MEM_START + 4101 ) ;
249
268
let mut sdt = MockSdt ( vec ! [ 0 ; 4 ] ) ;
250
- let addr = writer. write_acpi_table ( & mut sdt) . unwrap ( ) ;
269
+ let addr = writer
270
+ . write_acpi_table ( & mut vmm. device_manager . resource_allocator , & mut sdt)
271
+ . unwrap ( ) ;
251
272
assert_eq ! ( addr, SYSTEM_MEM_START + 4103 ) ;
252
273
let mut sdt = MockSdt ( vec ! [ 0 ; 8 ] ) ;
253
- let addr = writer. write_acpi_table ( & mut sdt) . unwrap ( ) ;
274
+ let addr = writer
275
+ . write_acpi_table ( & mut vmm. device_manager . resource_allocator , & mut sdt)
276
+ . unwrap ( ) ;
254
277
assert_eq ! ( addr, SYSTEM_MEM_START + 4107 ) ;
255
278
let mut sdt = MockSdt ( vec ! [ 0 ; 16 ] ) ;
256
- let addr = writer. write_acpi_table ( & mut sdt) . unwrap ( ) ;
279
+ let addr = writer
280
+ . write_acpi_table ( & mut vmm. device_manager . resource_allocator , & mut sdt)
281
+ . unwrap ( ) ;
257
282
assert_eq ! ( addr, SYSTEM_MEM_START + 4115 ) ;
258
283
}
259
284
@@ -268,11 +293,13 @@ mod tests {
268
293
let ( _, vm) = setup_vm_with_memory ( u64_to_usize ( SYSTEM_MEM_START + SYSTEM_MEM_SIZE - 4096 ) ) ;
269
294
let mut writer = AcpiTableWriter {
270
295
mem : vm. guest_memory ( ) ,
271
- resource_allocator : & mut ResourceAllocator :: new ( ) . unwrap ( ) ,
272
296
} ;
297
+ let mut resource_allocator = ResourceAllocator :: new ( ) . unwrap ( ) ;
273
298
274
299
let mut sdt = MockSdt ( vec ! [ 0 ; usize :: try_from( SYSTEM_MEM_SIZE ) . unwrap( ) ] ) ;
275
- let err = writer. write_acpi_table ( & mut sdt) . unwrap_err ( ) ;
300
+ let err = writer
301
+ . write_acpi_table ( & mut resource_allocator, & mut sdt)
302
+ . unwrap_err ( ) ;
276
303
assert ! (
277
304
matches!(
278
305
err,
0 commit comments