@@ -24,6 +24,7 @@ impl GICv3 {
24
24
const SZ_64K : u64 = 0x0001_0000 ;
25
25
const KVM_VGIC_V3_DIST_SIZE : u64 = GICv3 :: SZ_64K ;
26
26
const KVM_VGIC_V3_REDIST_SIZE : u64 = ( 2 * GICv3 :: SZ_64K ) ;
27
+ const GIC_V3_ITS_SIZE : u64 = 0x2_0000 ;
27
28
28
29
// Device trees specific constants
29
30
const ARCH_GIC_V3_MAINT_IRQ : u32 = 9 ;
@@ -48,6 +49,16 @@ impl GICv3 {
48
49
vcpu_count * GICv3 :: KVM_VGIC_V3_REDIST_SIZE
49
50
}
50
51
52
+ /// Get the MSI address
53
+ fn get_msi_address ( vcpu_count : u64 ) -> u64 {
54
+ Self :: get_redists_addr ( vcpu_count) - GICv3 :: GIC_V3_ITS_SIZE
55
+ }
56
+
57
+ /// Get the MSI size
58
+ const fn get_msi_size ( ) -> u64 {
59
+ GICv3 :: GIC_V3_ITS_SIZE
60
+ }
61
+
51
62
pub const VERSION : u32 = kvm_bindings:: kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3;
52
63
53
64
pub fn fdt_compatibility ( & self ) -> & str {
@@ -59,17 +70,41 @@ impl GICv3 {
59
70
}
60
71
61
72
/// Create the GIC device object
62
- pub fn create_device ( fd : DeviceFd , vcpu_count : u64 ) -> Self {
63
- GICv3 ( super :: GIC {
64
- fd,
73
+ pub fn create_device ( vm : & VmFd , vcpu_count : u64 ) -> Result < Self , GicError > {
74
+ // Create the GIC device
75
+ let mut gic_device = kvm_bindings:: kvm_create_device {
76
+ type_ : Self :: VERSION ,
77
+ fd : 0 ,
78
+ flags : 0 ,
79
+ } ;
80
+
81
+ let gic_fd = vm
82
+ . create_device ( & mut gic_device)
83
+ . map_err ( GicError :: CreateGIC ) ?;
84
+
85
+ // ITS part attributes
86
+ let mut its_device = kvm_bindings:: kvm_create_device {
87
+ type_ : kvm_bindings:: kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_ITS,
88
+ fd : 0 ,
89
+ flags : 0 ,
90
+ } ;
91
+
92
+ let its_fd = vm
93
+ . create_device ( & mut its_device)
94
+ . map_err ( GicError :: CreateGIC ) ?;
95
+
96
+ Ok ( GICv3 ( super :: GIC {
97
+ fd : gic_fd,
65
98
properties : [
66
99
GICv3 :: get_dist_addr ( ) ,
67
100
GICv3 :: get_dist_size ( ) ,
68
101
GICv3 :: get_redists_addr ( vcpu_count) ,
69
102
GICv3 :: get_redists_size ( vcpu_count) ,
70
103
] ,
104
+ msi_properties : Some ( [ GICv3 :: get_msi_address ( vcpu_count) , GICv3 :: get_msi_size ( ) ] ) ,
71
105
vcpu_count,
72
- } )
106
+ its_device : Some ( its_fd) ,
107
+ } ) )
73
108
}
74
109
75
110
pub fn save_device ( & self , mpidrs : & [ u64 ] ) -> Result < GicState , GicError > {
@@ -82,7 +117,7 @@ impl GICv3 {
82
117
83
118
pub fn init_device_attributes ( gic_device : & Self ) -> Result < ( ) , GicError > {
84
119
// Setting up the distributor attribute.
85
- // We are placing the GIC below 1GB so we need to substract the size of the distributor.
120
+ // We are placing the GIC below 1GB so we need to subtract the size of the distributor.
86
121
Self :: set_device_attribute (
87
122
gic_device. device_fd ( ) ,
88
123
kvm_bindings:: KVM_DEV_ARM_VGIC_GRP_ADDR ,
@@ -101,26 +136,29 @@ impl GICv3 {
101
136
0 ,
102
137
) ?;
103
138
104
- Ok ( ( ) )
105
- }
139
+ // Setting up the ITS attributes
140
+ Self :: set_device_attribute (
141
+ gic_device. its_device . as_ref ( ) . unwrap ( ) ,
142
+ kvm_bindings:: KVM_DEV_ARM_VGIC_GRP_ADDR ,
143
+ u64:: from ( kvm_bindings:: KVM_VGIC_ITS_ADDR_TYPE ) ,
144
+ Self :: get_msi_address ( gic_device. vcpu_count ( ) ) as * const u64 as u64 ,
145
+ 0 ,
146
+ ) ?;
106
147
107
- /// Initialize a GIC device
108
- pub fn init_device ( vm : & VmFd ) -> Result < DeviceFd , GicError > {
109
- let mut gic_device = kvm_bindings:: kvm_create_device {
110
- type_ : Self :: VERSION ,
111
- fd : 0 ,
112
- flags : 0 ,
113
- } ;
148
+ Self :: set_device_attribute (
149
+ gic_device . its_device . as_ref ( ) . unwrap ( ) ,
150
+ kvm_bindings:: KVM_DEV_ARM_VGIC_GRP_CTRL ,
151
+ u64 :: from ( kvm_bindings :: KVM_DEV_ARM_VGIC_CTRL_INIT ) ,
152
+ 0 ,
153
+ 0 ,
154
+ ) ? ;
114
155
115
- vm. create_device ( & mut gic_device)
116
- . map_err ( GicError :: CreateGIC )
156
+ Ok ( ( ) )
117
157
}
118
158
119
159
/// Method to initialize the GIC device
120
160
pub fn create ( vm : & VmFd , vcpu_count : u64 ) -> Result < Self , GicError > {
121
- let vgic_fd = Self :: init_device ( vm) ?;
122
-
123
- let device = Self :: create_device ( vgic_fd, vcpu_count) ;
161
+ let device = Self :: create_device ( vm, vcpu_count) ?;
124
162
125
163
Self :: init_device_attributes ( & device) ?;
126
164
0 commit comments