@@ -185,6 +185,7 @@ static void enable_vf(struct pci_vdev *pf_vdev)
185
185
sub_vid = (uint16_t ) pci_pdev_read_cfg (vf_bdf , PCIV_SUB_VENDOR_ID , 2U );
186
186
if ((sub_vid != 0xFFFFU ) && (sub_vid != 0U )) {
187
187
uint16_t num_vfs , stride , fst_off ;
188
+ struct pci_vdev * vf_vdev ;
188
189
189
190
num_vfs = read_sriov_reg (pf_vdev , PCIR_SRIOV_NUMVFS );
190
191
fst_off = read_sriov_reg (pf_vdev , PCIR_SRIOV_FST_VF_OFF );
@@ -193,9 +194,20 @@ static void enable_vf(struct pci_vdev *pf_vdev)
193
194
vf_bdf .fields .bus = get_vf_bus (pf_vdev , fst_off , stride , idx );
194
195
vf_bdf .fields .devfun = get_vf_devfun (pf_vdev , fst_off , stride , idx );
195
196
196
- /* if one VF has never been created then create new pdev/vdev for this VF */
197
- if (pci_find_vdev (& pf_vdev -> vpci -> vm -> vpci , vf_bdf ) == NULL ) {
197
+ /*
198
+ * If one VF has never been created then create new one including pdev/vdev structures.
199
+ *
200
+ * The VF maybe have already existed but it is a zombie instance that vf_vdev->vpci
201
+ * is NULL, in this case, we need to make the vf_vdev available again in here.
202
+ */
203
+ vf_vdev = pci_find_vdev (& pf_vdev -> vpci -> vm -> vpci , vf_bdf );
204
+ if (vf_vdev == NULL ) {
198
205
create_vf (pf_vdev , vf_bdf , idx );
206
+ } else {
207
+ /* Re-activate a zombie VF */
208
+ if (vf_vdev -> vpci == NULL ) {
209
+ vf_vdev -> vpci = pf_vdev -> vpci ;
210
+ }
199
211
}
200
212
}
201
213
} else {
@@ -213,8 +225,34 @@ static void enable_vf(struct pci_vdev *pf_vdev)
213
225
*/
214
226
static void disable_vf (struct pci_vdev * pf_vdev )
215
227
{
216
- /* Implementation in next patch */
217
- (void )pf_vdev ;
228
+ uint16_t idx , num_vfs , stride , first ;
229
+ struct pci_vdev * vf_vdev ;
230
+
231
+ /*
232
+ * PF can disable VFs only when all VFs are not used by any VM or any application
233
+ *
234
+ * Ideally, VF instances should be deleted after VFs are disabled, but for FuSa reasons,
235
+ * we simply set the VF instance status to "zombie" to avoid dynamically adding/removing
236
+ * resources
237
+ *
238
+ * If the VF drivers are still running in SOS or UOS, the MMIO access will return 0xFF.
239
+ *
240
+ * TODO For security reasons, we need to enforce a return of 0xFF to avoid information leakage.
241
+ */
242
+ num_vfs = read_sriov_reg (pf_vdev , PCIR_SRIOV_NUMVFS );
243
+ first = read_sriov_reg (pf_vdev , PCIR_SRIOV_FST_VF_OFF );
244
+ stride = read_sriov_reg (pf_vdev , PCIR_SRIOV_VF_STRIDE );
245
+ for (idx = 0U ; idx < num_vfs ; idx ++ ) {
246
+ union pci_bdf bdf ;
247
+
248
+ bdf .fields .bus = get_vf_bus (pf_vdev , first , stride , idx );
249
+ bdf .fields .devfun = get_vf_devfun (pf_vdev , first , stride , idx );
250
+ vf_vdev = pci_find_vdev (& pf_vdev -> vpci -> vm -> vpci , bdf );
251
+ if (vf_vdev != NULL ) {
252
+ /* set disabled VF as zombie vdev instance */
253
+ vf_vdev -> vpci = NULL ;
254
+ }
255
+ }
218
256
}
219
257
220
258
/**
0 commit comments