arm64 pmem support
Subsystems (3)
cover arm64 pmem support
Hi all,
With the latest updates to the pmem API, the arch code contribution becomes very straightforward to wire up - I think there's about as much code here to just cope with the existence of our new instruction as there is to actually make use of it. I don't have access to any NVDIMMs nor suitable hardware to put them in, so this is written purely to spec - the extent of testing has been the feature detection on a v8.2 Fast Model vs. v8.0 systems.
Patch #1 could go in as a fix ahead of the rest; it just needs to come before patch #5 to prevent that blowing up the build.
Robin.
Robin Murphy (6):
arm64: mm: Fix set_memory_valid() declaration
arm64: Convert __inval_cache_range() to area-based
arm64: Expose DC CVAP to userspace
arm64: Handle trapped DC CVAP
arm64: Implement pmem API support
arm64: uaccess: Implement *_flushcache variants
Documentation/arm64/cpu-feature-registers.txt | 2 ++ arch/arm64/Kconfig | 12 +++++++ arch/arm64/include/asm/assembler.h | 6 ++++ arch/arm64/include/asm/cacheflush.h | 4 ++- arch/arm64/include/asm/cpucaps.h | 3 +- arch/arm64/include/asm/esr.h | 3 +- arch/arm64/include/asm/string.h | 4 +++ arch/arm64/include/asm/sysreg.h | 1 + arch/arm64/include/asm/uaccess.h | 12 +++++++ arch/arm64/include/uapi/asm/hwcap.h | 1 + arch/arm64/kernel/cpufeature.c | 13 ++++++++ arch/arm64/kernel/cpuinfo.c | 1 + arch/arm64/kernel/head.S | 18 +++++----- arch/arm64/kernel/traps.c | 3 ++ arch/arm64/lib/Makefile | 2 ++ arch/arm64/lib/uaccess_flushcache.c | 47 +++++++++++++++++++++++++++ arch/arm64/mm/cache.S | 37 ++++++++++++++++----- arch/arm64/mm/pageattr.c | 18 ++++++++++ 18 files changed, 166 insertions(+), 21 deletions(-) create mode 100644 arch/arm64/lib/uaccess_flushcache.c
Signature · 6 lines
2.12.2.dirty _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
PATCH 1/6 arm64: mm: Fix set_memory_valid() declaration
Clearly, set_memory_valid() has never been seen in the same room as its declaration... Whilst the type mismatch is such that kexec probably wasn't broken in practice, fix it to match the definition as it should.
--- arch/arm64/include/asm/cacheflush.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/include/asm/cacheflush.h +1 -1
@@ -150,6 +150,6 @@ static inline void flush_cache_vunmap(unsigned long start, unsigned long end) { } -int set_memory_valid (unsigned long addr,unsigned long size,int enable); +int set_memory_valid (unsigned long addr,int numpages,int enable);#endif
Signature · 6 lines
2.12.2.dirty _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
PATCH 2/6 arm64: Convert __inval_cache_range() to area-based
In reply to Robin Murphy__inval_cache_range() is already the odd one out among our data cache maintenance routines as the only remaining range-based one; as we're going to want an invalidation routine to call from C code for the pmem API, let's tweak the prototype and name to bring it in line with the clean operations, and to make its relationship with __dma_inv_area() neatly mirror that of __clean_dcache_area_poc() and __dma_clean_area(). The loop clearing the early page tables gets mildly massaged in the process for the sake of consistency.
--- arch/arm64/include/asm/cacheflush.h | 1 + arch/arm64/kernel/head.S | 18 +++++++++--------- arch/arm64/mm/cache.S | 23 ++++++++++++++--------- 3 files changed, 24 insertions(+), 18 deletions(-)
arch/arm64/include/asm/cacheflush.h +1 -0
@@ -67,6 +67,7 @@*/ extern void flush_icache_range (unsigned long start,unsigned long end);extern void __flush_dcache_area (void *addr,size_t len); +extern void __inval_dcache_area (void *addr,size_t len);extern void __clean_dcache_area_poc (void *addr,size_t len);extern void __clean_dcache_area_pou (void *addr,size_t len);extern long __flush_cache_user_range (unsigned long start,unsigned long end);
arch/arm64/kernel/head.S +9 -9
@@ -143,8 +143,8 @@ preserve_boot_args: dmb sy // needed before dc ivac with // MMU off - add x1, x0, #0x20 // 4 x 8 bytes - b __inval_cache_range // tail call + mov x1, #0x20 // 4 x 8 bytes + b __inval_dcache_area // tail call ENDPROC(preserve_boot_args) /*
@@ -221,20 +221,20 @@ __create_page_tables: * dirty cache lines being evicted. */ adrp x0, idmap_pg_dir - adrp x1, swapper_pg_dir + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE - bl __inval_cache_range + ldr x1, =(IDMAP_DIR_SIZE + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE) + bl __inval_dcache_area /* * Clear the idmap and swapper page tables. */ adrp x0, idmap_pg_dir - adrp x6, swapper_pg_dir + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE + ldr x1, =(IDMAP_DIR_SIZE + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE) 1: stp xzr, xzr, [x0], #16 stp xzr, xzr, [x0], #16 stp xzr, xzr, [x0], #16 stp xzr, xzr, [x0], #16 - cmp x0, x6 - b.lo 1b + subs x1, x1, #64 + b.ne 1b mov x7, SWAPPER_MM_MMUFLAGS
@@ -307,9 +307,9 @@ __create_page_tables: * tables again to remove any speculatively loaded cache lines. */ adrp x0, idmap_pg_dir - adrp x1, swapper_pg_dir + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE + ldr x1, =(IDMAP_DIR_SIZE + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE) dmb sy - bl __inval_cache_range + bl __inval_dcache_area ret x28 ENDPROC(__create_page_tables)
arch/arm64/mm/cache.S +14 -9
@@ -109,20 +109,25 @@ ENTRY(__clean_dcache_area_pou) ENDPROC(__clean_dcache_area_pou) /* + * __inval_dcache_area(kaddr, size) + * + * Ensure that any D-cache lines for the interval [kaddr, kaddr+size) + * are invalidated. Any partial lines at the ends of the interval are + * also cleaned to PoC to prevent data loss. + * + * - kaddr - kernel address + * - size - size in question + */ +ENTRY(__inval_dcache_area) + /* FALLTHROUGH */ + +/* * __dma_inv_area(start, size) * - start - virtual start address of region * - size - size in question */ __dma_inv_area: add x1, x1, x0 - /* FALLTHROUGH */ - -/* - * __inval_cache_range(start, end) - * - start - start address of region - * - end - end address of region - */ -ENTRY(__inval_cache_range) dcache_line_size x2, x3 sub x3, x2, #1 tst x1, x3 // end cache line aligned?
@@ -140,7 +145,7 @@ ENTRY(__inval_cache_range) b.lo 2b dsb sy ret -ENDPIPROC(__inval_cache_range) +ENDPIPROC(__inval_dcache_area) ENDPROC(__dma_inv_area) /*
Signature · 6 lines
2.12.2.dirty _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
PATCH 3/6 arm64: Expose DC CVAP to userspace
In reply to Robin MurphyThe ARMv8.2-DCPoP feature introduces persistent memory support to the architecture, by defining a point of persistence in the memory hierarchy, and a corresponding cache maintenance operation, DC CVAP. Expose the support via HWCAP and MRS emulation.
--- Documentation/arm64/cpu-feature-registers.txt | 2 ++ arch/arm64/include/asm/sysreg.h | 1 + arch/arm64/include/uapi/asm/hwcap.h | 1 + arch/arm64/kernel/cpufeature.c | 2 ++ arch/arm64/kernel/cpuinfo.c | 1 + 5 files changed, 7 insertions(+)
Documentation/arm64/cpu-feature-registers.txt +2 -0
@@ -179,6 +179,8 @@ infrastructure: | FCMA | [19-16] | y | |--------------------------------------------------| | JSCVT | [15-12] | y | + |--------------------------------------------------| + | DPB | [3-0] | y | x--------------------------------------------------x Appendix I: Example
arch/arm64/include/asm/sysreg.h +1 -0
@@ -329,6 +329,7 @@#define ID_AA64ISAR1_LRCPC_SHIFT 20#define ID_AA64ISAR1_FCMA_SHIFT 16#define ID_AA64ISAR1_JSCVT_SHIFT 12 +#define ID_AA64ISAR1_DPB_SHIFT 0/* id_aa64pfr0 */ #define ID_AA64PFR0_GIC_SHIFT 24
arch/arm64/include/uapi/asm/hwcap.h +1 -0
@@ -35,5 +35,6 @@#define HWCAP_JSCVT (1 << 13)#define HWCAP_FCMA (1 << 14)#define HWCAP_LRCPC (1 << 15) +#define HWCAP_DCPOP (1 << 16)#endif /* _UAPI__ASM_HWCAP_H */
arch/arm64/kernel/cpufeature.c +2 -0
@@ -120,6 +120,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {ARM64_FTR_BITS (FTR_VISIBLE ,FTR_STRICT ,FTR_EXACT ,ID_AA64ISAR1_LRCPC_SHIFT ,4 ,0 ),ARM64_FTR_BITS (FTR_VISIBLE ,FTR_STRICT ,FTR_EXACT ,ID_AA64ISAR1_FCMA_SHIFT ,4 ,0 ),ARM64_FTR_BITS (FTR_VISIBLE ,FTR_STRICT ,FTR_EXACT ,ID_AA64ISAR1_JSCVT_SHIFT ,4 ,0 ), +ARM64_FTR_BITS (FTR_VISIBLE ,FTR_STRICT ,FTR_EXACT ,ID_AA64ISAR1_DPB_SHIFT ,4 ,0 ), ARM64_FTR_END, };
@@ -916,6 +917,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {HWCAP_CAP (SYS_ID_AA64PFR0_EL1 ,ID_AA64PFR0_FP_SHIFT ,FTR_SIGNED ,1 ,CAP_HWCAP ,HWCAP_FPHP ),HWCAP_CAP (SYS_ID_AA64PFR0_EL1 ,ID_AA64PFR0_ASIMD_SHIFT ,FTR_SIGNED ,0 ,CAP_HWCAP ,HWCAP_ASIMD ),HWCAP_CAP (SYS_ID_AA64PFR0_EL1 ,ID_AA64PFR0_ASIMD_SHIFT ,FTR_SIGNED ,1 ,CAP_HWCAP ,HWCAP_ASIMDHP ), +HWCAP_CAP (SYS_ID_AA64ISAR1_EL1 ,ID_AA64ISAR1_DPB_SHIFT ,FTR_UNSIGNED ,1 ,CAP_HWCAP ,HWCAP_DCPOP ),HWCAP_CAP (SYS_ID_AA64ISAR1_EL1 ,ID_AA64ISAR1_JSCVT_SHIFT ,FTR_UNSIGNED ,1 ,CAP_HWCAP ,HWCAP_JSCVT ),HWCAP_CAP (SYS_ID_AA64ISAR1_EL1 ,ID_AA64ISAR1_FCMA_SHIFT ,FTR_UNSIGNED ,1 ,CAP_HWCAP ,HWCAP_FCMA ), HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_LRCPC),
arch/arm64/kernel/cpuinfo.c +1 -0
@@ -68,6 +68,7 @@ static const char *const hwcap_str[] = {"jscvt" ,"fcma" ,"lrcpc" , +"dcpop" , NULL };
Signature · 6 lines
2.12.2.dirty _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
PATCH 4/6 arm64: Handle trapped DC CVAP
In reply to Robin MurphyCache clean to PoP is subject to the same access controls as to PoC, so if we are trapping userspace cache maintenance with SCTLR_EL1.UCI, we need to be prepared to handle it. To avoid getting into complicated fights with binutils about ARMv8.2 options, we'll just cheat and use the raw SYS instruction rather than the 'proper' DC alias.
--- arch/arm64/include/asm/esr.h | 3 ++- arch/arm64/kernel/traps.c | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-)
arch/arm64/include/asm/esr.h +2 -1
@@ -157,9 +157,10 @@/* * User space cache operations have the following sysreg encoding * in System instructions. -* op0=1, op1=3, op2=1, crn=7, crm={ 5, 10, 11, 14 }, WRITE (L=0) +* op0=1, op1=3, op2=1, crn=7, crm={ 5, 10, 11, 12, 14 }, WRITE (L=0) */ #define ESR_ELx_SYS64_ISS_CRM_DC_CIVAC 14 +#define ESR_ELx_SYS64_ISS_CRM_DC_CVAP 12#define ESR_ELx_SYS64_ISS_CRM_DC_CVAU 11#define ESR_ELx_SYS64_ISS_CRM_DC_CVAC 10#define ESR_ELx_SYS64_ISS_CRM_IC_IVAU 5
arch/arm64/kernel/traps.c +3 -0
@@ -480,6 +480,9 @@ static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)case ESR_ELx_SYS64_ISS_CRM_DC_CVAC:/* DC CVAC, gets promoted */ __user_cache_maint ("dc civac" , address, ret);break ; +case ESR_ELx_SYS64_ISS_CRM_DC_CVAP:/* DC CVAP */ +__user_cache_maint ("sys 3, c7, c12, 1" , address, ret); +break ;case ESR_ELx_SYS64_ISS_CRM_DC_CIVAC:/* DC CIVAC */ __user_cache_maint ("dc civac" , address, ret);break ;
Signature · 6 lines
2.12.2.dirty _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
PATCH 5/6 arm64: Implement pmem API support
In reply to Robin MurphyAdd a clean-to-point-of-persistence cache maintenance helper, and wire up the basic architectural support for the pmem driver based on it.
--- arch/arm64/Kconfig | 11 +++++++++++ arch/arm64/include/asm/assembler.h | 6 ++++++ arch/arm64/include/asm/cacheflush.h | 1 + arch/arm64/include/asm/cpucaps.h | 3 ++- arch/arm64/kernel/cpufeature.c | 11 +++++++++++ arch/arm64/mm/cache.S | 14 ++++++++++++++ arch/arm64/mm/pageattr.c | 18 ++++++++++++++++++ 7 files changed, 63 insertions(+), 1 deletion(-)
arch/arm64/Kconfig +11 -0
@@ -960,6 +960,17 @@ config ARM64_UAO regular load/store instructions if the cpu does not implement the feature. +config ARM64_PMEM + bool "Enable support for persistent memory" + select ARCH_HAS_PMEM_API + help + Say Y to enable support for the persistent memory API based on the + ARMv8.2 DCPoP feature. + + The feature is detected at runtime, and the kernel will use DC CVAC + operations if DC CVAP is not supported (following the behaviour of + DC CVAP itself if the system does not define a point of persistence). + endmenu config ARM64_MODULE_CMODEL_LARGE
arch/arm64/include/asm/assembler.h +6 -0
@@ -353,6 +353,12 @@ alternative_if_not ARM64_WORKAROUND_CLEAN_CACHEalternative_else dc civac, \kaddr alternative_endif + .elseif (\op == cvap) +alternative_if ARM64_HAS_DCPOP + sys 3, c7, c12, 1, \kaddr // dc cvap +alternative_else + dc cvac, \kaddr +alternative_endif .else dc \op, \kaddr .endif
arch/arm64/include/asm/cacheflush.h +1 -0
@@ -69,6 +69,7 @@ extern void flush_icache_range(unsigned long start, unsigned long end);extern void __flush_dcache_area (void *addr,size_t len);extern void __inval_dcache_area (void *addr,size_t len);extern void __clean_dcache_area_poc (void *addr,size_t len); +extern void __clean_dcache_area_pop (void *addr,size_t len);extern void __clean_dcache_area_pou (void *addr,size_t len);extern long __flush_cache_user_range (unsigned long start,unsigned long end);extern void sync_icache_aliases (void *kaddr,unsigned long len);
arch/arm64/include/asm/cpucaps.h +2 -1
@@ -39,7 +39,8 @@#define ARM64_WORKAROUND_QCOM_FALKOR_E1003 18#define ARM64_WORKAROUND_858921 19#define ARM64_WORKAROUND_CAVIUM_30115 20 +#define ARM64_HAS_DCPOP 21 -#define ARM64_NCAPS 21 +#define ARM64_NCAPS 22#endif /* __ASM_CPUCAPS_H */
arch/arm64/kernel/cpufeature.c +11 -0
@@ -889,6 +889,17 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .min_field_value = 0, .matches = has_no_fpsimd, }, +#ifdef CONFIG_ARM64_PMEM + { + .desc = "Data cache clean to Point of Persistence", + .capability = ARM64_HAS_DCPOP, + .def_scope = SCOPE_SYSTEM, + .matches = has_cpuid_feature, + .sys_reg = SYS_ID_AA64ISAR1_EL1, + .field_pos = ID_AA64ISAR1_DPB_SHIFT, + .min_field_value = 1, + }, +#endif {}, };
arch/arm64/mm/cache.S +14 -0
@@ -172,6 +172,20 @@ ENDPIPROC(__clean_dcache_area_poc) ENDPROC(__dma_clean_area) /* + * __clean_dcache_area_pop(kaddr, size) + * + * Ensure that any D-cache lines for the interval [kaddr, kaddr+size) + * are cleaned to the PoP. + * + * - kaddr - kernel address + * - size - size in question + */ +ENTRY(__clean_dcache_area_pop) + dcache_by_line_op cvap, sy, x0, x1, x2, x3 + ret +ENDPIPROC(__clean_dcache_area_pop) + +/* * __dma_flush_area(start, size) * * clean & invalidate D / U line
arch/arm64/mm/pageattr.c +18 -0
@@ -183,3 +183,21 @@ bool kernel_page_present(struct page *page) }#endif /* CONFIG_HIBERNATION */ #endif /* CONFIG_DEBUG_PAGEALLOC */ + +#ifdef CONFIG_ARCH_HAS_PMEM_API +#include <asm/cacheflush.h> + +static inline void arch_wb_cache_pmem (void *addr,size_t size) +{ +/* Ensure order against any prior non-cacheable writes */ +dmb (sy); +__clean_dcache_area_pop (addr, size); +} +EXPORT_SYMBOL_GPL (arch_wb_cache_pmem); + +static inline void arch_invalidate_pmem (void *addr,size_t size) +{ +__inval_dcache_area (addr, size); +} +EXPORT_SYMBOL_GPL (arch_invalidate_pmem); +#endif
Signature · 6 lines
2.12.2.dirty _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
Catalin Marinas
maintainerPATCH 5/6 arm64: Implement pmem API support
Two minor comments below.
Quoted 6 lines · Robin Murphy
arch/arm64/Kconfig +0
-0@@ -960,6 +960,17 @@ config ARM64_UAO regular load/store instructions if the cpu does not implement the feature.
arch/arm64/Kconfig config ARM64_UAO · line 972
Quoted 10 lines
arch/arm64/Kconfig +10
-0+config ARM64_PMEM + bool "Enable support for persistent memory" + select ARCH_HAS_PMEM_API + help + Say Y to enable support for the persistent memory API based on the + ARMv8.2 DCPoP feature. + + The feature is detected at runtime, and the kernel will use DC CVAC + operations if DC CVAP is not supported (following the behaviour of + DC CVAP itself if the system does not define a point of persistence).
Any reason not to have this default y?
Quoted 31 lines
arch/arm64/mm/cache.S +14
-0@@ -172,6 +172,20 @@ ENDPIPROC(__clean_dcache_area_poc) ENDPROC(__dma_clean_area) /* + * __clean_dcache_area_pop(kaddr, size) + * + * Ensure that any D-cache lines for the interval [kaddr, kaddr+size) + * are cleaned to the PoP. + * + * - kaddr - kernel address + * - size - size in question + */ +ENTRY(__clean_dcache_area_pop) + dcache_by_line_op cvap, sy, x0, x1, x2, x3 + ret +ENDPIPROC(__clean_dcache_area_pop) + +/* * __dma_flush_area(start, size) * * clean & invalidate D / U linearch/arm64/mm/pageattr.c +0
-0@@ -183,3 +183,21 @@ bool kernel_page_present(struct page *page) }#endif /* CONFIG_HIBERNATION */ #endif /* CONFIG_DEBUG_PAGEALLOC */
arch/arm64/mm/pageattr.c bool kernel_page_present(struct page *page) · line 195
Quoted 10 lines
arch/arm64/mm/pageattr.c +10
-0+ +#ifdef CONFIG_ARCH_HAS_PMEM_API +#include <asm/cacheflush.h> + +static inline void arch_wb_cache_pmem (void *addr,size_t size) +{ +/* Ensure order against any prior non-cacheable writes */ +dmb (sy); +__clean_dcache_area_pop (addr, size); +}
Could we keep the dmb() in the actual __clean_dcache_area_pop() implementation?
I can do the changes myself if you don't have any objections.
Signature · 5 lines
Catalin _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
PATCH 5/6 arm64: Implement pmem API support
Quoted 9 lines · Catalin Marinas
Two minor comments below.
Quoted 6 lines · Robin Murphy
arch/arm64/Kconfig +0
-0@@ -960,6 +960,17 @@ config ARM64_UAO regular load/store instructions if the cpu does not implement the feature.
Quoted 12 lines
arch/arm64/Kconfig config ARM64_UAO · line 972
Quoted 10 lines
arch/arm64/Kconfig +10
-0+config ARM64_PMEM + bool "Enable support for persistent memory" + select ARCH_HAS_PMEM_API + help + Say Y to enable support for the persistent memory API based on the + ARMv8.2 DCPoP feature. + + The feature is detected at runtime, and the kernel will use DC CVAC + operations if DC CVAP is not supported (following the behaviour of + DC CVAP itself if the system does not define a point of persistence).Any reason not to have this default y?
Mostly because it's untested, and not actually useful without some way of describing persistent memory regions to the kernel (I'm currently trying to make sense of what exactly ARCH_HAS_MMIO_FLUSH is supposed to mean in order to enable ACPI NFIT support).
There's also the potential issue that we can't disable ARCH_HAS_PMEM_API at runtime on pre-v8.2 systems where DC CVAC may not strictly give the guarantee of persistence that that is supposed to imply. However, I guess that's more of an open problem, since even on a v8.2 CPU reporting (mandatory) DC CVAP support we've still no way to actually know whether the interconnect/memory controller/etc. of any old system is up to the job. At this point I'm mostly hoping that people will only be sticking NVDIMMs into systems that *are* properly designed to support them, v8.2 CPUs or not.
Quoted 36 lines
Quoted 36 lines
arch/arm64/mm/cache.S +14
-0@@ -172,6 +172,20 @@ ENDPIPROC(__clean_dcache_area_poc) ENDPROC(__dma_clean_area) /* + * __clean_dcache_area_pop(kaddr, size) + * + * Ensure that any D-cache lines for the interval [kaddr, kaddr+size) + * are cleaned to the PoP. + * + * - kaddr - kernel address + * - size - size in question + */ +ENTRY(__clean_dcache_area_pop) + dcache_by_line_op cvap, sy, x0, x1, x2, x3 + ret +ENDPIPROC(__clean_dcache_area_pop) + +/* * __dma_flush_area(start, size) * * clean & invalidate D / U linearch/arm64/mm/pageattr.c +5
-0@@ -183,3 +183,21 @@ bool kernel_page_present(struct page *page) }#endif /* CONFIG_HIBERNATION */ #endif /* CONFIG_DEBUG_PAGEALLOC */ + +#ifdef CONFIG_ARCH_HAS_PMEM_API +#include <asm/cacheflush.h> + +static inline void arch_wb_cache_pmem (void *addr,size_t size)
Quoted 8 lines
arch/arm64/mm/pageattr.c bool kernel_page_present(struct page *page) · line 195
Quoted 5 lines
arch/arm64/mm/pageattr.c +5
-0+{ +/* Ensure order against any prior non-cacheable writes */ +dmb (sy); +__clean_dcache_area_pop (addr, size); +}Could we keep the
dmb()in the actual__clean_dcache_area_pop()implementation?
Mark held the opinion that it should follow the same pattern as the other cache maintenance primitives - e.g. we don't have such a dmb in __inval_cache_range(), but do place them at callsites where we know it may be necessary (head.S) - and I found it hard to disagree. The callers in patch #6 should never need a barrier, and arguably we may not even need this one, since it looks like pmem should currently always be mapped as MEMREMAP_WB if ARCH_HAS_PMEM_API.
Quoted 1 line
I can do the changes myself if you don't have any objections.
If you would prefer to play safe and move it back into the assembly that's fine by me, but note that the associated comments in patch #6 should also be removed if so.
Robin.
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
PATCH 5/6 arm64: Implement pmem API support
Quoted 23 lines · Robin Murphy
Quoted 9 lines · Catalin Marinas
Two minor comments below.
Quoted 6 lines · Robin Murphy
arch/arm64/Kconfig +0
-0@@ -960,6 +960,17 @@ config ARM64_UAO regular load/store instructions if the cpu does not implement the feature.Quoted 12 lines
arch/arm64/Kconfig config ARM64_UAO · line 972
Quoted 10 lines
arch/arm64/Kconfig +10
-0+config ARM64_PMEM + bool "Enable support for persistent memory" + select ARCH_HAS_PMEM_API + help + Say Y to enable support for the persistent memory API based on the + ARMv8.2 DCPoP feature. + + The feature is detected at runtime, and the kernel will use DC CVAC + operations if DC CVAP is not supported (following the behaviour of + DC CVAP itself if the system does not define a point of persistence).Any reason not to have this default y?
Quoted 4 lines
Mostly because it's untested, and not actually useful without some way of describing persistent memory regions to the kernel (I'm currently trying to make sense of what exactly
ARCH_HAS_MMIO_FLUSHis supposed to mean in order to enable ACPI NFIT support).
This is related to block-aperture support described by the NFIT where a sliding-memory-mapped window can be programmed to access different ranges of the NVDIMM. Before the window is programmed to a new DIMM-address we need to flush any dirty data through the current window setting to media. See the call to mmio_flush_range() in acpi_nfit_blk_single_io(). I think it's ok to omit ARCH_HAS_MMIO_FLUSH support, and add a configuration option to compile out the block-aperture support.
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
PATCH 5/6 arm64: Implement pmem API support
Quoted 29 lines · Dan Williams
Quoted 23 lines · Robin Murphy
Quoted 9 lines · Catalin Marinas
Two minor comments below.
Quoted 6 lines · Robin Murphy
arch/arm64/Kconfig +0
-0@@ -960,6 +960,17 @@ config ARM64_UAO regular load/store instructions if the cpu does not implement the feature.Quoted 12 lines
arch/arm64/Kconfig config ARM64_UAO · line 972
Quoted 10 lines
arch/arm64/Kconfig +10
-0+config ARM64_PMEM + bool "Enable support for persistent memory" + select ARCH_HAS_PMEM_API + help + Say Y to enable support for the persistent memory API based on the + ARMv8.2 DCPoP feature. + + The feature is detected at runtime, and the kernel will use DC CVAC + operations if DC CVAP is not supported (following the behaviour of + DC CVAP itself if the system does not define a point of persistence).Any reason not to have this default y?
Quoted 4 lines
Mostly because it's untested, and not actually useful without some way of describing persistent memory regions to the kernel (I'm currently trying to make sense of what exactly
ARCH_HAS_MMIO_FLUSHis supposed to mean in order to enable ACPI NFIT support).
Quoted 8 lines
This is related to block-aperture support described by the NFIT where a sliding-memory-mapped window can be programmed to access different ranges of the NVDIMM. Before the window is programmed to a new DIMM-address we need to flush any dirty data through the current window setting to media. See the call to
mmio_flush_range()inacpi_nfit_blk_single_io(). I think it's ok to omitARCH_HAS_MMIO_FLUSHsupport, and add a configuration option to compile out the block-aperture support.
Oh, I have every intention of implementing it one way or another if necessary - it's not difficult, it's just been a question of working through the NFIT code to figure out the subtleties of translation to arm64 ;)
If mmio_flush_range() is for true MMIO (i.e. __iomem) mappings, then arm64 should only need a barrier, rather than actual cache operations. If on the other hand it's misleadingly named and only actually used on MEMREMAP_WB mappings (as I'm staring to think it might be), then I can't help thinking it could simply go away in favour of arch_wb_pmem(), since that now seems to have those same semantics and intent, plus a much more appropriate name.
Robin.
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
PATCH 5/6 arm64: Implement pmem API support
Quoted 44 lines · Robin Murphy
Quoted 29 lines · Dan Williams
Quoted 23 lines · Robin Murphy
Quoted 9 lines · Catalin Marinas
Two minor comments below.
Quoted 6 lines · Robin Murphy
arch/arm64/Kconfig +0
-0@@ -960,6 +960,17 @@ config ARM64_UAO regular load/store instructions if the cpu does not implement the feature.Quoted 12 lines
arch/arm64/Kconfig config ARM64_UAO · line 972
Quoted 10 lines
arch/arm64/Kconfig +10
-0+config ARM64_PMEM + bool "Enable support for persistent memory" + select ARCH_HAS_PMEM_API + help + Say Y to enable support for the persistent memory API based on the + ARMv8.2 DCPoP feature. + + The feature is detected at runtime, and the kernel will use DC CVAC + operations if DC CVAP is not supported (following the behaviour of + DC CVAP itself if the system does not define a point of persistence).Any reason not to have this default y?
Quoted 4 lines
Mostly because it's untested, and not actually useful without some way of describing persistent memory regions to the kernel (I'm currently trying to make sense of what exactly
ARCH_HAS_MMIO_FLUSHis supposed to mean in order to enable ACPI NFIT support).Quoted 8 lines
This is related to block-aperture support described by the NFIT where a sliding-memory-mapped window can be programmed to access different ranges of the NVDIMM. Before the window is programmed to a new DIMM-address we need to flush any dirty data through the current window setting to media. See the call to
mmio_flush_range()inacpi_nfit_blk_single_io(). I think it's ok to omitARCH_HAS_MMIO_FLUSHsupport, and add a configuration option to compile out the block-aperture support.Oh, I have every intention of implementing it one way or another if necessary - it's not difficult, it's just been a question of working through the NFIT code to figure out the subtleties of translation to arm64 ;)
Quoted 8 lines
If
mmio_flush_range()is for true MMIO (i.e.__iomem) mappings, then arm64 should only need a barrier, rather than actual cache operations. If on the other hand it's misleadingly named and only actually used onMEMREMAP_WBmappings (as I'm staring to think it might be), then I can't help thinking it could simply go away in favour ofarch_wb_pmem(), since that now seems to have those same semantics and intent, plus a much more appropriate name.
The mapping type of block-apertures is up to the architecture, so you could mark them uncacheable and not worry about mmio_flush_range(). Also, arch_wb_pmem() is not a replacement for mmio_flush_range() since we also need the cache to be invalidated. arch_wb_pmem() is allowed to leave clean cache lines present.
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
PATCH 5/6 arm64: Implement pmem API support
In reply to Catalin MarinasQuoted 67 lines · Catalin Marinas
Two minor comments below.
Quoted 6 lines · Robin Murphy
arch/arm64/Kconfig +0
-0@@ -960,6 +960,17 @@ config ARM64_UAO regular load/store instructions if the cpu does not implement the feature.arch/arm64/Kconfig config ARM64_UAO · line 972
Quoted 10 lines
arch/arm64/Kconfig +10
-0+config ARM64_PMEM + bool "Enable support for persistent memory" + select ARCH_HAS_PMEM_API + help + Say Y to enable support for the persistent memory API based on the + ARMv8.2 DCPoP feature. + + The feature is detected at runtime, and the kernel will use DC CVAC + operations if DC CVAP is not supported (following the behaviour of + DC CVAP itself if the system does not define a point of persistence).Any reason not to have this default y?
Quoted 31 lines
arch/arm64/mm/cache.S +14
-0@@ -172,6 +172,20 @@ ENDPIPROC(__clean_dcache_area_poc) ENDPROC(__dma_clean_area) /* + * __clean_dcache_area_pop(kaddr, size) + * + * Ensure that any D-cache lines for the interval [kaddr, kaddr+size) + * are cleaned to the PoP. + * + * - kaddr - kernel address + * - size - size in question + */ +ENTRY(__clean_dcache_area_pop) + dcache_by_line_op cvap, sy, x0, x1, x2, x3 + ret +ENDPIPROC(__clean_dcache_area_pop) + +/* * __dma_flush_area(start, size) * * clean & invalidate D / U linearch/arm64/mm/pageattr.c +0
-0@@ -183,3 +183,21 @@ bool kernel_page_present(struct page *page) }#endif /* CONFIG_HIBERNATION */ #endif /* CONFIG_DEBUG_PAGEALLOC */ arch/arm64/mm/pageattr.c bool kernel_page_present(struct page *page) · line 195
Quoted 10 lines
arch/arm64/mm/pageattr.c +10
-0+ +#ifdef CONFIG_ARCH_HAS_PMEM_API +#include <asm/cacheflush.h> + +static inline void arch_wb_cache_pmem (void *addr,size_t size) +{ +/* Ensure order against any prior non-cacheable writes */ +dmb (sy); +__clean_dcache_area_pop (addr, size); +}Could we keep the
dmb()in the actual__clean_dcache_area_pop()implementation?
Quoted 1 line
I can do the changes myself if you don't have any objections.
I *think* the DMB can also be reworked to use the outer-shareable domain, much as we do for the dma_* barriers.
Will
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
PATCH 6/6 arm64: uaccess: Implement *_flushcache variants
In reply to Robin MurphyImplement the set of copy functions with guarantees of a clean cache upon completion necessary to support the pmem driver.
--- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/string.h | 4 ++++ arch/arm64/include/asm/uaccess.h | 12 ++++++++++ arch/arm64/lib/Makefile | 2 ++ arch/arm64/lib/uaccess_flushcache.c | 47 +++++++++++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+) create mode 100644 arch/arm64/lib/uaccess_flushcache.c
arch/arm64/Kconfig +1 -0
@@ -963,6 +963,7 @@ config ARM64_UAO config ARM64_PMEM bool "Enable support for persistent memory" select ARCH_HAS_PMEM_API + select ARCH_HAS_UACCESS_FLUSHCACHE help Say Y to enable support for the persistent memory API based on the ARMv8.2 DCPoP feature.
arch/arm64/include/asm/string.h +4 -0
@@ -52,6 +52,10 @@ extern void *__memset(void *, int, __kernel_size_t);#define __HAVE_ARCH_MEMCMPextern int memcmp (const void *,const void *,size_t ); +#ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE +#define __HAVE_ARCH_MEMCPY_FLUSHCACHE +void memcpy_flushcache (void *dst,const void *src,size_t cnt); +#endif #if defined(CONFIG_KASAN ) && !defined(__SANITIZE_ADDRESS__)
arch/arm64/include/asm/uaccess.h +12 -0
@@ -347,4 +347,16 @@ extern long strncpy_from_user(char *dest, const char __user *src, long count);extern __must_check long strnlen_user (const char __user *str,long n); +#ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE +struct page ; +void memcpy_page_flushcache (char *to,struct page *page,size_t offset,size_t len); +extern unsigned long __must_check __copy_user_flushcache (void *to,const void __user *from,unsigned long n); + +static inline int __copy_from_user_flushcache (void *dst,const void __user *src,unsigned size) +{ +kasan_check_write (dst, size); +return __copy_user_flushcache (dst, src, size); +} +#endif +#endif /* __ASM_UACCESS_H */
arch/arm64/lib/Makefile +2 -0
@@ -17,3 +17,5 @@ CFLAGS_atomic_ll_sc.o := -fcall-used-x0 -ffixed-x1 -ffixed-x2 \ -fcall-saved-x10 -fcall-saved-x11 -fcall-saved-x12 \ -fcall-saved-x13 -fcall-saved-x14 -fcall-saved-x15 \ -fcall-saved-x18 + +lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o
arch/arm64/lib/uaccess_flushcache.c new file +47 -0
47 lines not on this page · raw message
Signature · 6 lines
2.12.2.dirty _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
PATCH 6/6 arm64: uaccess: Implement *_flushcache variants
Quoted 12 lines · Robin Murphy
Implement the set of copy functions with guarantees of a clean cache upon completion necessary to support the pmem driver.
Signed-off-by Robin Murphy <[email protected]>--- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/string.h | 4 ++++ arch/arm64/include/asm/uaccess.h | 12 ++++++++++ arch/arm64/lib/Makefile | 2 ++ arch/arm64/lib/uaccess_flushcache.c | 47 +++++++++++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+) create mode 100644 arch/arm64/lib/uaccess_flushcache.c
[...]
Quoted 38 lines
arch/arm64/lib/uaccess_flushcache.c new file +32
-0@@ -0,0 +1,47 @@ +/* +* Copyright (C) 2017 ARM Ltd. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <linux/uaccess.h> +#include <asm/barrier.h> +#include <asm/cacheflush.h> + +void memcpy_flushcache (void *dst,const void *src,size_t cnt) +{ +/* +* We assume this should not be called with @dst pointing to +* non-cacheable memory, such that we don't need an explicit +* barrier to order the cache maintenance against the memcpy. +*/ +memcpy (dst, src, cnt); +__clean_dcache_area_pop (dst, cnt); +} +EXPORT_SYMBOL_GPL (memcpy_flushcache); +
arch/arm64/lib/uaccess_flushcache.c line 42
Quoted 10 lines
arch/arm64/lib/uaccess_flushcache.c new file +10
-0+void memcpy_page_flushcache (char *to,struct page *page,size_t offset, +size_t len) +{ +memcpy_flushcache (to,page_address (page) + offset, len); +} + +unsigned long __copy_user_flushcache (void *to,const void __user *from, +unsigned long n) +{ +unsigned long rc =__arch_copy_from_user (to, from, n);
I'm a bit nervous calling the bare user accessor here without an access_ok check beforehand. Can we rely on the caller having done the check for us? I tried to follow the breadcrumbs back out, but I noticed that other iov iterators (such as copy_from_iter) *do* do the bounds check, whereas the pmem version (copy_from_iter_nocache) doesn't appear to check the address.
Is that right?
Will
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
PATCH 6/6 arm64: uaccess: Implement *_flushcache variants
In reply to Robin MurphyQuoted 4 lines · Robin Murphy
Implement the set of copy functions with guarantees of a clean cache upon completion necessary to support the pmem driver.
Signed-off-by Robin Murphy <[email protected]>
Quoted 8 lines
--- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/string.h | 4 ++++ arch/arm64/include/asm/uaccess.h | 12 ++++++++++ arch/arm64/lib/Makefile | 2 ++ arch/arm64/lib/uaccess_flushcache.c | 47 +++++++++++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+) create mode 100644 arch/arm64/lib/uaccess_flushcache.c
It looks like Catalin applied part of this patch but forgot to add arch/arm64/lib/uaccess_flushcache.c
Arnd
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
Catalin Marinas
maintainerPATCH 6/6 arm64: uaccess: Implement *_flushcache variants
Quoted 14 lines · Arnd Bergmann
Quoted 4 lines · Robin Murphy
Implement the set of copy functions with guarantees of a clean cache upon completion necessary to support the pmem driver.
Signed-off-by Robin Murphy <[email protected]>Quoted 8 lines
--- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/string.h | 4 ++++ arch/arm64/include/asm/uaccess.h | 12 ++++++++++ arch/arm64/lib/Makefile | 2 ++ arch/arm64/lib/uaccess_flushcache.c | 47 +++++++++++++++++++++++++++++++++++++ 5 files changed, 66 insertions(+) create mode 100644 arch/arm64/lib/uaccess_flushcache.c
Quoted 2 lines
It looks like Catalin applied part of this patch but forgot to add
arch/arm64/lib/uaccess_flushcache.c
Added it now, thanks.
Signature · 5 lines
Catalin _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
cover arm64 pmem support
In reply to Robin MurphyQuoted 10 lines · Robin Murphy
With the latest updates to the pmem API, the arch code contribution becomes very straightforward to wire up - I think there's about as much code here to just cope with the existence of our new instruction as there is to actually make use of it. I don't have access to any NVDIMMs nor suitable hardware to put them in, so this is written purely to spec - the extent of testing has been the feature detection on a v8.2 Fast Model vs. v8.0 systems.
Patch #1 could go in as a fix ahead of the rest; it just needs to come before patch #5 to prevent that blowing up the build.
Modulo my two comments:
Will
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm