Page MenuHomeFreeBSD

Allow access to all accessible physical memory through /dev/mem
Needs ReviewPublic

Authored by gonzo on Dec 10 2020, 1:02 AM.

Details

Summary

Certain memory regions (like ACPI tables) may be excluded from
the available physmem as NOALLOC but they still should be accessible
to the userland tools like acpidump. Introduce new function physmem_hwregions
that generates list of all accessible physical memory regions and use
it when populating dmap mappings.

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint OK
Unit
No Unit Test Coverage
Build Status
Buildable 35784
Build 32673: arc lint + arc unit

Event Timeline

gonzo requested review of this revision.Dec 10 2020, 1:02 AM

I would prefer we don't map memory marked as noalloc in the DMAP. If we need to read it in /dev/mem then mem.c should handle unmapped memory within the DMAP region.

I would prefer we don't map memory marked as noalloc in the DMAP. If we need to read it in /dev/mem then mem.c should handle unmapped memory within the DMAP region.

I can look into it but what would be the right way to do it? I only came up with keeping the physavail list in mem.c and then check overlaps for every request. Is there any other way/API that can be used for this purpose?

pmap_kextract, although we will need to remove the DMAP check as it was added before we had a sparse DMAP region.

pmap_kextract does not do any checks if the area belongs to the sparse map or not, it just does arithmetic based on the base addresses.

We already have a PHYS_IN_DMAP check. It could be extended to also check the return value of pmap_kextract(PHYS_TO_DMAP(v)).

Ah, I think I misunderstood. By removing DMAP check, did you mean the one in pmap_kextract?

Yes, I think the fix for D27528 is to remove the DMAP check from pmap_kextract. You can then use it here in mem.c to see if the mapping is valid & fall through to uiomove_fromphys if not.

Check if region in dmap is actually present and not a "hole". Also
use pmap_mapdev to handle non-dmap physical addr accesses (as in amd64 code)
because uiomove_fromphys also avoid creating ephemeral mappings using
a check that fails on sparse dmap.

Since there seem to be no low-impact fix for this in pmap,
I think the way to go is to introduce stricter dmap check that
should be used to verify addresses that are not allocated
by the kernel's VM subsystem.

I afraid that this approach have problem on FDT based systems. FDT typically uses reserved memory regions also for secure portion of base memory (memory used by secure monitor or PSCI). And reserved memory is handled by using EXFLAG_NOALLOC -> https://cgit.freebsd.org/src/tree/sys/arm64/arm64/machdep.c#n1193
And of course this kind of memory cannot be accessed by /dev/mem.

But if kernel can access it - then it's not secure? I thought PSCI and secure monitors were supposed to be handled at a boot loader stage and be inaccessible even to the running kernel. FDT reservations were more like advisory thing (at least on RPi) to keep kernel from trampling over data in them. If kernel/module can access it, there is no reason not to provide access through /dev/mem.

Problem is that you cannot expect that (and moreover you cannot determine if) kernel can access memory describes by FDT reservation.
FDT reservation node is used for various purposes. It may be used as an advisory (i.e. for dma buffers location), as a shared memory (i.e. for framebuffer) or as hard exclusion area (i.e. for memory used in secure world) – thus inaccessible from kernel. Moreover, in last case, the implementation is allowed to generate (in rare cases) imprecise exception as result of attempt to access this protected (by trustzone hardware) memory
The FDT reservations are typically added dynamically by u-Boot or ATF -> see fdt_add_reserved_memory(). There is some chance that you can use “no-map” attribute to determine if the reservation may be accessible by kernel. For other cases you must be sure that memory is not mapped by kernel with different attributes than in u-boot or firmware -> this is architecturally undefined behavior which leads sooner or later to loss of coherency.
By all this, you cannot blindly take reserved memory as accessible by kernel and exportable by /dev/mem to userspace.
I can only recommend you try the opposite approach – explicitly map ACPI tables to kernel. I assume, that you can determine memory range where are these tables are and also than you can determine memory attributes if these are mapped by other party (ACPI).