Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

increase the size of uvm memory allocation #11

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions kernel-open/common/inc/nv-nanos.h
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,18 @@ typedef struct nvidia_event
#define BUILD_BUG_ON(expr) build_assert(!(expr))
#define BUILD_BUG_ON_NOT_POWER_OF_2(expr) build_assert(((expr) & ((expr) - 1)) == 0)

// To implement realloc for vmalloc-based allocations we need to track the size
// of the original allocation. We can do that by allocating a header along with
// the allocation itself. Since vmalloc is only used for relatively large
// allocations, this overhead is very small.
//
// We don't need this for kmalloc since we can use ksize().
typedef struct
{
size_t alloc_size;
uint8_t ptr[0];
} uvm_vmalloc_hdr_t;

#define ZERO_SIZE_PTR pointer_from_u64(16)
#define ZERO_OR_NULL_PTR(p) (u64_from_pointer(p) <= u64_from_pointer(ZERO_SIZE_PTR))

Expand All @@ -507,8 +519,13 @@ typedef struct nvidia_event
#define vmalloc(size) kmalloc(size, 0)
#define vzalloc(size) kzalloc(size, 0)
#define ksize(p) objcache_from_object(u64_from_pointer(p), PAGESIZE_2M)->pagesize
#define is_vmalloc_addr(p) false
#define vfree kfree
#define is_vmalloc_addr(p) (objcache_from_object(u64_from_pointer(p), PAGESIZE_2M) == INVALID_ADDRESS)
#define vfree(p) do { \
uvm_vmalloc_hdr_t *hdr; \
hdr = container_of(p, uvm_vmalloc_hdr_t, ptr); \
NV_KFREE(p, hdr->alloc_size); \
} while (0)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work if memory is allocated from outside the nvidia-uvm module, because it won't have the uvm_vmalloc_hdr_t header.
To deal with the vfree() call in linux_nvswitch.c, I would not use vmalloc/vfree at all in the nvswitch code; instead, I would use use another Nanos kernel heap, i.e. get_kernel_heaps()->malloc, which can take -1 as size argument when freeing memory. So, _nvswitch_os_malloc() will be as below:

    void *ptr = allocate(get_kernel_heaps()->malloc, size);

    if (ptr == INVALID_ADDRESS)
        return NULL;

    return ptr;

and _nvswitch_os_free() will be as below:

    if (!ptr)
        return;

    deallocate((get_kernel_heaps()->malloc), ptr, -1ull);

The vfree() macro will only be called from the nvidia-uvm module, where we can easily extract the size parameter from the uvm_vmalloc_hdr_t header.


static inline void *kmalloc(unsigned long size, int flags)
{
Expand Down
13 changes: 0 additions & 13 deletions kernel-open/nvidia-uvm/uvm_kvmalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,6 @@
#include "uvm_kvmalloc.h"
#include "uvm_rb_tree.h"

// To implement realloc for vmalloc-based allocations we need to track the size
// of the original allocation. We can do that by allocating a header along with
// the allocation itself. Since vmalloc is only used for relatively large
// allocations, this overhead is very small.
//
// We don't need this for kmalloc since we can use ksize().
typedef struct
{
size_t alloc_size;
uint8_t ptr[0];
} uvm_vmalloc_hdr_t;

typedef struct
{
const char *file;
Expand Down Expand Up @@ -257,7 +245,6 @@ static void *alloc_internal(size_t size, bool zero_memory)
// Make sure that (sizeof(hdr) + size) is what it should be
BUILD_BUG_ON(sizeof(uvm_vmalloc_hdr_t) != offsetof(uvm_vmalloc_hdr_t *, ptr));

assert(size <= (1 << 16));
if (size <= UVM_KMALLOC_THRESHOLD) {
if (zero_memory)
return kzalloc(size, NV_UVM_GFP_FLAGS);
Expand Down
7 changes: 6 additions & 1 deletion kernel-open/nvidia-uvm/uvm_kvmalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
#include "uvm_nanos.h"
#include "uvm_test_ioctl.h"

#ifndef _CONFIG_H_
#include <config.h>
#define _CONFIG_H_
#endif

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not necessary, the config.h header is included internally by other Nanos header files.

// kmalloc is faster than vmalloc because it doesn't have to remap kernel
// virtual memory, but for that same reason it requires physically-contiguous
// memory. It also supports a native krealloc function which is missing in
Expand All @@ -41,7 +46,7 @@
//
// This is in the header so callers can use it to inform their allocation sizes
// if they wish.
#define UVM_KMALLOC_THRESHOLD infinity
#define UVM_KMALLOC_THRESHOLD (1 << MAX_MCACHE_ORDER)

NV_STATUS uvm_kvmalloc_init(void);
void uvm_kvmalloc_exit(void);
Expand Down