Port-arm archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Raspberry Pi 3B: /dev/mem mmap GPIO works on earmv7hf but not onaarch64
I wrote:
> On the other hand, pmap_mmap_flags() (which is undocumented in pmap(9))
> exists, at least on aarch64 and x86, and looks like a place where
> mapping attributes for mmap(2) could be decided.
The following changes against aarch64 specific pmap_mmap_flags()
makes "mmap(2) GPIO via /dev/mem" work:
https://github.com/tsutsui/netbsd-src/commit/567111726df3fd5180ac7a81266be9fefa2c6ce4
---
aarch64: fix /dev/mem mmap cookie handling for MMIO devices
On aarch64, /dev/mem mmap(2) commonly returns an mmap cookie
without explicit MD ARM_MMAP_* attribute bits (nflag == 0) because
there is no MD hook in current MI mem(4) implementation.
In that case the mapping may end up as normal cacheable memory,
which breaks MMIO register access.
Adjust aarch64_mmap_flags(mdpgno) to return PMAP_DEV_NP only for
the narrow case where:
- AARCH64_MMAP_* bits are 0
(note AARCH64_MMAP_WRITEBACK is also 0 so "unspecified" is ambiguous),
- the PA is unmanaged (PHYS_TO_VM_PAGE(pa) == NULL), and
- the PA is within a devmap region (pmap_devmap_find_pa() != NULL).
Explicit cookie attributes (DEVICE, WRITECOMBINE, NOCACHE, and
WRITEBACK against managed or non-devmap memory) are still decoded
as before.
---
diff --git a/sys/arch/aarch64/aarch64/pmap.c b/sys/arch/aarch64/aarch64/pmap.c
index 53063d9dc92f..cff9859d5b8e 100644
--- a/sys/arch/aarch64/aarch64/pmap.c
+++ b/sys/arch/aarch64/aarch64/pmap.c
@@ -2755,6 +2755,59 @@ pmap_is_referenced(struct vm_page *pg)
return false;
}
+u_int
+aarch64_mmap_flags(paddr_t mdpgno)
+{
+ u_int nflag, pflag;
+ paddr_t pa;
+
+ /*
+ * aarch64 arch has 5 memory attributes defined:
+ *
+ * WriteBack - write back cache
+ * WriteThru - write through cache
+ * NoCache - no cache
+ * Device(nGnRE) - no Gathering, no Reordering, Early write ack
+ * Device(nGnRnE) - no Gathering, no Reordering, no Early write ack
+ *
+ * but pmap has PMAP_{NOCACHE,WRITE_COMBINE,WRITE_BACK} flags.
+ */
+
+ nflag = (mdpgno >> AARCH64_MMAP_FLAG_SHIFT) & AARCH64_MMAP_FLAG_MASK;
+
+ /*
+ * If AARCH64_MMAP_FLAG is 0 (i.e. no way to distinguish explicit
+ * AARCH64_MMAP_WRITEBACK from "0" as "not specified"),
+ * the specified page is unmanaged and is within devmap region,
+ * assume MMIO device mappings.
+ */
+ pa = pmap_phys_address(mdpgno);
+ if (nflag == 0 &&
+ PHYS_TO_VM_PAGE(pa) == NULL &&
+ pmap_devmap_find_pa(pa, PAGE_SIZE) != NULL) {
+ return PMAP_DEV_NP;
+ }
+
+ switch (nflag) {
+ case AARCH64_MMAP_DEVICE:
+ pflag = PMAP_DEV;
+ break;
+ case AARCH64_MMAP_WRITECOMBINE:
+ pflag = PMAP_WRITE_COMBINE;
+ break;
+ case AARCH64_MMAP_WRITEBACK:
+ pflag = PMAP_WRITE_BACK;
+ break;
+ case AARCH64_MMAP_NOCACHE:
+ pflag = PMAP_NOCACHE;
+ break;
+ default:
+ pflag = PMAP_NOCACHE;
+ break;
+ }
+ return pflag;
+}
+
/* get pointer to kernel segment L2 or L3 table entry */
pt_entry_t *
kvtopte(vaddr_t va)
diff --git a/sys/arch/aarch64/include/pmap.h b/sys/arch/aarch64/include/pmap.h
index 3721dcac4dfe..6103d40e479b 100644
--- a/sys/arch/aarch64/include/pmap.h
+++ b/sys/arch/aarch64/include/pmap.h
@@ -189,41 +189,7 @@ paddr_t vtophys(vaddr_t);
#define PMAP_DEV_NP 0x40000000 /* kenter_pa */
#define PMAP_DEV_MASK (PMAP_DEV | PMAP_DEV_NP)
-static inline u_int
-aarch64_mmap_flags(paddr_t mdpgno)
-{
- u_int nflag, pflag;
-
- /*
- * aarch64 arch has 5 memory attributes defined:
- *
- * WriteBack - write back cache
- * WriteThru - write through cache
- * NoCache - no cache
- * Device(nGnRE) - no Gathering, no Reordering, Early write ack
- * Device(nGnRnE) - no Gathering, no Reordering, no Early write ack
- *
- * but pmap has PMAP_{NOCACHE,WRITE_COMBINE,WRITE_BACK} flags.
- */
-
- nflag = (mdpgno >> AARCH64_MMAP_FLAG_SHIFT) & AARCH64_MMAP_FLAG_MASK;
- switch (nflag) {
- case AARCH64_MMAP_DEVICE:
- pflag = PMAP_DEV;
- break;
- case AARCH64_MMAP_WRITECOMBINE:
- pflag = PMAP_WRITE_COMBINE;
- break;
- case AARCH64_MMAP_WRITEBACK:
- pflag = PMAP_WRITE_BACK;
- break;
- case AARCH64_MMAP_NOCACHE:
- default:
- pflag = PMAP_NOCACHE;
- break;
- }
- return pflag;
-}
+u_int aarch64_mmap_flags(paddr_t);
#define pmap_phys_address(ppn) aarch64_ptob((ppn) & ~ARM_MMAP_MASK)
#define pmap_mmap_flags(ppn) aarch64_mmap_flags((ppn))
---
(moved from pmap.h to pmap.c because it's a bit complicated to use
PHYS_TO_VM_PAGE() (requires <uvm/uvm_page.h>) in an inline function)
The following additional change is just for readability:
https://github.com/tsutsui/netbsd-src/commit/0abc3913ad412488a74c3360bc951d16be034e6d
---
aarch64/pmap: explicitly strip ARM_MMAP_* bits in pmap_phys_address()
ARM_MMAP_* bits are placed higher bits in mdpgno so they will implicitly
be dropped after aarch64_ptob() (i.e. << PGSHIFT) op, but it's
a bit confusing for readers to depend on implementation details.
---
diff --git a/sys/arch/aarch64/include/pmap.h b/sys/arch/aarch64/include/pmap.h
index 52f909696cf8..3721dcac4dfe 100644
--- a/sys/arch/aarch64/include/pmap.h
+++ b/sys/arch/aarch64/include/pmap.h
@@ -225,7 +225,7 @@ aarch64_mmap_flags(paddr_t mdpgno)
return pflag;
}
-#define pmap_phys_address(pa) aarch64_ptob((pa))
+#define pmap_phys_address(ppn) aarch64_ptob((ppn) & ~ARM_MMAP_MASK)
#define pmap_mmap_flags(ppn) aarch64_mmap_flags((ppn))
void pmap_bootstrap(vaddr_t, vaddr_t);
---
Izumi Tsutsui
Home |
Main Index |
Thread Index |
Old Index