Skip to content

Frame::new_contiguous does not guarantee physical-address alignment #356

Description

@liulog

Description

Frame::new_contiguous(frame_count, align_to) claims to allocate contiguous physical pages aligned to align_to, but the returned physical address is not actually guaranteed to be aligned to align_to.
Typical trigger: the RISC-V G-stage root page table requires 16 KiB contiguous memory that is also 16 KiB aligned. The code allocates it via
Frame::new_contiguous(4, 16 * 1024) (see src/arch/riscv64/paging.rs), but the resulting physical address may be only 4 KiB aligned, violating the hardware requirement.

Root cause

Allocation is backed by bitmap_allocator, whose alloc_contiguous(size, align_log2) aligns the returned bitmap index idx.
The final physical address is composed as (src/memory/frame.rs):

idx * PAGE_SIZE + self.base
  • idx * PAGE_SIZE is indeed aligned to 2^align_log2 * PAGE_SIZE;
  • but self.base is then added on top.

And self.base is only aligned to PAGE_SIZE (4 KiB) in init, via align_up:

fn init(&mut self, base: PhysAddr, size: usize) {
    self.base = align_up(base); // 4 KiB alignment only
    ...
}

The origin of base is mem_pool_start = __core_end + MAX_CPU_NUM * PER_CPU_SIZE:

  • __core_end is only . = ALIGN(4K) in the linker scripts (4 KiB aligned);
  • PER_CPU_SIZE = 512 KiB is a multiple of 16 KiB, so it does not change the phase;
  • PHYS_VIRT_OFFSET used by virt_to_phys is not guaranteed to be 16 KiB aligned.

Therefore the 16 KiB phase of base is undefined. When base is not 16 KiB aligned, adding it to idx * PAGE_SIZE (which is 16 KiB aligned) yields a final physical address that is no longer 16 KiB aligned — only 4 KiB alignment holds.

Conclusion: the alignment applies to the index relative to base, while the phase of base breaks the alignment guarantee on the final physical address.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions