drm/i915/gtt: Add read only pages to gen8_pte_encode
commit 25dda4dabeeb12af5209b0183c788ef2a88dabbe upstream. We can set a bit inside the ppGTT PTE to indicate a page is read-only; writes from the GPU will be discarded. We can use this to protect pages and in particular support read-only userptr mappings (necessary for importing PROT_READ vma). Signed-off-by: Jon Bloomfield <jon.bloomfield@intel.com> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Matthew Auld <matthew.william.auld@gmail.com> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Reviewed-by: Matthew Auld <matthew.william.auld@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180712185315.3288-1-chris@chris-wilson.co.uk Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
b575bf8be3
commit
6d0cfddc7a
1 changed files with 13 additions and 9 deletions
|
@ -172,11 +172,14 @@ static void ppgtt_unbind_vma(struct i915_vma *vma)
|
||||||
|
|
||||||
static gen8_pte_t gen8_pte_encode(dma_addr_t addr,
|
static gen8_pte_t gen8_pte_encode(dma_addr_t addr,
|
||||||
enum i915_cache_level level,
|
enum i915_cache_level level,
|
||||||
bool valid)
|
bool valid, u32 flags)
|
||||||
{
|
{
|
||||||
gen8_pte_t pte = valid ? _PAGE_PRESENT | _PAGE_RW : 0;
|
gen8_pte_t pte = valid ? _PAGE_PRESENT | _PAGE_RW : 0;
|
||||||
pte |= addr;
|
pte |= addr;
|
||||||
|
|
||||||
|
if (unlikely(flags & PTE_READ_ONLY))
|
||||||
|
pte &= ~_PAGE_RW;
|
||||||
|
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case I915_CACHE_NONE:
|
case I915_CACHE_NONE:
|
||||||
pte |= PPAT_UNCACHED_INDEX;
|
pte |= PPAT_UNCACHED_INDEX;
|
||||||
|
@ -460,7 +463,7 @@ static void gen8_initialize_pt(struct i915_address_space *vm,
|
||||||
gen8_pte_t scratch_pte;
|
gen8_pte_t scratch_pte;
|
||||||
|
|
||||||
scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
|
scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
|
||||||
I915_CACHE_LLC, true);
|
I915_CACHE_LLC, true, 0);
|
||||||
|
|
||||||
fill_px(vm->dev, pt, scratch_pte);
|
fill_px(vm->dev, pt, scratch_pte);
|
||||||
}
|
}
|
||||||
|
@ -757,8 +760,9 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
|
||||||
{
|
{
|
||||||
struct i915_hw_ppgtt *ppgtt =
|
struct i915_hw_ppgtt *ppgtt =
|
||||||
container_of(vm, struct i915_hw_ppgtt, base);
|
container_of(vm, struct i915_hw_ppgtt, base);
|
||||||
gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
|
gen8_pte_t scratch_pte =
|
||||||
I915_CACHE_LLC, use_scratch);
|
gen8_pte_encode(px_dma(vm->scratch_page),
|
||||||
|
I915_CACHE_LLC, use_scratch, 0);
|
||||||
|
|
||||||
if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
|
if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
|
||||||
gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length,
|
gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length,
|
||||||
|
@ -799,7 +803,7 @@ gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm,
|
||||||
|
|
||||||
pt_vaddr[pte] =
|
pt_vaddr[pte] =
|
||||||
gen8_pte_encode(sg_page_iter_dma_address(sg_iter),
|
gen8_pte_encode(sg_page_iter_dma_address(sg_iter),
|
||||||
cache_level, true);
|
cache_level, true, 0);
|
||||||
if (++pte == GEN8_PTES) {
|
if (++pte == GEN8_PTES) {
|
||||||
kunmap_px(ppgtt, pt_vaddr);
|
kunmap_px(ppgtt, pt_vaddr);
|
||||||
pt_vaddr = NULL;
|
pt_vaddr = NULL;
|
||||||
|
@ -1447,7 +1451,7 @@ static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
|
||||||
uint64_t start = ppgtt->base.start;
|
uint64_t start = ppgtt->base.start;
|
||||||
uint64_t length = ppgtt->base.total;
|
uint64_t length = ppgtt->base.total;
|
||||||
gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
|
gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
|
||||||
I915_CACHE_LLC, true);
|
I915_CACHE_LLC, true, 0);
|
||||||
|
|
||||||
if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
|
if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
|
||||||
gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m);
|
gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m);
|
||||||
|
@ -2357,7 +2361,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
|
||||||
addr = sg_dma_address(sg_iter.sg) +
|
addr = sg_dma_address(sg_iter.sg) +
|
||||||
(sg_iter.sg_pgoffset << PAGE_SHIFT);
|
(sg_iter.sg_pgoffset << PAGE_SHIFT);
|
||||||
gen8_set_pte(>t_entries[i],
|
gen8_set_pte(>t_entries[i],
|
||||||
gen8_pte_encode(addr, level, true));
|
gen8_pte_encode(addr, level, true, 0));
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2370,7 +2374,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
|
||||||
*/
|
*/
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
WARN_ON(readq(>t_entries[i-1])
|
WARN_ON(readq(>t_entries[i-1])
|
||||||
!= gen8_pte_encode(addr, level, true));
|
!= gen8_pte_encode(addr, level, true, 0));
|
||||||
|
|
||||||
/* This next bit makes the above posting read even more important. We
|
/* This next bit makes the above posting read even more important. We
|
||||||
* want to flush the TLBs only after we're certain all the PTE updates
|
* want to flush the TLBs only after we're certain all the PTE updates
|
||||||
|
@ -2444,7 +2448,7 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
|
||||||
|
|
||||||
scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
|
scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
|
||||||
I915_CACHE_LLC,
|
I915_CACHE_LLC,
|
||||||
use_scratch);
|
use_scratch, 0);
|
||||||
for (i = 0; i < num_entries; i++)
|
for (i = 0; i < num_entries; i++)
|
||||||
gen8_set_pte(>t_base[i], scratch_pte);
|
gen8_set_pte(>t_base[i], scratch_pte);
|
||||||
readl(gtt_base);
|
readl(gtt_base);
|
||||||
|
|
Loading…
Add table
Reference in a new issue