From 51a32d8f2c97ae42fd714078c97af83c7136878f Mon Sep 17 00:00:00 2001 From: Alex Waterman Date: Thu, 21 Jul 2016 14:01:58 -0700 Subject: gpu: nvgpu: Ensure PDE alignment for GVA spaces When managing GVA spaces the buddy allocator requires PDE size alignment. This is to ensure that PTE size in buddies always remains consistent. Consider the following hypothetical GVA space: it is 32 elements long, order 0 block size is 1, and PDE size is 8. This leads to: Base: 8 Size: 24 Managed space: [8, 32) The start of the space will be 8 (base must be aligned to a PDE and we need a hole at the bottom for handling errors). Size is simply the max, 32, minus what we cut out for the low hole. The two top level buddies are [8 -> 24), and [24 -> 32). Now, suppose, instead the base were 4: Base: 4 Size: 28 Managed space: [4, 32) The top level buddies would be [4 -> 20), [20 -> 28), and [28 -> 32). This presents several problems: none of the buddies are PDE aligned and one top level buddy is smaller than the PDE size. The simplest issue is how to determine the PTE size of the [28 -> 32) block. We can just set it as small but that's not ideal. The bigger issue is the mis-alignment of the larger buddies. [20 -> 28) is halfway in one PDE and halfway in another. That means the allocator would have to manage the two sub-buddies [20 -> 24) and [24 -> 28) separately. Instead of dealing with the above issues in the allocator it is much more simple to require that any GVA space is PDE aligned since they are already massive and already, in practice, have this alignment. Change-Id: I9eacd2db6485291db9f9f1d6c4c03c2a5c22de03 Signed-off-by: Alex Waterman Reviewed-on: http://git-master/r/1185137 Reviewed-by: Yu-Huan Hsu --- drivers/gpu/nvgpu/gk20a/gk20a_allocator_buddy.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_allocator_buddy.c b/drivers/gpu/nvgpu/gk20a/gk20a_allocator_buddy.c index 4ed55971..8cd1bd0b 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a_allocator_buddy.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a_allocator_buddy.c @@ -1143,6 +1143,16 @@ int __gk20a_buddy_allocator_init(struct gk20a_allocator *__a, if (flags & GPU_ALLOC_GVA_SPACE) a->pte_blk_order = balloc_get_order(a, vm->big_page_size << 10); + /* + * When we have a GVA space with big_pages enabled the size and base + * must be PDE aligned. If big_pages are not enabled then this + * requirement is not necessary. + */ + if (flags & GPU_ALLOC_GVA_SPACE && vm->big_pages && + (base & ((vm->big_page_size << 10) - 1) || + size & ((vm->big_page_size << 10) - 1))) + return -EINVAL; + a->flags = flags; a->max_order = max_order; -- cgit v1.2.2