Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 14/20] arm64: erratum: Work around Falkor erratum #E1003 in trampoline code
From: Will Deacon @ 2017-12-06 12:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512563739-25239-1-git-send-email-will.deacon@arm.com>

We rely on an atomic swizzling of TTBR1 when transitioning from the entry
trampoline to the kernel proper on an exception. We can't rely on this
atomicity in the face of Falkor erratum #E1003, so on affected cores we
can issue a TLB invalidation to invalidate the walk cache prior to
jumping into the kernel. There is still the possibility of a TLB conflict
here due to conflicting walk cache entries prior to the invalidation, but
this doesn't appear to be the case on these CPUs in practice.

Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/Kconfig        | 17 +++++------------
 arch/arm64/kernel/entry.S | 12 ++++++++++++
 2 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index a93339f5178f..fdcc7b9bb15d 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -522,20 +522,13 @@ config CAVIUM_ERRATUM_30115
 config QCOM_FALKOR_ERRATUM_1003
 	bool "Falkor E1003: Incorrect translation due to ASID change"
 	default y
-	select ARM64_PAN if ARM64_SW_TTBR0_PAN
 	help
 	  On Falkor v1, an incorrect ASID may be cached in the TLB when ASID
-	  and BADDR are changed together in TTBRx_EL1. The workaround for this
-	  issue is to use a reserved ASID in cpu_do_switch_mm() before
-	  switching to the new ASID. Saying Y here selects ARM64_PAN if
-	  ARM64_SW_TTBR0_PAN is selected. This is done because implementing and
-	  maintaining the E1003 workaround in the software PAN emulation code
-	  would be an unnecessary complication. The affected Falkor v1 CPU
-	  implements ARMv8.1 hardware PAN support and using hardware PAN
-	  support versus software PAN emulation is mutually exclusive at
-	  runtime.
-
-	  If unsure, say Y.
+	  and BADDR are changed together in TTBRx_EL1. Since we keep the ASID
+	  in TTBR1_EL1, this situation only occurs in the entry trampoline and
+	  then only for entries in the walk cache, since the leaf translation
+	  is unchanged. Work around the erratum by invalidating the walk cache
+	  entries for the trampoline before entering the kernel proper.
 
 config QCOM_FALKOR_ERRATUM_1009
 	bool "Falkor E1009: Prematurely complete a DSB after a TLBI"
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 39e3873b8d5a..ce56592b5f70 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -989,6 +989,18 @@ __ni_sys_trace:
 	sub	\tmp, \tmp, #(SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE)
 	bic	\tmp, \tmp, #USER_ASID_FLAG
 	msr	ttbr1_el1, \tmp
+#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
+alternative_if ARM64_WORKAROUND_QCOM_FALKOR_E1003
+	/* ASID already in \tmp[63:48] */
+	movk	\tmp, #:abs_g2_nc:(TRAMP_VALIAS >> 12)
+	movk	\tmp, #:abs_g1_nc:(TRAMP_VALIAS >> 12)
+	/* 2MB boundary containing the vectors, so we nobble the walk cache */
+	movk	\tmp, #:abs_g0_nc:((TRAMP_VALIAS & ~(SZ_2M - 1)) >> 12)
+	isb
+	tlbi	vae1, \tmp
+	dsb	nsh
+alternative_else_nop_endif
+#endif /* CONFIG_QCOM_FALKOR_ERRATUM_1003 */
 	.endm
 
 	.macro tramp_unmap_kernel, tmp
-- 
2.1.4

^ permalink raw reply related

* [PATCH v3 15/20] arm64: tls: Avoid unconditional zeroing of tpidrro_el0 for native tasks
From: Will Deacon @ 2017-12-06 12:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512563739-25239-1-git-send-email-will.deacon@arm.com>

When unmapping the kernel at EL0, we use tpidrro_el0 as a scratch register
during exception entry from native tasks and subsequently zero it in
the kernel_ventry macro. We can therefore avoid zeroing tpidrro_el0
in the context-switch path for native tasks using the entry trampoline.

Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/kernel/process.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index b2adcce7bc18..aba3a1fb492d 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -361,16 +361,14 @@ void tls_preserve_current_state(void)
 
 static void tls_thread_switch(struct task_struct *next)
 {
-	unsigned long tpidr, tpidrro;
-
 	tls_preserve_current_state();
 
-	tpidr = *task_user_tls(next);
-	tpidrro = is_compat_thread(task_thread_info(next)) ?
-		  next->thread.tp_value : 0;
+	if (is_compat_thread(task_thread_info(next)))
+		write_sysreg(next->thread.tp_value, tpidrro_el0);
+	else if (!arm64_kernel_unmapped_at_el0())
+		write_sysreg(0, tpidrro_el0);
 
-	write_sysreg(tpidr, tpidr_el0);
-	write_sysreg(tpidrro, tpidrro_el0);
+	write_sysreg(*task_user_tls(next), tpidr_el0);
 }
 
 /* Restore the UAO state depending on next's addr_limit */
-- 
2.1.4

^ permalink raw reply related

* [PATCH v3 16/20] arm64: entry: Add fake CPU feature for unmapping the kernel at EL0
From: Will Deacon @ 2017-12-06 12:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512563739-25239-1-git-send-email-will.deacon@arm.com>

Allow explicit disabling of the entry trampoline on the kernel command
line (kpti=off) by adding a fake CPU feature (ARM64_UNMAP_KERNEL_AT_EL0)
that can be used to toggle the alternative sequences in our entry code and
avoid use of the trampoline altogether if desired. This also allows us to
make use of a static key in arm64_kernel_unmapped_at_el0().

Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/include/asm/cpucaps.h |  3 ++-
 arch/arm64/include/asm/mmu.h     |  3 ++-
 arch/arm64/kernel/cpufeature.c   | 41 ++++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/entry.S        |  9 +++++----
 4 files changed, 50 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 2ff7c5e8efab..b4537ffd1018 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -41,7 +41,8 @@
 #define ARM64_WORKAROUND_CAVIUM_30115		20
 #define ARM64_HAS_DCPOP				21
 #define ARM64_SVE				22
+#define ARM64_UNMAP_KERNEL_AT_EL0		23
 
-#define ARM64_NCAPS				23
+#define ARM64_NCAPS				24
 
 #endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index c07954638658..da6f12e40714 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -36,7 +36,8 @@ typedef struct {
 
 static inline bool arm64_kernel_unmapped_at_el0(void)
 {
-	return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0);
+	return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0) &&
+	       cpus_have_const_cap(ARM64_UNMAP_KERNEL_AT_EL0);
 }
 
 extern void paging_init(void);
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index c5ba0097887f..98e6563015a4 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -845,6 +845,40 @@ static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unus
 					ID_AA64PFR0_FP_SHIFT) < 0;
 }
 
+#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
+static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
+
+static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
+				int __unused)
+{
+	/* Forced on command line? */
+	if (__kpti_forced) {
+		pr_info("kernel page table isolation forced %s by command line option\n",
+			__kpti_forced > 0 ? "ON" : "OFF");
+		return __kpti_forced > 0;
+	}
+
+	/* Useful for KASLR robustness */
+	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
+		return true;
+
+	return false;
+}
+
+static int __init parse_kpti(char *str)
+{
+	bool enabled;
+	int ret = strtobool(str, &enabled);
+
+	if (ret)
+		return ret;
+
+	__kpti_forced = enabled ? 1 : -1;
+	return 0;
+}
+__setup("kpti=", parse_kpti);
+#endif	/* CONFIG_UNMAP_KERNEL_AT_EL0 */
+
 static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "GIC system register CPU interface",
@@ -931,6 +965,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
 		.def_scope = SCOPE_SYSTEM,
 		.matches = hyp_offset_low,
 	},
+#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
+	{
+		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
+		.def_scope = SCOPE_SYSTEM,
+		.matches = unmap_kernel_at_el0,
+	},
+#endif
 	{
 		/* FP/SIMD is not implemented */
 		.capability = ARM64_HAS_NO_FPSIMD,
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index ce56592b5f70..5d51bdbb2131 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -74,6 +74,7 @@
 	.macro kernel_ventry, el, label, regsize = 64
 	.align 7
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
+alternative_if ARM64_UNMAP_KERNEL_AT_EL0
 	.if	\el == 0
 	.if	\regsize == 64
 	mrs	x30, tpidrro_el0
@@ -82,6 +83,7 @@
 	mov	x30, xzr
 	.endif
 	.endif
+alternative_else_nop_endif
 #endif
 
 	sub	sp, sp, #S_FRAME_SIZE
@@ -323,10 +325,9 @@ alternative_else_nop_endif
 	ldr	lr, [sp, #S_LR]
 	add	sp, sp, #S_FRAME_SIZE		// restore sp
 
-#ifndef CONFIG_UNMAP_KERNEL_AT_EL0
-	eret
-#else
 	.if	\el == 0
+alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
+#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 	bne	4f
 	msr	far_el1, x30
 	tramp_alias	x30, tramp_exit_native
@@ -334,10 +335,10 @@ alternative_else_nop_endif
 4:
 	tramp_alias	x30, tramp_exit_compat
 	br	x30
+#endif
 	.else
 	eret
 	.endif
-#endif
 	.endm
 
 	.macro	irq_stack_entry
-- 
2.1.4

^ permalink raw reply related

* [PATCH v3 17/20] arm64: Kconfig: Add CONFIG_UNMAP_KERNEL_AT_EL0
From: Will Deacon @ 2017-12-06 12:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512563739-25239-1-git-send-email-will.deacon@arm.com>

Add a Kconfig entry to control use of the entry trampoline, which allows
us to unmap the kernel whilst running in userspace and improve the
robustness of KASLR.

Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/Kconfig | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index fdcc7b9bb15d..3af1657fcac3 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -833,6 +833,19 @@ config FORCE_MAX_ZONEORDER
 	  However for 4K, we choose a higher default value, 11 as opposed to 10, giving us
 	  4M allocations matching the default size used by generic code.
 
+config UNMAP_KERNEL_AT_EL0
+	bool "Unmap kernel when running in userspace (aka \"KAISER\")"
+	default y
+	help
+	  Some attacks against KASLR make use of the timing difference between
+	  a permission fault which could arise from a page table entry that is
+	  present in the TLB, and a translation fault which always requires a
+	  page table walk. This option defends against these attacks by unmapping
+	  the kernel whilst running in userspace, therefore forcing translation
+	  faults for all of kernel space.
+
+	  If unsure, say Y.
+
 menuconfig ARMV8_DEPRECATED
 	bool "Emulate deprecated/obsolete ARMv8 instructions"
 	depends on COMPAT
-- 
2.1.4

^ permalink raw reply related

* [PATCH v3 18/20] perf: arm_spe: Fail device probe when arm64_kernel_unmapped_at_el0()
From: Will Deacon @ 2017-12-06 12:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512563739-25239-1-git-send-email-will.deacon@arm.com>

When running with the kernel unmapped whilst at EL0, the virtually-addressed
SPE buffer is also unmapped, which can lead to buffer faults if userspace
profiling is enabled and potentially also when writing back kernel samples
unless an expensive drain operation is performed on exception return.

For now, fail the SPE driver probe when arm64_kernel_unmapped_at_el0().

Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 drivers/perf/arm_spe_pmu.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c
index 8ce262fc2561..51b40aecb776 100644
--- a/drivers/perf/arm_spe_pmu.c
+++ b/drivers/perf/arm_spe_pmu.c
@@ -1164,6 +1164,15 @@ static int arm_spe_pmu_device_dt_probe(struct platform_device *pdev)
 	struct arm_spe_pmu *spe_pmu;
 	struct device *dev = &pdev->dev;
 
+	/*
+	 * If kernelspace is unmapped when running at EL0, then the SPE
+	 * buffer will fault and prematurely terminate the AUX session.
+	 */
+	if (arm64_kernel_unmapped_at_el0()) {
+		dev_warn_once(dev, "profiling buffer inaccessible. Try passing \"kpti=off\" on the kernel command line\n");
+		return -EPERM;
+	}
+
 	spe_pmu = devm_kzalloc(dev, sizeof(*spe_pmu), GFP_KERNEL);
 	if (!spe_pmu) {
 		dev_err(dev, "failed to allocate spe_pmu\n");
-- 
2.1.4

^ permalink raw reply related

* [PATCH v3 19/20] arm64: mm: Introduce TTBR_ASID_MASK for getting at the ASID in the TTBR
From: Will Deacon @ 2017-12-06 12:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512563739-25239-1-git-send-email-will.deacon@arm.com>

There are now a handful of open-coded masks to extract the ASID from a
TTBR value, so introduce a TTBR_ASID_MASK and use that instead.

Suggested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/include/asm/asm-uaccess.h | 3 ++-
 arch/arm64/include/asm/mmu.h         | 1 +
 arch/arm64/include/asm/uaccess.h     | 4 ++--
 arch/arm64/kernel/entry.S            | 2 +-
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/asm-uaccess.h b/arch/arm64/include/asm/asm-uaccess.h
index 21b8cf304028..f4f234b6155e 100644
--- a/arch/arm64/include/asm/asm-uaccess.h
+++ b/arch/arm64/include/asm/asm-uaccess.h
@@ -4,6 +4,7 @@
 
 #include <asm/alternative.h>
 #include <asm/kernel-pgtable.h>
+#include <asm/mmu.h>
 #include <asm/sysreg.h>
 #include <asm/assembler.h>
 
@@ -17,7 +18,7 @@
 	msr	ttbr0_el1, \tmp1		// set reserved TTBR0_EL1
 	isb
 	sub	\tmp1, \tmp1, #SWAPPER_DIR_SIZE
-	bic	\tmp1, \tmp1, #(0xffff << 48)
+	bic	\tmp1, \tmp1, #TTBR_ASID_MASK
 	msr	ttbr1_el1, \tmp1		// set reserved ASID
 	isb
 	.endm
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index da6f12e40714..6f7bdb89817f 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -18,6 +18,7 @@
 
 #define MMCF_AARCH32	0x1	/* mm context flag for AArch32 executables */
 #define USER_ASID_FLAG	(UL(1) << 48)
+#define TTBR_ASID_MASK	(UL(0xffff) << 48)
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 750a3b76a01c..6eadf55ebaf0 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -112,7 +112,7 @@ static inline void __uaccess_ttbr0_disable(void)
 	write_sysreg(ttbr + SWAPPER_DIR_SIZE, ttbr0_el1);
 	isb();
 	/* Set reserved ASID */
-	ttbr &= ~(0xffffUL << 48);
+	ttbr &= ~TTBR_ASID_MASK;
 	write_sysreg(ttbr, ttbr1_el1);
 	isb();
 }
@@ -131,7 +131,7 @@ static inline void __uaccess_ttbr0_enable(void)
 
 	/* Restore active ASID */
 	ttbr1 = read_sysreg(ttbr1_el1);
-	ttbr1 |= ttbr0 & (0xffffUL << 48);
+	ttbr1 |= ttbr0 & TTBR_ASID_MASK;
 	write_sysreg(ttbr1, ttbr1_el1);
 	isb();
 
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 5d51bdbb2131..3eabcb194c87 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -205,7 +205,7 @@ alternative_else_nop_endif
 
 	.if	\el != 0
 	mrs	x21, ttbr1_el1
-	tst	x21, #0xffff << 48		// Check for the reserved ASID
+	tst	x21, #TTBR_ASID_MASK		// Check for the reserved ASID
 	orr	x23, x23, #PSR_PAN_BIT		// Set the emulated PAN in the saved SPSR
 	b.eq	1f				// TTBR0 access already disabled
 	and	x23, x23, #~PSR_PAN_BIT		// Clear the emulated PAN in the saved SPSR
-- 
2.1.4

^ permalink raw reply related

* [PATCH v3 20/20] arm64: kaslr: Put kernel vectors address in separate data page
From: Will Deacon @ 2017-12-06 12:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512563739-25239-1-git-send-email-will.deacon@arm.com>

The literal pool entry for identifying the vectors base is the only piece
of information in the trampoline page that identifies the true location
of the kernel.

This patch moves it into its own page, which is only mapped by the full
kernel page table, which protects against any accidental leakage of the
trampoline contents.

Suggested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/include/asm/fixmap.h |  1 +
 arch/arm64/kernel/entry.S       | 11 +++++++++++
 arch/arm64/kernel/vmlinux.lds.S | 35 ++++++++++++++++++++++++++++-------
 arch/arm64/mm/mmu.c             | 10 +++++++++-
 4 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h
index 8119b49be98d..ec1e6d6fa14c 100644
--- a/arch/arm64/include/asm/fixmap.h
+++ b/arch/arm64/include/asm/fixmap.h
@@ -59,6 +59,7 @@ enum fixed_addresses {
 #endif /* CONFIG_ACPI_APEI_GHES */
 
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
+	FIX_ENTRY_TRAMP_DATA,
 	FIX_ENTRY_TRAMP_TEXT,
 #define TRAMP_VALIAS		(__fix_to_virt(FIX_ENTRY_TRAMP_TEXT))
 #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 3eabcb194c87..a70c6dd2cc19 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -1030,7 +1030,13 @@ alternative_else_nop_endif
 	msr	tpidrro_el0, x30	// Restored in kernel_ventry
 	.endif
 	tramp_map_kernel	x30
+#ifdef CONFIG_RANDOMIZE_BASE
+	adr	x30, tramp_vectors + PAGE_SIZE
+alternative_insn isb, nop, ARM64_WORKAROUND_QCOM_FALKOR_E1003
+	ldr	x30, [x30]
+#else
 	ldr	x30, =vectors
+#endif
 	prfm	plil1strm, [x30, #(1b - tramp_vectors)]
 	msr	vbar_el1, x30
 	add	x30, x30, #(1b - tramp_vectors)
@@ -1073,6 +1079,11 @@ END(tramp_exit_compat)
 
 	.ltorg
 	.popsection				// .entry.tramp.text
+#ifdef CONFIG_RANDOMIZE_BASE
+	.pushsection ".entry.tramp.data", "a"	// .entry.tramp.data
+	.quad	vectors
+	.popsection				// .entry.tramp.data
+#endif /* CONFIG_RANDOMIZE_BASE */
 #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
 
 /*
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 6b4260f22aab..976109b3ae51 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -58,15 +58,28 @@ jiffies = jiffies_64;
 #endif
 
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
-#define TRAMP_TEXT					\
-	. = ALIGN(PAGE_SIZE);				\
-	VMLINUX_SYMBOL(__entry_tramp_text_start) = .;	\
-	*(.entry.tramp.text)				\
-	. = ALIGN(PAGE_SIZE);				\
+#define TRAMP_TEXT						\
+	. = ALIGN(PAGE_SIZE);					\
+	VMLINUX_SYMBOL(__entry_tramp_text_start) = .;		\
+	*(.entry.tramp.text)					\
+	. = ALIGN(PAGE_SIZE);					\
 	VMLINUX_SYMBOL(__entry_tramp_text_end) = .;
+#ifdef CONFIG_RANDOMIZE_BASE
+#define TRAMP_DATA						\
+	.entry.tramp.data : {					\
+		. = ALIGN(PAGE_SIZE);				\
+		VMLINUX_SYMBOL(__entry_tramp_data_start) = .;	\
+		*(.entry.tramp.data)				\
+		. = ALIGN(PAGE_SIZE);				\
+		VMLINUX_SYMBOL(__entry_tramp_data_end) = .;	\
+	}
+#else
+#define TRAMP_DATA
+#endif /* CONFIG_RANDOMIZE_BASE */
 #else
 #define TRAMP_TEXT
-#endif
+#define TRAMP_DATA
+#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
 
 /*
  * The size of the PE/COFF section that covers the kernel image, which
@@ -137,6 +150,7 @@ SECTIONS
 	RO_DATA(PAGE_SIZE)		/* everything from this point to     */
 	EXCEPTION_TABLE(8)		/* __init_begin will be marked RO NX */
 	NOTES
+	TRAMP_DATA
 
 	. = ALIGN(SEGMENT_ALIGN);
 	__init_begin = .;
@@ -251,7 +265,14 @@ ASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K,
 ASSERT(__hibernate_exit_text_end - (__hibernate_exit_text_start & ~(SZ_4K - 1))
 	<= SZ_4K, "Hibernate exit text too big or misaligned")
 #endif
-
+#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
+ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) == PAGE_SIZE,
+	"Entry trampoline text too big")
+#ifdef CONFIG_RANDOMIZE_BASE
+ASSERT((__entry_tramp_data_end - __entry_tramp_data_start) == PAGE_SIZE,
+	"Entry trampoline data too big")
+#endif
+#endif
 /*
  * If padding is applied before .head.text, virt<->phys conversions will fail.
  */
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index fe68a48c64cb..916d9ced1c3f 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -541,8 +541,16 @@ static int __init map_entry_trampoline(void)
 	__create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, PAGE_SIZE,
 			     prot, pgd_pgtable_alloc, 0);
 
-	/* ...as well as the kernel page table */
+	/* Map both the text and data into the kernel page table */
 	__set_fixmap(FIX_ENTRY_TRAMP_TEXT, pa_start, prot);
+	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
+		extern char __entry_tramp_data_start[];
+
+		__set_fixmap(FIX_ENTRY_TRAMP_DATA,
+			     __pa_symbol(__entry_tramp_data_start),
+			     PAGE_KERNEL_RO);
+	}
+
 	return 0;
 }
 core_initcall(map_entry_trampoline);
-- 
2.1.4

^ permalink raw reply related

* [RFC] spi: sun6i: disable/unprepare clocks on remove
From: Tobias Jordan @ 2017-12-06 12:50 UTC (permalink / raw)
  To: linux-arm-kernel

sun6i_spi_probe() uses sun6i_spi_runtime_resume() to prepare/enable clocks,
so sun6i_spi_remove() should use sun6i_spi_runtime_suspend() to
disable/unprepare them.

Found by Linux Driver Verification project (linuxtesting.org).

Fixes: 3558fe900e8af spi: sunxi: Add Allwinner A31 SPI controller driver
Signed-off-by: Tobias Jordan <Tobias.Jordan@elektrobit.com>
---
This was found by LDV, and it looks very suspicious to me, but I'm not
sure if the fix is that easy. Is suspend() called automatically when the
driver is removed? If not, is it correct to unconditionally call
suspend(), or should there be a check for the PM state instead?

 drivers/spi/spi-sun6i.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index fb38234249a8..5e5df09e5d04 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -541,6 +541,7 @@ static int sun6i_spi_probe(struct platform_device *pdev)
 
 static int sun6i_spi_remove(struct platform_device *pdev)
 {
+	sun6i_spi_runtime_suspend(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
 	return 0;
-- 
2.11.0

^ permalink raw reply related

* [PATCH 5/8] ASoC: uniphier: add support for UniPhier AIO driver
From: Mark Brown @ 2017-12-06 12:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <004801d36e57$ea1940d0$be4bc270$@socionext.com>

On Wed, Dec 06, 2017 at 03:03:18PM +0900, Katsuhiro Suzuki wrote:

> > I'd expect this code to be structured more like a library - have a
> > driver that handles the specific IPs then have it call into a shared
> > block of code that does the generic bits.  Though in this case the
> > device specific bit looks like a couple of tiny data tables so I'm not
> > sure it's worth making it conditional or separate at all.

> Sorry... I agree your opinion, but I can't imagine the detail.

> I think my driver has structure as follows (ex. startup):
>   DAI: uniphier_aio_startup()@aio-core.c
>   Lib: uniphier_aio_init()@aio-regctrl.c
>   SoC specific: uniphier_aio_ld11_spec at aio-ld11.c

> Am I wrong? Would you mean split the functions in aio-regctl.[ch] to other
> kernel module? I wonder if you could tell me the example from existing
> drivers. I'll try to fix my driver like as it.

One example is how all the drivers that use the generic dmaengine code
instantiate their DMA drivers, or how all the drivers for CODECs that
have both I2C and SPIi control interfaces instantiate - given that the
device specific code here seems to be mostly data tables that's probably
the closest thing.

> > At least.  I do think we need to get to the bottom of how flexible the
> > hardware is first though.

> Yes, indeed. This hardware is more flexible and complex, but now I (and our
> company) don't use it. Of course, I don't want to hide some features of this
> hardware from ALSA people. I should try to upstream all features in the future,
> I think.

My main concern here is to make sure that when you decide you need to
use the more complex hardware that this can be done without too much
pain to existing machines (and that they can benefit from as much of the
enhanced functionality as is possible).
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171206/bf132a6c/attachment.sig>

^ permalink raw reply

* [PATCH v3 20/20] arm64: kaslr: Put kernel vectors address in separate data page
From: Ard Biesheuvel @ 2017-12-06 12:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512563739-25239-21-git-send-email-will.deacon@arm.com>

On 6 December 2017 at 12:35, Will Deacon <will.deacon@arm.com> wrote:
> The literal pool entry for identifying the vectors base is the only piece
> of information in the trampoline page that identifies the true location
> of the kernel.
>
> This patch moves it into its own page, which is only mapped by the full
> kernel page table, which protects against any accidental leakage of the
> trampoline contents.
>
> Suggested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Signed-off-by: Will Deacon <will.deacon@arm.com>
> ---
>  arch/arm64/include/asm/fixmap.h |  1 +
>  arch/arm64/kernel/entry.S       | 11 +++++++++++
>  arch/arm64/kernel/vmlinux.lds.S | 35 ++++++++++++++++++++++++++++-------
>  arch/arm64/mm/mmu.c             | 10 +++++++++-
>  4 files changed, 49 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm64/include/asm/fixmap.h b/arch/arm64/include/asm/fixmap.h
> index 8119b49be98d..ec1e6d6fa14c 100644
> --- a/arch/arm64/include/asm/fixmap.h
> +++ b/arch/arm64/include/asm/fixmap.h
> @@ -59,6 +59,7 @@ enum fixed_addresses {
>  #endif /* CONFIG_ACPI_APEI_GHES */
>
>  #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
> +       FIX_ENTRY_TRAMP_DATA,
>         FIX_ENTRY_TRAMP_TEXT,
>  #define TRAMP_VALIAS           (__fix_to_virt(FIX_ENTRY_TRAMP_TEXT))
>  #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> index 3eabcb194c87..a70c6dd2cc19 100644
> --- a/arch/arm64/kernel/entry.S
> +++ b/arch/arm64/kernel/entry.S
> @@ -1030,7 +1030,13 @@ alternative_else_nop_endif
>         msr     tpidrro_el0, x30        // Restored in kernel_ventry
>         .endif
>         tramp_map_kernel        x30
> +#ifdef CONFIG_RANDOMIZE_BASE
> +       adr     x30, tramp_vectors + PAGE_SIZE
> +alternative_insn isb, nop, ARM64_WORKAROUND_QCOM_FALKOR_E1003
> +       ldr     x30, [x30]
> +#else
>         ldr     x30, =vectors
> +#endif
>         prfm    plil1strm, [x30, #(1b - tramp_vectors)]
>         msr     vbar_el1, x30
>         add     x30, x30, #(1b - tramp_vectors)
> @@ -1073,6 +1079,11 @@ END(tramp_exit_compat)
>
>         .ltorg
>         .popsection                             // .entry.tramp.text
> +#ifdef CONFIG_RANDOMIZE_BASE
> +       .pushsection ".entry.tramp.data", "a"   // .entry.tramp.data
> +       .quad   vectors
> +       .popsection                             // .entry.tramp.data

This does not need to be in a section of its own, and doesn't need to
be padded to a full page.

If you just stick this in .rodata but align it to page size, you can
just map whichever page it ends up in into the TRAMP_DATA fixmap slot
(which is a r/o mapping anyway). You could then drop most of the
changes below. And actually, I'm not entirely sure whether it still
makes sense then to do this only for CONFIG_RANDOMIZE_BASE.


> +#endif /* CONFIG_RANDOMIZE_BASE */
>  #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
>
>  /*
> diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
> index 6b4260f22aab..976109b3ae51 100644
> --- a/arch/arm64/kernel/vmlinux.lds.S
> +++ b/arch/arm64/kernel/vmlinux.lds.S
> @@ -58,15 +58,28 @@ jiffies = jiffies_64;
>  #endif
>
>  #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
> -#define TRAMP_TEXT                                     \
> -       . = ALIGN(PAGE_SIZE);                           \
> -       VMLINUX_SYMBOL(__entry_tramp_text_start) = .;   \
> -       *(.entry.tramp.text)                            \
> -       . = ALIGN(PAGE_SIZE);                           \
> +#define TRAMP_TEXT                                             \
> +       . = ALIGN(PAGE_SIZE);                                   \
> +       VMLINUX_SYMBOL(__entry_tramp_text_start) = .;           \
> +       *(.entry.tramp.text)                                    \
> +       . = ALIGN(PAGE_SIZE);                                   \
>         VMLINUX_SYMBOL(__entry_tramp_text_end) = .;
> +#ifdef CONFIG_RANDOMIZE_BASE
> +#define TRAMP_DATA                                             \
> +       .entry.tramp.data : {                                   \
> +               . = ALIGN(PAGE_SIZE);                           \
> +               VMLINUX_SYMBOL(__entry_tramp_data_start) = .;   \
> +               *(.entry.tramp.data)                            \
> +               . = ALIGN(PAGE_SIZE);                           \
> +               VMLINUX_SYMBOL(__entry_tramp_data_end) = .;     \
> +       }
> +#else
> +#define TRAMP_DATA
> +#endif /* CONFIG_RANDOMIZE_BASE */
>  #else
>  #define TRAMP_TEXT
> -#endif
> +#define TRAMP_DATA
> +#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
>
>  /*
>   * The size of the PE/COFF section that covers the kernel image, which
> @@ -137,6 +150,7 @@ SECTIONS
>         RO_DATA(PAGE_SIZE)              /* everything from this point to     */
>         EXCEPTION_TABLE(8)              /* __init_begin will be marked RO NX */
>         NOTES
> +       TRAMP_DATA
>
>         . = ALIGN(SEGMENT_ALIGN);
>         __init_begin = .;
> @@ -251,7 +265,14 @@ ASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K,
>  ASSERT(__hibernate_exit_text_end - (__hibernate_exit_text_start & ~(SZ_4K - 1))
>         <= SZ_4K, "Hibernate exit text too big or misaligned")
>  #endif
> -
> +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
> +ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) == PAGE_SIZE,
> +       "Entry trampoline text too big")
> +#ifdef CONFIG_RANDOMIZE_BASE
> +ASSERT((__entry_tramp_data_end - __entry_tramp_data_start) == PAGE_SIZE,
> +       "Entry trampoline data too big")
> +#endif
> +#endif
>  /*
>   * If padding is applied before .head.text, virt<->phys conversions will fail.
>   */
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index fe68a48c64cb..916d9ced1c3f 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -541,8 +541,16 @@ static int __init map_entry_trampoline(void)
>         __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, PAGE_SIZE,
>                              prot, pgd_pgtable_alloc, 0);
>
> -       /* ...as well as the kernel page table */
> +       /* Map both the text and data into the kernel page table */
>         __set_fixmap(FIX_ENTRY_TRAMP_TEXT, pa_start, prot);
> +       if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
> +               extern char __entry_tramp_data_start[];
> +
> +               __set_fixmap(FIX_ENTRY_TRAMP_DATA,
> +                            __pa_symbol(__entry_tramp_data_start),
> +                            PAGE_KERNEL_RO);
> +       }
> +
>         return 0;
>  }
>  core_initcall(map_entry_trampoline);
> --
> 2.1.4
>

^ permalink raw reply

* [PATCH] iio: stm32: Adopt SPDX identifier
From: Fabrice Gasnier @ 2017-12-06 13:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171205145559.20294-1-benjamin.gaignard@st.com>

On 12/05/2017 03:55 PM, Benjamin Gaignard wrote:
> Add SPDX identifier in stm32's files in IIO directory
> 
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> ---
>  drivers/iio/adc/stm32-adc-core.c            | 14 +-------------
>  drivers/iio/adc/stm32-adc-core.h            | 14 +-------------
>  drivers/iio/adc/stm32-adc.c                 | 15 +--------------
>  drivers/iio/counter/stm32-lptimer-cnt.c     |  2 +-
>  drivers/iio/dac/stm32-dac-core.c            | 14 +-------------
>  drivers/iio/dac/stm32-dac-core.h            | 15 +--------------
>  drivers/iio/dac/stm32-dac.c                 | 15 +--------------
>  drivers/iio/trigger/stm32-lptimer-trigger.c |  3 +--
>  drivers/iio/trigger/stm32-timer-trigger.c   |  2 +-
>  9 files changed, 9 insertions(+), 85 deletions(-)

Acked-by: Fabrice Gasnier <fabrice.gasnier@st.com>

Fabrice

> 
> diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
> index 6aefef99f935..40be7d9fadbf 100644
> --- a/drivers/iio/adc/stm32-adc-core.c
> +++ b/drivers/iio/adc/stm32-adc-core.c
> @@ -1,3 +1,4 @@
> +// SPDX-License-Identifier: GPL-2.0
>  /*
>   * This file is part of STM32 ADC driver
>   *
> @@ -6,19 +7,6 @@
>   *
>   * Inspired from: fsl-imx25-tsadc
>   *
> - * License type: GPLv2
> - *
> - * 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/clk.h>
> diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h
> index 250ee958a669..8af507b3f32d 100644
> --- a/drivers/iio/adc/stm32-adc-core.h
> +++ b/drivers/iio/adc/stm32-adc-core.h
> @@ -1,22 +1,10 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
>  /*
>   * This file is part of STM32 ADC driver
>   *
>   * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
>   * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
>   *
> - * License type: GPLv2
> - *
> - * 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/>.
>   */
>  
>  #ifndef __STM32_ADC_H
> diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
> index c9d96f935dba..f9ccd705bcbb 100644
> --- a/drivers/iio/adc/stm32-adc.c
> +++ b/drivers/iio/adc/stm32-adc.c
> @@ -1,22 +1,9 @@
> +// SPDX-License-Identifier: GPL-2.0
>  /*
>   * This file is part of STM32 ADC driver
>   *
>   * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
>   * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
> - *
> - * License type: GPLv2
> - *
> - * 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/clk.h>
> diff --git a/drivers/iio/counter/stm32-lptimer-cnt.c b/drivers/iio/counter/stm32-lptimer-cnt.c
> index 81ae5f74216d..42fb8ba67090 100644
> --- a/drivers/iio/counter/stm32-lptimer-cnt.c
> +++ b/drivers/iio/counter/stm32-lptimer-cnt.c
> @@ -1,3 +1,4 @@
> +// SPDX-License-Identifier: GPL-2.0
>  /*
>   * STM32 Low-Power Timer Encoder and Counter driver
>   *
> @@ -7,7 +8,6 @@
>   *
>   * Inspired by 104-quad-8 and stm32-timer-trigger drivers.
>   *
> - * License terms:  GNU General Public License (GPL), version 2
>   */
>  
>  #include <linux/bitfield.h>
> diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c
> index 55026fe1c610..d0fb3124de07 100644
> --- a/drivers/iio/dac/stm32-dac-core.c
> +++ b/drivers/iio/dac/stm32-dac-core.c
> @@ -1,22 +1,10 @@
> +// SPDX-License-Identifier: GPL-2.0
>  /*
>   * This file is part of STM32 DAC driver
>   *
>   * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
>   * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
>   *
> - * License type: GPLv2
> - *
> - * 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/clk.h>
> diff --git a/drivers/iio/dac/stm32-dac-core.h b/drivers/iio/dac/stm32-dac-core.h
> index daf09931857c..d3b415fb9575 100644
> --- a/drivers/iio/dac/stm32-dac-core.h
> +++ b/drivers/iio/dac/stm32-dac-core.h
> @@ -1,22 +1,9 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
>  /*
>   * This file is part of STM32 DAC driver
>   *
>   * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
>   * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
> - *
> - * License type: GPLv2
> - *
> - * 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/>.
>   */
>  
>  #ifndef __STM32_DAC_CORE_H
> diff --git a/drivers/iio/dac/stm32-dac.c b/drivers/iio/dac/stm32-dac.c
> index 9ffab02bf9f9..cce26a3a6627 100644
> --- a/drivers/iio/dac/stm32-dac.c
> +++ b/drivers/iio/dac/stm32-dac.c
> @@ -1,23 +1,10 @@
> +// SPDX-License-Identifier: GPL-2.0
>  /*
>   * This file is part of STM32 DAC driver
>   *
>   * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
>   * Authors: Amelie Delaunay <amelie.delaunay@st.com>
>   *	    Fabrice Gasnier <fabrice.gasnier@st.com>
> - *
> - * License type: GPLv2
> - *
> - * 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/bitfield.h>
> diff --git a/drivers/iio/trigger/stm32-lptimer-trigger.c b/drivers/iio/trigger/stm32-lptimer-trigger.c
> index de361d879929..98cdc7e47f3d 100644
> --- a/drivers/iio/trigger/stm32-lptimer-trigger.c
> +++ b/drivers/iio/trigger/stm32-lptimer-trigger.c
> @@ -1,3 +1,4 @@
> +// SPDX-License-Identifier: GPL-2.0
>  /*
>   * STM32 Low-Power Timer Trigger driver
>   *
> @@ -5,8 +6,6 @@
>   *
>   * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
>   *
> - * License terms:  GNU General Public License (GPL), version 2
> - *
>   * Inspired by Benjamin Gaignard's stm32-timer-trigger driver
>   */
>  
> diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c
> index b542dc484969..ccf1ce653b25 100644
> --- a/drivers/iio/trigger/stm32-timer-trigger.c
> +++ b/drivers/iio/trigger/stm32-timer-trigger.c
> @@ -1,9 +1,9 @@
> +// SPDX-License-Identifier: GPL-2.0
>  /*
>   * Copyright (C) STMicroelectronics 2016
>   *
>   * Author: Benjamin Gaignard <benjamin.gaignard@st.com>
>   *
> - * License terms:  GNU General Public License (GPL), version 2
>   */
>  
>  #include <linux/iio/iio.h>
> 

^ permalink raw reply

* [PATCH net-next 2/2 v6] net: ethernet: Add a driver for Gemini gigabit ethernet
From: Linus Walleij @ 2017-12-06 13:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171203.182149.1898604535140297695.davem@davemloft.net>

On Mon, Dec 4, 2017 at 12:21 AM, David Miller <davem@davemloft.net> wrote:

>> +static irqreturn_t gemini_port_irq_thread(int irq, void *data)
>> +{
>> +     struct gemini_ethernet_port *port = data;
>> +     struct gemini_ethernet *geth = port->geth;
>> +     unsigned long irqmask = SWFQ_EMPTY_INT_BIT;
>> +     unsigned long flags;
>
> Always order local variables in reverse-christmas-tree format,
> which is longest to shortest line.

It's hard to do in cases like this where I use the variable
when defining another variable:

struct gemini_ethernet_port *port = netdev_priv(netdev);
void __iomem *status_reg = port->gmac_base + GMAC_STATUS;

But I understand the aesthetic, so I fix it as well as I can.

If you want me to even rewrite the above using more lines of code
to keep the aestetic (moving assignment out of the variable
definitions), tell me and I can fix that too, whatever you like.

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH v3 2/4] ARM: dts: at91: sama5d2: added dma property for ADC device
From: Eugen Hristev @ 2017-12-06 13:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171129210507.GQ21126@piout.net>



On 29.11.2017 23:05, Alexandre Belloni wrote:
> Hi,
> 
> On 15/11/2017 at 14:56:46 +0200, Eugen Hristev wrote:
>> Added DMA property for ADC device
>>
>> Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
>> ---
>>   arch/arm/boot/dts/sama5d2.dtsi | 2 ++
>>   1 file changed, 2 insertions(+)
>>
> 
> This didn't apply cleanly, please check
> https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git/commit/?h=at91-dt&id=0ae80c039ef2407c08842ddde892af0c9128711b
Hi,

I tested on your tree and looked over the file, and it's all good.
Thanks.

> 
>> diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
>> index 38d2216..ca8bf13 100644
>> --- a/arch/arm/boot/dts/sama5d2.dtsi
>> +++ b/arch/arm/boot/dts/sama5d2.dtsi
>> @@ -1430,6 +1430,8 @@
>>   				atmel,min-sample-rate-hz = <200000>;
>>   				atmel,max-sample-rate-hz = <20000000>;
>>   				atmel,startup-time-ms = <4>;
>> +				dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(25))>;
>> +				dma-names = "rx";
>>   				status = "disabled";
>>   			};
>>   
>> -- 
>> 2.7.4
>>
> 

^ permalink raw reply

* [PATCH] ACPI / GED: unregister interrupts during shutdown
From: Sinan Kaya @ 2017-12-06 13:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAJZ5v0jcFqG=Jd19ms7XQMR+rGfdKTEaN7SK91DPzBa=xcMY1w@mail.gmail.com>

On 12/5/2017 5:18 PM, Rafael J. Wysocki wrote:
> On Tue, Dec 5, 2017 at 10:01 PM, Sinan Kaya <okaya@codeaurora.org> wrote:
>> Some GED interrupts could be pending by the time we are doing a reboot.
>>
>> Even though GED driver uses devm_request_irq() to register the interrupt
>> handler, the handler is not being freed on time during a shutdown since
>> the driver is missing a shutdown callback.
>>
>> If the ACPI handler is no longer available, this causes an interrupt
>> storm and delays shutdown.
>>
>> Register a shutdown callback and manually free the interrupts.
>>
>> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
>> ---
>>  drivers/acpi/evged.c | 36 +++++++++++++++++++++++++++++++++---
>>  1 file changed, 33 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/acpi/evged.c b/drivers/acpi/evged.c
>> index 46f0603..dde50ea 100644
>> --- a/drivers/acpi/evged.c
>> +++ b/drivers/acpi/evged.c
>> @@ -1,7 +1,7 @@
>>  /*
>>   * Generic Event Device for ACPI.
>>   *
>> - * Copyright (c) 2016, The Linux Foundation. All rights reserved.
>> + * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
> 
> Why are you changing this?

Some legal BS that we are trying to figure out internally. This slipped through
the cracks. I was going to remove it before posting.

> 
>>   *
>>   * This program is free software; you can redistribute it and/or modify
>>   * it under the terms of the GNU General Public License version 2 and
>> @@ -49,6 +49,11 @@
>>
>>  #define MODULE_NAME    "acpi-ged"
>>
>> +struct acpi_ged_device {
>> +       struct device *dev;
>> +       struct list_head event_list;
>> +};
>> +
>>  struct acpi_ged_event {
>>         struct list_head node;
>>         struct device *dev;
>> @@ -76,7 +81,8 @@ static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares,
>>         unsigned int irq;
>>         unsigned int gsi;
>>         unsigned int irqflags = IRQF_ONESHOT;
>> -       struct device *dev = context;
>> +       struct acpi_ged_device *geddev = context;
>> +       struct device *dev = geddev->dev;
>>         acpi_handle handle = ACPI_HANDLE(dev);
>>         acpi_handle evt_handle;
>>         struct resource r;
>> @@ -122,29 +128,53 @@ static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares,
>>                 return AE_ERROR;
>>         }
>>
>> +       dev_info(dev, "GED listening GSI %u @ IRQ %u\n", gsi, irq);
> 
> Why dev_info()?

I can change it to dev_dbg.

> 
>> +       list_add_tail(&event->node, &geddev->event_list);
>>         return AE_OK;
>>  }
>>
>>  static int ged_probe(struct platform_device *pdev)
>>  {
>> +       struct acpi_ged_device *geddev;
>>         acpi_status acpi_ret;
>>
>> +       geddev = devm_kzalloc(&pdev->dev, sizeof(*geddev), GFP_KERNEL);
>> +       if (!geddev)
>> +               return -ENOMEM;
>> +
>> +       geddev->dev = &pdev->dev;
>> +       INIT_LIST_HEAD(&geddev->event_list);
>>         acpi_ret = acpi_walk_resources(ACPI_HANDLE(&pdev->dev), "_CRS",
>> -                                      acpi_ged_request_interrupt, &pdev->dev);
>> +                                      acpi_ged_request_interrupt, geddev);
>>         if (ACPI_FAILURE(acpi_ret)) {
>>                 dev_err(&pdev->dev, "unable to parse the _CRS record\n");
>>                 return -EINVAL;
>>         }
>> +       platform_set_drvdata(pdev, geddev);
>>
>>         return 0;
>>  }
>>
>> +static void ged_remove(struct platform_device *pdev)
>> +{
>> +       struct acpi_ged_device *geddev = platform_get_drvdata(pdev);
>> +       struct acpi_ged_event *event, *next;
>> +
>> +       list_for_each_entry_safe(event, next, &geddev->event_list, node) {
>> +               devm_free_irq(geddev->dev, event->irq, event);
>> +               list_del(&event->node);
>> +               dev_info(geddev->dev, "GED releasing GSI %u @ IRQ %u\n",
>> +                        event->gsi, event->irq);
> 
> dev_dbg() and that if you really need it.

will change to dev_dbg

> 
>> +       }
>> +}
>> +
>>  static const struct acpi_device_id ged_acpi_ids[] = {
>>         {"ACPI0013"},
>>         {},
>>  };
>>
>>  static struct platform_driver ged_driver = {
>> +       .shutdown = ged_remove,
> 
> That ged_remove really should be called ged_shutdown.  It is confusing
> as is, because there is a ->remove callback in the structure too.

I'll rename as shutdown.

> 
>>         .probe = ged_probe,
>>         .driver = {
>>                 .name = MODULE_NAME,
>> --
> 
> Overall, it looks like we should just unbind the driver from all
> devices on shutdown.

I see that shutdown is getting called on all GED instances. That should
take care of it, right?

> 
> Thanks,
> Rafael
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH v3 20/20] arm64: kaslr: Put kernel vectors address in separate data page
From: Will Deacon @ 2017-12-06 13:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKv+Gu_qpJCXqfrGqMGDfjeYHQVYU4SWChMXdPi53g6rmqQz6Q@mail.gmail.com>

Hi Ard,

On Wed, Dec 06, 2017 at 12:59:40PM +0000, Ard Biesheuvel wrote:
> On 6 December 2017 at 12:35, Will Deacon <will.deacon@arm.com> wrote:
> > The literal pool entry for identifying the vectors base is the only piece
> > of information in the trampoline page that identifies the true location
> > of the kernel.
> >
> > This patch moves it into its own page, which is only mapped by the full
> > kernel page table, which protects against any accidental leakage of the
> > trampoline contents.

[...]

> > @@ -1073,6 +1079,11 @@ END(tramp_exit_compat)
> >
> >         .ltorg
> >         .popsection                             // .entry.tramp.text
> > +#ifdef CONFIG_RANDOMIZE_BASE
> > +       .pushsection ".entry.tramp.data", "a"   // .entry.tramp.data
> > +       .quad   vectors
> > +       .popsection                             // .entry.tramp.data
> 
> This does not need to be in a section of its own, and doesn't need to
> be padded to a full page.
> 
> If you just stick this in .rodata but align it to page size, you can
> just map whichever page it ends up in into the TRAMP_DATA fixmap slot
> (which is a r/o mapping anyway). You could then drop most of the
> changes below. And actually, I'm not entirely sure whether it still
> makes sense then to do this only for CONFIG_RANDOMIZE_BASE.

Good point; I momentarily forgot this was in the kernel page table anyway.
How about something like the diff below merged on top (so this basically
undoes a bunch of the patch)?

I'd prefer to keep the CONFIG_RANDOMIZE_BASE dependency, at least for now.

Will

--->8

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index a70c6dd2cc19..031392ee5f47 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -1080,9 +1080,12 @@ END(tramp_exit_compat)
 	.ltorg
 	.popsection				// .entry.tramp.text
 #ifdef CONFIG_RANDOMIZE_BASE
-	.pushsection ".entry.tramp.data", "a"	// .entry.tramp.data
+	.pushsection ".rodata", "a"
+	.align PAGE_SHIFT
+	.globl	__entry_tramp_data_start
+__entry_tramp_data_start:
 	.quad	vectors
-	.popsection				// .entry.tramp.data
+	.popsection				// .rodata
 #endif /* CONFIG_RANDOMIZE_BASE */
 #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
 
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 976109b3ae51..27cf9be20a00 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -64,21 +64,8 @@ jiffies = jiffies_64;
 	*(.entry.tramp.text)					\
 	. = ALIGN(PAGE_SIZE);					\
 	VMLINUX_SYMBOL(__entry_tramp_text_end) = .;
-#ifdef CONFIG_RANDOMIZE_BASE
-#define TRAMP_DATA						\
-	.entry.tramp.data : {					\
-		. = ALIGN(PAGE_SIZE);				\
-		VMLINUX_SYMBOL(__entry_tramp_data_start) = .;	\
-		*(.entry.tramp.data)				\
-		. = ALIGN(PAGE_SIZE);				\
-		VMLINUX_SYMBOL(__entry_tramp_data_end) = .;	\
-	}
-#else
-#define TRAMP_DATA
-#endif /* CONFIG_RANDOMIZE_BASE */
 #else
 #define TRAMP_TEXT
-#define TRAMP_DATA
 #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
 
 /*
@@ -150,7 +137,6 @@ SECTIONS
 	RO_DATA(PAGE_SIZE)		/* everything from this point to     */
 	EXCEPTION_TABLE(8)		/* __init_begin will be marked RO NX */
 	NOTES
-	TRAMP_DATA
 
 	. = ALIGN(SEGMENT_ALIGN);
 	__init_begin = .;
@@ -268,10 +254,6 @@ ASSERT(__hibernate_exit_text_end - (__hibernate_exit_text_start & ~(SZ_4K - 1))
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) == PAGE_SIZE,
 	"Entry trampoline text too big")
-#ifdef CONFIG_RANDOMIZE_BASE
-ASSERT((__entry_tramp_data_end - __entry_tramp_data_start) == PAGE_SIZE,
-	"Entry trampoline data too big")
-#endif
 #endif
 /*
  * If padding is applied before .head.text, virt<->phys conversions will fail.

^ permalink raw reply related

* [PATCH net-next v3 0/2] net: thunderx: add support for PTP clock
From: Aleksey Makarov @ 2017-12-06 13:30 UTC (permalink / raw)
  To: linux-arm-kernel

This series adds support for IEEE 1588 Precision Time Protocol
to Cavium ethernet driver.

The first patch adds support for the Precision Time Protocol Clocks and
Timestamping coprocessor (PTP) found on Cavium processors.
It registers a new PTP clock in the PTP core and provides functions
to use the counter in BGX, TNS, GTI, and NIC blocks.

The second patch introduces support for the PTP protocol to the
Cavium ThunderX ethernet driver.

v3:
- rebase to net-next

v2: https://lkml.kernel.org/r/20171117134909.8954-1-aleksey.makarov at cavium.com
- use readq()/writeq() in place of cavium_ptp_reg_read()/cavium_ptp_reg_write(),
  don't use readq_relaxed()/writeq_relaxed() (David Daney)

v1: https://lkml.kernel.org/r/20171107190704.15458-1-aleksey.makarov at cavium.com

Radoslaw Biernacki (1):
  net: add support for Cavium PTP coprocessor

Sunil Goutham (1):
  net: thunderx: add timestamping support

 drivers/net/ethernet/cavium/Kconfig                |  14 +
 drivers/net/ethernet/cavium/Makefile               |   1 +
 drivers/net/ethernet/cavium/common/Makefile        |   1 +
 drivers/net/ethernet/cavium/common/cavium_ptp.c    | 334 +++++++++++++++++++++
 drivers/net/ethernet/cavium/common/cavium_ptp.h    |  78 +++++
 drivers/net/ethernet/cavium/thunder/nic.h          |  15 +
 drivers/net/ethernet/cavium/thunder/nic_main.c     |  58 +++-
 drivers/net/ethernet/cavium/thunder/nic_reg.h      |   1 +
 .../net/ethernet/cavium/thunder/nicvf_ethtool.c    |  29 +-
 drivers/net/ethernet/cavium/thunder/nicvf_main.c   | 173 ++++++++++-
 drivers/net/ethernet/cavium/thunder/nicvf_queues.c |  26 ++
 drivers/net/ethernet/cavium/thunder/thunder_bgx.c  |  29 ++
 drivers/net/ethernet/cavium/thunder/thunder_bgx.h  |   4 +
 13 files changed, 757 insertions(+), 6 deletions(-)
 create mode 100644 drivers/net/ethernet/cavium/common/Makefile
 create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.c
 create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.h

-- 
2.15.1

^ permalink raw reply

* [PATCH net-next v3 1/2] net: add support for Cavium PTP coprocessor
From: Aleksey Makarov @ 2017-12-06 13:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171206133100.26436-1-aleksey.makarov@cavium.com>

From: Radoslaw Biernacki <rad@semihalf.com>

This patch adds support for the Precision Time Protocol
Clocks and Timestamping hardware found on Cavium ThunderX
processors.

Signed-off-by: Radoslaw Biernacki <rad@semihalf.com>
Signed-off-by: Aleksey Makarov <aleksey.makarov@cavium.com>
---
 drivers/net/ethernet/cavium/Kconfig             |  13 +
 drivers/net/ethernet/cavium/Makefile            |   1 +
 drivers/net/ethernet/cavium/common/Makefile     |   1 +
 drivers/net/ethernet/cavium/common/cavium_ptp.c | 334 ++++++++++++++++++++++++
 drivers/net/ethernet/cavium/common/cavium_ptp.h |  78 ++++++
 5 files changed, 427 insertions(+)
 create mode 100644 drivers/net/ethernet/cavium/common/Makefile
 create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.c
 create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.h

diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index 63be75eb34d2..fabe0ffcc2d4 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -50,6 +50,19 @@ config	THUNDER_NIC_RGX
 	  This driver supports configuring XCV block of RGX interface
 	  present on CN81XX chip.
 
+config CAVIUM_PTP
+	tristate "Cavium PTP coprocessor as PTP clock"
+	depends on 64BIT
+	depends on PTP_1588_CLOCK
+	select CAVIUM_RST
+	default y
+	---help---
+	  This driver adds support for the Precision Time Protocol Clocks and
+	  Timestamping coprocessor (PTP) found on Cavium processors.
+	  PTP provides timestamping mechanism that is suitable for use in IEEE 1588
+	  Precision Time Protocol or other purposes.  Timestamps can be used in
+	  BGX, TNS, GTI, and NIC blocks.
+
 config LIQUIDIO
 	tristate "Cavium LiquidIO support"
 	depends on 64BIT
diff --git a/drivers/net/ethernet/cavium/Makefile b/drivers/net/ethernet/cavium/Makefile
index 872da9f7c31a..946bba84e81d 100644
--- a/drivers/net/ethernet/cavium/Makefile
+++ b/drivers/net/ethernet/cavium/Makefile
@@ -1,6 +1,7 @@
 #
 # Makefile for the Cavium ethernet device drivers.
 #
+obj-$(CONFIG_NET_VENDOR_CAVIUM) += common/
 obj-$(CONFIG_NET_VENDOR_CAVIUM) += thunder/
 obj-$(CONFIG_NET_VENDOR_CAVIUM) += liquidio/
 obj-$(CONFIG_NET_VENDOR_CAVIUM) += octeon/
diff --git a/drivers/net/ethernet/cavium/common/Makefile b/drivers/net/ethernet/cavium/common/Makefile
new file mode 100644
index 000000000000..dd8561b8060b
--- /dev/null
+++ b/drivers/net/ethernet/cavium/common/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_CAVIUM_PTP) += cavium_ptp.o
diff --git a/drivers/net/ethernet/cavium/common/cavium_ptp.c b/drivers/net/ethernet/cavium/common/cavium_ptp.c
new file mode 100644
index 000000000000..f4c738db27fd
--- /dev/null
+++ b/drivers/net/ethernet/cavium/common/cavium_ptp.c
@@ -0,0 +1,334 @@
+/*
+ * cavium_ptp.c - PTP 1588 clock on Cavium hardware
+ *
+ * Copyright (c) 2003-2015, 2017 Cavium, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium, Inc. for more information
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/timecounter.h>
+#include <linux/pci.h>
+
+#include "cavium_ptp.h"
+
+#define DRV_NAME	"Cavium PTP Driver"
+
+#define PCI_DEVICE_ID_CAVIUM_PTP	0xA00C
+#define PCI_DEVICE_ID_CAVIUM_RST	0xA00E
+
+#define PCI_PTP_BAR_NO	0
+#define PCI_RST_BAR_NO	0
+
+#define PTP_CLOCK_CFG		0xF00ULL
+#define  PTP_CLOCK_CFG_PTP_EN	BIT(0)
+#define PTP_CLOCK_LO		0xF08ULL
+#define PTP_CLOCK_HI		0xF10ULL
+#define PTP_CLOCK_COMP		0xF18ULL
+
+#define RST_BOOT	0x1600ULL
+#define CLOCK_BASE_RATE	50000000ULL
+
+static u64 ptp_cavium_clock_get(void)
+{
+	struct pci_dev *pdev;
+	void __iomem *base;
+	u64 ret = CLOCK_BASE_RATE * 16;
+
+	pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
+			      PCI_DEVICE_ID_CAVIUM_RST, NULL);
+	if (!pdev)
+		goto error;
+
+	base = pci_ioremap_bar(pdev, PCI_RST_BAR_NO);
+	if (!base)
+		goto error_put_pdev;
+
+	ret = CLOCK_BASE_RATE * ((readq(base + RST_BOOT) >> 33) & 0x3f);
+
+	iounmap(base);
+
+error_put_pdev:
+	pci_dev_put(pdev);
+
+error:
+	return ret;
+}
+
+struct cavium_ptp *cavium_ptp_get(void)
+{
+	struct cavium_ptp *ptp;
+	struct pci_dev *pdev;
+
+	pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
+			      PCI_DEVICE_ID_CAVIUM_PTP, NULL);
+	if (!pdev)
+		return ERR_PTR(-ENODEV);
+
+	ptp = pci_get_drvdata(pdev);
+	if (!ptp) {
+		pci_dev_put(pdev);
+		ptp = ERR_PTR(-EPROBE_DEFER);
+	}
+
+	return ptp;
+}
+EXPORT_SYMBOL(cavium_ptp_get);
+
+void cavium_ptp_put(struct cavium_ptp *ptp)
+{
+	pci_dev_put(ptp->pdev);
+}
+EXPORT_SYMBOL(cavium_ptp_put);
+
+/**
+ * cavium_ptp_adjfreq() - Adjust ptp frequency
+ * @ptp: PTP clock info
+ * @ppb: how much to adjust by, in parts-per-billion
+ */
+static int cavium_ptp_adjfreq(struct ptp_clock_info *ptp_info, s32 ppb)
+{
+	struct cavium_ptp *clock =
+		container_of(ptp_info, struct cavium_ptp, ptp_info);
+	unsigned long flags;
+	u64 comp;
+	u64 adj;
+	bool neg_adj = false;
+
+	if (ppb < 0) {
+		neg_adj = true;
+		ppb = -ppb;
+	}
+
+	/* The hardware adds the clock compensation value to the PTP clock
+	 * on every coprocessor clock cycle. Typical convention is that it
+	 * represent number of nanosecond betwen each cycle. In this
+	 * convention compensation value is in 64 bit fixed-point
+	 * representation where upper 32 bits are number of nanoseconds
+	 * and lower is fractions of nanosecond.
+	 * The ppb represent the ratio in "parts per bilion" by which the
+	 * compensation value should be corrected.
+	 * To calculate new compenstation value we use 64bit fixed point
+	 * arithmetic on following formula comp = tbase + tbase * ppb / 1G
+	 * where tbase is the basic compensation value calculated initialy
+	 * in cavium_ptp_init() -> tbase = 1/Hz. Then we use endian
+	 * independent structure definition to write data to PTP register.
+	 */
+	comp = ((u64)1000000000ull << 32) / clock->clock_rate;
+	adj = comp * ppb;
+	adj = div_u64(adj, 1000000000ull);
+	comp = neg_adj ? comp - adj : comp + adj;
+
+	spin_lock_irqsave(&clock->spin_lock, flags);
+	writeq(comp, clock->reg_base + PTP_CLOCK_COMP);
+	spin_unlock_irqrestore(&clock->spin_lock, flags);
+
+	return 0;
+}
+
+/**
+ * cavium_ptp_adjtime() - Adjust ptp time
+ * @ptp:   PTP clock info
+ * @delta: how much to adjust by, in nanosecs
+ */
+static int cavium_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
+{
+	struct cavium_ptp *clock =
+		container_of(ptp_info, struct cavium_ptp, ptp_info);
+	unsigned long flags;
+
+	spin_lock_irqsave(&clock->spin_lock, flags);
+	timecounter_adjtime(&clock->time_counter, delta);
+	spin_unlock_irqrestore(&clock->spin_lock, flags);
+
+	/* Sync, for network driver to get latest value */
+	smp_mb();
+
+	return 0;
+}
+
+/**
+ * cavium_ptp_gettime() - Get hardware clock time with adjustment
+ * @ptp: PTP clock info
+ * @ts:  timespec
+ */
+static int cavium_ptp_gettime(struct ptp_clock_info *ptp_info,
+			      struct timespec64 *ts)
+{
+	struct cavium_ptp *clock =
+		container_of(ptp_info, struct cavium_ptp, ptp_info);
+	unsigned long flags;
+	u64 nsec;
+
+	spin_lock_irqsave(&clock->spin_lock, flags);
+	nsec = timecounter_read(&clock->time_counter);
+	spin_unlock_irqrestore(&clock->spin_lock, flags);
+
+	*ts = ns_to_timespec64(nsec);
+
+	return 0;
+}
+
+/**
+ * cavium_ptp_settime() - Set hardware clock time. Reset adjustment
+ * @ptp: PTP clock info
+ * @ts:  timespec
+ */
+static int cavium_ptp_settime(struct ptp_clock_info *ptp_info,
+			      const struct timespec64 *ts)
+{
+	struct cavium_ptp *clock =
+		container_of(ptp_info, struct cavium_ptp, ptp_info);
+	unsigned long flags;
+	u64 nsec;
+
+	nsec = timespec64_to_ns(ts);
+
+	spin_lock_irqsave(&clock->spin_lock, flags);
+	timecounter_init(&clock->time_counter, &clock->cycle_counter, nsec);
+	spin_unlock_irqrestore(&clock->spin_lock, flags);
+
+	return 0;
+}
+
+/**
+ * cavium_ptp_enable() - Check if PTP is enabled
+ * @ptp: PTP clock info
+ * @rq:  request
+ * @on:  is it on
+ */
+static int cavium_ptp_enable(struct ptp_clock_info *ptp_info,
+			     struct ptp_clock_request *rq, int on)
+{
+	return -EOPNOTSUPP;
+}
+
+static u64 cavium_ptp_cc_read(const struct cyclecounter *cc)
+{
+	struct cavium_ptp *clock =
+		container_of(cc, struct cavium_ptp, cycle_counter);
+
+	return readq(clock->reg_base + PTP_CLOCK_HI);
+}
+
+static int cavium_ptp_probe(struct pci_dev *pdev,
+			    const struct pci_device_id *ent)
+{
+	struct device *dev = &pdev->dev;
+	struct cavium_ptp *clock;
+	struct cyclecounter *cc;
+	u64 clock_cfg;
+	u64 clock_comp;
+	int err;
+
+	clock = devm_kzalloc(dev, sizeof(*clock), GFP_KERNEL);
+	if (!clock)
+		return -ENOMEM;
+
+	clock->pdev = pdev;
+
+	err = pcim_enable_device(pdev);
+	if (err)
+		return err;
+
+	err = pcim_iomap_regions(pdev, 1 << PCI_PTP_BAR_NO, pci_name(pdev));
+	if (err)
+		return err;
+
+	clock->reg_base = pcim_iomap_table(pdev)[PCI_PTP_BAR_NO];
+
+	spin_lock_init(&clock->spin_lock);
+
+	cc = &clock->cycle_counter;
+	cc->read = cavium_ptp_cc_read;
+	cc->mask = CYCLECOUNTER_MASK(64);
+	cc->mult = 1;
+	cc->shift = 0;
+
+	timecounter_init(&clock->time_counter, &clock->cycle_counter,
+			 ktime_to_ns(ktime_get_real()));
+
+	clock->clock_rate = ptp_cavium_clock_get();
+
+	clock->ptp_info = (struct ptp_clock_info) {
+		.owner		= THIS_MODULE,
+		.name		= "ThunderX PTP",
+		.max_adj	= 1000000000ull,
+		.n_ext_ts	= 0,
+		.n_pins		= 0,
+		.pps		= 0,
+		.adjfreq	= cavium_ptp_adjfreq,
+		.adjtime	= cavium_ptp_adjtime,
+		.gettime64	= cavium_ptp_gettime,
+		.settime64	= cavium_ptp_settime,
+		.enable		= cavium_ptp_enable,
+	};
+
+	clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG);
+	clock_cfg |= PTP_CLOCK_CFG_PTP_EN;
+	writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG);
+
+	clock_comp = ((u64)1000000000ull << 32) / clock->clock_rate;
+	writeq(clock_comp, clock->reg_base + PTP_CLOCK_COMP);
+
+	clock->ptp_clock = ptp_clock_register(&clock->ptp_info, dev);
+	if (IS_ERR(clock->ptp_clock)) {
+		clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG);
+		clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;
+		writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG);
+		return PTR_ERR(clock->ptp_clock);
+	}
+
+	pci_set_drvdata(pdev, clock);
+	return 0;
+}
+
+static void cavium_ptp_remove(struct pci_dev *pdev)
+{
+	struct cavium_ptp *clock = pci_get_drvdata(pdev);
+	u64 clock_cfg;
+
+	pci_set_drvdata(pdev, NULL);
+
+	ptp_clock_unregister(clock->ptp_clock);
+
+	clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG);
+	clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;
+	writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG);
+}
+
+static const struct pci_device_id cavium_ptp_id_table[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_CAVIUM_PTP) },
+	{ 0, }
+};
+
+static struct pci_driver cavium_ptp_driver = {
+	.name = DRV_NAME,
+	.id_table = cavium_ptp_id_table,
+	.probe = cavium_ptp_probe,
+	.remove = cavium_ptp_remove,
+};
+
+static int __init cavium_ptp_init_module(void)
+{
+	return pci_register_driver(&cavium_ptp_driver);
+}
+
+static void __exit cavium_ptp_cleanup_module(void)
+{
+	pci_unregister_driver(&cavium_ptp_driver);
+}
+
+module_init(cavium_ptp_init_module);
+module_exit(cavium_ptp_cleanup_module);
+
+MODULE_DESCRIPTION(DRV_NAME);
+MODULE_AUTHOR("Cavium Networks <support@cavium.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(pci, cavium_ptp_id_table);
diff --git a/drivers/net/ethernet/cavium/common/cavium_ptp.h b/drivers/net/ethernet/cavium/common/cavium_ptp.h
new file mode 100644
index 000000000000..7a9dcb027a93
--- /dev/null
+++ b/drivers/net/ethernet/cavium/common/cavium_ptp.h
@@ -0,0 +1,78 @@
+/*
+ * cavium_ptp.h - PTP 1588 clock on Cavium hardware
+ *
+ * Copyright (c) 2003-2015, 2017 Cavium, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium, Inc. for more information
+ */
+
+#ifndef CAVIUM_PTP_H
+#define CAVIUM_PTP_H
+
+#include <linux/ptp_clock_kernel.h>
+#include <linux/timecounter.h>
+
+struct cavium_ptp {
+	struct pci_dev *pdev;
+
+	/* Serialize access to cycle_counter, time_counter and hw_registers */
+	spinlock_t spin_lock;
+	struct cyclecounter cycle_counter;
+	struct timecounter time_counter;
+	void __iomem *reg_base;
+
+	u32 clock_rate;
+
+	struct ptp_clock_info ptp_info;
+	struct ptp_clock *ptp_clock;
+};
+
+#ifdef CONFIG_CAVIUM_PTP
+
+struct cavium_ptp *cavium_ptp_get(void);
+void cavium_ptp_put(struct cavium_ptp *ptp);
+
+static inline u64 cavium_ptp_tstamp2time(struct cavium_ptp *ptp, u64 tstamp)
+{
+	unsigned long flags;
+	u64 ret;
+
+	spin_lock_irqsave(&ptp->spin_lock, flags);
+	ret = timecounter_cyc2time(&ptp->time_counter, tstamp);
+	spin_unlock_irqrestore(&ptp->spin_lock, flags);
+
+	return ret;
+}
+
+static inline int cavium_ptp_clock_index(struct cavium_ptp *clock)
+{
+	return ptp_clock_index(clock->ptp_clock);
+}
+
+#else
+
+static inline struct cavium_ptp *cavium_ptp_get(void)
+{
+	return ERR_PTR(-ENODEV);
+}
+
+static inline void cavium_ptp_put(struct cavium_ptp *ptp) {}
+
+static inline u64 cavium_ptp_tstamp2time(struct cavium_ptp *ptp, u64 tstamp)
+{
+	return 0;
+}
+
+static inline int cavium_ptp_clock_index(struct cavium_ptp *clock)
+{
+	return -1;
+}
+
+#endif
+
+#endif
-- 
2.15.1

^ permalink raw reply related

* [PATCH net-next v3 2/2] net: thunderx: add timestamping support
From: Aleksey Makarov @ 2017-12-06 13:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171206133100.26436-1-aleksey.makarov@cavium.com>

From: Sunil Goutham <sgoutham@cavium.com>

This adds timestamping support for both receive and transmit
paths. On the receive side no filters are supported i.e either
all pkts will get a timestamp appended infront of the packet or none.
On the transmit side HW doesn't support timestamp insertion but
only generates a separate CQE with transmitted packet's timestamp.
Also HW supports only one packet at a time for timestamping on the
transmit side.

Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
Signed-off-by: Aleksey Makarov <aleksey.makarov@cavium.com>
---
 drivers/net/ethernet/cavium/Kconfig                |   1 +
 drivers/net/ethernet/cavium/thunder/nic.h          |  15 ++
 drivers/net/ethernet/cavium/thunder/nic_main.c     |  58 ++++++-
 drivers/net/ethernet/cavium/thunder/nic_reg.h      |   1 +
 .../net/ethernet/cavium/thunder/nicvf_ethtool.c    |  29 +++-
 drivers/net/ethernet/cavium/thunder/nicvf_main.c   | 173 ++++++++++++++++++++-
 drivers/net/ethernet/cavium/thunder/nicvf_queues.c |  26 ++++
 drivers/net/ethernet/cavium/thunder/thunder_bgx.c  |  29 ++++
 drivers/net/ethernet/cavium/thunder/thunder_bgx.h  |   4 +
 9 files changed, 330 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index fabe0ffcc2d4..6d003cbe197c 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -27,6 +27,7 @@ config THUNDER_NIC_PF
 
 config THUNDER_NIC_VF
 	tristate "Thunder Virtual function driver"
+	select CAVIUM_PTP
 	depends on 64BIT
 	---help---
 	  This driver supports Thunder's NIC virtual function
diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
index 4a02e618e318..204b234beb9d 100644
--- a/drivers/net/ethernet/cavium/thunder/nic.h
+++ b/drivers/net/ethernet/cavium/thunder/nic.h
@@ -263,6 +263,8 @@ struct nicvf_drv_stats {
 	struct u64_stats_sync   syncp;
 };
 
+struct cavium_ptp;
+
 struct nicvf {
 	struct nicvf		*pnicvf;
 	struct net_device	*netdev;
@@ -312,6 +314,12 @@ struct nicvf {
 	struct tasklet_struct	qs_err_task;
 	struct work_struct	reset_task;
 
+	/* PTP timestamp */
+	struct cavium_ptp	*ptp_clock;
+	bool			hw_rx_tstamp;
+	struct sk_buff		*ptp_skb;
+	atomic_t		tx_ptp_skbs;
+
 	/* Interrupt coalescing settings */
 	u32			cq_coalesce_usecs;
 	u32			msg_enable;
@@ -371,6 +379,7 @@ struct nicvf {
 #define	NIC_MBOX_MSG_LOOPBACK		0x16	/* Set interface in loopback */
 #define	NIC_MBOX_MSG_RESET_STAT_COUNTER 0x17	/* Reset statistics counters */
 #define	NIC_MBOX_MSG_PFC		0x18	/* Pause frame control */
+#define	NIC_MBOX_MSG_PTP_CFG		0x19	/* HW packet timestamp */
 #define	NIC_MBOX_MSG_CFG_DONE		0xF0	/* VF configuration done */
 #define	NIC_MBOX_MSG_SHUTDOWN		0xF1	/* VF is being shutdown */
 
@@ -521,6 +530,11 @@ struct pfc {
 	u8    fc_tx;
 };
 
+struct set_ptp {
+	u8    msg;
+	bool  enable;
+};
+
 /* 128 bit shared memory between PF and each VF */
 union nic_mbx {
 	struct { u8 msg; }	msg;
@@ -540,6 +554,7 @@ union nic_mbx {
 	struct set_loopback	lbk;
 	struct reset_stat_cfg	reset_stat;
 	struct pfc		pfc;
+	struct set_ptp		ptp;
 };
 
 #define NIC_NODE_ID_MASK	0x03
diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c
index 8f1dd55b3e08..4c1c5414a162 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nic_main.c
@@ -426,13 +426,22 @@ static void nic_init_hw(struct nicpf *nic)
 	/* Enable backpressure */
 	nic_reg_write(nic, NIC_PF_BP_CFG, (1ULL << 6) | 0x03);
 
-	/* TNS and TNS bypass modes are present only on 88xx */
+	/* TNS and TNS bypass modes are present only on 88xx
+	 * Also offset of this CSR has changed in 81xx and 83xx.
+	 */
 	if (nic->pdev->subsystem_device == PCI_SUBSYS_DEVID_88XX_NIC_PF) {
 		/* Disable TNS mode on both interfaces */
 		nic_reg_write(nic, NIC_PF_INTF_0_1_SEND_CFG,
-			      (NIC_TNS_BYPASS_MODE << 7) | BGX0_BLOCK);
+			      (NIC_TNS_BYPASS_MODE << 7) |
+			      BGX0_BLOCK | (1ULL << 16));
 		nic_reg_write(nic, NIC_PF_INTF_0_1_SEND_CFG | (1 << 8),
-			      (NIC_TNS_BYPASS_MODE << 7) | BGX1_BLOCK);
+			      (NIC_TNS_BYPASS_MODE << 7) |
+			      BGX1_BLOCK | (1ULL << 16));
+	} else {
+		/* Configure timestamp generation timeout to 10us */
+		for (i = 0; i < nic->hw->bgx_cnt; i++)
+			nic_reg_write(nic, NIC_PF_INTFX_SEND_CFG | (i << 3),
+				      (1ULL << 16));
 	}
 
 	nic_reg_write(nic, NIC_PF_INTF_0_1_BP_CFG,
@@ -880,6 +889,46 @@ static void nic_pause_frame(struct nicpf *nic, int vf, struct pfc *cfg)
 	}
 }
 
+/* Enable or disable HW timestamping by BGX for pkts received on a LMAC */
+static void nic_config_timestamp(struct nicpf *nic, int vf, struct set_ptp *ptp)
+{
+	struct pkind_cfg *pkind;
+	u8 lmac, bgx_idx;
+	u64 pkind_val, pkind_idx;
+
+	if (vf >= nic->num_vf_en)
+		return;
+
+	bgx_idx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+	lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+
+	pkind_idx = lmac + bgx_idx * MAX_LMAC_PER_BGX;
+	pkind_val = nic_reg_read(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3));
+	pkind = (struct pkind_cfg *)&pkind_val;
+
+	if (ptp->enable && !pkind->hdr_sl) {
+		/* Skiplen to exclude 8byte timestamp while parsing pkt
+		 * If not configured, will result in L2 errors.
+		 */
+		pkind->hdr_sl = 4;
+		/* Adjust max packet length allowed */
+		pkind->maxlen += (pkind->hdr_sl * 2);
+		bgx_config_timestamping(nic->node, bgx_idx, lmac, true);
+		nic_reg_write(nic,
+			      NIC_PF_RX_ETYPE_0_7 | (1 << 3),
+			      (ETYPE_ALG_ENDPARSE << 16) | ETH_P_1588);
+	} else if (!ptp->enable && pkind->hdr_sl) {
+		pkind->maxlen -= (pkind->hdr_sl * 2);
+		pkind->hdr_sl = 0;
+		bgx_config_timestamping(nic->node, bgx_idx, lmac, false);
+		nic_reg_write(nic,
+			      NIC_PF_RX_ETYPE_0_7 | (1 << 3),
+			      (1ULL << 16) | ETH_P_8021Q); /* reset value */
+	}
+
+	nic_reg_write(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3), pkind_val);
+}
+
 /* Interrupt handler to handle mailbox messages from VFs */
 static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
 {
@@ -1022,6 +1071,9 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
 	case NIC_MBOX_MSG_PFC:
 		nic_pause_frame(nic, vf, &mbx.pfc);
 		goto unlock;
+	case NIC_MBOX_MSG_PTP_CFG:
+		nic_config_timestamp(nic, vf, &mbx.ptp);
+		break;
 	default:
 		dev_err(&nic->pdev->dev,
 			"Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg);
diff --git a/drivers/net/ethernet/cavium/thunder/nic_reg.h b/drivers/net/ethernet/cavium/thunder/nic_reg.h
index 80d46337cf29..a16c48a1ebb2 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_reg.h
+++ b/drivers/net/ethernet/cavium/thunder/nic_reg.h
@@ -99,6 +99,7 @@
 #define   NIC_PF_ECC3_DBE_INT_W1S		(0x2708)
 #define   NIC_PF_ECC3_DBE_ENA_W1C		(0x2710)
 #define   NIC_PF_ECC3_DBE_ENA_W1S		(0x2718)
+#define   NIC_PF_INTFX_SEND_CFG			(0x4000)
 #define   NIC_PF_MCAM_0_191_ENA			(0x100000)
 #define   NIC_PF_MCAM_0_191_M_0_5_DATA		(0x110000)
 #define   NIC_PF_MCAM_CTRL			(0x120000)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
index b9ece9cbf98b..ed9f10bdf41e 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
@@ -9,12 +9,14 @@
 /* ETHTOOL Support for VNIC_VF Device*/
 
 #include <linux/pci.h>
+#include <linux/net_tstamp.h>
 
 #include "nic_reg.h"
 #include "nic.h"
 #include "nicvf_queues.h"
 #include "q_struct.h"
 #include "thunder_bgx.h"
+#include "../common/cavium_ptp.h"
 
 #define DRV_NAME	"thunder-nicvf"
 #define DRV_VERSION     "1.0"
@@ -824,6 +826,31 @@ static int nicvf_set_pauseparam(struct net_device *dev,
 	return 0;
 }
 
+static int nicvf_get_ts_info(struct net_device *netdev,
+			     struct ethtool_ts_info *info)
+{
+	struct nicvf *nic = netdev_priv(netdev);
+
+	if (!nic->ptp_clock)
+		return ethtool_op_get_ts_info(netdev, info);
+
+	info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
+				SOF_TIMESTAMPING_RX_SOFTWARE |
+				SOF_TIMESTAMPING_SOFTWARE |
+				SOF_TIMESTAMPING_TX_HARDWARE |
+				SOF_TIMESTAMPING_RX_HARDWARE |
+				SOF_TIMESTAMPING_RAW_HARDWARE;
+
+	info->phc_index = cavium_ptp_clock_index(nic->ptp_clock);
+
+	info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
+
+	info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+			   (1 << HWTSTAMP_FILTER_ALL);
+
+	return 0;
+}
+
 static const struct ethtool_ops nicvf_ethtool_ops = {
 	.get_link		= nicvf_get_link,
 	.get_drvinfo		= nicvf_get_drvinfo,
@@ -847,7 +874,7 @@ static const struct ethtool_ops nicvf_ethtool_ops = {
 	.set_channels		= nicvf_set_channels,
 	.get_pauseparam         = nicvf_get_pauseparam,
 	.set_pauseparam         = nicvf_set_pauseparam,
-	.get_ts_info		= ethtool_op_get_ts_info,
+	.get_ts_info		= nicvf_get_ts_info,
 	.get_link_ksettings	= nicvf_get_link_ksettings,
 };
 
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 52b3a6044f85..487d09a32b6d 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -20,11 +20,13 @@
 #include <linux/bpf.h>
 #include <linux/bpf_trace.h>
 #include <linux/filter.h>
+#include <linux/net_tstamp.h>
 
 #include "nic_reg.h"
 #include "nic.h"
 #include "nicvf_queues.h"
 #include "thunder_bgx.h"
+#include "../common/cavium_ptp.h"
 
 #define DRV_NAME	"thunder-nicvf"
 #define DRV_VERSION	"1.0"
@@ -601,6 +603,44 @@ static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog,
 	return false;
 }
 
+static void nicvf_snd_ptp_handler(struct net_device *netdev,
+				  struct cqe_send_t *cqe_tx)
+{
+	struct nicvf *nic = netdev_priv(netdev);
+	struct skb_shared_hwtstamps ts;
+	u64 ns;
+
+	nic = nic->pnicvf;
+
+	/* Sync for 'ptp_skb' */
+	smp_rmb();
+
+	/* New timestamp request can be queued now */
+	atomic_set(&nic->tx_ptp_skbs, 0);
+
+	/* Check for timestamp requested skb */
+	if (!nic->ptp_skb)
+		return;
+
+	/* Check if timestamping is timedout, which is set to 10us */
+	if (cqe_tx->send_status == CQ_TX_ERROP_TSTMP_TIMEOUT ||
+	    cqe_tx->send_status == CQ_TX_ERROP_TSTMP_CONFLICT)
+		goto no_tstamp;
+
+	/* Get the timestamp */
+	memset(&ts, 0, sizeof(ts));
+	ns = cavium_ptp_tstamp2time(nic->ptp_clock, cqe_tx->ptp_timestamp);
+	ts.hwtstamp = ns_to_ktime(ns);
+	skb_tstamp_tx(nic->ptp_skb, &ts);
+
+no_tstamp:
+	/* Free the original skb */
+	dev_kfree_skb_any(nic->ptp_skb);
+	nic->ptp_skb = NULL;
+	/* Sync 'ptp_skb' */
+	smp_wmb();
+}
+
 static void nicvf_snd_pkt_handler(struct net_device *netdev,
 				  struct cqe_send_t *cqe_tx,
 				  int budget, int *subdesc_cnt,
@@ -657,7 +697,12 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev,
 		prefetch(skb);
 		(*tx_pkts)++;
 		*tx_bytes += skb->len;
-		napi_consume_skb(skb, budget);
+		/* If timestamp is requested for this skb, don't free it */
+		if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS &&
+		    !nic->pnicvf->ptp_skb)
+			nic->pnicvf->ptp_skb = skb;
+		else
+			napi_consume_skb(skb, budget);
 		sq->skbuff[cqe_tx->sqe_ptr] = (u64)NULL;
 	} else {
 		/* In case of SW TSO on 88xx, only last segment will have
@@ -696,6 +741,21 @@ static inline void nicvf_set_rxhash(struct net_device *netdev,
 	skb_set_hash(skb, hash, hash_type);
 }
 
+static inline void nicvf_set_rxtstamp(struct nicvf *nic, struct sk_buff *skb)
+{
+	u64 ns;
+
+	if (!nic->ptp_clock || !nic->hw_rx_tstamp)
+		return;
+
+	/* The first 8 bytes is the timestamp */
+	ns = cavium_ptp_tstamp2time(nic->ptp_clock,
+				    be64_to_cpu(*(u64 *)skb->data));
+	skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(ns);
+
+	__skb_pull(skb, 8);
+}
+
 static void nicvf_rcv_pkt_handler(struct net_device *netdev,
 				  struct napi_struct *napi,
 				  struct cqe_rx_t *cqe_rx, struct snd_queue *sq)
@@ -746,6 +806,7 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev,
 		return;
 	}
 
+	nicvf_set_rxtstamp(nic, skb);
 	nicvf_set_rxhash(netdev, cqe_rx, skb);
 
 	skb_record_rx_queue(skb, rq_idx);
@@ -820,10 +881,12 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
 					      &tx_pkts, &tx_bytes);
 			tx_done++;
 		break;
+		case CQE_TYPE_SEND_PTP:
+			nicvf_snd_ptp_handler(netdev, (void *)cq_desc);
+		break;
 		case CQE_TYPE_INVALID:
 		case CQE_TYPE_RX_SPLIT:
 		case CQE_TYPE_RX_TCP:
-		case CQE_TYPE_SEND_PTP:
 			/* Ignore for now */
 		break;
 		}
@@ -1319,12 +1382,28 @@ int nicvf_stop(struct net_device *netdev)
 
 	nicvf_free_cq_poll(nic);
 
+	/* Free any pending SKB saved to receive timestamp */
+	if (nic->ptp_skb) {
+		dev_kfree_skb_any(nic->ptp_skb);
+		nic->ptp_skb = NULL;
+	}
+
 	/* Clear multiqset info */
 	nic->pnicvf = nic;
 
 	return 0;
 }
 
+static int nicvf_config_hw_rx_tstamp(struct nicvf *nic, bool enable)
+{
+	union nic_mbx mbx = {};
+
+	mbx.ptp.msg = NIC_MBOX_MSG_PTP_CFG;
+	mbx.ptp.enable = enable;
+
+	return nicvf_send_msg_to_pf(nic, &mbx);
+}
+
 static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu)
 {
 	union nic_mbx mbx = {};
@@ -1394,6 +1473,12 @@ int nicvf_open(struct net_device *netdev)
 	if (nic->sqs_mode)
 		nicvf_get_primary_vf_struct(nic);
 
+	/* Configure PTP timestamp */
+	if (nic->ptp_clock)
+		nicvf_config_hw_rx_tstamp(nic, nic->hw_rx_tstamp);
+	atomic_set(&nic->tx_ptp_skbs, 0);
+	nic->ptp_skb = NULL;
+
 	/* Configure receive side scaling and MTU */
 	if (!nic->sqs_mode) {
 		nicvf_rss_init(nic);
@@ -1820,6 +1905,77 @@ static void nicvf_xdp_flush(struct net_device *dev)
 	return;
 }
 
+int nicvf_config_hwtstamp(struct net_device *netdev, struct ifreq *ifr)
+{
+	struct hwtstamp_config config;
+	struct nicvf *nic = netdev_priv(netdev);
+
+	if (!nic->ptp_clock)
+		return -ENODEV;
+
+	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	/* reserved for future extensions */
+	if (config.flags)
+		return -EINVAL;
+
+	switch (config.tx_type) {
+	case HWTSTAMP_TX_OFF:
+	case HWTSTAMP_TX_ON:
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	switch (config.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		nic->hw_rx_tstamp = false;
+		break;
+	case HWTSTAMP_FILTER_ALL:
+	case HWTSTAMP_FILTER_SOME:
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		nic->hw_rx_tstamp = true;
+		config.rx_filter = HWTSTAMP_FILTER_ALL;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	if (netif_running(netdev)) {
+		if (nic->hw_rx_tstamp)
+			nicvf_config_hw_rx_tstamp(nic, true);
+		else
+			nicvf_config_hw_rx_tstamp(nic, false);
+	}
+
+	if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int nicvf_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
+{
+	switch (cmd) {
+	case SIOCSHWTSTAMP:
+		return nicvf_config_hwtstamp(netdev, req);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static const struct net_device_ops nicvf_netdev_ops = {
 	.ndo_open		= nicvf_open,
 	.ndo_stop		= nicvf_stop,
@@ -1833,6 +1989,7 @@ static const struct net_device_ops nicvf_netdev_ops = {
 	.ndo_bpf		= nicvf_xdp,
 	.ndo_xdp_xmit		= nicvf_xdp_xmit,
 	.ndo_xdp_flush          = nicvf_xdp_flush,
+	.ndo_do_ioctl           = nicvf_ioctl,
 };
 
 static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -1842,6 +1999,16 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct nicvf *nic;
 	int    err, qcount;
 	u16    sdevid;
+	struct cavium_ptp *ptp_clock;
+
+	ptp_clock = cavium_ptp_get();
+	if (IS_ERR(ptp_clock)) {
+		if (PTR_ERR(ptp_clock) == -ENODEV)
+			/* In virtualized environment we proceed without ptp */
+			ptp_clock = NULL;
+		else
+			return PTR_ERR(ptp_clock);
+	}
 
 	err = pci_enable_device(pdev);
 	if (err) {
@@ -1896,6 +2063,7 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 */
 	if (!nic->t88)
 		nic->max_queues *= 2;
+	nic->ptp_clock = ptp_clock;
 
 	/* MAP VF's configuration registers */
 	nic->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0);
@@ -2009,6 +2177,7 @@ static void nicvf_remove(struct pci_dev *pdev)
 	pci_set_drvdata(pdev, NULL);
 	if (nic->drv_stats)
 		free_percpu(nic->drv_stats);
+	cavium_ptp_put(nic->ptp_clock);
 	free_netdev(netdev);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index 095c18aeb8d5..9a999c62d6ba 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -978,6 +978,9 @@ void nicvf_qset_config(struct nicvf *nic, bool enable)
 		qs_cfg->be = 1;
 #endif
 		qs_cfg->vnic = qs->vnic_id;
+		/* Enable Tx timestamping capability */
+		if (nic->ptp_clock)
+			qs_cfg->send_tstmp_ena = 1;
 	}
 	nicvf_send_msg_to_pf(nic, &mbx);
 }
@@ -1383,6 +1386,29 @@ nicvf_sq_add_hdr_subdesc(struct nicvf *nic, struct snd_queue *sq, int qentry,
 		hdr->inner_l3_offset = skb_network_offset(skb) - 2;
 		this_cpu_inc(nic->pnicvf->drv_stats->tx_tso);
 	}
+
+	/* Check if timestamp is requested */
+	if (!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+		skb_tx_timestamp(skb);
+		return;
+	}
+
+	/* Tx timestamping not supported along with TSO, so ignore request */
+	if (skb_shinfo(skb)->gso_size)
+		return;
+
+	/* HW supports only a single outstanding packet to timestamp */
+	if (!atomic_add_unless(&nic->pnicvf->tx_ptp_skbs, 1, 1))
+		return;
+
+	/* Mark the SKB for later reference */
+	skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+
+	/* Finally enable timestamp generation
+	 * Since 'post_cqe' is also set, two CQEs will be posted
+	 * for this packet i.e CQE_TYPE_SEND and CQE_TYPE_SEND_PTP.
+	 */
+	hdr->tstmp = 1;
 }
 
 /* SQ GATHER subdescriptor
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 5e5c4d7796b8..0f23999c5bcf 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -245,6 +245,35 @@ void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable)
 }
 EXPORT_SYMBOL(bgx_lmac_rx_tx_enable);
 
+/* Enables or disables timestamp insertion by BGX for Rx packets */
+void bgx_config_timestamping(int node, int bgx_idx, int lmacid, bool enable)
+{
+	struct bgx *bgx = get_bgx(node, bgx_idx);
+	struct lmac *lmac;
+	u64 csr_offset, cfg;
+
+	if (!bgx)
+		return;
+
+	lmac = &bgx->lmac[lmacid];
+
+	if (lmac->lmac_type == BGX_MODE_SGMII ||
+	    lmac->lmac_type == BGX_MODE_QSGMII ||
+	    lmac->lmac_type == BGX_MODE_RGMII)
+		csr_offset = BGX_GMP_GMI_RXX_FRM_CTL;
+	else
+		csr_offset = BGX_SMUX_RX_FRM_CTL;
+
+	cfg = bgx_reg_read(bgx, lmacid, csr_offset);
+
+	if (enable)
+		cfg |= BGX_PKT_RX_PTP_EN;
+	else
+		cfg &= ~BGX_PKT_RX_PTP_EN;
+	bgx_reg_write(bgx, lmacid, csr_offset, cfg);
+}
+EXPORT_SYMBOL(bgx_config_timestamping);
+
 void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause)
 {
 	struct pfc *pfc = (struct pfc *)pause;
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
index 23acdc5ab896..5a7567d31138 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
@@ -122,6 +122,8 @@
 #define  SPU_DBG_CTL_AN_NONCE_MCT_DIS		BIT_ULL(29)
 
 #define BGX_SMUX_RX_INT			0x20000
+#define BGX_SMUX_RX_FRM_CTL		0x20020
+#define  BGX_PKT_RX_PTP_EN			BIT_ULL(12)
 #define BGX_SMUX_RX_JABBER		0x20030
 #define BGX_SMUX_RX_CTL			0x20048
 #define  SMU_RX_CTL_STATUS			(3ull << 0)
@@ -172,6 +174,7 @@
 #define  GMI_PORT_CFG_SPEED_MSB			BIT_ULL(8)
 #define  GMI_PORT_CFG_RX_IDLE			BIT_ULL(12)
 #define  GMI_PORT_CFG_TX_IDLE			BIT_ULL(13)
+#define BGX_GMP_GMI_RXX_FRM_CTL		0x38028
 #define BGX_GMP_GMI_RXX_JABBER		0x38038
 #define BGX_GMP_GMI_TXX_THRESH		0x38210
 #define BGX_GMP_GMI_TXX_APPEND		0x38218
@@ -223,6 +226,7 @@ void bgx_set_lmac_mac(int node, int bgx_idx, int lmacid, const u8 *mac);
 void bgx_get_lmac_link_state(int node, int bgx_idx, int lmacid, void *status);
 void bgx_lmac_internal_loopback(int node, int bgx_idx,
 				int lmac_idx, bool enable);
+void bgx_config_timestamping(int node, int bgx_idx, int lmacid, bool enable);
 void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause);
 void bgx_lmac_set_pfc(int node, int bgx_idx, int lmacid, void *pause);
 
-- 
2.15.1

^ permalink raw reply related

* [PATCH v3 18/20] perf: arm_spe: Fail device probe when arm64_kernel_unmapped_at_el0()
From: Mark Rutland @ 2017-12-06 13:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512563739-25239-19-git-send-email-will.deacon@arm.com>

On Wed, Dec 06, 2017 at 12:35:37PM +0000, Will Deacon wrote:
> When running with the kernel unmapped whilst at EL0, the virtually-addressed
> SPE buffer is also unmapped, which can lead to buffer faults if userspace
> profiling is enabled and potentially also when writing back kernel samples
> unless an expensive drain operation is performed on exception return.
> 
> For now, fail the SPE driver probe when arm64_kernel_unmapped_at_el0().
> 
> Signed-off-by: Will Deacon <will.deacon@arm.com>

Reviewed-by: Mark Rutland <mark.rutland@arm.com>

Mark.

> ---
>  drivers/perf/arm_spe_pmu.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c
> index 8ce262fc2561..51b40aecb776 100644
> --- a/drivers/perf/arm_spe_pmu.c
> +++ b/drivers/perf/arm_spe_pmu.c
> @@ -1164,6 +1164,15 @@ static int arm_spe_pmu_device_dt_probe(struct platform_device *pdev)
>  	struct arm_spe_pmu *spe_pmu;
>  	struct device *dev = &pdev->dev;
>  
> +	/*
> +	 * If kernelspace is unmapped when running at EL0, then the SPE
> +	 * buffer will fault and prematurely terminate the AUX session.
> +	 */
> +	if (arm64_kernel_unmapped_at_el0()) {
> +		dev_warn_once(dev, "profiling buffer inaccessible. Try passing \"kpti=off\" on the kernel command line\n");
> +		return -EPERM;
> +	}
> +
>  	spe_pmu = devm_kzalloc(dev, sizeof(*spe_pmu), GFP_KERNEL);
>  	if (!spe_pmu) {
>  		dev_err(dev, "failed to allocate spe_pmu\n");
> -- 
> 2.1.4
> 

^ permalink raw reply

* [RFC PATCH 2/5] perf jevents: add support for arch recommended events
From: Jiri Olsa @ 2017-12-06 13:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512490399-94107-3-git-send-email-john.garry@huawei.com>

On Wed, Dec 06, 2017 at 12:13:16AM +0800, John Garry wrote:
> For some architectures (like arm64), there are architecture-
> defined recommended events. Vendors may not be obliged to
> follow the recommendation and may implement their own pmu
> event for a specific event code.
> 
> This patch adds support for parsing events from arch-defined
> recommended JSONs, and then fixing up vendor events when
> they have implemented these events as recommended.

in the previous patch you added the vendor support, so
you have arch|vendor|platform key for the event list
and perf have the most current/local event list

why would you need to fix it? if there's new event list,
the table gets updated, perf is rebuilt.. I'm clearly
missing something ;-)

> In the vendor JSON, to specify that the event is supported
> according to the recommendation, only the event code is
> added to the JSON entry - no other event elements need be
> added, like below:
> [
>     {
>         "EventCode": "0x40",
>     },
> 
> ]
> 
> The pmu event parsing will check for "BriefDescription"
> field presence only for this.
> 
> If "BriefDescription" is present, then it is implied
> that the vendor has implemented their own custom event,
> and there is no fixup. Other fields are ignored.

if we are going this way, please use some new token,
this list is supposed to be human readable

thanks,
jirka

^ permalink raw reply

* [PATCH] ACPI / GED: unregister interrupts during shutdown
From: Rafael J. Wysocki @ 2017-12-06 13:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <0b661eec-f9c7-7818-ad09-f3d488adcefe@codeaurora.org>

On Wed, Dec 6, 2017 at 2:24 PM, Sinan Kaya <okaya@codeaurora.org> wrote:
> On 12/5/2017 5:18 PM, Rafael J. Wysocki wrote:
>> On Tue, Dec 5, 2017 at 10:01 PM, Sinan Kaya <okaya@codeaurora.org> wrote:
>>> Some GED interrupts could be pending by the time we are doing a reboot.

[cut]

>
>>
>>>         .probe = ged_probe,
>>>         .driver = {
>>>                 .name = MODULE_NAME,
>>> --
>>
>> Overall, it looks like we should just unbind the driver from all
>> devices on shutdown.
>
> I see that shutdown is getting called on all GED instances. That should
> take care of it, right?

Yes, it should, so I'm not sure why you need the list in the first place.

Also it looks like something along the lines of devres_release_all()
should be sufficient.

Thanks,
Rafael

^ permalink raw reply

* [PATCH 0/2] Fixes for SW PAN
From: Will Deacon @ 2017-12-06 13:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171206121941.vcxgcjb5pzr7dlpn@lakrids.cambridge.arm.com>

On Wed, Dec 06, 2017 at 12:19:41PM +0000, Mark Rutland wrote:
> On Wed, Dec 06, 2017 at 11:16:06AM +0000, Will Deacon wrote:
> > After lots of collective head scratching in response to Vinayak's mail
> > here:
> > 
> >   http://lists.infradead.org/pipermail/linux-arm-kernel/2017-December/545641.html
> > 
> > It turns out that we have a problem with SW PAN and kernel threads, where
> > the saved ttbr0 value for a kernel thread can be stale and subsequently
> > inherited by other kernel threads over a fork.
> > 
> > These two patches attempt to fix that. We've not be able to reproduce
> > the exact failure reported above, but I added some assertions to the
> > uaccess routines to check for discrepancies between the active_mm pgd
> > and the saved ttbr0 value (ignoring the zero page) and these no longer
> > fire with these changes, but do fire without them if EFI runtime services
> > are enabled on my Seattle board.
> 
> Both patches look good to me, per my understanding of the problem, so
> FWIW, for the series:
> 
> Reviewed-by: Mark Rutland <mark.rutland@arm.com>
> 
> However, I think we have another issue in this area. We have sequences
> where we update the HW TTBR0 before the shadow, e.g. in efi_set_pgd(),
> where we do:
> 
> 	cpu_set_reserved_ttbr0();
> 	update_saved_ttbr0(current, current->active_mm);
> 
> ... so if an exception comes in between after HW TTBR0 update but before
> the shadow update, the stale shadow value will be restored upon the
> exception return, leaving the HW TTBR0 stale.

I don't see how that can happen. The entry code checks the ttbr0 ASID value
and if it's zero (as it will be above), it sets the PAN bit in the saved PSR
and we avoid doing any uaccess toggling (including on exception return).

> That's easy enough to fix in the efi code, e.g.
> 
> 	update_saved_ttbr0(current, current->active_mm);
> 	barrier();
> 	cpu_set_reserved_ttbr0();
> 
> ... but I haven't yet figured out a nice way to sort out switch_mm(),
> __switch_mm(), and check_and_switch_context().

I don't see the problem there either. Can you elaborate please?

Will

^ permalink raw reply

* [RFC PATCH 2/5] perf jevents: add support for arch recommended events
From: Jiri Olsa @ 2017-12-06 13:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512490399-94107-3-git-send-email-john.garry@huawei.com>

On Wed, Dec 06, 2017 at 12:13:16AM +0800, John Garry wrote:

SNIP

> ---
>  tools/perf/pmu-events/jevents.c | 215 ++++++++++++++++++++++++++++++++++++----
>  1 file changed, 198 insertions(+), 17 deletions(-)
> 
> diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
> index a0d489e..a820ed4 100644
> --- a/tools/perf/pmu-events/jevents.c
> +++ b/tools/perf/pmu-events/jevents.c
> @@ -42,6 +42,7 @@
>  #include <dirent.h>
>  #include <sys/time.h>			/* getrlimit */
>  #include <sys/resource.h>		/* getrlimit */
> +#include <sys/queue.h>
>  #include <ftw.h>
>  #include <sys/stat.h>
>  #include "jsmn.h"
> @@ -366,6 +367,94 @@ static int print_events_table_entry(void *data, char *name, char *event,
>  	return 0;
>  }
>  
> +struct event_struct {
> +	char *name;
> +	char *event;
> +	char *desc;
> +	char *long_desc;
> +	char *pmu;
> +	char *unit;
> +	char *perpkg;
> +	char *metric_expr;
> +	char *metric_name;
> +	char *metric_group;
> +	LIST_ENTRY(event_struct) list;

is there any reason you don't use the 'struct list_head' ?
I dont think we want another thingie involved for lists

jirka

^ permalink raw reply

* [RFC PATCH 1/5] perf jevents: add support for pmu events vendor subdirectory
From: Jiri Olsa @ 2017-12-06 13:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512490399-94107-2-git-send-email-john.garry@huawei.com>

On Wed, Dec 06, 2017 at 12:13:15AM +0800, John Garry wrote:

SNIP

> diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
> index b578aa2..a0d489e 100644
> --- a/tools/perf/pmu-events/jevents.c
> +++ b/tools/perf/pmu-events/jevents.c
> @@ -588,7 +588,7 @@ static char *file_name_to_table_name(char *fname)
>  	 * Derive rest of table name from basename of the JSON file,
>  	 * replacing hyphens and stripping out .json suffix.
>  	 */
> -	n = asprintf(&tblname, "pme_%s", basename(fname));
> +	n = asprintf(&tblname, "pme_%s", fname);
>  	if (n < 0) {
>  		pr_info("%s: asprintf() error %s for file %s\n", prog,
>  				strerror(errno), fname);
> @@ -598,7 +598,7 @@ static char *file_name_to_table_name(char *fname)
>  	for (i = 0; i < strlen(tblname); i++) {
>  		c = tblname[i];
>  
> -		if (c == '-')
> +		if (c == '-' || c == '/')
>  			tblname[i] = '_';
>  		else if (c == '.') {
>  			tblname[i] = '\0';
> @@ -755,15 +755,52 @@ static int get_maxfds(void)
>  static FILE *eventsfp;
>  static char *mapfile;
>  
> +static int isLeafDir(const char *fpath)

we use _ to separate words in functions names

> +{
> +	DIR 		  *d;
> +	struct dirent *dir;
> +	int res = 1;
> +	d = opendir(fpath);
> +	if (!d)
> +		return 0;
> +
> +	while ((dir = readdir(d)) != NULL) {
> +		if (dir-> d_type == DT_DIR && dir->d_name[0] != '.') {
> +			res = 0;
> +			break;

just recently got into a issue on xfs when d_type is DT_UNKNOWN
for directory.. you need to handle it

thanks,
jirka

^ permalink raw reply

* [PATCH v9 3/5] perf utils: use pmu->is_uncore to detect PMU UNCORE devices
From: Arnaldo Carvalho de Melo @ 2017-12-06 13:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <71db0255-af9b-968a-7baa-238d7146f069@linux.intel.com>

Em Wed, Dec 06, 2017 at 08:30:37AM +0800, Jin, Yao escreveu:
> 
> 
> On 12/6/2017 2:42 AM, Arnaldo Carvalho de Melo wrote:
> > Em Tue, Dec 05, 2017 at 08:35:22PM +0800, Jin, Yao escreveu:
> > > A quick test with the new patch 'fix_json_v9_2.patch' shows it working.
> > 
> > I'll take this as a Tested-by: you, ok?
> 
> Hi Arnaldo,
> 
> I didn't do a full test for this patch and for the whole patch series.
> 
> I just do a quick test and it shows that the regression issue which was
> found in 'perf stat --per-thread' test case is disappear.
> 
> If you think it's enough for adding Tested-by, that's fine for me. :)

I guess this addresses at least your previous regression report, so I
think it is warranted, thanks!

- arnaldo
 
> Thanks
> Jin Yao
> 
> > > See the log:
> > > 
> > > root at skl:/tmp# perf stat --per-thread -p 10322 -M CPI,IPC
> > > ^C
> > >   Performance counter stats for process id '10322':
> > > 
> > >            vmstat-10322             1,879,654      inst_retired.any #
> > > 0.8 CPI
> > >            vmstat-10322             1,565,807      cycles
> > >            vmstat-10322             1,879,654      inst_retired.any #
> > > 1.2 IPC
> > >            vmstat-10322             1,565,807      cpu_clk_unhalted.thread
> > > 
> > >         2.850291804 seconds time elapsed
> > > 
> > > Thanks for fixing it quickly.
> > > 
> > > Thanks
> > > Jin Yao
> > > 
> > > On 12/5/2017 3:23 PM, Jin, Yao wrote:
> > > > Hi,
> > > > 
> > > > I applied the diff but it's failed.
> > > > 
> > > > jinyao at skl:~/skl-ws/perf-dev/lck-4594/src$ patch -p1 < 1.pat
> > > > patching file tools/perf/util/pmu.c
> > > > patch: **** malformed patch at line 41: *head, struct perf_pmu *pmu)
> > > > 
> > > > Could you send the patch as attachment to me in another mail thread?
> > > > 
> > > > to yao.jin at linux.intel.com
> > > > cc yao.jin at intel.com
> > > > 
> > > > Thanks
> > > > Jin Yao
> > > > 
> > > > On 12/5/2017 3:12 PM, Ganapatrao Kulkarni wrote:
> > > > > diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
> > > > > index 5ad8a18..57e38fd 100644
> > > > > --- a/tools/perf/util/pmu.c
> > > > > +++ b/tools/perf/util/pmu.c
> > > > > @@ -538,6 +538,34 @@ static bool pmu_is_uncore(const char *name)
> > > > >  ? }
> > > > > 
> > > > >  ? /*
> > > > > + *? PMU CORE devices have different name other than cpu in sysfs on some
> > > > > + *? platforms. looking for possible sysfs files to identify as core
> > > > > device.
> > > > > + */
> > > > > +static int is_pmu_core(const char *name)
> > > > > +{
> > > > > + struct stat st;
> > > > > + char path[PATH_MAX];
> > > > > + const char *sysfs = sysfs__mountpoint();
> > > > > +
> > > > > + if (!sysfs)
> > > > > + return 0;
> > > > > +
> > > > > + /* Look for cpu sysfs (x86 and others) */
> > > > > + scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu", sysfs);
> > > > > + if ((stat(path, &st) == 0) &&
> > > > > + (strncmp(name, "cpu", strlen("cpu")) == 0))
> > > > > + return 1;
> > > > > +
> > > > > + /* Look for cpu sysfs (specific to arm) */
> > > > > + scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s/cpus",
> > > > > + sysfs, name);
> > > > > + if (stat(path, &st) == 0)
> > > > > + return 1;
> > > > > +
> > > > > + return 0;
> > > > > +}
> > > > > +
> > > > > +/*
> > > > >  ?? * Return the CPU id as a raw string.
> > > > >  ?? *
> > > > >  ?? * Each architecture should provide a more precise id string that
> > > > > @@ -641,7 +669,7 @@ static void pmu_add_cpu_aliases(struct list_head
> > > > > *head, struct perf_pmu *pmu)
> > > > >  ?? break;
> > > > >  ?? }
> > > > > 
> > > > > - if (pmu->is_uncore) {
> > > > > + if (!is_pmu_core(name)) {
> > > > >  ?? /* check for uncore devices */
> > > > >  ?? if (pe->pmu == NULL)
> > > > >  ?? continue;

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox