The inteldrm(4) driver keeps a cache of graphics objects, allegedly to
make things faster by avoiding cache flushes. But those graphics
objects consume memory that we want to free if we need it for
something else.
The diff below hooks up the "shrinker" code in inteldrm(4) and calls
it from the pagedeamon if it thinks it needs to free up memory.
The diff still has some debug printfs such that we can tell that the
code is actually called.
Please test if you have inteldrm(4), esepcially on machines with
limited amounts of physical memory.
Index: dev/pci/drm/drm_linux.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/drm_linux.c,v
retrieving revision 1.50
diff -u -p -r1.50 drm_linux.c
--- dev/pci/drm/drm_linux.c 23 Oct 2019 10:17:40 -0000 1.50
+++ dev/pci/drm/drm_linux.c 27 Nov 2019 15:55:37 -0000
@@ -1867,3 +1867,29 @@ pci_resize_resource(struct pci_dev *pdev
return 0;
}
+
+TAILQ_HEAD(, shrinker) shrinkers = TAILQ_HEAD_INITIALIZER(shrinkers);
+
+int
+register_shrinker(struct shrinker *shrinker)
+{
+ TAILQ_INSERT_TAIL(&shrinkers, shrinker, next);
+ return 0;
+}
+
+void
+drmbackoff(long npages)
+{
+ struct shrink_control sc;
+ struct shrinker *shrinker;
+ u_long ret;
+
+ printf("%s: %ld\n", __func__, npages);
+ shrinker = TAILQ_FIRST(&shrinkers);
+ while (shrinker && npages > 0) {
+ sc.nr_to_scan = npages;
+ ret = shrinker->scan_objects(shrinker, &sc);
+ npages -= ret;
+ shrinker = TAILQ_NEXT(shrinker, next);
+ }
+}
Index: dev/pci/drm/i915/i915_drv.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915/i915_drv.h,v
retrieving revision 1.89
diff -u -p -r1.89 i915_drv.h
--- dev/pci/drm/i915/i915_drv.h 13 Nov 2019 06:41:55 -0000 1.89
+++ dev/pci/drm/i915/i915_drv.h 27 Nov 2019 15:55:37 -0000
@@ -1072,9 +1072,7 @@ struct i915_gem_mm {
struct notifier_block oom_notifier;
struct notifier_block vmap_notifier;
-#ifdef notyet
struct shrinker shrinker;
-#endif
/** LRU list of objects with fence regs on them. */
struct list_head fence_list;
Index: dev/pci/drm/i915/i915_gem_shrinker.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915/i915_gem_shrinker.c,v
retrieving revision 1.1
diff -u -p -r1.1 i915_gem_shrinker.c
--- dev/pci/drm/i915/i915_gem_shrinker.c 14 Apr 2019 10:14:51 -0000
1.1
+++ dev/pci/drm/i915/i915_gem_shrinker.c 27 Nov 2019 15:55:37 -0000
@@ -36,7 +36,6 @@
#include "i915_drv.h"
#include "i915_trace.h"
-#ifdef notyet
static bool shrinker_lock(struct drm_i915_private *i915, bool *unlock)
{
switch (mutex_trylock_recursive(&i915->drm.struct_mutex)) {
@@ -115,7 +114,6 @@ static bool unsafe_drop_pages(struct drm
__i915_gem_object_put_pages(obj, I915_MM_SHRINKER);
return !i915_gem_object_has_pages(obj);
}
-#endif
/**
* i915_gem_shrink - Shrink buffer object caches
@@ -148,9 +146,6 @@ i915_gem_shrink(struct drm_i915_private
unsigned long *nr_scanned,
unsigned flags)
{
- STUB();
- return -ENOSYS;
-#ifdef notyet
const struct {
struct list_head *list;
unsigned int bit;
@@ -163,6 +158,8 @@ i915_gem_shrink(struct drm_i915_private
unsigned long scanned = 0;
bool unlock;
+ printf("%s: %ld\n", __func__, target);
+
if (!shrinker_lock(i915, &unlock))
return 0;
@@ -280,7 +277,6 @@ i915_gem_shrink(struct drm_i915_private
if (nr_scanned)
*nr_scanned += scanned;
return count;
-#endif
}
/**
@@ -311,7 +307,6 @@ unsigned long i915_gem_shrink_all(struct
return freed;
}
-#ifdef notyet
static unsigned long
i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
{
@@ -393,6 +388,7 @@ i915_gem_shrinker_scan(struct shrinker *
return sc->nr_scanned ? freed : SHRINK_STOP;
}
+#ifdef notyet
static bool
shrinker_lock_uninterruptible(struct drm_i915_private *i915, bool *unlock,
int timeout_ms)
@@ -513,13 +509,13 @@ out:
*/
void i915_gem_shrinker_register(struct drm_i915_private *i915)
{
-#ifdef notyet
i915->mm.shrinker.scan_objects = i915_gem_shrinker_scan;
i915->mm.shrinker.count_objects = i915_gem_shrinker_count;
i915->mm.shrinker.seeks = DEFAULT_SEEKS;
i915->mm.shrinker.batch = 4096;
WARN_ON(register_shrinker(&i915->mm.shrinker));
+#ifdef notyet
i915->mm.oom_notifier.notifier_call = i915_gem_shrinker_oom;
WARN_ON(register_oom_notifier(&i915->mm.oom_notifier));
Index: dev/pci/drm/include/linux/mm.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/include/linux/mm.h,v
retrieving revision 1.2
diff -u -p -r1.2 mm.h
--- dev/pci/drm/include/linux/mm.h 8 May 2019 22:44:31 -0000 1.2
+++ dev/pci/drm/include/linux/mm.h 27 Nov 2019 15:55:37 -0000
@@ -78,4 +78,23 @@ get_order(size_t size)
return flsl((size - 1) >> PAGE_SHIFT);
}
+struct shrink_control {
+ u_long nr_to_scan;
+ u_long nr_scanned;
+};
+
+struct shrinker {
+ u_long (*count_objects)(struct shrinker *, struct shrink_control *);
+ u_long (*scan_objects)(struct shrinker *, struct shrink_control *);
+ long batch;
+ int seeks;
+ TAILQ_ENTRY(shrinker) next;
+};
+
+#define SHRINK_STOP ~0UL
+
+#define DEFAULT_SEEKS 2
+
+int register_shrinker(struct shrinker *);
+
#endif
Index: dev/pci/drm/include/linux/mutex.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/include/linux/mutex.h,v
retrieving revision 1.1
diff -u -p -r1.1 mutex.h
--- dev/pci/drm/include/linux/mutex.h 14 Apr 2019 10:14:53 -0000 1.1
+++ dev/pci/drm/include/linux/mutex.h 27 Nov 2019 15:55:37 -0000
@@ -16,7 +16,23 @@
#define mutex_lock_nested(rwl, sub) rw_enter_write(rwl)
#define mutex_trylock(rwl) (rw_enter(rwl, RW_WRITE | RW_NOSLEEP)
== 0)
#define mutex_unlock(rwl) rw_exit_write(rwl)
-#define mutex_is_locked(rwl) (rw_status(rwl) == RW_WRITE)
+#define mutex_is_locked(rwl) (rw_status(rwl) != 0)
#define mutex_destroy(rwl)
+
+enum mutex_trylock_recursive_result {
+ MUTEX_TRYLOCK_FAILED,
+ MUTEX_TRYLOCK_SUCCESS,
+ MUTEX_TRYLOCK_RECURSIVE
+};
+
+static inline enum mutex_trylock_recursive_result
+mutex_trylock_recursive(struct rwlock *rwl)
+{
+ if (rw_status(rwl) == RW_WRITE)
+ return MUTEX_TRYLOCK_RECURSIVE;
+ if (mutex_trylock(rwl))
+ return MUTEX_TRYLOCK_SUCCESS;
+ return MUTEX_TRYLOCK_FAILED;
+}
#endif
Index: dev/pci/drm/include/linux/swap.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/include/linux/swap.h,v
retrieving revision 1.1
diff -u -p -r1.1 swap.h
--- dev/pci/drm/include/linux/swap.h 14 Apr 2019 10:14:53 -0000 1.1
+++ dev/pci/drm/include/linux/swap.h 27 Nov 2019 15:55:37 -0000
@@ -11,4 +11,6 @@ get_nr_swap_pages(void)
return uvmexp.swpages - uvmexp.swpginuse;
}
+#define current_is_kswapd() 0
+
#endif
Index: uvm/uvm_pdaemon.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_pdaemon.c,v
retrieving revision 1.83
diff -u -p -r1.83 uvm_pdaemon.c
--- uvm/uvm_pdaemon.c 3 Jul 2019 22:39:33 -0000 1.83
+++ uvm/uvm_pdaemon.c 27 Nov 2019 15:55:38 -0000
@@ -262,6 +262,8 @@ uvm_pageout(void *arg)
size = 16; /* XXX */
uvm_unlock_pageq();
(void) bufbackoff(&constraint, size * 2);
+ extern void drmbackoff(long);
+ drmbackoff(size * 2);
uvm_lock_pageq();
/* Scan if needed to meet our targets. */