1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * (C) COPYRIGHT 2019-2022 ARM Limited. All rights reserved. 5*4882a593Smuzhiyun * 6*4882a593Smuzhiyun * This program is free software and is provided to you under the terms of the 7*4882a593Smuzhiyun * GNU General Public License version 2 as published by the Free Software 8*4882a593Smuzhiyun * Foundation, and any use by you of this program is subject to the terms 9*4882a593Smuzhiyun * of such GNU license. 10*4882a593Smuzhiyun * 11*4882a593Smuzhiyun * This program is distributed in the hope that it will be useful, 12*4882a593Smuzhiyun * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*4882a593Smuzhiyun * GNU General Public License for more details. 15*4882a593Smuzhiyun * 16*4882a593Smuzhiyun * You should have received a copy of the GNU General Public License 17*4882a593Smuzhiyun * along with this program; if not, you can access it online at 18*4882a593Smuzhiyun * http://www.gnu.org/licenses/gpl-2.0.html. 19*4882a593Smuzhiyun * 20*4882a593Smuzhiyun */ 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun #ifndef _MEMORY_GROUP_MANAGER_H_ 23*4882a593Smuzhiyun #define _MEMORY_GROUP_MANAGER_H_ 24*4882a593Smuzhiyun 25*4882a593Smuzhiyun #include <linux/mm.h> 26*4882a593Smuzhiyun #include <linux/of.h> 27*4882a593Smuzhiyun #include <linux/version.h> 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun #if (KERNEL_VERSION(4, 17, 0) > LINUX_VERSION_CODE) 30*4882a593Smuzhiyun typedef int vm_fault_t; 31*4882a593Smuzhiyun #endif 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun #define MEMORY_GROUP_MANAGER_NR_GROUPS (16) 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun struct memory_group_manager_device; 36*4882a593Smuzhiyun struct memory_group_manager_import_data; 37*4882a593Smuzhiyun 38*4882a593Smuzhiyun /** 39*4882a593Smuzhiyun * struct memory_group_manager_ops - Callbacks for memory group manager 40*4882a593Smuzhiyun * operations 41*4882a593Smuzhiyun * 42*4882a593Smuzhiyun * @mgm_alloc_page: Callback to allocate physical memory in a group 43*4882a593Smuzhiyun * @mgm_free_page: Callback to free physical memory in a group 44*4882a593Smuzhiyun * @mgm_get_import_memory_id: Callback to get the group ID for imported memory 45*4882a593Smuzhiyun * @mgm_update_gpu_pte: Callback to modify a GPU page table entry 46*4882a593Smuzhiyun * @mgm_pte_to_original_pte: Callback to get the original PTE entry as given 47*4882a593Smuzhiyun * to mgm_update_gpu_pte 48*4882a593Smuzhiyun * @mgm_vmf_insert_pfn_prot: Callback to map a physical memory page for the CPU 49*4882a593Smuzhiyun */ 50*4882a593Smuzhiyun struct memory_group_manager_ops { 51*4882a593Smuzhiyun /* 52*4882a593Smuzhiyun * mgm_alloc_page - Allocate a physical memory page in a group 53*4882a593Smuzhiyun * 54*4882a593Smuzhiyun * @mgm_dev: The memory group manager through which the request is 55*4882a593Smuzhiyun * being made. 56*4882a593Smuzhiyun * @group_id: A physical memory group ID. The meaning of this is defined 57*4882a593Smuzhiyun * by the systems integrator. Its valid range is 58*4882a593Smuzhiyun * 0 .. MEMORY_GROUP_MANAGER_NR_GROUPS-1. 59*4882a593Smuzhiyun * @gfp_mask: Bitmask of Get Free Page flags affecting allocator 60*4882a593Smuzhiyun * behavior. 61*4882a593Smuzhiyun * @order: Page order for physical page size (order=0 means 4 KiB, 62*4882a593Smuzhiyun * order=9 means 2 MiB). 63*4882a593Smuzhiyun * 64*4882a593Smuzhiyun * Return: Pointer to allocated page, or NULL if allocation failed. 65*4882a593Smuzhiyun */ 66*4882a593Smuzhiyun struct page *(*mgm_alloc_page)( 67*4882a593Smuzhiyun struct memory_group_manager_device *mgm_dev, int group_id, 68*4882a593Smuzhiyun gfp_t gfp_mask, unsigned int order); 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun /* 71*4882a593Smuzhiyun * mgm_free_page - Free a physical memory page in a group 72*4882a593Smuzhiyun * 73*4882a593Smuzhiyun * @mgm_dev: The memory group manager through which the request 74*4882a593Smuzhiyun * is being made. 75*4882a593Smuzhiyun * @group_id: A physical memory group ID. The meaning of this is 76*4882a593Smuzhiyun * defined by the systems integrator. Its valid range is 77*4882a593Smuzhiyun * 0 .. MEMORY_GROUP_MANAGER_NR_GROUPS-1. 78*4882a593Smuzhiyun * @page: Address of the struct associated with a page of physical 79*4882a593Smuzhiyun * memory that was allocated by calling the mgm_alloc_page 80*4882a593Smuzhiyun * method of the same memory pool with the same values of 81*4882a593Smuzhiyun * @group_id and @order. 82*4882a593Smuzhiyun * @order: Page order for physical page size (order=0 means 4 KiB, 83*4882a593Smuzhiyun * order=9 means 2 MiB). 84*4882a593Smuzhiyun */ 85*4882a593Smuzhiyun void (*mgm_free_page)( 86*4882a593Smuzhiyun struct memory_group_manager_device *mgm_dev, int group_id, 87*4882a593Smuzhiyun struct page *page, unsigned int order); 88*4882a593Smuzhiyun 89*4882a593Smuzhiyun /* 90*4882a593Smuzhiyun * mgm_get_import_memory_id - Get the physical memory group ID for the 91*4882a593Smuzhiyun * imported memory 92*4882a593Smuzhiyun * 93*4882a593Smuzhiyun * @mgm_dev: The memory group manager through which the request 94*4882a593Smuzhiyun * is being made. 95*4882a593Smuzhiyun * @import_data: Pointer to the data which describes imported memory. 96*4882a593Smuzhiyun * 97*4882a593Smuzhiyun * Note that provision of this call back is optional, where it is not 98*4882a593Smuzhiyun * provided this call back pointer must be set to NULL to indicate it 99*4882a593Smuzhiyun * is not in use. 100*4882a593Smuzhiyun * 101*4882a593Smuzhiyun * Return: The memory group ID to use when mapping pages from this 102*4882a593Smuzhiyun * imported memory. 103*4882a593Smuzhiyun */ 104*4882a593Smuzhiyun int (*mgm_get_import_memory_id)( 105*4882a593Smuzhiyun struct memory_group_manager_device *mgm_dev, 106*4882a593Smuzhiyun struct memory_group_manager_import_data *import_data); 107*4882a593Smuzhiyun 108*4882a593Smuzhiyun /* 109*4882a593Smuzhiyun * mgm_update_gpu_pte - Modify a GPU page table entry for a memory group 110*4882a593Smuzhiyun * 111*4882a593Smuzhiyun * @mgm_dev: The memory group manager through which the request 112*4882a593Smuzhiyun * is being made. 113*4882a593Smuzhiyun * @group_id: A physical memory group ID. The meaning of this is 114*4882a593Smuzhiyun * defined by the systems integrator. Its valid range is 115*4882a593Smuzhiyun * 0 .. MEMORY_GROUP_MANAGER_NR_GROUPS-1. 116*4882a593Smuzhiyun * @mmu_level: The level of the page table entry in @ate. 117*4882a593Smuzhiyun * @pte: The page table entry to modify, in LPAE or AArch64 format 118*4882a593Smuzhiyun * (depending on the driver's configuration). This should be 119*4882a593Smuzhiyun * decoded to determine the physical address and any other 120*4882a593Smuzhiyun * properties of the mapping the manager requires. 121*4882a593Smuzhiyun * 122*4882a593Smuzhiyun * This function allows the memory group manager to modify a GPU page 123*4882a593Smuzhiyun * table entry before it is stored by the kbase module (controller 124*4882a593Smuzhiyun * driver). It may set certain bits in the page table entry attributes 125*4882a593Smuzhiyun * or modify the physical address, based on the physical memory group ID 126*4882a593Smuzhiyun * and/or additional data in struct memory_group_manager_device. 127*4882a593Smuzhiyun * 128*4882a593Smuzhiyun * Return: A modified GPU page table entry to be stored in a page table. 129*4882a593Smuzhiyun */ 130*4882a593Smuzhiyun u64 (*mgm_update_gpu_pte)(struct memory_group_manager_device *mgm_dev, 131*4882a593Smuzhiyun int group_id, int mmu_level, u64 pte); 132*4882a593Smuzhiyun 133*4882a593Smuzhiyun /* 134*4882a593Smuzhiyun * mgm_pte_to_original_pte - Undo any modification done during mgm_update_gpu_pte() 135*4882a593Smuzhiyun * 136*4882a593Smuzhiyun * @mgm_dev: The memory group manager through which the request 137*4882a593Smuzhiyun * is being made. 138*4882a593Smuzhiyun * @group_id: A physical memory group ID. The meaning of this is 139*4882a593Smuzhiyun * defined by the systems integrator. Its valid range is 140*4882a593Smuzhiyun * 0 .. MEMORY_GROUP_MANAGER_NR_GROUPS-1. 141*4882a593Smuzhiyun * @mmu_level: The level of the page table entry in @ate. 142*4882a593Smuzhiyun * @pte: The page table entry to restore the original representation for, 143*4882a593Smuzhiyun * in LPAE or AArch64 format (depending on the driver's configuration). 144*4882a593Smuzhiyun * 145*4882a593Smuzhiyun * Undo any modifications done during mgm_update_gpu_pte(). 146*4882a593Smuzhiyun * This function allows getting back the original PTE entry as given 147*4882a593Smuzhiyun * to mgm_update_gpu_pte(). 148*4882a593Smuzhiyun * 149*4882a593Smuzhiyun * Return: PTE entry as originally specified to mgm_update_gpu_pte() 150*4882a593Smuzhiyun */ 151*4882a593Smuzhiyun u64 (*mgm_pte_to_original_pte)(struct memory_group_manager_device *mgm_dev, int group_id, 152*4882a593Smuzhiyun int mmu_level, u64 pte); 153*4882a593Smuzhiyun 154*4882a593Smuzhiyun /* 155*4882a593Smuzhiyun * mgm_vmf_insert_pfn_prot - Map a physical page in a group for the CPU 156*4882a593Smuzhiyun * 157*4882a593Smuzhiyun * @mgm_dev: The memory group manager through which the request 158*4882a593Smuzhiyun * is being made. 159*4882a593Smuzhiyun * @group_id: A physical memory group ID. The meaning of this is 160*4882a593Smuzhiyun * defined by the systems integrator. Its valid range is 161*4882a593Smuzhiyun * 0 .. MEMORY_GROUP_MANAGER_NR_GROUPS-1. 162*4882a593Smuzhiyun * @vma: The virtual memory area to insert the page into. 163*4882a593Smuzhiyun * @addr: A virtual address (in @vma) to assign to the page. 164*4882a593Smuzhiyun * @pfn: The kernel Page Frame Number to insert at @addr in @vma. 165*4882a593Smuzhiyun * @pgprot: Protection flags for the inserted page. 166*4882a593Smuzhiyun * 167*4882a593Smuzhiyun * Called from a CPU virtual memory page fault handler. This function 168*4882a593Smuzhiyun * creates a page table entry from the given parameter values and stores 169*4882a593Smuzhiyun * it at the appropriate location (unlike mgm_update_gpu_pte, which 170*4882a593Smuzhiyun * returns a modified entry). 171*4882a593Smuzhiyun * 172*4882a593Smuzhiyun * Return: Type of fault that occurred or VM_FAULT_NOPAGE if the page 173*4882a593Smuzhiyun * table entry was successfully installed. 174*4882a593Smuzhiyun */ 175*4882a593Smuzhiyun vm_fault_t (*mgm_vmf_insert_pfn_prot)( 176*4882a593Smuzhiyun struct memory_group_manager_device *mgm_dev, int group_id, 177*4882a593Smuzhiyun struct vm_area_struct *vma, unsigned long addr, 178*4882a593Smuzhiyun unsigned long pfn, pgprot_t pgprot); 179*4882a593Smuzhiyun }; 180*4882a593Smuzhiyun 181*4882a593Smuzhiyun /** 182*4882a593Smuzhiyun * struct memory_group_manager_device - Device structure for a memory group 183*4882a593Smuzhiyun * manager 184*4882a593Smuzhiyun * 185*4882a593Smuzhiyun * @ops: Callbacks associated with this device 186*4882a593Smuzhiyun * @data: Pointer to device private data 187*4882a593Smuzhiyun * @owner: pointer to owning module 188*4882a593Smuzhiyun * 189*4882a593Smuzhiyun * In order for a systems integrator to provide custom behaviors for memory 190*4882a593Smuzhiyun * operations performed by the kbase module (controller driver), they must 191*4882a593Smuzhiyun * provide a platform-specific driver module which implements this interface. 192*4882a593Smuzhiyun * 193*4882a593Smuzhiyun * This structure should be registered with the platform device using 194*4882a593Smuzhiyun * platform_set_drvdata(). 195*4882a593Smuzhiyun */ 196*4882a593Smuzhiyun struct memory_group_manager_device { 197*4882a593Smuzhiyun struct memory_group_manager_ops ops; 198*4882a593Smuzhiyun void *data; 199*4882a593Smuzhiyun struct module *owner; 200*4882a593Smuzhiyun }; 201*4882a593Smuzhiyun 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun enum memory_group_manager_import_type { 204*4882a593Smuzhiyun MEMORY_GROUP_MANAGER_IMPORT_TYPE_DMA_BUF 205*4882a593Smuzhiyun }; 206*4882a593Smuzhiyun 207*4882a593Smuzhiyun /** 208*4882a593Smuzhiyun * struct memory_group_manager_import_data - Structure describing the imported 209*4882a593Smuzhiyun * memory 210*4882a593Smuzhiyun * 211*4882a593Smuzhiyun * @type: type of imported memory 212*4882a593Smuzhiyun * @u: Union describing the imported memory 213*4882a593Smuzhiyun * @u.dma_buf: imported memory 214*4882a593Smuzhiyun * 215*4882a593Smuzhiyun */ 216*4882a593Smuzhiyun struct memory_group_manager_import_data { 217*4882a593Smuzhiyun enum memory_group_manager_import_type type; 218*4882a593Smuzhiyun union { 219*4882a593Smuzhiyun struct dma_buf *dma_buf; 220*4882a593Smuzhiyun } u; 221*4882a593Smuzhiyun }; 222*4882a593Smuzhiyun 223*4882a593Smuzhiyun #endif /* _MEMORY_GROUP_MANAGER_H_ */ 224