forked from rubenslte/android_kernel_samsung_msm8226
msm: kgsl: pass mmu pointer into address space query functions
This allows address space and pagetable configuration to be set from data in the mmu, such as devtree settings. Change-Id: I811b2d8bbac2613a0ea51795f7cd4b121ec203da Signed-off-by: Jeremy Gebben <jgebben@codeaurora.org>
This commit is contained in:
committed by
Shubhraprakash Das
parent
868d38a7f3
commit
90a9734d95
@@ -702,7 +702,7 @@ static void adreno_dump_a2xx(struct kgsl_device *device)
|
||||
" %08X\n", r1, r2, r3);
|
||||
|
||||
KGSL_LOG_DUMP(device, "PAGETABLE SIZE: %08X ",
|
||||
kgsl_mmu_get_ptsize());
|
||||
kgsl_mmu_get_ptsize(&device->mmu));
|
||||
|
||||
kgsl_regread(device, MH_MMU_TRAN_ERROR, &r1);
|
||||
KGSL_LOG_DUMP(device, " TRAN_ERROR = %08X\n", r1);
|
||||
|
||||
+9
-13
@@ -671,9 +671,10 @@ kgsl_get_process_private(struct kgsl_device_private *cur_dev_priv)
|
||||
if (kgsl_mmu_enabled())
|
||||
{
|
||||
unsigned long pt_name;
|
||||
struct kgsl_mmu *mmu = &cur_dev_priv->device->mmu;
|
||||
|
||||
pt_name = task_tgid_nr(current);
|
||||
private->pagetable = kgsl_mmu_getpagetable(pt_name);
|
||||
private->pagetable = kgsl_mmu_getpagetable(mmu, pt_name);
|
||||
if (private->pagetable == NULL) {
|
||||
kfree(private);
|
||||
private = NULL;
|
||||
@@ -872,7 +873,7 @@ kgsl_sharedmem_find_region(struct kgsl_process_private *private,
|
||||
{
|
||||
struct rb_node *node = private->mem_rb.rb_node;
|
||||
|
||||
if (!kgsl_mmu_gpuaddr_in_range(gpuaddr))
|
||||
if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr))
|
||||
return NULL;
|
||||
|
||||
while (node != NULL) {
|
||||
@@ -925,7 +926,7 @@ kgsl_sharedmem_region_empty(struct kgsl_process_private *private,
|
||||
|
||||
struct rb_node *node = private->mem_rb.rb_node;
|
||||
|
||||
if (!kgsl_mmu_gpuaddr_in_range(gpuaddr))
|
||||
if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr))
|
||||
return 0;
|
||||
|
||||
/* don't overflow */
|
||||
@@ -1193,7 +1194,9 @@ static long kgsl_ioctl_rb_issueibcmds(struct kgsl_device_private *dev_priv,
|
||||
}
|
||||
|
||||
for (i = 0; i < param->numibs; i++) {
|
||||
if (!kgsl_mmu_gpuaddr_in_range(ibdesc[i].gpuaddr)) {
|
||||
struct kgsl_pagetable *pt = dev_priv->process_priv->pagetable;
|
||||
|
||||
if (!kgsl_mmu_gpuaddr_in_range(pt, ibdesc[i].gpuaddr)) {
|
||||
result = -ERANGE;
|
||||
KGSL_DRV_ERR(dev_priv->device,
|
||||
"invalid ib base GPU virtual addr %x\n",
|
||||
@@ -1767,13 +1770,6 @@ err:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static inline int
|
||||
can_use_cpu_map(void)
|
||||
{
|
||||
return (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU
|
||||
&& kgsl_mmu_is_perprocess());
|
||||
}
|
||||
|
||||
static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
|
||||
unsigned int cmd, void *data)
|
||||
{
|
||||
@@ -1805,7 +1801,7 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
|
||||
| KGSL_MEMFLAGS_USE_CPU_MAP;
|
||||
|
||||
entry->memdesc.flags = param->flags;
|
||||
if (!can_use_cpu_map())
|
||||
if (!kgsl_mmu_use_cpu_map(private->pagetable->mmu))
|
||||
entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP;
|
||||
|
||||
switch (memtype) {
|
||||
@@ -2092,7 +2088,7 @@ kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv,
|
||||
struct kgsl_mem_entry *entry = NULL;
|
||||
int result;
|
||||
|
||||
if (!can_use_cpu_map())
|
||||
if (!kgsl_mmu_use_cpu_map(private->pagetable->mmu))
|
||||
param->flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP;
|
||||
|
||||
result = _gpumem_alloc(dev_priv, &entry, param->size, param->flags);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "kgsl.h"
|
||||
#include "kgsl_mmu.h"
|
||||
#include "kgsl_gpummu.h"
|
||||
#include "kgsl_device.h"
|
||||
#include "kgsl_sharedmem.h"
|
||||
#include "kgsl_trace.h"
|
||||
@@ -363,10 +364,9 @@ int kgsl_gpummu_pt_equal(struct kgsl_mmu *mmu,
|
||||
return gpummu_pt && pt_base && (gpummu_pt->base.gpuaddr == pt_base);
|
||||
}
|
||||
|
||||
void kgsl_gpummu_destroy_pagetable(void *mmu_specific_pt)
|
||||
void kgsl_gpummu_destroy_pagetable(struct kgsl_pagetable *pt)
|
||||
{
|
||||
struct kgsl_gpummu_pt *gpummu_pt = (struct kgsl_gpummu_pt *)
|
||||
mmu_specific_pt;
|
||||
struct kgsl_gpummu_pt *gpummu_pt = pt->priv;
|
||||
kgsl_ptpool_free((struct kgsl_ptpool *)kgsl_driver.ptpool,
|
||||
gpummu_pt->base.hostptr);
|
||||
|
||||
@@ -516,6 +516,11 @@ static int kgsl_gpummu_init(struct kgsl_mmu *mmu)
|
||||
*/
|
||||
int status = 0;
|
||||
|
||||
mmu->pt_base = KGSL_PAGETABLE_BASE;
|
||||
mmu->pt_size = CONFIG_MSM_KGSL_PAGE_TABLE_SIZE;
|
||||
mmu->pt_per_process = KGSL_MMU_USE_PER_PROCESS_PT;
|
||||
mmu->use_cpu_map = false;
|
||||
|
||||
/* sub-client MMU lookups require address translation */
|
||||
if ((mmu->config & ~0x1) > 0) {
|
||||
/*make sure virtual address range is a multiple of 64Kb */
|
||||
@@ -572,7 +577,7 @@ static int kgsl_gpummu_start(struct kgsl_mmu *mmu)
|
||||
|
||||
if (mmu->defaultpagetable == NULL)
|
||||
mmu->defaultpagetable =
|
||||
kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
|
||||
kgsl_mmu_getpagetable(mmu, KGSL_MMU_GLOBAL_PT);
|
||||
|
||||
/* Return error if the default pagetable doesn't exist */
|
||||
if (mmu->defaultpagetable == NULL)
|
||||
@@ -592,14 +597,14 @@ static int kgsl_gpummu_start(struct kgsl_mmu *mmu)
|
||||
}
|
||||
|
||||
static int
|
||||
kgsl_gpummu_unmap(void *mmu_specific_pt,
|
||||
kgsl_gpummu_unmap(struct kgsl_pagetable *pt,
|
||||
struct kgsl_memdesc *memdesc,
|
||||
unsigned int *tlb_flags)
|
||||
{
|
||||
unsigned int numpages;
|
||||
unsigned int pte, ptefirst, ptelast, superpte;
|
||||
unsigned int range = kgsl_sg_size(memdesc->sg, memdesc->sglen);
|
||||
struct kgsl_gpummu_pt *gpummu_pt = mmu_specific_pt;
|
||||
struct kgsl_gpummu_pt *gpummu_pt = pt->priv;
|
||||
|
||||
/* All GPU addresses as assigned are page aligned, but some
|
||||
functions purturb the gpuaddr with an offset, so apply the
|
||||
@@ -641,13 +646,13 @@ kgsl_gpummu_unmap(void *mmu_specific_pt,
|
||||
GSL_TLBFLUSH_FILTER_ISDIRTY((_p) / GSL_PT_SUPER_PTE))
|
||||
|
||||
static int
|
||||
kgsl_gpummu_map(void *mmu_specific_pt,
|
||||
kgsl_gpummu_map(struct kgsl_pagetable *pt,
|
||||
struct kgsl_memdesc *memdesc,
|
||||
unsigned int protflags,
|
||||
unsigned int *tlb_flags)
|
||||
{
|
||||
unsigned int pte;
|
||||
struct kgsl_gpummu_pt *gpummu_pt = mmu_specific_pt;
|
||||
struct kgsl_gpummu_pt *gpummu_pt = pt->priv;
|
||||
struct scatterlist *s;
|
||||
int flushtlb = 0;
|
||||
int i;
|
||||
|
||||
@@ -566,9 +566,9 @@ static int kgsl_iommu_pt_equal(struct kgsl_mmu *mmu,
|
||||
*
|
||||
* Return - void
|
||||
*/
|
||||
static void kgsl_iommu_destroy_pagetable(void *mmu_specific_pt)
|
||||
static void kgsl_iommu_destroy_pagetable(struct kgsl_pagetable *pt)
|
||||
{
|
||||
struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt;
|
||||
struct kgsl_iommu_pt *iommu_pt = pt->priv;
|
||||
if (iommu_pt->domain)
|
||||
iommu_domain_free(iommu_pt->domain);
|
||||
kfree(iommu_pt);
|
||||
@@ -776,7 +776,7 @@ static int kgsl_iommu_start_sync_lock(struct kgsl_mmu *mmu)
|
||||
|
||||
if (KGSL_DEVICE_3D0 != mmu->device->id ||
|
||||
!msm_soc_version_supports_iommu_v0() ||
|
||||
!kgsl_mmu_is_perprocess() ||
|
||||
!kgsl_mmu_is_perprocess(mmu) ||
|
||||
iommu->sync_lock_vars)
|
||||
return 0;
|
||||
|
||||
@@ -817,7 +817,7 @@ static int kgsl_iommu_init_sync_lock(struct kgsl_mmu *mmu)
|
||||
uint32_t page_offset = 0;
|
||||
|
||||
if (!msm_soc_version_supports_iommu_v0() ||
|
||||
!kgsl_mmu_is_perprocess())
|
||||
!kgsl_mmu_is_perprocess(mmu))
|
||||
return status;
|
||||
|
||||
/*
|
||||
@@ -1215,6 +1215,32 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu)
|
||||
if (status)
|
||||
goto done;
|
||||
|
||||
/* We presently do not support per-process for IOMMU-v1 */
|
||||
mmu->pt_per_process = KGSL_MMU_USE_PER_PROCESS_PT &&
|
||||
msm_soc_version_supports_iommu_v0();
|
||||
|
||||
/*
|
||||
* For IOMMU per-process pagetables, the allocatable range
|
||||
* and the kernel global range must both be outside
|
||||
* the userspace address range. There is a 1Mb gap
|
||||
* between these address ranges to make overrun
|
||||
* detection easier.
|
||||
* For the shared pagetable case use 2GB and because
|
||||
* mirroring the CPU address space is not possible and
|
||||
* we're better off with extra room.
|
||||
*/
|
||||
if (mmu->pt_per_process) {
|
||||
mmu->pt_base = PAGE_OFFSET;
|
||||
mmu->pt_size = KGSL_IOMMU_GLOBAL_MEM_BASE
|
||||
- kgsl_mmu_get_base_addr(mmu) - SZ_1M;
|
||||
mmu->use_cpu_map = true;
|
||||
} else {
|
||||
mmu->pt_base = KGSL_PAGETABLE_BASE;
|
||||
mmu->pt_size = SZ_2G;
|
||||
mmu->use_cpu_map = false;
|
||||
}
|
||||
|
||||
|
||||
iommu->iommu_reg_list = kgsl_iommuv0_reg;
|
||||
iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V0;
|
||||
|
||||
@@ -1268,7 +1294,8 @@ static int kgsl_iommu_setup_defaultpagetable(struct kgsl_mmu *mmu)
|
||||
* switching on the 3D side for which a separate table is allocated */
|
||||
if (!cpu_is_msm8960() && msm_soc_version_supports_iommu_v0()) {
|
||||
mmu->priv_bank_table =
|
||||
kgsl_mmu_getpagetable(KGSL_MMU_PRIV_BANK_TABLE_NAME);
|
||||
kgsl_mmu_getpagetable(mmu,
|
||||
KGSL_MMU_PRIV_BANK_TABLE_NAME);
|
||||
if (mmu->priv_bank_table == NULL) {
|
||||
status = -ENOMEM;
|
||||
goto err;
|
||||
@@ -1277,7 +1304,7 @@ static int kgsl_iommu_setup_defaultpagetable(struct kgsl_mmu *mmu)
|
||||
if (status)
|
||||
goto err;
|
||||
}
|
||||
mmu->defaultpagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
|
||||
mmu->defaultpagetable = kgsl_mmu_getpagetable(mmu, KGSL_MMU_GLOBAL_PT);
|
||||
/* Return error if the default pagetable doesn't exist */
|
||||
if (mmu->defaultpagetable == NULL) {
|
||||
status = -ENOMEM;
|
||||
@@ -1481,13 +1508,13 @@ done:
|
||||
}
|
||||
|
||||
static int
|
||||
kgsl_iommu_unmap(void *mmu_specific_pt,
|
||||
kgsl_iommu_unmap(struct kgsl_pagetable *pt,
|
||||
struct kgsl_memdesc *memdesc,
|
||||
unsigned int *tlb_flags)
|
||||
{
|
||||
int ret;
|
||||
unsigned int range = kgsl_sg_size(memdesc->sg, memdesc->sglen);
|
||||
struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt;
|
||||
struct kgsl_iommu_pt *iommu_pt = pt->priv;
|
||||
|
||||
/* All GPU addresses as assigned are page aligned, but some
|
||||
functions purturb the gpuaddr with an offset, so apply the
|
||||
@@ -1508,20 +1535,20 @@ kgsl_iommu_unmap(void *mmu_specific_pt,
|
||||
* Flushing only required if per process pagetables are used. With
|
||||
* global case, flushing will happen inside iommu_map function
|
||||
*/
|
||||
if (!ret && kgsl_mmu_is_perprocess())
|
||||
if (!ret && kgsl_mmu_is_perprocess(pt->mmu))
|
||||
*tlb_flags = UINT_MAX;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
kgsl_iommu_map(void *mmu_specific_pt,
|
||||
kgsl_iommu_map(struct kgsl_pagetable *pt,
|
||||
struct kgsl_memdesc *memdesc,
|
||||
unsigned int protflags,
|
||||
unsigned int *tlb_flags)
|
||||
{
|
||||
int ret;
|
||||
unsigned int iommu_virt_addr;
|
||||
struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt;
|
||||
struct kgsl_iommu_pt *iommu_pt = pt->priv;
|
||||
int size = kgsl_sg_size(memdesc->sg, memdesc->sglen);
|
||||
|
||||
BUG_ON(NULL == iommu_pt);
|
||||
|
||||
+20
-16
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "kgsl.h"
|
||||
#include "kgsl_mmu.h"
|
||||
#include "kgsl_gpummu.h"
|
||||
#include "kgsl_device.h"
|
||||
#include "kgsl_sharedmem.h"
|
||||
#include "adreno.h"
|
||||
@@ -103,7 +104,7 @@ static void kgsl_destroy_pagetable(struct kref *kref)
|
||||
if (pagetable->pool)
|
||||
gen_pool_destroy(pagetable->pool);
|
||||
|
||||
pagetable->pt_ops->mmu_destroy_pagetable(pagetable->priv);
|
||||
pagetable->pt_ops->mmu_destroy_pagetable(pagetable);
|
||||
|
||||
kfree(pagetable);
|
||||
}
|
||||
@@ -193,7 +194,7 @@ sysfs_show_va_range(struct kobject *kobj,
|
||||
|
||||
if (pt) {
|
||||
ret += snprintf(buf, PAGE_SIZE, "0x%x\n",
|
||||
kgsl_mmu_get_ptsize());
|
||||
kgsl_mmu_get_ptsize(pt->mmu));
|
||||
}
|
||||
|
||||
kgsl_put_pagetable(pt);
|
||||
@@ -415,7 +416,8 @@ void kgsl_mh_intrcallback(struct kgsl_device *device)
|
||||
}
|
||||
EXPORT_SYMBOL(kgsl_mh_intrcallback);
|
||||
|
||||
static struct kgsl_pagetable *kgsl_mmu_createpagetableobject(
|
||||
static struct kgsl_pagetable *
|
||||
kgsl_mmu_createpagetableobject(struct kgsl_mmu *mmu,
|
||||
unsigned int name)
|
||||
{
|
||||
int status = 0;
|
||||
@@ -434,8 +436,8 @@ static struct kgsl_pagetable *kgsl_mmu_createpagetableobject(
|
||||
|
||||
spin_lock_init(&pagetable->lock);
|
||||
|
||||
ptsize = kgsl_mmu_get_ptsize();
|
||||
|
||||
ptsize = kgsl_mmu_get_ptsize(mmu);
|
||||
pagetable->mmu = mmu;
|
||||
pagetable->name = name;
|
||||
pagetable->max_entries = KGSL_PAGETABLE_ENTRIES(ptsize);
|
||||
|
||||
@@ -467,7 +469,7 @@ static struct kgsl_pagetable *kgsl_mmu_createpagetableobject(
|
||||
goto err_kgsl_pool;
|
||||
}
|
||||
|
||||
if (gen_pool_add(pagetable->pool, kgsl_mmu_get_base_addr(),
|
||||
if (gen_pool_add(pagetable->pool, kgsl_mmu_get_base_addr(mmu),
|
||||
ptsize, -1)) {
|
||||
KGSL_CORE_ERR("gen_pool_add failed\n");
|
||||
goto err_pool;
|
||||
@@ -496,7 +498,7 @@ static struct kgsl_pagetable *kgsl_mmu_createpagetableobject(
|
||||
return pagetable;
|
||||
|
||||
err_mmu_create:
|
||||
pagetable->pt_ops->mmu_destroy_pagetable(pagetable->priv);
|
||||
pagetable->pt_ops->mmu_destroy_pagetable(pagetable);
|
||||
err_pool:
|
||||
gen_pool_destroy(pagetable->pool);
|
||||
err_kgsl_pool:
|
||||
@@ -508,20 +510,21 @@ err_alloc:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct kgsl_pagetable *kgsl_mmu_getpagetable(unsigned long name)
|
||||
struct kgsl_pagetable *kgsl_mmu_getpagetable(struct kgsl_mmu *mmu,
|
||||
unsigned long name)
|
||||
{
|
||||
struct kgsl_pagetable *pt;
|
||||
|
||||
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
|
||||
return (void *)(-1);
|
||||
|
||||
if (!kgsl_mmu_is_perprocess())
|
||||
if (!kgsl_mmu_is_perprocess(mmu))
|
||||
name = KGSL_MMU_GLOBAL_PT;
|
||||
|
||||
pt = kgsl_get_pagetable(name);
|
||||
|
||||
if (pt == NULL)
|
||||
pt = kgsl_mmu_createpagetableobject(name);
|
||||
pt = kgsl_mmu_createpagetableobject(mmu, name);
|
||||
|
||||
return pt;
|
||||
}
|
||||
@@ -658,7 +661,7 @@ kgsl_mmu_map(struct kgsl_pagetable *pagetable,
|
||||
|
||||
if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype())
|
||||
spin_lock(&pagetable->lock);
|
||||
ret = pagetable->pt_ops->mmu_map(pagetable->priv, memdesc, protflags,
|
||||
ret = pagetable->pt_ops->mmu_map(pagetable, memdesc, protflags,
|
||||
&pagetable->tlb_flags);
|
||||
if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype())
|
||||
spin_lock(&pagetable->lock);
|
||||
@@ -706,7 +709,7 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
|
||||
|
||||
if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype())
|
||||
spin_lock(&pagetable->lock);
|
||||
pagetable->pt_ops->mmu_unmap(pagetable->priv, memdesc,
|
||||
pagetable->pt_ops->mmu_unmap(pagetable, memdesc,
|
||||
&pagetable->tlb_flags);
|
||||
if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype())
|
||||
spin_lock(&pagetable->lock);
|
||||
@@ -853,15 +856,16 @@ void kgsl_mmu_set_mmutype(char *mmutype)
|
||||
}
|
||||
EXPORT_SYMBOL(kgsl_mmu_set_mmutype);
|
||||
|
||||
int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr)
|
||||
int kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, unsigned int gpuaddr)
|
||||
{
|
||||
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
|
||||
return 1;
|
||||
if (gpuaddr >= kgsl_mmu_get_base_addr() &&
|
||||
gpuaddr < kgsl_mmu_get_base_addr() + kgsl_mmu_get_ptsize())
|
||||
if (gpuaddr >= kgsl_mmu_get_base_addr(pt->mmu) &&
|
||||
gpuaddr < kgsl_mmu_get_base_addr(pt->mmu) +
|
||||
kgsl_mmu_get_ptsize(pt->mmu))
|
||||
return 1;
|
||||
if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU
|
||||
&& kgsl_mmu_is_perprocess())
|
||||
&& kgsl_mmu_is_perprocess(pt->mmu))
|
||||
return (gpuaddr > 0 && gpuaddr < TASK_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+41
-52
@@ -24,6 +24,13 @@
|
||||
|
||||
#define KGSL_MMU_ALIGN_MASK (~((1 << PAGE_SHIFT) - 1))
|
||||
|
||||
/* defconfig option for disabling per process pagetables */
|
||||
#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
|
||||
#define KGSL_MMU_USE_PER_PROCESS_PT true
|
||||
#else
|
||||
#define KGSL_MMU_USE_PER_PROCESS_PT false
|
||||
#endif
|
||||
|
||||
/* Identifier for the global page table */
|
||||
/* Per process page tables will probably pass in the thread group
|
||||
as an identifier */
|
||||
@@ -115,6 +122,7 @@ struct kgsl_pagetable {
|
||||
const struct kgsl_mmu_pt_ops *pt_ops;
|
||||
unsigned int tlb_flags;
|
||||
void *priv;
|
||||
struct kgsl_mmu *mmu;
|
||||
};
|
||||
|
||||
struct kgsl_mmu;
|
||||
@@ -159,15 +167,15 @@ struct kgsl_mmu_ops {
|
||||
};
|
||||
|
||||
struct kgsl_mmu_pt_ops {
|
||||
int (*mmu_map) (void *mmu_pt,
|
||||
int (*mmu_map) (struct kgsl_pagetable *pt,
|
||||
struct kgsl_memdesc *memdesc,
|
||||
unsigned int protflags,
|
||||
unsigned int *tlb_flags);
|
||||
int (*mmu_unmap) (void *mmu_pt,
|
||||
int (*mmu_unmap) (struct kgsl_pagetable *pt,
|
||||
struct kgsl_memdesc *memdesc,
|
||||
unsigned int *tlb_flags);
|
||||
void *(*mmu_create_pagetable) (void);
|
||||
void (*mmu_destroy_pagetable) (void *pt);
|
||||
void (*mmu_destroy_pagetable) (struct kgsl_pagetable *);
|
||||
};
|
||||
|
||||
#define KGSL_MMU_FLAGS_IOMMU_SYNC BIT(31)
|
||||
@@ -186,14 +194,19 @@ struct kgsl_mmu {
|
||||
const struct kgsl_mmu_ops *mmu_ops;
|
||||
void *priv;
|
||||
int fault;
|
||||
unsigned long pt_base;
|
||||
unsigned long pt_size;
|
||||
bool pt_per_process;
|
||||
bool use_cpu_map;
|
||||
};
|
||||
|
||||
#include "kgsl_gpummu.h"
|
||||
|
||||
extern struct kgsl_mmu_ops iommu_ops;
|
||||
extern struct kgsl_mmu_pt_ops iommu_pt_ops;
|
||||
extern struct kgsl_mmu_ops gpummu_ops;
|
||||
extern struct kgsl_mmu_pt_ops gpummu_pt_ops;
|
||||
|
||||
struct kgsl_pagetable *kgsl_mmu_getpagetable(unsigned long name);
|
||||
struct kgsl_pagetable *kgsl_mmu_getpagetable(struct kgsl_mmu *,
|
||||
unsigned long name);
|
||||
void kgsl_mmu_putpagetable(struct kgsl_pagetable *pagetable);
|
||||
void kgsl_mh_start(struct kgsl_device *device);
|
||||
void kgsl_mh_intrcallback(struct kgsl_device *device);
|
||||
@@ -218,7 +231,7 @@ void *kgsl_mmu_ptpool_init(int entries);
|
||||
int kgsl_mmu_enabled(void);
|
||||
void kgsl_mmu_set_mmutype(char *mmutype);
|
||||
enum kgsl_mmutype kgsl_mmu_get_mmutype(void);
|
||||
int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr);
|
||||
int kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, unsigned int gpuaddr);
|
||||
|
||||
/*
|
||||
* Static inline functions of MMU that simply call the SMMU specific
|
||||
@@ -332,75 +345,51 @@ static inline int kgsl_mmu_get_num_iommu_units(struct kgsl_mmu *mmu)
|
||||
/*
|
||||
* kgsl_mmu_is_perprocess() - Runtime check for per-process
|
||||
* pagetables.
|
||||
* @mmu: the mmu
|
||||
*
|
||||
* Returns non-zero if per-process pagetables are enabled,
|
||||
* 0 if not.
|
||||
* Returns true if per-process pagetables are enabled,
|
||||
* false if not.
|
||||
*/
|
||||
#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
|
||||
static inline int kgsl_mmu_is_perprocess(void)
|
||||
static inline int kgsl_mmu_is_perprocess(struct kgsl_mmu *mmu)
|
||||
{
|
||||
return mmu->pt_per_process;
|
||||
}
|
||||
|
||||
/* We presently do not support per-process for IOMMU-v1 */
|
||||
return (kgsl_mmu_get_mmutype() != KGSL_MMU_TYPE_IOMMU)
|
||||
|| msm_soc_version_supports_iommu_v0();
|
||||
}
|
||||
#else
|
||||
static inline int kgsl_mmu_is_perprocess(void)
|
||||
/*
|
||||
* kgsl_mmu_use_cpu_map() - Runtime check for matching the CPU
|
||||
* address space on the GPU.
|
||||
* @mmu: the mmu
|
||||
*
|
||||
* Returns true if supported false if not.
|
||||
*/
|
||||
static inline int kgsl_mmu_use_cpu_map(struct kgsl_mmu *mmu)
|
||||
{
|
||||
return 0;
|
||||
return mmu->pt_per_process;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* kgsl_mmu_base_addr() - Get gpu virtual address base.
|
||||
* @mmu: the mmu
|
||||
*
|
||||
* Returns the start address of the allocatable gpu
|
||||
* virtual address space. Other mappings that mirror
|
||||
* the CPU address space are possible outside this range.
|
||||
*/
|
||||
static inline unsigned int kgsl_mmu_get_base_addr(void)
|
||||
static inline unsigned int kgsl_mmu_get_base_addr(struct kgsl_mmu *mmu)
|
||||
{
|
||||
if (KGSL_MMU_TYPE_GPU == kgsl_mmu_get_mmutype()
|
||||
|| !kgsl_mmu_is_perprocess())
|
||||
return KGSL_PAGETABLE_BASE;
|
||||
/*
|
||||
* This is the start of the kernel address
|
||||
* space, so allocations from this range will
|
||||
* never conflict with userpace addresses
|
||||
*/
|
||||
return PAGE_OFFSET;
|
||||
return mmu->pt_base;
|
||||
}
|
||||
|
||||
/*
|
||||
* kgsl_mmu_get_ptsize() - Get gpu pagetable size
|
||||
* @mmu: the mmu
|
||||
*
|
||||
* Returns the usable size of the gpu allocatable
|
||||
* address space.
|
||||
*/
|
||||
static inline unsigned int kgsl_mmu_get_ptsize(void)
|
||||
static inline unsigned int kgsl_mmu_get_ptsize(struct kgsl_mmu *mmu)
|
||||
{
|
||||
/*
|
||||
* For IOMMU per-process pagetables, the allocatable range
|
||||
* and the kernel global range must both be outside
|
||||
* the userspace address range. There is a 1Mb gap
|
||||
* between these address ranges to make overrun
|
||||
* detection easier.
|
||||
* For the shared pagetable case use 2GB and because
|
||||
* mirroring the CPU address space is not possible and
|
||||
* we're better off with extra room.
|
||||
*/
|
||||
enum kgsl_mmutype mmu_type = kgsl_mmu_get_mmutype();
|
||||
|
||||
if (KGSL_MMU_TYPE_GPU == mmu_type)
|
||||
return CONFIG_MSM_KGSL_PAGE_TABLE_SIZE;
|
||||
else if (KGSL_MMU_TYPE_IOMMU == mmu_type) {
|
||||
if (kgsl_mmu_is_perprocess())
|
||||
return KGSL_IOMMU_GLOBAL_MEM_BASE
|
||||
- kgsl_mmu_get_base_addr() - SZ_1M;
|
||||
else
|
||||
return SZ_2G;
|
||||
}
|
||||
return 0;
|
||||
return mmu->pt_size;
|
||||
}
|
||||
|
||||
static inline int kgsl_mmu_sync_lock(struct kgsl_mmu *mmu,
|
||||
|
||||
Reference in New Issue
Block a user