on top of pmap_qmapdev_attr function.
Required by i915kms to support recent discrete graphics cards.
Details
- Reviewers
bz dumbbell kib - Group Reviewers
linuxkpi - Commits
- rGdf49fd8efa1a: LinuxKPI: Implement vmap_pfn
Diff Detail
- Repository
- rG FreeBSD src repository
- Lint
Lint Skipped - Unit
Tests Skipped - Build Status
Buildable 69273 Build 66156: arc lint + arc unit
Event Timeline
| sys/compat/linuxkpi/common/src/linux_page.c | ||
|---|---|---|
| 445 | Can we please call it linuxkpi_. I believe it's getting to the point where in the last year we consistently started doing that for official LinuxKPI functions and lkpi_ for otherwise. There was a time before when we were 50:50 split. It'll be hard enough to get rid of the linux_ prefix one day so let's try to be consistent. | |
| 460 | If I understand correctly vmap_pfn is used by discrete graphics cards? That means they can show up in any of the other architectures as well? So this and D54224 should likely be implemented for more architectures. Is there a plan for that? I think this (a) should use `%s, func``` and (b) needs a comment as-to why it is only implemented for amd64 and nothing else. | |
| sys/compat/linuxkpi/common/src/linux_page.c | ||
|---|---|---|
| 445 | Is the prot argument about protection, or the cache attributes? I assume the later, and my further response depends on it. | |
| 456 | I suggest to not even try to add pmap_qmapdev_attr(). The problem with the code in D54224 is that it misses ensuring that all mappings have consistent caching mode. This is required e.g. by IA32 (and I am sure by all other arches where FreeBSD runs). The following snippet should be not too far from the working code bool
f(vm_offset_t va, vm_paddr_r pa, vm_memattr_t mattr)
{
vm_page_t m;
m = PHYS_TO_VM_PAGE(pa);
if (m == NULL)
return (false);
pmap_page_set_memattr(m, mattr);
pmap_qenter(va, &m, 1);
return (true);
}And then, if the pmap layer is informed about the desired mapping caching, just pmap_qenter() works. | |
| 460 | Hopefully this panic() call would go away in the next iteration. | |
| sys/compat/linuxkpi/common/src/linux_page.c | ||
|---|---|---|
| 445 | Later. LinuxKPI does not use protection bits only cache ones. | |
| 456 | I am not sure that pmap_qenter() can be used here. Linux has 2 functions:
The later exists as device memory isn`t backed by pages at least in Linux that means one can not pass array of page references to vmap() as these pages do not exist. That is why map_pfn() which accepts array of page indexes was created. I think the same can be applied to FreeBSD. IIRC while debugging this about year ago I got NULL pointer dereferences in vtoslab() called from is_vmalloc_addr() that is why is_vmalloc_addr() is changed in this review too. Unfortunately, github garbage-collected crash report so I am not absolutely sure of it. | |
| 460 | Only recent Intel A* use vmap_pfn(). I very doubt i915kms works on other than amd64 or i386 | |
| sys/compat/linuxkpi/common/src/linux_page.c | ||
|---|---|---|
| 456 | Which kind of BAR? If it is io BAR, then it is normally located in below 4G, which is covered by DMAP, and then keeping consistent caching attributes is crusial. If it is an aperture-like BAR, which might be located in above 4G, which is typical for resizable BARs cards generation, then GEM needs to have PHYS_TO_VM_PAGE() working for many reasons, most important is the possibility of mapping it into userspace. So it must be registered with vm_phys_fictitious_reg_range(). That said, it is very easy to make pmap_qenter() to work with even unregistered uncovered by vm_page_array BAR: void
f(vm_offset_t va, vm_paddr_r pa, vm_memattr_t mattr)
{
struct vm_page fm;
vm_page_t m;
m = PHYS_TO_VM_PAGE(pa);
if (m == NULL) {
m = &fm;
vm_page_initfake(m, pa, mattr);
} else {
pmap_page_set_memattr(m, mattr);
}
pmap_qenter(va, &m, 1);
} | |
| sys/compat/linuxkpi/common/src/linux_page.c | ||
|---|---|---|
| 456 | I never hold this device in my hands. I think it is memory BAR as AFAIR mapped region was used to upload firmware blob to device with simple memcpy(), I do not know if it must be registered with vm_phys_fictitious_reg_range() or not. If it woudn't do a harm, I would add it to both map and unmap functions. | |
| sys/compat/linuxkpi/common/src/linux_page.c | ||
|---|---|---|
| 353 | ||
| 454 | ||
| 468 | I am not sure that doing such malloc() is good idea. If this might be used for mapping real apertures, I believe sizes like 1G and larger are expected. Now, for 1G on amd64, we need 1G/4096 == 256K vm_pages, which gives us sizeof(ma) == 256K*8 == 2M. This is on the edge of the reasonable size for the kernel malloc. But for fma, where sizeof(struct vm_page) == 88, we get the allocation size of ~22M, which is too heavy. Kernel might not have that much contiguous KVA due to fragmentation. | |