forked from Minki/linux
drm/i915/lmem: add the fake lmem region
Intended for upstream testing so that we can still exercise the LMEM plumbing and !i915_ggtt_has_aperture paths. Smoke tested on Skull Canyon device. This works by allocating an intel_memory_region for a reserved portion of system memory, which we treat like LMEM. For the LMEMBAR we steal the aperture and 1:1 it map to the stolen region. To enable simply set the i915 modparam fake_lmem_start= on the kernel cmdline with the start of reserved region(see memmap=). The size of the region we can use is determined by the size of the mappable aperture, so the size of reserved region should be >= mappable_end. For now we only enable for the selftests. Depends on CONFIG_DRM_I915_UNSTABLE being enabled. eg. memmap=2G$16G i915.fake_lmem_start=0x400000000 v2: make fake_lmem_start an i915 modparam Signed-off-by: Matthew Auld <matthew.auld@intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Abdiel Janulgue <abdiel.janulgue@linux.intel.com> Cc: Arkadiusz Hiler <arkadiusz.hiler@intel.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20191030173320.8850-1-matthew.auld@intel.com
This commit is contained in:
parent
4974826482
commit
1629224324
@ -19,3 +19,11 @@ config DRM_I915_UNSTABLE
|
|||||||
Recommended for driver developers _only_.
|
Recommended for driver developers _only_.
|
||||||
|
|
||||||
If in the slightest bit of doubt, say "N".
|
If in the slightest bit of doubt, say "N".
|
||||||
|
|
||||||
|
config DRM_I915_UNSTABLE_FAKE_LMEM
|
||||||
|
bool "Enable the experimental fake lmem"
|
||||||
|
depends on DRM_I915_UNSTABLE
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Convert some system memory into a fake local memory region for
|
||||||
|
testing.
|
||||||
|
@ -24,6 +24,7 @@ i915_gem_object_lmem_io_map_page(struct drm_i915_gem_object *obj,
|
|||||||
resource_size_t offset;
|
resource_size_t offset;
|
||||||
|
|
||||||
offset = i915_gem_object_get_dma_address(obj, n);
|
offset = i915_gem_object_get_dma_address(obj, n);
|
||||||
|
offset -= obj->mm.region->region.start;
|
||||||
|
|
||||||
return io_mapping_map_wc(&obj->mm.region->iomap, offset, PAGE_SIZE);
|
return io_mapping_map_wc(&obj->mm.region->iomap, offset, PAGE_SIZE);
|
||||||
}
|
}
|
||||||
@ -35,6 +36,7 @@ i915_gem_object_lmem_io_map_page_atomic(struct drm_i915_gem_object *obj,
|
|||||||
resource_size_t offset;
|
resource_size_t offset;
|
||||||
|
|
||||||
offset = i915_gem_object_get_dma_address(obj, n);
|
offset = i915_gem_object_get_dma_address(obj, n);
|
||||||
|
offset -= obj->mm.region->region.start;
|
||||||
|
|
||||||
return io_mapping_map_atomic_wc(&obj->mm.region->iomap, offset);
|
return io_mapping_map_atomic_wc(&obj->mm.region->iomap, offset);
|
||||||
}
|
}
|
||||||
@ -49,6 +51,7 @@ i915_gem_object_lmem_io_map(struct drm_i915_gem_object *obj,
|
|||||||
GEM_BUG_ON(!i915_gem_object_is_contiguous(obj));
|
GEM_BUG_ON(!i915_gem_object_is_contiguous(obj));
|
||||||
|
|
||||||
offset = i915_gem_object_get_dma_address(obj, n);
|
offset = i915_gem_object_get_dma_address(obj, n);
|
||||||
|
offset -= obj->mm.region->region.start;
|
||||||
|
|
||||||
return io_mapping_map_wc(&obj->mm.region->iomap, offset, size);
|
return io_mapping_map_wc(&obj->mm.region->iomap, offset, size);
|
||||||
}
|
}
|
||||||
|
@ -1483,6 +1483,21 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||||||
if (!i915_modparams.nuclear_pageflip && match_info->gen < 5)
|
if (!i915_modparams.nuclear_pageflip && match_info->gen < 5)
|
||||||
dev_priv->drm.driver_features &= ~DRIVER_ATOMIC;
|
dev_priv->drm.driver_features &= ~DRIVER_ATOMIC;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if we support fake LMEM -- for now we only unleash this for
|
||||||
|
* the live selftests(test-and-exit).
|
||||||
|
*/
|
||||||
|
if (IS_ENABLED(CONFIG_DRM_I915_UNSTABLE_FAKE_LMEM)) {
|
||||||
|
if (INTEL_GEN(dev_priv) >= 9 && i915_selftest.live < 0 &&
|
||||||
|
i915_modparams.fake_lmem_start) {
|
||||||
|
mkwrite_device_info(dev_priv)->memory_regions =
|
||||||
|
REGION_SMEM | REGION_LMEM | REGION_STOLEN;
|
||||||
|
mkwrite_device_info(dev_priv)->is_dgfx = true;
|
||||||
|
GEM_BUG_ON(!HAS_LMEM(dev_priv));
|
||||||
|
GEM_BUG_ON(!IS_DGFX(dev_priv));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = pci_enable_device(pdev);
|
ret = pci_enable_device(pdev);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_fini;
|
goto out_fini;
|
||||||
|
@ -179,6 +179,11 @@ i915_param_named(enable_gvt, bool, 0400,
|
|||||||
"Enable support for Intel GVT-g graphics virtualization host support(default:false)");
|
"Enable support for Intel GVT-g graphics virtualization host support(default:false)");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_DRM_I915_UNSTABLE_FAKE_LMEM)
|
||||||
|
i915_param_named_unsafe(fake_lmem_start, ulong, 0600,
|
||||||
|
"Fake LMEM start offset (default: 0)");
|
||||||
|
#endif
|
||||||
|
|
||||||
static __always_inline void _print_param(struct drm_printer *p,
|
static __always_inline void _print_param(struct drm_printer *p,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *type,
|
const char *type,
|
||||||
@ -190,6 +195,8 @@ static __always_inline void _print_param(struct drm_printer *p,
|
|||||||
drm_printf(p, "i915.%s=%d\n", name, *(const int *)x);
|
drm_printf(p, "i915.%s=%d\n", name, *(const int *)x);
|
||||||
else if (!__builtin_strcmp(type, "unsigned int"))
|
else if (!__builtin_strcmp(type, "unsigned int"))
|
||||||
drm_printf(p, "i915.%s=%u\n", name, *(const unsigned int *)x);
|
drm_printf(p, "i915.%s=%u\n", name, *(const unsigned int *)x);
|
||||||
|
else if (!__builtin_strcmp(type, "unsigned long"))
|
||||||
|
drm_printf(p, "i915.%s=%lu\n", name, *(const unsigned long *)x);
|
||||||
else if (!__builtin_strcmp(type, "char *"))
|
else if (!__builtin_strcmp(type, "char *"))
|
||||||
drm_printf(p, "i915.%s=%s\n", name, *(const char **)x);
|
drm_printf(p, "i915.%s=%s\n", name, *(const char **)x);
|
||||||
else
|
else
|
||||||
|
@ -66,6 +66,7 @@ struct drm_printer;
|
|||||||
param(int, fastboot, -1) \
|
param(int, fastboot, -1) \
|
||||||
param(int, enable_dpcd_backlight, 0) \
|
param(int, enable_dpcd_backlight, 0) \
|
||||||
param(char *, force_probe, CONFIG_DRM_I915_FORCE_PROBE) \
|
param(char *, force_probe, CONFIG_DRM_I915_FORCE_PROBE) \
|
||||||
|
param(unsigned long, fake_lmem_start, 0) \
|
||||||
/* leave bools at the end to not create holes */ \
|
/* leave bools at the end to not create holes */ \
|
||||||
param(bool, alpha_support, IS_ENABLED(CONFIG_DRM_I915_ALPHA_SUPPORT)) \
|
param(bool, alpha_support, IS_ENABLED(CONFIG_DRM_I915_ALPHA_SUPPORT)) \
|
||||||
param(bool, enable_hangcheck, true) \
|
param(bool, enable_hangcheck, true) \
|
||||||
|
@ -228,6 +228,9 @@ int intel_memory_regions_hw_probe(struct drm_i915_private *i915)
|
|||||||
case INTEL_MEMORY_STOLEN:
|
case INTEL_MEMORY_STOLEN:
|
||||||
mem = i915_gem_stolen_setup(i915);
|
mem = i915_gem_stolen_setup(i915);
|
||||||
break;
|
break;
|
||||||
|
case INTEL_MEMORY_LOCAL:
|
||||||
|
mem = intel_setup_fake_lmem(i915);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_ERR(mem)) {
|
if (IS_ERR(mem)) {
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/io-mapping.h>
|
#include <linux/io-mapping.h>
|
||||||
|
#include <drm/drm_mm.h>
|
||||||
|
|
||||||
#include "i915_buddy.h"
|
#include "i915_buddy.h"
|
||||||
|
|
||||||
@ -71,6 +72,9 @@ struct intel_memory_region {
|
|||||||
struct io_mapping iomap;
|
struct io_mapping iomap;
|
||||||
struct resource region;
|
struct resource region;
|
||||||
|
|
||||||
|
/* For fake LMEM */
|
||||||
|
struct drm_mm_node fake_mappable;
|
||||||
|
|
||||||
struct i915_buddy_mm mm;
|
struct i915_buddy_mm mm;
|
||||||
struct mutex mm_lock;
|
struct mutex mm_lock;
|
||||||
|
|
||||||
@ -83,6 +87,8 @@ struct intel_memory_region {
|
|||||||
unsigned int instance;
|
unsigned int instance;
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
|
|
||||||
|
dma_addr_t remap_addr;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct mutex lock; /* Protects access to objects */
|
struct mutex lock; /* Protects access to objects */
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
@ -9,9 +9,62 @@
|
|||||||
#include "gem/i915_gem_region.h"
|
#include "gem/i915_gem_region.h"
|
||||||
#include "intel_region_lmem.h"
|
#include "intel_region_lmem.h"
|
||||||
|
|
||||||
|
static int init_fake_lmem_bar(struct intel_memory_region *mem)
|
||||||
|
{
|
||||||
|
struct drm_i915_private *i915 = mem->i915;
|
||||||
|
struct i915_ggtt *ggtt = &i915->ggtt;
|
||||||
|
unsigned long n;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* We want to 1:1 map the mappable aperture to our reserved region */
|
||||||
|
|
||||||
|
mem->fake_mappable.start = 0;
|
||||||
|
mem->fake_mappable.size = resource_size(&mem->region);
|
||||||
|
mem->fake_mappable.color = I915_COLOR_UNEVICTABLE;
|
||||||
|
|
||||||
|
ret = drm_mm_reserve_node(&ggtt->vm.mm, &mem->fake_mappable);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
mem->remap_addr = dma_map_resource(&i915->drm.pdev->dev,
|
||||||
|
mem->region.start,
|
||||||
|
mem->fake_mappable.size,
|
||||||
|
PCI_DMA_BIDIRECTIONAL,
|
||||||
|
DMA_ATTR_FORCE_CONTIGUOUS);
|
||||||
|
if (dma_mapping_error(&i915->drm.pdev->dev, mem->remap_addr)) {
|
||||||
|
drm_mm_remove_node(&mem->fake_mappable);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (n = 0; n < mem->fake_mappable.size >> PAGE_SHIFT; ++n) {
|
||||||
|
ggtt->vm.insert_page(&ggtt->vm,
|
||||||
|
mem->remap_addr + (n << PAGE_SHIFT),
|
||||||
|
n << PAGE_SHIFT,
|
||||||
|
I915_CACHE_NONE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
mem->region = (struct resource)DEFINE_RES_MEM(mem->remap_addr,
|
||||||
|
mem->fake_mappable.size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void release_fake_lmem_bar(struct intel_memory_region *mem)
|
||||||
|
{
|
||||||
|
if (drm_mm_node_allocated(&mem->fake_mappable))
|
||||||
|
drm_mm_remove_node(&mem->fake_mappable);
|
||||||
|
|
||||||
|
dma_unmap_resource(&mem->i915->drm.pdev->dev,
|
||||||
|
mem->remap_addr,
|
||||||
|
mem->fake_mappable.size,
|
||||||
|
PCI_DMA_BIDIRECTIONAL,
|
||||||
|
DMA_ATTR_FORCE_CONTIGUOUS);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
region_lmem_release(struct intel_memory_region *mem)
|
region_lmem_release(struct intel_memory_region *mem)
|
||||||
{
|
{
|
||||||
|
release_fake_lmem_bar(mem);
|
||||||
io_mapping_fini(&mem->iomap);
|
io_mapping_fini(&mem->iomap);
|
||||||
intel_memory_region_release_buddy(mem);
|
intel_memory_region_release_buddy(mem);
|
||||||
}
|
}
|
||||||
@ -21,6 +74,11 @@ region_lmem_init(struct intel_memory_region *mem)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (i915_modparams.fake_lmem_start) {
|
||||||
|
ret = init_fake_lmem_bar(mem);
|
||||||
|
GEM_BUG_ON(ret);
|
||||||
|
}
|
||||||
|
|
||||||
if (!io_mapping_init_wc(&mem->iomap,
|
if (!io_mapping_init_wc(&mem->iomap,
|
||||||
mem->io_start,
|
mem->io_start,
|
||||||
resource_size(&mem->region)))
|
resource_size(&mem->region)))
|
||||||
@ -38,3 +96,37 @@ const struct intel_memory_region_ops intel_region_lmem_ops = {
|
|||||||
.release = region_lmem_release,
|
.release = region_lmem_release,
|
||||||
.create_object = __i915_gem_lmem_object_create,
|
.create_object = __i915_gem_lmem_object_create,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct intel_memory_region *
|
||||||
|
intel_setup_fake_lmem(struct drm_i915_private *i915)
|
||||||
|
{
|
||||||
|
struct pci_dev *pdev = i915->drm.pdev;
|
||||||
|
struct intel_memory_region *mem;
|
||||||
|
resource_size_t mappable_end;
|
||||||
|
resource_size_t io_start;
|
||||||
|
resource_size_t start;
|
||||||
|
|
||||||
|
GEM_BUG_ON(i915_ggtt_has_aperture(&i915->ggtt));
|
||||||
|
GEM_BUG_ON(!i915_modparams.fake_lmem_start);
|
||||||
|
|
||||||
|
/* Your mappable aperture belongs to me now! */
|
||||||
|
mappable_end = pci_resource_len(pdev, 2);
|
||||||
|
io_start = pci_resource_start(pdev, 2),
|
||||||
|
start = i915_modparams.fake_lmem_start;
|
||||||
|
|
||||||
|
mem = intel_memory_region_create(i915,
|
||||||
|
start,
|
||||||
|
mappable_end,
|
||||||
|
PAGE_SIZE,
|
||||||
|
io_start,
|
||||||
|
&intel_region_lmem_ops);
|
||||||
|
if (!IS_ERR(mem)) {
|
||||||
|
DRM_INFO("Intel graphics fake LMEM: %pR\n", &mem->region);
|
||||||
|
DRM_INFO("Intel graphics fake LMEM IO start: %llx\n",
|
||||||
|
(u64)mem->io_start);
|
||||||
|
DRM_INFO("Intel graphics fake LMEM size: %llx\n",
|
||||||
|
(u64)resource_size(&mem->region));
|
||||||
|
}
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
@ -6,6 +6,11 @@
|
|||||||
#ifndef __INTEL_REGION_LMEM_H
|
#ifndef __INTEL_REGION_LMEM_H
|
||||||
#define __INTEL_REGION_LMEM_H
|
#define __INTEL_REGION_LMEM_H
|
||||||
|
|
||||||
|
struct drm_i915_private;
|
||||||
|
|
||||||
extern const struct intel_memory_region_ops intel_region_lmem_ops;
|
extern const struct intel_memory_region_ops intel_region_lmem_ops;
|
||||||
|
|
||||||
|
struct intel_memory_region *
|
||||||
|
intel_setup_fake_lmem(struct drm_i915_private *i915);
|
||||||
|
|
||||||
#endif /* !__INTEL_REGION_LMEM_H */
|
#endif /* !__INTEL_REGION_LMEM_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user