@@ -6,11 +6,12 @@ use displaydoc::Display;
6
6
use kvm_bindings:: { KVM_ARM_VCPU_PVTIME_CTRL , KVM_ARM_VCPU_PVTIME_IPA } ;
7
7
use log:: { debug, info, warn} ;
8
8
use thiserror:: Error ;
9
+ use vm_memory:: GuestAddress ;
9
10
10
11
use crate :: device_manager:: resources:: ResourceAllocator ;
11
12
12
- /// Size of the stolen_time struct in bytes, see 3.2.2 in DEN0057A
13
- pub const STEALTIME_STRUCT_MEM_SIZE : u64 = 16 ;
13
+ /// 64 bytes due to alignment requirement in 3.1 of https://www.kernel.org/doc/html/v5.8/virt/kvm/devices/vcpu.html#attribute-kvm-arm-vcpu-pvtime-ipa
14
+ pub const STEALTIME_STRUCT_MEM_SIZE : u64 = 64 ;
14
15
15
16
/// Represent PVTime device for ARM
16
17
#[ derive( Debug ) ]
@@ -36,27 +37,21 @@ impl PVTime {
36
37
resource_allocator : & mut ResourceAllocator ,
37
38
vcpu_count : u8 ,
38
39
) -> Result < Self , PVTimeError > {
39
- info ! ( "Creating PVTime for {vcpu_count} vCPUs..." ) ;
40
- // This returns the IPA(?) of the start of our shared memory region for all vCPUs.
41
- // Q: Confirm that allocate_system_memory returns an IPA?
42
- let base_addr = resource_allocator
40
+
41
+ // This returns the IPA of the start of our shared memory region for all vCPUs.
42
+ let base_addr: GuestAddress = GuestAddress ( resource_allocator
43
43
. allocate_system_memory (
44
44
STEALTIME_STRUCT_MEM_SIZE * vcpu_count as u64 ,
45
- 16 , // Q: We believe this to be 16, need confirmation.
45
+ 64 ,
46
46
vm_allocator:: AllocPolicy :: LastMatch ,
47
47
)
48
- . map_err ( |e| PVTimeError :: AllocationFailed ( e. to_string ( ) ) ) ?;
48
+ . map_err ( |e| PVTimeError :: AllocationFailed ( e. to_string ( ) ) ) ?) ;
49
49
50
- debug ! (
51
- "Allocated base address for PVTime stolen_time region: 0x{:x}" ,
52
- base_addr
53
- ) ;
54
50
55
51
// Now we need to store the base IPA for each vCPU's steal_time struct.
56
52
let mut steal_time_regions = HashMap :: new ( ) ;
57
53
for i in 0 ..vcpu_count {
58
- let ipa = base_addr + ( i as u64 * STEALTIME_STRUCT_MEM_SIZE ) ;
59
- debug ! ( "Assigned vCPU {} to stolen_time IPA 0x{:x}" , i, ipa) ;
54
+ let ipa = base_addr. 0 + ( i as u64 * STEALTIME_STRUCT_MEM_SIZE ) ;
60
55
steal_time_regions. insert ( i, ipa) ;
61
56
}
62
57
@@ -70,40 +65,22 @@ impl PVTime {
70
65
vcpu_index : u8 ,
71
66
vcpu_fd : & kvm_ioctls:: VcpuFd ,
72
67
) -> Result < ( ) , PVTimeError > {
68
+
73
69
// Get IPA of the steal_time region for this vCPU
74
70
let ipa = self
75
71
. steal_time_regions
76
72
. get ( & vcpu_index)
77
73
. ok_or ( PVTimeError :: InvalidVcpuIndex ( vcpu_index) ) ?;
78
74
79
- debug ! (
80
- "Registering vCPU {} with stolen_time IPA = 0x{:x}" ,
81
- vcpu_index, ipa
82
- ) ;
83
-
84
- // IMPORTANT QUESTION: We need to confirm this is safe. We need to somehow
85
- // ensure the ipa value is not dropped before we use it etc. since we
86
- // are creating a raw pointer? Do we need a Box?
87
- let ipa_val = * ipa;
88
- let ipa_ptr = & ipa_val as * const u64 ;
89
- debug ! (
90
- "Registering vCPU {} with stolen_time IPA = 0x{:x} (at userspace addr 0x{:x})" ,
91
- vcpu_index, ipa_val, ipa_ptr as u64
92
- ) ;
93
-
94
75
// Use KVM syscall (kvm_set_device_attr) to register the vCPU with the steal_time region
95
76
let vcpu_device_attr = kvm_bindings:: kvm_device_attr {
96
77
group : KVM_ARM_VCPU_PVTIME_CTRL ,
97
78
attr : KVM_ARM_VCPU_PVTIME_IPA as u64 ,
98
- addr : ipa_ptr as u64 , // userspace address of attr data
79
+ addr : ipa as * const u64 as u64 , // userspace address of attr data
99
80
flags : 0 ,
100
81
} ;
101
82
102
83
vcpu_fd. set_device_attr ( & vcpu_device_attr) . map_err ( |err| {
103
- warn ! (
104
- "Failed to set device attribute for vCPU {}: {:?}" ,
105
- vcpu_index, err
106
- ) ;
107
84
PVTimeError :: DeviceAttribute ( err, true , KVM_ARM_VCPU_PVTIME_CTRL )
108
85
} ) ?;
109
86
0 commit comments