value = HAS_WT(dev_priv);
                break;
        case I915_PARAM_HAS_ALIASING_PPGTT:
-               value = USES_PPGTT(dev_priv);
+               value = min_t(int, INTEL_PPGTT(dev_priv), I915_GEM_PPGTT_FULL);
                break;
        case I915_PARAM_HAS_SEMAPHORES:
                value = HAS_LEGACY_SEMAPHORES(dev_priv);
 
 static void intel_sanitize_options(struct drm_i915_private *dev_priv)
 {
-       /*
-        * i915.enable_ppgtt is read-only, so do an early pass to validate the
-        * user's requested state against the hardware/driver capabilities.  We
-        * do this now so that we can print out any log messages once rather
-        * than every time we check intel_enable_ppgtt().
-        */
-       i915_modparams.enable_ppgtt =
-               intel_sanitize_enable_ppgtt(dev_priv,
-                                           i915_modparams.enable_ppgtt);
-       DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915_modparams.enable_ppgtt);
-
        intel_gvt_sanitize_options(dev_priv);
 }
 
 
        intel_device_info_runtime_init(mkwrite_device_info(dev_priv));
 
+       if (HAS_PPGTT(dev_priv)) {
+               if (intel_vgpu_active(dev_priv) &&
+                   !intel_vgpu_has_full_48bit_ppgtt(dev_priv)) {
+                       i915_report_error(dev_priv,
+                                         "incompatible vGPU found, support for isolated ppGTT required\n");
+                       return -ENXIO;
+               }
+       }
+
        intel_sanitize_options(dev_priv);
 
        i915_perf_init(dev_priv);
 
 
 #define HAS_EXECLISTS(dev_priv) HAS_LOGICAL_RING_CONTEXTS(dev_priv)
 
-#define USES_PPGTT(dev_priv)           (i915_modparams.enable_ppgtt)
-#define USES_FULL_PPGTT(dev_priv)      (i915_modparams.enable_ppgtt >= 2)
-#define USES_FULL_48BIT_PPGTT(dev_priv)        (i915_modparams.enable_ppgtt == 3)
+#define INTEL_PPGTT(dev_priv) (INTEL_INFO(dev_priv)->ppgtt)
+#define HAS_PPGTT(dev_priv) \
+       (INTEL_PPGTT(dev_priv) != INTEL_PPGTT_NONE)
+#define HAS_FULL_PPGTT(dev_priv) \
+       (INTEL_PPGTT(dev_priv) >= INTEL_PPGTT_FULL)
+#define HAS_FULL_48BIT_PPGTT(dev_priv) \
+       (INTEL_PPGTT(dev_priv) >= INTEL_PPGTT_FULL_4LVL)
+
 #define HAS_PAGE_SIZES(dev_priv, sizes) ({ \
        GEM_BUG_ON((sizes) == 0); \
        ((sizes) & ~(dev_priv)->info.page_sizes) == 0; \
        return IS_BROXTON(dev_priv) && intel_vtd_active();
 }
 
-int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,
-                               int enable_ppgtt);
-
 /* i915_drv.c */
 void __printf(3, 4)
 __i915_printk(struct drm_i915_private *dev_priv, const char *level,
 
        if (IS_ERR(ctx))
                return ctx;
 
-       if (USES_FULL_PPGTT(dev_priv)) {
+       if (HAS_FULL_PPGTT(dev_priv)) {
                struct i915_hw_ppgtt *ppgtt;
 
                ppgtt = i915_ppgtt_create(dev_priv, file_priv);
 
        i915->ggtt.invalidate(i915);
 }
 
-int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,
-                               int enable_ppgtt)
-{
-       bool has_full_ppgtt;
-       bool has_full_48bit_ppgtt;
-
-       if (!dev_priv->info.has_aliasing_ppgtt)
-               return 0;
-
-       has_full_ppgtt = dev_priv->info.has_full_ppgtt;
-       has_full_48bit_ppgtt = dev_priv->info.has_full_48bit_ppgtt;
-
-       if (intel_vgpu_active(dev_priv)) {
-               /* GVT-g has no support for 32bit ppgtt */
-               has_full_ppgtt = false;
-               has_full_48bit_ppgtt = intel_vgpu_has_full_48bit_ppgtt(dev_priv);
-       }
-
-       /*
-        * We don't allow disabling PPGTT for gen8+ as it's a requirement for
-        * execlists, the sole mechanism available to submit work.
-        */
-       if (enable_ppgtt == 0 && !HAS_EXECLISTS(dev_priv))
-               return 0;
-
-       if (enable_ppgtt == 1)
-               return 1;
-
-       if (enable_ppgtt == 2 && has_full_ppgtt)
-               return 2;
-
-       if (enable_ppgtt == 3 && has_full_48bit_ppgtt)
-               return 3;
-
-       /* Disable ppgtt on SNB if VT-d is on. */
-       if (IS_GEN6(dev_priv) && intel_vtd_active()) {
-               DRM_INFO("Disabling PPGTT because VT-d is on\n");
-               return 0;
-       }
-
-       if (has_full_48bit_ppgtt)
-               return 3;
-
-       if (has_full_ppgtt)
-               return 2;
-
-       return 1;
-}
-
 static int ppgtt_bind_vma(struct i915_vma *vma,
                          enum i915_cache_level cache_level,
                          u32 unused)
        ppgtt->vm.i915 = i915;
        ppgtt->vm.dma = &i915->drm.pdev->dev;
 
-       ppgtt->vm.total = USES_FULL_48BIT_PPGTT(i915) ?
+       ppgtt->vm.total = HAS_FULL_48BIT_PPGTT(i915) ?
                1ULL << 48 :
                1ULL << 32;
 
                  ppgtt->pd_addr + pde);
 }
 
-static void gen8_ppgtt_enable(struct drm_i915_private *dev_priv)
-{
-       struct intel_engine_cs *engine;
-       enum intel_engine_id id;
-
-       for_each_engine(engine, dev_priv, id) {
-               u32 four_level = USES_FULL_48BIT_PPGTT(dev_priv) ?
-                                GEN8_GFX_PPGTT_48B : 0;
-               I915_WRITE(RING_MODE_GEN7(engine),
-                          _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level));
-       }
-}
-
 static void gen7_ppgtt_enable(struct drm_i915_private *dev_priv)
 {
        struct intel_engine_cs *engine;
        ecochk = I915_READ(GAM_ECOCHK);
        I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT | ECOCHK_PPGTT_CACHE64B);
 
-       I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
+       if (HAS_PPGTT(dev_priv)) /* may be disabled for VT-d */
+               I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
 }
 
 /* PPGTT support for Sandybdrige/Gen6 and later */
 {
        gtt_write_workarounds(dev_priv);
 
-       /* In the case of execlists, PPGTT is enabled by the context descriptor
-        * and the PDPs are contained within the context itself.  We don't
-        * need to do anything here. */
-       if (HAS_LOGICAL_RING_CONTEXTS(dev_priv))
-               return 0;
-
-       if (!USES_PPGTT(dev_priv))
-               return 0;
-
        if (IS_GEN6(dev_priv))
                gen6_ppgtt_enable(dev_priv);
        else if (IS_GEN7(dev_priv))
                gen7_ppgtt_enable(dev_priv);
-       else if (INTEL_GEN(dev_priv) >= 8)
-               gen8_ppgtt_enable(dev_priv);
-       else
-               MISSING_CASE(INTEL_GEN(dev_priv));
 
        return 0;
 }
        /* And finally clear the reserved guard page */
        ggtt->vm.clear_range(&ggtt->vm, ggtt->vm.total - PAGE_SIZE, PAGE_SIZE);
 
-       if (USES_PPGTT(dev_priv) && !USES_FULL_PPGTT(dev_priv)) {
+       if (INTEL_PPGTT(dev_priv) == INTEL_PPGTT_ALIASING) {
                ret = i915_gem_init_aliasing_ppgtt(dev_priv);
                if (ret)
                        goto err;
        ppat->match = bdw_private_pat_match;
        ppat->clear_value = GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3);
 
-       if (!USES_PPGTT(ppat->i915)) {
+       if (!HAS_PPGTT(ppat->i915)) {
                /* Spec: "For GGTT, there is NO pat_sel[2:0] from the entry,
                 * so RTL will always use the value corresponding to
                 * pat_sel = 000".
        ggtt->vm.cleanup = gen6_gmch_remove;
        ggtt->vm.insert_page = gen8_ggtt_insert_page;
        ggtt->vm.clear_range = nop_clear_range;
-       if (!USES_FULL_PPGTT(dev_priv) || intel_scanout_needs_vtd_wa(dev_priv))
+       if (intel_scanout_needs_vtd_wa(dev_priv))
                ggtt->vm.clear_range = gen8_ggtt_clear_range;
 
        ggtt->vm.insert_entries = gen8_ggtt_insert_entries;
        /* Only VLV supports read-only GGTT mappings */
        ggtt->vm.has_read_only = IS_VALLEYVIEW(dev_priv);
 
-       if (!HAS_LLC(dev_priv) && !USES_PPGTT(dev_priv))
+       if (!HAS_LLC(dev_priv) && !HAS_PPGTT(dev_priv))
                ggtt->vm.mm.color_adjust = i915_gtt_color_adjust;
        mutex_unlock(&dev_priv->drm.struct_mutex);
 
 
                        err_printf(m, "  SYNC_2: 0x%08x\n",
                                   ee->semaphore_mboxes[2]);
        }
-       if (USES_PPGTT(m->i915)) {
+       if (HAS_PPGTT(m->i915)) {
                err_printf(m, "  GFX_MODE: 0x%08x\n", ee->vm_info.gfx_mode);
 
                if (INTEL_GEN(m->i915) >= 8) {
        ee->reset_count = i915_reset_engine_count(&dev_priv->gpu_error,
                                                  engine);
 
-       if (USES_PPGTT(dev_priv)) {
+       if (HAS_PPGTT(dev_priv)) {
                int i;
 
                ee->vm_info.gfx_mode = I915_READ(RING_MODE_GEN7(engine));
 
        "WARNING: Disabling this can cause system wide hangs. "
        "(default: true)");
 
-i915_param_named_unsafe(enable_ppgtt, int, 0400,
-       "Override PPGTT usage. "
-       "(-1=auto [default], 0=disabled, 1=aliasing, 2=full, 3=full with extended address space)");
-
 i915_param_named_unsafe(enable_psr, int, 0600,
        "Enable PSR "
        "(0=disabled, 1=enabled) "
 
        param(int, vbt_sdvo_panel_type, -1) \
        param(int, enable_dc, -1) \
        param(int, enable_fbc, -1) \
-       param(int, enable_ppgtt, -1) \
        param(int, enable_psr, -1) \
        param(int, disable_power_well, -1) \
        param(int, enable_ips, 1) \
 
        .has_llc = 1, \
        .has_rc6 = 1, \
        .has_rc6p = 1, \
-       .has_aliasing_ppgtt = 1, \
+       .ppgtt = INTEL_PPGTT_ALIASING, \
        GEN_DEFAULT_PIPEOFFSETS, \
        GEN_DEFAULT_PAGE_SIZES, \
        CURSOR_OFFSETS
        .has_llc = 1, \
        .has_rc6 = 1, \
        .has_rc6p = 1, \
-       .has_aliasing_ppgtt = 1, \
-       .has_full_ppgtt = 1, \
+       .ppgtt = INTEL_PPGTT_FULL, \
        GEN_DEFAULT_PIPEOFFSETS, \
        GEN_DEFAULT_PAGE_SIZES, \
        IVB_CURSOR_OFFSETS
        .has_rc6 = 1,
        .has_gmch_display = 1,
        .has_hotplug = 1,
-       .has_aliasing_ppgtt = 1,
-       .has_full_ppgtt = 1,
+       .ppgtt = INTEL_PPGTT_FULL,
        .has_snoop = true,
        .has_coherent_ggtt = false,
        .ring_mask = RENDER_RING | BSD_RING | BLT_RING,
        .page_sizes = I915_GTT_PAGE_SIZE_4K | \
                      I915_GTT_PAGE_SIZE_2M, \
        .has_logical_ring_contexts = 1, \
-       .has_full_48bit_ppgtt = 1, \
+       .ppgtt = INTEL_PPGTT_FULL_4LVL, \
        .has_64bit_reloc = 1, \
        .has_reset_engine = 1
 
        .has_rc6 = 1,
        .has_logical_ring_contexts = 1,
        .has_gmch_display = 1,
-       .has_aliasing_ppgtt = 1,
-       .has_full_ppgtt = 1,
+       .ppgtt = INTEL_PPGTT_FULL,
        .has_reset_engine = 1,
        .has_snoop = true,
        .has_coherent_ggtt = false,
        .has_logical_ring_contexts = 1, \
        .has_logical_ring_preemption = 1, \
        .has_guc = 1, \
-       .has_aliasing_ppgtt = 1, \
-       .has_full_ppgtt = 1, \
-       .has_full_48bit_ppgtt = 1, \
+       .ppgtt = INTEL_PPGTT_FULL_4LVL, \
        .has_reset_engine = 1, \
        .has_snoop = true, \
        .has_coherent_ggtt = false, \
 
        else if (INTEL_GEN(dev_priv) >= 11)
                gen11_sseu_info_init(dev_priv);
 
+       if (IS_GEN6(dev_priv) && intel_vtd_active()) {
+               DRM_INFO("Disabling ppGTT for VT-d support\n");
+               info->ppgtt = INTEL_PPGTT_NONE;
+       }
+
        /* Initialize command stream timestamp frequency */
        info->cs_timestamp_frequency_khz = read_timestamp_frequency(dev_priv);
 }
 
 #ifndef _INTEL_DEVICE_INFO_H_
 #define _INTEL_DEVICE_INFO_H_
 
+#include <uapi/drm/i915_drm.h>
+
 #include "intel_display.h"
 
 struct drm_printer;
        INTEL_MAX_PLATFORMS
 };
 
+enum intel_ppgtt {
+       INTEL_PPGTT_NONE = I915_GEM_PPGTT_NONE,
+       INTEL_PPGTT_ALIASING = I915_GEM_PPGTT_ALIASING,
+       INTEL_PPGTT_FULL = I915_GEM_PPGTT_FULL,
+       INTEL_PPGTT_FULL_4LVL,
+};
+
 #define DEV_INFO_FOR_EACH_FLAG(func) \
        func(is_mobile); \
        func(is_lp); \
        func(is_alpha_support); \
        /* Keep has_* in alphabetical order */ \
        func(has_64bit_reloc); \
-       func(has_aliasing_ppgtt); \
        func(has_csr); \
        func(has_ddi); \
        func(has_dp_mst); \
        func(has_reset_engine); \
        func(has_fbc); \
        func(has_fpga_dbg); \
-       func(has_full_ppgtt); \
-       func(has_full_48bit_ppgtt); \
        func(has_gmch_display); \
        func(has_guc); \
        func(has_guc_ct); \
        enum intel_platform platform;
        u32 platform_mask;
 
+       enum intel_ppgtt ppgtt;
        unsigned int page_sizes; /* page sizes supported by the HW */
 
        u32 display_mmio_offset;
 
 
 static u64 execlists_update_context(struct i915_request *rq)
 {
+       struct i915_hw_ppgtt *ppgtt = rq->gem_context->ppgtt;
        struct intel_context *ce = rq->hw_context;
-       struct i915_hw_ppgtt *ppgtt =
-               rq->gem_context->ppgtt ?: rq->i915->mm.aliasing_ppgtt;
        u32 *reg_state = ce->lrc_reg_state;
 
        reg_state[CTX_RING_TAIL+1] = intel_ring_set_tail(rq->ring, rq->tail);
        struct intel_context *ce = to_intel_context(ctx, engine);
 
        lockdep_assert_held(&ctx->i915->drm.struct_mutex);
-       GEM_BUG_ON(!(ctx->ppgtt ?: ctx->i915->mm.aliasing_ppgtt));
+       GEM_BUG_ON(!ctx->ppgtt);
 
        if (likely(ce->pin_count++))
                return ce;
         * it is unsafe in case of lite-restore (because the ctx is
         * not idle). PML4 is allocated during ppgtt init so this is
         * not needed in 48-bit.*/
-       if (rq->gem_context->ppgtt &&
-           (intel_engine_flag(rq->engine) & rq->gem_context->ppgtt->pd_dirty_rings) &&
+       if ((intel_engine_flag(rq->engine) & rq->gem_context->ppgtt->pd_dirty_rings) &&
            !i915_vm_is_48bit(&rq->gem_context->ppgtt->vm) &&
            !intel_vgpu_active(rq->i915)) {
                ret = intel_logical_ring_emit_pdps(rq);
                                     struct intel_ring *ring)
 {
        struct drm_i915_private *dev_priv = engine->i915;
-       struct i915_hw_ppgtt *ppgtt = ctx->ppgtt ?: dev_priv->mm.aliasing_ppgtt;
        u32 base = engine->mmio_base;
        bool rcs = engine->class == RENDER_CLASS;
 
        CTX_REG(regs, CTX_PDP0_UDW, GEN8_RING_PDP_UDW(engine, 0), 0);
        CTX_REG(regs, CTX_PDP0_LDW, GEN8_RING_PDP_LDW(engine, 0), 0);
 
-       if (i915_vm_is_48bit(&ppgtt->vm)) {
+       if (i915_vm_is_48bit(&ctx->ppgtt->vm)) {
                /* 64b PPGTT (48bit canonical)
                 * PDP0_DESCRIPTOR contains the base address to PML4 and
                 * other PDP Descriptors are ignored.
                 */
-               ASSIGN_CTX_PML4(ppgtt, regs);
+               ASSIGN_CTX_PML4(ctx->ppgtt, regs);
        }
 
        if (rcs) {
 
         * huge-gtt-pages.
         */
 
-       if (!USES_FULL_48BIT_PPGTT(dev_priv)) {
+       if (!HAS_FULL_48BIT_PPGTT(dev_priv)) {
                pr_info("48b PPGTT not supported, skipping\n");
                return 0;
        }
                SUBTEST(igt_mock_ppgtt_huge_fill),
                SUBTEST(igt_mock_ppgtt_64K),
        };
-       int saved_ppgtt = i915_modparams.enable_ppgtt;
        struct drm_i915_private *dev_priv;
-       struct pci_dev *pdev;
        struct i915_hw_ppgtt *ppgtt;
+       struct pci_dev *pdev;
        int err;
 
        dev_priv = mock_gem_device();
                return -ENOMEM;
 
        /* Pretend to be a device which supports the 48b PPGTT */
-       i915_modparams.enable_ppgtt = 3;
+       mkwrite_device_info(dev_priv)->ppgtt = INTEL_PPGTT_FULL_4LVL;
 
        pdev = dev_priv->drm.pdev;
        dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(39));
 
 out_unlock:
        mutex_unlock(&dev_priv->drm.struct_mutex);
-
-       i915_modparams.enable_ppgtt = saved_ppgtt;
-
        drm_dev_put(&dev_priv->drm);
 
        return err;
        struct i915_gem_context *ctx;
        int err;
 
-       if (!USES_PPGTT(dev_priv)) {
+       if (!HAS_PPGTT(dev_priv)) {
                pr_info("PPGTT not supported, skipping live-selftests\n");
                return 0;
        }
 
        IGT_TIMEOUT(end_time);
        LIST_HEAD(objects);
        unsigned long ncontexts, ndwords, dw;
-       bool first_shared_gtt = true;
        int err = -ENODEV;
 
        /*
                struct i915_gem_context *ctx;
                unsigned int id;
 
-               if (first_shared_gtt) {
-                       ctx = __create_hw_context(i915, file->driver_priv);
-                       first_shared_gtt = false;
-               } else {
-                       ctx = i915_gem_create_context(i915, file->driver_priv);
-               }
+               ctx = i915_gem_create_context(i915, file->driver_priv);
                if (IS_ERR(ctx)) {
                        err = PTR_ERR(ctx);
                        goto out_unlock;
        return err;
 }
 
-static int fake_aliasing_ppgtt_enable(struct drm_i915_private *i915)
-{
-       struct drm_i915_gem_object *obj;
-       int err;
-
-       err = i915_gem_init_aliasing_ppgtt(i915);
-       if (err)
-               return err;
-
-       list_for_each_entry(obj, &i915->mm.bound_list, mm.link) {
-               struct i915_vma *vma;
-
-               vma = i915_vma_instance(obj, &i915->ggtt.vm, NULL);
-               if (IS_ERR(vma))
-                       continue;
-
-               vma->flags &= ~I915_VMA_LOCAL_BIND;
-       }
-
-       return 0;
-}
-
-static void fake_aliasing_ppgtt_disable(struct drm_i915_private *i915)
-{
-       i915_gem_fini_aliasing_ppgtt(i915);
-}
-
 int i915_gem_context_mock_selftests(void)
 {
        static const struct i915_subtest tests[] = {
                SUBTEST(igt_ctx_exec),
                SUBTEST(igt_ctx_readonly),
        };
-       bool fake_alias = false;
-       int err;
 
        if (i915_terminally_wedged(&dev_priv->gpu_error))
                return 0;
 
-       /* Install a fake aliasing gtt for exercise */
-       if (USES_PPGTT(dev_priv) && !dev_priv->mm.aliasing_ppgtt) {
-               mutex_lock(&dev_priv->drm.struct_mutex);
-               err = fake_aliasing_ppgtt_enable(dev_priv);
-               mutex_unlock(&dev_priv->drm.struct_mutex);
-               if (err)
-                       return err;
-
-               GEM_BUG_ON(!dev_priv->mm.aliasing_ppgtt);
-               fake_alias = true;
-       }
-
-       err = i915_subtests(tests, dev_priv);
-
-       if (fake_alias) {
-               mutex_lock(&dev_priv->drm.struct_mutex);
-               fake_aliasing_ppgtt_disable(dev_priv);
-               mutex_unlock(&dev_priv->drm.struct_mutex);
-       }
-
-       return err;
+       return i915_subtests(tests, dev_priv);
 }
 
         * where the GTT space of the request is separate from the GGTT
         * allocation required to build the request.
         */
-       if (!USES_FULL_PPGTT(i915))
+       if (!HAS_FULL_PPGTT(i915))
                return 0;
 
        mutex_lock(&i915->drm.struct_mutex);
 
 
        /* Allocate a ppggt and try to fill the entire range */
 
-       if (!USES_PPGTT(dev_priv))
+       if (!HAS_PPGTT(dev_priv))
                return 0;
 
        ppgtt = __hw_ppgtt_create(dev_priv);
        IGT_TIMEOUT(end_time);
        int err;
 
-       if (!USES_FULL_PPGTT(dev_priv))
+       if (!HAS_FULL_PPGTT(dev_priv))
                return 0;
 
        file = mock_file(dev_priv);
 
        int irq_seq;
 } drm_i915_irq_wait_t;
 
+/*
+ * Different modes of per-process Graphics Translation Table,
+ * see I915_PARAM_HAS_ALIASING_PPGTT
+ */
+#define I915_GEM_PPGTT_NONE    0
+#define I915_GEM_PPGTT_ALIASING        1
+#define I915_GEM_PPGTT_FULL    2
+
 /* Ioctl to query kernel params:
  */
 #define I915_PARAM_IRQ_ACTIVE            1