Page MenuHomeFreeBSD

LinuxKPI: make __kmalloc() play by the rules
AcceptedPublic

Authored by bz on Sep 12 2024, 6:25 PM.
Tags
None
Referenced Files
Unknown Object (File)
Fri, Oct 18, 12:25 PM
Unknown Object (File)
Mon, Oct 14, 5:33 PM
Unknown Object (File)
Oct 9 2024, 4:34 AM
Unknown Object (File)
Oct 7 2024, 10:52 AM
Unknown Object (File)
Oct 3 2024, 5:07 PM
Unknown Object (File)
Oct 3 2024, 11:05 AM
Unknown Object (File)
Oct 3 2024, 2:35 AM
Unknown Object (File)
Oct 1 2024, 9:33 PM
Subscribers

Details

Reviewers
jhb
emaste
Group Reviewers
linuxkpi
Summary

According to Documentation/core-api/dma-api.rst kmalloc() is supposd
to provide physically contiguous memory. [1]

In order to guarantee that allocations are contiguous even if using
larger than PAGE_SIZE check the size and use contigmalloc if needed.
This makes use of 9e6544dd6e02 (and following) allowing free(9) to
also work for contigmalloced memory.

Sponsored by: The FreeBSD Foundation
Pointed out by: jhb [1]
MFC after: 3 days

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 59468
Build 56355: arc lint + arc unit

Event Timeline

bz requested review of this revision.Sep 12 2024, 6:25 PM
bz edited reviewers, added: jhb; removed: jh.Sep 12 2024, 6:28 PM

Looks reasonable to me. Aside, it seems we don't document boundary=0 in contigmalloc(9).

Looks reasonable to me. Aside, it seems we don't document boundary=0 in contigmalloc(9).

Yes, though most drivers in sys/dev do not set it; vm_page_alloc_contig documents it as

"If the boundary
parameter is non-zero, the pages constituting the run will not cross a
physical address that is a multiple of the parameter value, which must be
a power of two."

I followed a very long call chain to arrive at vm_addr_bound_ok, which confirmed -- and the nice thing is boundary == 0 doesn't even need to be a special case:

/*
 * Do the first and last addresses of a range match in all bits except the ones
 * in -boundary (a power-of-two)?  For boundary == 0, all addresses match.
 */
static inline bool
vm_addr_bound_ok(vm_paddr_t pa, vm_paddr_t size, vm_paddr_t boundary)
{                               
        KASSERT(powerof2(boundary), ("%s: boundary is not a power of 2: %#jx",
            __func__, (uintmax_t)boundary));
        return (((pa ^ (pa + size - 1)) & -boundary) == 0);
}

If I have a chance I'll propose a contigmalloc(9) addition.

sys/compat/linuxkpi/common/src/linux_slab.c
221

is this needed? (either for contigmalloc, or to match Linux KPI?)

Looking, kmem_alloc_contig_domain does asize = round_page(size); so unless we need it to be explicit about Linux behaviour perhaps just passing _s through is sensible?

bz marked an inline comment as done.Sep 12 2024, 9:03 PM
bz added inline comments.
sys/compat/linuxkpi/common/src/linux_slab.c
221

[ and so does contigmalloc itself: malloc_type_allocated(type, round_page(size)); ]

I think this is no longer needed; I'll remove it.

bz marked an inline comment as done.

simplify as @emaste pointed out; we no longer need to round up to page size.

LGTM, we can wait for @jhb as well though

This revision is now accepted and ready to land.Sep 13 2024, 1:06 AM