gpu: nvgpu: Control comptagline assignment from kernel
Terje Bergstrom [Thu, 17 Dec 2015 18:12:21 +0000 (10:12 -0800)]
On Maxwell comptaglines are assigned per 128k, but preferred big page
size for graphics is 64k. Bit 16 of GPU VA is used for determining
which half of comptagline is used.

This creates problems if user space wants to map a page multiple times
and to arbitrary GPU VA. In one mapping the page might be mapped to
lower half of 128k comptagline, and in another mapping the page might
be mapped to upper half.

Turn on mode where MSB of comptagline in PTE is used instead of bit 16
for determining the comptagline lower/upper half selection.

Bug 1704834

Change-Id: If87e8f6ac0fc9c5624e80fa1ba2ceeb02781355b
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/924373
(cherry picked from commit e05803201fd2097e7185dac4554b9237965e5bc8)
Reviewed-on: http://git-master/r/998467
GVS: Gerrit_Virtual_Submit
Reviewed-by: Mathias Heyer <mheyer@nvidia.com>
Tested-by: Mathias Heyer <mheyer@nvidia.com>

drivers/gpu/nvgpu/gk20a/gk20a.h
drivers/gpu/nvgpu/gk20a/hw_gmmu_gk20a.h
drivers/gpu/nvgpu/gk20a/mm_gk20a.c
drivers/gpu/nvgpu/gk20a/mm_gk20a.h
drivers/gpu/nvgpu/gm20b/fb_gm20b.c
drivers/gpu/nvgpu/gm20b/hw_fb_gm20b.h
drivers/gpu/nvgpu/gm20b/hw_gmmu_gm20b.h

index def40ba..39718e5 100644 (file)
@@ -189,6 +189,7 @@ struct gpu_ops {
                void (*init_uncompressed_kind_map)(struct gk20a *g);
                void (*init_kind_attr)(struct gk20a *g);
                void (*set_mmu_page_size)(struct gk20a *g);
+               bool (*set_use_full_comp_tag_line)(struct gk20a *g);
                int (*compression_page_size)(struct gk20a *g);
                int (*compressible_page_size)(struct gk20a *g);
                void (*dump_vpr_wpr_info)(struct gk20a *g);
index 19e4438..d92f0d5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2012-2015, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -210,6 +210,10 @@ static inline u32 gmmu_pte_read_disable_true_f(void)
 {
        return 0x40000000;
 }
+static inline u32 gmmu_pte_comptagline_s(void)
+{
+       return 17;
+}
 static inline u32 gmmu_pte_comptagline_f(u32 v)
 {
        return (v & 0x1ffff) << 12;
index 36a95c7..76a3cee 100644 (file)
@@ -402,6 +402,10 @@ int gk20a_init_mm_setup_hw(struct gk20a *g)
        gk20a_dbg_fn("");
 
        g->ops.fb.set_mmu_page_size(g);
+       if (g->ops.fb.set_use_full_comp_tag_line)
+               mm->use_full_comp_tag_line =
+                       g->ops.fb.set_use_full_comp_tag_line(g);
+
 
        inst_pa = (u32)(inst_pa >> bar1_instance_block_shift_gk20a());
        gk20a_dbg_info("bar1 inst block ptr: 0x%08x",  (u32)inst_pa);
@@ -2289,6 +2293,11 @@ static int update_gmmu_pte_locked(struct vm_gk20a *vm,
                        gmmu_pte_kind_f(kind_v) |
                        gmmu_pte_comptagline_f(*ctag / ctag_granularity);
 
+               if (vm->mm->use_full_comp_tag_line && *iova & 0x10000) {
+                       pte_w[1] |= gmmu_pte_comptagline_f(
+                                       1 << (gmmu_pte_comptagline_s() - 1));
+               }
+
                if (rw_flag == gk20a_mem_flag_read_only) {
                        pte_w[0] |= gmmu_pte_read_only_true_f();
                        pte_w[1] |=
index b43a50b..54470f2 100644 (file)
@@ -322,6 +322,7 @@ struct mm_gk20a {
        void (*remove_support)(struct mm_gk20a *mm);
        bool sw_ready;
        int physical_bits;
+       bool use_full_comp_tag_line;
 #ifdef CONFIG_DEBUG_FS
        u32 ltc_enabled;
        u32 ltc_enabled_debug;
index 3d4604c..c65cd45 100644 (file)
@@ -91,6 +91,16 @@ static void gm20b_fb_set_mmu_page_size(struct gk20a *g)
        gk20a_writel(g, fb_mmu_ctrl_r(), fb_mmu_ctrl);
 }
 
+static bool gm20b_fb_set_use_full_comp_tag_line(struct gk20a *g)
+{
+       /* set large page size in fb */
+       u32 fb_mmu_ctrl = gk20a_readl(g, fb_mmu_ctrl_r());
+       fb_mmu_ctrl |= fb_mmu_ctrl_use_full_comp_tag_line_true_f();
+       gk20a_writel(g, fb_mmu_ctrl_r(), fb_mmu_ctrl);
+
+       return true;
+}
+
 static int gm20b_fb_compression_page_size(struct gk20a *g)
 {
        return SZ_128K;
@@ -135,6 +145,7 @@ void gm20b_init_fb(struct gpu_ops *gops)
        gops->fb.reset = fb_gk20a_reset;
        gops->fb.init_fs_state = fb_gm20b_init_fs_state;
        gops->fb.set_mmu_page_size = gm20b_fb_set_mmu_page_size;
+       gops->fb.set_use_full_comp_tag_line = gm20b_fb_set_use_full_comp_tag_line;
        gops->fb.compression_page_size = gm20b_fb_compression_page_size;
        gops->fb.compressible_page_size = gm20b_fb_compressible_page_size;
        gops->fb.dump_vpr_wpr_info = gm20b_fb_dump_vpr_wpr_info;
index 214306c..4f99a80 100644 (file)
@@ -94,6 +94,14 @@ static inline u32 fb_mmu_ctrl_use_pdb_big_page_size_false_f(void)
 {
        return 0x0;
 }
+static inline u32 fb_mmu_ctrl_use_full_comp_tag_line_v(u32 r)
+{
+       return (r >> 12) & 0x1;
+}
+static inline u32 fb_mmu_ctrl_use_full_comp_tag_line_true_f(void)
+{
+       return 0x1000;
+}
 static inline u32 fb_priv_mmu_phy_secure_r(void)
 {
        return 0x00100ce4;
index 32b6591..572f727 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2015, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -210,6 +210,10 @@ static inline u32 gmmu_pte_read_disable_true_f(void)
 {
        return 0x40000000;
 }
+static inline u32 gmmu_pte_comptagline_s(void)
+{
+       return 17;
+}
 static inline u32 gmmu_pte_comptagline_f(u32 v)
 {
        return (v & 0x1ffff) << 12;