* Re: [PATCH v6 tip 2/8] tracing: attach BPF programs to kprobes
From: Alexei Starovoitov @ 2015-03-12 16:18 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Ingo Molnar, Steven Rostedt, Namhyung Kim,
Arnaldo Carvalho de Melo, Jiri Olsa, Masami Hiramatsu,
David S. Miller, Daniel Borkmann, linux-api, netdev, linux-kernel
In-Reply-To: <20150312151507.GI2896@worktop.programming.kicks-ass.net>
On 3/12/15 8:15 AM, Peter Zijlstra wrote:
> On Tue, Mar 10, 2015 at 09:18:48PM -0700, Alexei Starovoitov wrote:
>> +unsigned int trace_call_bpf(struct bpf_prog *prog, void *ctx)
>> +{
>> + unsigned int ret;
>> + int cpu;
>> +
>> + if (in_nmi()) /* not supported yet */
>> + return 1;
>> +
>> + preempt_disable_notrace();
>> +
>> + cpu = raw_smp_processor_id();
>> + if (unlikely(per_cpu(bpf_prog_active, cpu)++ != 0)) {
>> + /* since some bpf program is already running on this cpu,
>> + * don't call into another bpf program (same or different)
>> + * and don't send kprobe event into ring-buffer,
>> + * so return zero here
>> + */
>> + ret = 0;
>> + goto out;
>> + }
>> +
>> + rcu_read_lock();
>
> You've so far tried very hard to not get into tracing; and then you call
> rcu_read_lock() :-)
>
> So either document why this isn't a problem, provide
> rcu_read_lock_notrace() or switch to RCU-sched and thereby avoid the
> problem.
I don't see the problem.
I actually do turn on func and func_graph tracers from time to time to
debug bpf core itself. Why would tracing interfere with anything that
this patch is doing? When we're inside tracing processing, we need to
use only _notrace() helpers otherwise recursion will hurt, but this
code is not invoked from there. It's called from
kprobe_ftrace_handler|kprobe_int3_handler->kprobe_dispatcher->
kprobe_perf_func->trace_call_bpf which all are perfectly traceable.
Probably my copy paste of preempt_disable_notrace() line from
stack_trace_call() became source of confusion? I believe
normal preempt_disable() here will be just fine.
It's actually redundant too, since preemption is disabled by kprobe
anyway. Please help me understand what I'm missing.
^ permalink raw reply
* Re: [PATCH v6 tip 2/8] tracing: attach BPF programs to kprobes
From: Steven Rostedt @ 2015-03-12 16:23 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Peter Zijlstra, Ingo Molnar, Namhyung Kim,
Arnaldo Carvalho de Melo, Jiri Olsa, Masami Hiramatsu,
David S. Miller, Daniel Borkmann, linux-api, netdev, linux-kernel
In-Reply-To: <5501BC5A.6000204@plumgrid.com>
On Thu, 12 Mar 2015 09:18:34 -0700
Alexei Starovoitov <ast@plumgrid.com> wrote:
> > You've so far tried very hard to not get into tracing; and then you call
> > rcu_read_lock() :-)
> >
> > So either document why this isn't a problem, provide
> > rcu_read_lock_notrace() or switch to RCU-sched and thereby avoid the
> > problem.
>
> I don't see the problem.
> I actually do turn on func and func_graph tracers from time to time to
> debug bpf core itself. Why would tracing interfere with anything that
> this patch is doing? When we're inside tracing processing, we need to
> use only _notrace() helpers otherwise recursion will hurt, but this
> code is not invoked from there. It's called from
> kprobe_ftrace_handler|kprobe_int3_handler->kprobe_dispatcher->
> kprobe_perf_func->trace_call_bpf which all are perfectly traceable.
> Probably my copy paste of preempt_disable_notrace() line from
> stack_trace_call() became source of confusion? I believe
> normal preempt_disable() here will be just fine.
> It's actually redundant too, since preemption is disabled by kprobe
> anyway. Please help me understand what I'm missing.
As Peter stated, "You've so far tried very hard to not get into
tracing", which the preempt_disable_notrace() is the source of confusion.
Just remove the _notrace() part, as it doesn't make sense to have part
not traced, and other parts traced for no apparent reason.
-- Steve
^ permalink raw reply
* Re: [PATCH 13/14] kdbus: add walk-through user space example
From: David Herrmann @ 2015-03-12 16:34 UTC (permalink / raw)
To: Sasha Levin
Cc: Greg Kroah-Hartman, Arnd Bergmann, Eric W. Biederman,
One Thousand Gnomes, Tom Gundersen, Jiri Kosina, Andy Lutomirski,
Linux API, linux-kernel, Daniel Mack, Djalal Harouni
In-Reply-To: <5501A848.5080402-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
Hi
On Thu, Mar 12, 2015 at 3:52 PM, Sasha Levin <sasha.levin-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org> wrote:
> On 03/09/2015 09:09 AM, Greg Kroah-Hartman wrote:
>> diff --git a/samples/kdbus/Makefile b/samples/kdbus/Makefile
>> new file mode 100644
>> index 000000000000..d009025369f4
>> --- /dev/null
>> +++ b/samples/kdbus/Makefile
>> @@ -0,0 +1,10 @@
>> +# kbuild trick to avoid linker error. Can be omitted if a module is built.
>> +obj- := dummy.o
>> +
>> +hostprogs-y += kdbus-workers
>> +
>> +always := $(hostprogs-y)
>> +
>> +HOSTCFLAGS_kdbus-workers.o += \
>> + -I$(objtree)/usr/include/ \
>> + -I$(objtree)/include/uapi/
> -lrt
>
> For older glibcs, otherwise clock_gettime() isn't found on linking.
Right, thanks! Fixed in "[PATCH] samples/kdbus: add -lrt".
Thanks
David
^ permalink raw reply
* Re: [PATCH v6 tip 2/8] tracing: attach BPF programs to kprobes
From: Alexei Starovoitov @ 2015-03-12 16:43 UTC (permalink / raw)
To: Steven Rostedt
Cc: Peter Zijlstra, Ingo Molnar, Namhyung Kim,
Arnaldo Carvalho de Melo, Jiri Olsa, Masami Hiramatsu,
David S. Miller, Daniel Borkmann, linux-api, netdev, linux-kernel
In-Reply-To: <20150312122345.0b28c266@gandalf.local.home>
On 3/12/15 9:23 AM, Steven Rostedt wrote:
> On Thu, 12 Mar 2015 09:18:34 -0700
> Alexei Starovoitov <ast@plumgrid.com> wrote:
>
>>> You've so far tried very hard to not get into tracing; and then you call
>>> rcu_read_lock() :-)
>>>
>>> So either document why this isn't a problem, provide
>>> rcu_read_lock_notrace() or switch to RCU-sched and thereby avoid the
>>> problem.
>>
>> I don't see the problem.
>> I actually do turn on func and func_graph tracers from time to time to
>> debug bpf core itself. Why would tracing interfere with anything that
>> this patch is doing? When we're inside tracing processing, we need to
>> use only _notrace() helpers otherwise recursion will hurt, but this
>> code is not invoked from there. It's called from
>> kprobe_ftrace_handler|kprobe_int3_handler->kprobe_dispatcher->
>> kprobe_perf_func->trace_call_bpf which all are perfectly traceable.
>> Probably my copy paste of preempt_disable_notrace() line from
>> stack_trace_call() became source of confusion? I believe
>> normal preempt_disable() here will be just fine.
>> It's actually redundant too, since preemption is disabled by kprobe
>> anyway. Please help me understand what I'm missing.
>
> As Peter stated, "You've so far tried very hard to not get into
> tracing", which the preempt_disable_notrace() is the source of confusion.
>
> Just remove the _notrace() part, as it doesn't make sense to have part
> not traced, and other parts traced for no apparent reason.
sure. consider it done. should I respin right away or you can review
the rest?
^ permalink raw reply
* Re: [PATCH v6 tip 2/8] tracing: attach BPF programs to kprobes
From: Steven Rostedt @ 2015-03-12 16:47 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Peter Zijlstra, Ingo Molnar, Namhyung Kim,
Arnaldo Carvalho de Melo, Jiri Olsa, Masami Hiramatsu,
David S. Miller, Daniel Borkmann,
linux-api-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <5501C24A.30206-uqk4Ao+rVK5Wk0Htik3J/w@public.gmane.org>
On Thu, 12 Mar 2015 09:43:54 -0700
Alexei Starovoitov <ast-uqk4Ao+rVK5Wk0Htik3J/w@public.gmane.org> wrote:
> sure. consider it done. should I respin right away or you can review
> the rest?
Hold off for a bit, to let the review continue.
-- Steve
^ permalink raw reply
* Re: [PATCH] seccomp.2: Add note about alarm(2) not being sufficient to limit runtime
From: Andy Lutomirski @ 2015-03-12 17:30 UTC (permalink / raw)
To: Jann Horn
Cc: Michael Kerrisk, Mikael Pettersson, linux-man, Linux API,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Russell King, Catalin Marinas, Will Deacon, Thomas Gleixner,
Ingo Molnar, H. Peter Anvin, X86 ML, Jeff Dike,
Richard Weinberger, Kees Cook, Will Drewry
In-Reply-To: <20150312130701.GA11073-J1fxOzX/cBvk1uMJSBkQmQ@public.gmane.org>
On Thu, Mar 12, 2015 at 6:07 AM, Jann Horn <jann-XZ1E9jl8jIdeoWH0uzbU5w@public.gmane.org> wrote:
> On Wed, Mar 11, 2015 at 10:43:50PM +0100, Mikael Pettersson wrote:
>> Jann Horn writes:
>> > Or should I throw this patch away and write a patch
>> > for the prctl() manpage instead that documents that
>> > being able to call sigreturn() implies being able to
>> > effectively call sigprocmask(), at least on some
>> > architectures like X86?
>>
>> Well, that is the semantics of sigreturn(). It is essentially
>> setcontext() [which includes the actions of sigprocmask()], but
>> with restrictions on parameter placement (at least on x86).
>>
>> You could introduce some setting to restrict that aspect for
>> seccomp processes, but you can't change this for normal processes
>> without breaking things.
>
> Then I think it's probably better and easier to just document the existing
> behavior? If a new setting would have to be introduced and developers would
> need to be aware of that, it's probably easier to just tell everyone to use
> SIGKILL.
>
> Does this manpage patch look good?
Looks good to me.
FWIW, if we wanted to fix this in the kernel, I think it could be
easier to add SIG_KILL which would be just like SIG_DFL except always
fatal even if masked rather than coming up with complicated changes to
sigreturn.
--Andy
>
> ---
> man2/seccomp.2 | 25 +++++++++++++++++++++++++
> 1 file changed, 25 insertions(+)
>
> diff --git a/man2/seccomp.2 b/man2/seccomp.2
> index 702ceb8..f762d07 100644
> --- a/man2/seccomp.2
> +++ b/man2/seccomp.2
> @@ -64,6 +64,31 @@ Strict secure computing mode is useful for number-crunching
> applications that may need to execute untrusted byte code, perhaps
> obtained by reading from a pipe or socket.
>
> +Note that although the calling thread can no longer call
> +.BR sigprocmask (2),
> +it can use
> +.BR sigreturn (2)
> +to block all signals apart from
> +.BR SIGKILL
> +and
> +.BR SIGSTOP .
> +Therefore, to reliably terminate it,
> +.BR SIGKILL
> +has to be used, meaning that e.g.
> +.BR alarm (2)
> +is not sufficient for restricting its runtime. Instead, use
> +.BR timer_create (2)
> +with
> +.BR SIGEV_SIGNAL
> +and
> +.BR sigev_signo
> +set to
> +.BR SIGKILL
> +or use
> +.BR setrlimit (2)
> +to set the hard limit for
> +.BR RLIMIT_CPU .
> +
> This operation is available only if the kernel is configured with
> .BR CONFIG_SECCOMP
> enabled.
> --
> 2.1.4
>
--
Andy Lutomirski
AMA Capital Management, LLC
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] seccomp.2: Add note about alarm(2) not being sufficient to limit runtime
From: Kees Cook @ 2015-03-12 17:33 UTC (permalink / raw)
To: Jann Horn
Cc: Michael Kerrisk, Mikael Pettersson, linux-man, Linux API, LKML,
Russell King, Catalin Marinas, Will Deacon, Thomas Gleixner,
Ingo Molnar, H. Peter Anvin,
x86-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, Jeff Dike,
Richard Weinberger, Andy Lutomirski, Will Drewry
In-Reply-To: <20150312130701.GA11073-J1fxOzX/cBvk1uMJSBkQmQ@public.gmane.org>
On Thu, Mar 12, 2015 at 6:07 AM, Jann Horn <jann-XZ1E9jl8jIdeoWH0uzbU5w@public.gmane.org> wrote:
> On Wed, Mar 11, 2015 at 10:43:50PM +0100, Mikael Pettersson wrote:
>> Jann Horn writes:
>> > Or should I throw this patch away and write a patch
>> > for the prctl() manpage instead that documents that
>> > being able to call sigreturn() implies being able to
>> > effectively call sigprocmask(), at least on some
>> > architectures like X86?
>>
>> Well, that is the semantics of sigreturn(). It is essentially
>> setcontext() [which includes the actions of sigprocmask()], but
>> with restrictions on parameter placement (at least on x86).
>>
>> You could introduce some setting to restrict that aspect for
>> seccomp processes, but you can't change this for normal processes
>> without breaking things.
>
> Then I think it's probably better and easier to just document the existing
> behavior? If a new setting would have to be introduced and developers would
> need to be aware of that, it's probably easier to just tell everyone to use
> SIGKILL.
>
> Does this manpage patch look good?
>
> ---
> man2/seccomp.2 | 25 +++++++++++++++++++++++++
> 1 file changed, 25 insertions(+)
>
> diff --git a/man2/seccomp.2 b/man2/seccomp.2
> index 702ceb8..f762d07 100644
> --- a/man2/seccomp.2
> +++ b/man2/seccomp.2
> @@ -64,6 +64,31 @@ Strict secure computing mode is useful for number-crunching
> applications that may need to execute untrusted byte code, perhaps
> obtained by reading from a pipe or socket.
>
> +Note that although the calling thread can no longer call
> +.BR sigprocmask (2),
> +it can use
> +.BR sigreturn (2)
> +to block all signals apart from
> +.BR SIGKILL
> +and
> +.BR SIGSTOP .
> +Therefore, to reliably terminate it,
> +.BR SIGKILL
> +has to be used, meaning that e.g.
> +.BR alarm (2)
> +is not sufficient for restricting its runtime. Instead, use
> +.BR timer_create (2)
> +with
> +.BR SIGEV_SIGNAL
> +and
> +.BR sigev_signo
> +set to
> +.BR SIGKILL
> +or use
> +.BR setrlimit (2)
> +to set the hard limit for
> +.BR RLIMIT_CPU .
> +
> This operation is available only if the kernel is configured with
> .BR CONFIG_SECCOMP
> enabled.
> --
> 2.1.4
>
Thanks! This looks good.
Acked-by: Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
-Kees
--
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [RFC] capabilities: Ambient capabilities
From: Andy Lutomirski @ 2015-03-12 18:08 UTC (permalink / raw)
Cc: Andy Lutomirski, Kees Cook, Christoph Lameter, Serge Hallyn,
Andy Lutomirski, Jonathan Corbet, Aaron Jones, Ted Ts'o,
linux-security-module-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
akpm-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, Andrew G. Morgan,
Mimi Zohar, Austin S Hemmelgarn, Markku Savela, Jarkko Sakkinen,
Michael Kerrisk
Credit where credit is due: this idea comes from Christoph Lameter
with a lot of valuable input from Serge Hallyn. This patch is
heavily based on Christoph's patch.
===== The status quo =====
On Linux, there are a number of capabilities defined by the kernel.
To perform various privileged tasks, processes can wield
capabilities that they hold.
Each task has four capability masks: effective (pE), permitted (pP),
inheritable (pI), and a bounding set (X). When the kernel checks
for a capability, it checks pE. The other capability masks serve to
modify what capabilities can be in pE.
Any task can remove capabilities from pE, pP, or pI at any time. If
a task has a capability in pP, it can add that capability to pE
and/or pI. If a task has CAP_SETPCAP, then it can add any
capability to pI, and it can remove capabilities from X.
Tasks are not the only things that can have capabilities; files can
also have capabilities. A file can have no capabilty information at
all [1]. If a file has capability information, then it has a
permitted mask (fP) and an inheritable mask (fI) as well as a single
effective bit (fE) [2]. File capabilities modify the capabilities
of tasks that execve(2) them.
A task that successfully calls execve has its capabilities modified
for the file ultimately being excecuted (i.e. the binary itself if
that binary is ELF or for the interpreter if the binary is a
script.) [3] In the capability evolution rules, for each mask Z, pZ
represents the old value and pZ' represents the new value. The
rules are:
pP' = (X & fP) | (pI & fI)
pI' = pI
pE' = (fE ? pP' : 0)
X is unchanged
For setuid binaries, fP, fI, and fE are modified by a moderately
complicated set of rules that emulate POSIX behavior. Similarly, if
euid == 0 or ruid == 0, then fP, fI, and fE are modified differently
(primary, fP and fI usually end up being the full set). For nonroot
users executing binaries with neither setuid nor file caps, fI and
fP are empty and fE is false.
As an extra complication, if you execute a process as nonroot and fE
is set, then the "secure exec" rules are in effect: AT_SECURE gets
set, LD_PRELOAD doesn't work, etc.
This is rather messy. We've learned that making any changes is
dangerous, though: if a new kernel version allows an unprivileged
program to change its security state in a way that persists cross
execution of a setuid program or a program with file caps, this
persistent state is surprisingly likely to allow setuid or
file-capped programs to be exploited for privilege escalation.
===== The problem =====
Capability inheritance is basically useless.
If you aren't root and you execute an ordinary binary, fI is zero,
so your capabilities have no effect whatsoever on pP'. This means
that you can't usefully execute a helper process or a shell command
with elevated capabilities if you aren't root.
On current kernels, you can sort of work around this by setting fI
to the full set for most or all non-setuid executable files. This
causes pP' = pI for nonroot, and inheritance works. No one does
this because it's a PITA and it isn't even supported on most
filesystems.
If you try this, you'll discover that every nonroot program ends up
with secure exec rules, breaking many things.
This is a problem that has bitten many people who have tried to use
capabilities for anything useful.
===== The proposed change =====
This patch adds a fifth capability mask called the ambient mask
(pA). pA does what pI should have done.
pA obeys the invariant that no bit can ever be set in pA if it is
not set in both pP and pI. Dropping a bit from pP or pI drops that
bit from pA. This ensures that existing programs that try to drop
capabilities still do so, with a complication. Because capability
inheritance is so broken, setting KEEPCAPS, using setresuid to
switch to nonroot uids, and calling execve effectively drops
capabilities. Therefore, setresuid from root to nonroot
unconditionally clears pA. Processes that don't like this can
re-add bits to pA afterwards.
The capability evolution rules are changed:
pA' = (file caps or setuid or setgid ? 0 : pA)
pP' = (X & fP) | (pI & fI) | pA'
pI' = pI
pE' = (fE ? pP' : pA')
X is unchanged
If you are nonroot but you have a capability, you can add it to pA.
If you do so, your children get that capability in pA, pP, and pE.
For example, you can set pA = CAP_NET_BIND_SERVICE, and your
children can automatically bind low-numbered ports. Hallelujah!
Unprivileged users can create user namespaces, map themselves to a
nonzero uid, and create both privileged (relative to their
namespace) and unprivileged process trees. This is currently more
or less impossible. Hallelujah!
You cannot use pA to try to subvert a setuid, setgid, or file-capped
program: if you execute any such program, pA gets cleared and the
resulting evolution rules are unchanged by this patch.
Users with nonzero pA are unlikely to unintentionally leak that
capability. If they run programs that try to drop privileges,
dropping privileges will still work.
It's worth noting that the degree of paranoia in this patch could
possibly be relaxed without causing serious problems. Specifically,
if we allowed pA to persist across executing non-pA-aware setuid
binaries and across setresuid, then, naively, the only capabilities
that could leak as a result would be the capabilities in pA, and any
attacker *already* has those capabilities. This would make me
nervous, though -- setuid binaries that tried to privilege-separate
might fail to do so, and putting CAP_DAC_READ_SEARCH or
CAP_DAC_OVERRIDE into pA could have unexpected side effects.
(Whether these unexpected side effects would be exploitable is an
open question.) I've therefore taken the more paranoid route.
An alternative would be to either require PR_SET_NO_NEW_PRIVS before
setting ambient capabilities. I think that this would be annoying
and would make granting otherwise unprivileged users minor ambient
capabilities (CAP_NET_BIND_SERVICE or CAP_NET_RAW for example) much
less useful than it is with this patch.
===== Footnotes =====
[1] Files that are missing the "security.capability" xattr or that
have unrecognized values for that xattr end up with has_cap ==
false. The code that does that appears to be complicated for no
good reason.
[2] The libcap capability mask parsers and formatters are
dangerously misleading and the documentation is flat-out wrong. fE
is *not* a mask; it's a single bit. This has probably confused
every single person who has tried to use file capabilities.
[3] Linux very confusingly processes the script and the interpreter if
applicable, for reasons that escape me. The results from thinking
about a script's file capabilities and/or setuid bits are mostly discarded.
Cc: Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Cc: Christoph Lameter <cl-vYTEC60ixJUAvxtiuMwx3w@public.gmane.org>
Cc: Serge Hallyn <serge.hallyn-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
Cc: Andy Lutomirski <luto-kltTT9wpgjJwATOyAt5JVQ@public.gmane.org>
Cc: Jonathan Corbet <corbet-T1hC0tSOHrs@public.gmane.org>
Cc: Aaron Jones <aaronmdjones-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
CC: Ted Ts'o <tytso-3s7WtUTddSA@public.gmane.org>
Cc: linux-security-module-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: akpm-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org
Cc: Andrew G. Morgan <morgan-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: Mimi Zohar <zohar-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Cc: Austin S Hemmelgarn <ahferroin7-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Cc: Markku Savela <msa-kXoF896ld44xHbG02/KK1g@public.gmane.org>
Cc: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Cc: Michael Kerrisk <mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Andy Lutomirski <luto-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
Preliminary userspace code is here:
https://git.kernel.org/cgit/linux/kernel/git/luto/util-linux-playground.git/commit/?h=cap_ambient&id=860c73ac1acaaae976bdd3bb83b89b0180f0702a
fs/proc/array.c | 5 ++-
include/linux/cred.h | 15 +++++++++
include/uapi/linux/prctl.h | 6 ++++
kernel/user_namespace.c | 1 +
security/commoncap.c | 75 ++++++++++++++++++++++++++++++++++++++------
security/keys/process_keys.c | 1 +
6 files changed, 92 insertions(+), 11 deletions(-)
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 1295a00ca316..bc15356d6551 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -282,7 +282,8 @@ static void render_cap_t(struct seq_file *m, const char *header,
static inline void task_cap(struct seq_file *m, struct task_struct *p)
{
const struct cred *cred;
- kernel_cap_t cap_inheritable, cap_permitted, cap_effective, cap_bset;
+ kernel_cap_t cap_inheritable, cap_permitted, cap_effective,
+ cap_bset, cap_ambient;
rcu_read_lock();
cred = __task_cred(p);
@@ -290,12 +291,14 @@ static inline void task_cap(struct seq_file *m, struct task_struct *p)
cap_permitted = cred->cap_permitted;
cap_effective = cred->cap_effective;
cap_bset = cred->cap_bset;
+ cap_ambient = cred->cap_ambient;
rcu_read_unlock();
render_cap_t(m, "CapInh:\t", &cap_inheritable);
render_cap_t(m, "CapPrm:\t", &cap_permitted);
render_cap_t(m, "CapEff:\t", &cap_effective);
render_cap_t(m, "CapBnd:\t", &cap_bset);
+ render_cap_t(m, "CapAmb:\t", &cap_ambient);
}
static inline void task_seccomp(struct seq_file *m, struct task_struct *p)
diff --git a/include/linux/cred.h b/include/linux/cred.h
index 2fb2ca2127ed..a21bcba6ef84 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -122,6 +122,7 @@ struct cred {
kernel_cap_t cap_permitted; /* caps we're permitted */
kernel_cap_t cap_effective; /* caps we can actually use */
kernel_cap_t cap_bset; /* capability bounding set */
+ kernel_cap_t cap_ambient; /* Ambient capability set */
#ifdef CONFIG_KEYS
unsigned char jit_keyring; /* default keyring to attach requested
* keys to */
@@ -197,6 +198,20 @@ static inline void validate_process_creds(void)
}
#endif
+static inline void cap_enforce_ambient_invariants(struct cred *cred)
+{
+ cred->cap_ambient = cap_intersect(cred->cap_ambient,
+ cap_intersect(cred->cap_permitted,
+ cred->cap_inheritable));
+}
+
+static inline bool cap_ambient_invariant_ok(const struct cred *cred)
+{
+ return cap_issubset(cred->cap_ambient,
+ cap_intersect(cred->cap_permitted,
+ cred->cap_inheritable));
+}
+
/**
* get_new_cred - Get a reference on a new set of credentials
* @cred: The new credentials to reference
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index 31891d9535e2..65407f867e82 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -190,4 +190,10 @@ struct prctl_mm_map {
# define PR_FP_MODE_FR (1 << 0) /* 64b FP registers */
# define PR_FP_MODE_FRE (1 << 1) /* 32b compatibility */
+/* Control the ambient capability set */
+#define PR_CAP_AMBIENT 47
+# define PR_CAP_AMBIENT_GET 1
+# define PR_CAP_AMBIENT_RAISE 2
+# define PR_CAP_AMBIENT_LOWER 3
+
#endif /* _LINUX_PRCTL_H */
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 4109f8320684..dab0f808235a 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -39,6 +39,7 @@ static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns)
cred->cap_inheritable = CAP_EMPTY_SET;
cred->cap_permitted = CAP_FULL_SET;
cred->cap_effective = CAP_FULL_SET;
+ cred->cap_ambient = CAP_EMPTY_SET;
cred->cap_bset = CAP_FULL_SET;
#ifdef CONFIG_KEYS
key_put(cred->request_key_auth);
diff --git a/security/commoncap.c b/security/commoncap.c
index f66713bd7450..b3253886ecad 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -272,6 +272,7 @@ int cap_capset(struct cred *new,
new->cap_effective = *effective;
new->cap_inheritable = *inheritable;
new->cap_permitted = *permitted;
+ cap_enforce_ambient_invariants(new);
return 0;
}
@@ -352,6 +353,7 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
/*
* pP' = (X & fP) | (pI & fI)
+ * The addition of pA' is handled later.
*/
new->cap_permitted.cap[i] =
(new->cap_bset.cap[i] & permitted) |
@@ -479,10 +481,12 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
{
const struct cred *old = current_cred();
struct cred *new = bprm->cred;
- bool effective, has_cap = false;
+ bool effective, has_cap = false, is_setid;
int ret;
kuid_t root_uid;
+ BUG_ON(!cap_ambient_invariant_ok(old));
+
effective = false;
ret = get_file_caps(bprm, &effective, &has_cap);
if (ret < 0)
@@ -527,8 +531,9 @@ skip:
*
* In addition, if NO_NEW_PRIVS, then ensure we get no new privs.
*/
- if ((!uid_eq(new->euid, old->uid) ||
- !gid_eq(new->egid, old->gid) ||
+ is_setid = !uid_eq(new->euid, old->uid) || !gid_eq(new->egid, old->gid);
+
+ if ((is_setid ||
!cap_issubset(new->cap_permitted, old->cap_permitted)) &&
bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
/* downgrade; they get no more than they had, and maybe less */
@@ -544,10 +549,23 @@ skip:
new->suid = new->fsuid = new->euid;
new->sgid = new->fsgid = new->egid;
+ /* File caps or setid cancel ambient. */
+ if (has_cap || is_setid)
+ cap_clear(new->cap_ambient);
+
+ /*
+ * Now that we've computed pA', update pP' to give:
+ * pP' = (X & fP) | (pI & fI) | pA'
+ */
+ new->cap_permitted = cap_combine(new->cap_permitted, new->cap_ambient);
+
if (effective)
new->cap_effective = new->cap_permitted;
else
- cap_clear(new->cap_effective);
+ new->cap_effective = new->cap_ambient;
+
+ BUG_ON(!cap_ambient_invariant_ok(new));
+
bprm->cap_effective = effective;
/*
@@ -562,7 +580,7 @@ skip:
* Number 1 above might fail if you don't have a full bset, but I think
* that is interesting information to audit.
*/
- if (!cap_isclear(new->cap_effective)) {
+ if (!cap_issubset(new->cap_effective, new->cap_ambient)) {
if (!cap_issubset(CAP_FULL_SET, new->cap_effective) ||
!uid_eq(new->euid, root_uid) || !uid_eq(new->uid, root_uid) ||
issecure(SECURE_NOROOT)) {
@@ -573,6 +591,9 @@ skip:
}
new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
+
+ BUG_ON(!cap_ambient_invariant_ok(new));
+
return 0;
}
@@ -594,7 +615,7 @@ int cap_bprm_secureexec(struct linux_binprm *bprm)
if (!uid_eq(cred->uid, root_uid)) {
if (bprm->cap_effective)
return 1;
- if (!cap_isclear(cred->cap_permitted))
+ if (!cap_issubset(cred->cap_permitted, cred->cap_ambient))
return 1;
}
@@ -696,10 +717,18 @@ static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old)
uid_eq(old->suid, root_uid)) &&
(!uid_eq(new->uid, root_uid) &&
!uid_eq(new->euid, root_uid) &&
- !uid_eq(new->suid, root_uid)) &&
- !issecure(SECURE_KEEP_CAPS)) {
- cap_clear(new->cap_permitted);
- cap_clear(new->cap_effective);
+ !uid_eq(new->suid, root_uid))) {
+ if (!issecure(SECURE_KEEP_CAPS)) {
+ cap_clear(new->cap_permitted);
+ cap_clear(new->cap_effective);
+ }
+
+ /*
+ * Pre-ambient programs except setresuid to nonroot followed
+ * by exec to drop capabilities. We should make sure that
+ * this remains the case.
+ */
+ cap_clear(new->cap_ambient);
}
if (uid_eq(old->euid, root_uid) && !uid_eq(new->euid, root_uid))
cap_clear(new->cap_effective);
@@ -929,6 +958,32 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
return commit_creds(new);
+ case PR_CAP_AMBIENT:
+ if (((!cap_valid(arg3)) | arg4 | arg5))
+ return -EINVAL;
+
+ if (arg2 == PR_CAP_AMBIENT_GET) {
+ return !!cap_raised(current_cred()->cap_ambient, arg3);
+ } else if (arg2 != PR_CAP_AMBIENT_RAISE &&
+ arg2 != PR_CAP_AMBIENT_LOWER) {
+ return -EINVAL;
+ } else {
+ if (arg2 == PR_CAP_AMBIENT_RAISE &&
+ (!cap_raised(current_cred()->cap_permitted, arg3) ||
+ !cap_raised(current_cred()->cap_inheritable,
+ arg3)))
+ return -EPERM;
+
+ new = prepare_creds();
+ if (!new)
+ return -ENOMEM;
+ if (arg2 == PR_CAP_AMBIENT_RAISE)
+ cap_raise(new->cap_ambient, arg3);
+ else
+ cap_lower(new->cap_ambient, arg3);
+ return commit_creds(new);
+ }
+
default:
/* No functionality available - continue with default */
return -ENOSYS;
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index bd536cb221e2..43b4cddbf2b3 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -848,6 +848,7 @@ void key_change_session_keyring(struct callback_head *twork)
new->cap_inheritable = old->cap_inheritable;
new->cap_permitted = old->cap_permitted;
new->cap_effective = old->cap_effective;
+ new->cap_ambient = old->cap_ambient;
new->cap_bset = old->cap_bset;
new->jit_keyring = old->jit_keyring;
--
2.3.0
^ permalink raw reply related
* Re: [PATCH] seccomp.2: Add note about alarm(2) not being sufficient to limit runtime
From: Mikael Pettersson @ 2015-03-12 20:01 UTC (permalink / raw)
To: Jann Horn
Cc: Michael Kerrisk, Mikael Pettersson,
linux-man-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Russell King,
Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
H. Peter Anvin, x86-DgEjT+Ai2ygdnm+yROfE0A, Jeff Dike,
Richard Weinberger, Kees Cook, Andy Lutomirski, Will Drewry
In-Reply-To: <20150312130701.GA11073-J1fxOzX/cBvk1uMJSBkQmQ@public.gmane.org>
Jann Horn writes:
> On Wed, Mar 11, 2015 at 10:43:50PM +0100, Mikael Pettersson wrote:
> > Jann Horn writes:
> > > Or should I throw this patch away and write a patch
> > > for the prctl() manpage instead that documents that
> > > being able to call sigreturn() implies being able to
> > > effectively call sigprocmask(), at least on some
> > > architectures like X86?
> >
> > Well, that is the semantics of sigreturn(). It is essentially
> > setcontext() [which includes the actions of sigprocmask()], but
> > with restrictions on parameter placement (at least on x86).
> >
> > You could introduce some setting to restrict that aspect for
> > seccomp processes, but you can't change this for normal processes
> > without breaking things.
>
> Then I think it's probably better and easier to just document the existing
> behavior? If a new setting would have to be introduced and developers would
> need to be aware of that, it's probably easier to just tell everyone to use
> SIGKILL.
>
> Does this manpage patch look good?
LGTM
Acked-by: Mikael Pettersson <mikpelinux-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>
> ---
> man2/seccomp.2 | 25 +++++++++++++++++++++++++
> 1 file changed, 25 insertions(+)
>
> diff --git a/man2/seccomp.2 b/man2/seccomp.2
> index 702ceb8..f762d07 100644
> --- a/man2/seccomp.2
> +++ b/man2/seccomp.2
> @@ -64,6 +64,31 @@ Strict secure computing mode is useful for number-crunching
> applications that may need to execute untrusted byte code, perhaps
> obtained by reading from a pipe or socket.
>
> +Note that although the calling thread can no longer call
> +.BR sigprocmask (2),
> +it can use
> +.BR sigreturn (2)
> +to block all signals apart from
> +.BR SIGKILL
> +and
> +.BR SIGSTOP .
> +Therefore, to reliably terminate it,
> +.BR SIGKILL
> +has to be used, meaning that e.g.
> +.BR alarm (2)
> +is not sufficient for restricting its runtime. Instead, use
> +.BR timer_create (2)
> +with
> +.BR SIGEV_SIGNAL
> +and
> +.BR sigev_signo
> +set to
> +.BR SIGKILL
> +or use
> +.BR setrlimit (2)
> +to set the hard limit for
> +.BR RLIMIT_CPU .
> +
> This operation is available only if the kernel is configured with
> .BR CONFIG_SECCOMP
> enabled.
> --
> 2.1.4
--
^ permalink raw reply
* Re: [PATCH v2 07/18] drivers: reset: Add STM32 reset driver
From: Maxime Coquelin @ 2015-03-12 21:05 UTC (permalink / raw)
To: Philipp Zabel
Cc: Arnd Bergmann, Uwe Kleine-König, Andreas Färber,
Geert Uytterhoeven, Rob Herring, Jonathan Corbet, Pawel Moll,
Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
Daniel Lezcano, Thomas Gleixner, Linus Walleij,
Greg Kroah-Hartman, Jiri Slaby, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo
In-Reply-To: <1426079308.3101.57.camel@pengutronix.de>
2015-03-11 14:08 GMT+01:00 Philipp Zabel <p.zabel@pengutronix.de>:
> Am Dienstag, den 10.03.2015, 22:20 +0100 schrieb Maxime Coquelin:
>> 2015-03-10 21:21 GMT+01:00 Arnd Bergmann <arnd@arndb.de>:
>> > On Tuesday 10 March 2015 16:44:24 Maxime Coquelin wrote:
>> >> 2015-03-10 16:02 GMT+01:00 Arnd Bergmann <arnd@arndb.de>:
>> >> > On Friday 20 February 2015 19:01:06 Maxime Coquelin wrote:
>> >> >> +/* AHB1 */
>> >> >> +#define GPIOA_RESET 0
>> >> >> +#define GPIOB_RESET 1
>> >> >> +#define GPIOC_RESET 2
>> >> >> +#define GPIOD_RESET 3
>> >> >> +#define GPIOE_RESET 4
>> >> >> +#define GPIOF_RESET 5
>> >> >> +#define GPIOG_RESET 6
>> >> >> +#define GPIOH_RESET 7
>> >> >> +#define GPIOI_RESET 8
>> >> >> +#define GPIOJ_RESET 9
>> >> >> +#define GPIOK_RESET 10
>> >> >>
>> >> >
>> >> > As these are just the hardware numbers, it's better to not make them
>> >> > part of the binding at all. Instead, just document in the binding that
>> >> > one is supposed to pass the hardware number as the argument.
>> >>
>> >> The reset controller is part of the RCC (Reset & Clock Controller) IP.
>> >> In this version, I only provided the reset registers to the reset
>> >> controller driver, but as per Andreas Färber remark, I should avec a
>> >> single DT node for both the resets and clocks.
>> >>
>> >> In the next version I am preparing, the defines doesn't look as
>> >> trivial as in this version, GPIOA_RESET being 128 for instance.
>> >>
>> >> Is it fine for you if I keep the defines part of the binding?
>> >>
>> >>
>> >
>> > It's always better to avoid these files entirely, as they are
>> > a frequent source of merge dependencies, and they make it less
>> > obvious what's going on than having binary values in the dtb
>> > that make sense.
>>
>> I agree it is always painful to have to have to manage these merge dependencies.
>> What I will do, if Philipp agrees, is to list all the values in the
>> binding documentation.
>>
>> Doing that, the user of a reset won't have to do the calculation, and
>> no more merge dependencies.
>
> I'd prefer to have #defines for the reset bits if they are named in the
> documentation and use the names in the dts. But if you want to reference
> reset bits by number in the device tree instead, I won't insist.
>
> Consider using two cells in the phandle for register and bit offset
> instead of a single number that arbitrarily starts at 128.
Thanks for your feedback.
I would prefer using a single cell, which is less error prone in my opinion.
Will you accept this?
Kind regards,
Maxime
>
> regards
> Philipp
>
^ permalink raw reply
* Re: [PATCH v2 05/18] reset: Add reset_controller_of_init() function
From: Maxime Coquelin @ 2015-03-12 21:08 UTC (permalink / raw)
To: Rob Herring
Cc: Arnd Bergmann, Maxime Ripard, Uwe Kleine-König,
Andreas Färber, Geert Uytterhoeven, Rob Herring,
Philipp Zabel, Jonathan Corbet, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Russell King, Daniel Lezcano,
Thomas Gleixner, Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Andrew Morton, David S. Miller, Mauro Carvalho Chehab
In-Reply-To: <CAL_Jsq+_ridpAaUwpqo91xB6Ea1ctCWfYTYUrcZ=gB_0FiBD4g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-03-10 22:30 GMT+01:00 Rob Herring <robherring2-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:
> On Tue, Mar 10, 2015 at 3:19 PM, Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> wrote:
>> On Tuesday 10 March 2015 16:28:44 Maxime Coquelin wrote:
>>> 2015-03-10 16:00 GMT+01:00 Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>:
>>> > On Friday 20 February 2015 19:01:04 Maxime Coquelin wrote:
>>> >> Some platforms need to initialize the reset controller before the timers.
>>> >>
>>> >> This patch introduces a reset_controller_of_init() function that can be
>>> >> called before the timers intialization.
>>> >>
>>> >> Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>>> >>
>>> >
>>> > Not sure about this. It seems like the cleanest approach if we get
>>> > a lot of these, but then again it is probably very rare, and I'd
>>> > like to avoid adding such infrastructure if it's just for one
>>> > SoC. Could we add a hack in the machine initialization instead?
>>>
>>> Sun6i also need to initialize the reset controller early. Today, they
>>> hack the machine initialization.
>>> With two SoCs having the same need, what should we do?
>>
>> Good question, I'd like to hear some other opinions on this first.
>
> 2 is still far from the common case.
>
>>> > I think ideally this would be done in the boot loader before we
>>> > even start Linux, but I don't know if that's possible for you.
>>>
>>> From what I understand, the only constraint is to perform it after the
>>> clock is enabled.
>>> So this should be possible to do it in the bootloader, but it means
>>> also adding timers clocks ungating in the bootloader.
>>
>> Ungating the timer clock input seems like a reasonable thing to
>> do for the bootloader, I think a lot of platforms rely on this
>> elsewhere (but enough of them don't, which is why we have the
>> early clk init).
>
> +1
>
> If the bootloader is u-boot, then you need a timer anyway.
Ok, I moved it to the bootloader, and use the reset as optional in the
timer driver.
Thanks,
Maxime
>
> Rob
^ permalink raw reply
* Re: [RFC] capabilities: Ambient capabilities
From: Kees Cook @ 2015-03-12 21:49 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Christoph Lameter, Serge Hallyn, Andy Lutomirski, Jonathan Corbet,
Aaron Jones, Ted Ts'o, linux-security-module, LKML, Linux API,
akpm, Andrew G. Morgan, Mimi Zohar, Austin S Hemmelgarn,
Markku Savela, Jarkko Sakkinen, Michael Kerrisk
In-Reply-To: <933931146caf5dac58379f50c017bff9f6c47661.1426183417.git.luto@kernel.org>
On Thu, Mar 12, 2015 at 11:08 AM, Andy Lutomirski <luto@kernel.org> wrote:
> Credit where credit is due: this idea comes from Christoph Lameter
> with a lot of valuable input from Serge Hallyn. This patch is
> heavily based on Christoph's patch.
>
> ===== The status quo =====
>
> On Linux, there are a number of capabilities defined by the kernel.
> To perform various privileged tasks, processes can wield
> capabilities that they hold.
>
> Each task has four capability masks: effective (pE), permitted (pP),
> inheritable (pI), and a bounding set (X). When the kernel checks
> for a capability, it checks pE. The other capability masks serve to
> modify what capabilities can be in pE.
>
> Any task can remove capabilities from pE, pP, or pI at any time. If
> a task has a capability in pP, it can add that capability to pE
> and/or pI. If a task has CAP_SETPCAP, then it can add any
> capability to pI, and it can remove capabilities from X.
>
> Tasks are not the only things that can have capabilities; files can
> also have capabilities. A file can have no capabilty information at
> all [1]. If a file has capability information, then it has a
> permitted mask (fP) and an inheritable mask (fI) as well as a single
> effective bit (fE) [2]. File capabilities modify the capabilities
> of tasks that execve(2) them.
>
> A task that successfully calls execve has its capabilities modified
> for the file ultimately being excecuted (i.e. the binary itself if
> that binary is ELF or for the interpreter if the binary is a
> script.) [3] In the capability evolution rules, for each mask Z, pZ
> represents the old value and pZ' represents the new value. The
> rules are:
>
> pP' = (X & fP) | (pI & fI)
> pI' = pI
> pE' = (fE ? pP' : 0)
> X is unchanged
>
> For setuid binaries, fP, fI, and fE are modified by a moderately
> complicated set of rules that emulate POSIX behavior. Similarly, if
> euid == 0 or ruid == 0, then fP, fI, and fE are modified differently
> (primary, fP and fI usually end up being the full set). For nonroot
> users executing binaries with neither setuid nor file caps, fI and
> fP are empty and fE is false.
>
> As an extra complication, if you execute a process as nonroot and fE
> is set, then the "secure exec" rules are in effect: AT_SECURE gets
> set, LD_PRELOAD doesn't work, etc.
>
> This is rather messy. We've learned that making any changes is
> dangerous, though: if a new kernel version allows an unprivileged
> program to change its security state in a way that persists cross
> execution of a setuid program or a program with file caps, this
> persistent state is surprisingly likely to allow setuid or
> file-capped programs to be exploited for privilege escalation.
>
> ===== The problem =====
>
> Capability inheritance is basically useless.
>
> If you aren't root and you execute an ordinary binary, fI is zero,
> so your capabilities have no effect whatsoever on pP'. This means
> that you can't usefully execute a helper process or a shell command
> with elevated capabilities if you aren't root.
>
> On current kernels, you can sort of work around this by setting fI
> to the full set for most or all non-setuid executable files. This
> causes pP' = pI for nonroot, and inheritance works. No one does
> this because it's a PITA and it isn't even supported on most
> filesystems.
>
> If you try this, you'll discover that every nonroot program ends up
> with secure exec rules, breaking many things.
>
> This is a problem that has bitten many people who have tried to use
> capabilities for anything useful.
>
> ===== The proposed change =====
>
> This patch adds a fifth capability mask called the ambient mask
> (pA). pA does what pI should have done.
>
> pA obeys the invariant that no bit can ever be set in pA if it is
> not set in both pP and pI. Dropping a bit from pP or pI drops that
> bit from pA. This ensures that existing programs that try to drop
> capabilities still do so, with a complication. Because capability
> inheritance is so broken, setting KEEPCAPS, using setresuid to
> switch to nonroot uids, and calling execve effectively drops
> capabilities. Therefore, setresuid from root to nonroot
> unconditionally clears pA. Processes that don't like this can
> re-add bits to pA afterwards.
>
> The capability evolution rules are changed:
>
> pA' = (file caps or setuid or setgid ? 0 : pA)
> pP' = (X & fP) | (pI & fI) | pA'
> pI' = pI
> pE' = (fE ? pP' : pA')
> X is unchanged
>
> If you are nonroot but you have a capability, you can add it to pA.
> If you do so, your children get that capability in pA, pP, and pE.
> For example, you can set pA = CAP_NET_BIND_SERVICE, and your
> children can automatically bind low-numbered ports. Hallelujah!
>
> Unprivileged users can create user namespaces, map themselves to a
> nonzero uid, and create both privileged (relative to their
> namespace) and unprivileged process trees. This is currently more
> or less impossible. Hallelujah!
>
> You cannot use pA to try to subvert a setuid, setgid, or file-capped
> program: if you execute any such program, pA gets cleared and the
> resulting evolution rules are unchanged by this patch.
>
> Users with nonzero pA are unlikely to unintentionally leak that
> capability. If they run programs that try to drop privileges,
> dropping privileges will still work.
>
> It's worth noting that the degree of paranoia in this patch could
> possibly be relaxed without causing serious problems. Specifically,
> if we allowed pA to persist across executing non-pA-aware setuid
> binaries and across setresuid, then, naively, the only capabilities
> that could leak as a result would be the capabilities in pA, and any
> attacker *already* has those capabilities. This would make me
> nervous, though -- setuid binaries that tried to privilege-separate
> might fail to do so, and putting CAP_DAC_READ_SEARCH or
> CAP_DAC_OVERRIDE into pA could have unexpected side effects.
> (Whether these unexpected side effects would be exploitable is an
> open question.) I've therefore taken the more paranoid route.
>
> An alternative would be to either require PR_SET_NO_NEW_PRIVS before
> setting ambient capabilities. I think that this would be annoying
> and would make granting otherwise unprivileged users minor ambient
> capabilities (CAP_NET_BIND_SERVICE or CAP_NET_RAW for example) much
> less useful than it is with this patch.
>
> ===== Footnotes =====
>
> [1] Files that are missing the "security.capability" xattr or that
> have unrecognized values for that xattr end up with has_cap ==
> false. The code that does that appears to be complicated for no
> good reason.
>
> [2] The libcap capability mask parsers and formatters are
> dangerously misleading and the documentation is flat-out wrong. fE
> is *not* a mask; it's a single bit. This has probably confused
> every single person who has tried to use file capabilities.
>
> [3] Linux very confusingly processes the script and the interpreter if
> applicable, for reasons that escape me. The results from thinking
> about a script's file capabilities and/or setuid bits are mostly discarded.
>
> Cc: Kees Cook <keescook@chromium.org>
> Cc: Christoph Lameter <cl@linux.com>
> Cc: Serge Hallyn <serge.hallyn@canonical.com>
> Cc: Andy Lutomirski <luto@amacapital.net>
> Cc: Jonathan Corbet <corbet@lwn.net>
> Cc: Aaron Jones <aaronmdjones@gmail.com>
> CC: Ted Ts'o <tytso@mit.edu>
> Cc: linux-security-module@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-api@vger.kernel.org
> Cc: akpm@linuxfoundation.org
> Cc: Andrew G. Morgan <morgan@kernel.org>
> Cc: Mimi Zohar <zohar@linux.vnet.ibm.com>
> Cc: Austin S Hemmelgarn <ahferroin7@gmail.com>
> Cc: Markku Savela <msa@moth.iki.fi>
> Cc: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> Cc: Michael Kerrisk <mtk.manpages@gmail.com>
> Signed-off-by: Andy Lutomirski <luto@kernel.org>
This would be quite welcome for things we're doing in Chrome OS.
Presently, we're able to use fscaps to keep non-root caps across exec
and haven't encountered issues with AT_SECURE (yet), but using pA
would be much nicer and exactly matches how we want to use it: a
launcher is creating a tree of processes that are non-root but need
some capabilities. Right now the tree is very small and we're able to
sprinkle our fscaps lightly. :) This would be better.
-Kees
> ---
>
> Preliminary userspace code is here:
>
> https://git.kernel.org/cgit/linux/kernel/git/luto/util-linux-playground.git/commit/?h=cap_ambient&id=860c73ac1acaaae976bdd3bb83b89b0180f0702a
>
> fs/proc/array.c | 5 ++-
> include/linux/cred.h | 15 +++++++++
> include/uapi/linux/prctl.h | 6 ++++
> kernel/user_namespace.c | 1 +
> security/commoncap.c | 75 ++++++++++++++++++++++++++++++++++++++------
> security/keys/process_keys.c | 1 +
> 6 files changed, 92 insertions(+), 11 deletions(-)
>
> diff --git a/fs/proc/array.c b/fs/proc/array.c
> index 1295a00ca316..bc15356d6551 100644
> --- a/fs/proc/array.c
> +++ b/fs/proc/array.c
> @@ -282,7 +282,8 @@ static void render_cap_t(struct seq_file *m, const char *header,
> static inline void task_cap(struct seq_file *m, struct task_struct *p)
> {
> const struct cred *cred;
> - kernel_cap_t cap_inheritable, cap_permitted, cap_effective, cap_bset;
> + kernel_cap_t cap_inheritable, cap_permitted, cap_effective,
> + cap_bset, cap_ambient;
>
> rcu_read_lock();
> cred = __task_cred(p);
> @@ -290,12 +291,14 @@ static inline void task_cap(struct seq_file *m, struct task_struct *p)
> cap_permitted = cred->cap_permitted;
> cap_effective = cred->cap_effective;
> cap_bset = cred->cap_bset;
> + cap_ambient = cred->cap_ambient;
> rcu_read_unlock();
>
> render_cap_t(m, "CapInh:\t", &cap_inheritable);
> render_cap_t(m, "CapPrm:\t", &cap_permitted);
> render_cap_t(m, "CapEff:\t", &cap_effective);
> render_cap_t(m, "CapBnd:\t", &cap_bset);
> + render_cap_t(m, "CapAmb:\t", &cap_ambient);
> }
>
> static inline void task_seccomp(struct seq_file *m, struct task_struct *p)
> diff --git a/include/linux/cred.h b/include/linux/cred.h
> index 2fb2ca2127ed..a21bcba6ef84 100644
> --- a/include/linux/cred.h
> +++ b/include/linux/cred.h
> @@ -122,6 +122,7 @@ struct cred {
> kernel_cap_t cap_permitted; /* caps we're permitted */
> kernel_cap_t cap_effective; /* caps we can actually use */
> kernel_cap_t cap_bset; /* capability bounding set */
> + kernel_cap_t cap_ambient; /* Ambient capability set */
> #ifdef CONFIG_KEYS
> unsigned char jit_keyring; /* default keyring to attach requested
> * keys to */
> @@ -197,6 +198,20 @@ static inline void validate_process_creds(void)
> }
> #endif
>
> +static inline void cap_enforce_ambient_invariants(struct cred *cred)
> +{
> + cred->cap_ambient = cap_intersect(cred->cap_ambient,
> + cap_intersect(cred->cap_permitted,
> + cred->cap_inheritable));
> +}
> +
> +static inline bool cap_ambient_invariant_ok(const struct cred *cred)
> +{
> + return cap_issubset(cred->cap_ambient,
> + cap_intersect(cred->cap_permitted,
> + cred->cap_inheritable));
> +}
> +
> /**
> * get_new_cred - Get a reference on a new set of credentials
> * @cred: The new credentials to reference
> diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
> index 31891d9535e2..65407f867e82 100644
> --- a/include/uapi/linux/prctl.h
> +++ b/include/uapi/linux/prctl.h
> @@ -190,4 +190,10 @@ struct prctl_mm_map {
> # define PR_FP_MODE_FR (1 << 0) /* 64b FP registers */
> # define PR_FP_MODE_FRE (1 << 1) /* 32b compatibility */
>
> +/* Control the ambient capability set */
> +#define PR_CAP_AMBIENT 47
> +# define PR_CAP_AMBIENT_GET 1
> +# define PR_CAP_AMBIENT_RAISE 2
> +# define PR_CAP_AMBIENT_LOWER 3
> +
> #endif /* _LINUX_PRCTL_H */
> diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
> index 4109f8320684..dab0f808235a 100644
> --- a/kernel/user_namespace.c
> +++ b/kernel/user_namespace.c
> @@ -39,6 +39,7 @@ static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns)
> cred->cap_inheritable = CAP_EMPTY_SET;
> cred->cap_permitted = CAP_FULL_SET;
> cred->cap_effective = CAP_FULL_SET;
> + cred->cap_ambient = CAP_EMPTY_SET;
> cred->cap_bset = CAP_FULL_SET;
> #ifdef CONFIG_KEYS
> key_put(cred->request_key_auth);
> diff --git a/security/commoncap.c b/security/commoncap.c
> index f66713bd7450..b3253886ecad 100644
> --- a/security/commoncap.c
> +++ b/security/commoncap.c
> @@ -272,6 +272,7 @@ int cap_capset(struct cred *new,
> new->cap_effective = *effective;
> new->cap_inheritable = *inheritable;
> new->cap_permitted = *permitted;
> + cap_enforce_ambient_invariants(new);
> return 0;
> }
>
> @@ -352,6 +353,7 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
>
> /*
> * pP' = (X & fP) | (pI & fI)
> + * The addition of pA' is handled later.
> */
> new->cap_permitted.cap[i] =
> (new->cap_bset.cap[i] & permitted) |
> @@ -479,10 +481,12 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
> {
> const struct cred *old = current_cred();
> struct cred *new = bprm->cred;
> - bool effective, has_cap = false;
> + bool effective, has_cap = false, is_setid;
> int ret;
> kuid_t root_uid;
>
> + BUG_ON(!cap_ambient_invariant_ok(old));
> +
> effective = false;
> ret = get_file_caps(bprm, &effective, &has_cap);
> if (ret < 0)
> @@ -527,8 +531,9 @@ skip:
> *
> * In addition, if NO_NEW_PRIVS, then ensure we get no new privs.
> */
> - if ((!uid_eq(new->euid, old->uid) ||
> - !gid_eq(new->egid, old->gid) ||
> + is_setid = !uid_eq(new->euid, old->uid) || !gid_eq(new->egid, old->gid);
> +
> + if ((is_setid ||
> !cap_issubset(new->cap_permitted, old->cap_permitted)) &&
> bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
> /* downgrade; they get no more than they had, and maybe less */
> @@ -544,10 +549,23 @@ skip:
> new->suid = new->fsuid = new->euid;
> new->sgid = new->fsgid = new->egid;
>
> + /* File caps or setid cancel ambient. */
> + if (has_cap || is_setid)
> + cap_clear(new->cap_ambient);
> +
> + /*
> + * Now that we've computed pA', update pP' to give:
> + * pP' = (X & fP) | (pI & fI) | pA'
> + */
> + new->cap_permitted = cap_combine(new->cap_permitted, new->cap_ambient);
> +
> if (effective)
> new->cap_effective = new->cap_permitted;
> else
> - cap_clear(new->cap_effective);
> + new->cap_effective = new->cap_ambient;
> +
> + BUG_ON(!cap_ambient_invariant_ok(new));
> +
> bprm->cap_effective = effective;
>
> /*
> @@ -562,7 +580,7 @@ skip:
> * Number 1 above might fail if you don't have a full bset, but I think
> * that is interesting information to audit.
> */
> - if (!cap_isclear(new->cap_effective)) {
> + if (!cap_issubset(new->cap_effective, new->cap_ambient)) {
> if (!cap_issubset(CAP_FULL_SET, new->cap_effective) ||
> !uid_eq(new->euid, root_uid) || !uid_eq(new->uid, root_uid) ||
> issecure(SECURE_NOROOT)) {
> @@ -573,6 +591,9 @@ skip:
> }
>
> new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
> +
> + BUG_ON(!cap_ambient_invariant_ok(new));
> +
> return 0;
> }
>
> @@ -594,7 +615,7 @@ int cap_bprm_secureexec(struct linux_binprm *bprm)
> if (!uid_eq(cred->uid, root_uid)) {
> if (bprm->cap_effective)
> return 1;
> - if (!cap_isclear(cred->cap_permitted))
> + if (!cap_issubset(cred->cap_permitted, cred->cap_ambient))
> return 1;
> }
>
> @@ -696,10 +717,18 @@ static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old)
> uid_eq(old->suid, root_uid)) &&
> (!uid_eq(new->uid, root_uid) &&
> !uid_eq(new->euid, root_uid) &&
> - !uid_eq(new->suid, root_uid)) &&
> - !issecure(SECURE_KEEP_CAPS)) {
> - cap_clear(new->cap_permitted);
> - cap_clear(new->cap_effective);
> + !uid_eq(new->suid, root_uid))) {
> + if (!issecure(SECURE_KEEP_CAPS)) {
> + cap_clear(new->cap_permitted);
> + cap_clear(new->cap_effective);
> + }
> +
> + /*
> + * Pre-ambient programs except setresuid to nonroot followed
> + * by exec to drop capabilities. We should make sure that
> + * this remains the case.
> + */
> + cap_clear(new->cap_ambient);
> }
> if (uid_eq(old->euid, root_uid) && !uid_eq(new->euid, root_uid))
> cap_clear(new->cap_effective);
> @@ -929,6 +958,32 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
> new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
> return commit_creds(new);
>
> + case PR_CAP_AMBIENT:
> + if (((!cap_valid(arg3)) | arg4 | arg5))
> + return -EINVAL;
> +
> + if (arg2 == PR_CAP_AMBIENT_GET) {
> + return !!cap_raised(current_cred()->cap_ambient, arg3);
> + } else if (arg2 != PR_CAP_AMBIENT_RAISE &&
> + arg2 != PR_CAP_AMBIENT_LOWER) {
> + return -EINVAL;
> + } else {
> + if (arg2 == PR_CAP_AMBIENT_RAISE &&
> + (!cap_raised(current_cred()->cap_permitted, arg3) ||
> + !cap_raised(current_cred()->cap_inheritable,
> + arg3)))
> + return -EPERM;
> +
> + new = prepare_creds();
> + if (!new)
> + return -ENOMEM;
> + if (arg2 == PR_CAP_AMBIENT_RAISE)
> + cap_raise(new->cap_ambient, arg3);
> + else
> + cap_lower(new->cap_ambient, arg3);
> + return commit_creds(new);
> + }
> +
> default:
> /* No functionality available - continue with default */
> return -ENOSYS;
> diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
> index bd536cb221e2..43b4cddbf2b3 100644
> --- a/security/keys/process_keys.c
> +++ b/security/keys/process_keys.c
> @@ -848,6 +848,7 @@ void key_change_session_keyring(struct callback_head *twork)
> new->cap_inheritable = old->cap_inheritable;
> new->cap_permitted = old->cap_permitted;
> new->cap_effective = old->cap_effective;
> + new->cap_ambient = old->cap_ambient;
> new->cap_bset = old->cap_bset;
>
> new->jit_keyring = old->jit_keyring;
> --
> 2.3.0
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
--
Kees Cook
Chrome OS Security
^ permalink raw reply
* [PATCH v3 00/15] Add support to STMicroelectronics STM32 family
From: Maxime Coquelin @ 2015-03-12 21:55 UTC (permalink / raw)
To: u.kleine-koenig, afaerber, geert, Rob Herring, Philipp Zabel,
Linus Walleij, Arnd Bergmann, stefan, pmeerw, pebolle
Cc: Jonathan Corbet, Pawel Moll, Mark Rutland, Ian Campbell,
Kumar Gala, Russell King, Daniel Lezcano, Thomas Gleixner,
Greg Kroah-Hartman, Jiri Slaby, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will Deacon, Nikolay Borisov, Rusty Russell, Kees Cook,
Michal Marek, linux-doc, linux-arm-kernel, linux-kernel
From: Maxime Coquelin <mcoquelin.stm32@gmail.com>
This third round tries to address most of the comments made on previous series.
It contains few less patches, as the reset_controller_of_init() patch has been
removed, now that the bootlaoder handles the reset of the timers.
The pinctrl driver has also been removed after Linus review.
It will be reworked to use the generic pinconf bindings, and may contain
changes for other machines (Mediatek), to add support for pinmux property
handling directly in pinconf-generic.
STM32 MCUs are Cortex-M CPU, used in various applications (consumer
electronics, industrial applications, hobbyists...).
Datasheets, user and programming manuals are publicly available on
STMicroelectronics website.
With this series applied, the STM32F419 Discovery can boot succesfully.
Changes since v2:
-----------------
- Remove pinctrl driver from the series.
- Remove reset_controller_of_init(), and reset the timers in the bootloader
- Add HW flow contrl property for serial driver
- Lots of changes in the DTS file, as per Andreas recommendations
- Some Kconfig clean-ups
- Adapt the config to be compatible with Andreas' bootwrapper, except UART port.
- Various fixes in documentation
Changes since v1:
-----------------
- Move bindings documentation in their own patches (Andreas)
- Rename ARM System timer to armv7m-systick (Rob)
- Add clock-frequency property handling in armv7m-systick (Rob)
- Re-factor the reset controllers into a single controller (Philipp)
- Add kerneldoc to reset_controller_of_init (Philipp)
- Add named constants in include/dt-bindings/reset/ (Philipp)
- Make pinctrl driver to depend on ARCH_STM32 or COMPILE_TEST (Geert)
- Introduce CPUV7M_NUM_IRQ config flag to indicate the number of interrupts
supported by the MCU, in order to limit memory waste in vectors' table (Uwe)
Maxime Coquelin (15):
scripts: link-vmlinux: Don't pass page offset to kallsyms if XIP
Kernel
ARM: ARMv7-M: Enlarge vector table up to 256 entries
dt-bindings: Document the ARM System timer bindings
clocksource: Add ARM System timer driver
dt-bindings: Document the STM32 reset bindings
drivers: reset: Add STM32 reset driver
dt-bindings: Document the STM32 timer bindings
clockevent: Add STM32 Timer driver
dt-bindings: Document the STM32 USART bindings
serial: stm32-usart: Add STM32 USART Driver
ARM: Add STM32 family machine
ARM: dts: Add ARM System timer as clockevent in armv7m
ARM: dts: Introduce STM32F429 MCU
ARM: configs: Add STM32 defconfig
MAINTAINERS: Add entry for STM32 MCUs
Documentation/arm/stm32/overview.txt | 32 +
Documentation/arm/stm32/stm32f429-overview.txt | 22 +
.../devicetree/bindings/arm/armv7m_systick.txt | 26 +
.../devicetree/bindings/reset/st,stm32-rcc.txt | 102 +++
.../devicetree/bindings/serial/st,stm32-usart.txt | 32 +
.../devicetree/bindings/timer/st,stm32-timer.txt | 22 +
MAINTAINERS | 8 +
arch/arm/Kconfig | 18 +
arch/arm/Makefile | 1 +
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/armv7-m.dtsi | 6 +
arch/arm/boot/dts/stm32f429-disco.dts | 71 +++
arch/arm/boot/dts/stm32f429.dtsi | 226 +++++++
arch/arm/configs/stm32_defconfig | 71 +++
arch/arm/kernel/entry-v7m.S | 13 +-
arch/arm/mach-stm32/Makefile | 1 +
arch/arm/mach-stm32/Makefile.boot | 3 +
arch/arm/mach-stm32/board-dt.c | 19 +
arch/arm/mm/Kconfig | 15 +
drivers/clocksource/Kconfig | 15 +
drivers/clocksource/Makefile | 2 +
drivers/clocksource/armv7m_systick.c | 78 +++
drivers/clocksource/timer-stm32.c | 184 ++++++
drivers/reset/Makefile | 1 +
drivers/reset/reset-stm32.c | 125 ++++
drivers/tty/serial/Kconfig | 17 +
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/stm32-usart.c | 695 +++++++++++++++++++++
include/uapi/linux/serial_core.h | 3 +
scripts/link-vmlinux.sh | 2 +-
30 files changed, 1807 insertions(+), 5 deletions(-)
create mode 100644 Documentation/arm/stm32/overview.txt
create mode 100644 Documentation/arm/stm32/stm32f429-overview.txt
create mode 100644 Documentation/devicetree/bindings/arm/armv7m_systick.txt
create mode 100644 Documentation/devicetree/bindings/reset/st,stm32-rcc.txt
create mode 100644 Documentation/devicetree/bindings/serial/st,stm32-usart.txt
create mode 100644 Documentation/devicetree/bindings/timer/st,stm32-timer.txt
create mode 100644 arch/arm/boot/dts/stm32f429-disco.dts
create mode 100644 arch/arm/boot/dts/stm32f429.dtsi
create mode 100644 arch/arm/configs/stm32_defconfig
create mode 100644 arch/arm/mach-stm32/Makefile
create mode 100644 arch/arm/mach-stm32/Makefile.boot
create mode 100644 arch/arm/mach-stm32/board-dt.c
create mode 100644 drivers/clocksource/armv7m_systick.c
create mode 100644 drivers/clocksource/timer-stm32.c
create mode 100644 drivers/reset/reset-stm32.c
create mode 100644 drivers/tty/serial/stm32-usart.c
--
1.9.1
^ permalink raw reply
* [PATCH v3 01/15] scripts: link-vmlinux: Don't pass page offset to kallsyms if XIP Kernel
From: Maxime Coquelin @ 2015-03-12 21:55 UTC (permalink / raw)
To: u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ, afaerber-l3A5Bk7waGM,
geert-Td1EMuHUCqxL1ZNQvxDV9g, Rob Herring, Philipp Zabel,
Linus Walleij, Arnd Bergmann, stefan-XLVq0VzYD2Y,
pmeerw-jW+XmwGofnusTnJN9+BGXg, pebolle-IWqWACnzNjzz+pZb47iToQ
Cc: Jonathan Corbet, Pawel Moll, Mark Rutland, Ian Campbell,
Kumar Gala, Russell King, Daniel Lezcano, Thomas Gleixner,
Greg Kroah-Hartman, Jiri Slaby, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will Deacon, Nikolay Borisov, Rusty Russell, Kees Cook,
Michal Marek, linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TZNg+MwTxZMZA
In-Reply-To: <1426197361-19290-1-git-send-email-maxime.coquelin-qxv4g6HH51o@public.gmane.org>
From: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
When Kernel is executed in place from ROM, the symbol addresses can be
lower than the page offset.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
scripts/link-vmlinux.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 86a4fe7..b055d9d 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -82,7 +82,7 @@ kallsyms()
kallsymopt="${kallsymopt} --all-symbols"
fi
- if [ -n "${CONFIG_ARM}" ] && [ -n "${CONFIG_PAGE_OFFSET}" ]; then
+ if [ -n "${CONFIG_ARM}" ] && [ -z "${CONFIG_XIP_KERNEL}" ] && [ -n "${CONFIG_PAGE_OFFSET}" ]; then
kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
fi
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v3 02/15] ARM: ARMv7-M: Enlarge vector table up to 256 entries
From: Maxime Coquelin @ 2015-03-12 21:55 UTC (permalink / raw)
To: u.kleine-koenig, afaerber, geert, Rob Herring, Philipp Zabel,
Linus Walleij, Arnd Bergmann, stefan, pmeerw, pebolle
Cc: Mark Rutland, linux-doc, Will Deacon, Nikolay Borisov, linux-api,
Jiri Slaby, Mauro Carvalho Chehab, linux-arch, Russell King,
Jonathan Corbet, Daniel Lezcano, Antti Palosaari, linux-serial,
devicetree, Kees Cook, Pawel Moll, Ian Campbell, Rusty Russell,
Joe Perches, Thomas Gleixner, linux-arm-kernel, Michal Marek,
linux-gpio, Greg Kroah-Hartman, linux-kernel, mco
In-Reply-To: <1426197361-19290-1-git-send-email-maxime.coquelin@st.com>
From: Maxime Coquelin <mcoquelin.stm32@gmail.com>
From Cortex-M reference manuals, the nvic supports up to 240 interrupts.
So the number of entries in vectors table is up to 256.
This patch adds a new config flag to specify the number of external interrupts.
Some ifdeferies are added in order to respect the natural alignment without
wasting too much space on smaller systems.
Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Acked-by: Stefan Agner <stefan@agner.ch>
Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
---
arch/arm/kernel/entry-v7m.S | 13 +++++++++----
arch/arm/mm/Kconfig | 15 +++++++++++++++
2 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/arch/arm/kernel/entry-v7m.S b/arch/arm/kernel/entry-v7m.S
index 8944f49..b6c8bb9 100644
--- a/arch/arm/kernel/entry-v7m.S
+++ b/arch/arm/kernel/entry-v7m.S
@@ -117,9 +117,14 @@ ENTRY(__switch_to)
ENDPROC(__switch_to)
.data
- .align 8
+#if CONFIG_CPU_V7M_NUM_IRQ <= 112
+ .align 9
+#else
+ .align 10
+#endif
+
/*
- * Vector table (64 words => 256 bytes natural alignment)
+ * Vector table (Natural alignment need to be ensured)
*/
ENTRY(vector_table)
.long 0 @ 0 - Reset stack pointer
@@ -138,6 +143,6 @@ ENTRY(vector_table)
.long __invalid_entry @ 13 - Reserved
.long __pendsv_entry @ 14 - PendSV
.long __invalid_entry @ 15 - SysTick
- .rept 64 - 16
- .long __irq_entry @ 16..64 - External Interrupts
+ .rept CONFIG_CPU_V7M_NUM_IRQ
+ .long __irq_entry @ External Interrupts
.endr
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 9b4f29e..aec53b4 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -604,6 +604,21 @@ config CPU_USE_DOMAINS
This option enables or disables the use of domain switching
via the set_fs() function.
+config CPU_V7M_NUM_IRQ
+ int "Number of external interrupts connected to the NVIC"
+ depends on CPU_V7M
+ default 90 if ARCH_STM32
+ default 38 if ARCH_EFM32
+ default 240
+ help
+ This option indicates the number of interrupts connected to the NVIC.
+ The value can be larger than the real number of interrupts supported
+ by the system, but must not be lower.
+ The default value is 240, corresponding to the maximum number of
+ interrupts supported by the NVIC on Cortex-M family.
+
+ If unsure, keep default value.
+
#
# CPU supports 36-bit I/O
#
--
1.9.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 03/15] dt-bindings: Document the ARM System timer bindings
From: Maxime Coquelin @ 2015-03-12 21:55 UTC (permalink / raw)
To: u.kleine-koenig, afaerber, geert, Rob Herring, Philipp Zabel,
Linus Walleij, Arnd Bergmann, stefan, pmeerw, pebolle
Cc: Jonathan Corbet, Pawel Moll, Mark Rutland, Ian Campbell,
Kumar Gala, Russell King, Daniel Lezcano, Thomas Gleixner,
Greg Kroah-Hartman, Jiri Slaby, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will Deacon, Nikolay Borisov, Rusty Russell, Kees Cook,
Michal Marek, linux-doc, linux-arm-kernel, linux-kernel
In-Reply-To: <1426197361-19290-1-git-send-email-maxime.coquelin@st.com>
From: Maxime Coquelin <mcoquelin.stm32@gmail.com>
This adds documentation of device tree bindings for the
ARM System timer.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
---
.../devicetree/bindings/arm/armv7m_systick.txt | 26 ++++++++++++++++++++++
1 file changed, 26 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/armv7m_systick.txt
diff --git a/Documentation/devicetree/bindings/arm/armv7m_systick.txt b/Documentation/devicetree/bindings/arm/armv7m_systick.txt
new file mode 100644
index 0000000..7cf4a24
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/armv7m_systick.txt
@@ -0,0 +1,26 @@
+* ARMv7M System Timer
+
+ARMv7-M includes a system timer, known as SysTick. Current driver only
+implements the clocksource feature.
+
+Required properties:
+- compatible : Should be "arm,armv7m-systick"
+- reg : The address range of the timer
+
+Required clocking property, have to be one of:
+- clocks : The input clock of the timer
+- clock-frequency : The rate in HZ in input of the ARM SysTick
+
+Examples:
+
+systick: timer@e000e010 {
+ compatible = "arm,armv7m-systick";
+ reg = <0xe000e010 0x10>;
+ clocks = <&clk_systick>;
+};
+
+systick: timer@e000e010 {
+ compatible = "arm,armv7m-systick";
+ reg = <0xe000e010 0x10>;
+ clock-frequency = <90000000>;
+};
--
1.9.1
^ permalink raw reply related
* [PATCH v3 04/15] clocksource: Add ARM System timer driver
From: Maxime Coquelin @ 2015-03-12 21:55 UTC (permalink / raw)
To: u.kleine-koenig, afaerber, geert, Rob Herring, Philipp Zabel,
Linus Walleij, Arnd Bergmann, stefan, pmeerw, pebolle
Cc: Jonathan Corbet, Pawel Moll, Mark Rutland, Ian Campbell,
Kumar Gala, Russell King, Daniel Lezcano, Thomas Gleixner,
Greg Kroah-Hartman, Jiri Slaby, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will Deacon, Nikolay Borisov, Rusty Russell, Kees Cook,
Michal Marek, linux-doc, linux-arm-kernel, linux-kernel
In-Reply-To: <1426197361-19290-1-git-send-email-maxime.coquelin@st.com>
From: Maxime Coquelin <mcoquelin.stm32@gmail.com>
This patch adds clocksource support for ARMv7-M's System timer,
also known as SysTick.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
---
drivers/clocksource/Kconfig | 7 ++++
drivers/clocksource/Makefile | 1 +
drivers/clocksource/armv7m_systick.c | 78 ++++++++++++++++++++++++++++++++++++
3 files changed, 86 insertions(+)
create mode 100644 drivers/clocksource/armv7m_systick.c
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 1c2506f..b82e58b 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -134,6 +134,13 @@ config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
help
Use ARM global timer clock source as sched_clock
+config ARMV7M_SYSTICK
+ bool
+ select CLKSRC_OF if OF
+ select CLKSRC_MMIO
+ help
+ This options enables support for the ARMv7M system timer unit
+
config ATMEL_PIT
select CLKSRC_OF if OF
def_bool SOC_AT91SAM9 || SOC_SAMA5
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 752d5c7..1c9a643 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_MTK_TIMER) += mtk_timer.o
obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o
+obj-$(CONFIG_ARMV7M_SYSTICK) += armv7m_systick.o
obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o
obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o
obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o
diff --git a/drivers/clocksource/armv7m_systick.c b/drivers/clocksource/armv7m_systick.c
new file mode 100644
index 0000000..23d8249
--- /dev/null
+++ b/drivers/clocksource/armv7m_systick.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk.h>
+#include <linux/bitops.h>
+
+#define SYST_CSR 0x00
+#define SYST_RVR 0x04
+#define SYST_CVR 0x08
+#define SYST_CALIB 0x0c
+
+#define SYST_CSR_ENABLE BIT(0)
+
+#define SYSTICK_LOAD_RELOAD_MASK 0x00FFFFFF
+
+static void __init system_timer_of_register(struct device_node *np)
+{
+ struct clk *clk;
+ void __iomem *base;
+ u32 rate = 0;
+ int ret;
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_warn("system-timer: invalid base address\n");
+ return;
+ }
+
+ clk = of_clk_get(np, 0);
+ if (!IS_ERR(clk)) {
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ clk_put(clk);
+ goto out_unmap;
+ }
+
+ rate = clk_get_rate(clk);
+ }
+
+ /* If no clock found, try to get clock-frequency property */
+ if (!rate) {
+ ret = of_property_read_u32(np, "clock-frequency", &rate);
+ if (ret)
+ goto out_unmap;
+ }
+
+ writel_relaxed(SYSTICK_LOAD_RELOAD_MASK, base + SYST_RVR);
+ writel_relaxed(SYST_CSR_ENABLE, base + SYST_CSR);
+
+ ret = clocksource_mmio_init(base + SYST_CVR, "arm_system_timer", rate,
+ 200, 24, clocksource_mmio_readl_down);
+ if (ret) {
+ pr_err("failed to init clocksource (%d)\n", ret);
+ goto out_clk_disable;
+ }
+
+ pr_info("ARM System timer initialized as clocksource\n");
+
+ return;
+
+out_clk_disable:
+ if (!IS_ERR(clk))
+ clk_disable_unprepare(clk);
+out_unmap:
+ iounmap(base);
+ WARN(ret, "ARM System timer register failed (%d)\n", ret);
+}
+
+CLOCKSOURCE_OF_DECLARE(arm_systick, "arm,armv7m-systick",
+ system_timer_of_register);
--
1.9.1
^ permalink raw reply related
* [PATCH v3 05/15] dt-bindings: Document the STM32 reset bindings
From: Maxime Coquelin @ 2015-03-12 21:55 UTC (permalink / raw)
To: u.kleine-koenig, afaerber, geert, Rob Herring, Philipp Zabel,
Linus Walleij, Arnd Bergmann, stefan, pmeerw, pebolle
Cc: Jonathan Corbet, Pawel Moll, Mark Rutland, Ian Campbell,
Kumar Gala, Russell King, Daniel Lezcano, Thomas Gleixner,
Greg Kroah-Hartman, Jiri Slaby, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will Deacon, Nikolay Borisov, Rusty Russell, Kees Cook,
Michal Marek, linux-doc, linux-arm-kernel, linux-kernel
In-Reply-To: <1426197361-19290-1-git-send-email-maxime.coquelin@st.com>
From: Maxime Coquelin <mcoquelin.stm32@gmail.com>
This adds documentation of device tree bindings for the
STM32 reset controller.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
---
.../devicetree/bindings/reset/st,stm32-rcc.txt | 102 +++++++++++++++++++++
1 file changed, 102 insertions(+)
create mode 100644 Documentation/devicetree/bindings/reset/st,stm32-rcc.txt
diff --git a/Documentation/devicetree/bindings/reset/st,stm32-rcc.txt b/Documentation/devicetree/bindings/reset/st,stm32-rcc.txt
new file mode 100644
index 0000000..962f961
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/st,stm32-rcc.txt
@@ -0,0 +1,102 @@
+STMicroelectronics STM32 Peripheral Reset Controller
+====================================================
+
+The RCC IP is both a reset and a clock controller. This documentation only
+document the reset part.
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "st,stm32-rcc"
+- reg: should be register base and length as documented in the
+ datasheet
+- #reset-cells: 1, see below
+
+example:
+
+rcc: reset@40023800 {
+ #reset-cells = <1>;
+ compatible = "st,stm32-rcc";
+ reg = <0x40023800 0x400>;
+};
+
+Specifying softreset control of devices
+=======================================
+
+Device nodes should specify the reset channel required in their "resets"
+property, containing a phandle to the reset device node and an index specifying
+which channel to use.
+
+example:
+
+ timer2 {
+ resets = <&rcc 256>;
+ };
+
+List of indexes for STM32F429:
+ - gpioa: 128
+ - gpiob: 129
+ - gpioc: 130
+ - gpiod: 131
+ - gpioe: 132
+ - gpiof: 133
+ - gpiog: 134
+ - gpioh: 135
+ - gpioi: 136
+ - gpioj: 137
+ - gpiok: 138
+ - crc: 140
+ - dma1: 149
+ - dma2: 150
+ - dma2d: 151
+ - ethmac: 153
+ - otghs: 157
+ - dcmi: 160
+ - cryp: 164
+ - hash: 165
+ - rng: 166
+ - otgfs: 167
+ - fmc: 192
+ - tim2: 256
+ - tim3: 257
+ - tim4: 258
+ - tim5: 259
+ - tim6: 260
+ - tim7: 261
+ - tim12: 262
+ - tim13: 263
+ - tim14: 264
+ - wwdg: 267
+ - spi2: 270
+ - spi3: 271
+ - uart2: 273
+ - uart3: 274
+ - uart4: 275
+ - uart5: 276
+ - i2c1: 277
+ - i2c2: 278
+ - i2c3: 279
+ - can1: 281
+ - can2: 282
+ - pwr: 284
+ - dac: 285
+ - uart7: 286
+ - uart8: 287
+ - tim1: 288
+ - tim8: 289
+ - usart1: 292
+ - usart6: 293
+ - adc: 296
+ - sdio: 299
+ - spi1: 300
+ - spi4: 301
+ - syscfg: 302
+ - tim9: 304
+ - tim10: 305
+ - tim11: 306
+ - spi5: 308
+ - spi6: 309
+ - sai1: 310
+ - ltdc: 31
+
--
1.9.1
^ permalink raw reply related
* [PATCH v3 06/15] drivers: reset: Add STM32 reset driver
From: Maxime Coquelin @ 2015-03-12 21:55 UTC (permalink / raw)
To: u.kleine-koenig, afaerber, geert, Rob Herring, Philipp Zabel,
Linus Walleij, Arnd Bergmann, stefan, pmeerw, pebolle
Cc: Jonathan Corbet, Pawel Moll, Mark Rutland, Ian Campbell,
Kumar Gala, Russell King, Daniel Lezcano, Thomas Gleixner,
Greg Kroah-Hartman, Jiri Slaby, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will Deacon, Nikolay Borisov, Rusty Russell, Kees Cook,
Michal Marek, linux-doc, linux-arm-kernel, linux-kernel
In-Reply-To: <1426197361-19290-1-git-send-email-maxime.coquelin@st.com>
From: Maxime Coquelin <mcoquelin.stm32@gmail.com>
The STM32 MCUs family IP can be reset by accessing some shared registers.
The specificity is that some reset lines are used by the timers.
At timer initialization time, the timer has to be reset, that's why
we cannot use a regular driver.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
---
drivers/reset/Makefile | 1 +
drivers/reset/reset-stm32.c | 125 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 126 insertions(+)
create mode 100644 drivers/reset/reset-stm32.c
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 157d421..aed12d1 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_RESET_CONTROLLER) += core.o
obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
+obj-$(CONFIG_ARCH_STM32) += reset-stm32.o
obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
obj-$(CONFIG_ARCH_STI) += sti/
diff --git a/drivers/reset/reset-stm32.c b/drivers/reset/reset-stm32.c
new file mode 100644
index 0000000..0d389b1
--- /dev/null
+++ b/drivers/reset/reset-stm32.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Heavily based on sunxi driver from Maxime Ripard.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+struct stm32_reset_data {
+ spinlock_t lock;
+ void __iomem *membase;
+ struct reset_controller_dev rcdev;
+};
+
+static int stm32_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct stm32_reset_data *data = container_of(rcdev,
+ struct stm32_reset_data,
+ rcdev);
+ int bank = id / BITS_PER_LONG;
+ int offset = id % BITS_PER_LONG;
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&data->lock, flags);
+
+ reg = readl_relaxed(data->membase + (bank * 4));
+ writel_relaxed(reg | BIT(offset), data->membase + (bank * 4));
+
+ spin_unlock_irqrestore(&data->lock, flags);
+
+ return 0;
+}
+
+static int stm32_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct stm32_reset_data *data = container_of(rcdev,
+ struct stm32_reset_data,
+ rcdev);
+ int bank = id / BITS_PER_LONG;
+ int offset = id % BITS_PER_LONG;
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&data->lock, flags);
+
+ reg = readl_relaxed(data->membase + (bank * 4));
+ writel_relaxed(reg & ~BIT(offset), data->membase + (bank * 4));
+
+ spin_unlock_irqrestore(&data->lock, flags);
+
+ return 0;
+}
+
+static struct reset_control_ops stm32_reset_ops = {
+ .assert = stm32_reset_assert,
+ .deassert = stm32_reset_deassert,
+};
+
+static const struct of_device_id stm32_reset_dt_ids[] = {
+ { .compatible = "st,stm32-rcc", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, sstm32_reset_dt_ids);
+
+static int stm32_reset_probe(struct platform_device *pdev)
+{
+ struct stm32_reset_data *data;
+ struct resource *res;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data->membase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(data->membase))
+ return PTR_ERR(data->membase);
+
+ spin_lock_init(&data->lock);
+
+ data->rcdev.owner = THIS_MODULE;
+ data->rcdev.nr_resets = resource_size(res) * 8;
+ data->rcdev.ops = &stm32_reset_ops;
+ data->rcdev.of_node = pdev->dev.of_node;
+
+ return reset_controller_register(&data->rcdev);
+}
+
+static int stm32_reset_remove(struct platform_device *pdev)
+{
+ struct stm32_reset_data *data = platform_get_drvdata(pdev);
+
+ reset_controller_unregister(&data->rcdev);
+
+ return 0;
+}
+
+static struct platform_driver stm32_reset_driver = {
+ .probe = stm32_reset_probe,
+ .remove = stm32_reset_remove,
+ .driver = {
+ .name = "stm32-rcc-reset",
+ .of_match_table = stm32_reset_dt_ids,
+ },
+};
+module_platform_driver(stm32_reset_driver);
+
+MODULE_AUTHOR("Maxime Coquelin <maxime.coquelin@gmail.com>");
+MODULE_DESCRIPTION("STM32 MCUs Reset Controller Driver");
+MODULE_LICENSE("GPL");
+
--
1.9.1
^ permalink raw reply related
* [PATCH v3 07/15] dt-bindings: Document the STM32 timer bindings
From: Maxime Coquelin @ 2015-03-12 21:55 UTC (permalink / raw)
To: u.kleine-koenig, afaerber, geert, Rob Herring, Philipp Zabel,
Linus Walleij, Arnd Bergmann, stefan, pmeerw, pebolle
Cc: Mark Rutland, linux-doc, Will Deacon, Nikolay Borisov, linux-api,
Jiri Slaby, Mauro Carvalho Chehab, linux-arch, Russell King,
Jonathan Corbet, Daniel Lezcano, Antti Palosaari, linux-serial,
devicetree, Kees Cook, Pawel Moll, Ian Campbell, Rusty Russell,
Joe Perches, Thomas Gleixner, linux-arm-kernel, Michal Marek,
linux-gpio, Greg Kroah-Hartman, linux-kernel, mco
In-Reply-To: <1426197361-19290-1-git-send-email-maxime.coquelin@st.com>
From: Maxime Coquelin <mcoquelin.stm32@gmail.com>
This adds documentation of device tree bindings for the
STM32 timer.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
---
.../devicetree/bindings/timer/st,stm32-timer.txt | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
create mode 100644 Documentation/devicetree/bindings/timer/st,stm32-timer.txt
diff --git a/Documentation/devicetree/bindings/timer/st,stm32-timer.txt b/Documentation/devicetree/bindings/timer/st,stm32-timer.txt
new file mode 100644
index 0000000..d3fdeb0
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/st,stm32-timer.txt
@@ -0,0 +1,22 @@
+. STMicroelectronics STM32 timer
+
+The STM32 MCUs family has several general-purpose 16 and 32 bits timers.
+
+Required properties:
+- compatible : Should be st,stm32-timer"
+- reg : Address and length of the register set
+- clocks : Reference on the timer input clock
+- interrupts : Reference to the timer interrupt
+
+Optional properties:
+- resets: Reference to a reset controller asserting the timer
+
+Example:
+
+timer5: timer@40000c00 {
+ compatible = "st,stm32-timer";
+ reg = <0x40000c00 0x400>;
+ interrupts = <50>;
+ resets = <&rrc 259>;
+ clocks = <&clk_pmtr1>;
+};
--
1.9.1
^ permalink raw reply related
* [PATCH v3 08/15] clockevent: Add STM32 Timer driver
From: Maxime Coquelin @ 2015-03-12 21:55 UTC (permalink / raw)
To: u.kleine-koenig, afaerber, geert, Rob Herring, Philipp Zabel,
Linus Walleij, Arnd Bergmann, stefan, pmeerw, pebolle
Cc: Jonathan Corbet, Pawel Moll, Mark Rutland, Ian Campbell,
Kumar Gala, Russell King, Daniel Lezcano, Thomas Gleixner,
Greg Kroah-Hartman, Jiri Slaby, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will Deacon, Nikolay Borisov, Rusty Russell, Kees Cook,
Michal Marek, linux-doc, linux-arm-kernel, linux-kernel
In-Reply-To: <1426197361-19290-1-git-send-email-maxime.coquelin@st.com>
From: Maxime Coquelin <mcoquelin.stm32@gmail.com>
STM32 MCUs feature 16 and 32 bits general purpose timers with prescalers.
The drivers detects whether the time is 16 or 32 bits, and applies a
1024 prescaler value if it is 16 bits.
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
---
drivers/clocksource/Kconfig | 8 ++
drivers/clocksource/Makefile | 1 +
drivers/clocksource/timer-stm32.c | 184 ++++++++++++++++++++++++++++++++++++++
3 files changed, 193 insertions(+)
create mode 100644 drivers/clocksource/timer-stm32.c
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index b82e58b..519304b 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -101,6 +101,14 @@ config CLKSRC_EFM32
Support to use the timers of EFM32 SoCs as clock source and clock
event device.
+config CLKSRC_STM32
+ bool "Clocksource for STM32 SoCs" if !ARCH_STM32
+ depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
+ select CLKSRC_MMIO
+ default ARCH_STM32
+ help
+ Support to use the timers of STM32 SoCs as clock event device.
+
config ARM_ARCH_TIMER
bool
select CLKSRC_OF if OF
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 1c9a643..525dafe 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o
obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm_kona_timer.o
obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence_ttc_timer.o
obj-$(CONFIG_CLKSRC_EFM32) += time-efm32.o
+obj-$(CONFIG_CLKSRC_STM32) += timer-stm32.o
obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o
obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o
obj-$(CONFIG_FSL_FTM_TIMER) += fsl_ftm_timer.o
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
new file mode 100644
index 0000000..fad2e2e
--- /dev/null
+++ b/drivers/clocksource/timer-stm32.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Inspired by time-efm32.c from Uwe Kleine-Koenig
+ */
+
+#include <linux/kernel.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+
+#define TIM_CR1 0x00
+#define TIM_DIER 0x0c
+#define TIM_SR 0x10
+#define TIM_EGR 0x14
+#define TIM_PSC 0x28
+#define TIM_ARR 0x2c
+
+#define TIM_CR1_CEN BIT(0)
+#define TIM_CR1_OPM BIT(3)
+#define TIM_CR1_ARPE BIT(7)
+
+#define TIM_DIER_UIE BIT(0)
+
+#define TIM_SR_UIF BIT(0)
+
+#define TIM_EGR_UG BIT(0)
+
+struct stm32_clock_event_ddata {
+ struct clock_event_device evtdev;
+ unsigned periodic_top;
+ void __iomem *base;
+};
+
+static void stm32_clock_event_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evtdev)
+{
+ struct stm32_clock_event_ddata *data =
+ container_of(evtdev, struct stm32_clock_event_ddata, evtdev);
+ void *base = data->base;
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ writel_relaxed(data->periodic_top, base + TIM_ARR);
+ writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, base + TIM_CR1);
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+ default:
+ writel_relaxed(0, base + TIM_CR1);
+ break;
+ }
+}
+
+static int stm32_clock_event_set_next_event(unsigned long evt,
+ struct clock_event_device *evtdev)
+{
+ struct stm32_clock_event_ddata *data =
+ container_of(evtdev, struct stm32_clock_event_ddata, evtdev);
+
+ writel_relaxed(evt, data->base + TIM_ARR);
+ writel_relaxed(TIM_CR1_ARPE | TIM_CR1_OPM | TIM_CR1_CEN,
+ data->base + TIM_CR1);
+
+ return 0;
+}
+
+static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
+{
+ struct stm32_clock_event_ddata *data = dev_id;
+
+ writel_relaxed(0, data->base + TIM_SR);
+
+ data->evtdev.event_handler(&data->evtdev);
+
+ return IRQ_HANDLED;
+}
+
+static struct stm32_clock_event_ddata clock_event_ddata = {
+ .evtdev = {
+ .name = "stm32 clockevent",
+ .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
+ .set_mode = stm32_clock_event_set_mode,
+ .set_next_event = stm32_clock_event_set_next_event,
+ .rating = 200,
+ },
+};
+
+static void __init stm32_clockevent_init(struct device_node *np)
+{
+ struct stm32_clock_event_ddata *data = &clock_event_ddata;
+ struct clk *clk;
+ struct reset_control *rstc;
+ unsigned long rate, max_delta;
+ int irq, ret, bits, prescaler = 1;
+
+ clk = of_clk_get(np, 0);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ pr_err("failed to get clock for clockevent (%d)\n", ret);
+ goto err_clk_get;
+ }
+
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ pr_err("failed to enable timer clock for clockevent (%d)\n",
+ ret);
+ goto err_clk_enable;
+ }
+
+ rate = clk_get_rate(clk);
+
+ rstc = of_reset_control_get(np, NULL);
+ if (!IS_ERR(rstc)) {
+ reset_control_assert(rstc);
+ reset_control_deassert(rstc);
+ }
+
+ data->base = of_iomap(np, 0);
+ if (!data->base) {
+ pr_err("failed to map registers for clockevent\n");
+ goto err_iomap;
+ }
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (!irq) {
+ pr_err("%s: failed to get irq.\n", np->full_name);
+ goto err_get_irq;
+ }
+
+ /* Detect whether the timer is 16 or 32 bits */
+ writel_relaxed(~0UL, data->base + TIM_ARR);
+ max_delta = readl_relaxed(data->base + TIM_ARR);
+ if (max_delta == ~0UL) {
+ prescaler = 1;
+ bits = 32;
+ } else {
+ prescaler = 1024;
+ bits = 16;
+ }
+ writel_relaxed(0, data->base + TIM_ARR);
+
+ writel_relaxed(prescaler - 1, data->base + TIM_PSC);
+ writel_relaxed(TIM_EGR_UG, data->base + TIM_EGR);
+ writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER);
+ writel_relaxed(0, data->base + TIM_SR);
+
+ data->periodic_top = DIV_ROUND_CLOSEST(rate, prescaler * HZ);
+
+ clockevents_config_and_register(&data->evtdev,
+ DIV_ROUND_CLOSEST(rate, prescaler),
+ 0x1, max_delta);
+
+ ret = request_irq(irq, stm32_clock_event_handler, IRQF_TIMER,
+ "stm32 clockevent", data);
+ if (ret) {
+ pr_err("%s: failed to request irq.\n", np->full_name);
+ goto err_get_irq;
+ }
+
+ pr_info("%s: STM32 clockevent driver initialized (%d bits)\n",
+ np->full_name, bits);
+
+ return;
+
+err_get_irq:
+ iounmap(data->base);
+err_iomap:
+ clk_disable_unprepare(clk);
+err_clk_enable:
+ clk_put(clk);
+err_clk_get:
+ return;
+}
+
+CLOCKSOURCE_OF_DECLARE(stm32, "st,stm32-timer", stm32_clockevent_init);
--
1.9.1
^ permalink raw reply related
* [PATCH v3 09/15] dt-bindings: Document the STM32 USART bindings
From: Maxime Coquelin @ 2015-03-12 21:55 UTC (permalink / raw)
To: u.kleine-koenig, afaerber, geert, Rob Herring, Philipp Zabel,
Linus Walleij, Arnd Bergmann, stefan, pmeerw, pebolle
Cc: Jonathan Corbet, Pawel Moll, Mark Rutland, Ian Campbell,
Kumar Gala, Russell King, Daniel Lezcano, Thomas Gleixner,
Greg Kroah-Hartman, Jiri Slaby, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will Deacon, Nikolay Borisov, Rusty Russell, Kees Cook,
Michal Marek, linux-doc, linux-arm-kernel, linux-kernel
In-Reply-To: <1426197361-19290-1-git-send-email-maxime.coquelin@st.com>
From: Maxime Coquelin <mcoquelin.stm32@gmail.com>
This adds documentation of device tree bindings for the
STM32 USART
Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
---
.../devicetree/bindings/serial/st,stm32-usart.txt | 32 ++++++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 Documentation/devicetree/bindings/serial/st,stm32-usart.txt
diff --git a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
new file mode 100644
index 0000000..090a3a4
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
@@ -0,0 +1,32 @@
+* STMicroelectronics STM32 USART
+
+Required properties:
+- compatible: Can be either "st,stm32-usart" or "st,stm32-uart" depending on
+whether the device supports synchronous mode.
+- reg: The address and length of the peripheral registers space
+- interrupts: The interrupt line of the USART instance
+- clocks: The input clock of the USART instance
+
+Optional properties:
+- pinctrl: The reference on the pins configuration
+- st,hw-flow-ctrl: bool flag to enable hardware flow control.
+
+Examples:
+usart4: serial@40004c00 {
+ compatible = "st,stm32-uart";
+ reg = <0x40004c00 0x400>;
+ interrupts = <52>;
+ clocks = <&clk_pclk1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart4>;
+};
+
+usart2: serial@40004400 {
+ compatible = "st,stm32-usart", "st,stm32-uart";
+ reg = <0x40004400 0x400>;
+ interrupts = <38>;
+ clocks = <&clk_pclk1>;
+ st,hw-flow-ctrl;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart2 &pinctrl_usart2_rtscts>;
+};
--
1.9.1
^ permalink raw reply related
* [PATCH v3 10/15] serial: stm32-usart: Add STM32 USART Driver
From: Maxime Coquelin @ 2015-03-12 21:55 UTC (permalink / raw)
To: u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ, afaerber-l3A5Bk7waGM,
geert-Td1EMuHUCqxL1ZNQvxDV9g, Rob Herring, Philipp Zabel,
Linus Walleij, Arnd Bergmann, stefan-XLVq0VzYD2Y,
pmeerw-jW+XmwGofnusTnJN9+BGXg, pebolle-IWqWACnzNjzz+pZb47iToQ
Cc: Jonathan Corbet, Pawel Moll, Mark Rutland, Ian Campbell,
Kumar Gala, Russell King, Daniel Lezcano, Thomas Gleixner,
Greg Kroah-Hartman, Jiri Slaby, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will Deacon, Nikolay Borisov, Rusty Russell, Kees Cook,
Michal Marek, linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TZNg+MwTxZMZA
In-Reply-To: <1426197361-19290-1-git-send-email-maxime.coquelin-qxv4g6HH51o@public.gmane.org>
From: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
This drivers adds support to the STM32 USART controller, which is a
standard serial driver.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
drivers/tty/serial/Kconfig | 17 +
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/stm32-usart.c | 695 +++++++++++++++++++++++++++++++++++++++
include/uapi/linux/serial_core.h | 3 +
4 files changed, 716 insertions(+)
create mode 100644 drivers/tty/serial/stm32-usart.c
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index d2501f0..880cb4f 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1611,6 +1611,23 @@ config SERIAL_SPRD_CONSOLE
with "earlycon" on the kernel command line. The console is
enabled when early_param is processed.
+config SERIAL_STM32
+ tristate "STMicroelectronics STM32 serial port support"
+ select SERIAL_CORE
+ depends on ARM || COMPILE_TEST
+ help
+ This driver is for the on-chip Serial Controller on
+ STMicroelectronics STM32 MCUs.
+ USART supports Rx & Tx functionality.
+ It support all industry standard baud rates.
+
+ If unsure, say N.
+
+config SERIAL_STM32_CONSOLE
+ bool "Support for console on STM32"
+ depends on SERIAL_STM32=y
+ select SERIAL_CORE_CONSOLE
+
endmenu
config SERIAL_MCTRL_GPIO
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 599be4b..67c5023 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -95,6 +95,7 @@ obj-$(CONFIG_SERIAL_FSL_LPUART) += fsl_lpuart.o
obj-$(CONFIG_SERIAL_CONEXANT_DIGICOLOR) += digicolor-usart.o
obj-$(CONFIG_SERIAL_MEN_Z135) += men_z135_uart.o
obj-$(CONFIG_SERIAL_SPRD) += sprd_serial.o
+obj-$(CONFIG_SERIAL_STM32) += stm32-usart.o
# GPIOLIB helpers for modem control lines
obj-$(CONFIG_SERIAL_MCTRL_GPIO) += serial_mctrl_gpio.o
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
new file mode 100644
index 0000000..61bb065
--- /dev/null
+++ b/drivers/tty/serial/stm32-usart.c
@@ -0,0 +1,695 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Inspired by st-asc.c from STMicroelectronics (c)
+ */
+
+#if defined(CONFIG_SERIAL_STM32_USART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/serial_core.h>
+#include <linux/clk.h>
+
+#define DRIVER_NAME "stm32-usart"
+
+/* Register offsets */
+#define USART_SR 0x00
+#define USART_DR 0x04
+#define USART_BRR 0x08
+#define USART_CR1 0x0c
+#define USART_CR2 0x10
+#define USART_CR3 0x14
+#define USART_GTPR 0x18
+
+/* USART_SR */
+#define USART_SR_PE BIT(0)
+#define USART_SR_FE BIT(1)
+#define USART_SR_NF BIT(2)
+#define USART_SR_ORE BIT(3)
+#define USART_SR_IDLE BIT(4)
+#define USART_SR_RXNE BIT(5)
+#define USART_SR_TC BIT(6)
+#define USART_SR_TXE BIT(7)
+#define USART_SR_LBD BIT(8)
+#define USART_SR_CTS BIT(9)
+#define USART_SR_ERR_MASK (USART_SR_LBD | USART_SR_ORE | \
+ USART_SR_FE | USART_SR_PE)
+/* Dummy bits */
+#define USART_SR_DUMMY_RX BIT(16)
+
+/* USART_DR */
+#define USART_DR_MASK GENMASK(8, 0)
+
+/* USART_BRR */
+#define USART_BRR_DIV_F_MASK GENMASK(3, 0)
+#define USART_BRR_DIV_M_MASK GENMASK(15, 4)
+#define USART_BRR_DIV_M_SHIFT 4
+
+/* USART_CR1 */
+#define USART_CR1_SBK BIT(0)
+#define USART_CR1_RWU BIT(1)
+#define USART_CR1_RE BIT(2)
+#define USART_CR1_TE BIT(3)
+#define USART_CR1_IDLEIE BIT(4)
+#define USART_CR1_RXNEIE BIT(5)
+#define USART_CR1_TCIE BIT(6)
+#define USART_CR1_TXEIE BIT(7)
+#define USART_CR1_PEIE BIT(8)
+#define USART_CR1_PS BIT(9)
+#define USART_CR1_PCE BIT(10)
+#define USART_CR1_WAKE BIT(11)
+#define USART_CR1_M BIT(12)
+#define USART_CR1_UE BIT(13)
+#define USART_CR1_OVER8 BIT(15)
+#define USART_CR1_IE_MASK GENMASK(8, 4)
+
+/* USART_CR2 */
+#define USART_CR2_ADD_MASK GENMASK(3, 0)
+#define USART_CR2_LBDL BIT(5)
+#define USART_CR2_LBDIE BIT(6)
+#define USART_CR2_LBCL BIT(8)
+#define USART_CR2_CPHA BIT(9)
+#define USART_CR2_CPOL BIT(10)
+#define USART_CR2_CLKEN BIT(11)
+#define USART_CR2_STOP_2B BIT(13)
+#define USART_CR2_STOP_MASK GENMASK(13, 12)
+#define USART_CR2_LINEN BIT(14)
+
+/* USART_CR3 */
+#define USART_CR3_EIE BIT(0)
+#define USART_CR3_IREN BIT(1)
+#define USART_CR3_IRLP BIT(2)
+#define USART_CR3_HDSEL BIT(3)
+#define USART_CR3_NACK BIT(4)
+#define USART_CR3_SCEN BIT(5)
+#define USART_CR3_DMAR BIT(6)
+#define USART_CR3_DMAT BIT(7)
+#define USART_CR3_RTSE BIT(8)
+#define USART_CR3_CTSE BIT(9)
+#define USART_CR3_CTSIE BIT(10)
+#define USART_CR3_ONEBIT BIT(11)
+
+/* USART_GTPR */
+#define USART_GTPR_PSC_MASK GENMASK(7, 0)
+#define USART_GTPR_GT_MASK GENMASK(15, 8)
+
+#define DRIVER_NAME "stm32-usart"
+#define STM32_SERIAL_NAME "ttyS"
+#define STM32_MAX_PORTS 6
+
+struct stm32_port {
+ struct uart_port port;
+ struct clk *clk;
+};
+
+static struct stm32_port stm32_ports[STM32_MAX_PORTS];
+static struct uart_driver stm32_usart_driver;
+
+static void stm32_stop_tx(struct uart_port *port);
+
+static void stm32_set_bits(struct uart_port *port, u32 reg, u32 bits)
+{
+ u32 val;
+
+ val = readl_relaxed(port->membase + reg);
+ val |= bits;
+ writel_relaxed(val, port->membase + reg);
+}
+
+static void stm32_clr_bits(struct uart_port *port, u32 reg, u32 bits)
+{
+ u32 val;
+
+ val = readl_relaxed(port->membase + reg);
+ val &= ~bits;
+ writel_relaxed(val, port->membase + reg);
+}
+
+static void stm32_receive_chars(struct uart_port *port)
+{
+ struct tty_port *tport = &port->state->port;
+ unsigned long c;
+ u32 sr;
+ char flag;
+
+ if (port->irq_wake)
+ pm_wakeup_event(tport->tty->dev, 0);
+
+ while ((sr = readl_relaxed(port->membase + USART_SR)) & USART_SR_RXNE) {
+ sr |= USART_SR_DUMMY_RX;
+ c = readl_relaxed(port->membase + USART_DR);
+ flag = TTY_NORMAL;
+ port->icount.rx++;
+
+ if (sr & USART_SR_ERR_MASK) {
+ if (sr & USART_SR_LBD) {
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ continue;
+ } else if (sr & USART_SR_ORE) {
+ port->icount.overrun++;
+ } else if (sr & USART_SR_PE) {
+ port->icount.parity++;
+ } else if (sr & USART_SR_FE) {
+ port->icount.frame++;
+ }
+
+ sr &= port->read_status_mask;
+
+ if (sr & USART_SR_LBD)
+ flag = TTY_BREAK;
+ else if (sr & USART_SR_PE)
+ flag = TTY_PARITY;
+ else if (sr & USART_SR_FE)
+ flag = TTY_FRAME;
+ }
+
+ if (uart_handle_sysrq_char(port, c))
+ continue;
+ uart_insert_char(port, sr, USART_SR_ORE, c, flag);
+ }
+
+ spin_unlock(&port->lock);
+ tty_flip_buffer_push(tport);
+ spin_lock(&port->lock);
+}
+
+static void stm32_transmit_chars(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->state->xmit;
+
+ if (port->x_char) {
+ writel_relaxed(port->x_char, port->membase + USART_DR);
+ port->x_char = 0;
+ port->icount.tx++;
+ return;
+ }
+
+ if (uart_tx_stopped(port)) {
+ stm32_stop_tx(port);
+ return;
+ }
+
+ if (uart_circ_empty(xmit)) {
+ stm32_stop_tx(port);
+ return;
+ }
+
+ writel_relaxed(xmit->buf[xmit->tail], port->membase + USART_DR);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit))
+ stm32_stop_tx(port);
+}
+
+static irqreturn_t stm32_interrupt(int irq, void *ptr)
+{
+ struct uart_port *port = ptr;
+ u32 sr;
+
+ spin_lock(&port->lock);
+
+ sr = readl_relaxed(port->membase + USART_SR);
+
+ if (sr & USART_SR_RXNE)
+ stm32_receive_chars(port);
+
+ if (sr & USART_SR_TXE)
+ stm32_transmit_chars(port);
+
+ spin_unlock(&port->lock);
+
+ return IRQ_HANDLED;
+}
+
+static unsigned int stm32_tx_empty(struct uart_port *port)
+{
+ return readl_relaxed(port->membase + USART_SR) & USART_SR_TXE;
+}
+
+static void stm32_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ /*
+ * This routine is used for seting signals of: DTR, DCD, CTS/RTS
+ * We use USART's hardware for CTS/RTS, so don't need any for that.
+ * Some boards have DTR and DCD implemented using PIO pins,
+ * code to do this should be hooked in here.
+ */
+}
+
+static unsigned int stm32_get_mctrl(struct uart_port *port)
+{
+ /*
+ * This routine is used for geting signals of: DTR, DCD, DSR, RI,
+ * and CTS/RTS
+ */
+ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+/* There are probably characters waiting to be transmitted. */
+static void stm32_start_tx(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->state->xmit;
+
+ if (uart_circ_empty(xmit))
+ return;
+
+ stm32_set_bits(port, USART_CR1, USART_CR1_TXEIE | USART_CR1_TE);
+}
+
+/* Transmit stop */
+static void stm32_stop_tx(struct uart_port *port)
+{
+ stm32_clr_bits(port, USART_CR1, USART_CR1_TXEIE);
+}
+
+/* Receive stop */
+static void stm32_stop_rx(struct uart_port *port)
+{
+ stm32_clr_bits(port, USART_CR1, USART_CR1_RXNEIE);
+}
+
+/* Handle breaks - ignored by us */
+static void stm32_break_ctl(struct uart_port *port, int break_state)
+{
+ /* Nothing here yet .. */
+}
+
+static int stm32_startup(struct uart_port *port)
+{
+ const char *name = to_platform_device(port->dev)->name;
+ u32 val;
+
+ if (request_irq(port->irq, stm32_interrupt, IRQF_NO_SUSPEND,
+ name, port)) {
+ dev_err(port->dev, "cannot allocate irq %d\n", port->irq);
+ return -ENODEV;
+ }
+
+ val = USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE;
+ stm32_set_bits(port, USART_CR1, val);
+
+ return 0;
+}
+
+static void stm32_shutdown(struct uart_port *port)
+{
+ u32 val;
+
+ val = USART_CR1_TXEIE | USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE;
+ stm32_set_bits(port, USART_CR1, val);
+
+ free_irq(port->irq, port);
+}
+
+static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+ unsigned int baud;
+ u32 usardiv, mantissa, fraction;
+ tcflag_t cflag;
+ u32 cr1, cr2, cr3;
+ unsigned long flags;
+
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
+ cflag = termios->c_cflag;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* Stop serial port and reset value */
+ writel_relaxed(0, port->membase + USART_CR1);
+
+ cr1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE | USART_CR1_RXNEIE;
+
+ if (cflag & CSTOPB)
+ cr2 = USART_CR2_STOP_2B;
+
+ if (cflag & PARENB) {
+ cr1 |= USART_CR1_PCE;
+ if ((cflag & CSIZE) == CS8)
+ cr1 |= USART_CR1_M;
+ }
+
+ if (cflag & PARODD)
+ cr1 |= USART_CR1_PS;
+
+ if (cflag & CRTSCTS)
+ cr3 = USART_CR3_RTSE | USART_CR3_CTSE;
+
+ usardiv = (port->uartclk * 25) / (baud * 4);
+ mantissa = (usardiv / 100) << USART_BRR_DIV_M_SHIFT;
+ fraction = DIV_ROUND_CLOSEST((usardiv % 100) * 16, 100);
+ if (fraction & ~USART_BRR_DIV_F_MASK) {
+ fraction = 0;
+ mantissa += (1 << USART_BRR_DIV_M_SHIFT);
+ }
+
+ writel_relaxed(mantissa | fraction, port->membase + USART_BRR);
+
+ uart_update_timeout(port, cflag, baud);
+
+ port->read_status_mask = USART_SR_ORE;
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= USART_SR_PE | USART_SR_FE;
+ if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
+ port->read_status_mask |= USART_SR_LBD;
+
+ /* Characters to ignore */
+ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask = USART_SR_PE | USART_SR_FE;
+ if (termios->c_iflag & IGNBRK) {
+ port->ignore_status_mask |= USART_SR_LBD;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= USART_SR_ORE;
+ }
+
+ /*
+ * Ignore all characters if CREAD is not set.
+ */
+ if ((termios->c_cflag & CREAD) == 0)
+ port->ignore_status_mask |= USART_SR_DUMMY_RX;
+
+ writel_relaxed(cr3, port->membase + USART_CR3);
+ writel_relaxed(cr2, port->membase + USART_CR2);
+ writel_relaxed(cr1, port->membase + USART_CR1);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *stm32_type(struct uart_port *port)
+{
+ return (port->type == PORT_STM32) ? DRIVER_NAME : NULL;
+}
+
+static void stm32_release_port(struct uart_port *port)
+{
+}
+
+static int stm32_request_port(struct uart_port *port)
+{
+ return 0;
+}
+
+static void stm32_config_port(struct uart_port *port, int flags)
+{
+ if ((flags & UART_CONFIG_TYPE))
+ port->type = PORT_STM32;
+}
+
+static int
+stm32_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ /* No user changeable parameters */
+ return -EINVAL;
+}
+
+static void stm32_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate)
+{
+ struct stm32_port *stm32port = container_of(port,
+ struct stm32_port, port);
+ unsigned long flags = 0;
+
+ switch (state) {
+ case UART_PM_STATE_ON:
+ clk_prepare_enable(stm32port->clk);
+ break;
+ case UART_PM_STATE_OFF:
+ spin_lock_irqsave(&port->lock, flags);
+ stm32_clr_bits(port, USART_CR1, USART_CR1_UE);
+ spin_unlock_irqrestore(&port->lock, flags);
+ clk_disable_unprepare(stm32port->clk);
+ break;
+ }
+}
+
+static struct uart_ops stm32_uart_ops = {
+ .tx_empty = stm32_tx_empty,
+ .set_mctrl = stm32_set_mctrl,
+ .get_mctrl = stm32_get_mctrl,
+ .start_tx = stm32_start_tx,
+ .stop_tx = stm32_stop_tx,
+ .stop_rx = stm32_stop_rx,
+ .break_ctl = stm32_break_ctl,
+ .startup = stm32_startup,
+ .shutdown = stm32_shutdown,
+ .set_termios = stm32_set_termios,
+ .type = stm32_type,
+ .release_port = stm32_release_port,
+ .request_port = stm32_request_port,
+ .config_port = stm32_config_port,
+ .verify_port = stm32_verify_port,
+ .pm = stm32_pm,
+};
+
+static int stm32_init_port(struct stm32_port *stm32port,
+ struct platform_device *pdev)
+{
+ struct uart_port *port = &stm32port->port;
+ struct resource *res;
+
+ port->iotype = UPIO_MEM;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->ops = &stm32_uart_ops;
+ port->dev = &pdev->dev;
+ port->irq = platform_get_irq(pdev, 0);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ port->membase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(port->membase))
+ return PTR_ERR(port->membase);
+ port->mapbase = res->start;
+
+ spin_lock_init(&port->lock);
+
+ stm32port->clk = devm_clk_get(&pdev->dev, NULL);
+
+ if (WARN_ON(IS_ERR(stm32port->clk)))
+ return -EINVAL;
+
+ /* ensure that clk rate is correct by enabling the clk */
+ clk_prepare_enable(stm32port->clk);
+ stm32port->port.uartclk = clk_get_rate(stm32port->clk);
+ WARN_ON(stm32port->port.uartclk == 0);
+ clk_disable_unprepare(stm32port->clk);
+
+ return 0;
+}
+
+static struct stm32_port *stm32_of_get_stm32_port(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int id;
+
+ if (!np)
+ return NULL;
+
+ id = of_alias_get_id(np, STM32_SERIAL_NAME);
+
+ if (id < 0)
+ id = 0;
+
+ if (WARN_ON(id >= STM32_MAX_PORTS))
+ return NULL;
+
+ stm32_ports[id].port.line = id;
+ return &stm32_ports[id];
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id stm32_match[] = {
+ { .compatible = "st,stm32-usart", },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, stm32_match);
+#endif
+
+static int stm32_serial_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct stm32_port *stm32port;
+
+ stm32port = stm32_of_get_stm32_port(pdev);
+ if (!stm32port)
+ return -ENODEV;
+
+ ret = stm32_init_port(stm32port, pdev);
+ if (ret)
+ return ret;
+
+ ret = uart_add_one_port(&stm32_usart_driver, &stm32port->port);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, &stm32port->port);
+
+ return 0;
+}
+
+static int stm32_serial_remove(struct platform_device *pdev)
+{
+ struct uart_port *port = platform_get_drvdata(pdev);
+
+ return uart_remove_one_port(&stm32_usart_driver, port);
+}
+
+
+#ifdef CONFIG_SERIAL_STM32_CONSOLE
+static void stm32_console_putchar(struct uart_port *port, int ch)
+{
+ while (!(readl_relaxed(port->membase + USART_SR) & USART_SR_TXE))
+ cpu_relax();
+
+ writel_relaxed(ch, port->membase + USART_DR);
+}
+
+static void stm32_console_write(struct console *co, const char *s, unsigned cnt)
+{
+ struct uart_port *port = &stm32_ports[co->index].port;
+ unsigned long flags;
+ u32 old_cr1, new_cr1;
+ int locked = 1;
+
+ if (oops_in_progress) {
+ locked = spin_trylock_irqsave(&port->lock, flags);
+ } else {
+ locked = 1;
+ spin_lock_irqsave(&port->lock, flags);
+ }
+
+ /* Save and disable interrupts */
+ old_cr1 = readl_relaxed(port->membase + USART_CR1);
+ new_cr1 = old_cr1 & ~USART_CR1_IE_MASK;
+ writel_relaxed(new_cr1, port->membase + USART_CR1);
+
+ uart_console_write(port, s, cnt, stm32_console_putchar);
+
+ /* Restore interrupt state */
+ writel_relaxed(old_cr1, port->membase + USART_CR1);
+
+ if (locked)
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int stm32_console_setup(struct console *co, char *options)
+{
+ struct stm32_port *stm32port;
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if (co->index >= STM32_MAX_PORTS)
+ return -ENODEV;
+
+ stm32port = &stm32_ports[co->index];
+
+ /*
+ * This driver does not support early console initialization
+ * (use ARM early printk support instead), so we only expect
+ * this to be called during the uart port registration when the
+ * driver gets probed and the port should be mapped at that point.
+ */
+ if (stm32port->port.mapbase == 0 || stm32port->port.membase == NULL)
+ return -ENXIO;
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(&stm32port->port, co, baud, parity, bits, flow);
+}
+
+static struct console stm32_console = {
+ .name = STM32_SERIAL_NAME,
+ .device = uart_console_device,
+ .write = stm32_console_write,
+ .setup = stm32_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &stm32_usart_driver,
+};
+
+#define STM32_SERIAL_CONSOLE (&stm32_console)
+
+#else
+#define STM32_SERIAL_CONSOLE NULL
+#endif /* CONFIG_SERIAL_STM32_CONSOLE */
+
+static struct uart_driver stm32_usart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = DRIVER_NAME,
+ .dev_name = STM32_SERIAL_NAME,
+ .major = 0,
+ .minor = 0,
+ .nr = STM32_MAX_PORTS,
+ .cons = STM32_SERIAL_CONSOLE,
+};
+
+static struct platform_driver stm32_serial_driver = {
+ .probe = stm32_serial_probe,
+ .remove = stm32_serial_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(stm32_match),
+ },
+};
+
+static int __init usart_init(void)
+{
+ int ret;
+ static char banner[] __initdata =
+ KERN_INFO "STM32 USART driver initialized\n";
+
+ printk(banner);
+
+ ret = uart_register_driver(&stm32_usart_driver);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&stm32_serial_driver);
+ if (ret)
+ uart_unregister_driver(&stm32_usart_driver);
+
+ return ret;
+}
+
+static void __exit usart_exit(void)
+{
+ platform_driver_unregister(&stm32_serial_driver);
+ uart_unregister_driver(&stm32_usart_driver);
+}
+
+module_init(usart_init);
+module_exit(usart_exit);
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_DESCRIPTION("STMicroelectronics STM32 serial port driver");
+MODULE_LICENSE("GPL");
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index b212281..e22dee5 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -258,4 +258,7 @@
/* Cris v10 / v32 SoC */
#define PORT_CRIS 112
+/* STM32 USART */
+#define PORT_STM32 110
+
#endif /* _UAPILINUX_SERIAL_CORE_H */
--
1.9.1
^ permalink raw reply related
* [PATCH v3 11/15] ARM: Add STM32 family machine
From: Maxime Coquelin @ 2015-03-12 21:55 UTC (permalink / raw)
To: u.kleine-koenig, afaerber, geert, Rob Herring, Philipp Zabel,
Linus Walleij, Arnd Bergmann, stefan, pmeerw, pebolle
Cc: Jonathan Corbet, Pawel Moll, Mark Rutland, Ian Campbell,
Kumar Gala, Russell King, Daniel Lezcano, Thomas Gleixner,
Greg Kroah-Hartman, Jiri Slaby, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will Deacon, Nikolay Borisov, Rusty Russell, Kees Cook,
Michal Marek, linux-doc, linux-arm-kernel, linux-kernel
In-Reply-To: <1426197361-19290-1-git-send-email-maxime.coquelin@st.com>
From: Maxime Coquelin <mcoquelin.stm32@gmail.com>
STMicrolectronics's STM32 series is a family of Cortex-M
microcontrollers. It is used in various applications, and
proposes a wide range of peripherals.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
---
Documentation/arm/stm32/overview.txt | 32 ++++++++++++++++++++++++++
Documentation/arm/stm32/stm32f429-overview.txt | 22 ++++++++++++++++++
arch/arm/Kconfig | 18 +++++++++++++++
arch/arm/Makefile | 1 +
arch/arm/mach-stm32/Makefile | 1 +
arch/arm/mach-stm32/Makefile.boot | 3 +++
arch/arm/mach-stm32/board-dt.c | 19 +++++++++++++++
7 files changed, 96 insertions(+)
create mode 100644 Documentation/arm/stm32/overview.txt
create mode 100644 Documentation/arm/stm32/stm32f429-overview.txt
create mode 100644 arch/arm/mach-stm32/Makefile
create mode 100644 arch/arm/mach-stm32/Makefile.boot
create mode 100644 arch/arm/mach-stm32/board-dt.c
diff --git a/Documentation/arm/stm32/overview.txt b/Documentation/arm/stm32/overview.txt
new file mode 100644
index 0000000..09aed55
--- /dev/null
+++ b/Documentation/arm/stm32/overview.txt
@@ -0,0 +1,32 @@
+ STM32 ARM Linux Overview
+ ========================
+
+Introduction
+------------
+
+ The STMicroelectronics family of Cortex-M based MCUs are supported by the
+ 'STM32' platform of ARM Linux. Currently only the STM32F429 is supported.
+
+
+Configuration
+-------------
+
+ A generic configuration is provided for STM32 family, and can be used as the
+ default by
+ make stm32_defconfig
+
+Layout
+------
+
+ All the files for multiple machine families are located in the platform code
+ contained in arch/arm/mach-stm32
+
+ There is a generic board board-dt.c in the mach folder which support
+ Flattened Device Tree, which means, it works with any compatible board with
+ Device Trees.
+
+
+Document Author
+---------------
+
+ Maxime Coquelin <mcoquelin.stm32@gmail.com>
diff --git a/Documentation/arm/stm32/stm32f429-overview.txt b/Documentation/arm/stm32/stm32f429-overview.txt
new file mode 100644
index 0000000..5206822
--- /dev/null
+++ b/Documentation/arm/stm32/stm32f429-overview.txt
@@ -0,0 +1,22 @@
+ STM32F429 Overview
+ ==================
+
+ Introduction
+ ------------
+ The STM32F429 is a Cortex-M4 MCU aimed at various applications.
+ It features:
+ - ARM Cortex-M4 up to 180MHz with FPU
+ - 2MB internal Flash Memory
+ - External memory support through FMC controller (PSRAM, SDRAM, NOR, NAND)
+ - I2C, SPI, SAI, CAN, USB OTG, Ethernet controllers
+ - LCD controller & Camera interface
+ - Cryptographic processor
+
+ Resources
+ ---------
+ Datasheet and reference manual are publicly available on ST website:
+ - http://www.st.com/web/en/catalog/mmc/FM141/SC1169/SS1577/LN1806?ecmp=stm32f429-439_pron_pr-ces2014_nov2013
+
+ Document Author
+ ---------------
+ Maxime Coquelin <mcoquelin.stm32@gmail.com>
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9f1f09a..5b1157d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -776,6 +776,24 @@ config ARCH_OMAP1
help
Support for older TI OMAP1 (omap7xx, omap15xx or omap16xx)
+config ARCH_STM32
+ bool "STMicrolectronics STM32"
+ depends on !MMU
+ select ARCH_HAS_RESET_CONTROLLER
+ select ARM_NVIC
+ select ARMV7M_SYSTICK
+ select AUTO_ZRELADDR
+ select CLKSRC_OF
+ select COMMON_CLK
+ select CPU_V7M
+ select GENERIC_CLOCKEVENTS
+ select NO_IOPORT_MAP
+ select RESET_CONTROLLER
+ select SPARSE_IRQ
+ select USE_OF
+ help
+ Support for STMicroelectronics STM32 processors.
+
endchoice
menu "Multiple platform selection"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 7f99cd6..982c104 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -196,6 +196,7 @@ machine-$(CONFIG_ARCH_SHMOBILE) += shmobile
machine-$(CONFIG_ARCH_SIRF) += prima2
machine-$(CONFIG_ARCH_SOCFPGA) += socfpga
machine-$(CONFIG_ARCH_STI) += sti
+machine-$(CONFIG_ARCH_STM32) += stm32
machine-$(CONFIG_ARCH_SUNXI) += sunxi
machine-$(CONFIG_ARCH_TEGRA) += tegra
machine-$(CONFIG_ARCH_U300) += u300
diff --git a/arch/arm/mach-stm32/Makefile b/arch/arm/mach-stm32/Makefile
new file mode 100644
index 0000000..bd0b7b5
--- /dev/null
+++ b/arch/arm/mach-stm32/Makefile
@@ -0,0 +1 @@
+obj-y += board-dt.o
diff --git a/arch/arm/mach-stm32/Makefile.boot b/arch/arm/mach-stm32/Makefile.boot
new file mode 100644
index 0000000..eacfc3f
--- /dev/null
+++ b/arch/arm/mach-stm32/Makefile.boot
@@ -0,0 +1,3 @@
+# Empty file waiting for deletion once Makefile.boot isn't needed any more.
+# Patch waits for application at
+# http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=7889/1 .
diff --git a/arch/arm/mach-stm32/board-dt.c b/arch/arm/mach-stm32/board-dt.c
new file mode 100644
index 0000000..f2ad772
--- /dev/null
+++ b/arch/arm/mach-stm32/board-dt.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/kernel.h>
+#include <asm/v7m.h>
+#include <asm/mach/arch.h>
+
+static const char *const stm32_compat[] __initconst = {
+ "st,stm32f429",
+ NULL
+};
+
+DT_MACHINE_START(STM32DT, "STM32 (Device Tree Support)")
+ .dt_compat = stm32_compat,
+ .restart = armv7m_restart,
+MACHINE_END
--
1.9.1
^ permalink raw reply related
* [PATCH v3 12/15] ARM: dts: Add ARM System timer as clockevent in armv7m
From: Maxime Coquelin @ 2015-03-12 21:55 UTC (permalink / raw)
To: u.kleine-koenig, afaerber, geert, Rob Herring, Philipp Zabel,
Linus Walleij, Arnd Bergmann, stefan, pmeerw, pebolle
Cc: Jonathan Corbet, Pawel Moll, Mark Rutland, Ian Campbell,
Kumar Gala, Russell King, Daniel Lezcano, Thomas Gleixner,
Greg Kroah-Hartman, Jiri Slaby, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will Deacon, Nikolay Borisov, Rusty Russell, Kees Cook,
Michal Marek, linux-doc, linux-arm-kernel, linux-kernel
In-Reply-To: <1426197361-19290-1-git-send-email-maxime.coquelin@st.com>
From: Maxime Coquelin <mcoquelin.stm32@gmail.com>
Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
---
arch/arm/boot/dts/armv7-m.dtsi | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm/boot/dts/armv7-m.dtsi b/arch/arm/boot/dts/armv7-m.dtsi
index 5a660d0..b1ad7cf 100644
--- a/arch/arm/boot/dts/armv7-m.dtsi
+++ b/arch/arm/boot/dts/armv7-m.dtsi
@@ -8,6 +8,12 @@
reg = <0xe000e100 0xc00>;
};
+ systick: timer@e000e010 {
+ compatible = "arm,armv7m-systick";
+ reg = <0xe000e010 0x10>;
+ status = "disabled";
+ };
+
soc {
#address-cells = <1>;
#size-cells = <1>;
--
1.9.1
^ 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