1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2023 Advanced Micro Devices, Inc. */
4 #include <linux/anon_inodes.h>
5 #include <linux/file.h>
7 #include <linux/highmem.h>
8 #include <linux/vfio.h>
9 #include <linux/vfio_pci_core.h>
14 static struct pds_vfio_lm_file
*
15 pds_vfio_get_lm_file(const struct file_operations
*fops
, int flags
, u64 size
)
17 struct pds_vfio_lm_file
*lm_file
= NULL
;
18 unsigned long long npages
;
26 /* Alloc file structure */
27 lm_file
= kzalloc(sizeof(*lm_file
), GFP_KERNEL
);
33 anon_inode_getfile("pds_vfio_lm", fops
, lm_file
, flags
);
34 if (IS_ERR(lm_file
->filep
))
37 stream_open(lm_file
->filep
->f_inode
, lm_file
->filep
);
38 mutex_init(&lm_file
->lock
);
40 /* prevent file from being released before we are done with it */
41 get_file(lm_file
->filep
);
43 /* Allocate memory for file pages */
44 npages
= DIV_ROUND_UP_ULL(size
, PAGE_SIZE
);
45 pages
= kmalloc_array(npages
, sizeof(*pages
), GFP_KERNEL
);
49 page_mem
= kvzalloc(ALIGN(size
, PAGE_SIZE
), GFP_KERNEL
);
51 goto out_free_pages_array
;
53 p
= page_mem
- offset_in_page(page_mem
);
54 for (unsigned long long i
= 0; i
< npages
; i
++) {
55 if (is_vmalloc_addr(p
))
56 pages
[i
] = vmalloc_to_page(p
);
58 pages
[i
] = kmap_to_page((void *)p
);
60 goto out_free_page_mem
;
65 /* Create scatterlist of file pages to use for DMA mapping later */
66 if (sg_alloc_table_from_pages(&lm_file
->sg_table
, pages
, npages
, 0,
68 goto out_free_page_mem
;
71 lm_file
->pages
= pages
;
72 lm_file
->npages
= npages
;
73 lm_file
->page_mem
= page_mem
;
74 lm_file
->alloc_size
= npages
* PAGE_SIZE
;
84 mutex_destroy(&lm_file
->lock
);
91 static void pds_vfio_put_lm_file(struct pds_vfio_lm_file
*lm_file
)
93 mutex_lock(&lm_file
->lock
);
95 lm_file
->disabled
= true;
97 lm_file
->alloc_size
= 0;
98 lm_file
->filep
->f_pos
= 0;
100 /* Free scatter list of file pages */
101 sg_free_table(&lm_file
->sg_table
);
103 kvfree(lm_file
->page_mem
);
104 lm_file
->page_mem
= NULL
;
105 kfree(lm_file
->pages
);
106 lm_file
->pages
= NULL
;
108 mutex_unlock(&lm_file
->lock
);
110 /* allow file to be released since we are done with it */
111 fput(lm_file
->filep
);
114 void pds_vfio_put_save_file(struct pds_vfio_pci_device
*pds_vfio
)
116 if (!pds_vfio
->save_file
)
119 pds_vfio_put_lm_file(pds_vfio
->save_file
);
120 pds_vfio
->save_file
= NULL
;
123 void pds_vfio_put_restore_file(struct pds_vfio_pci_device
*pds_vfio
)
125 if (!pds_vfio
->restore_file
)
128 pds_vfio_put_lm_file(pds_vfio
->restore_file
);
129 pds_vfio
->restore_file
= NULL
;
132 static struct page
*pds_vfio_get_file_page(struct pds_vfio_lm_file
*lm_file
,
133 unsigned long offset
)
135 unsigned long cur_offset
= 0;
136 struct scatterlist
*sg
;
139 /* All accesses are sequential */
140 if (offset
< lm_file
->last_offset
|| !lm_file
->last_offset_sg
) {
141 lm_file
->last_offset
= 0;
142 lm_file
->last_offset_sg
= lm_file
->sg_table
.sgl
;
143 lm_file
->sg_last_entry
= 0;
146 cur_offset
= lm_file
->last_offset
;
148 for_each_sg(lm_file
->last_offset_sg
, sg
,
149 lm_file
->sg_table
.orig_nents
- lm_file
->sg_last_entry
, i
) {
150 if (offset
< sg
->length
+ cur_offset
) {
151 lm_file
->last_offset_sg
= sg
;
152 lm_file
->sg_last_entry
+= i
;
153 lm_file
->last_offset
= cur_offset
;
154 return nth_page(sg_page(sg
),
155 (offset
- cur_offset
) / PAGE_SIZE
);
157 cur_offset
+= sg
->length
;
163 static int pds_vfio_release_file(struct inode
*inode
, struct file
*filp
)
165 struct pds_vfio_lm_file
*lm_file
= filp
->private_data
;
167 mutex_lock(&lm_file
->lock
);
168 lm_file
->filep
->f_pos
= 0;
170 mutex_unlock(&lm_file
->lock
);
171 mutex_destroy(&lm_file
->lock
);
177 static ssize_t
pds_vfio_save_read(struct file
*filp
, char __user
*buf
,
178 size_t len
, loff_t
*pos
)
180 struct pds_vfio_lm_file
*lm_file
= filp
->private_data
;
187 mutex_lock(&lm_file
->lock
);
189 if (lm_file
->disabled
) {
194 if (*pos
> lm_file
->size
) {
199 len
= min_t(size_t, lm_file
->size
- *pos
, len
);
207 page_offset
= (*pos
) % PAGE_SIZE
;
208 page
= pds_vfio_get_file_page(lm_file
, *pos
- page_offset
);
215 page_len
= min_t(size_t, len
, PAGE_SIZE
- page_offset
);
216 from_buff
= kmap_local_page(page
);
217 err
= copy_to_user(buf
, from_buff
+ page_offset
, page_len
);
218 kunmap_local(from_buff
);
230 mutex_unlock(&lm_file
->lock
);
234 static const struct file_operations pds_vfio_save_fops
= {
235 .owner
= THIS_MODULE
,
236 .read
= pds_vfio_save_read
,
237 .release
= pds_vfio_release_file
,
240 static int pds_vfio_get_save_file(struct pds_vfio_pci_device
*pds_vfio
)
242 struct device
*dev
= &pds_vfio
->vfio_coredev
.pdev
->dev
;
243 struct pds_vfio_lm_file
*lm_file
;
247 /* Get live migration state size in this state */
248 err
= pds_vfio_get_lm_state_size_cmd(pds_vfio
, &size
);
250 dev_err(dev
, "failed to get save status: %pe\n", ERR_PTR(err
));
254 dev_dbg(dev
, "save status, size = %lld\n", size
);
257 dev_err(dev
, "invalid state size\n");
261 lm_file
= pds_vfio_get_lm_file(&pds_vfio_save_fops
, O_RDONLY
, size
);
263 dev_err(dev
, "failed to create save file\n");
267 dev_dbg(dev
, "size = %lld, alloc_size = %lld, npages = %lld\n",
268 lm_file
->size
, lm_file
->alloc_size
, lm_file
->npages
);
270 pds_vfio
->save_file
= lm_file
;
275 static ssize_t
pds_vfio_restore_write(struct file
*filp
, const char __user
*buf
,
276 size_t len
, loff_t
*pos
)
278 struct pds_vfio_lm_file
*lm_file
= filp
->private_data
;
279 loff_t requested_length
;
288 check_add_overflow((loff_t
)len
, *pos
, &requested_length
))
291 mutex_lock(&lm_file
->lock
);
293 if (lm_file
->disabled
) {
305 page_offset
= (*pos
) % PAGE_SIZE
;
306 page
= pds_vfio_get_file_page(lm_file
, *pos
- page_offset
);
313 page_len
= min_t(size_t, len
, PAGE_SIZE
- page_offset
);
314 to_buff
= kmap_local_page(page
);
315 err
= copy_from_user(to_buff
+ page_offset
, buf
, page_len
);
316 kunmap_local(to_buff
);
325 lm_file
->size
+= page_len
;
328 mutex_unlock(&lm_file
->lock
);
332 static const struct file_operations pds_vfio_restore_fops
= {
333 .owner
= THIS_MODULE
,
334 .write
= pds_vfio_restore_write
,
335 .release
= pds_vfio_release_file
,
338 static int pds_vfio_get_restore_file(struct pds_vfio_pci_device
*pds_vfio
)
340 struct device
*dev
= &pds_vfio
->vfio_coredev
.pdev
->dev
;
341 struct pds_vfio_lm_file
*lm_file
;
344 size
= sizeof(union pds_lm_dev_state
);
345 dev_dbg(dev
, "restore status, size = %lld\n", size
);
348 dev_err(dev
, "invalid state size");
352 lm_file
= pds_vfio_get_lm_file(&pds_vfio_restore_fops
, O_WRONLY
, size
);
354 dev_err(dev
, "failed to create restore file");
357 pds_vfio
->restore_file
= lm_file
;
363 pds_vfio_step_device_state_locked(struct pds_vfio_pci_device
*pds_vfio
,
364 enum vfio_device_mig_state next
)
366 enum vfio_device_mig_state cur
= pds_vfio
->state
;
369 if (cur
== VFIO_DEVICE_STATE_STOP
&& next
== VFIO_DEVICE_STATE_STOP_COPY
) {
370 err
= pds_vfio_get_save_file(pds_vfio
);
374 err
= pds_vfio_get_lm_state_cmd(pds_vfio
);
376 pds_vfio_put_save_file(pds_vfio
);
380 return pds_vfio
->save_file
->filep
;
383 if (cur
== VFIO_DEVICE_STATE_STOP_COPY
&& next
== VFIO_DEVICE_STATE_STOP
) {
384 pds_vfio_put_save_file(pds_vfio
);
385 pds_vfio_dirty_disable(pds_vfio
, true);
389 if (cur
== VFIO_DEVICE_STATE_STOP
&& next
== VFIO_DEVICE_STATE_RESUMING
) {
390 err
= pds_vfio_get_restore_file(pds_vfio
);
394 return pds_vfio
->restore_file
->filep
;
397 if (cur
== VFIO_DEVICE_STATE_RESUMING
&& next
== VFIO_DEVICE_STATE_STOP
) {
398 err
= pds_vfio_set_lm_state_cmd(pds_vfio
);
402 pds_vfio_put_restore_file(pds_vfio
);
406 if (cur
== VFIO_DEVICE_STATE_RUNNING
&& next
== VFIO_DEVICE_STATE_RUNNING_P2P
) {
407 pds_vfio_send_host_vf_lm_status_cmd(pds_vfio
,
408 PDS_LM_STA_IN_PROGRESS
);
409 err
= pds_vfio_suspend_device_cmd(pds_vfio
,
410 PDS_LM_SUSPEND_RESUME_TYPE_P2P
);
417 if (cur
== VFIO_DEVICE_STATE_RUNNING_P2P
&& next
== VFIO_DEVICE_STATE_RUNNING
) {
418 err
= pds_vfio_resume_device_cmd(pds_vfio
,
419 PDS_LM_SUSPEND_RESUME_TYPE_FULL
);
423 pds_vfio_send_host_vf_lm_status_cmd(pds_vfio
, PDS_LM_STA_NONE
);
427 if (cur
== VFIO_DEVICE_STATE_STOP
&& next
== VFIO_DEVICE_STATE_RUNNING_P2P
) {
428 err
= pds_vfio_resume_device_cmd(pds_vfio
,
429 PDS_LM_SUSPEND_RESUME_TYPE_P2P
);
436 if (cur
== VFIO_DEVICE_STATE_RUNNING_P2P
&& next
== VFIO_DEVICE_STATE_STOP
) {
437 err
= pds_vfio_suspend_device_cmd(pds_vfio
,
438 PDS_LM_SUSPEND_RESUME_TYPE_FULL
);
444 return ERR_PTR(-EINVAL
);