• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use hypervisor::kvm::get_cpuid_with_initial_capacity;
6 use hypervisor::kvm::Kvm;
7 use hypervisor::kvm::KvmVcpu;
8 use hypervisor::kvm::KvmVm;
9 use hypervisor::DeliveryMode;
10 use hypervisor::DeliveryStatus;
11 use hypervisor::DestinationMode;
12 use hypervisor::Fpu;
13 use hypervisor::Hypervisor;
14 use hypervisor::HypervisorCap;
15 use hypervisor::HypervisorX86_64;
16 use hypervisor::IoapicRedirectionTableEntry;
17 use hypervisor::IoapicState;
18 use hypervisor::IrqRoute;
19 use hypervisor::IrqSource;
20 use hypervisor::IrqSourceChip;
21 use hypervisor::LapicState;
22 use hypervisor::PicInitState;
23 use hypervisor::PicState;
24 use hypervisor::PitChannelState;
25 use hypervisor::PitRWMode;
26 use hypervisor::PitRWState;
27 use hypervisor::PitState;
28 use hypervisor::TriggerMode;
29 use hypervisor::Vm;
30 use hypervisor::VmCap;
31 use hypervisor::VmX86_64;
32 use kvm_sys::*;
33 use libc::EINVAL;
34 use vm_memory::GuestAddress;
35 use vm_memory::GuestMemory;
36 
37 #[test]
get_supported_cpuid()38 fn get_supported_cpuid() {
39     let hypervisor = Kvm::new().unwrap();
40     let cpuid = hypervisor.get_supported_cpuid().unwrap();
41     assert!(!cpuid.cpu_id_entries.is_empty());
42 }
43 
44 #[test]
get_emulated_cpuid()45 fn get_emulated_cpuid() {
46     let hypervisor = Kvm::new().unwrap();
47     let cpuid = hypervisor.get_emulated_cpuid().unwrap();
48     assert!(!cpuid.cpu_id_entries.is_empty());
49 }
50 
51 #[test]
get_msr_index_list()52 fn get_msr_index_list() {
53     let kvm = Kvm::new().unwrap();
54     let msr_list = kvm.get_msr_index_list().unwrap();
55     assert!(msr_list.len() >= 2);
56 }
57 
58 #[test]
entries_double_on_error()59 fn entries_double_on_error() {
60     let hypervisor = Kvm::new().unwrap();
61     let cpuid = get_cpuid_with_initial_capacity(&hypervisor, KVM_GET_SUPPORTED_CPUID(), 4).unwrap();
62     assert!(cpuid.cpu_id_entries.len() > 4);
63 }
64 
65 #[test]
check_vm_arch_capability()66 fn check_vm_arch_capability() {
67     let kvm = Kvm::new().unwrap();
68     let gm = GuestMemory::new(&[(GuestAddress(0), 0x1000)]).unwrap();
69     let vm = KvmVm::new(&kvm, gm, Default::default()).unwrap();
70     assert!(vm.check_capability(VmCap::PvClock));
71 }
72 
73 #[test]
pic_state()74 fn pic_state() {
75     let state = PicState {
76         last_irr: 0b00000001,
77         irr: 0b00000010,
78         imr: 0b00000100,
79         isr: 0b00001000,
80         priority_add: 0b00010000,
81         irq_base: 0b00100000,
82         read_reg_select: false,
83         poll: true,
84         special_mask: true,
85         init_state: PicInitState::Icw3,
86         auto_eoi: true,
87         rotate_on_auto_eoi: false,
88         special_fully_nested_mode: true,
89         use_4_byte_icw: true,
90         elcr: 0b01000000,
91         elcr_mask: 0b10000000,
92     };
93 
94     let kvm_state = kvm_pic_state::from(&state);
95 
96     assert_eq!(kvm_state.last_irr, 0b00000001);
97     assert_eq!(kvm_state.irr, 0b00000010);
98     assert_eq!(kvm_state.imr, 0b00000100);
99     assert_eq!(kvm_state.isr, 0b00001000);
100     assert_eq!(kvm_state.priority_add, 0b00010000);
101     assert_eq!(kvm_state.irq_base, 0b00100000);
102     assert_eq!(kvm_state.read_reg_select, 0);
103     assert_eq!(kvm_state.poll, 1);
104     assert_eq!(kvm_state.special_mask, 1);
105     assert_eq!(kvm_state.init_state, 0b10);
106     assert_eq!(kvm_state.auto_eoi, 1);
107     assert_eq!(kvm_state.rotate_on_auto_eoi, 0);
108     assert_eq!(kvm_state.special_fully_nested_mode, 1);
109     assert_eq!(kvm_state.auto_eoi, 1);
110     assert_eq!(kvm_state.elcr, 0b01000000);
111     assert_eq!(kvm_state.elcr_mask, 0b10000000);
112 
113     let orig_state = PicState::from(&kvm_state);
114     assert_eq!(state, orig_state);
115 }
116 
117 #[test]
ioapic_state()118 fn ioapic_state() {
119     let mut entry = IoapicRedirectionTableEntry::default();
120     let noredir = IoapicRedirectionTableEntry::default();
121 
122     // default entry should be 0
123     assert_eq!(entry.get(0, 64), 0);
124 
125     // set some values on our entry
126     entry.set_vector(0b11111111);
127     entry.set_delivery_mode(DeliveryMode::SMI);
128     entry.set_dest_mode(DestinationMode::Physical);
129     entry.set_delivery_status(DeliveryStatus::Pending);
130     entry.set_polarity(1);
131     entry.set_remote_irr(true);
132     entry.set_trigger_mode(TriggerMode::Level);
133     entry.set_interrupt_mask(true);
134     entry.set_dest_id(0b10101010);
135 
136     // Bit repr as:  destid-reserved--------------------------------flags----vector--
137     let bit_repr = 0b1010101000000000000000000000000000000000000000011111001011111111;
138     // where flags is [interrupt_mask(1), trigger_mode(Level=1), remote_irr(1), polarity(1),
139     //   delivery_status(Pending=1), dest_mode(Physical=0), delivery_mode(SMI=010)]
140 
141     assert_eq!(entry.get(0, 64), bit_repr);
142 
143     let mut state = IoapicState {
144         base_address: 1,
145         ioregsel: 2,
146         ioapicid: 4,
147         current_interrupt_level_bitmap: 8,
148         redirect_table: [noredir; 24],
149     };
150 
151     // Initialize first 24 (kvm_state limit) redirection entries
152     for i in 0..24 {
153         state.redirect_table[i] = entry;
154     }
155 
156     let kvm_state = kvm_ioapic_state::from(&state);
157     assert_eq!(kvm_state.base_address, 1);
158     assert_eq!(kvm_state.ioregsel, 2);
159     assert_eq!(kvm_state.id, 4);
160     assert_eq!(kvm_state.irr, 8);
161     assert_eq!(kvm_state.pad, 0);
162     // check first 24 entries
163     for i in 0..24 {
164         assert_eq!(
165             {
166                 // SAFETY: trivially safe
167                 unsafe { kvm_state.redirtbl[i].bits }
168             },
169             bit_repr
170         );
171     }
172 
173     // compare with a conversion back
174     assert_eq!(state, IoapicState::from(&kvm_state));
175 }
176 
177 #[test]
lapic_state()178 fn lapic_state() {
179     let mut state = LapicState { regs: [0; 64] };
180     // Apic id register, 4 bytes each with a different bit set
181     state.regs[2] = 1 | 2 << 8 | 4 << 16 | 8 << 24;
182 
183     let kvm_state = kvm_lapic_state::from(&state);
184 
185     // check little endian bytes in kvm_state
186     for i in 0..4 {
187         assert_eq!(kvm_state.regs[32 + i] as u8, 2u8.pow(i as u32));
188     }
189 
190     // Test converting back to a LapicState
191     assert_eq!(state, LapicState::from(&kvm_state));
192 }
193 
194 #[test]
pit_state()195 fn pit_state() {
196     let channel = PitChannelState {
197         count: 256,
198         latched_count: 512,
199         count_latched: PitRWState::LSB,
200         status_latched: false,
201         status: 7,
202         read_state: PitRWState::MSB,
203         write_state: PitRWState::Word1,
204         reload_value: 8,
205         rw_mode: PitRWMode::Both,
206         mode: 5,
207         bcd: false,
208         gate: true,
209         count_load_time: 1024,
210     };
211 
212     let kvm_channel = kvm_pit_channel_state::from(&channel);
213 
214     // compare the various field translations
215     assert_eq!(kvm_channel.count, 256);
216     assert_eq!(kvm_channel.latched_count, 512);
217     assert_eq!(kvm_channel.count_latched, 1);
218     assert_eq!(kvm_channel.status_latched, 0);
219     assert_eq!(kvm_channel.status, 7);
220     assert_eq!(kvm_channel.read_state, 2);
221     assert_eq!(kvm_channel.write_state, 4);
222     assert_eq!(kvm_channel.write_latch, 8);
223     assert_eq!(kvm_channel.rw_mode, 3);
224     assert_eq!(kvm_channel.mode, 5);
225     assert_eq!(kvm_channel.bcd, 0);
226     assert_eq!(kvm_channel.gate, 1);
227     assert_eq!(kvm_channel.count_load_time, 1024);
228 
229     // convert back and compare
230     assert_eq!(channel, PitChannelState::from(&kvm_channel));
231 
232     // convert the full pitstate
233     let state = PitState {
234         channels: [channel, channel, channel],
235         flags: 255,
236     };
237     let kvm_state = kvm_pit_state2::from(&state);
238 
239     assert_eq!(kvm_state.flags, 255);
240 
241     // compare a channel
242     assert_eq!(channel, PitChannelState::from(&kvm_state.channels[0]));
243     // convert back and compare
244     assert_eq!(state, PitState::from(&kvm_state));
245 }
246 
247 #[test]
clock_handling()248 fn clock_handling() {
249     let kvm = Kvm::new().unwrap();
250     let gm = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
251     let vm = KvmVm::new(&kvm, gm, Default::default()).unwrap();
252     let mut clock_data = vm.get_pvclock().unwrap();
253     clock_data.clock += 1000;
254     vm.set_pvclock(&clock_data).unwrap();
255 }
256 
257 #[test]
set_gsi_routing()258 fn set_gsi_routing() {
259     let kvm = Kvm::new().unwrap();
260     let gm = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
261     let vm = KvmVm::new(&kvm, gm, Default::default()).unwrap();
262     vm.create_irq_chip().unwrap();
263     vm.set_gsi_routing(&[]).unwrap();
264     vm.set_gsi_routing(&[IrqRoute {
265         gsi: 1,
266         source: IrqSource::Irqchip {
267             chip: IrqSourceChip::Ioapic,
268             pin: 3,
269         },
270     }])
271     .unwrap();
272     vm.set_gsi_routing(&[IrqRoute {
273         gsi: 1,
274         source: IrqSource::Msi {
275             address: 0xf000000,
276             data: 0xa0,
277         },
278     }])
279     .unwrap();
280     vm.set_gsi_routing(&[
281         IrqRoute {
282             gsi: 1,
283             source: IrqSource::Irqchip {
284                 chip: IrqSourceChip::Ioapic,
285                 pin: 3,
286             },
287         },
288         IrqRoute {
289             gsi: 2,
290             source: IrqSource::Msi {
291                 address: 0xf000000,
292                 data: 0xa0,
293             },
294         },
295     ])
296     .unwrap();
297 }
298 
299 #[test]
set_identity_map_addr()300 fn set_identity_map_addr() {
301     let kvm = Kvm::new().unwrap();
302     let gm = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
303     let vm = KvmVm::new(&kvm, gm, Default::default()).unwrap();
304     vm.set_identity_map_addr(GuestAddress(0x20000)).unwrap();
305 }
306 
307 #[test]
mp_state()308 fn mp_state() {
309     let kvm = Kvm::new().unwrap();
310     let gm = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
311     let vm = KvmVm::new(&kvm, gm, Default::default()).unwrap();
312     vm.create_irq_chip().unwrap();
313     let vcpu: KvmVcpu = vm.create_kvm_vcpu(0).unwrap();
314     let state = vcpu.get_mp_state().unwrap();
315     vcpu.set_mp_state(&state).unwrap();
316 }
317 
318 #[test]
enable_feature()319 fn enable_feature() {
320     let kvm = Kvm::new().unwrap();
321     let gm = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
322     let vm = KvmVm::new(&kvm, gm, Default::default()).unwrap();
323     vm.create_irq_chip().unwrap();
324     let vcpu = vm.create_vcpu(0).unwrap();
325     // SAFETY: trivially safe
326     unsafe { vcpu.enable_raw_capability(kvm_sys::KVM_CAP_HYPERV_SYNIC, &[0; 4]) }.unwrap();
327 }
328 
329 #[test]
from_fpu()330 fn from_fpu() {
331     // Fpu has the largest arrays in our struct adapters.  Test that they're small enough for
332     // Rust to copy.
333     let mut fpu: Fpu = Default::default();
334     let m = fpu.xmm.len();
335     let n = fpu.xmm[0].len();
336     fpu.xmm[m - 1][n - 1] = 42;
337 
338     let fpu = kvm_fpu::from(&fpu);
339     assert_eq!(fpu.xmm.len(), m);
340     assert_eq!(fpu.xmm[0].len(), n);
341     assert_eq!(fpu.xmm[m - 1][n - 1], 42);
342 }
343 
344 #[test]
debugregs()345 fn debugregs() {
346     let kvm = Kvm::new().unwrap();
347     let gm = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
348     let vm = KvmVm::new(&kvm, gm, Default::default()).unwrap();
349     let vcpu = vm.create_vcpu(0).unwrap();
350     let mut dregs = vcpu.get_debugregs().unwrap();
351     dregs.dr7 = 13;
352     vcpu.set_debugregs(&dregs).unwrap();
353     let dregs2 = vcpu.get_debugregs().unwrap();
354     assert_eq!(dregs.dr7, dregs2.dr7);
355 }
356 
357 #[test]
xcrs()358 fn xcrs() {
359     let kvm = Kvm::new().unwrap();
360     if !kvm.check_capability(HypervisorCap::Xcrs) {
361         return;
362     }
363 
364     let gm = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
365     let vm = KvmVm::new(&kvm, gm, Default::default()).unwrap();
366     let vcpu = vm.create_vcpu(0).unwrap();
367     vcpu.set_xcr(0, 1).unwrap();
368     let xcrs = vcpu.get_xcrs().unwrap();
369     let xcr0 = xcrs.get(&0).unwrap();
370     assert_eq!(*xcr0, 1);
371 }
372 
373 #[test]
get_msr()374 fn get_msr() {
375     let kvm = Kvm::new().unwrap();
376     let gm = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
377     let vm = KvmVm::new(&kvm, gm, Default::default()).unwrap();
378     let vcpu = vm.create_vcpu(0).unwrap();
379 
380     // This one should succeed
381     let _value = vcpu.get_msr(0x0000011e).unwrap();
382 
383     // This one will fail to fetch
384     vcpu.get_msr(0xffffffff)
385         .expect_err("invalid MSR index should fail");
386 }
387 
388 #[test]
set_msr()389 fn set_msr() {
390     let kvm = Kvm::new().unwrap();
391     let gm = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
392     let vm = KvmVm::new(&kvm, gm, Default::default()).unwrap();
393     let vcpu = vm.create_vcpu(0).unwrap();
394 
395     const MSR_TSC_AUX: u32 = 0xc0000103;
396     vcpu.set_msr(MSR_TSC_AUX, 42).unwrap();
397     let msr_tsc_aux = vcpu.get_msr(MSR_TSC_AUX).unwrap();
398     assert_eq!(msr_tsc_aux, 42);
399 }
400 
401 #[test]
set_msr_unsupported()402 fn set_msr_unsupported() {
403     let kvm = Kvm::new().unwrap();
404     let gm = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
405     let vm = KvmVm::new(&kvm, gm, Default::default()).unwrap();
406     let vcpu = vm.create_vcpu(0).unwrap();
407 
408     assert_eq!(
409         vcpu.set_msr(u32::MAX, u64::MAX),
410         Err(base::Error::new(libc::EPERM))
411     );
412 }
413 
414 #[test]
get_hyperv_cpuid()415 fn get_hyperv_cpuid() {
416     let kvm = Kvm::new().unwrap();
417     let gm = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
418     let vm = KvmVm::new(&kvm, gm, Default::default()).unwrap();
419     let vcpu = vm.create_vcpu(0).unwrap();
420     let cpuid = vcpu.get_hyperv_cpuid();
421     // Older kernels don't support so tolerate this kind of failure.
422     match cpuid {
423         Ok(_) => {}
424         Err(e) => {
425             assert_eq!(e.errno(), EINVAL);
426         }
427     }
428 }
429