vfio/mlx5: Allow loading of larger images than 512 MB
authorYishai Hadas <yishaih@nvidia.com>
Sun, 8 Jan 2023 15:44:23 +0000 (17:44 +0200)
committerAlex Williamson <alex.williamson@redhat.com>
Mon, 23 Jan 2023 18:26:29 +0000 (11:26 -0700)
Allow loading of larger images than 512 MB by dropping the arbitrary
hard-coded value that we have today and move to use the max device
loading value which is for now 4GB.

As part of that we move to use the GFP_KERNEL_ACCOUNT option upon
allocating the persistent data of mlx5 and rely on the cgroup to provide
the memory limit for the given user.

The GFP_KERNEL_ACCOUNT option lets the memory allocator know that this
is untrusted allocation triggered from userspace and should be a subject
of kmem accounting, and as such it is controlled by the cgroup
mechanism.

Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/20230108154427.32609-3-yishaih@nvidia.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
drivers/vfio/pci/mlx5/cmd.c
drivers/vfio/pci/mlx5/main.c

index c5dcddb..0586f09 100644 (file)
@@ -373,7 +373,7 @@ mlx5vf_alloc_data_buffer(struct mlx5_vf_migration_file *migf,
        struct mlx5_vhca_data_buffer *buf;
        int ret;
 
-       buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+       buf = kzalloc(sizeof(*buf), GFP_KERNEL_ACCOUNT);
        if (!buf)
                return ERR_PTR(-ENOMEM);
 
@@ -1032,7 +1032,7 @@ mlx5vf_create_rc_qp(struct mlx5_core_dev *mdev,
        void *in;
        int err;
 
-       qp = kzalloc(sizeof(*qp), GFP_KERNEL);
+       qp = kzalloc(sizeof(*qp), GFP_KERNEL_ACCOUNT);
        if (!qp)
                return ERR_PTR(-ENOMEM);
 
@@ -1213,12 +1213,13 @@ static int alloc_recv_pages(struct mlx5_vhca_recv_buf *recv_buf,
        int i;
 
        recv_buf->page_list = kvcalloc(npages, sizeof(*recv_buf->page_list),
-                                      GFP_KERNEL);
+                                      GFP_KERNEL_ACCOUNT);
        if (!recv_buf->page_list)
                return -ENOMEM;
 
        for (;;) {
-               filled = alloc_pages_bulk_array(GFP_KERNEL, npages - done,
+               filled = alloc_pages_bulk_array(GFP_KERNEL_ACCOUNT,
+                                               npages - done,
                                                recv_buf->page_list + done);
                if (!filled)
                        goto err;
@@ -1248,7 +1249,7 @@ static int register_dma_recv_pages(struct mlx5_core_dev *mdev,
 
        recv_buf->dma_addrs = kvcalloc(recv_buf->npages,
                                       sizeof(*recv_buf->dma_addrs),
-                                      GFP_KERNEL);
+                                      GFP_KERNEL_ACCOUNT);
        if (!recv_buf->dma_addrs)
                return -ENOMEM;
 
index 9feb89c..7ba127d 100644 (file)
@@ -21,8 +21,8 @@
 
 #include "cmd.h"
 
-/* Arbitrary to prevent userspace from consuming endless memory */
-#define MAX_MIGRATION_SIZE (512*1024*1024)
+/* Device specification max LOAD size */
+#define MAX_LOAD_SIZE (BIT_ULL(__mlx5_bit_sz(load_vhca_state_in, size)) - 1)
 
 static struct mlx5vf_pci_core_device *mlx5vf_drvdata(struct pci_dev *pdev)
 {
@@ -73,12 +73,13 @@ int mlx5vf_add_migration_pages(struct mlx5_vhca_data_buffer *buf,
        int ret;
 
        to_fill = min_t(unsigned int, npages, PAGE_SIZE / sizeof(*page_list));
-       page_list = kvzalloc(to_fill * sizeof(*page_list), GFP_KERNEL);
+       page_list = kvzalloc(to_fill * sizeof(*page_list), GFP_KERNEL_ACCOUNT);
        if (!page_list)
                return -ENOMEM;
 
        do {
-               filled = alloc_pages_bulk_array(GFP_KERNEL, to_fill, page_list);
+               filled = alloc_pages_bulk_array(GFP_KERNEL_ACCOUNT, to_fill,
+                                               page_list);
                if (!filled) {
                        ret = -ENOMEM;
                        goto err;
@@ -87,7 +88,7 @@ int mlx5vf_add_migration_pages(struct mlx5_vhca_data_buffer *buf,
                ret = sg_alloc_append_table_from_pages(
                        &buf->table, page_list, filled, 0,
                        filled << PAGE_SHIFT, UINT_MAX, SG_MAX_SINGLE_ALLOC,
-                       GFP_KERNEL);
+                       GFP_KERNEL_ACCOUNT);
 
                if (ret)
                        goto err;
@@ -467,7 +468,7 @@ mlx5vf_pci_save_device_data(struct mlx5vf_pci_core_device *mvdev, bool track)
        size_t length;
        int ret;
 
-       migf = kzalloc(sizeof(*migf), GFP_KERNEL);
+       migf = kzalloc(sizeof(*migf), GFP_KERNEL_ACCOUNT);
        if (!migf)
                return ERR_PTR(-ENOMEM);
 
@@ -564,7 +565,7 @@ mlx5vf_resume_read_image_no_header(struct mlx5_vhca_data_buffer *vhca_buf,
 {
        int ret;
 
-       if (requested_length > MAX_MIGRATION_SIZE)
+       if (requested_length > MAX_LOAD_SIZE)
                return -ENOMEM;
 
        if (vhca_buf->allocated_length < requested_length) {
@@ -648,7 +649,7 @@ mlx5vf_resume_read_header(struct mlx5_vf_migration_file *migf,
                u64 flags;
 
                vhca_buf->header_image_size = le64_to_cpup((__le64 *)to_buff);
-               if (vhca_buf->header_image_size > MAX_MIGRATION_SIZE) {
+               if (vhca_buf->header_image_size > MAX_LOAD_SIZE) {
                        ret = -ENOMEM;
                        goto end;
                }
@@ -781,7 +782,7 @@ mlx5vf_pci_resume_device_data(struct mlx5vf_pci_core_device *mvdev)
        struct mlx5_vhca_data_buffer *buf;
        int ret;
 
-       migf = kzalloc(sizeof(*migf), GFP_KERNEL);
+       migf = kzalloc(sizeof(*migf), GFP_KERNEL_ACCOUNT);
        if (!migf)
                return ERR_PTR(-ENOMEM);