diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/Makefile.am | 4 | ||||
| -rw-r--r-- | tests/radeon/Makefile.am | 12 | ||||
| -rw-r--r-- | tests/radeon/list.h | 137 | ||||
| -rw-r--r-- | tests/radeon/radeon_ttm.c | 75 | ||||
| -rw-r--r-- | tests/radeon/rbo.c | 171 | ||||
| -rw-r--r-- | tests/radeon/rbo.h | 50 | 
6 files changed, 449 insertions, 0 deletions
| diff --git a/tests/Makefile.am b/tests/Makefile.am index bf1987f1..a3a59bd5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -16,6 +16,10 @@ if HAVE_LIBKMS  SUBDIRS += kmstest modetest  endif +if HAVE_RADEON +SUBDIRS += radeon +endif +  if HAVE_LIBUDEV  check_LTLIBRARIES = libdrmtest.la diff --git a/tests/radeon/Makefile.am b/tests/radeon/Makefile.am new file mode 100644 index 00000000..021ca722 --- /dev/null +++ b/tests/radeon/Makefile.am @@ -0,0 +1,12 @@ +AM_CFLAGS = \ +	-I $(top_srcdir)/include/drm \ +	-I $(top_srcdir) + +LDADD = $(top_builddir)/libdrm.la + +noinst_PROGRAMS = \ +	radeon_ttm + +radeon_ttm_SOURCES = \ +	rbo.c \ +	radeon_ttm.c diff --git a/tests/radeon/list.h b/tests/radeon/list.h new file mode 100644 index 00000000..305c903e --- /dev/null +++ b/tests/radeon/list.h @@ -0,0 +1,137 @@ +/* + * + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ + +/** + * \file + * List macros heavily inspired by the Linux kernel + * list handling. No list looping yet. + * + * Is not threadsafe, so common operations need to + * be protected using an external mutex. + */ +#ifndef _U_DOUBLE_LIST_H_ +#define _U_DOUBLE_LIST_H_ + +#include <stddef.h> + +struct list_head +{ +    struct list_head *prev; +    struct list_head *next; +}; + +static void list_inithead(struct list_head *item) +{ +    item->prev = item; +    item->next = item; +} + +static void list_add(struct list_head *item, struct list_head *list) +{ +    item->prev = list; +    item->next = list->next; +    list->next->prev = item; +    list->next = item; +} + +static void list_addtail(struct list_head *item, struct list_head *list) +{ +    item->next = list; +    item->prev = list->prev; +    list->prev->next = item; +    list->prev = item; +} + +static void list_replace(struct list_head *from, struct list_head *to) +{ +    to->prev = from->prev; +    to->next = from->next; +    from->next->prev = to; +    from->prev->next = to; +} + +static void list_del(struct list_head *item) +{ +    item->prev->next = item->next; +    item->next->prev = item->prev; +} + +static void list_delinit(struct list_head *item) +{ +    item->prev->next = item->next; +    item->next->prev = item->prev; +    item->next = item; +    item->prev = item; +} + +#define LIST_INITHEAD(__item) list_inithead(__item) +#define LIST_ADD(__item, __list) list_add(__item, __list) +#define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list) +#define LIST_REPLACE(__from, __to) list_replace(__from, __to) +#define LIST_DEL(__item) list_del(__item) +#define LIST_DELINIT(__item) list_delinit(__item) + +#define LIST_ENTRY(__type, __item, __field)   \ +    ((__type *)(((char *)(__item)) - offsetof(__type, __field))) + +#define LIST_IS_EMPTY(__list)                   \ +    ((__list)->next == (__list)) + +#ifndef container_of +#define container_of(ptr, sample, member)				\ +    (void *)((char *)(ptr)						\ +	     - ((char *)&(sample)->member - (char *)(sample))) +#endif + +#define LIST_FOR_EACH_ENTRY(pos, head, member)				\ +   for (pos = container_of((head)->next, pos, member);			\ +	&pos->member != (head);						\ +	pos = container_of(pos->member.next, pos, member)) + +#define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member)	\ +   for (pos = container_of((head)->next, pos, member),			\ +	storage = container_of(pos->member.next, pos, member);	\ +	&pos->member != (head);						\ +	pos = storage, storage = container_of(storage->member.next, storage, member)) + +#define LIST_FOR_EACH_ENTRY_SAFE_REV(pos, storage, head, member)	\ +   for (pos = container_of((head)->prev, pos, member),			\ +	storage = container_of(pos->member.prev, pos, member);		\ +	&pos->member != (head);						\ +	pos = storage, storage = container_of(storage->member.prev, storage, member)) + +#define LIST_FOR_EACH_ENTRY_FROM(pos, start, head, member)		\ +   for (pos = container_of((start), pos, member);			\ +	&pos->member != (head);						\ +	pos = container_of(pos->member.next, pos, member)) + +#define LIST_FOR_EACH_ENTRY_FROM_REV(pos, start, head, member)		\ +   for (pos = container_of((start), pos, member);			\ +	&pos->member != (head);						\ +	pos = container_of(pos->member.prev, pos, member)) + +#endif /*_U_DOUBLE_LIST_H_*/ diff --git a/tests/radeon/radeon_ttm.c b/tests/radeon/radeon_ttm.c new file mode 100644 index 00000000..246fd993 --- /dev/null +++ b/tests/radeon/radeon_ttm.c @@ -0,0 +1,75 @@ +/* + * Copyright © 2011 Red Hat + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + *    Jerome Glisse <j.glisse@gmail.com> + */ +#include <stdio.h> +#include <stdlib.h> +#include "rbo.h" + +/* allocate as many single page bo to try to starve the kernel + * memory zone (below highmem) + */ +void ttm_starve_kernel_private_memory(int fd) +{ +    struct list_head list; +    struct rbo *bo, *tmp; +    unsigned nbo = 0; + +    printf("\n[%s]\n", __func__); +    list_inithead(&list); +    while (1) { +        bo = rbo(fd, 0, 4096, 0, NULL); +        if (bo == NULL) { +            printf("failing after %d bo\n", nbo); +            break; +        } +        nbo++; +        list_add(&bo->list, &list); +    } +    LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &list, list) { +        list_del(&bo->list); +        rbo_decref(bo); +    } +} + +int radeon_open_fd(void) +{ +    return drmOpen("radeon", NULL); +} + +int main(void) +{ +    int radeonfd; + +    radeonfd = radeon_open_fd(); +    if (radeonfd < 0) { +        fprintf(stderr, "failed to open radeon fd\n"); +        return -1; +    } + +    ttm_starve_kernel_private_memory(radeonfd); + +    close(radeonfd); +    return 0; +} diff --git a/tests/radeon/rbo.c b/tests/radeon/rbo.c new file mode 100644 index 00000000..70a288c3 --- /dev/null +++ b/tests/radeon/rbo.c @@ -0,0 +1,171 @@ +/* + * Copyright © 2011 Red Hat + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + *    Jerome Glisse <j.glisse@gmail.com> + */ +#define _FILE_OFFSET_BITS 64 +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <errno.h> +#include "xf86drm.h" +#include "radeon_drm.h" +#include "rbo.h" + +struct rbo *rbo(int fd, unsigned handle, unsigned size, +                unsigned alignment, void *ptr) +{ +    struct rbo *bo; +    int r; + +    bo = calloc(1, sizeof(*bo)); +    if (bo == NULL) { +        return NULL; +    } +    list_inithead(&bo->list); +    bo->fd = fd; +    bo->size = size; +    bo->handle = handle; +    bo->refcount = 1; +    bo->alignment = alignment; + +    if (handle) { +        struct drm_gem_open open_arg; + +        memset(&open_arg, 0, sizeof(open_arg)); +        open_arg.name = handle; +        r = drmIoctl(fd, DRM_IOCTL_GEM_OPEN, &open_arg); +        if (r != 0) { +            free(bo); +            return NULL; +        } +        bo->handle = open_arg.handle; +    } else { +        struct drm_radeon_gem_create args; + +        args.size = size; +        args.alignment = alignment; +        args.initial_domain = RADEON_GEM_DOMAIN_CPU; +        args.flags = 0; +        args.handle = 0; +        r = drmCommandWriteRead(fd, DRM_RADEON_GEM_CREATE, +                                &args, sizeof(args)); +        bo->handle = args.handle; +        if (r) { +            fprintf(stderr, "Failed to allocate :\n"); +            fprintf(stderr, "   size      : %d bytes\n", size); +            fprintf(stderr, "   alignment : %d bytes\n", alignment); +            free(bo); +            return NULL; +        } +    } +    if (ptr) { +        if (rbo_map(bo)) { +            fprintf(stderr, "%s failed to copy data into bo\n", __func__); +            return rbo_decref(bo); +        } +        memcpy(bo->data, ptr, size); +        rbo_unmap(bo); +    } +    return bo; +} + +int rbo_map(struct rbo *bo) +{ +    struct drm_radeon_gem_mmap args; +    void *ptr; +    int r; + +    if (bo->mapcount++ != 0) { +        return 0; +    } +    /* Zero out args to make valgrind happy */ +    memset(&args, 0, sizeof(args)); +    args.handle = bo->handle; +    args.offset = 0; +    args.size = (uint64_t)bo->size; +    r = drmCommandWriteRead(bo->fd, DRM_RADEON_GEM_MMAP, +                            &args, sizeof(args)); +    if (r) { +        fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n", +            bo, bo->handle, r); +        return r; +    } +    ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, bo->fd, args.addr_ptr); +    if (ptr == MAP_FAILED) { +        fprintf(stderr, "%s failed to map bo\n", __func__); +        return -errno; +    } +    bo->data = ptr; +    return 0; +} + +void rbo_unmap(struct rbo *bo) +{ +    if (--bo->mapcount > 0) { +        return; +    } +    munmap(bo->data, bo->size); +    bo->data = NULL; +} + +struct rbo *rbo_incref(struct rbo *bo) +{ +    bo->refcount++; +    return bo; +} + +struct rbo *rbo_decref(struct rbo *bo) +{ +    struct drm_gem_close args; + +    if (bo == NULL) +        return NULL; +    if (--bo->refcount > 0) { +        return NULL; +    } + +    munmap(bo->data, bo->size); +    memset(&args, 0, sizeof(args)); +    args.handle = bo->handle; +    drmIoctl(bo->fd, DRM_IOCTL_GEM_CLOSE, &args); +    memset(bo, 0, sizeof(struct rbo)); +    free(bo); +    return NULL; +} + +int rbo_wait(struct rbo *bo) +{ +    struct drm_radeon_gem_wait_idle args; +    int ret; + +    /* Zero out args to make valgrind happy */ +    memset(&args, 0, sizeof(args)); +    args.handle = bo->handle; +    do { +        ret = drmCommandWriteRead(bo->fd, DRM_RADEON_GEM_WAIT_IDLE, +                                  &args, sizeof(args)); +    } while (ret == -EBUSY); +    return ret; +} diff --git a/tests/radeon/rbo.h b/tests/radeon/rbo.h new file mode 100644 index 00000000..c25c73a4 --- /dev/null +++ b/tests/radeon/rbo.h @@ -0,0 +1,50 @@ +/* + * Copyright © 2011 Red Hat + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + *    Jerome Glisse <j.glisse@gmail.com> + */ +#ifndef RBO_H +#define RBO_H + +#include "list.h" + +struct rbo { +    struct list_head    list; +    int                 fd; +    unsigned            refcount; +    unsigned            mapcount; +    unsigned            handle; +    unsigned            size; +    unsigned            alignment; +    void                *data; +}; + +struct rbo *rbo(int fd, unsigned handle, unsigned size, +                unsigned alignment, void *ptr); +int rbo_map(struct rbo *bo); +void rbo_unmap(struct rbo *bo); +struct rbo *rbo_incref(struct rbo *bo); +struct rbo *rbo_decref(struct rbo *bo); +int rbo_wait(struct rbo *bo); + +#endif | 
