Skip to content

Commit f232836

Browse files
brettcreeleyawilliam
authored andcommitted
vfio/pds: Add support for dirty page tracking
In order to support dirty page tracking, the driver has to implement the VFIO subsystem's vfio_log_ops. This includes log_start, log_stop, and log_read_and_clear. All of the tracker resources are allocated and dirty tracking on the device is started during log_start. The resources are cleaned up and dirty tracking on the device is stopped during log_stop. The dirty pages are determined and reported during log_read_and_clear. In order to support these callbacks admin queue commands are used. All of the adminq queue command structures and implementations are included as part of this patch. PDS_LM_CMD_DIRTY_STATUS is added to query the current status of dirty tracking on the device. This includes if it's enabled (i.e. number of regions being tracked from the device's perspective) and the maximum number of regions supported from the device's perspective. PDS_LM_CMD_DIRTY_ENABLE is added to enable dirty tracking on the specified number of regions and their iova ranges. PDS_LM_CMD_DIRTY_DISABLE is added to disable dirty tracking for all regions on the device. PDS_LM_CMD_READ_SEQ and PDS_LM_CMD_DIRTY_WRITE_ACK are added to support reading and acknowledging the currently dirtied pages. Signed-off-by: Brett Creeley <[email protected]> Signed-off-by: Shannon Nelson <[email protected]> Reviewed-by: Simon Horman <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Reviewed-by: Shameer Kolothum <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alex Williamson <[email protected]>
1 parent bb500db commit f232836

File tree

9 files changed

+932
-2
lines changed

9 files changed

+932
-2
lines changed

drivers/vfio/pci/pds/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ obj-$(CONFIG_PDS_VFIO_PCI) += pds-vfio-pci.o
55

66
pds-vfio-pci-y := \
77
cmds.o \
8+
dirty.o \
89
lm.o \
910
pci_drv.o \
1011
vfio_dev.o

drivers/vfio/pci/pds/cmds.c

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,3 +382,128 @@ void pds_vfio_send_host_vf_lm_status_cmd(struct pds_vfio_pci_device *pds_vfio,
382382
dev_warn(dev, "failed to send host VF migration status: %pe\n",
383383
ERR_PTR(err));
384384
}
385+
386+
int pds_vfio_dirty_status_cmd(struct pds_vfio_pci_device *pds_vfio,
387+
u64 regions_dma, u8 *max_regions, u8 *num_regions)
388+
{
389+
union pds_core_adminq_cmd cmd = {
390+
.lm_dirty_status = {
391+
.opcode = PDS_LM_CMD_DIRTY_STATUS,
392+
.vf_id = cpu_to_le16(pds_vfio->vf_id),
393+
},
394+
};
395+
struct device *dev = pds_vfio_to_dev(pds_vfio);
396+
union pds_core_adminq_comp comp = {};
397+
int err;
398+
399+
dev_dbg(dev, "vf%u: Dirty status\n", pds_vfio->vf_id);
400+
401+
cmd.lm_dirty_status.regions_dma = cpu_to_le64(regions_dma);
402+
cmd.lm_dirty_status.max_regions = *max_regions;
403+
404+
err = pds_vfio_client_adminq_cmd(pds_vfio, &cmd, &comp, false);
405+
if (err) {
406+
dev_err(dev, "failed to get dirty status: %pe\n", ERR_PTR(err));
407+
return err;
408+
}
409+
410+
/* only support seq_ack approach for now */
411+
if (!(le32_to_cpu(comp.lm_dirty_status.bmp_type_mask) &
412+
BIT(PDS_LM_DIRTY_BMP_TYPE_SEQ_ACK))) {
413+
dev_err(dev, "Dirty bitmap tracking SEQ_ACK not supported\n");
414+
return -EOPNOTSUPP;
415+
}
416+
417+
*num_regions = comp.lm_dirty_status.num_regions;
418+
*max_regions = comp.lm_dirty_status.max_regions;
419+
420+
dev_dbg(dev,
421+
"Page Tracking Status command successful, max_regions: %d, num_regions: %d, bmp_type: %s\n",
422+
*max_regions, *num_regions, "PDS_LM_DIRTY_BMP_TYPE_SEQ_ACK");
423+
424+
return 0;
425+
}
426+
427+
int pds_vfio_dirty_enable_cmd(struct pds_vfio_pci_device *pds_vfio,
428+
u64 regions_dma, u8 num_regions)
429+
{
430+
union pds_core_adminq_cmd cmd = {
431+
.lm_dirty_enable = {
432+
.opcode = PDS_LM_CMD_DIRTY_ENABLE,
433+
.vf_id = cpu_to_le16(pds_vfio->vf_id),
434+
.regions_dma = cpu_to_le64(regions_dma),
435+
.bmp_type = PDS_LM_DIRTY_BMP_TYPE_SEQ_ACK,
436+
.num_regions = num_regions,
437+
},
438+
};
439+
struct device *dev = pds_vfio_to_dev(pds_vfio);
440+
union pds_core_adminq_comp comp = {};
441+
int err;
442+
443+
err = pds_vfio_client_adminq_cmd(pds_vfio, &cmd, &comp, false);
444+
if (err) {
445+
dev_err(dev, "failed dirty tracking enable: %pe\n",
446+
ERR_PTR(err));
447+
return err;
448+
}
449+
450+
return 0;
451+
}
452+
453+
int pds_vfio_dirty_disable_cmd(struct pds_vfio_pci_device *pds_vfio)
454+
{
455+
union pds_core_adminq_cmd cmd = {
456+
.lm_dirty_disable = {
457+
.opcode = PDS_LM_CMD_DIRTY_DISABLE,
458+
.vf_id = cpu_to_le16(pds_vfio->vf_id),
459+
},
460+
};
461+
struct device *dev = pds_vfio_to_dev(pds_vfio);
462+
union pds_core_adminq_comp comp = {};
463+
int err;
464+
465+
err = pds_vfio_client_adminq_cmd(pds_vfio, &cmd, &comp, false);
466+
if (err || comp.lm_dirty_status.num_regions != 0) {
467+
/* in case num_regions is still non-zero after disable */
468+
err = err ? err : -EIO;
469+
dev_err(dev,
470+
"failed dirty tracking disable: %pe, num_regions %d\n",
471+
ERR_PTR(err), comp.lm_dirty_status.num_regions);
472+
return err;
473+
}
474+
475+
return 0;
476+
}
477+
478+
int pds_vfio_dirty_seq_ack_cmd(struct pds_vfio_pci_device *pds_vfio,
479+
u64 sgl_dma, u16 num_sge, u32 offset,
480+
u32 total_len, bool read_seq)
481+
{
482+
const char *cmd_type_str = read_seq ? "read_seq" : "write_ack";
483+
union pds_core_adminq_cmd cmd = {
484+
.lm_dirty_seq_ack = {
485+
.vf_id = cpu_to_le16(pds_vfio->vf_id),
486+
.len_bytes = cpu_to_le32(total_len),
487+
.off_bytes = cpu_to_le32(offset),
488+
.sgl_addr = cpu_to_le64(sgl_dma),
489+
.num_sge = cpu_to_le16(num_sge),
490+
},
491+
};
492+
struct device *dev = pds_vfio_to_dev(pds_vfio);
493+
union pds_core_adminq_comp comp = {};
494+
int err;
495+
496+
if (read_seq)
497+
cmd.lm_dirty_seq_ack.opcode = PDS_LM_CMD_DIRTY_READ_SEQ;
498+
else
499+
cmd.lm_dirty_seq_ack.opcode = PDS_LM_CMD_DIRTY_WRITE_ACK;
500+
501+
err = pds_vfio_client_adminq_cmd(pds_vfio, &cmd, &comp, false);
502+
if (err) {
503+
dev_err(dev, "failed cmd Page Tracking %s: %pe\n", cmd_type_str,
504+
ERR_PTR(err));
505+
return err;
506+
}
507+
508+
return 0;
509+
}

drivers/vfio/pci/pds/cmds.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,13 @@ int pds_vfio_get_lm_state_cmd(struct pds_vfio_pci_device *pds_vfio);
1313
int pds_vfio_set_lm_state_cmd(struct pds_vfio_pci_device *pds_vfio);
1414
void pds_vfio_send_host_vf_lm_status_cmd(struct pds_vfio_pci_device *pds_vfio,
1515
enum pds_lm_host_vf_status vf_status);
16+
int pds_vfio_dirty_status_cmd(struct pds_vfio_pci_device *pds_vfio,
17+
u64 regions_dma, u8 *max_regions,
18+
u8 *num_regions);
19+
int pds_vfio_dirty_enable_cmd(struct pds_vfio_pci_device *pds_vfio,
20+
u64 regions_dma, u8 num_regions);
21+
int pds_vfio_dirty_disable_cmd(struct pds_vfio_pci_device *pds_vfio);
22+
int pds_vfio_dirty_seq_ack_cmd(struct pds_vfio_pci_device *pds_vfio,
23+
u64 sgl_dma, u16 num_sge, u32 offset,
24+
u32 total_len, bool read_seq);
1625
#endif /* _CMDS_H_ */

0 commit comments

Comments
 (0)