Change various kernel APIs to work with pointers instead of vm_offset_t#2068
Change various kernel APIs to work with pointers instead of vm_offset_t#2068bsdjhb wants to merge 19 commits intofreebsd:mainfrom
Conversation
No functional change, but this is friendlier for CHERI.
This removes the need for several casts to pointer in callers.
Add explicit uintptr_t casts to the arguments to these macros so that the work both with virtual addresses (e.g. vm_offset_t) and pointers. Drop no-longer-needed casts in various invocations of DMAP_TO_PHYS.
Consistently use vm_paddr_t for the type returned from moea64_bootstrap_alloc and avoid temporarily smuggling it via a pointer. Instead, be explicit in the places that assume a 1:1 mapping.
|
The justification makes sense to me. What I worry is mixing My suggestion is creating a typedef to |
|
|
||
| static int | ||
| pmap_change_props_locked(vm_offset_t va, vm_size_t size, vm_prot_t prot, | ||
| pmap_change_props_locked(void *addr, vm_size_t size, vm_prot_t prot, |
There was a problem hiding this comment.
I am not sure about this change. pmap_change_props() operates on address/page table, not on the pointer.
There was a problem hiding this comment.
Yes, this one was more about a tradeoff of casts in callers vs just one here, and yes it is a bit more squirrely.
| int error; | ||
| bool changed; | ||
|
|
||
| va = (vm_offset_t)addr; |
There was a problem hiding this comment.
And the fact that you have to immediately cast the address to vm_offset_t aligns with my doubts.
| ("physical address %#jx not covered by the DMAP", \ | ||
| (uintmax_t)x)); \ | ||
| (x) + kva_layout.dmap_low; }) | ||
| (void *)((x) + kva_layout.dmap_low); }) |
There was a problem hiding this comment.
I think this change is fine. But I suggest to provide a macro, lets call it PHYS_TO_DMAP_ADDR(), which is identical to the old PHYS_TO_DMAP(), which returns the address. Then PHYS_TO_DMAP() becomes ((void *)PHYS_TO_DMAP_ADDR()).
PHYS_TO_DMA_ADDR() should be used where you immediately cast PHYS_TO_DMAP() result back to address.
| #define VIRT_IN_DMAP(va) \ | ||
| ((va) >= kva_layout.dmap_low && (va) < kva_layout.dmap_low + dmaplimit) | ||
| #define VIRT_IN_DMAP(va) \ | ||
| ((uintptr_t)(va) >= kva_layout.dmap_low && \ |
There was a problem hiding this comment.
I would suggest to add a local of the uintptr_t type and evaluate and cast the 'va' arg only once.
| if (pmap->pm_pmltopu != NULL) { | ||
| m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pmap-> | ||
| pm_pmltopu)); | ||
| m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS(pmap->pm_pmltopu)); |
There was a problem hiding this comment.
Might be we need DMAP_TO_VM_PAGE() ?
There was a problem hiding this comment.
Certainly this is a common pattern. Such a macro could also be MI as it would be spelled the same on all architectures.
BSD has a legacy typedef (caddr_t), but we generally avoid that in new code. Also, I think the only place that might be char * in this series is td_kstack? |
I would avoid
I see But actually, we can address this by adding a note to style(9). e.g.:
and use |
kostikbel
left a comment
There was a problem hiding this comment.
This one seems to be rather arbitrary. The patch adds more casts than it removes. Also, the kva is internal member which denotes the address which is used for page table manipulation (pmap_qenter()) and not a pointer that is operated upon. The single cast in sf_buf_kva() seems more proper to me.
|
sf_buf_kva's returned value is used as a pointer, and in the non-DMAP + SFBUF case that pointer comes from the kva member. Yes, it's true that all supported CHERI architectures have a DMAP, but we should be consistent with types. |
In CHERI kernels, pointers are not the same size as addresses, and vm_offset_t represents a virtual address (ptraddr_t). To handle places that use vm_offset_t to hold pointers that can be dereferenced by the CPU, CheriBSD adds a new vm_pointer_t type (uintptr_t). However, using vm_pointer_t can be a bit fragile, as C compilers will silently accept conversions between uintptr_t and ptraddr_t. The resulting errors can only be found at runtime. However, if pointers are stored as a pointer type such as void *, then mismatches between addresses and pointers can be caught at compile time including when compiling on non-CHERI architectures. As such, this series converts various kernel pmap/virtual memory kernel APIs that currently use vm_offset_t to use pointer types (either void * or char *) instead. Normally void * is used, but char * is preferred if the API or structure member is commonly used in pointer arithmetic. In practice, these changes seem to be cleaner as most kernel consumers for many of these APIs had to cast between pointer types and vm_offset_t anyway and now those casts can be removed.
Note, when landing this series, I will add a commit to bump __FreeBSD_version so that kmods in ports can handle these changes, but it's pointless to add that commit until this is actually landed. This would also not be a MFC candidate.
Also, this seems too unwieldy to review in phabricator, hence reviewing here.