On Fri, Feb 14, 2014 at 03:55:47PM +0200, Andriy Gapon wrote:
> 
> I am using "radeonkms" on a machine with quite mixed, diverse and varying 
> loads.
> Sometimes I get an X server crash like the following:
> 
> kernel: [TTM] Unable to allocate page
> kernel: error: [drm:pid1815:radeon_gem_object_create] *ERROR* Failed to 
> allocate
> GEM object (25591808, 2, 4096, -12)
> kernel: [TTM] Unable to allocate page
> kernel: [TTM] Buffer eviction failed
> kernel: vm_fault: pager read error, pid 1815 (Xorg)
> kernel: pid 1815 (Xorg), uid 0: exited on signal 11 (core dumped)
> 
> At the same time there was the following in X servers stderr:
> Failed to allocate :
>    size      : 25589760 bytes
>    alignment : 256 bytes
>    domains   : 2
> 
> I wonder if this is a generic problem for example caused by severe resource
> exhaustion or if this is something where FreeBSD specific code does not do 
> its best.
> In particular, it caught my attention that ttm_get_pages() effectively has
> semantics of M_NOWAIT as it never retries allocation failures in
> vm_page_alloc_contig().

It seems you are right that Linux tries much harder to allocate the page
than the current FreeBSD TTM ports does.  Can you try the following patch ?
I did not tested it, only compiled.  Please keep witness enabled.

diff --git a/sys/dev/drm2/ttm/ttm_bo.c b/sys/dev/drm2/ttm/ttm_bo.c
index d87940c..748c969 100644
--- a/sys/dev/drm2/ttm/ttm_bo.c
+++ b/sys/dev/drm2/ttm/ttm_bo.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/drm2/ttm/ttm_module.h>
 #include <dev/drm2/ttm/ttm_bo_driver.h>
 #include <dev/drm2/ttm/ttm_placement.h>
+#include <vm/vm_pageout.h>
 
 #define TTM_ASSERT_LOCKED(param)
 #define TTM_DEBUG(fmt, arg...)
@@ -1489,15 +1490,23 @@ int ttm_bo_global_init(struct drm_global_reference *ref)
                container_of(ref, struct ttm_bo_global_ref, ref);
        struct ttm_bo_global *glob = ref->object;
        int ret;
+       int tries;
 
        sx_init(&glob->device_list_mutex, "ttmdlm");
        mtx_init(&glob->lru_lock, "ttmlru", NULL, MTX_DEF);
        glob->mem_glob = bo_ref->mem_glob;
+       tries = 0;
+retry:
        glob->dummy_read_page = vm_page_alloc_contig(NULL, 0,
            VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ,
            1, 0, VM_MAX_ADDRESS, PAGE_SIZE, 0, VM_MEMATTR_UNCACHEABLE);
 
        if (unlikely(glob->dummy_read_page == NULL)) {
+               if (tries < 1) {
+                       vm_pageout_grow_cache(tries, 0, VM_MAX_ADDRESS);
+                       tries++;
+                       goto retry;
+               }
                ret = -ENOMEM;
                goto out_no_drp;
        }
diff --git a/sys/dev/drm2/ttm/ttm_page_alloc.c 
b/sys/dev/drm2/ttm/ttm_page_alloc.c
index 3c0f18a..29a3621 100644
--- a/sys/dev/drm2/ttm/ttm_page_alloc.c
+++ b/sys/dev/drm2/ttm/ttm_page_alloc.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/drm2/drmP.h>
 #include <dev/drm2/ttm/ttm_bo_driver.h>
 #include <dev/drm2/ttm/ttm_page_alloc.h>
+#include <vm/vm_pageout.h>
 
 #ifdef TTM_HAS_AGP
 #include <asm/agp.h>
@@ -476,6 +477,14 @@ static void ttm_handle_caching_state_failure(struct pglist 
*pages,
        }
 }
 
+static vm_paddr_t
+ttm_alloc_high_bound(int ttm_alloc_flags)
+{
+
+       return ((ttm_alloc_flags & TTM_PAGE_FLAG_DMA32) ? 0xffffffff :
+           VM_MAX_ADDRESS);
+}
+
 /**
  * Allocate new pages with correct caching.
  *
@@ -491,6 +500,7 @@ static int ttm_alloc_new_pages(struct pglist *pages, int 
ttm_alloc_flags,
        unsigned i, cpages, aflags;
        unsigned max_cpages = min(count,
                        (unsigned)(PAGE_SIZE/sizeof(vm_page_t)));
+       int tries;
 
        aflags = VM_ALLOC_NORMAL | VM_ALLOC_WIRED | VM_ALLOC_NOOBJ |
            ((ttm_alloc_flags & TTM_PAGE_FLAG_ZERO_ALLOC) != 0 ?
@@ -501,11 +511,18 @@ static int ttm_alloc_new_pages(struct pglist *pages, int 
ttm_alloc_flags,
            M_WAITOK | M_ZERO);
 
        for (i = 0, cpages = 0; i < count; ++i) {
+               tries = 0;
+retry:
                p = vm_page_alloc_contig(NULL, 0, aflags, 1, 0,
-                   (ttm_alloc_flags & TTM_PAGE_FLAG_DMA32) ? 0xffffffff :
-                   VM_MAX_ADDRESS, PAGE_SIZE, 0,
-                   ttm_caching_state_to_vm(cstate));
+                   ttm_alloc_high_bound(ttm_alloc_flags),
+                   PAGE_SIZE, 0, ttm_caching_state_to_vm(cstate));
                if (!p) {
+                       if (tries < 3) {
+                               vm_pageout_grow_cache(tries, 0,
+                                   ttm_alloc_high_bound(ttm_alloc_flags));
+                               tries++;
+                               goto retry;
+                       }
                        printf("[TTM] Unable to get page %u\n", i);
 
                        /* store already allocated pages in the pool after
@@ -707,6 +724,7 @@ static int ttm_get_pages(vm_page_t *pages, unsigned npages, 
int flags,
        int gfp_flags, aflags;
        unsigned count;
        int r;
+       int tries;
 
        aflags = VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED |
            ((flags & TTM_PAGE_FLAG_ZERO_ALLOC) != 0 ? VM_ALLOC_ZERO : 0);
@@ -714,11 +732,18 @@ static int ttm_get_pages(vm_page_t *pages, unsigned 
npages, int flags,
        /* No pool for cached pages */
        if (pool == NULL) {
                for (r = 0; r < npages; ++r) {
+                       tries = 0;
+retry:
                        p = vm_page_alloc_contig(NULL, 0, aflags, 1, 0,
-                           (flags & TTM_PAGE_FLAG_DMA32) ? 0xffffffff :
-                           VM_MAX_ADDRESS, PAGE_SIZE,
+                           ttm_alloc_high_bound(flags), PAGE_SIZE,
                            0, ttm_caching_state_to_vm(cstate));
                        if (!p) {
+                               if (tries < 3) {
+                                       vm_pageout_grow_cache(tries, 0,
+                                           ttm_alloc_high_bound(flags));
+                                       tries++;
+                                       goto retry;
+                               }
                                printf("[TTM] Unable to allocate page\n");
                                return -ENOMEM;
                        }

Attachment: pgpcjNc2D3Cdx.pgp
Description: PGP signature

Reply via email to