* [RFT v2 1/4] perf cs-etm: Generate sample for missed packets
From: Arnaldo Carvalho de Melo @ 2018-05-25 15:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <03a53a72-8af5-02de-21a8-fd02a0974ed6@arm.com>
Em Fri, May 25, 2018 at 03:03:47PM +0100, Robert Walker escreveu:
> Hi Leo,
>
> Following the discussions from your reply to this with a simplified patch,
> this version of the patch works better as you also need to emit a branch
> sample when handling a CS_ETM_TRACE_ON packet to indicate the end of a block
> of trace.
>
> This patch does not break the output from perf inject to generate
> instruction samples for AutoFDO, so I am happy with that.
>
> Regards
>
> Rob
>
> Reviewed-by: Robert Walker <robert.walker@arm.com>
So, Leo, can you please resubmit, bumping the v2 to v3 (or the latest
one, I haven't fully reread this thread) add this "Reviewed-by: Robert"
tag and any other that people may have provided, so that I can merge it?
Thanks,
- Arnaldo
>
> On 22/05/18 09:39, Leo Yan wrote:
> > Hi Rob,
> >
> > On Mon, May 21, 2018 at 12:27:42PM +0100, Robert Walker wrote:
> > > Hi Leo,
> > >
> > > On 21/05/18 09:52, Leo Yan wrote:
> > > > Commit e573e978fb12 ("perf cs-etm: Inject capabilitity for CoreSight
> > > > traces") reworks the samples generation flow from CoreSight trace to
> > > > match the correct format so Perf report tool can display the samples
> > > > properly. But the change has side effect for packet handling, it only
> > > > generate samples when 'prev_packet->last_instr_taken_branch' is true,
> > > > this results in the start tracing packet and exception packets are
> > > > dropped.
> > > >
> > > > This patch checks extra two conditions for complete samples:
> > > >
> > > > - If 'prev_packet->sample_type' is zero we can use this condition to
> > > > get to know this is the start tracing packet; for this case, the start
> > > > packet's end_addr is zero as well so we need to handle it in the
> > > > function cs_etm__last_executed_instr();
> > > >
> > > I think you also need to add something in to handle discontinuities in
> > > trace - for example it is possible to configure the ETM to only trace
> > > execution in specific code regions or to trace a few cycles every so
> > > often. In these cases, prev_packet->sample_type will not be zero, but
> > > whatever the previous packet was. You will get a CS_ETM_TRACE_ON packet in
> > > such cases, generated by an I_TRACE_ON element in the trace stream.
> > > You also get this on exception return.
> > >
> > > However, you should also keep the test for prev_packet->sample_type == 0
> > > as you may not see a CS_ETM_TRACE_ON when decoding a buffer that has
> > > wrapped.
> > Thanks for reviewing. Let's dig more detailed into this issue,
> > especially for handling packet CS_ETM_TRACE_ON, I'd like divide into two
> > sub cases.
> >
> > - The first case is for using python script:
> >
> > I use python script to analyze packets with below command:
> > ./perf script --itrace=ril128 -s arm-cs-trace-disasm.py -F cpu,event,ip,addr,sym -- -v -d objdump -k ./vmlinux
> >
> > What I observe is after we pass python script with parameter '-s
> > arm-cs-trace-disasm.py', then instruction tracing options
> > '--itrace=ril128' isn't really used; the perf tool creates another
> > new process for launch python script and re-enter cmd_script()
> > function, but at the second time when invoke cmd_script() for python
> > script execution the option '--itrace=ril128' is dropped and all
> > parameters are only valid defined by the python script.
> >
> > As result, I can the variable 'etmq->etm->synth_opts.last_branch' is
> > always FALSE for running python script. So all CS_ETM_TRACE_ON
> > packets will be ignored in the function cs_etm__flush().
> >
> > Even the CS_ETM_TRACE_ON packets are missed to handle, the program
> > flow still can work well. The reason is without the interference by
> > CS_ETM_TRACE_ON, the CS_ETM_RANGE packets can smoothly create
> > instruction range by ignore the middle CS_ETM_TRACE_ON packet.
> >
> > Please see below example, in this example there have 3 packets, the
> > first one packet is CS_ETM_RANGE packet which is labelled with
> > 'PACKET_1', the first one packet can properly generate branch sample
> > data with previous packet as expected; the second packet is
> > PACKET_2 which is CS_ETM_TRACE_ON, but
> > 'etmq->etm->synth_opts.last_branch' is false so function
> > cs_etm__flush() doesn't handle it and skip the swap operation
> > "etmq->prev_packet = tmp"; the third packet is PACKET_3, which is
> > CS_ETM_RANGE packet and we can see it's smoontly to create
> > continous instruction range between PACKET_1 and PACKET_3.
> >
> > cs_etm__sample: prev_packet: sample_type=1 exc=0 exc_ret=0 cpu=1 start_addr=0xffff000008a5f79c end_addr=0xffff000008a5f7bc last_instr_taken_branch=1
> > PACKET_1: cs_etm__sample: packet: sample_type=1 exc=0 exc_ret=0 cpu=1 start_addr=0xffff000008a5f858 end_addr=0xffff000008a5f864 last_instr_taken_branch=1
> > cs_etm__synth_branch_sample: ip=0xffff000008a5f7b8 addr=0xffff000008a5f858 pid=2290 tid=2290 id=1000000021 stream_id=1000000021 period=1 cpu=1 flags=0 cpumode=2
> >
> > cs_etm__flush: prev_packet: sample_type=1 exc=0 exc_ret=0 cpu=1 start_addr=0xffff000008a5f858 end_addr=0xffff000008a5f864 last_instr_taken_branch=1
> > PACKET_2: cs_etm__flush: packet: sample_type=2 exc=0 exc_ret=0 cpu=2 start_addr=0xdeadbeefdeadbeef end_addr=0xdeadbeefdeadbeef last_instr_taken_branch=1
> >
> > cs_etm__sample: prev_packet: sample_type=1 exc=0 exc_ret=0 cpu=1 start_addr=0xffff000008a5f858 end_addr=0xffff000008a5f864 last_instr_taken_branch=1
> > PACKET_3: cs_etm__sample: packet: sample_type=1 exc=0 exc_ret=0 cpu=2 start_addr=0xffff000008be7528 end_addr=0xffff000008be7538 last_instr_taken_branch=1
> > cs_etm__synth_branch_sample: ip=0xffff000008a5f860 addr=0xffff000008be7528 pid=2290 tid=2290 id=1000000021 stream_id=1000000021 period=1 cpu=2 flags=0 cpumode=2
> >
> > So seems to me, the CS_ETM_TRACE_ON packet doesn't introduce trouble
> > for the program flow analysis if we can handle all CS_ETM_RANGE
> > packets and without handling CS_ETM_TRACE_ON packet for branch
> > samples.
> >
> > - The second case is for --itrace option without python script:
> > ./perf script --itrace=ril -F cpu,event,ip,addr,sym -k ./vmlinux
> >
> > In this case, the flag 'etmq->etm->synth_opts.last_branch' is true
> > so CS_ETM_TRACE_ON packet will be handled; but I can observe the
> > CS_ETM_RANGE packet in etmq->prev_packet isn't handled in the
> > function cs_etm__flush() for branch sample, so actually we miss some
> > branch sample for this case.
> >
> > So I think we also need handle CS_ETM_RANGE packet in function
> > cs_etm__flush() to generate branch samples. But this has side
> > effect, we introduce the extra track for CS_ETM_TRACE_ON packet for
> > branch samples, so we will see one branch range like:
> > [ 0xdeadbeefdeadbeef .. 0xdeadbeefdeadbeef ].
> >
> > Please reivew below change is okay for you? Thanks a lot for
> > suggestions.
> >
> > diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
> > index 822ba91..37d3722 100644
> > --- a/tools/perf/util/cs-etm.c
> > +++ b/tools/perf/util/cs-etm.c
> > @@ -495,6 +495,13 @@ static inline void cs_etm__reset_last_branch_rb(struct cs_etm_queue *etmq)
> > static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
> > {
> > /*
> > + * The packet is the start tracing packet if the end_addr is zero,
> > + * returns 0 for this case.
> > + */
> > + if (!packet->end_addr)
> > + return 0;
> > +
> > + /*
> > * The packet records the execution range with an exclusive end address
> > *
> > * A64 instructions are constant size, so the last executed
> > @@ -897,13 +904,28 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
> > etmq->period_instructions = instrs_over;
> > }
> > - if (etm->sample_branches &&
> > - etmq->prev_packet &&
> > - etmq->prev_packet->sample_type == CS_ETM_RANGE &&
> > - etmq->prev_packet->last_instr_taken_branch) {
> > - ret = cs_etm__synth_branch_sample(etmq);
> > - if (ret)
> > - return ret;
> > + if (etm->sample_branches && etmq->prev_packet) {
> > + bool generate_sample = false;
> > +
> > + /* Generate sample for start tracing packet */
> > + if (etmq->prev_packet->sample_type == 0 ||
> > + etmq->prev_packet->sample_type == CS_ETM_TRACE_ON)
> > + generate_sample = true;
> > +
> > + /* Generate sample for exception packet */
> > + if (etmq->prev_packet->exc == true)
> > + generate_sample = true;
> > +
> > + /* Generate sample for normal branch packet */
> > + if (etmq->prev_packet->sample_type == CS_ETM_RANGE &&
> > + etmq->prev_packet->last_instr_taken_branch)
> > + generate_sample = true;
> > +
> > + if (generate_sample) {
> > + ret = cs_etm__synth_branch_sample(etmq);
> > + if (ret)
> > + return ret;
> > + }
> > }
> > if (etm->sample_branches || etm->synth_opts.last_branch) {
> > @@ -921,12 +943,17 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
> > static int cs_etm__flush(struct cs_etm_queue *etmq)
> > {
> > + struct cs_etm_auxtrace *etm = etmq->etm;
> > int err = 0;
> > struct cs_etm_packet *tmp;
> > - if (etmq->etm->synth_opts.last_branch &&
> > - etmq->prev_packet &&
> > - etmq->prev_packet->sample_type == CS_ETM_RANGE) {
> > + if (!etmq->prev_packet)
> > + return 0;
> > +
> > + if (etmq->prev_packet->sample_type != CS_ETM_RANGE)
> > + return 0;
> > +
> > + if (etmq->etm->synth_opts.last_branch) {
> > /*
> > * Generate a last branch event for the branches left in the
> > * circular buffer at the end of the trace.
> > @@ -939,18 +966,25 @@ static int cs_etm__flush(struct cs_etm_queue *etmq)
> > err = cs_etm__synth_instruction_sample(
> > etmq, addr,
> > etmq->period_instructions);
> > + if (err)
> > + return err;
> > etmq->period_instructions = 0;
> > + }
> > - /*
> > - * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
> > - * the next incoming packet.
> > - */
> > - tmp = etmq->packet;
> > - etmq->packet = etmq->prev_packet;
> > - etmq->prev_packet = tmp;
> > + if (etm->sample_branches) {
> > + err = cs_etm__synth_branch_sample(etmq);
> > + if (err)
> > + return err;
> > }
> > - return err;
> > + /*
> > + * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
> > + * the next incoming packet.
> > + */
> > + tmp = etmq->packet;
> > + etmq->packet = etmq->prev_packet;
> > + etmq->prev_packet = tmp;
> > + return 0;
> > }
> > static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
^ permalink raw reply
* [PATCH 1/6] coresight: remove CORESIGHT_LINKS_AND_SINKS dependencies and selections
From: Mathieu Poirier @ 2018-05-25 15:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524183027.dc498058344604e2d6027eff@arm.com>
On 24 May 2018 at 17:30, Kim Phillips <kim.phillips@arm.com> wrote:
> On Thu, 24 May 2018 09:32:48 -0600
> Mathieu Poirier <mathieu.poirier@linaro.org> wrote:
>
>> On 23 May 2018 at 13:51, Kim Phillips <kim.phillips@arm.com> wrote:
>> > On Tue, 22 May 2018 11:31:40 -0600
>> > Mathieu Poirier <mathieu.poirier@linaro.org> wrote:
>> >
>> >> On Thu, May 17, 2018 at 08:20:19PM -0500, Kim Phillips wrote:
>> >> > A coresight topology doesn't need to include links, i.e., a source can
>> >> > be directly connected to a sink. As such, selecting and/or depending on
>> >> > LINKS_AND_SINKS is no longer needed.
>> >>
>> >> I'm good with this patch but now the help text for CORESIGHT_LINKS_AND_SINKS no
>> >> longer match what the config does. I see two ways to fix this:
>> >
>> > This patch doesn't change what the config does, it just changes what
>> > other config options depend on it.
>> >
>> >> 1) Rework the help text.
>> >
>> > I don't see how, given the above. Here's the text:
>> >
>> > config CORESIGHT_LINKS_AND_SINKS
>> > bool "CoreSight Link and Sink drivers"
>> > help
>> > This enables support for CoreSight link and sink drivers that are
>> > responsible for transporting and collecting the trace data
>> > respectively. Link and sinks are dynamically aggregated with a trace
>> > entity at run time to form a complete trace path.
>> >
>> > What part of that becomes invalid with this patch?
>>
>> Looking at the new Kconfig, what sink component depend on
>> CORESIGHT_LINKS_AND_SINKS?
>
> How does that affect the description text? The description text
> doesn't insinuate any implicit dependencies or non-.
Now that the depends are gone there is no correlation between this
config and sinks.
>
>> config CORESIGHT_LINKS
>
> Please, not another gratuitous config name change, I've already
> experienced usage regressions from the CORESIGHT_QCOM_REPLICATOR =>
> CORESIGHT_DYNAMIC_REPLICATOR change:
Defines within subsystems are bound to change as they evolves. Most
of the CoreSight subsystem was developed on the OMAP3 based
beagleboard. Since then new topologies have emerged and new IP blocks
came along. It is only normal that we adjust configuration options to
reflect the reality of the HW the subsystem is managing. I can guide
you through the history of the replicator config name change if you
want - it is quite logical. Other than that and until this patchset,
we haven't modified a single configuration in the 5 years the
subsystem has existed. Not bad for all the churn and new IP blocks
that came in.
>
> https://patchwork.kernel.org/patch/10206023/
>
>> bool "CoreSight Link drivers"
>> help
>> This enables support for CoreSight link drivers that are responsible
>> for transporting trace data from source to sink. Links are
>> dynamically
>> aggregated with other traces entities at run time to form a
>> complete trace
>> path.
>
> Oh, I see, so your point is that LINKS_AND_SINKS doesn't technically
> build any sink drivers? That's completely orthogonal to removing a
> dependency chain: that just tells me the name was a poor choice in the
> first place maybe? I don't see where the Makefile may have built a
> sink, but it may be before the move to drivers/hwtracing/coresight, or
> some other reorganization.
Because of the depends property carried by the sink drivers (which we
are now removing), defining CORESIGHT_LINKS_AND_SINKS was mandatory to
build sink drivers. That was accurate 5 years ago with the topologies
that were available at that time. Now there is no point in having the
define, which is why I'm asking you to make this modification.
>
>> >> 2) Rework CORESIGHT_LINKS_AND_SINKS to be CORESIGHT_FUNNEL and move
>> >> coresight-replicator.o under CORESIGHT_DYNAMIC_REPLICATOR in the Makefile. I
>> >> really liked your idea of making the replicator driver intelligent enough to
>> >> deal with both DT and platform declaration, which merges two driver into one.
>> >>
>> >> I'm obviously favouring the second option but recognise it doesn't have to be
>> >> part of this patchet. So for this set please rework the help text for
>> >> CORESIGHT_LINKS_AND_SINKS. Once we've dealt with this topic we can refactor the
>> >> replicator driver.
>> >
>> > I'd really like to just focus on getting CoreSight to load as modules,
>> > something for which this patch isn't technically required...
>>
>> The only thing I'm asking is that the config description and help text
>> reflect what the Makefile does.
>
> argh, wellll, it's a completely different change, and we're now
> completely off the modularization topic, and I'm uncomfortable doing
I don't agree with you. This is a very simple change and I even wrote
down what needed to be modified.
> reorgs on things I don't understand, renaming CONFIG_s, esp. when
> others such as the REPLICATOR, since as far as I know, that's also a
> link??
Correct, a replicator is a link and completely removed from this conversation.
If this is so hard for you then simply don't make the modification - I
will do it myself, something that will take me about 10 minutes
(including writing the changelog).
>
> Kim
^ permalink raw reply
* [PATCH v5 2/2] arm64: signal: Report signal frame size to userspace via auxv
From: Will Deacon @ 2018-05-25 15:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527261428-6662-3-git-send-email-Dave.Martin@arm.com>
On Fri, May 25, 2018 at 04:17:08PM +0100, Dave Martin wrote:
> Stateful CPU architecture extensions may require the signal frame
> to grow to a size that exceeds the arch's MINSIGSTKSZ #define.
> However, changing this #define is an ABI break.
>
> To allow userspace the option of determining the signal frame size
> in a more forwards-compatible way, this patch adds a new auxv entry
> tagged with AT_MINSIGSTKSZ, which provides the maximum signal frame
> size that the process can observe during its lifetime.
>
> If AT_MINSIGSTKSZ is absent from the aux vector, the caller can
> assume that the MINSIGSTKSZ #define is sufficient. This allows for
> a consistent interface with older kernels that do not provide
> AT_MINSIGSTKSZ.
>
> The idea is that libc could expose this via sysconf() or some
> similar mechanism.
>
> There is deliberately no AT_SIGSTKSZ. The kernel knows nothing
> about userspace's own stack overheads and should not pretend to
> know.
Thanks, Dave.
Acked-by: Will Deacon <will.deacon@arm.com>
Will
^ permalink raw reply
* [PATCH v5 2/2] arm64: signal: Report signal frame size to userspace via auxv
From: Dave Martin @ 2018-05-25 15:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527261428-6662-1-git-send-email-Dave.Martin@arm.com>
Stateful CPU architecture extensions may require the signal frame
to grow to a size that exceeds the arch's MINSIGSTKSZ #define.
However, changing this #define is an ABI break.
To allow userspace the option of determining the signal frame size
in a more forwards-compatible way, this patch adds a new auxv entry
tagged with AT_MINSIGSTKSZ, which provides the maximum signal frame
size that the process can observe during its lifetime.
If AT_MINSIGSTKSZ is absent from the aux vector, the caller can
assume that the MINSIGSTKSZ #define is sufficient. This allows for
a consistent interface with older kernels that do not provide
AT_MINSIGSTKSZ.
The idea is that libc could expose this via sysconf() or some
similar mechanism.
There is deliberately no AT_SIGSTKSZ. The kernel knows nothing
about userspace's own stack overheads and should not pretend to
know.
For arm64:
The primary motivation for this interface is the Scalable Vector
Extension, which can require at least 4KB or so of extra space
in the signal frame for the largest hardware implementations.
To determine the correct value, a "Christmas tree" mode (via the
add_all argument) is added to setup_sigframe_layout(), to simulate
addition of all possible records to the signal frame at maximum
possible size.
If this procedure goes wrong somehow, resulting in a stupidly large
frame layout and hence failure of sigframe_alloc() to allocate a
record to the frame, then this is indicative of a kernel bug. In
this case, we WARN() and no attempt is made to populate
AT_MINSIGSTKSZ for userspace.
For arm64 SVE:
The SVE context block in the signal frame needs to be considered
too when computing the maximum possible signal frame size.
Because the size of this block depends on the vector length, this
patch computes the size based not on the thread's current vector
length but instead on the maximum possible vector length: this
determines the maximum size of SVE context block that can be
observed in any signal frame for the lifetime of the process.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Alex Benn?e <alex.bennee@linaro.org>
---
Changes since v4:
Requested by Will Deacon:
* Fix typo in ARCH_INFO comment.
* Remove special-casing of minsigstksz_setup() failure. Just
WARN() and don't populate AT_MINSIGSTKSZ for userspace in this
case, rather than trying to make an intelligent guess about
how to populate it when the kernel is obviously broken.
---
arch/arm64/include/asm/elf.h | 11 ++++++++
arch/arm64/include/asm/processor.h | 5 ++++
arch/arm64/include/uapi/asm/auxvec.h | 3 ++-
arch/arm64/kernel/cpufeature.c | 1 +
arch/arm64/kernel/signal.c | 52 +++++++++++++++++++++++++++++++-----
5 files changed, 64 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index fac1c4d..8cf112b 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -121,6 +121,9 @@
#ifndef __ASSEMBLY__
+#include <linux/bug.h>
+#include <asm/processor.h> /* for signal_minsigstksz, used by ARCH_DLINFO */
+
typedef unsigned long elf_greg_t;
#define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t))
@@ -148,6 +151,14 @@ typedef struct user_fpsimd_state elf_fpregset_t;
do { \
NEW_AUX_ENT(AT_SYSINFO_EHDR, \
(elf_addr_t)current->mm->context.vdso); \
+ \
+ /* \
+ * Should always be nonzero unless there's a kernel bug. \
+ * If we haven't determined a sensible value to give to \
+ * userspace, omit the entry: \
+ */ \
+ if (likely(signal_minsigstksz)) \
+ NEW_AUX_ENT(AT_MINSIGSTKSZ, signal_minsigstksz); \
} while (0)
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 7675989..65ab83e 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -35,6 +35,8 @@
#ifdef __KERNEL__
#include <linux/build_bug.h>
+#include <linux/cache.h>
+#include <linux/init.h>
#include <linux/stddef.h>
#include <linux/string.h>
@@ -244,6 +246,9 @@ void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused);
void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused);
void cpu_clear_disr(const struct arm64_cpu_capabilities *__unused);
+extern unsigned long __ro_after_init signal_minsigstksz; /* sigframe size */
+extern void __init minsigstksz_setup(void);
+
/* Userspace interface for PR_SVE_{SET,GET}_VL prctl()s: */
#define SVE_SET_VL(arg) sve_set_current_vl(arg)
#define SVE_GET_VL() sve_get_current_vl()
diff --git a/arch/arm64/include/uapi/asm/auxvec.h b/arch/arm64/include/uapi/asm/auxvec.h
index ec0a86d..743c0b8 100644
--- a/arch/arm64/include/uapi/asm/auxvec.h
+++ b/arch/arm64/include/uapi/asm/auxvec.h
@@ -19,7 +19,8 @@
/* vDSO location */
#define AT_SYSINFO_EHDR 33
+#define AT_MINSIGSTKSZ 51 /* stack needed for signal delivery */
-#define AT_VECTOR_SIZE_ARCH 1 /* entries in ARCH_DLINFO */
+#define AT_VECTOR_SIZE_ARCH 2 /* entries in ARCH_DLINFO */
#endif
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 9d1b06d..0e0b53d 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1619,6 +1619,7 @@ void __init setup_cpu_features(void)
pr_info("emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching\n");
sve_setup();
+ minsigstksz_setup();
/* Advertise that we have computed the system capabilities */
set_sys_caps_initialised();
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 154b7d3..e7da5db 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -17,6 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/cache.h>
#include <linux/compat.h>
#include <linux/errno.h>
#include <linux/kernel.h>
@@ -570,8 +571,15 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
return 0;
}
-/* Determine the layout of optional records in the signal frame */
-static int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
+/*
+ * Determine the layout of optional records in the signal frame
+ *
+ * add_all: if true, lays out the biggest possible signal frame for
+ * this task; otherwise, generates a layout for the current state
+ * of the task.
+ */
+static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
+ bool add_all)
{
int err;
@@ -581,7 +589,7 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
return err;
/* fault information, if valid */
- if (current->thread.fault_code) {
+ if (add_all || current->thread.fault_code) {
err = sigframe_alloc(user, &user->esr_offset,
sizeof(struct esr_context));
if (err)
@@ -591,8 +599,14 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
if (system_supports_sve()) {
unsigned int vq = 0;
- if (test_thread_flag(TIF_SVE))
- vq = sve_vq_from_vl(current->thread.sve_vl);
+ if (add_all || test_thread_flag(TIF_SVE)) {
+ int vl = sve_max_vl;
+
+ if (!add_all)
+ vl = current->thread.sve_vl;
+
+ vq = sve_vq_from_vl(vl);
+ }
err = sigframe_alloc(user, &user->sve_offset,
SVE_SIG_CONTEXT_SIZE(vq));
@@ -603,7 +617,6 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
return sigframe_alloc_end(user);
}
-
static int setup_sigframe(struct rt_sigframe_user_layout *user,
struct pt_regs *regs, sigset_t *set)
{
@@ -701,7 +714,7 @@ static int get_sigframe(struct rt_sigframe_user_layout *user,
int err;
init_user_layout(user);
- err = setup_sigframe_layout(user);
+ err = setup_sigframe_layout(user, false);
if (err)
return err;
@@ -936,3 +949,28 @@ asmlinkage void do_notify_resume(struct pt_regs *regs,
thread_flags = READ_ONCE(current_thread_info()->flags);
} while (thread_flags & _TIF_WORK_MASK);
}
+
+unsigned long __ro_after_init signal_minsigstksz;
+
+/*
+ * Determine the stack space required for guaranteed signal devliery.
+ * This function is used to populate AT_MINSIGSTKSZ at process startup.
+ * cpufeatures setup is assumed to be complete.
+ */
+void __init minsigstksz_setup(void)
+{
+ struct rt_sigframe_user_layout user;
+
+ init_user_layout(&user);
+
+ /*
+ * If this fails, SIGFRAME_MAXSZ needs to be enlarged. It won't
+ * be big enough, but it's our best guess:
+ */
+ if (WARN_ON(setup_sigframe_layout(&user, true)))
+ return;
+
+ signal_minsigstksz = sigframe_size(&user) +
+ round_up(sizeof(struct frame_record), 16) +
+ 16; /* max alignment padding */
+}
--
2.1.4
^ permalink raw reply related
* [PATCH v5 1/2] arm64/sve: Thin out initialisation sanity-checks for sve_max_vl
From: Dave Martin @ 2018-05-25 15:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527261428-6662-1-git-send-email-Dave.Martin@arm.com>
Now that the kernel SVE support is reasonably mature, it is
excessive to default sve_max_vl to the invalid value -1 and then
sprinkle WARN_ON()s around the place to make sure it has been
initialised before use. The cpufeatures code already runs pretty
early, and will ensure sve_max_vl gets initialised.
This patch initialises sve_max_vl to something sane that will be
supported by every SVE implementation, and removes most of the
sanity checks.
The checks in find_supported_vector_length() are retained for now.
If anything goes horribly wrong, we are likely to trip a check here
sooner or later.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Acked-by: Will Deacon <will.deacon@arm.com>
---
arch/arm64/kernel/fpsimd.c | 17 ++++-------------
arch/arm64/kernel/ptrace.c | 3 ---
2 files changed, 4 insertions(+), 16 deletions(-)
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 87a3536..f9ec640 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -129,7 +129,7 @@ static int sve_default_vl = -1;
#ifdef CONFIG_ARM64_SVE
/* Maximum supported vector length across all CPUs (initially poisoned) */
-int __ro_after_init sve_max_vl = -1;
+int __ro_after_init sve_max_vl = SVE_VL_MIN;
/* Set of available vector lengths, as vq_to_bit(vq): */
static __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
static void __percpu *efi_sve_state;
@@ -360,22 +360,13 @@ static int sve_proc_do_default_vl(struct ctl_table *table, int write,
return ret;
/* Writing -1 has the special meaning "set to max": */
- if (vl == -1) {
- /* Fail safe if sve_max_vl wasn't initialised */
- if (WARN_ON(!sve_vl_valid(sve_max_vl)))
- vl = SVE_VL_MIN;
- else
- vl = sve_max_vl;
-
- goto chosen;
- }
+ if (vl == -1)
+ vl = sve_max_vl;
if (!sve_vl_valid(vl))
return -EINVAL;
- vl = find_supported_vector_length(vl);
-chosen:
- sve_default_vl = vl;
+ sve_default_vl = find_supported_vector_length(vl);
return 0;
}
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 7ff81fe..577deb0 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -766,9 +766,6 @@ static void sve_init_header_from_task(struct user_sve_header *header,
vq = sve_vq_from_vl(header->vl);
header->max_vl = sve_max_vl;
- if (WARN_ON(!sve_vl_valid(sve_max_vl)))
- header->max_vl = header->vl;
-
header->size = SVE_PT_SIZE(vq, header->flags);
header->max_size = SVE_PT_SIZE(sve_vq_from_vl(header->max_vl),
SVE_PT_REGS_SVE);
--
2.1.4
^ permalink raw reply related
* [PATCH v5 0/2] arm64: signal: Report signal frame size to userspace via auxv
From: Dave Martin @ 2018-05-25 15:17 UTC (permalink / raw)
To: linux-arm-kernel
This series adds support for telling userspace the size of the signal
frame via a new AT_MINSIGSTKSZ entry in the aux vector.
This is an update to [1]. Changes are minor. The main difference is
that no attempt is made to give userspace a sensible AT_MINSIGSTKSZ if
initialisation goes wrong, since this is indicative of a kernel bug
anyway.
See individual patches for the delta.
[1] [PATCH v4 0/2] arm64: signal: Report signal frame size to userspace via auxv
http://lists.infradead.org/pipermail/linux-arm-kernel/2018-May/580284.html
Dave Martin (2):
arm64/sve: Thin out initialisation sanity-checks for sve_max_vl
arm64: signal: Report signal frame size to userspace via auxv
arch/arm64/include/asm/elf.h | 11 ++++++++
arch/arm64/include/asm/processor.h | 5 ++++
arch/arm64/include/uapi/asm/auxvec.h | 3 ++-
arch/arm64/kernel/cpufeature.c | 1 +
arch/arm64/kernel/fpsimd.c | 17 +++---------
arch/arm64/kernel/ptrace.c | 3 ---
arch/arm64/kernel/signal.c | 52 +++++++++++++++++++++++++++++++-----
7 files changed, 68 insertions(+), 24 deletions(-)
--
2.1.4
^ permalink raw reply
* [PATCH] mtd: nand: raw: atmel: add module param to avoid using dma
From: Tudor Ambarus @ 2018-05-25 14:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <959d826d-1a98-ca22-acee-a4548427fcd3@microchip.com>
Hi, Peter,
On 04/11/2018 06:34 PM, Nicolas Ferre wrote:
> I'll try to move forward with your detailed explanation and with my
> contacts within the "product" team internally.
We have talked with the hardware team, looks like there is an error in
the description of the Master to Slave Access matrix. CPU accesses DDR2
port0 through AXI matrix and not AHB. There is no conflict between CPU
and LCDC DMA when accessing DDR2 ports. This explains why using CPU
helps.
The slave numbers from "Table 14-3 Master to Slave Access" are wrong.
The 7th row should be removed and all the other rows from below it,
shifted up with one level (DDR2 Port 1 is Slave no 7, DDR2 port 2 is
Slave no 8, ... , APB1 is slave no 11).
We think the best way is to keep LCD on DDR Ports 2 and 3 (8th and 9th
slaves), to have maximum bandwidth and to use DMA on DDR port 1 for NAND
(7th slave).
Also, some information about your configuration is useful. Can you
please tell us what NAND DMA configuration did you use? Are you using
NAND storage for the videos that you are playing on the LCD screen?
Thanks,
ta
^ permalink raw reply
* [GIT PULL] late omap soc changes for v4.18 merge window
From: Tony Lindgren @ 2018-05-25 14:51 UTC (permalink / raw)
To: linux-arm-kernel
From: "Tony Lindgren" <tony@atomide.com>
The following changes since commit 3bb3799cd4233b7c24622ae8c41455fb27a55c0f:
Merge branch 'omap-for-v4.18/soc-fixes' into omap-for-v4.18/soc (2018-05-21 10:34:17 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v4.18/soc-late-signed
for you to fetch changes up to 759c27bdc77577aaecb6f31768e5951a858f97a9:
OMAP: CLK: CLKSRC: Add suspend resume hooks (2018-05-23 14:16:26 -0700)
----------------------------------------------------------------
Late omap soc changes for v4.18 merge window
This series contains two omap1 ams-delta GPIO clean-up patches to get
started with removal of hard-coded GPIO numbers from drivers. And then
the removal of board mach includes from drivers. The second patch mostly
touches the ams-delta audio driver but is included here because of the
removal of the latch gpios and is acked by Mark Brown.
And there are two more am437x related PM patches to save and restore
control module and timer registers for RTC only suspend mode. Looks like
the patch title for the timer changes is a bit misleading, not all the
timer code is yet living under drivers/clocksource. But I had already
pushed out the branch before I noticed this.
----------------------------------------------------------------
Janusz Krzysztofik (2):
ARM: OMAP1: ams-delta: add GPIO lookup tables
ASoC: ams_delta: use GPIO lookup table
Keerthy (1):
OMAP: CLK: CLKSRC: Add suspend resume hooks
Tero Kristo (1):
ARM: AM43XX: Add functions to save/restore am43xx control registers
arch/arm/mach-omap1/board-ams-delta.c | 107 ++++++++++++++++++++++++++++++--
arch/arm/mach-omap2/control.c | 112 ++++++++++++++++++++++++++++++++++
arch/arm/mach-omap2/control.h | 61 ++++++++++++++++++
arch/arm/mach-omap2/timer.c | 32 ++++++++++
sound/soc/omap/ams-delta.c | 38 ++++++------
5 files changed, 328 insertions(+), 22 deletions(-)
^ permalink raw reply
* [PATCH v4 2/2] arm64: signal: Report signal frame size to userspace via auxv
From: Dave Martin @ 2018-05-25 14:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525113251.GB3255@arm.com>
On Fri, May 25, 2018 at 12:32:51PM +0100, Will Deacon wrote:
> On Thu, May 24, 2018 at 06:07:13PM +0100, Dave Martin wrote:
> > On Thu, May 24, 2018 at 05:50:48PM +0100, Will Deacon wrote:
> > > On Thu, May 24, 2018 at 04:55:17PM +0100, Dave Martin wrote:
> > > > On Thu, May 24, 2018 at 01:49:21PM +0100, Will Deacon wrote:
> > > > > On Wed, May 23, 2018 at 06:46:56PM +0100, Dave Martin wrote:
> > > > > > @@ -936,3 +949,28 @@ asmlinkage void do_notify_resume(struct pt_regs *regs,
> > > > > > thread_flags = READ_ONCE(current_thread_info()->flags);
> > > > > > } while (thread_flags & _TIF_WORK_MASK);
> > > > > > }
> > > > > > +
> > > > > > +unsigned long __ro_after_init signal_minsigstksz;
> > > > > > +
> > > > > > +/*
> > > > > > + * Determine the stack space required for guaranteed signal devliery.
> > > > > > + * This function is used to populate AT_MINSIGSTKSZ at process startup.
> > > > > > + * cpufeatures setup is assumed to be complete.
> > > > > > + */
> > > > > > +void __init minsigstksz_setup(void)
> > > > > > +{
> > > > > > + struct rt_sigframe_user_layout user;
> > > > > > +
> > > > > > + init_user_layout(&user);
> > > > > > +
> > > > > > + /*
> > > > > > + * If this fails, SIGFRAME_MAXSZ needs to be enlarged. It won't
> > > > > > + * be big enough, but it's our best guess:
> > > > > > + */
> > > > > > + if (WARN_ON(setup_sigframe_layout(&user, true)))
> > > > > > + signal_minsigstksz = SIGFRAME_MAXSZ;
> > > > >
> > > > > Can we not leave signal_minsigstksz as zero in this case?
> > > >
> > > > I prefer to distinguish the "kernel went wrong" case (where we just omit
> > > > AT_MINSIGSTKSZ for backwards compatibilty) from the "sigframe too
> > > > large" case.
> > >
> > > Hmm, so I'm confused as to the distinction here. Wouldn't an allocation
> > > failure in setup_sigframe_layout be indicative of "kernel went wrong"?
> > >
> > > To put it another way, if we could determine the maximum sigframe size
> > > at build time, surely we'd fail the build if SIGFRAME_MAXSZ wasn't big
> > > enough? In that case, detecting this at runtime is also pretty bad (hence
> >
> > Yup
>
> Good, I was starting to worry I was missing something!
>
> > > the WARN_ON) and I think we should drop the aux entry rather than provide
> > > a value that is known to be incorrect.
> >
> > Telling userspace the signal frame size is not optional: by omitting
> > AT_MINSIGSTKSZ we implicitly tell userspace than MINSIGSTKSZ
> > is sufficient. But in this case we not only know that this is false, we
> > know that SIGFRAME_MAXSZ is not sufficient either. But we also know
> > that SIGFRAME_MAXSZ is a closer estimate to the true requirement, because
> > it's the larger value.
> >
> > This falls under the heading of "being no more wrong than necessary".
>
> I think I just prefer distinguishing between "AT_MINSIGSTKSZ isn't
> present, I'll assume MINSIGSTKSZ is sufficient but it might not be" and
> "AT_MINSIGSTKSZ is present, I know that it's sufficient".
>
> > Either way, this is trying to paper over a kernel bug, by telling
> > userspace something "sensible". This may not be a sensible course
> > of action...
> >
> > So if you feel strongly I'm happy to not distinguish the two cases and
> > just WARN() in minsigstksz_setup() as at present.
>
> Yes, please.
OK, will do. This saves on explanations at least.
Cheers
---Dave
^ permalink raw reply
* [PATCH v11 4/4] Revert "arm64: Enforce BBM for huge IO/VMAP mappings"
From: Chintan Pandya @ 2018-05-25 14:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527258489-30473-1-git-send-email-cpandya@codeaurora.org>
This commit 15122ee2c515a ("arm64: Enforce BBM for huge
IO/VMAP mappings") is a temporary work-around until the
issues with CONFIG_HAVE_ARCH_HUGE_VMAP gets fixed.
Revert this change as we have fixes for the issue.
Signed-off-by: Chintan Pandya <cpandya@codeaurora.org>
---
arch/arm64/mm/mmu.c | 8 --------
1 file changed, 8 deletions(-)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 5f2da5c..c71e9df 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -935,10 +935,6 @@ int pud_set_huge(pud_t *pudp, phys_addr_t phys, pgprot_t prot)
pgprot_t sect_prot = __pgprot(PUD_TYPE_SECT |
pgprot_val(mk_sect_prot(prot)));
- /* ioremap_page_range doesn't honour BBM */
- if (pud_present(READ_ONCE(*pudp)))
- return 0;
-
BUG_ON(phys & ~PUD_MASK);
set_pud(pudp, pfn_pud(__phys_to_pfn(phys), sect_prot));
return 1;
@@ -949,10 +945,6 @@ int pmd_set_huge(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot)
pgprot_t sect_prot = __pgprot(PMD_TYPE_SECT |
pgprot_val(mk_sect_prot(prot)));
- /* ioremap_page_range doesn't honour BBM */
- if (pmd_present(READ_ONCE(*pmdp)))
- return 0;
-
BUG_ON(phys & ~PMD_MASK);
set_pmd(pmdp, pfn_pmd(__phys_to_pfn(phys), sect_prot));
return 1;
--
Qualcomm India Private Limited, on behalf of Qualcomm Innovation
Center, Inc., is a member of Code Aurora Forum, a Linux Foundation
Collaborative Project
^ permalink raw reply related
* [PATCH v11 3/4] arm64: Implement page table free interfaces
From: Chintan Pandya @ 2018-05-25 14:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527258489-30473-1-git-send-email-cpandya@codeaurora.org>
Implement pud_free_pmd_page() and pmd_free_pte_page().
Implementation requires,
1) Clearing off the current pud/pmd entry
2) Invalidate TLB which could have previously
valid but not stale entry
3) Freeing of the un-used next level page tables
Signed-off-by: Chintan Pandya <cpandya@codeaurora.org>
---
arch/arm64/mm/mmu.c | 38 ++++++++++++++++++++++++++++++++++----
1 file changed, 34 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index da98828..5f2da5c 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -45,6 +45,7 @@
#include <asm/memblock.h>
#include <asm/mmu_context.h>
#include <asm/ptdump.h>
+#include <asm/tlbflush.h>
#define NO_BLOCK_MAPPINGS BIT(0)
#define NO_CONT_MAPPINGS BIT(1)
@@ -973,12 +974,41 @@ int pmd_clear_huge(pmd_t *pmdp)
return 1;
}
-int pud_free_pmd_page(pud_t *pud, unsigned long addr)
+int pmd_free_pte_page(pmd_t *pmdp, unsigned long addr)
{
- return pud_none(*pud);
+ pte_t *table;
+ pmd_t pmd;
+
+ pmd = READ_ONCE(*pmdp);
+ if (pmd_present(pmd)) {
+ table = __va(pmd_page_paddr(pmd));
+ pmd_clear(pmdp);
+ __flush_tlb_kernel_pgtable(addr);
+ pte_free_kernel(NULL, table);
+ }
+ return 1;
}
-int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
+int pud_free_pmd_page(pud_t *pudp, unsigned long addr)
{
- return pmd_none(*pmd);
+ pmd_t *table;
+ pmd_t *entry;
+ pud_t pud;
+ unsigned long next, end;
+
+ pud = READ_ONCE(*pudp);
+ if (pud_present(pud)) {
+ table = __va(pud_page_paddr(pud));
+ entry = table;
+ next = addr;
+ end = addr + PUD_SIZE;
+ do {
+ pmd_free_pte_page(entry, next);
+ } while (entry++, next += PMD_SIZE, next != end);
+
+ pud_clear(pudp);
+ __flush_tlb_kernel_pgtable(addr);
+ pmd_free(NULL, table);
+ }
+ return 1;
}
--
Qualcomm India Private Limited, on behalf of Qualcomm Innovation
Center, Inc., is a member of Code Aurora Forum, a Linux Foundation
Collaborative Project
^ permalink raw reply related
* [PATCH v11 2/4] arm64: tlbflush: Introduce __flush_tlb_kernel_pgtable
From: Chintan Pandya @ 2018-05-25 14:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527258489-30473-1-git-send-email-cpandya@codeaurora.org>
Add an interface to invalidate intermediate page tables
from TLB for kernel.
Signed-off-by: Chintan Pandya <cpandya@codeaurora.org>
---
arch/arm64/include/asm/tlbflush.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index dfc61d7..a4a1901 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -218,6 +218,13 @@ static inline void __flush_tlb_pgtable(struct mm_struct *mm,
dsb(ish);
}
+static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr)
+{
+ unsigned long addr = __TLBI_VADDR(kaddr, 0);
+
+ __tlbi(vaae1is, addr);
+ dsb(ish);
+}
#endif
#endif
--
Qualcomm India Private Limited, on behalf of Qualcomm Innovation
Center, Inc., is a member of Code Aurora Forum, a Linux Foundation
Collaborative Project
^ permalink raw reply related
* [PATCH v11 1/4] ioremap: Update pgtable free interfaces with addr
From: Chintan Pandya @ 2018-05-25 14:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527258489-30473-1-git-send-email-cpandya@codeaurora.org>
From: Chintan Pandya <cpandya@codeaurora.org>
The following kernel panic was observed on ARM64 platform due to a stale
TLB entry.
1. ioremap with 4K size, a valid pte page table is set.
2. iounmap it, its pte entry is set to 0.
3. ioremap the same address with 2M size, update its pmd entry with
a new value.
4. CPU may hit an exception because the old pmd entry is still in TLB,
which leads to a kernel panic.
Commit b6bdb7517c3d ("mm/vmalloc: add interfaces to free unmapped page
table") has addressed this panic by falling to pte mappings in the above
case on ARM64.
To support pmd mappings in all cases, TLB purge needs to be performed
in this case on ARM64.
Add a new arg, 'addr', to pud_free_pmd_page() and pmd_free_pte_page()
so that TLB purge can be added later in seprate patches.
[toshi at hpe.com: merge changes, rewrite patch description]
Fixes: 28ee90fe6048 ("x86/mm: implement free pmd/pte page interfaces")
Signed-off-by: Chintan Pandya <cpandya@codeaurora.org>
Signed-off-by: Toshi Kani <toshi.kani@hpe.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: <stable@vger.kernel.org>
---
arch/arm64/mm/mmu.c | 4 ++--
arch/x86/mm/pgtable.c | 8 +++++---
include/asm-generic/pgtable.h | 8 ++++----
lib/ioremap.c | 4 ++--
4 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 2dbb2c9..da98828 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -973,12 +973,12 @@ int pmd_clear_huge(pmd_t *pmdp)
return 1;
}
-int pud_free_pmd_page(pud_t *pud)
+int pud_free_pmd_page(pud_t *pud, unsigned long addr)
{
return pud_none(*pud);
}
-int pmd_free_pte_page(pmd_t *pmd)
+int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
{
return pmd_none(*pmd);
}
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index ffc8c13..37e3cba 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -718,11 +718,12 @@ int pmd_clear_huge(pmd_t *pmd)
/**
* pud_free_pmd_page - Clear pud entry and free pmd page.
* @pud: Pointer to a PUD.
+ * @addr: Virtual address associated with pud.
*
* Context: The pud range has been unmaped and TLB purged.
* Return: 1 if clearing the entry succeeded. 0 otherwise.
*/
-int pud_free_pmd_page(pud_t *pud)
+int pud_free_pmd_page(pud_t *pud, unsigned long addr)
{
pmd_t *pmd;
int i;
@@ -733,7 +734,7 @@ int pud_free_pmd_page(pud_t *pud)
pmd = (pmd_t *)pud_page_vaddr(*pud);
for (i = 0; i < PTRS_PER_PMD; i++)
- if (!pmd_free_pte_page(&pmd[i]))
+ if (!pmd_free_pte_page(&pmd[i], addr + (i * PMD_SIZE)))
return 0;
pud_clear(pud);
@@ -745,11 +746,12 @@ int pud_free_pmd_page(pud_t *pud)
/**
* pmd_free_pte_page - Clear pmd entry and free pte page.
* @pmd: Pointer to a PMD.
+ * @addr: Virtual address associated with pmd.
*
* Context: The pmd range has been unmaped and TLB purged.
* Return: 1 if clearing the entry succeeded. 0 otherwise.
*/
-int pmd_free_pte_page(pmd_t *pmd)
+int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
{
pte_t *pte;
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index f59639a..b081794 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -1019,8 +1019,8 @@ static inline int p4d_clear_huge(p4d_t *p4d)
int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot);
int pud_clear_huge(pud_t *pud);
int pmd_clear_huge(pmd_t *pmd);
-int pud_free_pmd_page(pud_t *pud);
-int pmd_free_pte_page(pmd_t *pmd);
+int pud_free_pmd_page(pud_t *pud, unsigned long addr);
+int pmd_free_pte_page(pmd_t *pmd, unsigned long addr);
#else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
static inline int p4d_set_huge(p4d_t *p4d, phys_addr_t addr, pgprot_t prot)
{
@@ -1046,11 +1046,11 @@ static inline int pmd_clear_huge(pmd_t *pmd)
{
return 0;
}
-static inline int pud_free_pmd_page(pud_t *pud)
+static inline int pud_free_pmd_page(pud_t *pud, unsigned long addr)
{
return 0;
}
-static inline int pmd_free_pte_page(pmd_t *pmd)
+static inline int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
{
return 0;
}
diff --git a/lib/ioremap.c b/lib/ioremap.c
index 54e5bba..517f585 100644
--- a/lib/ioremap.c
+++ b/lib/ioremap.c
@@ -92,7 +92,7 @@ static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr,
if (ioremap_pmd_enabled() &&
((next - addr) == PMD_SIZE) &&
IS_ALIGNED(phys_addr + addr, PMD_SIZE) &&
- pmd_free_pte_page(pmd)) {
+ pmd_free_pte_page(pmd, addr)) {
if (pmd_set_huge(pmd, phys_addr + addr, prot))
continue;
}
@@ -119,7 +119,7 @@ static inline int ioremap_pud_range(p4d_t *p4d, unsigned long addr,
if (ioremap_pud_enabled() &&
((next - addr) == PUD_SIZE) &&
IS_ALIGNED(phys_addr + addr, PUD_SIZE) &&
- pud_free_pmd_page(pud)) {
+ pud_free_pmd_page(pud, addr)) {
if (pud_set_huge(pud, phys_addr + addr, prot))
continue;
}
--
Qualcomm India Private Limited, on behalf of Qualcomm Innovation
Center, Inc., is a member of Code Aurora Forum, a Linux Foundation
Collaborative Project
^ permalink raw reply related
* [PATCH v11 0/4] Fix issues with huge mapping in ioremap for ARM64
From: Chintan Pandya @ 2018-05-25 14:28 UTC (permalink / raw)
To: linux-arm-kernel
This series of patches re-bring huge vmap back for arm64.
Patch 1/4 has been taken by Toshi in his series of patches
by name "[PATCH v3 0/3] fix free pmd/pte page handlings on x86"
to avoid merge conflict with this series.
Patch 4/4 may conflict with Laura's patch "[PATCHv2] arm64: Make
sure permission updates happen for pmd/pud". It looks to me that,
problem addressed by this patch will also get resolved by below
series of patches. There could be multiple ways to resolve this.
I would let maintainer suggest the best approach, and I will do
the needful.
These patches are tested on 4.16 kernel with Cortex-A75 based SoC.
The test used for verifying these patches is a stress test on
ioremap/unmap which tries to re-use same io-address but changes
size of mapping randomly i.e. 4K to 2M to 16K etc. The same test
used to reproduce 3rd level translation fault without these fixes
(and also of course with Revert "arm64: Enforce BBM for huge IO/VMAP
mappings" being part of the tree).
These patches can also go into '-stable' branch (if accepted)
for 4.6 onwards.
>From V10->V11:
- Updated pud_free_pmd_page & pmd_free_pte_page to use consistent
conding style
- Fixed few bugs by using pmd_page_paddr & pud_page_paddr
>From V9->V10:
- Updated commit log for patch 1/4 by Toshi
- Addressed review comments by Will on patch 3/4
>From V8->V9:
- Used __TLBI_VADDR macros in new TLB flush API
>From V7->V8:
- Properly fixed compilation issue in x86 file
>From V6->V7:
- Fixed compilation issue in x86 case
- V6 patches were not properly enumarated
>From V5->V6:
- Use __flush_tlb_kernel_pgtable() for both PUD and PMD. Remove
"bool tlb_inv" based variance as it is not need now
- Re-naming for consistency
>From V4->V5:
- Add new API __flush_tlb_kernel_pgtable(unsigned long addr)
for kernel addresses
>From V3->V4:
- Add header for 'addr' in x86 implementation
- Re-order pmd/pud clear and table free
- Avoid redundant TLB invalidatation in one perticular case
>From V2->V3:
- Use the exisiting page table free interface to do arm64
specific things
>From V1->V2:
- Rebased my patches on top of "[PATCH v2 1/2] mm/vmalloc:
Add interfaces to free unmapped page table"
- Honored BBM for ARM64
Chintan Pandya (4):
ioremap: Update pgtable free interfaces with addr
arm64: tlbflush: Introduce __flush_tlb_kernel_pgtable
arm64: Implement page table free interfaces
Revert "arm64: Enforce BBM for huge IO/VMAP mappings"
arch/arm64/include/asm/tlbflush.h | 7 ++++++
arch/arm64/mm/mmu.c | 46 +++++++++++++++++++++++++++++----------
arch/x86/mm/pgtable.c | 8 ++++---
include/asm-generic/pgtable.h | 8 +++----
lib/ioremap.c | 4 ++--
5 files changed, 52 insertions(+), 21 deletions(-)
--
Qualcomm India Private Limited, on behalf of Qualcomm Innovation
Center, Inc., is a member of Code Aurora Forum, a Linux Foundation
Collaborative Project
^ permalink raw reply
* [PATCH v2 5/5] MAINTAINERS: Add Actions Semi S900 pinctrl entries
From: Manivannan Sadhasivam @ 2018-05-25 14:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACRpkdaTQOWA_5nyasxTwE=cGRis+uaLhw66pmkd+qPxMC6FFQ@mail.gmail.com>
On Fri, May 25, 2018 at 02:12:06PM +0200, Linus Walleij wrote:
> On Fri, May 25, 2018 at 7:01 AM, Manivannan Sadhasivam
> <manivannan.sadhasivam@linaro.org> wrote:
>
> > FYI, I have ordered S700 based Cubieboard and will work on adding support for
> > that first. I still don't have access to S500 board yet since it is not
> > available on my region. Will find a way to get this asap.
>
> Awesome, then we can count on some actions action here.
>
Oops... Small correction here, I have ordered S500 based board.
> >> Also I had been investing efforts in explaining the upstreaming process
> >> to Actions, last in November. I see Thomas Liau and Jeff Chen missing in
> >> CC and I have not seen any Reviewed-by or Acked-by from anyone at
> >> Actions on this and the preceding series. There are more chips than the
> >> one on Linaro's 96board, so I would prefer to assure that the design
> >> works for all. Thus I am very critical of you applying the patches
> >> without waiting for review by Actions.
> >
> > I don't think Actions would be interested in any upstreaming efforts. It
> > is our (comunity) responsibility to add support for that in order to
> > have our boards running mainline kernel and that's what we both have been
> > doing. Moreover I only saw once David Liau responded to your patchset and
> > there isn't much further. So how can you expect the subsystem maintainer's
> > to hold the patch series waiting for a so far silent SoC manufacturer's
> > response?
>
> They are certainly informed now! :D
>
> Actions semi folks, please familiarize yourself with the following:
> https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git/tree/Documentation/devicetree/bindings/pinctrl/actions,s900-pinctrl.txt?h=devel
> https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git/tree/drivers/pinctrl/actions?h=devel
>
> If you have any concerns with this, now is a good time to share them.
>
> > I
> > did ask you to add me as Co-Maintainer but you didn't responded to that.
> > I know that I can't send any pull requests to Arnd, but we should sort
> > it out IMO. Also, if you are completely swamped, then I take take up the
> > maintainership role now inorder to keep the things moving. TBH I don't
> > want my patches to be floating for months without any reason.
>
> Doing some comainatinership can very well include doing pull
> requests as long as you agree on who does what.
>
> I think it may be a bit late for the next merge window right now,
> but if you simply queue up stuff in some git tree and ask
> Srothwell to include it in linux-next then Andreas can very well
> pull it to his tree from there and then to ARM SoC or you can
> queue patches as well.
>
Cool. Will queue up all approved dts patches in a git tree and share it with
andreas.
Thanks,
Mani
> Yours,
> Linus Walleij
^ permalink raw reply
* [PATCH] ARM: dts: imx51-zii-rdu1: Make sure SD1_WP is low
From: Lucas Stach @ 2018-05-25 14:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525030153.15986-1-andrew.smirnov@gmail.com>
Am Donnerstag, den 24.05.2018, 20:01 -0700 schrieb Andrey Smirnov:
> Make sure that MX51_PAD_GPIO1_1 does not remain configure as
> ALT0/SD1_WP (it is out of reset). This is needed because of external
> pull-up resistor attached to that pad that, when left unchanged, will
> drive SD1_WP high preventing eSDHC1/eMMC from working correctly.
>
> To fix that add a pinmux configuration line configureing the pad to
> function as a GPIO. While we are at it, add a corresponding input GPIO
> hog in an effort to minimize current consumption.
Enabling the input part of the pad also consumes (a small amount of)
power, if you are after minimizing power consumption, better configure
the pin as output and drive it in the pull direction.
>
> > Cc: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
> > Cc: Shawn Guo <shawnguo@kernel.org>
> > Cc: Fabio Estevam <fabio.estevam@nxp.com>
> > Cc: Lucas Stach <l.stach@pengutronix.de>
> > Cc: Chris Healy <cphealy@gmail.com>
> > Cc: Rob Herring <robh+dt@kernel.org>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: devicetree at vger.kernel.org
> Cc: linux-kernel at vger.kernel.org
> > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
> ---
> ?arch/arm/boot/dts/imx51-zii-rdu1.dts | 28 ++++++++++++++++++++++++++++
> ?1 file changed, 28 insertions(+)
>
> diff --git a/arch/arm/boot/dts/imx51-zii-rdu1.dts b/arch/arm/boot/dts/imx51-zii-rdu1.dts
> index df9eca94d812..d484e7e46b27 100644
> --- a/arch/arm/boot/dts/imx51-zii-rdu1.dts
> +++ b/arch/arm/boot/dts/imx51-zii-rdu1.dts
> @@ -476,6 +476,17 @@
> > ? status = "okay";
> ?};
> ?
> +&gpio1 {
> > + unused-sd3-wp-gpio {
> > + /*
> > + ?* See pinctrl_esdhc1 below for more details on this
> > + ?*/
> > + gpio-hog;
> > + gpios = <1 GPIO_ACTIVE_HIGH>;
> > + input;
> > + };
> +};
> +
> ?&i2c2 {
> > ? pinctrl-names = "default";
> > ? pinctrl-0 = <&pinctrl_i2c2>;
> @@ -660,6 +671,23 @@
> > > ? MX51_PAD_SD1_DATA1__SD1_DATA1 0x20d5
> > > ? MX51_PAD_SD1_DATA2__SD1_DATA2 0x20d5
> > > ? MX51_PAD_SD1_DATA3__SD1_DATA3 0x20d5
> > + /*
> > + ?* GPIO1_1 is not directly used by eSDHC1 in
> > + ?* any capacity, but earlier versions of RDU1
> > + ?* used that pin as WP GPIO for eSDHC3 and
> > + ?* because of that that pad has an external
> > + ?* pull-up resistor. This is problematic
> > + ?* because out of reset the pad is configured
> > + ?* as ALT0 which serves as SD1_WP, which, when
> > + ?* pulled high by and external pull-up, will
> > + ?* inhibit execution of any write request to
> > + ?* attached eMMC device.
> > + ?*
> > + ?* To avoid this problem we configure the pad
> > +???????????????? ?* to ALT1/GPIO and avoid driving SD1_WP
> +???????????????? ?* signal high.
Applying the patch complains about whitespace damage in the above 2
lines.
Regards,
Lucas
^ permalink raw reply
* [PATCH v2 39/40] iommu/arm-smmu-v3: Add support for PRI
From: Bharat Kumar Gogada @ 2018-05-25 14:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180511190641.23008-40-jean-philippe.brucker@arm.com>
>
> For PCI devices that support it, enable the PRI capability and handle PRI Page
> Requests with the generic fault handler. It is enabled on demand by
> iommu_sva_device_init().
>
> Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
>
> ---
> v1->v2:
> * Terminate the page request and disable PRI if no handler is registered
> * Enable and disable PRI in sva_device_init/shutdown, instead of
> add/remove_device
> ---
> drivers/iommu/arm-smmu-v3.c | 192 +++++++++++++++++++++++++++-------
> --
> 1 file changed, 145 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
> index 6cb69ace371b..0edbb8d19579 100644
> --- a/drivers/iommu/arm-smmu-v3.c
> +++ b/drivers/iommu/arm-smmu-v3.c
> @@ -248,6 +248,7 @@
> #define STRTAB_STE_1_S1COR GENMASK_ULL(5, 4)
> #define STRTAB_STE_1_S1CSH GENMASK_ULL(7, 6)
>
> +#define STRTAB_STE_1_PPAR (1UL << 18)
> #define STRTAB_STE_1_S1STALLD (1UL << 27)
>
> #define STRTAB_STE_1_EATS GENMASK_ULL(29, 28)
> @@ -309,6 +310,9 @@
> #define CMDQ_PRI_0_SID GENMASK_ULL(63, 32)
> #define CMDQ_PRI_1_GRPID GENMASK_ULL(8, 0)
> #define CMDQ_PRI_1_RESP GENMASK_ULL(13, 12)
> +#define CMDQ_PRI_1_RESP_FAILURE
> FIELD_PREP(CMDQ_PRI_1_RESP, 0UL)
> +#define CMDQ_PRI_1_RESP_INVALID
> FIELD_PREP(CMDQ_PRI_1_RESP, 1UL)
> +#define CMDQ_PRI_1_RESP_SUCCESS
> FIELD_PREP(CMDQ_PRI_1_RESP, 2UL)
>
> #define CMDQ_RESUME_0_SID GENMASK_ULL(63, 32)
> #define CMDQ_RESUME_0_ACTION_RETRY (1UL << 12)
> @@ -383,12 +387,6 @@ module_param_named(disable_ats_check,
> disable_ats_check, bool, S_IRUGO);
> MODULE_PARM_DESC(disable_ats_check,
> "By default, the SMMU checks whether each incoming transaction
> marked as translated is allowed by the stream configuration. This option
> disables the check.");
>
> -enum pri_resp {
> - PRI_RESP_DENY = 0,
> - PRI_RESP_FAIL = 1,
> - PRI_RESP_SUCC = 2,
> -};
> -
> enum arm_smmu_msi_index {
> EVTQ_MSI_INDEX,
> GERROR_MSI_INDEX,
> @@ -471,7 +469,7 @@ struct arm_smmu_cmdq_ent {
> u32 sid;
> u32 ssid;
> u16 grpid;
> - enum pri_resp resp;
> + enum page_response_code resp;
> } pri;
>
> #define CMDQ_OP_RESUME 0x44
> @@ -556,6 +554,7 @@ struct arm_smmu_strtab_ent {
> struct arm_smmu_s2_cfg *s2_cfg;
>
> bool can_stall;
> + bool prg_resp_needs_ssid;
> };
>
> struct arm_smmu_strtab_cfg {
> @@ -907,14 +906,18 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd,
> struct arm_smmu_cmdq_ent *ent)
> cmd[0] |= FIELD_PREP(CMDQ_PRI_0_SID, ent->pri.sid);
> cmd[1] |= FIELD_PREP(CMDQ_PRI_1_GRPID, ent->pri.grpid);
> switch (ent->pri.resp) {
> - case PRI_RESP_DENY:
> - case PRI_RESP_FAIL:
> - case PRI_RESP_SUCC:
> + case IOMMU_PAGE_RESP_FAILURE:
> + cmd[1] |= CMDQ_PRI_1_RESP_FAILURE;
> + break;
> + case IOMMU_PAGE_RESP_INVALID:
> + cmd[1] |= CMDQ_PRI_1_RESP_INVALID;
> + break;
> + case IOMMU_PAGE_RESP_SUCCESS:
> + cmd[1] |= CMDQ_PRI_1_RESP_SUCCESS;
> break;
> default:
> return -EINVAL;
> }
> - cmd[1] |= FIELD_PREP(CMDQ_PRI_1_RESP, ent->pri.resp);
> break;
> case CMDQ_OP_RESUME:
> cmd[0] |= FIELD_PREP(CMDQ_RESUME_0_SID, ent-
> >resume.sid); @@ -1114,8 +1117,15 @@ static int
> arm_smmu_page_response(struct device *dev,
> cmd.resume.sid = sid;
> cmd.resume.stag = resp->page_req_group_id;
> cmd.resume.resp = resp->resp_code;
> + } else if (master->can_fault) {
> + cmd.opcode = CMDQ_OP_PRI_RESP;
> + cmd.substream_valid = resp->pasid_present &&
> + master->ste.prg_resp_needs_ssid;
> + cmd.pri.sid = sid;
> + cmd.pri.ssid = resp->pasid;
> + cmd.pri.grpid = resp->page_req_group_id;
> + cmd.pri.resp = resp->resp_code;
> } else {
> - /* TODO: put PRI response here */
> return -ENODEV;
> }
>
> @@ -1236,6 +1246,9 @@ static void arm_smmu_write_strtab_ent(struct
> arm_smmu_device *smmu, u32 sid,
> FIELD_PREP(STRTAB_STE_1_S1CSH,
> ARM_SMMU_SH_ISH) |
> FIELD_PREP(STRTAB_STE_1_STRW, strw));
>
> + if (ste->prg_resp_needs_ssid)
> + dst[1] |= STRTAB_STE_1_PPAR;
> +
> if (smmu->features & ARM_SMMU_FEAT_STALLS &&
> !(smmu->features & ARM_SMMU_FEAT_STALL_FORCE) &&
> !ste->can_stall)
> @@ -1471,39 +1484,54 @@ static irqreturn_t arm_smmu_evtq_thread(int
> irq, void *dev)
>
> static void arm_smmu_handle_ppr(struct arm_smmu_device *smmu, u64
> *evt) {
> - u32 sid, ssid;
> - u16 grpid;
> - bool ssv, last;
> -
> - sid = FIELD_GET(PRIQ_0_SID, evt[0]);
> - ssv = FIELD_GET(PRIQ_0_SSID_V, evt[0]);
> - ssid = ssv ? FIELD_GET(PRIQ_0_SSID, evt[0]) : 0;
> - last = FIELD_GET(PRIQ_0_PRG_LAST, evt[0]);
> - grpid = FIELD_GET(PRIQ_1_PRG_IDX, evt[1]);
> -
> - dev_info(smmu->dev, "unexpected PRI request received:\n");
> - dev_info(smmu->dev,
> - "\tsid 0x%08x.0x%05x: [%u%s] %sprivileged %s%s%s access
> at iova 0x%016llx\n",
> - sid, ssid, grpid, last ? "L" : "",
> - evt[0] & PRIQ_0_PERM_PRIV ? "" : "un",
> - evt[0] & PRIQ_0_PERM_READ ? "R" : "",
> - evt[0] & PRIQ_0_PERM_WRITE ? "W" : "",
> - evt[0] & PRIQ_0_PERM_EXEC ? "X" : "",
> - evt[1] & PRIQ_1_ADDR_MASK);
> -
> - if (last) {
> - struct arm_smmu_cmdq_ent cmd = {
> - .opcode =
> CMDQ_OP_PRI_RESP,
> - .substream_valid = ssv,
> - .pri = {
> - .sid = sid,
> - .ssid = ssid,
> - .grpid = grpid,
> - .resp = PRI_RESP_DENY,
> - },
> + u32 sid = FIELD_PREP(PRIQ_0_SID, evt[0]);
> +
> + struct arm_smmu_master_data *master;
> + struct iommu_fault_event fault = {
> + .type = IOMMU_FAULT_PAGE_REQ,
> + .last_req = FIELD_GET(PRIQ_0_PRG_LAST,
> evt[0]),
> + .pasid_valid = FIELD_GET(PRIQ_0_SSID_V, evt[0]),
> + .pasid = FIELD_GET(PRIQ_0_SSID, evt[0]),
> + .page_req_group_id = FIELD_GET(PRIQ_1_PRG_IDX,
> evt[1]),
> + .addr = evt[1] & PRIQ_1_ADDR_MASK,
> + };
> +
> + if (evt[0] & PRIQ_0_PERM_READ)
> + fault.prot |= IOMMU_FAULT_READ;
> + if (evt[0] & PRIQ_0_PERM_WRITE)
> + fault.prot |= IOMMU_FAULT_WRITE;
> + if (evt[0] & PRIQ_0_PERM_EXEC)
> + fault.prot |= IOMMU_FAULT_EXEC;
> + if (evt[0] & PRIQ_0_PERM_PRIV)
> + fault.prot |= IOMMU_FAULT_PRIV;
> +
> + /* Discard Stop PASID marker, it isn't used */
> + if (!(fault.prot & (IOMMU_FAULT_READ|IOMMU_FAULT_WRITE)) &&
> + fault.last_req)
> + return;
> +
> + master = arm_smmu_find_master(smmu, sid);
> + if (WARN_ON(!master))
> + return;
> +
> + if (iommu_report_device_fault(master->dev, &fault)) {
> + /*
> + * No handler registered, so subsequent faults won't produce
> + * better results. Try to disable PRI.
> + */
> + struct page_response_msg page_response = {
> + .addr = fault.addr,
> + .pasid = fault.pasid,
> + .pasid_present = fault.pasid_valid,
> + .page_req_group_id = fault.page_req_group_id,
> + .resp_code =
> IOMMU_PAGE_RESP_FAILURE,
> };
>
> - arm_smmu_cmdq_issue_cmd(smmu, &cmd);
> + dev_warn(master->dev,
> + "PPR 0x%x:0x%llx 0x%x: nobody cared, disabling
> PRI\n",
> + fault.pasid_valid ? fault.pasid : 0, fault.addr,
> + fault.prot);
> + arm_smmu_page_response(master->dev, &page_response);
> }
> }
>
> @@ -1529,6 +1557,11 @@ static irqreturn_t arm_smmu_priq_thread(int irq,
> void *dev)
> }
>
> if (queue_sync_prod(q) == -EOVERFLOW)
> + /*
> + * TODO: flush pending faults, since the SMMU might
> have
> + * auto-responded to the Last request of a pending
> + * group
> + */
> dev_err(smmu->dev, "PRIQ overflow detected --
> requests lost\n");
> } while (!queue_empty(q));
>
> @@ -1577,7 +1610,8 @@ static int arm_smmu_flush_queues(void *cookie,
> struct device *dev)
> master = dev->iommu_fwspec->iommu_priv;
> if (master->ste.can_stall)
> arm_smmu_flush_queue(smmu, &smmu->evtq.q,
> "evtq");
> - /* TODO: add support for PRI */
> + else if (master->can_fault)
> + arm_smmu_flush_queue(smmu, &smmu->priq.q,
> "priq");
> return 0;
> }
>
> @@ -2301,6 +2335,59 @@ arm_smmu_iova_to_phys(struct iommu_domain
> *domain, dma_addr_t iova)
> return ops->iova_to_phys(ops, iova);
> }
>
> +static int arm_smmu_enable_pri(struct arm_smmu_master_data *master) {
> + int ret, pos;
> + struct pci_dev *pdev;
> + /*
> + * TODO: find a good inflight PPR number. We should divide the PRI
> queue
> + * by the number of PRI-capable devices, but it's impossible to know
> + * about current and future (hotplugged) devices. So we're at risk of
> + * dropping PPRs (and leaking pending requests in the FQ).
> + */
> + size_t max_inflight_pprs = 16;
> + struct arm_smmu_device *smmu = master->smmu;
> +
> + if (!(smmu->features & ARM_SMMU_FEAT_PRI) ||
> !dev_is_pci(master->dev))
> + return -ENOSYS;
> +
> + pdev = to_pci_dev(master->dev);
> +
> + ret = pci_reset_pri(pdev);
> + if (ret)
> + return ret;
> +
> + ret = pci_enable_pri(pdev, max_inflight_pprs);
> + if (ret) {
> + dev_err(master->dev, "cannot enable PRI: %d\n", ret);
> + return ret;
> + }
> +
> + master->can_fault = true;
> + master->ste.prg_resp_needs_ssid =
> pci_prg_resp_requires_prefix(pdev);
Any reason why this is not cleared in arm_smmu_disable_pri ?
> +
> + dev_dbg(master->dev, "enabled PRI\n");
> +
> + return 0;
> +}
> +
> +static void arm_smmu_disable_pri(struct arm_smmu_master_data
> *master) {
> + struct pci_dev *pdev;
> +
> + if (!dev_is_pci(master->dev))
> + return;
> +
> + pdev = to_pci_dev(master->dev);
> +
> + if (!pdev->pri_enabled)
> + return;
> +
> + pci_disable_pri(pdev);
> + dev_dbg(master->dev, "disabled PRI\n");
> + master->can_fault = false;
> +}
> +
> static int arm_smmu_sva_init(struct device *dev, struct iommu_sva_param
> *param) {
> int ret;
> @@ -2314,11 +2401,15 @@ static int arm_smmu_sva_init(struct device
> *dev, struct iommu_sva_param *param)
> return -EINVAL;
>
> if (param->features & IOMMU_SVA_FEAT_IOPF) {
> - if (!master->can_fault)
> - return -EINVAL;
> + arm_smmu_enable_pri(master);
> + if (!master->can_fault) {
> + ret = -ENODEV;
> + goto err_disable_pri;
> + }
> +
> ret = iopf_queue_add_device(master->smmu->iopf_queue,
> dev);
> if (ret)
> - return ret;
> + goto err_disable_pri;
> }
>
> if (!param->max_pasid)
> @@ -2329,11 +2420,17 @@ static int arm_smmu_sva_init(struct device
> *dev, struct iommu_sva_param *param)
> param->max_pasid = min(param->max_pasid, (1U << master-
> >ssid_bits) - 1);
>
> return 0;
> +
> +err_disable_pri:
> + arm_smmu_disable_pri(master);
> +
> + return ret;
> }
>
> static void arm_smmu_sva_shutdown(struct device *dev,
> struct iommu_sva_param *param)
> {
> + arm_smmu_disable_pri(dev->iommu_fwspec->iommu_priv);
> iopf_queue_remove_device(dev);
> }
>
> @@ -2671,6 +2768,7 @@ static void arm_smmu_remove_device(struct
> device *dev)
> iommu_group_remove_device(dev);
> arm_smmu_remove_master(smmu, master);
> iommu_device_unlink(&smmu->iommu, dev);
> + arm_smmu_disable_pri(master);
> arm_smmu_disable_ats(master);
> kfree(master);
> iommu_fwspec_free(dev);
> --
> 2.17.0
^ permalink raw reply
* [PATCH v3 6/6] tty/serial: atmel: changed the driver to work under at91-usart mfd
From: Radu Pirea @ 2018-05-25 14:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <f817c82a-95b6-afb3-e662-c481a877cf01@sorico.fr>
On 05/25/2018 04:35 PM, Richard Genoud wrote:
> On 25/05/2018 14:17, Radu Pirea wrote:
>>
>>
>> On 05/15/2018 04:14 PM, Richard Genoud wrote:
>>> On 15/05/2018 14:47, Radu Pirea wrote:
>>>> On Mon, 2018-05-14 at 12:57 +0200, Richard Genoud wrote:
>>>>> After your patch, the DMA is not selected anymore:
>>>>> atmel_usart_serial atmel_usart_serial.0.auto: TX channel not
>>>>> available, switch to pio
>>>>> instead of:
>>>>> atmel_usart fffff200.serial: using dma1chan2 for tx DMA transfers
>>>>>
>>>> Fixed.
>>>>> And the kernel doesn't log anymore on the serial console, despite the
>>>>> loglevel=8
>>>>> (after reverting this series, the kernel logs reappears on the serial
>>>>> console)
>>>>>
>>>> Which serial are you using as console?
>>> fffff200.serial (sam9g35-cm)
>>> ( stdout-path = "serial0:115200n8"; in the DTS )
>>>
>>> With this series applied, all the kernel log goes on the screen.
>>> Without, it goes on the serial debug.
>>>
>> I tested again with archlinux arm and poky-linux4sam release as distros
>> and kernel log goes on the serial debug. Can you give me more details
>> like cmdline?
> I used kernel 4.17-rc6
> at91_dt_defconfig
> at91sam9g35ek.dtb
>
> Kernel command line: root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs
I reproduced your issue.
If in cmdline console is not set like this "console=ttyS0,115200", the
console goes to the lcd.
> ( the one from the DTS )
>
> Detailed instructions:
>
> git checkout v4.17-rc6
> ARCH=arm CROSS_COMPILE=path_to_my_Xchain/arm-linux- LOADADDR=0x20008000 make -j 12 at91_dt_defconfig
> ARCH=arm CROSS_COMPILE=path_to_my_Xchain/arm-linux- LOADADDR=0x20008000 make -j 12 uImage at91sam9g35ek.dtb
> cp arch/arm/boot/uImage arch/arm/boot/dts/at91sam9g35ek.dtb /tftpboot/
>
> From uboot:
> tftpboot 0x20007FC0 uImage
> tftpboot 0x26400000 at91sam9g35ek.dtb
> bootm 0x20007FC0 - 0x26400000
>
> [ I see the logs on the serial debug ]
>
> git am \[PATCH\ v3\ [1-6]*
>
> ARCH=arm CROSS_COMPILE=path_to_my_Xchain/arm-linux- LOADADDR=0x20008000 make -j 12 uImage at91sam9g35ek.dtb
> cp arch/arm/boot/uImage arch/arm/boot/dts/at91sam9g35ek.dtb /tftpboot/
>
> From uboot:
> tftpboot 0x20007FC0 uImage
> tftpboot 0x26400000 at91sam9g35ek.dtb
> bootm 0x20007FC0 - 0x26400000
>
> [ I don't see the logs on the serial debug anymore ]
>
>
>>>>> (tests done on sam9g35)
>>>>>
>>>> I will consider the rest of suggestions.
>>>>> regards,
>>>>> Richard
>>>
>
^ permalink raw reply
* [PATCH] PCI: Try to clean up resources via remove if shutdown doesn't exist
From: Sinan Kaya @ 2018-05-25 14:04 UTC (permalink / raw)
To: linux-arm-kernel
It is up to a driver to implement shutdown() callback. If shutdown()
callback is not implemented, PCI device can have pending interrupt and
even do DMA transactions while the system is going down.
If kexec is in use, this can damage the newly booting kexec kernel
or even prevent it from booting altogether. Fallback to calling the
remove() callback if shutdown() isn't implemented for a given driver.
Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
drivers/pci/pci-driver.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 6ace470..4ac72e3 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -475,8 +475,17 @@ static void pci_device_shutdown(struct device *dev)
pm_runtime_resume(dev);
+ /*
+ * Try shutdown callback if it exists, otherwise fallback to remove
+ * callback. PCI drivers can do DMA and have pending interrupts.
+ * Leaving the DMA and interrupts pending could damage the newly
+ * booting kexec kernel as well as prevent it from booting altogether
+ * if the pending interrupt is level.
+ */
if (drv && drv->shutdown)
drv->shutdown(pci_dev);
+ else if (drv && drv->remove)
+ drv->remove(pci_dev);
/*
* If this is a kexec reboot, turn off Bus Master bit on the
--
2.7.4
^ permalink raw reply related
* [RFT v2 1/4] perf cs-etm: Generate sample for missed packets
From: Robert Walker @ 2018-05-25 14:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180522083920.GD31075@leoy-ThinkPad-X240s>
Hi Leo,
Following the discussions from your reply to this with a simplified
patch, this version of the patch works better as you also need to emit a
branch sample when handling a CS_ETM_TRACE_ON packet to indicate the end
of a block of trace.
This patch does not break the output from perf inject to generate
instruction samples for AutoFDO, so I am happy with that.
Regards
Rob
Reviewed-by: Robert Walker <robert.walker@arm.com>
On 22/05/18 09:39, Leo Yan wrote:
> Hi Rob,
>
> On Mon, May 21, 2018 at 12:27:42PM +0100, Robert Walker wrote:
>> Hi Leo,
>>
>> On 21/05/18 09:52, Leo Yan wrote:
>>> Commit e573e978fb12 ("perf cs-etm: Inject capabilitity for CoreSight
>>> traces") reworks the samples generation flow from CoreSight trace to
>>> match the correct format so Perf report tool can display the samples
>>> properly. But the change has side effect for packet handling, it only
>>> generate samples when 'prev_packet->last_instr_taken_branch' is true,
>>> this results in the start tracing packet and exception packets are
>>> dropped.
>>>
>>> This patch checks extra two conditions for complete samples:
>>>
>>> - If 'prev_packet->sample_type' is zero we can use this condition to
>>> get to know this is the start tracing packet; for this case, the start
>>> packet's end_addr is zero as well so we need to handle it in the
>>> function cs_etm__last_executed_instr();
>>>
>> I think you also need to add something in to handle discontinuities in
>> trace - for example it is possible to configure the ETM to only trace
>> execution in specific code regions or to trace a few cycles every so
>> often. In these cases, prev_packet->sample_type will not be zero, but
>> whatever the previous packet was. You will get a CS_ETM_TRACE_ON packet in
>> such cases, generated by an I_TRACE_ON element in the trace stream.
>> You also get this on exception return.
>>
>> However, you should also keep the test for prev_packet->sample_type == 0
>> as you may not see a CS_ETM_TRACE_ON when decoding a buffer that has
>> wrapped.
> Thanks for reviewing. Let's dig more detailed into this issue,
> especially for handling packet CS_ETM_TRACE_ON, I'd like divide into two
> sub cases.
>
> - The first case is for using python script:
>
> I use python script to analyze packets with below command:
> ./perf script --itrace=ril128 -s arm-cs-trace-disasm.py -F cpu,event,ip,addr,sym -- -v -d objdump -k ./vmlinux
>
> What I observe is after we pass python script with parameter '-s
> arm-cs-trace-disasm.py', then instruction tracing options
> '--itrace=ril128' isn't really used; the perf tool creates another
> new process for launch python script and re-enter cmd_script()
> function, but at the second time when invoke cmd_script() for python
> script execution the option '--itrace=ril128' is dropped and all
> parameters are only valid defined by the python script.
>
> As result, I can the variable 'etmq->etm->synth_opts.last_branch' is
> always FALSE for running python script. So all CS_ETM_TRACE_ON
> packets will be ignored in the function cs_etm__flush().
>
> Even the CS_ETM_TRACE_ON packets are missed to handle, the program
> flow still can work well. The reason is without the interference by
> CS_ETM_TRACE_ON, the CS_ETM_RANGE packets can smoothly create
> instruction range by ignore the middle CS_ETM_TRACE_ON packet.
>
> Please see below example, in this example there have 3 packets, the
> first one packet is CS_ETM_RANGE packet which is labelled with
> 'PACKET_1', the first one packet can properly generate branch sample
> data with previous packet as expected; the second packet is
> PACKET_2 which is CS_ETM_TRACE_ON, but
> 'etmq->etm->synth_opts.last_branch' is false so function
> cs_etm__flush() doesn't handle it and skip the swap operation
> "etmq->prev_packet = tmp"; the third packet is PACKET_3, which is
> CS_ETM_RANGE packet and we can see it's smoontly to create
> continous instruction range between PACKET_1 and PACKET_3.
>
> cs_etm__sample: prev_packet: sample_type=1 exc=0 exc_ret=0 cpu=1 start_addr=0xffff000008a5f79c end_addr=0xffff000008a5f7bc last_instr_taken_branch=1
> PACKET_1: cs_etm__sample: packet: sample_type=1 exc=0 exc_ret=0 cpu=1 start_addr=0xffff000008a5f858 end_addr=0xffff000008a5f864 last_instr_taken_branch=1
> cs_etm__synth_branch_sample: ip=0xffff000008a5f7b8 addr=0xffff000008a5f858 pid=2290 tid=2290 id=1000000021 stream_id=1000000021 period=1 cpu=1 flags=0 cpumode=2
>
> cs_etm__flush: prev_packet: sample_type=1 exc=0 exc_ret=0 cpu=1 start_addr=0xffff000008a5f858 end_addr=0xffff000008a5f864 last_instr_taken_branch=1
> PACKET_2: cs_etm__flush: packet: sample_type=2 exc=0 exc_ret=0 cpu=2 start_addr=0xdeadbeefdeadbeef end_addr=0xdeadbeefdeadbeef last_instr_taken_branch=1
>
> cs_etm__sample: prev_packet: sample_type=1 exc=0 exc_ret=0 cpu=1 start_addr=0xffff000008a5f858 end_addr=0xffff000008a5f864 last_instr_taken_branch=1
> PACKET_3: cs_etm__sample: packet: sample_type=1 exc=0 exc_ret=0 cpu=2 start_addr=0xffff000008be7528 end_addr=0xffff000008be7538 last_instr_taken_branch=1
> cs_etm__synth_branch_sample: ip=0xffff000008a5f860 addr=0xffff000008be7528 pid=2290 tid=2290 id=1000000021 stream_id=1000000021 period=1 cpu=2 flags=0 cpumode=2
>
> So seems to me, the CS_ETM_TRACE_ON packet doesn't introduce trouble
> for the program flow analysis if we can handle all CS_ETM_RANGE
> packets and without handling CS_ETM_TRACE_ON packet for branch
> samples.
>
> - The second case is for --itrace option without python script:
> ./perf script --itrace=ril -F cpu,event,ip,addr,sym -k ./vmlinux
>
> In this case, the flag 'etmq->etm->synth_opts.last_branch' is true
> so CS_ETM_TRACE_ON packet will be handled; but I can observe the
> CS_ETM_RANGE packet in etmq->prev_packet isn't handled in the
> function cs_etm__flush() for branch sample, so actually we miss some
> branch sample for this case.
>
> So I think we also need handle CS_ETM_RANGE packet in function
> cs_etm__flush() to generate branch samples. But this has side
> effect, we introduce the extra track for CS_ETM_TRACE_ON packet for
> branch samples, so we will see one branch range like:
> [ 0xdeadbeefdeadbeef .. 0xdeadbeefdeadbeef ].
>
> Please reivew below change is okay for you? Thanks a lot for
> suggestions.
>
> diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
> index 822ba91..37d3722 100644
> --- a/tools/perf/util/cs-etm.c
> +++ b/tools/perf/util/cs-etm.c
> @@ -495,6 +495,13 @@ static inline void cs_etm__reset_last_branch_rb(struct cs_etm_queue *etmq)
> static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
> {
> /*
> + * The packet is the start tracing packet if the end_addr is zero,
> + * returns 0 for this case.
> + */
> + if (!packet->end_addr)
> + return 0;
> +
> + /*
> * The packet records the execution range with an exclusive end address
> *
> * A64 instructions are constant size, so the last executed
> @@ -897,13 +904,28 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
> etmq->period_instructions = instrs_over;
> }
>
> - if (etm->sample_branches &&
> - etmq->prev_packet &&
> - etmq->prev_packet->sample_type == CS_ETM_RANGE &&
> - etmq->prev_packet->last_instr_taken_branch) {
> - ret = cs_etm__synth_branch_sample(etmq);
> - if (ret)
> - return ret;
> + if (etm->sample_branches && etmq->prev_packet) {
> + bool generate_sample = false;
> +
> + /* Generate sample for start tracing packet */
> + if (etmq->prev_packet->sample_type == 0 ||
> + etmq->prev_packet->sample_type == CS_ETM_TRACE_ON)
> + generate_sample = true;
> +
> + /* Generate sample for exception packet */
> + if (etmq->prev_packet->exc == true)
> + generate_sample = true;
> +
> + /* Generate sample for normal branch packet */
> + if (etmq->prev_packet->sample_type == CS_ETM_RANGE &&
> + etmq->prev_packet->last_instr_taken_branch)
> + generate_sample = true;
> +
> + if (generate_sample) {
> + ret = cs_etm__synth_branch_sample(etmq);
> + if (ret)
> + return ret;
> + }
> }
>
> if (etm->sample_branches || etm->synth_opts.last_branch) {
> @@ -921,12 +943,17 @@ static int cs_etm__sample(struct cs_etm_queue *etmq)
>
> static int cs_etm__flush(struct cs_etm_queue *etmq)
> {
> + struct cs_etm_auxtrace *etm = etmq->etm;
> int err = 0;
> struct cs_etm_packet *tmp;
>
> - if (etmq->etm->synth_opts.last_branch &&
> - etmq->prev_packet &&
> - etmq->prev_packet->sample_type == CS_ETM_RANGE) {
> + if (!etmq->prev_packet)
> + return 0;
> +
> + if (etmq->prev_packet->sample_type != CS_ETM_RANGE)
> + return 0;
> +
> + if (etmq->etm->synth_opts.last_branch) {
> /*
> * Generate a last branch event for the branches left in the
> * circular buffer at the end of the trace.
> @@ -939,18 +966,25 @@ static int cs_etm__flush(struct cs_etm_queue *etmq)
> err = cs_etm__synth_instruction_sample(
> etmq, addr,
> etmq->period_instructions);
> + if (err)
> + return err;
> etmq->period_instructions = 0;
> + }
>
> - /*
> - * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
> - * the next incoming packet.
> - */
> - tmp = etmq->packet;
> - etmq->packet = etmq->prev_packet;
> - etmq->prev_packet = tmp;
> + if (etm->sample_branches) {
> + err = cs_etm__synth_branch_sample(etmq);
> + if (err)
> + return err;
> }
>
> - return err;
> + /*
> + * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
> + * the next incoming packet.
> + */
> + tmp = etmq->packet;
> + etmq->packet = etmq->prev_packet;
> + etmq->prev_packet = tmp;
> + return 0;
> }
>
> static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
^ permalink raw reply
* [PATCH v3 15/15] ARM: KVM: report support for SMCCC_ARCH_WORKAROUND_1
From: Russell King @ 2018-05-25 14:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525135938.GE17671@n2100.armlinux.org.uk>
Report support for SMCCC_ARCH_WORKAROUND_1 to KVM guests for affected
CPUs.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
arch/arm/include/asm/kvm_host.h | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 248b930563e5..11f91744ffb0 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -21,6 +21,7 @@
#include <linux/types.h>
#include <linux/kvm_types.h>
+#include <asm/cputype.h>
#include <asm/kvm.h>
#include <asm/kvm_asm.h>
#include <asm/kvm_mmio.h>
@@ -311,8 +312,17 @@ static inline void kvm_arm_vhe_guest_exit(void) {}
static inline bool kvm_arm_harden_branch_predictor(void)
{
- /* No way to detect it yet, pretend it is not there. */
- return false;
+ switch(read_cpuid_part()) {
+#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
+ case ARM_CPU_PART_BRAHMA_B15:
+ case ARM_CPU_PART_CORTEX_A12:
+ case ARM_CPU_PART_CORTEX_A15:
+ case ARM_CPU_PART_CORTEX_A17:
+ return true;
+#endif
+ default:
+ return false;
+ }
}
#endif /* __ARM_KVM_HOST_H__ */
--
2.7.4
^ permalink raw reply related
* [PATCH v3 14/15] ARM: KVM: Add SMCCC_ARCH_WORKAROUND_1 fast handling
From: Russell King @ 2018-05-25 14:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525135938.GE17671@n2100.armlinux.org.uk>
We want SMCCC_ARCH_WORKAROUND_1 to be fast. As fast as possible.
So let's intercept it as early as we can by testing for the
function call number as soon as we've identified a HVC call
coming from the guest.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
arch/arm/kvm/hyp/hyp-entry.S | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/arch/arm/kvm/hyp/hyp-entry.S b/arch/arm/kvm/hyp/hyp-entry.S
index 918a05dd2d63..aa3f9a9837ac 100644
--- a/arch/arm/kvm/hyp/hyp-entry.S
+++ b/arch/arm/kvm/hyp/hyp-entry.S
@@ -16,6 +16,7 @@
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include <linux/arm-smccc.h>
#include <linux/linkage.h>
#include <asm/kvm_arm.h>
#include <asm/kvm_asm.h>
@@ -202,7 +203,7 @@ ENDPROC(__hyp_do_panic)
lsr r2, r2, #16
and r2, r2, #0xff
cmp r2, #0
- bne guest_trap @ Guest called HVC
+ bne guest_hvc_trap @ Guest called HVC
/*
* Getting here means host called HVC, we shift parameters and branch
@@ -253,6 +254,20 @@ THUMB( orr lr, #1)
pop {r2, lr}
eret
+guest_hvc_trap:
+ movw r2, #:lower16:ARM_SMCCC_ARCH_WORKAROUND_1
+ movt r2, #:upper16:ARM_SMCCC_ARCH_WORKAROUND_1
+ ldr r0, [sp] @ Guest's r0
+ teq r0, r2
+ bne guest_trap
+ add sp, sp, #12
+ @ Returns:
+ @ r0 = 0
+ @ r1 = HSR value (perfectly predictable)
+ @ r2 = ARM_SMCCC_ARCH_WORKAROUND_1
+ mov r0, #0
+ eret
+
guest_trap:
load_vcpu r0 @ Load VCPU pointer to r0
--
2.7.4
^ permalink raw reply related
* [PATCH v3 13/15] ARM: spectre-v2: KVM: invalidate icache on guest exit for Brahma B15
From: Russell King @ 2018-05-25 14:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525135938.GE17671@n2100.armlinux.org.uk>
Include Brahma B15 in the Spectre v2 KVM workarounds.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
---
arch/arm/include/asm/kvm_mmu.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 48edb1f4ced4..fea770f78144 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -306,6 +306,7 @@ static inline void *kvm_get_hyp_vector(void)
return kvm_ksym_ref(__kvm_hyp_vector_bp_inv);
}
+ case ARM_CPU_PART_BRAHMA_B15:
case ARM_CPU_PART_CORTEX_A15:
{
extern char __kvm_hyp_vector_ic_inv[];
--
2.7.4
^ permalink raw reply related
* [PATCH v3 12/15] ARM: KVM: invalidate icache on guest exit for Cortex-A15
From: Russell King @ 2018-05-25 14:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525135938.GE17671@n2100.armlinux.org.uk>
From: Marc Zyngier <marc.zyngier@arm.com>
In order to avoid aliasing attacks against the branch predictor
on Cortex-A15, let's invalidate the BTB on guest exit, which can
only be done by invalidating the icache (with ACTLR[0] being set).
We use the same hack as for A12/A17 to perform the vector decoding.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
arch/arm/include/asm/kvm_mmu.h | 5 +++++
arch/arm/kvm/hyp/hyp-entry.S | 24 ++++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index d08ce9c41df4..48edb1f4ced4 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -306,6 +306,11 @@ static inline void *kvm_get_hyp_vector(void)
return kvm_ksym_ref(__kvm_hyp_vector_bp_inv);
}
+ case ARM_CPU_PART_CORTEX_A15:
+ {
+ extern char __kvm_hyp_vector_ic_inv[];
+ return kvm_ksym_ref(__kvm_hyp_vector_ic_inv);
+ }
#endif
default:
{
diff --git a/arch/arm/kvm/hyp/hyp-entry.S b/arch/arm/kvm/hyp/hyp-entry.S
index e789f52a5129..918a05dd2d63 100644
--- a/arch/arm/kvm/hyp/hyp-entry.S
+++ b/arch/arm/kvm/hyp/hyp-entry.S
@@ -73,6 +73,28 @@
#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
.align 5
+__kvm_hyp_vector_ic_inv:
+ .global __kvm_hyp_vector_ic_inv
+
+ /*
+ * We encode the exception entry in the bottom 3 bits of
+ * SP, and we have to guarantee to be 8 bytes aligned.
+ */
+ W(add) sp, sp, #1 /* Reset 7 */
+ W(add) sp, sp, #1 /* Undef 6 */
+ W(add) sp, sp, #1 /* Syscall 5 */
+ W(add) sp, sp, #1 /* Prefetch abort 4 */
+ W(add) sp, sp, #1 /* Data abort 3 */
+ W(add) sp, sp, #1 /* HVC 2 */
+ W(add) sp, sp, #1 /* IRQ 1 */
+ W(nop) /* FIQ 0 */
+
+ mcr p15, 0, r0, c7, c5, 0 /* ICIALLU */
+ isb
+
+ b decode_vectors
+
+ .align 5
__kvm_hyp_vector_bp_inv:
.global __kvm_hyp_vector_bp_inv
@@ -92,6 +114,8 @@
mcr p15, 0, r0, c7, c5, 6 /* BPIALL */
isb
+decode_vectors:
+
#ifdef CONFIG_THUMB2_KERNEL
/*
* Yet another silly hack: Use VPIDR as a temp register.
--
2.7.4
^ permalink raw reply related
* [PATCH v3 11/15] ARM: KVM: invalidate BTB on guest exit for Cortex-A12/A17
From: Russell King @ 2018-05-25 14:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180525135938.GE17671@n2100.armlinux.org.uk>
From: Marc Zyngier <marc.zyngier@arm.com>
In order to avoid aliasing attacks against the branch predictor,
let's invalidate the BTB on guest exit. This is made complicated
by the fact that we cannot take a branch before invalidating the
BTB.
We only apply this to A12 and A17, which are the only two ARM
cores on which this useful.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
arch/arm/include/asm/kvm_asm.h | 2 --
arch/arm/include/asm/kvm_mmu.h | 17 +++++++++-
arch/arm/kvm/hyp/hyp-entry.S | 71 ++++++++++++++++++++++++++++++++++++++++--
3 files changed, 85 insertions(+), 5 deletions(-)
diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
index 36dd2962a42d..df24ed48977d 100644
--- a/arch/arm/include/asm/kvm_asm.h
+++ b/arch/arm/include/asm/kvm_asm.h
@@ -61,8 +61,6 @@ struct kvm_vcpu;
extern char __kvm_hyp_init[];
extern char __kvm_hyp_init_end[];
-extern char __kvm_hyp_vector[];
-
extern void __kvm_flush_vm_context(void);
extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index de1b919404e4..d08ce9c41df4 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -297,7 +297,22 @@ static inline unsigned int kvm_get_vmid_bits(void)
static inline void *kvm_get_hyp_vector(void)
{
- return kvm_ksym_ref(__kvm_hyp_vector);
+ switch(read_cpuid_part()) {
+#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
+ case ARM_CPU_PART_CORTEX_A12:
+ case ARM_CPU_PART_CORTEX_A17:
+ {
+ extern char __kvm_hyp_vector_bp_inv[];
+ return kvm_ksym_ref(__kvm_hyp_vector_bp_inv);
+ }
+
+#endif
+ default:
+ {
+ extern char __kvm_hyp_vector[];
+ return kvm_ksym_ref(__kvm_hyp_vector);
+ }
+ }
}
static inline int kvm_map_vectors(void)
diff --git a/arch/arm/kvm/hyp/hyp-entry.S b/arch/arm/kvm/hyp/hyp-entry.S
index 95a2faefc070..e789f52a5129 100644
--- a/arch/arm/kvm/hyp/hyp-entry.S
+++ b/arch/arm/kvm/hyp/hyp-entry.S
@@ -71,6 +71,66 @@
W(b) hyp_irq
W(b) hyp_fiq
+#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
+ .align 5
+__kvm_hyp_vector_bp_inv:
+ .global __kvm_hyp_vector_bp_inv
+
+ /*
+ * We encode the exception entry in the bottom 3 bits of
+ * SP, and we have to guarantee to be 8 bytes aligned.
+ */
+ W(add) sp, sp, #1 /* Reset 7 */
+ W(add) sp, sp, #1 /* Undef 6 */
+ W(add) sp, sp, #1 /* Syscall 5 */
+ W(add) sp, sp, #1 /* Prefetch abort 4 */
+ W(add) sp, sp, #1 /* Data abort 3 */
+ W(add) sp, sp, #1 /* HVC 2 */
+ W(add) sp, sp, #1 /* IRQ 1 */
+ W(nop) /* FIQ 0 */
+
+ mcr p15, 0, r0, c7, c5, 6 /* BPIALL */
+ isb
+
+#ifdef CONFIG_THUMB2_KERNEL
+ /*
+ * Yet another silly hack: Use VPIDR as a temp register.
+ * Thumb2 is really a pain, as SP cannot be used with most
+ * of the bitwise instructions. The vect_br macro ensures
+ * things gets cleaned-up.
+ */
+ mcr p15, 4, r0, c0, c0, 0 /* VPIDR */
+ mov r0, sp
+ and r0, r0, #7
+ sub sp, sp, r0
+ push {r1, r2}
+ mov r1, r0
+ mrc p15, 4, r0, c0, c0, 0 /* VPIDR */
+ mrc p15, 0, r2, c0, c0, 0 /* MIDR */
+ mcr p15, 4, r2, c0, c0, 0 /* VPIDR */
+#endif
+
+.macro vect_br val, targ
+ARM( eor sp, sp, #\val )
+ARM( tst sp, #7 )
+ARM( eorne sp, sp, #\val )
+
+THUMB( cmp r1, #\val )
+THUMB( popeq {r1, r2} )
+
+ beq \targ
+.endm
+
+ vect_br 0, hyp_fiq
+ vect_br 1, hyp_irq
+ vect_br 2, hyp_hvc
+ vect_br 3, hyp_dabt
+ vect_br 4, hyp_pabt
+ vect_br 5, hyp_svc
+ vect_br 6, hyp_undef
+ vect_br 7, hyp_reset
+#endif
+
.macro invalid_vector label, cause
.align
\label: mov r0, #\cause
@@ -149,7 +209,14 @@ ENDPROC(__hyp_do_panic)
bx ip
1:
- push {lr}
+ /*
+ * Pushing r2 here is just a way of keeping the stack aligned to
+ * 8 bytes on any path that can trigger a HYP exception. Here,
+ * we may well be about to jump into the guest, and the guest
+ * exit would otherwise be badly decoded by our fancy
+ * "decode-exception-without-a-branch" code...
+ */
+ push {r2, lr}
mov lr, r0
mov r0, r1
@@ -159,7 +226,7 @@ ENDPROC(__hyp_do_panic)
THUMB( orr lr, #1)
blx lr @ Call the HYP function
- pop {lr}
+ pop {r2, lr}
eret
guest_trap:
--
2.7.4
^ 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