diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gp10b')
-rw-r--r-- | drivers/gpu/nvgpu/gp10b/mm_gp10b.c | 77 |
1 files changed, 72 insertions, 5 deletions
diff --git a/drivers/gpu/nvgpu/gp10b/mm_gp10b.c b/drivers/gpu/nvgpu/gp10b/mm_gp10b.c index dc746153..9bfb290a 100644 --- a/drivers/gpu/nvgpu/gp10b/mm_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/mm_gp10b.c | |||
@@ -319,27 +319,94 @@ static void update_gmmu_pte_locked(struct vm_gk20a *vm, | |||
319 | pd_write(g, pd, pd_offset + 1, pte_w[1]); | 319 | pd_write(g, pd, pd_offset + 1, pte_w[1]); |
320 | } | 320 | } |
321 | 321 | ||
322 | #define GP10B_PDE0_ENTRY_SIZE 16 | ||
323 | |||
324 | /* | ||
325 | * Calculate the pgsz of the pde level | ||
326 | * Pascal+ implements a 5 level page table structure with only the last | ||
327 | * level having a different number of entries depending on whether it holds | ||
328 | * big pages or small pages. | ||
329 | */ | ||
330 | static enum gmmu_pgsz_gk20a gp10b_get_pde0_pgsz(struct gk20a *g, | ||
331 | struct nvgpu_gmmu_pd *pd, u32 pd_idx) | ||
332 | { | ||
333 | u32 pde_base = pd->mem_offs / sizeof(u32); | ||
334 | u32 pde_v[GP10B_PDE0_ENTRY_SIZE >> 2]; | ||
335 | u32 i; | ||
336 | enum gmmu_pgsz_gk20a pgsz = gmmu_nr_page_sizes; | ||
337 | |||
338 | if (!pd->mem) | ||
339 | return pgsz; | ||
340 | |||
341 | nvgpu_mem_begin(g, pd->mem); | ||
342 | for (i = 0; i < GP10B_PDE0_ENTRY_SIZE >> 2; i++) | ||
343 | pde_v[i] = nvgpu_mem_rd32(g, pd->mem, pde_base + i); | ||
344 | nvgpu_mem_end(g, pd->mem); | ||
345 | |||
346 | /* | ||
347 | * Check if the aperture AND address are set | ||
348 | */ | ||
349 | if (pde_v[2] & (gmmu_new_dual_pde_aperture_small_sys_mem_ncoh_f() || | ||
350 | gmmu_new_dual_pde_aperture_small_video_memory_f())) { | ||
351 | u64 addr = ((u64) (pde_v[2] & | ||
352 | gmmu_new_dual_pde_address_small_sys_f(~0)) << | ||
353 | gmmu_new_dual_pde_address_shift_v()) | | ||
354 | ((u64) pde_v[3] << 32); | ||
355 | |||
356 | if (addr) | ||
357 | pgsz = gmmu_page_size_small; | ||
358 | } | ||
359 | |||
360 | if (pde_v[0] & (gmmu_new_dual_pde_aperture_big_sys_mem_ncoh_f() | | ||
361 | gmmu_new_dual_pde_aperture_big_video_memory_f())) { | ||
362 | u64 addr = ((u64) (pde_v[0] & | ||
363 | gmmu_new_dual_pde_address_big_sys_f(~0)) << | ||
364 | gmmu_new_dual_pde_address_big_shift_v()) | | ||
365 | ((u64) pde_v[1] << 32); | ||
366 | if (addr) { | ||
367 | /* | ||
368 | * If small is set that means that somehow MM allowed | ||
369 | * both small and big to be set, the PDE is not valid | ||
370 | * and may be corrupted | ||
371 | */ | ||
372 | if (pgsz == gmmu_page_size_small) { | ||
373 | nvgpu_err(g, | ||
374 | "both small and big apertures enabled"); | ||
375 | return gmmu_nr_page_sizes; | ||
376 | } | ||
377 | } | ||
378 | pgsz = gmmu_page_size_big; | ||
379 | } | ||
380 | |||
381 | return pgsz; | ||
382 | } | ||
383 | |||
322 | static const struct gk20a_mmu_level gp10b_mm_levels[] = { | 384 | static const struct gk20a_mmu_level gp10b_mm_levels[] = { |
323 | {.hi_bit = {48, 48}, | 385 | {.hi_bit = {48, 48}, |
324 | .lo_bit = {47, 47}, | 386 | .lo_bit = {47, 47}, |
325 | .update_entry = update_gmmu_pde3_locked, | 387 | .update_entry = update_gmmu_pde3_locked, |
326 | .entry_size = 8}, | 388 | .entry_size = 8, |
389 | .get_pgsz = gk20a_get_pde_pgsz}, | ||
327 | {.hi_bit = {46, 46}, | 390 | {.hi_bit = {46, 46}, |
328 | .lo_bit = {38, 38}, | 391 | .lo_bit = {38, 38}, |
329 | .update_entry = update_gmmu_pde3_locked, | 392 | .update_entry = update_gmmu_pde3_locked, |
330 | .entry_size = 8}, | 393 | .entry_size = 8, |
394 | .get_pgsz = gk20a_get_pde_pgsz}, | ||
331 | {.hi_bit = {37, 37}, | 395 | {.hi_bit = {37, 37}, |
332 | .lo_bit = {29, 29}, | 396 | .lo_bit = {29, 29}, |
333 | .update_entry = update_gmmu_pde3_locked, | 397 | .update_entry = update_gmmu_pde3_locked, |
334 | .entry_size = 8}, | 398 | .entry_size = 8, |
399 | .get_pgsz = gk20a_get_pde_pgsz}, | ||
335 | {.hi_bit = {28, 28}, | 400 | {.hi_bit = {28, 28}, |
336 | .lo_bit = {21, 21}, | 401 | .lo_bit = {21, 21}, |
337 | .update_entry = update_gmmu_pde0_locked, | 402 | .update_entry = update_gmmu_pde0_locked, |
338 | .entry_size = 16}, | 403 | .entry_size = GP10B_PDE0_ENTRY_SIZE, |
404 | .get_pgsz = gp10b_get_pde0_pgsz}, | ||
339 | {.hi_bit = {20, 20}, | 405 | {.hi_bit = {20, 20}, |
340 | .lo_bit = {12, 16}, | 406 | .lo_bit = {12, 16}, |
341 | .update_entry = update_gmmu_pte_locked, | 407 | .update_entry = update_gmmu_pte_locked, |
342 | .entry_size = 8}, | 408 | .entry_size = 8, |
409 | .get_pgsz = gk20a_get_pte_pgsz}, | ||
343 | {.update_entry = NULL} | 410 | {.update_entry = NULL} |
344 | }; | 411 | }; |
345 | 412 | ||