* [PATCH v2 0/3] Add R8A7743/SK-RZG1M PFC support
From: Simon Horman @ 2017-04-24 6:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170420185132.258111787@cogentembedded.com>
On Thu, Apr 20, 2017 at 09:51:32PM +0300, Sergei Shtylyov wrote:
> Hello.
>
> Here's the set of 3 patches against Simon Horman's 'renesas.git' repo,
> 'renesas-devel-20170420-v4.11-rc7' tag. We're adding the R8A7743 PFC node
> and then describing the pins for SCIF0 and Ether devices declared earlier.
> These patches depend on the R8A7743 PFC suport in order to work properly.
Thanks. I have marked these as deferred pending acceptance of the PFC
driver changes. Please repost or otherwise let me know when dependency
is satisfied.
^ permalink raw reply
* [PATCH v2 0/9] drm/sun4i: Support multiple display pipelines
From: Maxime Ripard @ 2017-04-24 5:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170421083857.29636-1-wens@csie.org>
On Fri, Apr 21, 2017 at 04:38:48PM +0800, Chen-Yu Tsai wrote:
> Hi,
>
> This is v2 of the series previously named "drm/sun4i: Support two
> display pipelines". As the name change suggests, the driver now
> supports any number of pipelines, though the hardware only has
> 2 or 3.
>
> Changes since v1:
>
> - Add component endpoint ID numbering scheme to device tree binding.
>
> - Use lists to keep references to registered backends and tcons.
>
> - Save pointer to device node for backends.
>
> - Traverse the device tree of_graph starting from the tcons, going
> up towards the inputs, and matching the device nodes with the
> device nodes of registered backends, to find the one linked with
> the tcon the search started from.
>
> - Copy the ID for the tcon from its upstream backend, instead of
> trying, and possibly failing, to figure it out from the device
> tree.
>
> - Split out hunk dropping trailing 0 from a backend error message.
>
> Patch 1 adds the component endpoint ID numbering scheme to the
> device tree binding. New in v2.
>
> Patch 2 adds lists to track registered display backends and TCONs,
> instead of just one pointer per component type. Previously added
> arrays of pointers in v1.
>
> Patch 3 drops the trailing 0 from one of the backend's bind error
> messages. This was previously part of the patch "drm/sun4i: Support
> two display pipelines".
>
> Patch 4 adds a function to fetch a backend's ID from the device tree.
> Unchanged.
>
> Patch 5 adds a device node field to the backend data structure and
> saves a reference to the underlying device node of the backend.
> New in v2.
>
> Patch 6 makes the tcon driver find its upstream backend by traversing
> the of_graph and matching device nodes against the device nodes of
> registered backends.
> New in v2.
>
> Patch 7 makes the tcon driver use the ID from its associated backend.
> New in v2. This is not immediately used in this series, but will be
> used in similar fashion for downstream encoders to figure out IDs and
> muxing
>
> Patch 8 adds device nodes for sun6i's second display pipeline.
> Unchanged.
>
> Patch 9 enables sun6i's tcon0 by default.
> Unchanged.
Applied everything, thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170424/d2d06eab/attachment.sig>
^ permalink raw reply
* linux-next: build failure after merge of the arm tree
From: Vinod Koul @ 2017-04-24 4:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <f89b6045-8c09-f6c4-3893-84f172260926@free.fr>
On Sat, Apr 22, 2017 at 10:41:37AM +0200, Mason wrote:
> On 22/04/2017 01:43, Russell King - ARM Linux wrote:
>
> > Or I drop the offending patch (done) and we get the DMA subsystem fixed
> > first. Given how long it's been this way, I doubt there's any hurry to
> > get this change in for the next merge window.
>
> Your solution makes sense.
>
> Vinod, could you apply [PATCH v2] dmaengine: sun4i: fix invalid argument
> to your tree when you have the time?
Done now..
--
~Vinod
^ permalink raw reply
* Touchscreen failure with CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
From: Viresh Kumar @ 2017-04-24 4:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOMZO5BZ8Z8dfwsfuiunNQ_q39_k4QJg7jLPQfaxn+YBsmz2jw@mail.gmail.com>
On 21-04-17, 13:11, Fabio Estevam wrote:
> Hi,
>
> Running 4.11-rc7 on a imx6q-sabresd board I notice that egalax
> touchscreen stops generating evtest events after a random period of
> time.
>
> This problem can be avoided if I unselect CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND:
>
> --- a/arch/arm/configs/imx_v6_v7_defconfig
> +++ b/arch/arm/configs/imx_v6_v7_defconfig
> @@ -54,7 +54,6 @@ CONFIG_CMA=y
> CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
> CONFIG_KEXEC=y
> CONFIG_CPU_FREQ=y
> -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
> CONFIG_ARM_IMX6Q_CPUFREQ=y
> CONFIG_CPU_IDLE=y
> CONFIG_VFP=y
>
> With this change evtest always capture all touchscreen events. No
> single failure is seen.
>
> I could see the same behavior with all mainline kernels I tested (4.9 and 4.10).
>
> Any ideas as to how fix this bug when CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y?
So as Rafael pointed out the problem doesn't happen if you stay at the max
frequencies, but otherwise.
You need to investigate on why that is the case. You can go to the cpufreq sysfs
directory and see what frequencies are getting selected, etc..
Give me output of this for now:
grep . /sys/devices/system/cpu/cpufreq/policy0/*
grep . /sys/devices/system/cpu/cpufreq/policy0/stats/*
--
viresh
^ permalink raw reply
* [PATCH 1/1] mt7601u: check return value of alloc_skb
From: Jakub Kicinski @ 2017-04-24 3:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492930823-17249-1-git-send-email-bianpan2016@163.com>
On Sun, 23 Apr 2017 15:00:23 +0800, Pan Bian wrote:
> Function alloc_skb() will return a NULL pointer if there is no enough
> memory. However, in function mt7601u_mcu_msg_alloc(), its return value
> is not validated before it is used. This patch fixes it.
>
> Signed-off-by: Pan Bian <bianpan2016@163.com>
Acked-by: Jakub Kicinski <kubakici@wp.pl>
Thanks!
^ permalink raw reply
* [PATCH 1/2 v2] dt-bindings: qoriq-clock: Add coreclk
From: Andy Tang @ 2017-04-24 3:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <DB6PR0402MB283701D478A1678D28894C77F30A0@DB6PR0402MB2837.eurprd04.prod.outlook.com>
Does anyone give me a clue why this patch set can't be responded after so long time?
Thanks,
Andy
-----Original Message-----
From: Andy Tang
Sent: Monday, April 17, 2017 9:37 AM
To: 'mturquette at baylibre.com' <mturquette@baylibre.com>; 'sboyd at codeaurora.org' <sboyd@codeaurora.org>
Cc: 'robh+dt at kernel.org' <robh+dt@kernel.org>; 'mark.rutland at arm.com' <mark.rutland@arm.com>; 'linux-clk at vger.kernel.org' <linux-clk@vger.kernel.org>; 'devicetree at vger.kernel.org' <devicetree@vger.kernel.org>; 'linux-kernel at vger.kernel.org' <linux-kernel@vger.kernel.org>; 'linux-arm-kernel at lists.infradead.org' <linux-arm-kernel@lists.infradead.org>; 'Scott Wood' <oss@buserror.net>
Subject: RE: [PATCH 1/2 v2] dt-bindings: qoriq-clock: Add coreclk
Hi Stephen and Michael,
This patch set has been pending for more than two months since it was first sent.
I have not received any response from you until now.
Could you give some comments on it?
Regards,
Andy
-----Original Message-----
From: Andy Tang
Sent: Wednesday, April 05, 2017 2:16 PM
To: mturquette at baylibre.com; sboyd at codeaurora.org
Cc: robh+dt at kernel.org; mark.rutland at arm.com; linux-clk at vger.kernel.org; devicetree at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-kernel at lists.infradead.org; Scott Wood <oss@buserror.net>
Subject: RE: [PATCH 1/2 v2] dt-bindings: qoriq-clock: Add coreclk
Hello
Do you have any comments on this patch set which was acked by Rob?
Regards,
Andy
> -----Original Message-----
> From: Yuantian Tang [mailto:andy.tang at nxp.com]
> Sent: Monday, March 20, 2017 10:37 AM
> To: mturquette at baylibre.com
> Cc: sboyd at codeaurora.org; robh+dt at kernel.org; mark.rutland at arm.com;
> linux-clk at vger.kernel.org; devicetree at vger.kernel.org; linux-
> kernel at vger.kernel.org; linux-arm-kernel at lists.infradead.org; Scott
> Wood <oss@buserror.net>; Andy Tang <andy.tang@nxp.com>
> Subject: [PATCH 1/2 v2] dt-bindings: qoriq-clock: Add coreclk
>
> From: Scott Wood <oss@buserror.net>
>
> ls1012a has separate input root clocks for core PLLs versus the
> platform PLL, with the latter described as sysclk in the hw docs.
> Update the qoriq-clock binding to allow a second input clock, named
> "coreclk". If present, this clock will be used for the core PLLs.
>
> Signed-off-by: Scott Wood <oss@buserror.net>
> Signed-off-by: Tang Yuantian <andy.tang@nxp.com>
> Acked-by: Rob Herring <robh@kernel.org>
> ---
> v2:
> -- change the author to Scott
> Documentation/devicetree/bindings/clock/qoriq-clock.txt | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/clock/qoriq-clock.txt
> b/Documentation/devicetree/bindings/clock/qoriq-clock.txt
> index aa3526f..119cafd 100644
> --- a/Documentation/devicetree/bindings/clock/qoriq-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/qoriq-clock.txt
> @@ -56,6 +56,11 @@ Optional properties:
> - clocks: If clock-frequency is not specified, sysclk may be provided
> as an input clock. Either clock-frequency or clocks must be
> provided.
> + A second input clock, called "coreclk", may be provided if
> + core PLLs are based on a different input clock from the
> + platform PLL.
> +- clock-names: Required if a coreclk is present. Valid names are
> + "sysclk" and "coreclk".
>
> 2. Clock Provider
>
> @@ -72,6 +77,7 @@ second cell is the clock index for the specified type.
> 2 hwaccel index (n in CLKCGnHWACSR)
> 3 fman 0 for fm1, 1 for fm2
> 4 platform pll 0=pll, 1=pll/2, 2=pll/3, 3=pll/4
> + 5 coreclk must be 0
>
> 3. Example
>
> --
> 2.1.0.27.g96db324
^ permalink raw reply
* [PATCH v5 1/4] printk/nmi: generic solution for safe printk in NMI
From: Sergey Senozhatsky @ 2017-04-24 2:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170421120627.GO3452@pathway.suse.cz>
On (04/21/17 14:06), Petr Mladek wrote:
[..]
> > I agree that this_cpu_read(printk_context) covers slightly more than
> > logbuf_lock scope, so we may get positive this_cpu_read(printk_context)
> > with unlocked logbuf_lock, but I don't tend to think that it's a big
> > problem.
>
> PRINTK_SAFE_CONTEXT is set also in call_console_drivers().
> It might take rather long and logbuf_lock is availe. So, it is
> noticeable source of false positives.
yes, agree.
probably we need additional printk_safe annotations for
"logbuf_lock is locked from _this_ CPU"
false positives there can be very painful.
[..]
> if (raw_spin_is_locked(&logbuf_lock))
> this_cpu_or(printk_context, PRINTK_NMI_CONTEXT_MASK);
> else
> this_cpu_or(printk_context, PRINTK_NMI_DEFERRED_CONTEXT_MASK);
well, if everyone is fine with logbuf_lock access from every CPU from every
NMI then I won't object either. but may be it makes sense to reduce the
possibility of false positives. Steven is loosing critically important logs,
after all.
by the way,
does this `nmi_print_seq' bypass even fix anything for Steven? it sort of
can, in theory, but just in theory. so may be we need direct message flush
from NMI handler (printk->console_unlock), which will be a really big problem.
logbuf might not be big enough for 4890096 messages (Steven's report
mentions "Lost 4890096 message(s)!"). we are counting on the fact that
in case of `nmi_print_seq' bypass some other CPU will call console_unlock()
and print pending logbuf messages, but this is not guaranteed and the
messages can be dropped even from logbuf.
I don't know,
should we try to queue printk_deferred irq_work for all online CPUs from
vprintk_nmi() when it bypasses printk_safe_log_store()? in order to minimize
possibilities of logbuf overflow. printk_deferred() will queue work on
vprintk_nmi() CPU, sure, but we don't know how many messages we are going
to add to logbuf from NMI.
> > @@ -303,7 +303,10 @@ static int vprintk_nmi(const char *fmt, va_list args)
> > {
> > struct printk_safe_seq_buf *s = this_cpu_ptr(&nmi_print_seq);
> >
> > - return printk_safe_log_store(s, fmt, args);
> > + if (this_cpu_read(printk_context) & PRINTK_SAFE_CONTEXT_MASK)
> > + return printk_safe_log_store(s, fmt, args);
> > +
> > + return vprintk_emit(0, LOGLEVEL_SCHED, NULL, 0, fmt, args);
> > }
>
> It looks simple but some things are missing. It will be used also
> outside panic/oops, so it should queue the irq_work to flush the console.
you are right. I thought about moving irq_work to vprintk_emit(), but
completely forgot about it. without that missing bit the proposed two-liner
is not complete.
-ss
^ permalink raw reply
* [PATCH v2 07/11] soc/fsl/qbman: Rework ioremap() calls for ARM/PPC
From: Scott Wood @ 2017-04-24 1:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492634930-10765-8-git-send-email-roy.pledge@nxp.com>
On Wed, 2017-04-19 at 16:48 -0400, Roy Pledge wrote:
> Rework ioremap() for PPC and ARM. The PPC devices require a
> non-coherent mapping while ARM will work with a non-cachable/write
> combine mapping.
>
> Signed-off-by: Roy Pledge <roy.pledge@nxp.com>
> ---
> ?drivers/soc/fsl/qbman/bman_portal.c | 16 +++++++++++++---
> ?drivers/soc/fsl/qbman/qman_portal.c | 16 +++++++++++++---
> ?2 files changed, 26 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/soc/fsl/qbman/bman_portal.c
> b/drivers/soc/fsl/qbman/bman_portal.c
> index 8354d4d..a661f30 100644
> --- a/drivers/soc/fsl/qbman/bman_portal.c
> +++ b/drivers/soc/fsl/qbman/bman_portal.c
> @@ -125,7 +125,18 @@ static int bman_portal_probe(struct platform_device
> *pdev)
> ? }
> ? pcfg->irq = irq;
> ?
> - va = ioremap_prot(addr_phys[0]->start, resource_size(addr_phys[0]),
> 0);
> +#ifdef CONFIG_PPC
> + /* PPC requires a cacheable/non-coherent mapping of the portal */
> + va = ioremap_prot(addr_phys[0]->start, resource_size(addr_phys[0]),
> + ??(pgprot_val(PAGE_KERNEL) & ~_PAGE_COHERENT));
> +#else
> + /*
> + ?* For ARM we can use write combine mapping.??A cacheable/non
> shareable
> + ?* mapping will perform better but equires additional platform
> + ?* support which is not currently available
> + ?*/
s/equires/requires/
Would be nice to describe the platform support that is required.
-Scott
^ permalink raw reply
* [PATCH v2 02/11] soc/fsl/qbman: Use shared-dma-pool for QMan private memory allocations
From: Scott Wood @ 2017-04-24 1:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492634930-10765-3-git-send-email-roy.pledge@nxp.com>
On Wed, 2017-04-19 at 16:48 -0400, Roy Pledge wrote:
> @@ -727,10 +730,81 @@ static int fsl_qman_probe(struct platform_device
> *pdev)
> ? qm_channel_caam = QMAN_CHANNEL_CAAM_REV3;
> ? }
> ?
> - ret = zero_priv_mem(dev, node, fqd_a, fqd_sz);
> - WARN_ON(ret);
> - if (ret)
> - return -ENODEV;
> + if (fqd_a) {
> +#ifdef CONFIG_PPC
> + /*
> + ?* For PPC backward DT compatibility
> + ?* FQD memory MUST be zero'd by software
> + ?*/
> + zero_priv_mem(fqd_a, fqd_sz);
> +#endif
Should probably warn if you get here on non-PPC rather than silently accepting
it.
> + } else {
> + /*
> + ?* Order of memory regions is assumed as FQD followed by
> PFDR
> + ?* in order to ensure allocations from the correct regions
> the
> + ?* driver initializes then allocates each piece in order
> + ?*/
This should be explicitly specified in the binding rather than here.
> + ret = of_reserved_mem_device_init_by_idx(dev, dev->of_node,
> 0);
> + if (ret) {
> + dev_err(dev, "of_reserved_mem_device_init_by_idx(0)
> failed 0x%x\n",
> + ret);
> + return -ENODEV;
> + }
> + mem_node = of_parse_phandle(dev->of_node, "memory-region",
> 0);
> + if (mem_node) {
> + ret = of_property_read_u64(mem_node, "size",
> &size);
> + if (ret) {
> + dev_err(dev, "FQD: of_address_to_resource
> fails 0x%x\n",
> + ret);
> + return -ENODEV;
> + }
> + fqd_sz = size;
> + } else {
> + dev_err(dev, "No memory-region found for FQD\n");
> + return -ENODEV;
> + }
> + if (!dma_zalloc_coherent(dev, fqd_sz, &fqd_a, 0)) {
> + dev_err(dev, "Alloc FQD memory failed\n");
> + return -ENODEV;
> + }
> +
> + /*
> + ?* Disassociate the FQD reseverd memory area from the
> device
> + ?* because a device can only have one DMA memory area. This
> + ?* should be fine since the memory is allocated and
> initialized
> + ?* and only ever accessed by the QMan device from now on
> + ?*/
> + of_reserved_mem_device_release(dev);
s/reseverd/reserved/
> + }
> + dev_info(dev, "Allocated FQD 0x%llx 0x%zx\n", fqd_a, fqd_sz);
dev_dbg()?
-Scott
^ permalink raw reply
* linux-next: build failure after merge of the drm-misc tree
From: Stephen Rothwell @ 2017-04-24 1:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170421121014.3ee14a83@canb.auug.org.au>
Hi all,
On Fri, 21 Apr 2017 12:10:14 +1000 Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>
> After merging the drm-misc tree, today's linux-next build (x86_64
> allmodconfig) failed like this:
>
> drivers/tee/tee_shm.c:87:2: error: unknown field 'kmap_atomic' specified in initializer
> .kmap_atomic = tee_shm_op_kmap_atomic,
> ^
> drivers/tee/tee_shm.c:87:17: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
> .kmap_atomic = tee_shm_op_kmap_atomic,
> ^
> drivers/tee/tee_shm.c:87:17: note: (near initialization for 'tee_shm_dma_buf_ops.begin_cpu_access')
> drivers/tee/tee_shm.c:88:2: error: unknown field 'kmap' specified in initializer
> .kmap = tee_shm_op_kmap,
> ^
> drivers/tee/tee_shm.c:88:10: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
> .kmap = tee_shm_op_kmap,
> ^
> drivers/tee/tee_shm.c:88:10: note: (near initialization for 'tee_shm_dma_buf_ops.end_cpu_access')
>
> Caused by commit
>
> f9b67f0014cb ("dma-buf: Rename dma-ops to prevent conflict with kunmap_atomic macro")
>
> interacting with commit
>
> 967c9cca2cc5 ("tee: generic TEE subsystem")
>
> from the arm-soc tree.
>
> I applied the following merge fix patch for today:
>
> From: Stephen Rothwell <sfr@canb.auug.org.au>
> Date: Fri, 21 Apr 2017 12:06:32 +1000
> Subject: [PATCH] tee: merge fix for dma-ops field name changes
>
> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
> ---
> drivers/tee/tee_shm.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
> index 0be1e3e93bee..4e14c9c9cb1c 100644
> --- a/drivers/tee/tee_shm.c
> +++ b/drivers/tee/tee_shm.c
> @@ -84,8 +84,8 @@ static struct dma_buf_ops tee_shm_dma_buf_ops = {
> .map_dma_buf = tee_shm_op_map_dma_buf,
> .unmap_dma_buf = tee_shm_op_unmap_dma_buf,
> .release = tee_shm_op_release,
> - .kmap_atomic = tee_shm_op_kmap_atomic,
> - .kmap = tee_shm_op_kmap,
> + .map_atomic = tee_shm_op_kmap_atomic,
> + .map = tee_shm_op_kmap,
> .mmap = tee_shm_op_mmap,
> };
>
> --
> 2.11.0
This merge fix is now needed when I merge the drm tree (as Dave merged
the drm-misc tree).
--
Cheers,
Stephen Rothwell
^ permalink raw reply
* [PATCH v3] ARM: dts: at91: sama5d2: add m_can nodes
From: Wenyou Yang @ 2017-04-24 1:12 UTC (permalink / raw)
To: linux-arm-kernel
Add nodes to support the Controller Area Network(M_CAN) on SAMA5D2.
The version of M_CAN IP core is 3.1.0 (CREL = 0x31040730).
As said in SAMA5D2 datasheet, the CAN clock is recommended to use
frequencies of 20, 40 or 80 MHz. To achieve these frequencies,
PMC GCLK3 must select the UPLLCK(480 MHz) as source clock and
divide by 24, 12, or 6. So, the "assigned-clock-rates" property
has three options: 20000000, 40000000, and 80000000.
The "assigned-clock-parents" property should be referred to utmi
fixedly.
The MSBs [bits 31:16] of the CAN Message RAM for CAN0 and CAN1 are
default configured in 0x00200000. To avoid conflict with SRAM map
for PM, change them to 0x00210000 in the AT91Bootstrap via setting
the CAN Memories Address-based Register(SFR_CAN) of SFR.
Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
Tested-by: Quentin Schulz <quentin.schulz@free-electrons.com>
---
The patch is tested on SAMA5D2 Xplained and based on the patch set,
1. [PATCH v4 1/7] can: m_can: Disabled Interrupt Line 1
http://marc.info/?l=linux-can&m=149165343604033&w=2
Changes in v3:
- Add Tested-by tag.
- Change the number of Rx Rx Buffers, Tx Buffers and Tx Event FIFO
to maximum.
Changes in v2:
- Configures 10 TX Event FIFO elements and 10 TX Buffers/FIFO slots,
because the TXE FIFO is needed to be configured.
- Configure the offset of Message RAM for CAN1 followed from CAN0's.
arch/arm/boot/dts/at91-sama5d2_xplained.dts | 24 +++++++++++++
arch/arm/boot/dts/sama5d2.dtsi | 56 +++++++++++++++++++++++++++++
2 files changed, 80 insertions(+)
diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index 9f7f8a7d8ff9..2f19b08dc226 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -257,6 +257,12 @@
status = "okay";
};
+ can0: can at f8054000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can0_default>;
+ status = "okay";
+ };
+
uart3: serial at fc008000 {
atmel,use-dma-rx;
atmel,use-dma-tx;
@@ -321,6 +327,18 @@
bias-disable;
};
+ pinctrl_can0_default: can0_default {
+ pinmux = <PIN_PC10__CANTX0>,
+ <PIN_PC11__CANRX0>;
+ bias-disable;
+ };
+
+ pinctrl_can1_default: can1_default {
+ pinmux = <PIN_PC26__CANTX1>,
+ <PIN_PC27__CANRX1>;
+ bias-disable;
+ };
+
pinctrl_charger_chglev: charger_chglev {
pinmux = <PIN_PA12__GPIO>;
bias-disable;
@@ -468,6 +486,12 @@
};
};
+
+ can1: can at fc050000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_can1_default>;
+ status = "okay";
+ };
};
};
diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
index 22332be72140..7e00fa21373e 100644
--- a/arch/arm/boot/dts/sama5d2.dtsi
+++ b/arch/arm/boot/dts/sama5d2.dtsi
@@ -762,6 +762,18 @@
atmel,clk-output-range = <0 83000000>;
};
+ can0_clk: can0_clk {
+ #clock-cells = <0>;
+ reg = <56>;
+ atmel,clk-output-range = <0 83000000>;
+ };
+
+ can1_clk: can1_clk {
+ #clock-cells = <0>;
+ reg = <57>;
+ atmel,clk-output-range = <0 83000000>;
+ };
+
classd_clk: classd_clk {
#clock-cells = <0>;
reg = <59>;
@@ -890,6 +902,18 @@
#clock-cells = <0>;
reg = <55>;
};
+
+ can0_gclk: can0_gclk {
+ #clock-cells = <0>;
+ reg = <56>;
+ atmel,clk-output-range = <0 80000000>;
+ };
+
+ can1_gclk: can1_gclk {
+ #clock-cells = <0>;
+ reg = <57>;
+ atmel,clk-output-range = <0 80000000>;
+ };
};
};
@@ -1144,6 +1168,22 @@
clocks = <&clk32k>;
};
+ can0: can at f8054000 {
+ compatible = "bosch,m_can";
+ reg = <0xf8054000 0x4000>, <0x210000 0x4000>;
+ reg-names = "m_can", "message_ram";
+ interrupts = <56 IRQ_TYPE_LEVEL_HIGH 7>,
+ <64 IRQ_TYPE_LEVEL_HIGH 7>;
+ interrupt-names = "int0", "int1";
+ clocks = <&can0_clk>, <&can0_gclk>;
+ clock-names = "hclk", "cclk";
+ assigned-clocks = <&can0_gclk>;
+ assigned-clock-parents = <&utmi>;
+ assigned-clock-rates = <40000000>;
+ bosch,mram-cfg = <0x0 0 0 64 0 0 32 32>;
+ status = "disabled";
+ };
+
spi1: spi at fc000000 {
compatible = "atmel,at91rm9200-spi";
reg = <0xfc000000 0x100>;
@@ -1305,6 +1345,22 @@
status = "okay";
};
+ can1: can at fc050000 {
+ compatible = "bosch,m_can";
+ reg = <0xfc050000 0x4000>, <0x210000 0x4000>;
+ reg-names = "m_can", "message_ram";
+ interrupts = <57 IRQ_TYPE_LEVEL_HIGH 7>,
+ <65 IRQ_TYPE_LEVEL_HIGH 7>;
+ interrupt-names = "int0", "int1";
+ clocks = <&can1_clk>, <&can1_gclk>;
+ clock-names = "hclk", "cclk";
+ assigned-clocks = <&can1_gclk>;
+ assigned-clock-parents = <&utmi>;
+ assigned-clock-rates = <40000000>;
+ bosch,mram-cfg = <0x1100 0 0 64 0 0 32 32>;
+ status = "disabled";
+ };
+
chipid at fc069000 {
compatible = "atmel,sama5d2-chipid";
reg = <0xfc069000 0x8>;
--
2.11.0
^ permalink raw reply related
* [PATCH v2 03/11] dt-bindings: soc/fsl: Update reserved memory binding for QBMan
From: Scott Wood @ 2017-04-24 1:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492634930-10765-4-git-send-email-roy.pledge@nxp.com>
On Wed, 2017-04-19 at 16:48 -0400, Roy Pledge wrote:
> Updates the QMan and BMan device tree bindings for reserved memory
> nodes. This makes the reserved memory allocation compatiable with
> the shared-dma-pool usage.
>
> Signed-off-by: Roy Pledge <roy.pledge@nxp.com>
> ---
> ?Documentation/devicetree/bindings/soc/fsl/bman.txt | 11 ++++++-----
> ?Documentation/devicetree/bindings/soc/fsl/qman.txt | 18 +++++++++++-------
> ?2 files changed, 17 insertions(+), 12 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/soc/fsl/bman.txt
> b/Documentation/devicetree/bindings/soc/fsl/bman.txt
> index 47ac834..3cd1e2c 100644
> --- a/Documentation/devicetree/bindings/soc/fsl/bman.txt
> +++ b/Documentation/devicetree/bindings/soc/fsl/bman.txt
> @@ -65,8 +65,8 @@ to the respective BMan instance
> ?BMan Private Memory Node
> ?
> ?BMan requires a contiguous range of physical memory used for the backing
> store
> -for BMan Free Buffer Proxy Records (FBPR). This memory is
> reserved/allocated as a
> -node under the /reserved-memory node
> +for BMan Free Buffer Proxy Records (FBPR). This memory is
> reserved/allocated as
> +a node under the /reserved-memory node.
> ?
> ?The BMan FBPR memory node must be named "bman-fbpr"
> ?
> @@ -75,7 +75,8 @@ PROPERTIES
> ?- compatible
> ? Usage: required
> ? Value type: <stringlist>
> - Definition: Must inclide "fsl,bman-fbpr"
> + Definition: PPC platforms: Must include "fsl,bman-fbpr"
> + ARM platforms: Must include "shared-dma-pool"
> ?
> ?The following constraints are relevant to the FBPR private memory:
> ? - The size must be 2^(size + 1), with size = 11..33. That is 4 KiB
> to
> @@ -100,10 +101,10 @@ The example below shows a BMan FBPR dynamic allocation
> memory node
> ? ranges;
> ?
> ? bman_fbpr: bman-fbpr {
> - compatible = "fsl,bman-fbpr";
> - alloc-ranges = <0 0 0x10 0>;
> + compatible = "shared-mem-pool";
> ? size = <0 0x1000000>;
> ? alignment = <0 0x1000000>;
> + no-map;
> ? };
> ? };
> ?
The requirement for using no-map with shared-mem-pool should be explicitly
stated, not just in the example.
-Scott
^ permalink raw reply
* [arm64] OOPS when using /proc/kcore to disassemble the kernel symbols in "perf top"
From: Tan Xiaojun @ 2017-04-24 1:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170421093436.GD6406@leverpostej>
On 2017/4/21 17:34, Mark Rutland wrote:
> Hi,
>
> On Fri, Apr 21, 2017 at 01:46:43PM +0800, Tan Xiaojun wrote:
>> On 2017/4/20 9:38, Tan Xiaojun wrote:
>>> On 2017/4/19 19:49, Mark Rutland wrote:
>>>> Hi,
>>>>
>>>> Ard, this sseems to be a nomap issue. Please see below.
>>>>
>>>> Xiaojun, for some reason, the first message in this thread didn't seem
>>>> to make it to LAKML (or to me). In future could you please Cc me for
>>>> emails regarding perf on arm/arm64?
>>>>
>>>
>>> Sorry, this is my negligence.
>>>
>>>> On Wed, Apr 19, 2017 at 09:44:56AM +0530, Pratyush Anand wrote:
>>>>> On Saturday 15 April 2017 02:18 PM, Tan Xiaojun wrote:
>>>>>> My test server is Hisilicon D03/D05 (arm64).
>>>>>> Kernel source code is 4.11-rc6 (up to date) and config (as an attachment in the end) is generated by defconfig.
>>>>>> (Old version does not seem to have this problem. Linux-4.1 is fine and other versions I have not tested yet.)
>>>>>
>>>>> I tested with mustang(ARM64) and 4.11-rc6 and could not reproduce it.
>>>>>
>>
>> Hi,
>> Pratyush,
>>
>> Sorry, could you test it again? Because I tested it many times and found it is not triggered every time.
>> And you can run "perf top -U" and try more kernel symbols to increase the probability of occurrence, or
>> maybe you can try Mark's way "cat /proc/kcore > /dev/null".
>>
>> I would like to confirm whether this is hardware related, but I have no other arm64 boards except the
>> boards of Hisilicon.
>
> As I mentioned in my prior reply, this is a bug in the way we handle
> nomap memory in the kernel.
>
> This is not hardware related, and this is not specific to perf.
>
> The kcore code expects that if a vmalloc mapping has a corresponding
> struct page, that it can be accessed via the linear mapping. However,
> this is not true for nomap memory.
>
Yes, you are right.
>> I found the patch which introduced the problem.
>> The commit is:
>>
>> commit f9040773b7bbbd9e98eb6184a263512a7cfc133f
>> Author: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> Date: Tue Feb 16 13:52:40 2016 +0100
>>
>> arm64: move kernel image to base of vmalloc area
>>
>> This moves the module area to right before the vmalloc area, and moves
>> the kernel image to the base of the vmalloc area. This is an intermediate
>> step towards implementing KASLR, which allows the kernel image to be
>> located anywhere in the vmalloc area.
>>
>> Since other subsystems such as hibernate may still need to refer to the
>> kernel text or data segments via their linears addresses, both are mapped
>> in the linear region as well. The linear alias of the text region is
>> mapped read-only/non-executable to prevent inadvertent modification or
>> execution.
>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
>>
>> It can work well without this patch in Linux-4.5-rc4. And it can
>> trigger an OOPS with this patch in Linux-4.5-rc4.
>>
>> I try to revert it in v4.11-rc6, but it involves too much conflict.
>> So I need to understand this patch fist. Then I can known where the problem is.
>
> Reverting this patch is not the correct fix.
>
> The fix will either be changing the way we set things up for nomap
> memory, or with additions to the kcore or vread code to cater for nomap.
>
It seems that the problem is serious and I want to fix it as soon as possible. But I know little
about nomap memory. So if you can give a fix patch, I am glad to test it. ^-^
Thanks.
Xiaojun.
> Thanks,
> Mark.
> .
>
^ permalink raw reply
* [PATCH 1/5] arm64: renesas: r8a7796: Add external audio clocks
From: Kuninori Morimoto @ 2017-04-23 23:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492779321-23939-2-git-send-email-geert+renesas@glider.be>
Hi Geert
> Add the external audio clocks as zero Hz fixed-frequency clocks.
> Boards that provide these clocks should override them.
>
> Based on commit 623197b90c7aa97c ("arm64: renesas: r8a7795: Sound SSI
> PIO support").
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> arch/arm64/boot/dts/renesas/r8a7796.dtsi | 23 +++++++++++++++++++++++
> 1 file changed, 23 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> index 2ec1ed5f499165ad..101cd41d693a7ab5 100644
> --- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> +++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
> @@ -120,6 +120,29 @@
> clock-frequency = <0>;
> };
>
> + /*
> + * The external audio clocks are configured as 0 Hz fixed frequency
> + * clocks by default.
> + * Boards that provide audio clocks should override them.
> + */
> + audio_clk_a: audio_clk_a {
> + compatible = "fixed-clock";
> + #clock-cells = <0>;
> + clock-frequency = <0>;
> + };
> +
> + audio_clk_b: audio_clk_b {
> + compatible = "fixed-clock";
> + #clock-cells = <0>;
> + clock-frequency = <0>;
> + };
> +
> + audio_clk_c: audio_clk_c {
> + compatible = "fixed-clock";
> + #clock-cells = <0>;
> + clock-frequency = <0>;
> + };
> +
> /* External CAN clock - to be overridden by boards that provide it */
> can_clk: can {
> compatible = "fixed-clock";
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH 2/2] arm64:vdso: Remove ISB from gettimeofday.
From: Andrew Pinski @ 2017-04-23 23:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1492991221-5156-1-git-send-email-apinski@cavium.com>
ISB is normally required before mrs CNTVCT if we want the
mrs to completed after the loads. In this case it is not.
As we are taking the difference and if that difference
was going to be negative, we just use the last counter value
instead.
Signed-off-by: Andrew Pinski <apinski@cavium.com>
---
arch/arm64/kernel/vdso/gettimeofday.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kernel/vdso/gettimeofday.c b/arch/arm64/kernel/vdso/gettimeofday.c
index a0ab8b1..cf3235a 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.c
+++ b/arch/arm64/kernel/vdso/gettimeofday.c
@@ -117,10 +117,20 @@ static notrace u64 get_clock_shifted_nsec(u64 cycle_last, u64 mult)
u64 res;
/* Read the virtual counter. */
- isb();
+ /*
+ * This normally requires an ISB but since we know the
+ * read of the last cycle will always be after the
+ * read of the values are valid word.
+ */
asm volatile("mrs %0, cntvct_el0" : "=r" (res) :: "memory");
- res = res - cycle_last;
+ /*
+ * If the current cycle is greater than the last,
+ * then get the difference.
+ */
+ if (res > cycle_last)
+ res = res - cycle_last;
+
/* We can only guarantee 56 bits of precision. */
res &= ~(0xff00ul<<48);
return res * mult;
--
2.7.4
^ permalink raw reply related
* [PATCH 1/2] arm64:vdso: Rewrite gettimeofday into C.
From: Andrew Pinski @ 2017-04-23 23:47 UTC (permalink / raw)
To: linux-arm-kernel
This allows the compiler to optimize the divide by 1000.
And remove the other divide.
On ThunderX, gettimeofday improves by 32%. On ThunderX 2,
gettimeofday improves by 18%.
Signed-off-by: Andrew Pinski <apinski@cavium.com>
---
arch/arm64/kernel/vdso/Makefile | 13 +-
arch/arm64/kernel/vdso/gettimeofday.S | 329 --------------------------------
arch/arm64/kernel/vdso/gettimeofday.c | 342 ++++++++++++++++++++++++++++++++++
3 files changed, 348 insertions(+), 336 deletions(-)
delete mode 100644 arch/arm64/kernel/vdso/gettimeofday.S
create mode 100644 arch/arm64/kernel/vdso/gettimeofday.c
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
index 62c84f7..55f352f 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -11,10 +11,15 @@ obj-vdso := gettimeofday.o note.o sigreturn.o
targets := $(obj-vdso) vdso.so vdso.so.dbg
obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
-ccflags-y := -shared -fno-common -fno-builtin
+ccflags-y := -shared -fno-common -fno-builtin -fno-stack-protector
+ccflags-y += -DDISABLE_BRANCH_PROFILING
ccflags-y += -nostdlib -Wl,-soname=linux-vdso.so.1 \
$(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+# Force -O2 to avoid libgcc dependencies
+CFLAGS_REMOVE_gettimeofday.o = -pg -Os
+CFLAGS_gettimeofday.o = -O2 -mcmodel=tiny
+
# Disable gcov profiling for VDSO code
GCOV_PROFILE := n
@@ -48,15 +53,9 @@ endef
include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
$(call if_changed,vdsosym)
-# Assembly rules for the .S files
-$(obj-vdso): %.o: %.S FORCE
- $(call if_changed_dep,vdsoas)
-
# Actual build commands
quiet_cmd_vdsold = VDSOL $@
cmd_vdsold = $(CC) $(c_flags) -Wl,-n -Wl,-T $^ -o $@
-quiet_cmd_vdsoas = VDSOA $@
- cmd_vdsoas = $(CC) $(a_flags) -c -o $@ $<
# Install commands for the unstripped file
quiet_cmd_vdso_install = INSTALL $@
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
deleted file mode 100644
index e00b467..0000000
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Userspace implementations of gettimeofday() and friends.
- *
- * Copyright (C) 2012 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * Author: Will Deacon <will.deacon@arm.com>
- */
-
-#include <linux/linkage.h>
-#include <asm/asm-offsets.h>
-#include <asm/unistd.h>
-
-#define NSEC_PER_SEC_LO16 0xca00
-#define NSEC_PER_SEC_HI16 0x3b9a
-
-vdso_data .req x6
-seqcnt .req w7
-w_tmp .req w8
-x_tmp .req x8
-
-/*
- * Conventions for macro arguments:
- * - An argument is write-only if its name starts with "res".
- * - All other arguments are read-only, unless otherwise specified.
- */
-
- .macro seqcnt_acquire
-9999: ldr seqcnt, [vdso_data, #VDSO_TB_SEQ_COUNT]
- tbnz seqcnt, #0, 9999b
- dmb ishld
- .endm
-
- .macro seqcnt_check fail
- dmb ishld
- ldr w_tmp, [vdso_data, #VDSO_TB_SEQ_COUNT]
- cmp w_tmp, seqcnt
- b.ne \fail
- .endm
-
- .macro syscall_check fail
- ldr w_tmp, [vdso_data, #VDSO_USE_SYSCALL]
- cbnz w_tmp, \fail
- .endm
-
- .macro get_nsec_per_sec res
- mov \res, #NSEC_PER_SEC_LO16
- movk \res, #NSEC_PER_SEC_HI16, lsl #16
- .endm
-
- /*
- * Returns the clock delta, in nanoseconds left-shifted by the clock
- * shift.
- */
- .macro get_clock_shifted_nsec res, cycle_last, mult
- /* Read the virtual counter. */
- isb
- mrs x_tmp, cntvct_el0
- /* Calculate cycle delta and convert to ns. */
- sub \res, x_tmp, \cycle_last
- /* We can only guarantee 56 bits of precision. */
- movn x_tmp, #0xff00, lsl #48
- and \res, x_tmp, \res
- mul \res, \res, \mult
- .endm
-
- /*
- * Returns in res_{sec,nsec} the REALTIME timespec, based on the
- * "wall time" (xtime) and the clock_mono delta.
- */
- .macro get_ts_realtime res_sec, res_nsec, \
- clock_nsec, xtime_sec, xtime_nsec, nsec_to_sec
- add \res_nsec, \clock_nsec, \xtime_nsec
- udiv x_tmp, \res_nsec, \nsec_to_sec
- add \res_sec, \xtime_sec, x_tmp
- msub \res_nsec, x_tmp, \nsec_to_sec, \res_nsec
- .endm
-
- /*
- * Returns in res_{sec,nsec} the timespec based on the clock_raw delta,
- * used for CLOCK_MONOTONIC_RAW.
- */
- .macro get_ts_clock_raw res_sec, res_nsec, clock_nsec, nsec_to_sec
- udiv \res_sec, \clock_nsec, \nsec_to_sec
- msub \res_nsec, \res_sec, \nsec_to_sec, \clock_nsec
- .endm
-
- /* sec and nsec are modified in place. */
- .macro add_ts sec, nsec, ts_sec, ts_nsec, nsec_to_sec
- /* Add timespec. */
- add \sec, \sec, \ts_sec
- add \nsec, \nsec, \ts_nsec
-
- /* Normalise the new timespec. */
- cmp \nsec, \nsec_to_sec
- b.lt 9999f
- sub \nsec, \nsec, \nsec_to_sec
- add \sec, \sec, #1
-9999:
- cmp \nsec, #0
- b.ge 9998f
- add \nsec, \nsec, \nsec_to_sec
- sub \sec, \sec, #1
-9998:
- .endm
-
- .macro clock_gettime_return, shift=0
- .if \shift == 1
- lsr x11, x11, x12
- .endif
- stp x10, x11, [x1, #TSPEC_TV_SEC]
- mov x0, xzr
- ret
- .endm
-
- .macro jump_slot jumptable, index, label
- .if (. - \jumptable) != 4 * (\index)
- .error "Jump slot index mismatch"
- .endif
- b \label
- .endm
-
- .text
-
-/* int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz); */
-ENTRY(__kernel_gettimeofday)
- .cfi_startproc
- adr vdso_data, _vdso_data
- /* If tv is NULL, skip to the timezone code. */
- cbz x0, 2f
-
- /* Compute the time of day. */
-1: seqcnt_acquire
- syscall_check fail=4f
- ldr x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
- /* w11 = cs_mono_mult, w12 = cs_shift */
- ldp w11, w12, [vdso_data, #VDSO_CS_MONO_MULT]
- ldp x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
- seqcnt_check fail=1b
-
- get_nsec_per_sec res=x9
- lsl x9, x9, x12
-
- get_clock_shifted_nsec res=x15, cycle_last=x10, mult=x11
- get_ts_realtime res_sec=x10, res_nsec=x11, \
- clock_nsec=x15, xtime_sec=x13, xtime_nsec=x14, nsec_to_sec=x9
-
- /* Convert ns to us. */
- mov x13, #1000
- lsl x13, x13, x12
- udiv x11, x11, x13
- stp x10, x11, [x0, #TVAL_TV_SEC]
-2:
- /* If tz is NULL, return 0. */
- cbz x1, 3f
- ldp w4, w5, [vdso_data, #VDSO_TZ_MINWEST]
- stp w4, w5, [x1, #TZ_MINWEST]
-3:
- mov x0, xzr
- ret
-4:
- /* Syscall fallback. */
- mov x8, #__NR_gettimeofday
- svc #0
- ret
- .cfi_endproc
-ENDPROC(__kernel_gettimeofday)
-
-#define JUMPSLOT_MAX CLOCK_MONOTONIC_COARSE
-
-/* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */
-ENTRY(__kernel_clock_gettime)
- .cfi_startproc
- cmp w0, #JUMPSLOT_MAX
- b.hi syscall
- adr vdso_data, _vdso_data
- adr x_tmp, jumptable
- add x_tmp, x_tmp, w0, uxtw #2
- br x_tmp
-
- ALIGN
-jumptable:
- jump_slot jumptable, CLOCK_REALTIME, realtime
- jump_slot jumptable, CLOCK_MONOTONIC, monotonic
- b syscall
- b syscall
- jump_slot jumptable, CLOCK_MONOTONIC_RAW, monotonic_raw
- jump_slot jumptable, CLOCK_REALTIME_COARSE, realtime_coarse
- jump_slot jumptable, CLOCK_MONOTONIC_COARSE, monotonic_coarse
-
- .if (. - jumptable) != 4 * (JUMPSLOT_MAX + 1)
- .error "Wrong jumptable size"
- .endif
-
- ALIGN
-realtime:
- seqcnt_acquire
- syscall_check fail=syscall
- ldr x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
- /* w11 = cs_mono_mult, w12 = cs_shift */
- ldp w11, w12, [vdso_data, #VDSO_CS_MONO_MULT]
- ldp x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
- seqcnt_check fail=realtime
-
- /* All computations are done with left-shifted nsecs. */
- get_nsec_per_sec res=x9
- lsl x9, x9, x12
-
- get_clock_shifted_nsec res=x15, cycle_last=x10, mult=x11
- get_ts_realtime res_sec=x10, res_nsec=x11, \
- clock_nsec=x15, xtime_sec=x13, xtime_nsec=x14, nsec_to_sec=x9
- clock_gettime_return, shift=1
-
- ALIGN
-monotonic:
- seqcnt_acquire
- syscall_check fail=syscall
- ldr x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
- /* w11 = cs_mono_mult, w12 = cs_shift */
- ldp w11, w12, [vdso_data, #VDSO_CS_MONO_MULT]
- ldp x13, x14, [vdso_data, #VDSO_XTIME_CLK_SEC]
- ldp x3, x4, [vdso_data, #VDSO_WTM_CLK_SEC]
- seqcnt_check fail=monotonic
-
- /* All computations are done with left-shifted nsecs. */
- lsl x4, x4, x12
- get_nsec_per_sec res=x9
- lsl x9, x9, x12
-
- get_clock_shifted_nsec res=x15, cycle_last=x10, mult=x11
- get_ts_realtime res_sec=x10, res_nsec=x11, \
- clock_nsec=x15, xtime_sec=x13, xtime_nsec=x14, nsec_to_sec=x9
-
- add_ts sec=x10, nsec=x11, ts_sec=x3, ts_nsec=x4, nsec_to_sec=x9
- clock_gettime_return, shift=1
-
- ALIGN
-monotonic_raw:
- seqcnt_acquire
- syscall_check fail=syscall
- ldr x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
- /* w11 = cs_raw_mult, w12 = cs_shift */
- ldp w12, w11, [vdso_data, #VDSO_CS_SHIFT]
- ldp x13, x14, [vdso_data, #VDSO_RAW_TIME_SEC]
- seqcnt_check fail=monotonic_raw
-
- /* All computations are done with left-shifted nsecs. */
- lsl x14, x14, x12
- get_nsec_per_sec res=x9
- lsl x9, x9, x12
-
- get_clock_shifted_nsec res=x15, cycle_last=x10, mult=x11
- get_ts_clock_raw res_sec=x10, res_nsec=x11, \
- clock_nsec=x15, nsec_to_sec=x9
-
- add_ts sec=x10, nsec=x11, ts_sec=x13, ts_nsec=x14, nsec_to_sec=x9
- clock_gettime_return, shift=1
-
- ALIGN
-realtime_coarse:
- seqcnt_acquire
- ldp x10, x11, [vdso_data, #VDSO_XTIME_CRS_SEC]
- seqcnt_check fail=realtime_coarse
- clock_gettime_return
-
- ALIGN
-monotonic_coarse:
- seqcnt_acquire
- ldp x10, x11, [vdso_data, #VDSO_XTIME_CRS_SEC]
- ldp x13, x14, [vdso_data, #VDSO_WTM_CLK_SEC]
- seqcnt_check fail=monotonic_coarse
-
- /* Computations are done in (non-shifted) nsecs. */
- get_nsec_per_sec res=x9
- add_ts sec=x10, nsec=x11, ts_sec=x13, ts_nsec=x14, nsec_to_sec=x9
- clock_gettime_return
-
- ALIGN
-syscall: /* Syscall fallback. */
- mov x8, #__NR_clock_gettime
- svc #0
- ret
- .cfi_endproc
-ENDPROC(__kernel_clock_gettime)
-
-/* int __kernel_clock_getres(clockid_t clock_id, struct timespec *res); */
-ENTRY(__kernel_clock_getres)
- .cfi_startproc
- cmp w0, #CLOCK_REALTIME
- ccmp w0, #CLOCK_MONOTONIC, #0x4, ne
- ccmp w0, #CLOCK_MONOTONIC_RAW, #0x4, ne
- b.ne 1f
-
- ldr x2, 5f
- b 2f
-1:
- cmp w0, #CLOCK_REALTIME_COARSE
- ccmp w0, #CLOCK_MONOTONIC_COARSE, #0x4, ne
- b.ne 4f
- ldr x2, 6f
-2:
- cbz w1, 3f
- stp xzr, x2, [x1]
-
-3: /* res == NULL. */
- mov w0, wzr
- ret
-
-4: /* Syscall fallback. */
- mov x8, #__NR_clock_getres
- svc #0
- ret
-5:
- .quad CLOCK_REALTIME_RES
-6:
- .quad CLOCK_COARSE_RES
- .cfi_endproc
-ENDPROC(__kernel_clock_getres)
diff --git a/arch/arm64/kernel/vdso/gettimeofday.c b/arch/arm64/kernel/vdso/gettimeofday.c
new file mode 100644
index 0000000..a0ab8b1
--- /dev/null
+++ b/arch/arm64/kernel/vdso/gettimeofday.c
@@ -0,0 +1,342 @@
+/*
+ * Userspace implementations of gettimeofday() and friends.
+ *
+ * Copyright (C) 2017 Cavium, Inc.
+ * Copyright (C) 2012 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ * Rewriten into C by: Andrew Pinski <apinski@cavium.com>
+ */
+
+#include <uapi/linux/time.h>
+#include <asm/unistd.h>
+#include <asm/vdso_datapage.h>
+#include <linux/math64.h>
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/hrtimer.h>
+
+extern struct vdso_data _vdso_data;
+
+static notrace int gettimeofday_fallback(struct timeval *_tv,
+ struct timezone *_tz)
+{
+ register struct timezone *tz asm("x1") = _tz;
+ register struct timeval *tv asm("x0") = _tv;
+ register long ret asm ("x0");
+ register long nr asm("x8") = __NR_gettimeofday;
+
+ asm volatile(
+ " svc #0\n"
+ : "=r" (ret)
+ : "r" (tv), "r" (tz), "r" (nr)
+ : "memory");
+
+ return ret;
+}
+
+static notrace long clock_gettime_fallback(clockid_t _clkid,
+ struct timespec *_ts)
+{
+ register struct timespec *ts asm("x1") = _ts;
+ register clockid_t clkid asm("x0") = _clkid;
+ register long ret asm ("x0");
+ register long nr asm("x8") = __NR_clock_gettime;
+
+ asm volatile(
+ " svc #0\n"
+ : "=r" (ret)
+ : "r" (clkid), "r" (ts), "r" (nr)
+ : "memory");
+
+ return ret;
+}
+
+static notrace int clock_getres_fallback(clockid_t _clkid,
+ struct timespec *_ts)
+{
+ register struct timespec *ts asm("x1") = _ts;
+ register clockid_t clkid asm("x0") = _clkid;
+ register long ret asm ("x0");
+ register long nr asm("x8") = __NR_clock_getres;
+
+ asm volatile(
+ " svc #0\n"
+ : "=r" (ret)
+ : "r" (clkid), "r" (ts), "r" (nr)
+ : "memory");
+
+ return ret;
+}
+
+static notrace u32 vdso_read_begin(const struct vdso_data *vd)
+{
+ u32 seq;
+
+ do {
+ seq = READ_ONCE(vd->tb_seq_count);
+
+ if ((seq & 1) == 0)
+ break;
+
+ asm volatile ("" : : : "memory");
+ } while (true);
+
+ smp_rmb(); /* Pairs with smp_wmb in vdso_write_end */
+ return seq;
+}
+
+static notrace u32 vdso_read_retry(const struct vdso_data *vd, u32 start)
+{
+ u32 seq;
+
+ smp_rmb(); /* Pairs with smp_wmb in vdso_write_begin */
+ seq = READ_ONCE(vd->tb_seq_count);
+ return seq != start;
+}
+
+
+/*
+ * Returns the clock delta, in nanoseconds left-shifted by the clock
+ * shift.
+ */
+static notrace u64 get_clock_shifted_nsec(u64 cycle_last, u64 mult)
+{
+ u64 res;
+
+ /* Read the virtual counter. */
+ isb();
+ asm volatile("mrs %0, cntvct_el0" : "=r" (res) :: "memory");
+
+ res = res - cycle_last;
+ /* We can only guarantee 56 bits of precision. */
+ res &= ~(0xff00ul<<48);
+ return res * mult;
+}
+
+
+/* Code size doesn't matter (vdso is 4k/16k/64k anyway) and this is faster. */
+static __always_inline notrace int do_realtime(const struct vdso_data *vd,
+ struct timespec *ts)
+{
+ u32 seq, cs_mono_mult, cs_shift;
+ u64 ns, sec, cycle_last;
+
+ do {
+ seq = vdso_read_begin(vd);
+
+ if (vd->use_syscall)
+ return -1;
+
+ cycle_last = vd->cs_cycle_last;
+
+ cs_mono_mult = vd->cs_mono_mult;
+ cs_shift = vd->cs_shift;
+
+ sec = vd->xtime_clock_sec;
+ ns = vd->xtime_clock_nsec;
+
+ } while (unlikely(vdso_read_retry(vd, seq)));
+
+ ns += get_clock_shifted_nsec(cycle_last, cs_mono_mult);
+ ns >>= cs_shift;
+ ts->tv_sec = sec + __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
+ ts->tv_nsec = ns;
+
+ return 0;
+}
+
+static notrace int do_monotonic(const struct vdso_data *vd,
+ struct timespec *ts)
+{
+ u32 seq, cs_mono_mult, cs_shift;
+ u64 ns, cycle_last, sec;
+
+ do {
+ seq = vdso_read_begin(vd);
+
+ if (vd->use_syscall)
+ return 1;
+
+ cycle_last = vd->cs_cycle_last;
+
+ cs_mono_mult = vd->cs_mono_mult;
+ cs_shift = vd->cs_shift;
+
+ sec = vd->xtime_clock_sec;
+ ns = vd->xtime_clock_nsec;
+
+ sec += vd->wtm_clock_sec;
+ ns += vd->wtm_clock_nsec << cs_shift;
+
+ } while (unlikely(vdso_read_retry(vd, seq)));
+
+ ns += get_clock_shifted_nsec(cycle_last, cs_mono_mult);
+ ns >>= cs_shift;
+
+ ts->tv_sec = sec + __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
+ ts->tv_nsec = ns;
+
+ return 0;
+}
+
+static notrace int do_monotonic_raw(const struct vdso_data *vd,
+ struct timespec *ts)
+{
+ u32 seq, cs_raw_mult, cs_shift;
+ u64 ns, sec, cycle_last;
+
+ do {
+ seq = vdso_read_begin(vd);
+
+ if (vd->use_syscall)
+ return -1;
+
+ cycle_last = vd->cs_cycle_last;
+
+ cs_raw_mult = vd->cs_raw_mult;
+ cs_shift = vd->cs_shift;
+
+ sec = vd->raw_time_sec;
+ ns = vd->raw_time_nsec;
+
+ } while (unlikely(vdso_read_retry(vd, seq)));
+
+ ns += get_clock_shifted_nsec(cycle_last, cs_raw_mult);
+ ns >>= cs_shift;
+ ts->tv_sec = sec + __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
+ ts->tv_nsec = ns;
+
+ return 0;
+}
+
+
+static notrace void do_realtime_coarse(const struct vdso_data *vd,
+ struct timespec *ts)
+{
+ u32 seq;
+ u64 ns, sec;
+
+ do {
+ seq = vdso_read_begin(vd);
+
+ sec = vd->xtime_coarse_sec;
+ ns = vd->xtime_coarse_nsec;
+
+ } while (unlikely(vdso_read_retry(vd, seq)));
+
+ ts->tv_sec = sec;
+ ts->tv_nsec = ns;
+}
+
+static notrace void do_monotonic_coarse(const struct vdso_data *vd,
+ struct timespec *ts)
+{
+ u32 seq;
+ u64 ns, sec, wtm_sec, wtm_ns;
+
+ do {
+
+ seq = vdso_read_begin(vd);
+
+ sec = vd->xtime_coarse_sec;
+ ns = vd->xtime_coarse_nsec;
+
+ wtm_sec = vd->wtm_clock_sec;
+ wtm_ns = vd->wtm_clock_nsec;
+
+ } while (unlikely(vdso_read_retry(vd, seq)));
+
+ sec += wtm_sec;
+ ns += wtm_ns;
+ ts->tv_sec = sec + __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
+ ts->tv_nsec = ns;
+}
+
+notrace int __kernel_clock_gettime(clockid_t clock, struct timespec *ts)
+{
+ const struct vdso_data *vd = &_vdso_data;
+
+ switch (clock) {
+ case CLOCK_REALTIME:
+ if (do_realtime(vd, ts))
+ goto fallback;
+ break;
+ case CLOCK_MONOTONIC:
+ if (do_monotonic(vd, ts))
+ goto fallback;
+ break;
+ case CLOCK_MONOTONIC_RAW:
+ do_monotonic_raw(vd, ts);
+ break;
+ case CLOCK_REALTIME_COARSE:
+ do_realtime_coarse(vd, ts);
+ break;
+ case CLOCK_MONOTONIC_COARSE:
+ do_monotonic_coarse(vd, ts);
+ break;
+ default:
+ goto fallback;
+ }
+
+ return 0;
+fallback:
+ return clock_gettime_fallback(clock, ts);
+}
+
+
+
+notrace int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ const struct vdso_data *vd = &_vdso_data;
+
+ if (likely(tv != NULL)) {
+ struct timespec ts;
+
+ if (do_realtime(vd, &ts))
+ return gettimeofday_fallback(tv, tz);
+
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / 1000;
+ }
+
+ if (unlikely(tz != NULL)) {
+ tz->tz_minuteswest = vd->tz_minuteswest;
+ tz->tz_dsttime = vd->tz_dsttime;
+ }
+
+ return 0;
+}
+
+
+int __kernel_clock_getres(clockid_t clock_id, struct timespec *res)
+{
+ u64 ns;
+
+ if (clock_id == CLOCK_REALTIME ||
+ clock_id == CLOCK_MONOTONIC ||
+ clock_id == CLOCK_MONOTONIC_RAW)
+ ns = MONOTONIC_RES_NSEC;
+ else if (clock_id == CLOCK_REALTIME_COARSE ||
+ clock_id == CLOCK_MONOTONIC_COARSE)
+ ns = LOW_RES_NSEC;
+ else
+ return clock_getres_fallback(clock_id, res);
+
+ res->tv_sec = 0;
+ res->tv_nsec = ns;
+
+ return 0;
+}
--
2.7.4
^ permalink raw reply related
* [RFC] minimum gcc version for kernel: raise to gcc-4.3 or 4.6?
From: Geert Uytterhoeven @ 2017-04-23 20:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAK8P3a28fi0GRcz1yLq+wRkaBBO_w74NnBCY7f3myg78JpaCCQ@mail.gmail.com>
Hi Arnd,
On Sat, Apr 22, 2017 at 5:30 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> Based on what I found so far, gcc-4 can be pretty much ruled out from
> being the minimum version based on the number of failures I got.
> It's much better than 3.4 but much worse than 4.1 or 4.2 which seem
> fixable on MIPS and x86 at least, and may or may not work depending
> on configuration. So the best two possible (but conflicting) answers I
> have are
>
> a) There are known users on gcc-4.1, and we never break things that
> work for users, so gcc-4.1 (or possibly 4.0 if a user shows up) would
> be the minimum version.
> b) gcc-4.1 and 4.2 have too many problems, so users are better off
> when we tell them to upgrade to something newer, and a minimum
> version of gcc-4.3 has fewer surprises. We should remove all
> workarounds for pre-gcc-4.3 compilers and just force a build error
> message.
If there's no real good reason (brokenness) to deprecate gcc-4.1, I would not
do it.I guess most people using old compilers know what they're doing.
My main motivation for keep on using gcc-4.1 is that it gives many warnings
that were disabled in later gcc versions. I do look at all new warnings, and
send patches when they are real bugs, or are trivial to silence.
Lately the usefulness has been decreasing, as you've been too aggressively
killing compiler warnings with recent gcc versions (which became better) ;-)
Hence if I detected a new warning with a point or an rc release, it usually
means the code was never in nex (ugh)t, or the maintainer ignored your patch.
I could easily switch to v4.9 from kernel.org crosstool, though, but then I
would loose all those warnings.
BTW, below is the diff I use to avoid an ICE.
After that, it builds and (test)boots fine on ARAnyM ;-)
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index ec0848fcca02d896..eb75b324ac0ac53d 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -650,13 +650,16 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
struct gfs2_glock **glp)
{
struct super_block *s = sdp->sd_vfs;
- struct lm_lockname name = { .ln_number = number,
+ // FIXME Avoid gcc 4.1.2 20061115 (prerelease) (Ubuntu 4.1.1-21) ICE
+ //struct lm_lockname name = { .ln_number = number,
+ struct lm_lockname name = {
.ln_type = glops->go_type,
.ln_sbd = sdp };
struct gfs2_glock *gl, *tmp = NULL;
struct address_space *mapping;
struct kmem_cache *cachep;
int ret, tries = 0;
+ name.ln_number = number;
rcu_read_lock();
gl = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms);
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 86ccc01593937d93..8783b72df5fa3d0c 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1767,7 +1767,11 @@ static void try_rgrp_unlink(struct gfs2_rgrpd
*rgd, u64 *last_unlinked, u64 skip
struct gfs2_inode *ip;
int error;
int found = 0;
- struct gfs2_rbm rbm = { .rgd = rgd, .bii = 0, .offset = 0 };
+ // FIXME Avoid gcc 4.1.2 20061115 (prerelease) (Ubuntu 4.1.1-21) ICE
+ // struct gfs2_rbm rbm = { .rgd = rgd, .bii = 0, .offset = 0 };
+ struct gfs2_rbm rbm = { .bii = 0, .offset = 0 };
+ rbm.rgd = rgd;
+
while (1) {
down_write(&sdp->sd_log_flush_lock);
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply related
* [PULL 79/79] ARM: KVM: Fix idmap stub entry when running Thumb-2 code
From: Christoffer Dall @ 2017-04-23 17:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170423170929.27334-1-cdall@linaro.org>
From: Marc Zyngier <marc.zyngier@arm.com>
When entering the hyp stub implemented in the idmap, we try to
be mindful of the fact that we could be running a Thumb-2 kernel
by adding 1 to the address we compute. Unfortunately, the assembler
also knows about this trick, and has already generated an address
that has bit 0 set in the litteral pool.
Our superfluous correction ends up confusing the CPU entierely,
as we now branch to the stub in ARM mode instead of Thumb, and on
a possibly unaligned address for good measure. From that point,
nothing really good happens.
The obvious fix in to remove this stupid target PC correction.
Fixes: 6bebcecb6c5b ("ARM: KVM: Allow the main HYP code to use the init hyp stub implementation")
Reported-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
arch/arm/kvm/hyp/hyp-entry.S | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/arm/kvm/hyp/hyp-entry.S b/arch/arm/kvm/hyp/hyp-entry.S
index a35baa8..95a2fae 100644
--- a/arch/arm/kvm/hyp/hyp-entry.S
+++ b/arch/arm/kvm/hyp/hyp-entry.S
@@ -144,7 +144,6 @@ hyp_hvc:
ldr r1, [r1]
ldr ip, =__kvm_handle_stub_hvc
sub ip, ip, r1
-THUMB( add ip, ip, #1)
pop {r1}
bx ip
--
2.9.0
^ permalink raw reply related
* [PULL 78/79] ARM: hyp-stub: Fix Thumb-2 compilation
From: Christoffer Dall @ 2017-04-23 17:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170423170929.27334-1-cdall@linaro.org>
From: Marc Zyngier <marc.zyngier@arm.com>
The assembler defaults to emiting the short form of ADR, leading
to an out-of-range immediate. Using the wide version solves this
issue.
Fixes: bc845e4fbbbb ("ARM: KVM: Implement HVC_RESET_VECTORS stub hypercall in the init code")
Reported-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
arch/arm/kernel/hyp-stub.S | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S
index d8523cc..ec7e737 100644
--- a/arch/arm/kernel/hyp-stub.S
+++ b/arch/arm/kernel/hyp-stub.S
@@ -125,7 +125,7 @@ ENTRY(__hyp_stub_install_secondary)
* (see safe_svcmode_maskall).
*/
@ Now install the hypervisor stub:
- adr r7, __hyp_stub_vectors
+ W(adr) r7, __hyp_stub_vectors
mcr p15, 4, r7, c12, c0, 0 @ set hypervisor vector base (HVBAR)
@ Disable all traps, so we don't get any nasty surprise
--
2.9.0
^ permalink raw reply related
* [PULL 77/79] KVM: arm/arm64: vgic-v3: Fix off-by-one LR access
From: Christoffer Dall @ 2017-04-23 17:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170423170929.27334-1-cdall@linaro.org>
From: Marc Zyngier <marc.zyngier@arm.com>
When iterating over the used LRs, be careful not to try to access
an unused LR, or even an unimplemented one if you're unlucky...
Reviewed-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
virt/kvm/arm/hyp/vgic-v3-sr.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 91922c1..bce6037 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -143,7 +143,7 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
val = read_gicreg(ICH_VTR_EL2);
nr_pri_bits = vtr_to_nr_pri_bits(val);
- for (i = 0; i <= used_lrs; i++) {
+ for (i = 0; i < used_lrs; i++) {
if (cpu_if->vgic_elrsr & (1 << i))
cpu_if->vgic_lr[i] &= ~ICH_LR_STATE;
else
--
2.9.0
^ permalink raw reply related
* [PULL 76/79] KVM: arm/arm64: vgic-v3: De-optimize VMCR save/restore when emulating a GICv2
From: Christoffer Dall @ 2017-04-23 17:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170423170929.27334-1-cdall@linaro.org>
From: Marc Zyngier <marc.zyngier@arm.com>
When emulating a GICv2-on-GICv3, special care must be taken to only
save/restore VMCR_EL2 when ICC_SRE_EL1.SRE is cleared. Otherwise,
all Group-0 interrupts end-up being delivered as FIQ, which is
probably not what the guest expects, as demonstrated here with
an unhappy EFI:
FIQ Exception at 0x000000013BD21CC4
This means that we cannot perform the load/put trick when dealing
with VMCR_EL2 (because the host has SRE set), and we have to deal
with it in the world-switch.
Fortunately, this is not the most common case (modern guests should
be able to deal with GICv3 directly), and the performance is not worse
than what it was before the VMCR optimization.
Reviewed-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
virt/kvm/arm/hyp/vgic-v3-sr.c | 8 ++++++--
virt/kvm/arm/vgic/vgic-v3.c | 11 +++++++++--
2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 3d0b1dd..91922c1 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -128,8 +128,10 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
* Make sure stores to the GIC via the memory mapped interface
* are now visible to the system register interface.
*/
- if (!cpu_if->vgic_sre)
+ if (!cpu_if->vgic_sre) {
dsb(st);
+ cpu_if->vgic_vmcr = read_gicreg(ICH_VMCR_EL2);
+ }
if (used_lrs) {
int i;
@@ -205,11 +207,13 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
* delivered as a FIQ to the guest, with potentially fatal
* consequences. So we must make sure that ICC_SRE_EL1 has
* been actually programmed with the value we want before
- * starting to mess with the rest of the GIC.
+ * starting to mess with the rest of the GIC, and VMCR_EL2 in
+ * particular.
*/
if (!cpu_if->vgic_sre) {
write_gicreg(0, ICC_SRE_EL1);
isb();
+ write_gicreg(cpu_if->vgic_vmcr, ICH_VMCR_EL2);
}
val = read_gicreg(ICH_VTR_EL2);
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index bc7010d..df15036 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -373,12 +373,19 @@ void vgic_v3_load(struct kvm_vcpu *vcpu)
{
struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
- kvm_call_hyp(__vgic_v3_write_vmcr, cpu_if->vgic_vmcr);
+ /*
+ * If dealing with a GICv2 emulation on GICv3, VMCR_EL2.VFIQen
+ * is dependent on ICC_SRE_EL1.SRE, and we have to perform the
+ * VMCR_EL2 save/restore in the world switch.
+ */
+ if (likely(cpu_if->vgic_sre))
+ kvm_call_hyp(__vgic_v3_write_vmcr, cpu_if->vgic_vmcr);
}
void vgic_v3_put(struct kvm_vcpu *vcpu)
{
struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
- cpu_if->vgic_vmcr = kvm_call_hyp(__vgic_v3_read_vmcr);
+ if (likely(cpu_if->vgic_sre))
+ cpu_if->vgic_vmcr = kvm_call_hyp(__vgic_v3_read_vmcr);
}
--
2.9.0
^ permalink raw reply related
* [PULL 75/79] KVM: arm/arm64: fix races in kvm_psci_vcpu_on
From: Christoffer Dall @ 2017-04-23 17:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170423170929.27334-1-cdall@linaro.org>
From: Andrew Jones <drjones@redhat.com>
Fix potential races in kvm_psci_vcpu_on() by taking the kvm->lock
mutex. In general, it's a bad idea to allow more than one PSCI_CPU_ON
to process the same target VCPU at the same time. One such problem
that may arise is that one PSCI_CPU_ON could be resetting the target
vcpu, which fills the entire sys_regs array with a temporary value
including the MPIDR register, while another looks up the VCPU based
on the MPIDR value, resulting in no target VCPU found. Resolves both
races found with the kvm-unit-tests/arm/psci unit test.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Christoffer Dall <cdall@linaro.org>
Reported-by: Levente Kurusa <lkurusa@redhat.com>
Suggested-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Andrew Jones <drjones@redhat.com>
Cc: stable at vger.kernel.org
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
arch/arm/kvm/psci.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index c2b1315..a08d7a9 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -208,9 +208,10 @@ int kvm_psci_version(struct kvm_vcpu *vcpu)
static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
{
- int ret = 1;
+ struct kvm *kvm = vcpu->kvm;
unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
unsigned long val;
+ int ret = 1;
switch (psci_fn) {
case PSCI_0_2_FN_PSCI_VERSION:
@@ -230,7 +231,9 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
break;
case PSCI_0_2_FN_CPU_ON:
case PSCI_0_2_FN64_CPU_ON:
+ mutex_lock(&kvm->lock);
val = kvm_psci_vcpu_on(vcpu);
+ mutex_unlock(&kvm->lock);
break;
case PSCI_0_2_FN_AFFINITY_INFO:
case PSCI_0_2_FN64_AFFINITY_INFO:
@@ -279,6 +282,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
{
+ struct kvm *kvm = vcpu->kvm;
unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
unsigned long val;
@@ -288,7 +292,9 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
val = PSCI_RET_SUCCESS;
break;
case KVM_PSCI_FN_CPU_ON:
+ mutex_lock(&kvm->lock);
val = kvm_psci_vcpu_on(vcpu);
+ mutex_unlock(&kvm->lock);
break;
default:
val = PSCI_RET_NOT_SUPPORTED;
--
2.9.0
^ permalink raw reply related
* [PULL 74/79] KVM: arm/arm64: Advertise support for KVM_CAP_ARM_USER_IRQ
From: Christoffer Dall @ 2017-04-23 17:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170423170929.27334-1-cdall@linaro.org>
From: Christoffer Dall <christoffer.dall@linaro.org>
Now that we support both timers and PMU reporting interrupts
to userspace, we can advertise this support.
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
arch/arm/kvm/arm.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 9eda293..7941699 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -229,6 +229,13 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
else
r = kvm->arch.vgic.msis_require_devid;
break;
+ case KVM_CAP_ARM_USER_IRQ:
+ /*
+ * 1: EL1_VTIMER, EL1_PTIMER, and PMU.
+ * (bump this number if adding more devices)
+ */
+ r = 1;
+ break;
default:
r = kvm_arch_dev_ioctl_check_extension(kvm, ext);
break;
--
2.9.0
^ permalink raw reply related
* [PULL 73/79] KVM: arm/arm64: Report PMU overflow interrupts to userspace irqchip
From: Christoffer Dall @ 2017-04-23 17:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170423170929.27334-1-cdall@linaro.org>
From: Christoffer Dall <christoffer.dall@linaro.org>
When not using an in-kernel VGIC, but instead emulating an interrupt
controller in userspace, we should report the PMU overflow status to
that userspace interrupt controller using the KVM_CAP_ARM_USER_IRQ
feature.
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
arch/arm/kvm/arm.c | 13 +++++++++----
include/kvm/arm_pmu.h | 7 +++++++
virt/kvm/arm/arch_timer.c | 3 ---
virt/kvm/arm/pmu.c | 39 +++++++++++++++++++++++++++++++++++----
4 files changed, 51 insertions(+), 11 deletions(-)
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index ac6e57b..9eda293 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -635,11 +635,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
/*
* If we have a singal pending, or need to notify a userspace
- * irqchip about timer level changes, then we exit (and update
- * the timer level state in kvm_timer_update_run below).
+ * irqchip about timer or PMU level changes, then we exit (and
+ * update the timer level state in kvm_timer_update_run
+ * below).
*/
if (signal_pending(current) ||
- kvm_timer_should_notify_user(vcpu)) {
+ kvm_timer_should_notify_user(vcpu) ||
+ kvm_pmu_should_notify_user(vcpu)) {
ret = -EINTR;
run->exit_reason = KVM_EXIT_INTR;
}
@@ -712,7 +714,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
}
/* Tell userspace about in-kernel device output levels */
- kvm_timer_update_run(vcpu);
+ if (unlikely(!irqchip_in_kernel(vcpu->kvm))) {
+ kvm_timer_update_run(vcpu);
+ kvm_pmu_update_run(vcpu);
+ }
if (vcpu->sigset_active)
sigprocmask(SIG_SETMASK, &sigsaved, NULL);
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index 92e7e97..1ab4633 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -50,6 +50,8 @@ void kvm_pmu_enable_counter(struct kvm_vcpu *vcpu, u64 val);
void kvm_pmu_overflow_set(struct kvm_vcpu *vcpu, u64 val);
void kvm_pmu_flush_hwstate(struct kvm_vcpu *vcpu);
void kvm_pmu_sync_hwstate(struct kvm_vcpu *vcpu);
+bool kvm_pmu_should_notify_user(struct kvm_vcpu *vcpu);
+void kvm_pmu_update_run(struct kvm_vcpu *vcpu);
void kvm_pmu_software_increment(struct kvm_vcpu *vcpu, u64 val);
void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val);
void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data,
@@ -85,6 +87,11 @@ static inline void kvm_pmu_enable_counter(struct kvm_vcpu *vcpu, u64 val) {}
static inline void kvm_pmu_overflow_set(struct kvm_vcpu *vcpu, u64 val) {}
static inline void kvm_pmu_flush_hwstate(struct kvm_vcpu *vcpu) {}
static inline void kvm_pmu_sync_hwstate(struct kvm_vcpu *vcpu) {}
+static inline bool kvm_pmu_should_notify_user(struct kvm_vcpu *vcpu)
+{
+ return false;
+}
+static inline void kvm_pmu_update_run(struct kvm_vcpu *vcpu) {}
static inline void kvm_pmu_software_increment(struct kvm_vcpu *vcpu, u64 val) {}
static inline void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val) {}
static inline void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu,
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 5dc2167..5976609 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -193,9 +193,6 @@ void kvm_timer_update_run(struct kvm_vcpu *vcpu)
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
struct kvm_sync_regs *regs = &vcpu->run->s.regs;
- if (likely(irqchip_in_kernel(vcpu->kvm)))
- return;
-
/* Populate the device bitmap with the timer states */
regs->device_irq_level &= ~(KVM_ARM_DEV_EL1_VTIMER |
KVM_ARM_DEV_EL1_PTIMER);
diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
index 69ccce3..4b43e7f 100644
--- a/virt/kvm/arm/pmu.c
+++ b/virt/kvm/arm/pmu.c
@@ -230,13 +230,44 @@ static void kvm_pmu_update_state(struct kvm_vcpu *vcpu)
return;
overflow = !!kvm_pmu_overflow_status(vcpu);
- if (pmu->irq_level != overflow) {
- pmu->irq_level = overflow;
- kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
- pmu->irq_num, overflow);
+ if (pmu->irq_level == overflow)
+ return;
+
+ pmu->irq_level = overflow;
+
+ if (likely(irqchip_in_kernel(vcpu->kvm))) {
+ int ret;
+ ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
+ pmu->irq_num, overflow);
+ WARN_ON(ret);
}
}
+bool kvm_pmu_should_notify_user(struct kvm_vcpu *vcpu)
+{
+ struct kvm_pmu *pmu = &vcpu->arch.pmu;
+ struct kvm_sync_regs *sregs = &vcpu->run->s.regs;
+ bool run_level = sregs->device_irq_level & KVM_ARM_DEV_PMU;
+
+ if (likely(irqchip_in_kernel(vcpu->kvm)))
+ return false;
+
+ return pmu->irq_level != run_level;
+}
+
+/*
+ * Reflect the PMU overflow interrupt output level into the kvm_run structure
+ */
+void kvm_pmu_update_run(struct kvm_vcpu *vcpu)
+{
+ struct kvm_sync_regs *regs = &vcpu->run->s.regs;
+
+ /* Populate the timer bitmap for user space */
+ regs->device_irq_level &= ~KVM_ARM_DEV_PMU;
+ if (vcpu->arch.pmu.irq_level)
+ regs->device_irq_level |= KVM_ARM_DEV_PMU;
+}
+
/**
* kvm_pmu_flush_hwstate - flush pmu state to cpu
* @vcpu: The vcpu pointer
--
2.9.0
^ permalink raw reply related
* [PULL 72/79] KVM: arm/arm64: Support arch timers with a userspace gic
From: Christoffer Dall @ 2017-04-23 17:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170423170929.27334-1-cdall@linaro.org>
From: Alexander Graf <agraf@suse.de>
If you're running with a userspace gic or other interrupt controller
(that is no vgic in the kernel), then you have so far not been able to
use the architected timers, because the output of the architected
timers, which are driven inside the kernel, was a kernel-only construct
between the arch timer code and the vgic.
This patch implements the new KVM_CAP_ARM_USER_IRQ feature, where we use a
side channel on the kvm_run structure, run->s.regs.device_irq_level, to
always notify userspace of the timer output levels when using a userspace
irqchip.
This works by ensuring that before we enter the guest, if the timer
output level has changed compared to what we last told userspace, we
don't enter the guest, but instead return to userspace to notify it of
the new level. If we are exiting, because of an MMIO for example, and
the level changed at the same time, the value is also updated and
userspace can sample the line as it needs. This is nicely achieved
simply always updating the timer_irq_level field after the main run
loop.
Note that the kvm_timer_update_irq trace event is changed to show the
host IRQ number for the timer instead of the guest IRQ number, because
the kernel no longer know which IRQ userspace wires up the timer signal
to.
Also note that this patch implements all required functionality but does
not yet advertise the capability.
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
arch/arm/kvm/arm.c | 18 +++----
include/kvm/arm_arch_timer.h | 2 +
virt/kvm/arm/arch_timer.c | 122 +++++++++++++++++++++++++++++++++++--------
3 files changed, 110 insertions(+), 32 deletions(-)
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index c378502..ac6e57b 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -515,13 +515,7 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
return ret;
}
- /*
- * Enable the arch timers only if we have an in-kernel VGIC
- * and it has been properly initialized, since we cannot handle
- * interrupts from the virtual timer with a userspace gic.
- */
- if (irqchip_in_kernel(kvm) && vgic_initialized(kvm))
- ret = kvm_timer_enable(vcpu);
+ ret = kvm_timer_enable(vcpu);
return ret;
}
@@ -640,9 +634,12 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
local_irq_disable();
/*
- * Re-check atomic conditions
+ * If we have a singal pending, or need to notify a userspace
+ * irqchip about timer level changes, then we exit (and update
+ * the timer level state in kvm_timer_update_run below).
*/
- if (signal_pending(current)) {
+ if (signal_pending(current) ||
+ kvm_timer_should_notify_user(vcpu)) {
ret = -EINTR;
run->exit_reason = KVM_EXIT_INTR;
}
@@ -714,6 +711,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
ret = handle_exit(vcpu, run, ret);
}
+ /* Tell userspace about in-kernel device output levels */
+ kvm_timer_update_run(vcpu);
+
if (vcpu->sigset_active)
sigprocmask(SIG_SETMASK, &sigsaved, NULL);
return ret;
diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index fe797d6..295584f 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -63,6 +63,8 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu);
void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu);
void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu);
+bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu);
+void kvm_timer_update_run(struct kvm_vcpu *vcpu);
void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu);
u64 kvm_arm_timer_get_reg(struct kvm_vcpu *, u64 regid);
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 363f0d2..5dc2167 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -184,6 +184,27 @@ bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx)
return cval <= now;
}
+/*
+ * Reflect the timer output level into the kvm_run structure
+ */
+void kvm_timer_update_run(struct kvm_vcpu *vcpu)
+{
+ struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
+ struct kvm_sync_regs *regs = &vcpu->run->s.regs;
+
+ if (likely(irqchip_in_kernel(vcpu->kvm)))
+ return;
+
+ /* Populate the device bitmap with the timer states */
+ regs->device_irq_level &= ~(KVM_ARM_DEV_EL1_VTIMER |
+ KVM_ARM_DEV_EL1_PTIMER);
+ if (vtimer->irq.level)
+ regs->device_irq_level |= KVM_ARM_DEV_EL1_VTIMER;
+ if (ptimer->irq.level)
+ regs->device_irq_level |= KVM_ARM_DEV_EL1_PTIMER;
+}
+
static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
struct arch_timer_context *timer_ctx)
{
@@ -194,9 +215,12 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
trace_kvm_timer_update_irq(vcpu->vcpu_id, timer_ctx->irq.irq,
timer_ctx->irq.level);
- ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id, timer_ctx->irq.irq,
- timer_ctx->irq.level);
- WARN_ON(ret);
+ if (likely(irqchip_in_kernel(vcpu->kvm))) {
+ ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
+ timer_ctx->irq.irq,
+ timer_ctx->irq.level);
+ WARN_ON(ret);
+ }
}
/*
@@ -215,7 +239,7 @@ static void kvm_timer_update_state(struct kvm_vcpu *vcpu)
* because the guest would never see the interrupt. Instead wait
* until we call this function from kvm_timer_flush_hwstate.
*/
- if (!timer->enabled)
+ if (unlikely(!timer->enabled))
return;
if (kvm_timer_should_fire(vtimer) != vtimer->irq.level)
@@ -282,28 +306,12 @@ void kvm_timer_unschedule(struct kvm_vcpu *vcpu)
timer_disarm(timer);
}
-/**
- * kvm_timer_flush_hwstate - prepare to move the virt timer to the cpu
- * @vcpu: The vcpu pointer
- *
- * Check if the virtual timer has expired while we were running in the host,
- * and inject an interrupt if that was the case.
- */
-void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
+static void kvm_timer_flush_hwstate_vgic(struct kvm_vcpu *vcpu)
{
- struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
bool phys_active;
int ret;
- if (unlikely(!timer->enabled))
- return;
-
- kvm_timer_update_state(vcpu);
-
- /* Set the background timer for the physical timer emulation. */
- kvm_timer_emulate(vcpu, vcpu_ptimer(vcpu));
-
/*
* If we enter the guest with the virtual input level to the VGIC
* asserted, then we have already told the VGIC what we need to, and
@@ -355,11 +363,72 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
vtimer->active_cleared_last = !phys_active;
}
+bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu)
+{
+ struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+ struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
+ struct kvm_sync_regs *sregs = &vcpu->run->s.regs;
+ bool vlevel, plevel;
+
+ if (likely(irqchip_in_kernel(vcpu->kvm)))
+ return false;
+
+ vlevel = sregs->device_irq_level & KVM_ARM_DEV_EL1_VTIMER;
+ plevel = sregs->device_irq_level & KVM_ARM_DEV_EL1_PTIMER;
+
+ return vtimer->irq.level != vlevel ||
+ ptimer->irq.level != plevel;
+}
+
+static void kvm_timer_flush_hwstate_user(struct kvm_vcpu *vcpu)
+{
+ struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+
+ /*
+ * To prevent continuously exiting from the guest, we mask the
+ * physical interrupt such that the guest can make forward progress.
+ * Once we detect the output level being deasserted, we unmask the
+ * interrupt again so that we exit from the guest when the timer
+ * fires.
+ */
+ if (vtimer->irq.level)
+ disable_percpu_irq(host_vtimer_irq);
+ else
+ enable_percpu_irq(host_vtimer_irq, 0);
+}
+
+/**
+ * kvm_timer_flush_hwstate - prepare timers before running the vcpu
+ * @vcpu: The vcpu pointer
+ *
+ * Check if the virtual timer has expired while we were running in the host,
+ * and inject an interrupt if that was the case, making sure the timer is
+ * masked or disabled on the host so that we keep executing. Also schedule a
+ * software timer for the physical timer if it is enabled.
+ */
+void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
+{
+ struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+
+ if (unlikely(!timer->enabled))
+ return;
+
+ kvm_timer_update_state(vcpu);
+
+ /* Set the background timer for the physical timer emulation. */
+ kvm_timer_emulate(vcpu, vcpu_ptimer(vcpu));
+
+ if (unlikely(!irqchip_in_kernel(vcpu->kvm)))
+ kvm_timer_flush_hwstate_user(vcpu);
+ else
+ kvm_timer_flush_hwstate_vgic(vcpu);
+}
+
/**
* kvm_timer_sync_hwstate - sync timer state from cpu
* @vcpu: The vcpu pointer
*
- * Check if the virtual timer has expired while we were running in the guest,
+ * Check if any of the timers have expired while we were running in the guest,
* and inject an interrupt if that was the case.
*/
void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
@@ -559,6 +628,13 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
if (timer->enabled)
return 0;
+ /* Without a VGIC we do not map virtual IRQs to physical IRQs */
+ if (!irqchip_in_kernel(vcpu->kvm))
+ goto no_vgic;
+
+ if (!vgic_initialized(vcpu->kvm))
+ return -ENODEV;
+
/*
* Find the physical IRQ number corresponding to the host_vtimer_irq
*/
@@ -582,8 +658,8 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
if (ret)
return ret;
+no_vgic:
timer->enabled = 1;
-
return 0;
}
--
2.9.0
^ 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