Expand description
GPU buddy allocator bindings.
C header: include/linux/gpu_buddy.h
This module provides Rust abstractions over the Linux kernel’s GPU buddy allocator, which implements a binary buddy memory allocator.
The buddy allocator manages a contiguous address space and allocates blocks in power-of-two sizes, useful for GPU physical memory management.
§Examples
Create a buddy allocator and perform a basic range allocation:
use kernel::{
gpu::buddy::{
GpuBuddy,
GpuBuddyAllocFlags,
GpuBuddyAllocMode,
GpuBuddyParams, //
},
prelude::*,
ptr::Alignment,
sizes::*, //
};
// Create a 1GB buddy allocator with 4KB minimum chunk size.
let buddy = GpuBuddy::new(GpuBuddyParams {
base_offset: 0,
size: SZ_1G as u64,
chunk_size: Alignment::new::<SZ_4K>(),
})?;
assert_eq!(buddy.size(), SZ_1G as u64);
assert_eq!(buddy.chunk_size(), Alignment::new::<SZ_4K>());
let initial_free = buddy.avail();
// Allocate 16MB. Block lands at the top of the address range.
let allocated = KBox::pin_init(
buddy.alloc_blocks(
GpuBuddyAllocMode::Simple,
SZ_16M as u64,
Alignment::new::<SZ_16M>(),
GpuBuddyAllocFlags::default(),
),
GFP_KERNEL,
)?;
assert_eq!(buddy.avail(), initial_free - SZ_16M as u64);
let block = allocated.iter().next().expect("expected one block");
assert_eq!(block.offset(), (SZ_1G - SZ_16M) as u64);
assert_eq!(block.order(), 12); // 2^12 pages = 16MB
assert_eq!(block.size(), SZ_16M as u64);
assert_eq!(allocated.iter().count(), 1);
// Dropping the allocation returns the range to the buddy allocator.
drop(allocated);
assert_eq!(buddy.avail(), initial_free);Top-down allocation allocates from the highest addresses:
let topdown = KBox::pin_init(
buddy.alloc_blocks(
GpuBuddyAllocMode::TopDown,
SZ_16M as u64,
Alignment::new::<SZ_16M>(),
GpuBuddyAllocFlags::default(),
),
GFP_KERNEL,
)?;
assert_eq!(buddy.avail(), initial_free - SZ_16M as u64);
let block = topdown.iter().next().expect("expected one block");
assert_eq!(block.offset(), (SZ_1G - SZ_16M) as u64);
assert_eq!(block.order(), 12);
assert_eq!(block.size(), SZ_16M as u64);
// Dropping the allocation returns the range to the buddy allocator.
drop(topdown);
assert_eq!(buddy.avail(), initial_free);Non-contiguous allocation can fill fragmented memory by returning multiple blocks:
// Create fragmentation by allocating 4MB blocks at [0,4M) and [8M,12M).
let frag1 = KBox::pin_init(
buddy.alloc_blocks(
GpuBuddyAllocMode::Range(0..SZ_4M as u64),
SZ_4M as u64,
Alignment::new::<SZ_4M>(),
GpuBuddyAllocFlags::default(),
),
GFP_KERNEL,
)?;
assert_eq!(buddy.avail(), initial_free - SZ_4M as u64);
let frag2 = KBox::pin_init(
buddy.alloc_blocks(
GpuBuddyAllocMode::Range(SZ_8M as u64..(SZ_8M + SZ_4M) as u64),
SZ_4M as u64,
Alignment::new::<SZ_4M>(),
GpuBuddyAllocFlags::default(),
),
GFP_KERNEL,
)?;
assert_eq!(buddy.avail(), initial_free - SZ_8M as u64);
// Allocate 8MB, this returns 2 blocks from the holes.
let fragmented = KBox::pin_init(
buddy.alloc_blocks(
GpuBuddyAllocMode::Range(0..SZ_16M as u64),
SZ_8M as u64,
Alignment::new::<SZ_4M>(),
GpuBuddyAllocFlags::default(),
),
GFP_KERNEL,
)?;
assert_eq!(buddy.avail(), initial_free - SZ_16M as u64);
let (mut count, mut total) = (0u32, 0u64);
for block in fragmented.iter() {
assert_eq!(block.size(), SZ_4M as u64);
total += block.size();
count += 1;
}
assert_eq!(total, SZ_8M as u64);
assert_eq!(count, 2);Contiguous allocation fails when only fragmented space is available:
// Create a small 16MB buddy allocator with fragmented memory.
let small = GpuBuddy::new(GpuBuddyParams {
base_offset: 0,
size: SZ_16M as u64,
chunk_size: Alignment::new::<SZ_4K>(),
})?;
let _hole1 = KBox::pin_init(
small.alloc_blocks(
GpuBuddyAllocMode::Range(0..SZ_4M as u64),
SZ_4M as u64,
Alignment::new::<SZ_4M>(),
GpuBuddyAllocFlags::default(),
),
GFP_KERNEL,
)?;
let _hole2 = KBox::pin_init(
small.alloc_blocks(
GpuBuddyAllocMode::Range(SZ_8M as u64..(SZ_8M + SZ_4M) as u64),
SZ_4M as u64,
Alignment::new::<SZ_4M>(),
GpuBuddyAllocFlags::default(),
),
GFP_KERNEL,
)?;
// 8MB contiguous should fail, only two non-contiguous 4MB holes exist.
let result = KBox::pin_init(
small.alloc_blocks(
GpuBuddyAllocMode::Simple,
SZ_8M as u64,
Alignment::new::<SZ_4M>(),
GpuBuddyAllocFlag::Contiguous,
),
GFP_KERNEL,
);
assert!(result.is_err());Structs§
- Allocated
Block - A buddy block paired with its owning
AllocatedBlockscontext. - Allocated
Blocks - Allocated blocks from the buddy allocator with automatic cleanup.
- GpuBuddy
- GPU buddy allocator instance.
- GpuBuddy
Alloc Flags - Modifier flags for GPU buddy allocation.
- GpuBuddy
Params - Parameters for creating a GPU buddy allocator.
Enums§
- GpuBuddy
Alloc Flag - Individual modifier flag for GPU buddy allocation.
- GpuBuddy
Alloc Mode - Allocation mode for the GPU buddy allocator.