@@ -372,7 +372,7 @@ impl Vmm {
372372 }
373373 #[ cfg( target_arch = "aarch64" ) ]
374374 {
375- let mpidrs = construct_gicr_typer ( & vcpu_states) ;
375+ let mpidrs = construct_kvm_mpidrs ( & vcpu_states) ;
376376
377377 self . vm . save_state ( & mpidrs) . map_err ( SaveVmState ) ?
378378 }
@@ -684,35 +684,29 @@ impl Vmm {
684684 }
685685}
686686
687+ /// Process the content of the MPIDR_EL1 register in order to be able to pass it to KVM
688+ ///
689+ /// The kernel expects to find the four affinity levels of the MPIDR in the first 32 bits of the
690+ /// VGIC register attribute:
691+ /// https://elixir.free-electrons.com/linux/v4.14.203/source/virt/kvm/arm/vgic/vgic-kvm-device.c#L445.
692+ ///
693+ /// The format of the MPIDR_EL1 register is:
694+ /// | 39 .... 32 | 31 .... 24 | 23 .... 16 | 15 .... 8 | 7 .... 0 |
695+ /// | Aff3 | Other | Aff2 | Aff1 | Aff0 |
696+ ///
697+ /// The KVM mpidr format is:
698+ /// | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
699+ /// | Aff3 | Aff2 | Aff1 | Aff0 |
700+ /// As specified in the linux kernel: Documentation/virt/kvm/devices/arm-vgic-v3.rst
687701#[ cfg( target_arch = "aarch64" ) ]
688- fn construct_gicr_typer ( vcpu_states : & [ VcpuState ] ) -> Vec < u64 > {
689- /* Pre-construct the GICR_TYPER:
690- * For our implementation:
691- * Top 32 bits are the affinity value of the associated CPU
692- * CommonLPIAff == 01 (redistributors with same Aff3 share LPI table)
693- * Processor_Number == CPU index starting from 0
694- * DPGS == 0 (GICR_CTLR.DPG* not supported)
695- * Last == 1 if this is the last redistributor in a series of
696- * contiguous redistributor pages
697- * DirectLPI == 0 (direct injection of LPIs not supported)
698- * VLPIS == 0 (virtual LPIs not supported)
699- * PLPIS == 0 (physical LPIs not supported)
700- */
701- let mut mpidrs: Vec < u64 > = Vec :: new ( ) ;
702- for ( index, state) in vcpu_states. iter ( ) . enumerate ( ) {
703- let last = {
704- if index == vcpu_states. len ( ) - 1 {
705- 1
706- } else {
707- 0
708- }
709- } ;
710- //calculate affinity
711- let mut cpu_affid = state. mpidr & 0xFF_00FF_FFFF ;
712- cpu_affid = ( ( cpu_affid & 0xFF_0000_0000 ) >> 8 ) | ( cpu_affid & 0xFF_FFFF ) ;
713- mpidrs. push ( ( cpu_affid << 32 ) | ( 1 << 24 ) | ( index as u64 ) << 8 | ( last << 4 ) ) ;
714- }
715- mpidrs
702+ fn construct_kvm_mpidrs ( vcpu_states : & [ VcpuState ] ) -> Vec < u64 > {
703+ vcpu_states
704+ . iter ( )
705+ . map ( |state| {
706+ let cpu_affid = ( ( state. mpidr & 0xFF_0000_0000 ) >> 8 ) | ( state. mpidr & 0xFF_FFFF ) ;
707+ cpu_affid << 32
708+ } )
709+ . collect ( )
716710}
717711
718712impl Drop for Vmm {
0 commit comments