* [PATCH 09/18] arm64: convert syscall trace logic to C
From: Mark Rutland @ 2018-05-14 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514094640.27569-1-mark.rutland@arm.com>
Currently syscall tracing is a tricky assembly state machine, which can
be rather difficult to follow, and even harder to modify. Before we
start fiddling with it for pt_regs syscalls, let's convert it to C.
This is not intended to have any functional change.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
arch/arm64/kernel/entry.S | 53 ++----------------------------------------
arch/arm64/kernel/syscall.c | 56 +++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 56 insertions(+), 53 deletions(-)
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index d6e057500eaf..5c60369b52fc 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -866,24 +866,6 @@ el0_error_naked:
b ret_to_user
ENDPROC(el0_error)
-
-/*
- * This is the fast syscall return path. We do as little as possible here,
- * and this includes saving x0 back into the kernel stack.
- */
-ret_fast_syscall:
- disable_daif
- ldr x1, [tsk, #TSK_TI_FLAGS] // re-check for syscall tracing
- and x2, x1, #_TIF_SYSCALL_WORK
- cbnz x2, ret_fast_syscall_trace
- and x2, x1, #_TIF_WORK_MASK
- cbnz x2, work_pending
- enable_step_tsk x1, x2
- kernel_exit 0
-ret_fast_syscall_trace:
- enable_daif
- b __sys_trace_return_skipped // we already saved x0
-
/*
* Ok, we need to do extra processing, enter the slow path.
*/
@@ -939,44 +921,13 @@ alternative_else_nop_endif
#endif
el0_svc_naked: // compat entry point
- stp x0, xscno, [sp, #S_ORIG_X0] // save the original x0 and syscall number
- enable_daif
- ct_user_exit 1
-
- tst x16, #_TIF_SYSCALL_WORK // check for syscall hooks
- b.ne __sys_trace
mov x0, sp
mov w1, wscno
mov w2, wsc_nr
mov x3, stbl
- bl invoke_syscall
- b ret_fast_syscall
-ENDPROC(el0_svc)
-
- /*
- * This is the really slow path. We're going to be doing context
- * switches, and waiting for our parent to respond.
- */
-__sys_trace:
- cmp wscno, #NO_SYSCALL // user-issued syscall(-1)?
- b.ne 1f
- mov x0, #-ENOSYS // set default errno if so
- str x0, [sp, #S_X0]
-1: mov x0, sp
- bl syscall_trace_enter
- cmp w0, #NO_SYSCALL // skip the syscall?
- b.eq __sys_trace_return_skipped
-
- mov x0, sp
- mov w1, wscno
- mov w2, wsc_nr
- mov x3, stbl
- bl invoke_syscall
-
-__sys_trace_return_skipped:
- mov x0, sp
- bl syscall_trace_exit
+ bl el0_svc_common
b ret_to_user
+ENDPROC(el0_svc)
.popsection // .entry.text
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c
index 58d7569f47df..5df857e32b48 100644
--- a/arch/arm64/kernel/syscall.c
+++ b/arch/arm64/kernel/syscall.c
@@ -1,8 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
+#include <linux/compiler.h>
+#include <linux/context_tracking.h>
#include <linux/nospec.h>
#include <linux/ptrace.h>
+#include <asm/daifflags.h>
+#include <asm/thread_info.h>
+
long do_ni_syscall(struct pt_regs *regs);
typedef long (*syscall_fn_t)(unsigned long, unsigned long,
@@ -16,8 +21,8 @@ static void __invoke_syscall(struct pt_regs *regs, syscall_fn_t syscall_fn)
regs->regs[4], regs->regs[5]);
}
-asmlinkage void invoke_syscall(struct pt_regs *regs, int scno, int sc_nr,
- syscall_fn_t syscall_table[])
+static void invoke_syscall(struct pt_regs *regs, int scno, int sc_nr,
+ syscall_fn_t syscall_table[])
{
if (scno < sc_nr) {
syscall_fn_t syscall_fn;
@@ -27,3 +32,50 @@ asmlinkage void invoke_syscall(struct pt_regs *regs, int scno, int sc_nr,
regs->regs[0] = do_ni_syscall(regs);
}
}
+
+static inline bool has_syscall_work(unsigned long flags)
+{
+ return unlikely(flags & _TIF_SYSCALL_WORK);
+}
+
+int syscall_trace_enter(struct pt_regs *regs);
+void syscall_trace_exit(struct pt_regs *regs);
+
+asmlinkage void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
+ syscall_fn_t syscall_table[])
+{
+ unsigned long flags = current_thread_info()->flags;
+
+ regs->orig_x0 = regs->regs[0];
+ regs->syscallno = scno;
+
+ local_daif_restore(DAIF_PROCCTX);
+ user_exit();
+
+ if (has_syscall_work(flags)) {
+ /* set default errno for user-issued syscall(-1) */
+ if (scno == NO_SYSCALL)
+ regs->regs[0] = -ENOSYS;
+ scno = syscall_trace_enter(regs);
+ if (scno == NO_SYSCALL)
+ goto trace_exit;
+ }
+
+ invoke_syscall(regs, scno, sc_nr, syscall_table);
+
+ /*
+ * The tracing status may have changed under our feet, so we have to
+ * check again. However, if we were tracing entry, then we always trace
+ * exit regardless, as the old entry assembly did.
+ */
+ if (!has_syscall_work(flags)) {
+ local_daif_mask();
+ flags = current_thread_info()->flags;
+ if (!has_syscall_work(flags))
+ return;
+ local_daif_restore(DAIF_PROCCTX);
+ }
+
+trace_exit:
+ syscall_trace_exit(regs);
+}
--
2.11.0
^ permalink raw reply related
* [PATCH 08/18] arm64: convert raw syscall invocation to C
From: Mark Rutland @ 2018-05-14 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514094640.27569-1-mark.rutland@arm.com>
As a first step towards invoking syscalls with a pt_regs argument,
convert the raw syscall invocation logic to C. We end up with a bit more
register shuffling, but the unified invocation logic means we can unify
the tracing paths, too.
This only converts the invocation of the syscall. The rest of the
syscall triage and tracing is left in assembly for now, and will be
converted in subsequent patches.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
arch/arm64/kernel/Makefile | 3 ++-
arch/arm64/kernel/entry.S | 36 ++++++++++--------------------------
arch/arm64/kernel/syscall.c | 29 +++++++++++++++++++++++++++++
3 files changed, 41 insertions(+), 27 deletions(-)
create mode 100644 arch/arm64/kernel/syscall.c
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index bf825f38d206..c22e8ace5ea3 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -18,7 +18,8 @@ arm64-obj-y := debug-monitors.o entry.o irq.o fpsimd.o \
hyp-stub.o psci.o cpu_ops.o insn.o \
return_address.o cpuinfo.o cpu_errata.o \
cpufeature.o alternative.o cacheinfo.o \
- smp.o smp_spin_table.o topology.o smccc-call.o
+ smp.o smp_spin_table.o topology.o smccc-call.o \
+ syscall.o
extra-$(CONFIG_EFI) := efi-entry.o
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 08ea3cbfb08f..d6e057500eaf 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -873,7 +873,6 @@ ENDPROC(el0_error)
*/
ret_fast_syscall:
disable_daif
- str x0, [sp, #S_X0] // returned x0
ldr x1, [tsk, #TSK_TI_FLAGS] // re-check for syscall tracing
and x2, x1, #_TIF_SYSCALL_WORK
cbnz x2, ret_fast_syscall_trace
@@ -946,15 +945,11 @@ el0_svc_naked: // compat entry point
tst x16, #_TIF_SYSCALL_WORK // check for syscall hooks
b.ne __sys_trace
- cmp wscno, wsc_nr // check upper syscall limit
- b.hs ni_sys
- mask_nospec64 xscno, xsc_nr, x19 // enforce bounds for syscall number
- ldr x16, [stbl, xscno, lsl #3] // address in the syscall table
- blr x16 // call sys_* routine
- b ret_fast_syscall
-ni_sys:
mov x0, sp
- bl do_ni_syscall
+ mov w1, wscno
+ mov w2, wsc_nr
+ mov x3, stbl
+ bl invoke_syscall
b ret_fast_syscall
ENDPROC(el0_svc)
@@ -971,29 +966,18 @@ __sys_trace:
bl syscall_trace_enter
cmp w0, #NO_SYSCALL // skip the syscall?
b.eq __sys_trace_return_skipped
- mov wscno, w0 // syscall number (possibly new)
- mov x1, sp // pointer to regs
- cmp wscno, wsc_nr // check upper syscall limit
- b.hs __ni_sys_trace
- ldp x0, x1, [sp] // restore the syscall args
- ldp x2, x3, [sp, #S_X2]
- ldp x4, x5, [sp, #S_X4]
- ldp x6, x7, [sp, #S_X6]
- ldr x16, [stbl, xscno, lsl #3] // address in the syscall table
- blr x16 // call sys_* routine
-__sys_trace_return:
- str x0, [sp, #S_X0] // save returned x0
+ mov x0, sp
+ mov w1, wscno
+ mov w2, wsc_nr
+ mov x3, stbl
+ bl invoke_syscall
+
__sys_trace_return_skipped:
mov x0, sp
bl syscall_trace_exit
b ret_to_user
-__ni_sys_trace:
- mov x0, sp
- bl do_ni_syscall
- b __sys_trace_return
-
.popsection // .entry.text
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c
new file mode 100644
index 000000000000..58d7569f47df
--- /dev/null
+++ b/arch/arm64/kernel/syscall.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/nospec.h>
+#include <linux/ptrace.h>
+
+long do_ni_syscall(struct pt_regs *regs);
+
+typedef long (*syscall_fn_t)(unsigned long, unsigned long,
+ unsigned long, unsigned long,
+ unsigned long, unsigned long);
+
+static void __invoke_syscall(struct pt_regs *regs, syscall_fn_t syscall_fn)
+{
+ regs->regs[0] = syscall_fn(regs->regs[0], regs->regs[1],
+ regs->regs[2], regs->regs[3],
+ regs->regs[4], regs->regs[5]);
+}
+
+asmlinkage void invoke_syscall(struct pt_regs *regs, int scno, int sc_nr,
+ syscall_fn_t syscall_table[])
+{
+ if (scno < sc_nr) {
+ syscall_fn_t syscall_fn;
+ syscall_fn = syscall_table[array_index_nospec(scno, sc_nr)];
+ __invoke_syscall(regs, syscall_fn);
+ } else {
+ regs->regs[0] = do_ni_syscall(regs);
+ }
+}
--
2.11.0
^ permalink raw reply related
* [PATCH 07/18] arm64: remove sigreturn wrappers
From: Mark Rutland @ 2018-05-14 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514094640.27569-1-mark.rutland@arm.com>
The arm64 sigreturn* syscall handlers are non-standard. Rather than
taking a number of user parameters in registers as per the AAPCS,
they expect the pt_regs as their sole argument.
To make this work, we override the syscall definitions to invoke
wrappers written in assembly, which mov the SP into x0, and branch to
their respective C functions.
On other architectures (such as x86), the sigreturn* functions take no
argument and instead use current_pt_regs() to acquire the user
registers. This requires less boilerplate code, and allows for other
features such as interposing C code in this path.
This patch takes the same approach for arm64.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
arch/arm64/include/asm/unistd32.h | 4 ++--
arch/arm64/kernel/entry.S | 8 --------
arch/arm64/kernel/entry32.S | 10 ----------
arch/arm64/kernel/signal.c | 3 ++-
arch/arm64/kernel/signal32.c | 6 ++++--
arch/arm64/kernel/sys.c | 3 +--
arch/arm64/kernel/sys32.c | 4 ++--
7 files changed, 11 insertions(+), 27 deletions(-)
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index ef292160748c..ab95554b1734 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -260,7 +260,7 @@ __SYSCALL(117, sys_ni_syscall)
#define __NR_fsync 118
__SYSCALL(__NR_fsync, sys_fsync)
#define __NR_sigreturn 119
-__SYSCALL(__NR_sigreturn, compat_sys_sigreturn_wrapper)
+__SYSCALL(__NR_sigreturn, compat_sys_sigreturn)
#define __NR_clone 120
__SYSCALL(__NR_clone, sys_clone)
#define __NR_setdomainname 121
@@ -368,7 +368,7 @@ __SYSCALL(__NR_getresgid, sys_getresgid16)
#define __NR_prctl 172
__SYSCALL(__NR_prctl, sys_prctl)
#define __NR_rt_sigreturn 173
-__SYSCALL(__NR_rt_sigreturn, compat_sys_rt_sigreturn_wrapper)
+__SYSCALL(__NR_rt_sigreturn, compat_sys_rt_sigreturn)
#define __NR_rt_sigaction 174
__SYSCALL(__NR_rt_sigaction, compat_sys_rt_sigaction)
#define __NR_rt_sigprocmask 175
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index ec2ee720e33e..08ea3cbfb08f 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -1108,14 +1108,6 @@ __entry_tramp_data_start:
#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
/*
- * Special system call wrappers.
- */
-ENTRY(sys_rt_sigreturn_wrapper)
- mov x0, sp
- b sys_rt_sigreturn
-ENDPROC(sys_rt_sigreturn_wrapper)
-
-/*
* Register switch for AArch64. The callee-saved registers need to be saved
* and restored. On entry:
* x0 = previous task_struct (must be preserved across the switch)
diff --git a/arch/arm64/kernel/entry32.S b/arch/arm64/kernel/entry32.S
index f332d5d1f6b4..f9461696dde4 100644
--- a/arch/arm64/kernel/entry32.S
+++ b/arch/arm64/kernel/entry32.S
@@ -30,16 +30,6 @@
* System call wrappers for the AArch32 compatibility layer.
*/
-ENTRY(compat_sys_sigreturn_wrapper)
- mov x0, sp
- b compat_sys_sigreturn
-ENDPROC(compat_sys_sigreturn_wrapper)
-
-ENTRY(compat_sys_rt_sigreturn_wrapper)
- mov x0, sp
- b compat_sys_rt_sigreturn
-ENDPROC(compat_sys_rt_sigreturn_wrapper)
-
ENTRY(compat_sys_statfs64_wrapper)
mov w3, #84
cmp w1, #88
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 8e624fec4707..caa7a68cf2d2 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -538,8 +538,9 @@ static int restore_sigframe(struct pt_regs *regs,
return err;
}
-asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
+asmlinkage long sys_rt_sigreturn(void)
{
+ struct pt_regs *regs = current_pt_regs();
struct rt_sigframe __user *frame;
/* Always make any pending restarted system calls return -EINTR */
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 77b91f478995..cb10588a7cb2 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -282,8 +282,9 @@ static int compat_restore_sigframe(struct pt_regs *regs,
return err;
}
-asmlinkage int compat_sys_sigreturn(struct pt_regs *regs)
+asmlinkage int compat_sys_sigreturn(void)
{
+ struct pt_regs *regs = current_pt_regs();
struct compat_sigframe __user *frame;
/* Always make any pending restarted system calls return -EINTR */
@@ -312,8 +313,9 @@ asmlinkage int compat_sys_sigreturn(struct pt_regs *regs)
return 0;
}
-asmlinkage int compat_sys_rt_sigreturn(struct pt_regs *regs)
+asmlinkage int compat_sys_rt_sigreturn(void)
{
+ struct pt_regs *regs = current_pt_regs();
struct compat_rt_sigframe __user *frame;
/* Always make any pending restarted system calls return -EINTR */
diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c
index 72981bae10eb..31045f3fed92 100644
--- a/arch/arm64/kernel/sys.c
+++ b/arch/arm64/kernel/sys.c
@@ -48,8 +48,7 @@ SYSCALL_DEFINE1(arm64_personality, unsigned int, personality)
/*
* Wrappers to pass the pt_regs argument.
*/
-asmlinkage long sys_rt_sigreturn_wrapper(void);
-#define sys_rt_sigreturn sys_rt_sigreturn_wrapper
+asmlinkage long sys_rt_sigreturn(void);
#define sys_personality sys_arm64_personality
#undef __SYSCALL
diff --git a/arch/arm64/kernel/sys32.c b/arch/arm64/kernel/sys32.c
index a40b1343b819..1ef103c95410 100644
--- a/arch/arm64/kernel/sys32.c
+++ b/arch/arm64/kernel/sys32.c
@@ -25,8 +25,8 @@
#include <linux/compiler.h>
#include <linux/syscalls.h>
-asmlinkage long compat_sys_sigreturn_wrapper(void);
-asmlinkage long compat_sys_rt_sigreturn_wrapper(void);
+asmlinkage long compat_sys_sigreturn(void);
+asmlinkage long compat_sys_rt_sigreturn(void);
asmlinkage long compat_sys_statfs64_wrapper(void);
asmlinkage long compat_sys_fstatfs64_wrapper(void);
asmlinkage long compat_sys_pread64_wrapper(void);
--
2.11.0
^ permalink raw reply related
* [PATCH 06/18] arm64: move sve_user_{enable, disable} to <asm/fpsimd.h>
From: Mark Rutland @ 2018-05-14 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514094640.27569-1-mark.rutland@arm.com>
In subsequent patches, we'll want to make use of sve_user_enable() and
sve_user_disable() outside of kernel/fpsimd.c. Let's move these to
<asm/fpsimd.h> where we can make use of them.
To avoid ifdeffery in sequences like:
if (system_supports_sve() && some_condition
sve_user_disable();
... empty stubs are provided when support for SVE is not enabled.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
arch/arm64/include/asm/fpsimd.h | 17 ++++++++++++++++-
arch/arm64/kernel/fpsimd.c | 11 -----------
2 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index aa7162ae93e3..7377d7593c06 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -16,11 +16,13 @@
#ifndef __ASM_FP_H
#define __ASM_FP_H
-#include <asm/ptrace.h>
#include <asm/errno.h>
+#include <asm/ptrace.h>
+#include <asm/sysreg.h>
#ifndef __ASSEMBLY__
+#include <linux/build_bug.h>
#include <linux/cache.h>
#include <linux/init.h>
#include <linux/stddef.h>
@@ -81,6 +83,16 @@ extern int sve_set_vector_length(struct task_struct *task,
extern int sve_set_current_vl(unsigned long arg);
extern int sve_get_current_vl(void);
+static inline void sve_user_disable(void)
+{
+ sysreg_clear_set(cpacr_el1, CPACR_EL1_ZEN_EL0EN, 0);
+}
+
+static inline void sve_user_enable(void)
+{
+ sysreg_clear_set(cpacr_el1, 0, CPACR_EL1_ZEN_EL0EN);
+}
+
/*
* Probing and setup functions.
* Calls to these functions must be serialised with one another.
@@ -107,6 +119,9 @@ static inline int sve_get_current_vl(void)
return -EINVAL;
}
+static inline void sve_user_disable(void) { }
+static inline void sve_user_enable(void) { }
+
static inline void sve_init_vq_map(void) { }
static inline void sve_update_vq_map(void) { }
static inline int sve_verify_vq_map(void) { return 0; }
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 088940387a4d..79a81c7d85c6 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -159,7 +159,6 @@ static void sve_free(struct task_struct *task)
__sve_free(task);
}
-
/* Offset of FFR in the SVE register dump */
static size_t sve_ffr_offset(int vl)
{
@@ -172,16 +171,6 @@ static void *sve_pffr(struct task_struct *task)
sve_ffr_offset(task->thread.sve_vl);
}
-static void sve_user_disable(void)
-{
- sysreg_clear_set(cpacr_el1, CPACR_EL1_ZEN_EL0EN, 0);
-}
-
-static void sve_user_enable(void)
-{
- sysreg_clear_set(cpacr_el1, 0, CPACR_EL1_ZEN_EL0EN);
-}
-
/*
* TIF_SVE controls whether a task can use SVE without trapping while
* in userspace, and also the way a task's FPSIMD/SVE state is stored
--
2.11.0
^ permalink raw reply related
* [PATCH 05/18] arm64: kill change_cpacr()
From: Mark Rutland @ 2018-05-14 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514094640.27569-1-mark.rutland@arm.com>
Now that we have sysreg_clear_set(), we can use this instead of
change_cpacr().
Note that the order of the set and clear arguments differs between
change_cpacr() and sysreg_clear_set(), so these are flipped as part of
the conversion. Also, sve_user_enable() redundantly clears
CPACR_EL1_ZEN_EL0EN before setting it; this is removed for clarity.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
arch/arm64/kernel/fpsimd.c | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 87a35364e750..088940387a4d 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -172,23 +172,14 @@ static void *sve_pffr(struct task_struct *task)
sve_ffr_offset(task->thread.sve_vl);
}
-static void change_cpacr(u64 val, u64 mask)
-{
- u64 cpacr = read_sysreg(CPACR_EL1);
- u64 new = (cpacr & ~mask) | val;
-
- if (new != cpacr)
- write_sysreg(new, CPACR_EL1);
-}
-
static void sve_user_disable(void)
{
- change_cpacr(0, CPACR_EL1_ZEN_EL0EN);
+ sysreg_clear_set(cpacr_el1, CPACR_EL1_ZEN_EL0EN, 0);
}
static void sve_user_enable(void)
{
- change_cpacr(CPACR_EL1_ZEN_EL0EN, CPACR_EL1_ZEN_EL0EN);
+ sysreg_clear_set(cpacr_el1, 0, CPACR_EL1_ZEN_EL0EN);
}
/*
--
2.11.0
^ permalink raw reply related
* [PATCH 04/18] arm64: kill config_sctlr_el1()
From: Mark Rutland @ 2018-05-14 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514094640.27569-1-mark.rutland@arm.com>
Now that we have sysreg_clear_set(), we can consistently use this
instead of config_sctlr_el1().
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
arch/arm64/include/asm/sysreg.h | 10 ----------
arch/arm64/kernel/armv8_deprecated.c | 8 ++++----
arch/arm64/kernel/cpu_errata.c | 3 +--
arch/arm64/kernel/traps.c | 2 +-
arch/arm64/mm/fault.c | 2 +-
5 files changed, 7 insertions(+), 18 deletions(-)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index b52762769329..3493c7048994 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -740,16 +740,6 @@ asm(
write_sysreg(__scs_new, sysreg); \
} while (0)
-static inline void config_sctlr_el1(u32 clear, u32 set)
-{
- u32 val;
-
- val = read_sysreg(sctlr_el1);
- val &= ~clear;
- val |= set;
- write_sysreg(val, sctlr_el1);
-}
-
#endif
#endif /* __ASM_SYSREG_H */
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 6e47fc3ab549..778cf810f0d8 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -512,9 +512,9 @@ static int cp15barrier_handler(struct pt_regs *regs, u32 instr)
static int cp15_barrier_set_hw_mode(bool enable)
{
if (enable)
- config_sctlr_el1(0, SCTLR_EL1_CP15BEN);
+ sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_CP15BEN);
else
- config_sctlr_el1(SCTLR_EL1_CP15BEN, 0);
+ sysreg_clear_set(sctlr_el1, SCTLR_EL1_CP15BEN, 0);
return 0;
}
@@ -549,9 +549,9 @@ static int setend_set_hw_mode(bool enable)
return -EINVAL;
if (enable)
- config_sctlr_el1(SCTLR_EL1_SED, 0);
+ sysreg_clear_set(sctlr_el1, SCTLR_EL1_SED, 0);
else
- config_sctlr_el1(0, SCTLR_EL1_SED);
+ sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_SED);
return 0;
}
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index a900befadfe8..879daf8ea0f8 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -74,8 +74,7 @@ has_mismatched_cache_line_size(const struct arm64_cpu_capabilities *entry,
static void
cpu_enable_trap_ctr_access(const struct arm64_cpu_capabilities *__unused)
{
- /* Clear SCTLR_EL1.UCT */
- config_sctlr_el1(SCTLR_EL1_UCT, 0);
+ sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCT, 0);
}
atomic_t arm64_el2_vector_last_slot = ATOMIC_INIT(-1);
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 8bbdc17e49df..b8d3e0d8c616 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -411,7 +411,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused)
{
- config_sctlr_el1(SCTLR_EL1_UCI, 0);
+ sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCI, 0);
}
#define __user_cache_maint(insn, address, res) \
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 4165485e8b6e..e7977d932038 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -812,7 +812,7 @@ void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused)
*/
WARN_ON_ONCE(in_interrupt());
- config_sctlr_el1(SCTLR_EL1_SPAN, 0);
+ sysreg_clear_set(sctlr_el1, SCTLR_EL1_SPAN, 0);
asm(SET_PSTATE_PAN(1));
}
#endif /* CONFIG_ARM64_PAN */
--
2.11.0
^ permalink raw reply related
* [PATCH 03/18] arm64: introduce sysreg_clear_set()
From: Mark Rutland @ 2018-05-14 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514094640.27569-1-mark.rutland@arm.com>
Currently we have a couple of helpers to manipulate bits in particular
sysregs:
* config_sctlr_el1(u32 clear, u32 set)
* change_cpacr(u64 val, u64 mask)
The parameters of these differ in naming convention, order, and size,
which is unfortunate. They also differ slightly in behaviour, as
change_cpacr() skips the sysreg write if the bits are unchanged, which
is a useful optimization when sysreg writes are expensive.
Before we gain more yet another sysreg manipulation function, let's
unify these with a common helper, providing a consistent order for
clear/set operands, and the write skipping behaviour from
change_cpacr(). Code will be migrated to the new helper in subsequent
patches.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/sysreg.h | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index bd1d1194a5e7..b52762769329 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -729,6 +729,17 @@ asm(
asm volatile("msr_s " __stringify(r) ", %x0" : : "rZ" (__val)); \
} while (0)
+/*
+ * Modify bits in a sysreg. Bits in the clear mask are zeroed, then bits in the
+ * set mask are set. Other bits are left as-is.
+ */
+#define sysreg_clear_set(sysreg, clear, set) do { \
+ u64 __scs_val = read_sysreg(sysreg); \
+ u64 __scs_new = (__scs_val & ~(u64)(clear)) | (set); \
+ if (__scs_new != __scs_val) \
+ write_sysreg(__scs_new, sysreg); \
+} while (0)
+
static inline void config_sctlr_el1(u32 clear, u32 set)
{
u32 val;
--
2.11.0
^ permalink raw reply related
* [PATCH 02/18] arm64: move SCTLR_EL{1,2} assertions to <asm/sysreg.h>
From: Mark Rutland @ 2018-05-14 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514094640.27569-1-mark.rutland@arm.com>
Currently we assert that the SCTLR_EL{1,2}_{SET,CLEAR} bits are
self-consistent with an assertion in config_sctlr_el1(). This is a bit
unusual, since config_sctlr_el1() doesn't make use of these definitions,
and is far away from the definitions themselves.
We can use the CPP #error directive to have equivalent assertions in
<asm/sysreg.h>, next to the definitions of the set/clear bits, which is
a bit clearer and simpler.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
arch/arm64/include/asm/sysreg.h | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 6171178075dc..bd1d1194a5e7 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -452,9 +452,9 @@
SCTLR_ELx_SA | SCTLR_ELx_I | SCTLR_ELx_WXN | \
ENDIAN_CLEAR_EL2 | SCTLR_EL2_RES0)
-/* Check all the bits are accounted for */
-#define SCTLR_EL2_BUILD_BUG_ON_MISSING_BITS BUILD_BUG_ON((SCTLR_EL2_SET ^ SCTLR_EL2_CLEAR) != ~0)
-
+#if (SCTLR_EL2_SET ^ SCTLR_EL2_CLEAR) != 0xffffffff
+#error "Inconsistent SCTLR_EL2 set/clear bits"
+#endif
/* SCTLR_EL1 specific flags. */
#define SCTLR_EL1_UCI (1 << 26)
@@ -492,8 +492,9 @@
SCTLR_EL1_UMA | SCTLR_ELx_WXN | ENDIAN_CLEAR_EL1 |\
SCTLR_EL1_RES0)
-/* Check all the bits are accounted for */
-#define SCTLR_EL1_BUILD_BUG_ON_MISSING_BITS BUILD_BUG_ON((SCTLR_EL1_SET ^ SCTLR_EL1_CLEAR) != ~0)
+#if (SCTLR_EL1_SET ^ SCTLR_EL1_CLEAR) != 0xffffffff
+#error "Inconsistent SCTLR_EL1 set/clear bits"
+#endif
/* id_aa64isar0 */
#define ID_AA64ISAR0_TS_SHIFT 52
@@ -732,9 +733,6 @@ static inline void config_sctlr_el1(u32 clear, u32 set)
{
u32 val;
- SCTLR_EL2_BUILD_BUG_ON_MISSING_BITS;
- SCTLR_EL1_BUILD_BUG_ON_MISSING_BITS;
-
val = read_sysreg(sctlr_el1);
val &= ~clear;
val |= set;
--
2.11.0
^ permalink raw reply related
* [PATCH 01/18] arm64: consistently use unsigned long for thread flags
From: Mark Rutland @ 2018-05-14 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514094640.27569-1-mark.rutland@arm.com>
In do_notify_resume, we manipulate thread_flags as a 32-bit unsigned
int, whereas thread_info::flags is a 64-bit unsigned long, and elsewhere
(e.g. in the entry assembly) we manipulate the flags as a 64-bit
quantity.
For consistency, and to avoid problems if we end up with more than 32
flags, let's make do_notify_resume take the flags as a 64-bit unsigned
long.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
arch/arm64/kernel/signal.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 154b7d30145d..8e624fec4707 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -896,7 +896,7 @@ static void do_signal(struct pt_regs *regs)
}
asmlinkage void do_notify_resume(struct pt_regs *regs,
- unsigned int thread_flags)
+ unsigned long thread_flags)
{
/*
* The assembly code enters us with IRQs off, but it hasn't
--
2.11.0
^ permalink raw reply related
* [PATCH 00/18] arm64: invoke syscalls with pt_regs
From: Mark Rutland @ 2018-05-14 9:46 UTC (permalink / raw)
To: linux-arm-kernel
This series reworks arm64's syscall handling to minimize the propagation
of user-controlled register values into speculated code paths. As with
x86 [1], a wrapper is generated for each syscall, which extracts the
argument from a struct pt_regs. During kernel entry from userspace,
registers are zeroed.
The arm64 kernel code directly invokes some syscalls which the x86 code
doesn't, so I've added ksys_* wrappers for these, following the x86
example. The rest of the series is arm64-specific.
I've pushed the series out to my arm64/syscall-regs branch [2] on
kernel.org.
Thanks,
Mark.
[1] https://lkml.kernel.org/r/20180330093720.6780-1-linux at dominikbrodowski.net
[2] git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git
Mark Rutland (18):
arm64: consistently use unsigned long for thread flags
arm64: move SCTLR_EL{1,2} assertions to <asm/sysreg.h>
arm64: introduce sysreg_clear_set()
arm64: kill config_sctlr_el1()
arm64: kill change_cpacr()
arm64: move sve_user_{enable,disable} to <asm/fpsimd.h>
arm64: remove sigreturn wrappers
arm64: convert raw syscall invocation to C
arm64: convert syscall trace logic to C
arm64: convert native/compat syscall entry to C
arm64: zero GPRs upon entry from EL0
kernel: add ksys_personality()
kernel: add kcompat_sys_{f,}statfs64()
arm64: remove in-kernel call to sys_personality()
arm64: use {COMPAT,}SYSCALL_DEFINE0 for sigreturn
arm64: use SYSCALL_DEFINE6() for mmap
arm64: convert compat wrappers to C
arm64: implement syscall wrappers
arch/arm64/Kconfig | 1 +
arch/arm64/include/asm/fpsimd.h | 17 ++++-
arch/arm64/include/asm/syscall_wrapper.h | 80 ++++++++++++++++++++
arch/arm64/include/asm/sysreg.h | 33 ++++----
arch/arm64/include/asm/unistd32.h | 26 +++----
arch/arm64/kernel/Makefile | 5 +-
arch/arm64/kernel/armv8_deprecated.c | 8 +-
arch/arm64/kernel/cpu_errata.c | 3 +-
arch/arm64/kernel/entry.S | 126 +++----------------------------
arch/arm64/kernel/entry32.S | 121 -----------------------------
arch/arm64/kernel/fpsimd.c | 20 -----
arch/arm64/kernel/signal.c | 5 +-
arch/arm64/kernel/signal32.c | 6 +-
arch/arm64/kernel/sys.c | 19 +++--
arch/arm64/kernel/sys32.c | 116 ++++++++++++++++++++++++----
arch/arm64/kernel/syscall.c | 113 +++++++++++++++++++++++++++
arch/arm64/kernel/traps.c | 4 +-
arch/arm64/mm/fault.c | 2 +-
fs/statfs.c | 14 +++-
include/linux/syscalls.h | 9 +++
kernel/exec_domain.c | 7 +-
21 files changed, 411 insertions(+), 324 deletions(-)
create mode 100644 arch/arm64/include/asm/syscall_wrapper.h
delete mode 100644 arch/arm64/kernel/entry32.S
create mode 100644 arch/arm64/kernel/syscall.c
--
2.11.0
^ permalink raw reply
* [PATCH v2 04/13] soc: rockchip: power-domain: Fix wrong value when power up pd
From: Heiko Stuebner @ 2018-05-14 9:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526268578-9361-1-git-send-email-zhangqing@rock-chips.com>
Hi Elaine,
Am Montag, 14. Mai 2018, 05:29:38 CEST schrieb Elaine Zhang:
> From: Finley Xiao <finley.xiao@rock-chips.com>
>
> Solve the pd could only ever turn off but never turn them on again,
> If the pd registers have the writemask bits.
>
> Fix up the code error for commit:
> commit 79bb17ce8edb3141339b5882e372d0ec7346217c
> Author: Elaine Zhang <zhangqing@rock-chips.com>
> Date: Fri Dec 23 11:47:52 2016 +0800
>
> soc: rockchip: power-domain: Support domain control in hiword-registers
>
> New Rockchips SoCs may have their power-domain control in registers
> using a writemask-based access scheme (upper 16bit being the write
> mask). So add a DOMAIN_M type and handle this case accordingly.
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
>
> Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
As Gregs automated mail noted, the stable-notice needed some changes.
I've done these changes and applied the result for 4.18.
When you look at [0] you'll see the two lines "Fixes:..." and "Cc:..."
in the commit message. Greg then has automated scripts running that
extract so marked patches from Linus' tree and queue them for possible
stable-inclusion.
[The other patches need to wait a bit to give Rob a chance to Ack them]
Heiko
[0] https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git/commit/?id=ed726894761c056b3513ce15915af74ce5d7d57b
^ permalink raw reply
* Allwinner A64: Issue on external rtc clock to wifi chip
From: Jagan Teki @ 2018-05-14 9:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514090618.r5xc3elzpvfp47f4@flea>
On Mon, May 14, 2018 at 2:36 PM, Maxime Ripard
<maxime.ripard@bootlin.com> wrote:
> On Mon, May 14, 2018 at 02:34:22PM +0530, Jagan Teki wrote:
>> On Mon, May 14, 2018 at 1:57 PM, Maxime Ripard
>> <maxime.ripard@bootlin.com> wrote:
>> > On Mon, May 14, 2018 at 01:34:56PM +0530, Jagan Teki wrote:
>> >> On Mon, May 14, 2018 at 1:27 PM, Maxime Ripard
>> >> <maxime.ripard@bootlin.com> wrote:
>> >> > Hi,
>> >> >
>> >> > On Mon, May 14, 2018 at 12:37:49PM +0530, Jagan Teki wrote:
>> >> >> Hi Maxime and All,
>> >> >>
>> >> >> We are trying to bring-up AP6330 Wifi chip for A64 board. We noticed
>> >> >> to have an external rtc clock has driven from wifi chip.
>> >> >>
>> >> >> So the devicetree is configured according to this as below.
>> >> >>
>> >> >> / {
>> >> >> wifi_pwrseq: wifi-pwrseq {
>> >> >> compatible = "mmc-pwrseq-simple";
>> >> >> clocks = <&rtc 1>;
>> >> >> clock-names = "ext_clock";
>> >> >> reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
>> >> >> post-power-on-delay-ms = <400>;
>> >> >> };
>> >> >> };
>> >> >>
>> >> >> &rtc {
>> >> >> clock-output-names = "rtc-osc32k", "rtc-osc32k-out";
>> >> >> clocks = <&osc32k>;
>> >> >> #clock-cells = <1>;
>> >> >> };
>> >> >>
>> >> >> &mmc1 {
>> >> >> pinctrl-names = "default";
>> >> >> pinctrl-0 = <&mmc1_pins>;
>> >> >> vmmc-supply = <®_dcdc1>;
>> >> >> vqmmc-supply = <®_eldo1>;
>> >> >> mmc-pwrseq = <&wifi_pwrseq>;
>> >> >> bus-width = <4>;
>> >> >> non-removable;
>> >> >> status = "okay";
>> >> >>
>> >> >> brcmf: wifi at 1 {
>> >> >> reg = <1>;
>> >> >> compatible = "brcm,bcm4329-fmac";
>> >> >> interrupt-parent = <&r_pio>;
>> >> >> interrupts = <0 3 IRQ_TYPE_LEVEL_LOW>; /* WL-WAKE-AP: PL3 */
>> >> >> interrupt-names = "host-wake";
>> >> >> };
>> >> >> };
>> >> >>
>> >> >> And observed rtc-osc32k-out clock is never enabled[1] and the value of
>> >> >> LOSC_OUT_GATING is 0x0 which eventually not enabling
>> >> >> LOSC_OUT_GATING_EN
>> >> >>
>> >> >> Pls. let us know if we miss anything here?
>> >> >>
>> >> >> [1] https://paste.ubuntu.com/p/X2By4q8kD2/
>> >> >
>> >> > Could you paste your config and the logs from a boot to?
>> >>
>> >> .config
>> >> https://paste.ubuntu.com/p/w9w2KB7RFc/
>> >>
>> >> dmesg
>> >> https://paste.ubuntu.com/p/mrZGk5bWRR/
>> >
>> > This is kind of weird. Have you tested with a 4.17 kernel? We have
>> > runtime_pm changes lined up in next, so that might be a regression
>> > there, even though we tested it with Quentin at some point.
>>
>> This is 4.17-rc4 do you want to try it on 4.16 ?
>
> No, this is next-20180503. Please try with 4.17-rc4
Couldn't find any different in behaviour [2]
[2] https://paste.ubuntu.com/p/m3PGBwrv6W/
^ permalink raw reply
* [GIT PULL 3/3] omap sdhci dts changes for v4.18 merge window
From: Ulf Hansson @ 2018-05-14 9:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514082224.dx63ao3vz3ay5ng5@localhost>
On 14 May 2018 at 10:22, Olof Johansson <olof@lixom.net> wrote:
> On Fri, May 04, 2018 at 09:17:33AM -0700, Tony Lindgren wrote:
>> From: "Tony Lindgren" <tony@atomide.com>
>>
>> The following changes since commit 3f4028780287ff5a7308f40e10bbba9a42b993aa:
>>
>> mmc: sdhci-omap: Get IODelay values for 3.3v DDR mode (2018-05-03 09:37:13 +0200)
>>
>> are available in the Git repository at:
>>
>> git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v4.18/dt-sdhci-signed
>>
>> for you to fetch changes up to 24a6f1f65ea567d017c598faf1374ee443f73851:
>>
>> Documentation: ARM: Add new MMC requirements for DRA7/K2G (2018-05-03 10:32:20 -0700)
>>
>> ----------------------------------------------------------------
>> Device tree changes for omap variants for SDHCI
>>
>> This series adds the devicetree configuration needed for pinctrl on
>> dra7 variants to use the SDHCI SDIO driver instead of mmc-omap-hs
>> driver. To use SDHCI, both the pins and the iodelay needs to be
>> configured.
>>
>> This series is based on the related SDHCI drivers changes on a branch
>> set up by Ulf.
>
> Hi Tony,
>
> Just to make sure Ulf isn't taken by surprise (since I didn't see the initial
> agreement of a stable branch), it's a good idea to include him on the pull
> request.
No surprise.
>
> Also, the diffstat doesn't take that branch into consideration so it doesn't
> match with what I've merged with. Having the URL of Ulf's branch helps, in that
> case I'd just merge that branch first and get the dependency documented.
>
>
> Ulf, does the above sound OK with you, and said branch is 100% guaranteed to
> not be rebased?
Right, the branch is immutable. Feel free to pull it.
git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git sdhci_omap
Or if you prefer a signed tag: sdhci-omap-v4.17-rc3
Kind regards
Uffe
^ permalink raw reply
* [PATCH 2/2] arm64: Clear the stack
From: Alexander Popov @ 2018-05-14 9:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514051555.bpbydgr56hyffjch@salmiak>
On 14.05.2018 08:15, Mark Rutland wrote:
> On Sun, May 13, 2018 at 11:40:07AM +0300, Alexander Popov wrote:
>> It seems that previously I was very "lucky" to accidentally have those MIN_STACK_LEFT,
>> call trace depth and oops=panic together to experience a hang on stack overflow
>> during BUG().
>>
>>
>> When I run my test in a loop _without_ VMAP_STACK, I manage to corrupt the neighbour
>> processes with BUG() handling overstepping the stack boundary. It's a pity, but
>> I have an idea.
>
> I think that in the absence of VMAP_STACK, there will always be cases where we
> *could* corrupt a neighbouring stack, but I agree that trying to minimize that
> possibility would be good.
Ok!
>> In kernel/sched/core.c we already have:
>>
>> #ifdef CONFIG_SCHED_STACK_END_CHECK
>> if (task_stack_end_corrupted(prev))
>> panic("corrupted stack end detected inside scheduler\n");
>> #endif
>>
>> So what would you think if I do the following in check_alloca():
>>
>> if (size >= stack_left) {
>> #if !defined(CONFIG_VMAP_STACK) && defined(CONFIG_SCHED_STACK_END_CHECK)
>> panic("alloca over the kernel stack boundary\n");
>> #else
>> BUG();
>> #endif
>
> Given this is already out-of-line, how about we always use panic(), regardless
> of VMAP_STACK and SCHED_STACK_END_CHECK? i.e. just
>
> if (unlikely(size >= stack_left))
> panic("alloca over the kernel stack boundary");
>
> If we have VMAP_STACK selected, and overflow during the panic, it's the same as
> if we overflowed during the BUG(). It's likely that panic() will use less stack
> space than BUG(), and the compiler can put the call in a slow path that
> shouldn't affect most calls, so in all cases it's likely preferable.
I'm sure that maintainers and Linus will strongly dislike my patch if I always
use panic() here. panic() kills the whole kernel and we shouldn't use it when we
can safely continue to work.
Let me describe my logic. So let's have size >= stack_left on a thread stack.
1. If CONFIG_VMAP_STACK is enabled, we can safely use BUG(). Even if BUG()
handling overflows the thread stack into the guard page, handle_stack_overflow()
is called and the neighbour memory is not corrupted. The kernel can proceed to live.
2. If CONFIG_VMAP_STACK is disabled, BUG() handling can corrupt the neighbour
kernel memory and cause the undefined behaviour of the whole kernel. I see it on
my lkdtm test. That is a cogent reason for panic().
2.a. If CONFIG_SCHED_STACK_END_CHECK is enabled, the kernel already does panic()
when STACK_END_MAGIC is corrupted. So we will _not_ break the safety policy if
we do panic() in a similar situation in check_alloca().
2.b. If CONFIG_SCHED_STACK_END_CHECK is disabled, the user has some real reasons
not to do panic() when the kernel stack is corrupted. So we should not do it in
check_alloca() as well, just use BUG() and hope for the best.
That logic can be expressed this way:
if (size >= stack_left) {
#if !defined(CONFIG_VMAP_STACK) && defined(CONFIG_SCHED_STACK_END_CHECK)
panic("alloca over the kernel stack boundary\n");
#else
BUG();
#endif
I think I should add a proper comment to describe it.
Thank you.
Best regards,
Alexander
^ permalink raw reply
* [PATCH net-next v2 02/13] net: phy: sfp: handle non-wired SFP connectors
From: Antoine Tenart @ 2018-05-14 9:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180508115247.GF16141@n2100.armlinux.org.uk>
Hi Russell,
On Tue, May 08, 2018 at 12:52:47PM +0100, Russell King - ARM Linux wrote:
> On Fri, May 04, 2018 at 03:56:32PM +0200, Antoine Tenart wrote:
> > SFP connectors can be solder on a board without having any of their pins
> > (LOS, i2c...) wired. In such cases the SFP link state cannot be guessed,
> > and the overall link status reporting is left to other layers.
> >
> > In order to achieve this, a new SFP_DEV status is added, named UNKNOWN.
> > This mode is set when it is not possible for the SFP code to get the
> > link status and as a result the link status is reported to be always UP
> > from the SFP point of view.
>
> This looks weird to me. SFP_DEV_* states track the netdevice up/down
> state and have little to do with whether LOS or MODDEF0 are implemented.
That's right.
> I think it would be better to have a new SFP_MOD_* and to force
> sm_mod_state to that in this circumstance.
The idea was to avoid depending on the state machine, as this could be
difficult to maintain in the future (it's hard to tell exactly what are
all the possible paths). But I get your point about SFP_DEV_.
I can have a look at adding a new SFP_MOD_, or I could add a broken flag
into 'struct sfp', although having a SFP_MOD_ would be proper.
Before doing so, we should decide whether or not this approach is valid,
as there were comments from Florian and Andrew asking for a fixed-link
solution. I think fixed-link wouldn't be perfect from the user point of
view, but I understand the point. If we go with fixed-link, then this
patch can be dropped (the two others net: sfp: patches could be kept).
What do you think?
Thanks,
Antoine
--
Antoine T?nart, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* [PATCH v2] tty: pl011: Avoid spuriously stuck-off interrupts
From: Wei Xu @ 2018-05-14 9:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1525972103-26691-1-git-send-email-Dave.Martin@arm.com>
Hi Dave,
On 2018/5/10 18:08, Dave Martin wrote:
> Commit 9b96fbacda34 ("serial: PL011: clear pending interrupts")
> clears the RX and receive timeout interrupts on pl011 startup, to
> avoid a screaming-interrupt scenario that can occur when the
> firmware or bootloader leaves these interrupts asserted.
>
> This has been noted as an issue when running Linux on qemu [1].
>
> Unfortunately, the above fix seems to lead to potential
> misbehaviour if the RX FIFO interrupt is asserted _non_ spuriously
> on driver startup, if the RX FIFO is also already full to the
> trigger level.
>
> Clearing the RX FIFO interrupt does not change the FIFO fill level.
> In this scenario, because the interrupt is now clear and because
> the FIFO is already full to the trigger level, no new assertion of
> the RX FIFO interrupt can occur unless the FIFO is drained back
> below the trigger level. This never occurs because the pl011
> driver is waiting for an RX FIFO interrupt to tell it that there is
> something to read, and does not read the FIFO at all until that
> interrupt occurs.
>
> Thus, simply clearing "spurious" interrupts on startup may be
> misguided, since there is no way to be sure that the interrupts are
> truly spurious, and things can go wrong if they are not.
>
> This patch instead clears the interrupt condition by draining the
> RX FIFO during UART startup, after clearing any potentially
> spurious interrupt. This should ensure that an interrupt will
> definitely be asserted if the RX FIFO subsequently becomes
> sufficiently full.
>
> The drain is done at the point of enabling interrupts only. This
> means that it will occur any time the UART is newly opened through
> the tty layer. It will not apply to polled-mode use of the UART by
> kgdboc: since that scenario cannot use interrupts by design, this
> should not matter. kgdboc will interact badly with "normal" use of
> the UART in any case: this patch makes no attempt to paper over
> such issues.
>
> This patch does not attempt to address the case where the RX FIFO
> fills faster than it can be drained: that is a pathological
> hardware design problem that is beyond the scope of the driver to
> work around. As a failsafe, the number of poll iterations for
> draining the FIFO is limited to twice the FIFO size. This will
> ensure that the kernel at least boots even if it is impossible to
> drain the FIFO for some reason.
>
> [1] [Qemu-devel] [Qemu-arm] [PATCH] pl011: do not put into fifo
> before enabled the interruption
> https://lists.gnu.org/archive/html/qemu-devel/2018-01/msg06446.html
>
> Reported-by: Wei Xu <xuwei5@hisilicon.com>
> Cc: Russell King <linux@armlinux.org.uk>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Peter Maydell <peter.maydell@linaro.org>
> Fixes: 9b96fbacda34 ("serial: PL011: clear pending interrupts")
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Thanks!
Tested on hisilicon D05 board.
Tested-by: Wei Xu <xuwei5@hisilicon.com>
Best Regards,
Wei
>
> ---
>
> Changes since v1 [1]
>
> * Deleted Andrew Jones' Reviewed/Tested-bys due to the following
> change.
>
> If you can please retest that the updated patch fixes your
> issue that would be appreciated.
>
> Suggested by Russell King:
>
> * Only drain 2 * FIFO size, to avoid going into an infinite spin
> if something does wrong. If the FIFO still couldn't be drained
> sufficiently then pl011 RX won't work properly, but the kernel
> will at least boot.
>
>
> [1] [PATCH] tty: pl011: Avoid spuriously stuck-off interrupts
> http://lists.infradead.org/pipermail/linux-arm-kernel/2018-April/574362.html
>
> ---
> drivers/tty/serial/amba-pl011.c | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
> index 4b40a5b..ebd33c0 100644
> --- a/drivers/tty/serial/amba-pl011.c
> +++ b/drivers/tty/serial/amba-pl011.c
> @@ -1727,10 +1727,26 @@ static int pl011_allocate_irq(struct uart_amba_port *uap)
> */
> static void pl011_enable_interrupts(struct uart_amba_port *uap)
> {
> + unsigned int i;
> +
> spin_lock_irq(&uap->port.lock);
>
> /* Clear out any spuriously appearing RX interrupts */
> pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR);
> +
> + /*
> + * RXIS is asserted only when the RX FIFO transitions from below
> + * to above the trigger threshold. If the RX FIFO is already
> + * full to the threshold this can't happen and RXIS will now be
> + * stuck off. Drain the RX FIFO explicitly to fix this:
> + */
> + for (i = 0; i < uap->fifosize * 2; ++i) {
> + if (pl011_read(uap, REG_FR) & UART01x_FR_RXFE)
> + break;
> +
> + pl011_read(uap, REG_DR);
> + }
> +
> uap->im = UART011_RTIM;
> if (!pl011_dma_rx_running(uap))
> uap->im |= UART011_RXIM;
>
^ permalink raw reply
* [PATCH 1/3] thermal: imx: remove cpufreq cooling registration
From: Bastian Stender @ 2018-05-14 9:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AM3PR04MB1315B6320421800346313075F59C0@AM3PR04MB1315.eurprd04.prod.outlook.com>
On 05/14/2018 11:10 AM, Anson Huang wrote:
>> -----Original Message-----
>> From: Bastian Stender [mailto:bst at pengutronix.de]
>> Sent: Monday, May 14, 2018 4:37 PM
>> To: Anson Huang <anson.huang@nxp.com>; shawnguo at kernel.org;
>> s.hauer at pengutronix.de; kernel at pengutronix.de; Fabio Estevam
>> <fabio.estevam@nxp.com>; robh+dt at kernel.org; mark.rutland at arm.com;
>> rjw at rjwysocki.net; viresh.kumar at linaro.org; rui.zhang at intel.com;
>> edubezval at gmail.com
>> Cc: devicetree at vger.kernel.org; linux-pm at vger.kernel.org; dl-linux-imx
>> <linux-imx@nxp.com>; linux-arm-kernel at lists.infradead.org;
>> linux-kernel at vger.kernel.org
>> Subject: Re: [PATCH 1/3] thermal: imx: remove cpufreq cooling registration
>>
>> Hi,
>>
>> On 05/14/2018 10:09 AM, Anson Huang wrote:
>>> This patch removes cpufreq cooling registration in thermal .probe
>>> function, cpufreq cooling should be done in cpufreq driver when it is
>>> ready.
>>>
>>> Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
>>
>> It seems you are trying to achieve something similar to a patch I sent a couple
>> of month ago. Unfortunately I did not have the time to rework it yet:
>>
>>
>> https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatch
>> work.kernel.org%2Fpatch%2F10059085%2F&data=02%7C01%7Canson.huang
>> %40nxp.com%7C179da3635cab4a14deef08d5b975ecb6%7C686ea1d3bc2b4c6f
>> a92cd99c5c301635%7C0%7C0%7C636618838508978629&sdata=BcQ9tc%2BE
>> CZ%2Fk4AsZFxshgmvSsPg7eRN0ASzP8LO8yBI%3D&reserved=0
>>
>> Some of the comments might apply here too.
>
> Ah, I did NOT notice this thread, so how to proceed, will you
> continue to finish your patch? If yes, then you can just ignore/skip
> my patch, thanks.
Yes, I will revisit the patch in a couple of weeks. It would be nice to
get your feedback then.
Regards,
Bastian
--
Pengutronix e.K.
Industrial Linux Solutions
http://www.pengutronix.de/
Peiner Str. 6-8, 31137 Hildesheim, Germany
Amtsgericht Hildesheim, HRA 2686
^ permalink raw reply
* [PATCH 1/3] thermal: imx: remove cpufreq cooling registration
From: Anson Huang @ 2018-05-14 9:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5a449fc0-4d3e-c7c7-0e9a-43efb4b909cf@pengutronix.de>
Anson Huang
Best Regards!
> -----Original Message-----
> From: Bastian Stender [mailto:bst at pengutronix.de]
> Sent: Monday, May 14, 2018 4:37 PM
> To: Anson Huang <anson.huang@nxp.com>; shawnguo at kernel.org;
> s.hauer at pengutronix.de; kernel at pengutronix.de; Fabio Estevam
> <fabio.estevam@nxp.com>; robh+dt at kernel.org; mark.rutland at arm.com;
> rjw at rjwysocki.net; viresh.kumar at linaro.org; rui.zhang at intel.com;
> edubezval at gmail.com
> Cc: devicetree at vger.kernel.org; linux-pm at vger.kernel.org; dl-linux-imx
> <linux-imx@nxp.com>; linux-arm-kernel at lists.infradead.org;
> linux-kernel at vger.kernel.org
> Subject: Re: [PATCH 1/3] thermal: imx: remove cpufreq cooling registration
>
> Hi,
>
> On 05/14/2018 10:09 AM, Anson Huang wrote:
> > This patch removes cpufreq cooling registration in thermal .probe
> > function, cpufreq cooling should be done in cpufreq driver when it is
> > ready.
> >
> > Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
>
> It seems you are trying to achieve something similar to a patch I sent a couple
> of month ago. Unfortunately I did not have the time to rework it yet:
>
>
> https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatch
> work.kernel.org%2Fpatch%2F10059085%2F&data=02%7C01%7Canson.huang
> %40nxp.com%7C179da3635cab4a14deef08d5b975ecb6%7C686ea1d3bc2b4c6f
> a92cd99c5c301635%7C0%7C0%7C636618838508978629&sdata=BcQ9tc%2BE
> CZ%2Fk4AsZFxshgmvSsPg7eRN0ASzP8LO8yBI%3D&reserved=0
>
> Some of the comments might apply here too.
Ah, I did NOT notice this thread, so how to proceed, will you continue to finish your patch?
If yes, then you can just ignore/skip my patch, thanks.
Anson.
>
> Regards,
> Bastian
>
> > ---
> > drivers/thermal/imx_thermal.c | 16 ----------------
> > 1 file changed, 16 deletions(-)
> >
> > diff --git a/drivers/thermal/imx_thermal.c
> > b/drivers/thermal/imx_thermal.c index c30dc21..8eedb97 100644
> > --- a/drivers/thermal/imx_thermal.c
> > +++ b/drivers/thermal/imx_thermal.c
> > @@ -9,7 +9,6 @@
> >
> > #include <linux/clk.h>
> > #include <linux/cpufreq.h>
> > -#include <linux/cpu_cooling.h>
> > #include <linux/delay.h>
> > #include <linux/device.h>
> > #include <linux/init.h>
> > @@ -207,7 +206,6 @@ static struct thermal_soc_data thermal_imx7d_data
> = {
> > struct imx_thermal_data {
> > struct cpufreq_policy *policy;
> > struct thermal_zone_device *tz;
> > - struct thermal_cooling_device *cdev;
> > enum thermal_device_mode mode;
> > struct regmap *tempmon;
> > u32 c1, c2; /* See formula in imx_init_calib() */ @@ -729,22
> > +727,12 @@ static int imx_thermal_probe(struct platform_device *pdev)
> > return -EPROBE_DEFER;
> > }
> >
> > - data->cdev = cpufreq_cooling_register(data->policy);
> > - if (IS_ERR(data->cdev)) {
> > - ret = PTR_ERR(data->cdev);
> > - dev_err(&pdev->dev,
> > - "failed to register cpufreq cooling device: %d\n", ret);
> > - cpufreq_cpu_put(data->policy);
> > - return ret;
> > - }
> > -
> > data->thermal_clk = devm_clk_get(&pdev->dev, NULL);
> > if (IS_ERR(data->thermal_clk)) {
> > ret = PTR_ERR(data->thermal_clk);
> > if (ret != -EPROBE_DEFER)
> > dev_err(&pdev->dev,
> > "failed to get thermal clk: %d\n", ret);
> > - cpufreq_cooling_unregister(data->cdev);
> > cpufreq_cpu_put(data->policy);
> > return ret;
> > }
> > @@ -759,7 +747,6 @@ static int imx_thermal_probe(struct platform_device
> *pdev)
> > ret = clk_prepare_enable(data->thermal_clk);
> > if (ret) {
> > dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
> > - cpufreq_cooling_unregister(data->cdev);
> > cpufreq_cpu_put(data->policy);
> > return ret;
> > }
> > @@ -775,7 +762,6 @@ static int imx_thermal_probe(struct platform_device
> *pdev)
> > dev_err(&pdev->dev,
> > "failed to register thermal zone device %d\n", ret);
> > clk_disable_unprepare(data->thermal_clk);
> > - cpufreq_cooling_unregister(data->cdev);
> > cpufreq_cpu_put(data->policy);
> > return ret;
> > }
> > @@ -811,7 +797,6 @@ static int imx_thermal_probe(struct platform_device
> *pdev)
> > dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
> > clk_disable_unprepare(data->thermal_clk);
> > thermal_zone_device_unregister(data->tz);
> > - cpufreq_cooling_unregister(data->cdev);
> > cpufreq_cpu_put(data->policy);
> > return ret;
> > }
> > @@ -831,7 +816,6 @@ static int imx_thermal_remove(struct
> platform_device *pdev)
> > clk_disable_unprepare(data->thermal_clk);
> >
> > thermal_zone_device_unregister(data->tz);
> > - cpufreq_cooling_unregister(data->cdev);
> > cpufreq_cpu_put(data->policy);
> >
> > return 0;
> >
>
> --
> Pengutronix e.K.
> Industrial Linux Solutions
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.
> pengutronix.de%2F&data=02%7C01%7Canson.huang%40nxp.com%7C179da36
> 35cab4a14deef08d5b975ecb6%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0
> %7C0%7C636618838508978629&sdata=kHHjnbmj2kV0aPlAvULXUh%2Fm%2Fp
> gbu21luMQ6jfIUgLo%3D&reserved=0
> Peiner Str. 6-8, 31137 Hildesheim, Germany Amtsgericht Hildesheim, HRA 2686
^ permalink raw reply
* Allwinner A64: Issue on external rtc clock to wifi chip
From: Maxime Ripard @ 2018-05-14 9:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAMty3ZC3ggxkZwirpQ-aRP8Udg=aYypBArb0KcR0_Z0AG8wATA@mail.gmail.com>
On Mon, May 14, 2018 at 02:34:22PM +0530, Jagan Teki wrote:
> On Mon, May 14, 2018 at 1:57 PM, Maxime Ripard
> <maxime.ripard@bootlin.com> wrote:
> > On Mon, May 14, 2018 at 01:34:56PM +0530, Jagan Teki wrote:
> >> On Mon, May 14, 2018 at 1:27 PM, Maxime Ripard
> >> <maxime.ripard@bootlin.com> wrote:
> >> > Hi,
> >> >
> >> > On Mon, May 14, 2018 at 12:37:49PM +0530, Jagan Teki wrote:
> >> >> Hi Maxime and All,
> >> >>
> >> >> We are trying to bring-up AP6330 Wifi chip for A64 board. We noticed
> >> >> to have an external rtc clock has driven from wifi chip.
> >> >>
> >> >> So the devicetree is configured according to this as below.
> >> >>
> >> >> / {
> >> >> wifi_pwrseq: wifi-pwrseq {
> >> >> compatible = "mmc-pwrseq-simple";
> >> >> clocks = <&rtc 1>;
> >> >> clock-names = "ext_clock";
> >> >> reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
> >> >> post-power-on-delay-ms = <400>;
> >> >> };
> >> >> };
> >> >>
> >> >> &rtc {
> >> >> clock-output-names = "rtc-osc32k", "rtc-osc32k-out";
> >> >> clocks = <&osc32k>;
> >> >> #clock-cells = <1>;
> >> >> };
> >> >>
> >> >> &mmc1 {
> >> >> pinctrl-names = "default";
> >> >> pinctrl-0 = <&mmc1_pins>;
> >> >> vmmc-supply = <®_dcdc1>;
> >> >> vqmmc-supply = <®_eldo1>;
> >> >> mmc-pwrseq = <&wifi_pwrseq>;
> >> >> bus-width = <4>;
> >> >> non-removable;
> >> >> status = "okay";
> >> >>
> >> >> brcmf: wifi at 1 {
> >> >> reg = <1>;
> >> >> compatible = "brcm,bcm4329-fmac";
> >> >> interrupt-parent = <&r_pio>;
> >> >> interrupts = <0 3 IRQ_TYPE_LEVEL_LOW>; /* WL-WAKE-AP: PL3 */
> >> >> interrupt-names = "host-wake";
> >> >> };
> >> >> };
> >> >>
> >> >> And observed rtc-osc32k-out clock is never enabled[1] and the value of
> >> >> LOSC_OUT_GATING is 0x0 which eventually not enabling
> >> >> LOSC_OUT_GATING_EN
> >> >>
> >> >> Pls. let us know if we miss anything here?
> >> >>
> >> >> [1] https://paste.ubuntu.com/p/X2By4q8kD2/
> >> >
> >> > Could you paste your config and the logs from a boot to?
> >>
> >> .config
> >> https://paste.ubuntu.com/p/w9w2KB7RFc/
> >>
> >> dmesg
> >> https://paste.ubuntu.com/p/mrZGk5bWRR/
> >
> > This is kind of weird. Have you tested with a 4.17 kernel? We have
> > runtime_pm changes lined up in next, so that might be a regression
> > there, even though we tested it with Quentin at some point.
>
> This is 4.17-rc4 do you want to try it on 4.16 ?
No, this is next-20180503. Please try with 4.17-rc4
Maxime
--
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180514/4a2bdde5/attachment-0001.sig>
^ permalink raw reply
* Allwinner A64: Issue on external rtc clock to wifi chip
From: Jagan Teki @ 2018-05-14 9:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180514082744.ydmfg5mzsbol5onu@flea>
On Mon, May 14, 2018 at 1:57 PM, Maxime Ripard
<maxime.ripard@bootlin.com> wrote:
> On Mon, May 14, 2018 at 01:34:56PM +0530, Jagan Teki wrote:
>> On Mon, May 14, 2018 at 1:27 PM, Maxime Ripard
>> <maxime.ripard@bootlin.com> wrote:
>> > Hi,
>> >
>> > On Mon, May 14, 2018 at 12:37:49PM +0530, Jagan Teki wrote:
>> >> Hi Maxime and All,
>> >>
>> >> We are trying to bring-up AP6330 Wifi chip for A64 board. We noticed
>> >> to have an external rtc clock has driven from wifi chip.
>> >>
>> >> So the devicetree is configured according to this as below.
>> >>
>> >> / {
>> >> wifi_pwrseq: wifi-pwrseq {
>> >> compatible = "mmc-pwrseq-simple";
>> >> clocks = <&rtc 1>;
>> >> clock-names = "ext_clock";
>> >> reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
>> >> post-power-on-delay-ms = <400>;
>> >> };
>> >> };
>> >>
>> >> &rtc {
>> >> clock-output-names = "rtc-osc32k", "rtc-osc32k-out";
>> >> clocks = <&osc32k>;
>> >> #clock-cells = <1>;
>> >> };
>> >>
>> >> &mmc1 {
>> >> pinctrl-names = "default";
>> >> pinctrl-0 = <&mmc1_pins>;
>> >> vmmc-supply = <®_dcdc1>;
>> >> vqmmc-supply = <®_eldo1>;
>> >> mmc-pwrseq = <&wifi_pwrseq>;
>> >> bus-width = <4>;
>> >> non-removable;
>> >> status = "okay";
>> >>
>> >> brcmf: wifi at 1 {
>> >> reg = <1>;
>> >> compatible = "brcm,bcm4329-fmac";
>> >> interrupt-parent = <&r_pio>;
>> >> interrupts = <0 3 IRQ_TYPE_LEVEL_LOW>; /* WL-WAKE-AP: PL3 */
>> >> interrupt-names = "host-wake";
>> >> };
>> >> };
>> >>
>> >> And observed rtc-osc32k-out clock is never enabled[1] and the value of
>> >> LOSC_OUT_GATING is 0x0 which eventually not enabling
>> >> LOSC_OUT_GATING_EN
>> >>
>> >> Pls. let us know if we miss anything here?
>> >>
>> >> [1] https://paste.ubuntu.com/p/X2By4q8kD2/
>> >
>> > Could you paste your config and the logs from a boot to?
>>
>> .config
>> https://paste.ubuntu.com/p/w9w2KB7RFc/
>>
>> dmesg
>> https://paste.ubuntu.com/p/mrZGk5bWRR/
>
> This is kind of weird. Have you tested with a 4.17 kernel? We have
> runtime_pm changes lined up in next, so that might be a regression
> there, even though we tested it with Quentin at some point.
This is 4.17-rc4 do you want to try it on 4.16 ?
^ permalink raw reply
* [RFC PATCH 10/10] time: timekeeping: Remove time compensating from nonstop clocksources
From: Baolin Wang @ 2018-05-14 8:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1526285602.git.baolin.wang@linaro.org>
Since we have converted all nonstop clocksources to use persistent clock,
thus we can simplify the time compensating by removing the nonstop
clocksources. Now we can compensate the suspend time for the OS time from
the persistent clock or rtc device.
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
---
kernel/time/timekeeping.c | 19 ++++---------------
1 file changed, 4 insertions(+), 15 deletions(-)
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 49cbcee..48d2a80 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1666,7 +1666,6 @@ void timekeeping_inject_sleeptime64(struct timespec64 *delta)
void timekeeping_resume(void)
{
struct timekeeper *tk = &tk_core.timekeeper;
- struct clocksource *clock = tk->tkr_mono.clock;
unsigned long flags;
struct timespec64 ts_new, ts_delta;
u64 cycle_now;
@@ -1682,27 +1681,17 @@ void timekeeping_resume(void)
/*
* After system resumes, we need to calculate the suspended time and
- * compensate it for the OS time. There are 3 sources that could be
- * used: Nonstop clocksource during suspend, persistent clock and rtc
- * device.
+ * compensate it for the OS time. There are 2 sources that could be
+ * used: persistent clock and rtc device.
*
* One specific platform may have 1 or 2 or all of them, and the
* preference will be:
- * suspend-nonstop clocksource -> persistent clock -> rtc
+ * persistent clock -> rtc
* The less preferred source will only be tried if there is no better
* usable source. The rtc part is handled separately in rtc core code.
*/
cycle_now = tk_clock_read(&tk->tkr_mono);
- if ((clock->flags & CLOCK_SOURCE_SUSPEND_NONSTOP) &&
- cycle_now > tk->tkr_mono.cycle_last) {
- u64 nsec, cyc_delta;
-
- cyc_delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last,
- tk->tkr_mono.mask);
- nsec = mul_u64_u32_shr(cyc_delta, clock->mult, clock->shift);
- ts_delta = ns_to_timespec64(nsec);
- sleeptime_injected = true;
- } else if (timespec64_compare(&ts_new, &timekeeping_suspend_time) > 0) {
+ if (timespec64_compare(&ts_new, &timekeeping_suspend_time) > 0) {
ts_delta = timespec64_sub(ts_new, timekeeping_suspend_time);
sleeptime_injected = true;
}
--
1.7.9.5
^ permalink raw reply related
* [RFC PATCH 09/10] x86: tsc: Register the persistent clock
From: Baolin Wang @ 2018-05-14 8:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1526285602.git.baolin.wang@linaro.org>
Register the tsc as one persistent clock to compensate the suspend time
if the tsc clocksource is always available.
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
---
arch/x86/Kconfig | 1 +
arch/x86/kernel/tsc.c | 16 ++++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index c07f492..667e3a7 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -195,6 +195,7 @@ config X86
select USER_STACKTRACE_SUPPORT
select VIRT_TO_BUS
select X86_FEATURE_NAMES if PROC_FS
+ select PERSISTENT_CLOCK
config INSTRUCTION_DECODER
def_bool y
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 74392d9..dd8d7c3 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -11,6 +11,7 @@
#include <linux/delay.h>
#include <linux/clocksource.h>
#include <linux/percpu.h>
+#include <linux/persistent_clock.h>
#include <linux/timex.h>
#include <linux/static_key.h>
@@ -1032,6 +1033,11 @@ static u64 read_tsc(struct clocksource *cs)
return (u64)rdtsc_ordered();
}
+static u64 notrace tsc_read_persistent_clock(void)
+{
+ return (u64)rdtsc_ordered();
+}
+
static void tsc_cs_mark_unstable(struct clocksource *cs)
{
if (tsc_unstable)
@@ -1300,6 +1306,11 @@ static void tsc_refine_calibration_work(struct work_struct *work)
if (boot_cpu_has(X86_FEATURE_ART))
art_related_clocksource = &clocksource_tsc;
clocksource_register_khz(&clocksource_tsc, tsc_khz);
+
+ if (clocksource_tsc.flags & CLOCK_SOURCE_SUSPEND_NONSTOP)
+ persistent_clock_init_and_register(tsc_read_persistent_clock,
+ CLOCKSOURCE_MASK(64),
+ tsc_khz, 0);
unreg:
clocksource_unregister(&clocksource_tsc_early);
}
@@ -1327,6 +1338,11 @@ static int __init init_tsc_clocksource(void)
if (boot_cpu_has(X86_FEATURE_ART))
art_related_clocksource = &clocksource_tsc;
clocksource_register_khz(&clocksource_tsc, tsc_khz);
+
+ if (clocksource_tsc.flags & CLOCK_SOURCE_SUSPEND_NONSTOP)
+ persistent_clock_init_and_register(tsc_read_persistent_clock,
+ CLOCKSOURCE_MASK(64),
+ tsc_khz, 0);
unreg:
clocksource_unregister(&clocksource_tsc_early);
return 0;
--
1.7.9.5
^ permalink raw reply related
* [RFC PATCH 08/10] clocksource: time-pistachio: Register the persistent clock
From: Baolin Wang @ 2018-05-14 8:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1526285602.git.baolin.wang@linaro.org>
Since the timer on pistachio platform is always available, we can
register it as one persistent clock to compensate the suspend time
for the OS time.
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
---
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/time-pistachio.c | 3 +++
2 files changed, 4 insertions(+)
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index ed19757..b45be75 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -255,6 +255,7 @@ config CLKSRC_PISTACHIO
bool "Clocksource for Pistachio SoC" if COMPILE_TEST
depends on HAS_IOMEM
select TIMER_OF
+ select PERSISTENT_CLOCK
help
Enables the clocksource for the Pistachio SoC.
diff --git a/drivers/clocksource/time-pistachio.c b/drivers/clocksource/time-pistachio.c
index a2dd85d..5c3eb71 100644
--- a/drivers/clocksource/time-pistachio.c
+++ b/drivers/clocksource/time-pistachio.c
@@ -20,6 +20,7 @@
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/persistent_clock.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/sched_clock.h>
@@ -212,6 +213,8 @@ static int __init pistachio_clksrc_of_init(struct device_node *node)
raw_spin_lock_init(&pcs_gpt.lock);
sched_clock_register(pistachio_read_sched_clock, 32, rate);
+ persistent_clock_init_and_register(pistachio_read_sched_clock,
+ CLOCKSOURCE_MASK(32), rate, 0);
return clocksource_register_hz(&pcs_gpt.cs, rate);
}
TIMER_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer",
--
1.7.9.5
^ permalink raw reply related
* [RFC PATCH 07/10] clocksource: timer-ti-32k: Register the persistent clock
From: Baolin Wang @ 2018-05-14 8:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1526285602.git.baolin.wang@linaro.org>
Since the 32K counter is always available, then we can register the
persistent clock to compensate the suspend time for the OS time.
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
---
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/timer-ti-32k.c | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 884719c..ed19757 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -262,6 +262,7 @@ config CLKSRC_TI_32K
bool "Texas Instruments 32.768 Hz Clocksource" if COMPILE_TEST
depends on GENERIC_SCHED_CLOCK
select TIMER_OF if OF
+ select PERSISTENT_CLOCK
help
This option enables support for Texas Instruments 32.768 Hz clocksource
available on many OMAP-like platforms.
diff --git a/drivers/clocksource/timer-ti-32k.c b/drivers/clocksource/timer-ti-32k.c
index 880a861..353ff9d 100644
--- a/drivers/clocksource/timer-ti-32k.c
+++ b/drivers/clocksource/timer-ti-32k.c
@@ -41,6 +41,7 @@
#include <linux/clocksource.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/persistent_clock.h>
/*
* 32KHz clocksource ... always available, on pretty most chips except
@@ -120,6 +121,9 @@ static int __init ti_32k_timer_init(struct device_node *np)
}
sched_clock_register(omap_32k_read_sched_clock, 32, 32768);
+ persistent_clock_init_and_register(omap_32k_read_sched_clock,
+ CLOCKSOURCE_MASK(32), 32768, 0);
+
pr_info("OMAP clocksource: 32k_counter at 32768 Hz\n");
return 0;
--
1.7.9.5
^ permalink raw reply related
* [RFC PATCH 06/10] clocksource: arm_arch_timer: Register the persistent clock
From: Baolin Wang @ 2018-05-14 8:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1526285602.git.baolin.wang@linaro.org>
Register the persistent clock to compensate the suspend time for OS time,
if the ARM counter clocksource will not be stopped in suspend state.
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
---
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/arm_arch_timer.c | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index d7dddcc..884719c 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -308,6 +308,7 @@ config ARC_TIMERS_64BIT
config ARM_ARCH_TIMER
bool
+ select PERSISTENT_CLOCK
select TIMER_OF if OF
select TIMER_ACPI if ACPI
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 57cb2f0..671be63 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -32,6 +32,7 @@
#include <asm/virt.h>
#include <clocksource/arm_arch_timer.h>
+#include <linux/persistent_clock.h>
#undef pr_fmt
#define pr_fmt(fmt) "arch_timer: " fmt
@@ -950,6 +951,15 @@ static void __init arch_counter_register(unsigned type)
/* 56 bits minimum, so we assume worst case rollover */
sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate);
+
+ /*
+ * Register the persistent clock if the clocksource will not be stopped
+ * in suspend state.
+ */
+ if (!arch_counter_suspend_stop)
+ persistent_clock_init_and_register(arch_timer_read_counter,
+ CLOCKSOURCE_MASK(56),
+ arch_timer_rate, 0);
}
static void arch_timer_stop(struct clock_event_device *clk)
--
1.7.9.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox