summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/mm/gmmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/common/mm/gmmu.c')
-rw-r--r--drivers/gpu/nvgpu/common/mm/gmmu.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/common/mm/gmmu.c b/drivers/gpu/nvgpu/common/mm/gmmu.c
index 748e9f45..a04e501f 100644
--- a/drivers/gpu/nvgpu/common/mm/gmmu.c
+++ b/drivers/gpu/nvgpu/common/mm/gmmu.c
@@ -36,6 +36,9 @@
36 36
37#include "gk20a/mm_gk20a.h" 37#include "gk20a/mm_gk20a.h"
38 38
39// XXX: Shouldn't really be here! Needed for __nvgpu_update_paddr()
40#include <nvgpu/hw/gp10b/hw_gmmu_gp10b.h>
41
39#define __gmmu_dbg(g, attrs, fmt, args...) \ 42#define __gmmu_dbg(g, attrs, fmt, args...) \
40 do { \ 43 do { \
41 if (attrs->debug) { \ 44 if (attrs->debug) { \
@@ -938,3 +941,54 @@ int __nvgpu_set_pte(struct gk20a *g, struct vm_gk20a *vm, u64 vaddr, u32 *pte)
938 941
939 return 0; 942 return 0;
940} 943}
944
945u64 pgsz_enum_to_bytes(int sz) {
946 if (sz == GMMU_PAGE_SIZE_SMALL)
947 return SZ_4K;
948 else
949 return SZ_64K; // Dangerous! Big pages may also be 128k. Should check ram_in_big_page_size... registers.
950}
951
952// Caller is responsible for TLB/L2 flushing so that this can be called
953// repeatedly with low overhead.
954int __nvgpu_update_paddr(struct gk20a *g, struct vm_gk20a *vm, u64 vaddr, u64 paddr)
955{
956 struct nvgpu_gmmu_pd *pd;
957 u32 pd_idx, pd_offs;
958 int err;
959 u32 pte[2]; // Safe for at least gv11b
960 struct nvgpu_gmmu_attrs attrs = {
961 .pgsz = 0,
962 };
963// u32 pte_orig[2];
964
965 // Get existing pte entry and location
966 err = __nvgpu_locate_pte(g, vm, &vm->pdb,
967 vaddr, 0, &attrs,
968 pte, &pd, &pd_idx, &pd_offs);
969 if (unlikely(err)) {
970 printk(KERN_ERR "nvgpu: Unable to find PTE for vaddr %llx in __nvgpu_update_paddr()\n", vaddr);
971 return err;
972 }
973 // TODO: Verify that the PTE is actually in SYSMEM
974// pte_orig[0] = pte[0];
975// pte_orig[1] = pte[1];
976
977 // Following logic is borrowed from __update_pte() for gp10b+
978 // TODO: Make this work for gk20a-gp10b!
979 // Zero-out the address field
980 pte[0] &= ~gmmu_new_pte_address_sys_f(~0 >> gmmu_new_pte_address_shift_v());
981 pte[1] &= ~(~0U >> (24 + gmmu_new_pte_address_shift_v()));
982 // Write new address (upper and lower bits)
983 pte[0] |= gmmu_new_pte_address_sys_f(paddr >> gmmu_new_pte_address_shift_v());
984 pte[1] |= paddr >> (24 + gmmu_new_pte_address_shift_v());
985 // Commit to the page tables
986 pd_write(g, pd, pd_offs, pte[0]);
987 pd_write(g, pd, pd_offs + 1, pte[1]);
988 nvgpu_wmb(); // XXX: Is this needed?
989// printk(KERN_INFO "nvgpu: Mapped vaddr %llx @ paddr %llx. %lluKb pg. [%08x, %08x]\n", vaddr, paddr, pgsz_enum_to_bytes(attrs.pgsz)/1024, pte[1], pte[0]);
990// if (pte_orig[0] != pte[0] || pte_orig[1] != pte[1]) {
991// printk(KERN_INFO "nvgpu: Updated PTE entry from {%x,%x} to {%x, %x}\n", pte_orig[0], pte_orig[1], pte[0], pte[1]);
992// }
993 return pgsz_enum_to_bytes(attrs.pgsz);
994}