mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-25 11:04:51 +03:00
gpu: nvgpu: add safety for vidmem addresses
Add new API set_vidmem_page_alloc() which sets BIT(0) in sg_dma_address() only for vidmem allocation Add and use new API get_vidmem_page_alloc() which receives scatterlist and returns pointer to vidmem allocation i.e. struct gk20a_page_alloc *alloc In this API, check if BIT(0) is set or not in sg_dma_address() before converting it to allocation address In gk20a_mm_smmu_vaddr_translate(), ensure that the address is pure IOVA address by verifying that BIT(0) is not set in that address Jira DNVGPU-22 Change-Id: Ib53ff4b63ac59a8d870bc01d0af59839c6143334 Signed-off-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-on: http://git-master/r/1216142 (cherry picked from commit 03c9fbdaa40746dc43335cd8fbe9f97ef2ef50c9) Reviewed-on: http://git-master/r/1219705 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
f036594190
commit
f919aab509
@@ -58,6 +58,34 @@
|
||||
static void gk20a_vidmem_clear_mem_worker(struct work_struct *work);
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
set_vidmem_page_alloc(struct scatterlist *sgl, u64 addr)
|
||||
{
|
||||
/* set bit 0 to indicate vidmem allocation */
|
||||
sg_dma_address(sgl) = (addr | 1ULL);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_vidmem_page_alloc(u64 addr)
|
||||
{
|
||||
return !!(addr & 1ULL);
|
||||
}
|
||||
|
||||
static inline struct gk20a_page_alloc *
|
||||
get_vidmem_page_alloc(struct scatterlist *sgl)
|
||||
{
|
||||
u64 addr;
|
||||
|
||||
addr = sg_dma_address(sgl);
|
||||
|
||||
if (is_vidmem_page_alloc(addr))
|
||||
addr = addr & ~1ULL;
|
||||
else
|
||||
WARN_ON(1);
|
||||
|
||||
return (struct gk20a_page_alloc *)(uintptr_t)addr;
|
||||
}
|
||||
|
||||
int gk20a_mem_begin(struct gk20a *g, struct mem_desc *mem)
|
||||
{
|
||||
void *cpu_va;
|
||||
@@ -149,8 +177,7 @@ static inline void pramin_access_batched(struct gk20a *g, struct mem_desc *mem,
|
||||
struct page_alloc_chunk *chunk = NULL;
|
||||
u32 byteoff, start_reg, until_end, n;
|
||||
|
||||
alloc = (struct gk20a_page_alloc *)(uintptr_t)
|
||||
sg_dma_address(mem->sgt->sgl);
|
||||
alloc = get_vidmem_page_alloc(mem->sgt->sgl);
|
||||
list_for_each_entry(chunk, &alloc->alloc_chunks, list_entry) {
|
||||
if (offset >= chunk->length)
|
||||
offset -= chunk->length;
|
||||
@@ -2197,8 +2224,7 @@ static u64 gk20a_mm_get_align(struct gk20a *g, struct scatterlist *sgl,
|
||||
u64 buf_addr;
|
||||
|
||||
if (aperture == APERTURE_VIDMEM) {
|
||||
struct gk20a_page_alloc *alloc = (struct gk20a_page_alloc *)
|
||||
(uintptr_t)sg_dma_address(sgl);
|
||||
struct gk20a_page_alloc *alloc = get_vidmem_page_alloc(sgl);
|
||||
struct page_alloc_chunk *chunk = NULL;
|
||||
|
||||
list_for_each_entry(chunk, &alloc->alloc_chunks, list_entry) {
|
||||
@@ -2914,8 +2940,7 @@ static int gk20a_gmmu_clear_vidmem_mem(struct gk20a *g, struct mem_desc *mem)
|
||||
if (g->mm.vidmem.ce_ctx_id == ~0)
|
||||
return -EINVAL;
|
||||
|
||||
alloc = (struct gk20a_page_alloc *)(uintptr_t)
|
||||
sg_dma_address(mem->sgt->sgl);
|
||||
alloc = get_vidmem_page_alloc(mem->sgt->sgl);
|
||||
|
||||
list_for_each_entry(chunk, &alloc->alloc_chunks, list_entry) {
|
||||
if (gk20a_last_fence)
|
||||
@@ -3038,7 +3063,7 @@ int gk20a_gmmu_alloc_attr_vid_at(struct gk20a *g, enum dma_attr attr,
|
||||
if (err)
|
||||
goto fail_kfree;
|
||||
|
||||
sg_dma_address(mem->sgt->sgl) = addr;
|
||||
set_vidmem_page_alloc(mem->sgt->sgl, addr);
|
||||
sg_set_page(mem->sgt->sgl, NULL, size, 0);
|
||||
|
||||
mem->size = size;
|
||||
@@ -3082,7 +3107,7 @@ static void gk20a_gmmu_free_attr_vid(struct gk20a *g, enum dma_attr attr,
|
||||
} else {
|
||||
gk20a_memset(g, mem, 0, 0, mem->size);
|
||||
gk20a_free(mem->allocator,
|
||||
sg_dma_address(mem->sgt->sgl));
|
||||
(u64)get_vidmem_page_alloc(mem->sgt->sgl));
|
||||
gk20a_free_sgtable(&mem->sgt);
|
||||
|
||||
mem->size = 0;
|
||||
@@ -3120,8 +3145,7 @@ u64 gk20a_mem_get_base_addr(struct gk20a *g, struct mem_desc *mem,
|
||||
u64 addr;
|
||||
|
||||
if (mem->aperture == APERTURE_VIDMEM) {
|
||||
alloc = (struct gk20a_page_alloc *)(uintptr_t)
|
||||
sg_dma_address(mem->sgt->sgl);
|
||||
alloc = get_vidmem_page_alloc(mem->sgt->sgl);
|
||||
|
||||
/* This API should not be used with > 1 chunks */
|
||||
WARN_ON(alloc->nr_chunks != 1);
|
||||
@@ -3159,7 +3183,7 @@ static void gk20a_vidmem_clear_mem_worker(struct work_struct *work)
|
||||
while ((mem = get_pending_mem_desc(mm)) != NULL) {
|
||||
gk20a_gmmu_clear_vidmem_mem(g, mem);
|
||||
gk20a_free(mem->allocator,
|
||||
sg_dma_address(mem->sgt->sgl));
|
||||
(u64)get_vidmem_page_alloc(mem->sgt->sgl));
|
||||
gk20a_free_sgtable(&mem->sgt);
|
||||
|
||||
WARN_ON(atomic_dec_return(&mm->vidmem.clears_pending) < 0);
|
||||
@@ -3400,6 +3424,9 @@ void gk20a_free_sgtable(struct sg_table **sgt)
|
||||
|
||||
u64 gk20a_mm_smmu_vaddr_translate(struct gk20a *g, dma_addr_t iova)
|
||||
{
|
||||
/* ensure it is not vidmem allocation */
|
||||
WARN_ON(is_vidmem_page_alloc((u64)iova));
|
||||
|
||||
if (device_is_iommuable(dev_from_gk20a(g)) &&
|
||||
g->ops.mm.get_physical_addr_bits)
|
||||
return iova | 1ULL << g->ops.mm.get_physical_addr_bits(g);
|
||||
@@ -3747,8 +3774,7 @@ static int update_gmmu_ptes_locked(struct vm_gk20a *vm,
|
||||
pgsz_idx, gpu_va, gpu_end-1, iova);
|
||||
|
||||
if (sgt) {
|
||||
alloc = (struct gk20a_page_alloc *)(uintptr_t)
|
||||
sg_dma_address(sgt->sgl);
|
||||
alloc = get_vidmem_page_alloc(sgt->sgl);
|
||||
|
||||
list_for_each_entry(chunk, &alloc->alloc_chunks,
|
||||
list_entry) {
|
||||
|
||||
Reference in New Issue
Block a user