Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nitro_enclaves: Merge contiguous physical memory regions

There can be cases when there are more memory regions that need to be
set for an enclave than the maximum supported number of memory regions
per enclave. One example can be when the memory regions are backed by 2
MiB hugepages (the minimum supported hugepage size).

Let's merge the adjacent regions if they are physically contiguous. This
way the final number of memory regions is less than before merging and
could potentially avoid reaching maximum.

Reviewed-by: Andra Paraschiv <andraprs@amazon.com>
Signed-off-by: Longpeng <longpeng2@huawei.com>
Link: https://lore.kernel.org/r/20211107140918.2106-2-longpeng2@huawei.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Longpeng and committed by
Greg Kroah-Hartman
f6bdc0aa dc74e8cf

+56 -28
+56 -28
drivers/virt/nitro_enclaves/ne_misc_dev.c
··· 24 24 #include <linux/nitro_enclaves.h> 25 25 #include <linux/pci.h> 26 26 #include <linux/poll.h> 27 + #include <linux/range.h> 27 28 #include <linux/slab.h> 28 29 #include <linux/types.h> 29 30 #include <uapi/linux/vm_sockets.h> ··· 125 124 }; 126 125 127 126 static struct ne_cpu_pool ne_cpu_pool; 127 + 128 + /** 129 + * struct ne_phys_contig_mem_regions - Contiguous physical memory regions. 130 + * @num: The number of regions that currently has. 131 + * @regions: The array of physical memory regions. 132 + */ 133 + struct ne_phys_contig_mem_regions { 134 + unsigned long num; 135 + struct range *regions; 136 + }; 128 137 129 138 /** 130 139 * ne_check_enclaves_created() - Verify if at least one enclave has been created. ··· 836 825 } 837 826 838 827 /** 828 + * ne_merge_phys_contig_memory_regions() - Add a memory region and merge the adjacent 829 + * regions if they are physically contiguous. 830 + * @phys_contig_regions : Private data associated with the contiguous physical memory regions. 831 + * @page_paddr : Physical start address of the region to be added. 832 + * @page_size : Length of the region to be added. 833 + * 834 + * Context: Process context. This function is called with the ne_enclave mutex held. 835 + */ 836 + static void 837 + ne_merge_phys_contig_memory_regions(struct ne_phys_contig_mem_regions *phys_contig_regions, 838 + u64 page_paddr, u64 page_size) 839 + { 840 + unsigned long num = phys_contig_regions->num; 841 + 842 + /* Physically contiguous, just merge */ 843 + if (num && (phys_contig_regions->regions[num - 1].end + 1) == page_paddr) { 844 + phys_contig_regions->regions[num - 1].end += page_size; 845 + 846 + return; 847 + } 848 + 849 + phys_contig_regions->regions[num].start = page_paddr; 850 + phys_contig_regions->regions[num].end = page_paddr + page_size - 1; 851 + phys_contig_regions->num++; 852 + } 853 + 854 + /** 839 855 * ne_set_user_memory_region_ioctl() - Add user space memory region to the slot 840 856 * associated with the current enclave. 841 857 * @ne_enclave : Private data associated with the current enclave. ··· 881 843 unsigned long max_nr_pages = 0; 882 844 unsigned long memory_size = 0; 883 845 struct ne_mem_region *ne_mem_region = NULL; 884 - unsigned long nr_phys_contig_mem_regions = 0; 885 846 struct pci_dev *pdev = ne_devs.ne_pci_dev->pdev; 886 - struct page **phys_contig_mem_regions = NULL; 847 + struct ne_phys_contig_mem_regions phys_contig_mem_regions = {}; 887 848 int rc = -EINVAL; 888 849 889 850 rc = ne_sanity_check_user_mem_region(ne_enclave, mem_region); ··· 903 866 goto free_mem_region; 904 867 } 905 868 906 - phys_contig_mem_regions = kcalloc(max_nr_pages, sizeof(*phys_contig_mem_regions), 907 - GFP_KERNEL); 908 - if (!phys_contig_mem_regions) { 869 + phys_contig_mem_regions.regions = kcalloc(max_nr_pages, 870 + sizeof(*phys_contig_mem_regions.regions), 871 + GFP_KERNEL); 872 + if (!phys_contig_mem_regions.regions) { 909 873 rc = -ENOMEM; 910 874 911 875 goto free_mem_region; ··· 939 901 if (rc < 0) 940 902 goto put_pages; 941 903 942 - /* 943 - * TODO: Update once handled non-contiguous memory regions 944 - * received from user space or contiguous physical memory regions 945 - * larger than 2 MiB e.g. 8 MiB. 946 - */ 947 - phys_contig_mem_regions[i] = ne_mem_region->pages[i]; 904 + ne_merge_phys_contig_memory_regions(&phys_contig_mem_regions, 905 + page_to_phys(ne_mem_region->pages[i]), 906 + page_size(ne_mem_region->pages[i])); 948 907 949 908 memory_size += page_size(ne_mem_region->pages[i]); 950 909 951 910 ne_mem_region->nr_pages++; 952 911 } while (memory_size < mem_region.memory_size); 953 912 954 - /* 955 - * TODO: Update once handled non-contiguous memory regions received 956 - * from user space or contiguous physical memory regions larger than 957 - * 2 MiB e.g. 8 MiB. 958 - */ 959 - nr_phys_contig_mem_regions = ne_mem_region->nr_pages; 960 - 961 - if ((ne_enclave->nr_mem_regions + nr_phys_contig_mem_regions) > 913 + if ((ne_enclave->nr_mem_regions + phys_contig_mem_regions.num) > 962 914 ne_enclave->max_mem_regions) { 963 915 dev_err_ratelimited(ne_misc_dev.this_device, 964 916 "Reached max memory regions %lld\n", ··· 959 931 goto put_pages; 960 932 } 961 933 962 - for (i = 0; i < nr_phys_contig_mem_regions; i++) { 963 - u64 phys_region_addr = page_to_phys(phys_contig_mem_regions[i]); 964 - u64 phys_region_size = page_size(phys_contig_mem_regions[i]); 934 + for (i = 0; i < phys_contig_mem_regions.num; i++) { 935 + u64 phys_region_addr = phys_contig_mem_regions.regions[i].start; 936 + u64 phys_region_size = range_len(&phys_contig_mem_regions.regions[i]); 965 937 966 938 if (phys_region_size & (NE_MIN_MEM_REGION_SIZE - 1)) { 967 939 dev_err_ratelimited(ne_misc_dev.this_device, ··· 987 959 988 960 list_add(&ne_mem_region->mem_region_list_entry, &ne_enclave->mem_regions_list); 989 961 990 - for (i = 0; i < nr_phys_contig_mem_regions; i++) { 962 + for (i = 0; i < phys_contig_mem_regions.num; i++) { 991 963 struct ne_pci_dev_cmd_reply cmd_reply = {}; 992 964 struct slot_add_mem_req slot_add_mem_req = {}; 993 965 994 966 slot_add_mem_req.slot_uid = ne_enclave->slot_uid; 995 - slot_add_mem_req.paddr = page_to_phys(phys_contig_mem_regions[i]); 996 - slot_add_mem_req.size = page_size(phys_contig_mem_regions[i]); 967 + slot_add_mem_req.paddr = phys_contig_mem_regions.regions[i].start; 968 + slot_add_mem_req.size = range_len(&phys_contig_mem_regions.regions[i]); 997 969 998 970 rc = ne_do_request(pdev, SLOT_ADD_MEM, 999 971 &slot_add_mem_req, sizeof(slot_add_mem_req), ··· 1002 974 dev_err_ratelimited(ne_misc_dev.this_device, 1003 975 "Error in slot add mem [rc=%d]\n", rc); 1004 976 1005 - kfree(phys_contig_mem_regions); 977 + kfree(phys_contig_mem_regions.regions); 1006 978 1007 979 /* 1008 980 * Exit here without put pages as memory regions may ··· 1015 987 ne_enclave->nr_mem_regions++; 1016 988 } 1017 989 1018 - kfree(phys_contig_mem_regions); 990 + kfree(phys_contig_mem_regions.regions); 1019 991 1020 992 return 0; 1021 993 ··· 1023 995 for (i = 0; i < ne_mem_region->nr_pages; i++) 1024 996 put_page(ne_mem_region->pages[i]); 1025 997 free_mem_region: 1026 - kfree(phys_contig_mem_regions); 998 + kfree(phys_contig_mem_regions.regions); 1027 999 kfree(ne_mem_region->pages); 1028 1000 kfree(ne_mem_region); 1029 1001