* [PATCH v3 2/3] crypto: inside-secure: add SafeXcel EIP197 crypto engine driver
From: Robin Murphy @ 2017-05-03 11:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170424075407.19730-3-antoine.tenart@free-electrons.com>
Hi Antoine,
On 24/04/17 08:54, Antoine Tenart wrote:
> Add support for Inside Secure SafeXcel EIP197 cryptographic engine,
> which can be found on Marvell Armada 7k and 8k boards. This driver
> currently implements: ecb(aes), cbc(aes), sha1, sha224, sha256 and
> hmac(sah1) algorithms.
>
> Two firmwares are needed for this engine to work. Their are mostly used
> for more advanced operations than the ones supported (as of now), but we
> still need them to pass the data to the internal cryptographic engine.
>
> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
[...]
> diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c
> new file mode 100644
> index 000000000000..9cb3d0832835
> --- /dev/null
> +++ b/drivers/crypto/inside-secure/safexcel.c
> @@ -0,0 +1,925 @@
> +/*
> + * Copyright (C) 2017 Marvell
> + *
> + * Antoine Tenart <antoine.tenart@free-electrons.com>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/dmapool.h>
> +#include <linux/firmware.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/workqueue.h>
> +
> +#include <asm/dma-mapping.h>
<linux/dma-mapping.h> everywhere, please.
Other than that, the DMA aspects all look much nicer now, thanks.
Robin.
^ permalink raw reply
* [PATCH] arm64: Add translation functions for /dev/mem read/write
From: Will Deacon @ 2017-05-03 11:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1493756885-29704-1-git-send-email-sgoel@codeaurora.org>
[adding some /dev/mem fans to cc]
On Tue, May 02, 2017 at 02:28:05PM -0600, Sameer Goel wrote:
> Port architecture specific xlate and unxlate functions for /dev/mem
> read/write. This sets up the mapping for a valid physical address if a
> kernel direct mapping is not already present.
>
> This is a generic issue as a user space app should not be allowed to crash
> the kernel.
> This issue was observed when systemd tried to access performance
> pointer record from the FPDT table.
Why is it doing that? Is there not a way to get this via /sys?
> Ported from commit e045fb2a988a ("x86: PAT avoid aliasing in /dev/mem
> read/write")
>
> Crash Signature:
> Unable to handle kernel paging request at virtual address ffff800008ff0000
> pgd = ffff8007de8b2200
> [ffff800008ff0000] *pgd=0000000000000000, *pud=0000000000000000
> Internal error: Oops: 96000007 [#1] SMP
> ................
> CPU: 0 PID: 1 Comm: systemd Not tainted 4.10.0 #1
> task: ffff8007c0820000 task.stack: ffff8007c0900000
> PC is at __arch_copy_to_user+0xb4/0x280
> LR is at read_mem+0xc0/0x138
> pc : [<ffff0000084b3bb4>] lr : [<ffff00000869d178>]
> pstate: 80000145
> sp : ffff8007c0903d40
> ....................
> x3 : ffff800800000000 x2 : 0000000000000008
> x1 : ffff800008ff0000 x0 : 0000fffff6fdac00
> ....................
> Call trace:
> Exception stack(0xffff8007c0903b70 to 0xffff8007c0903ca0)
> [<ffff0000084b3bb4>] __arch_copy_to_user+0xb4/0x280
> [<ffff0000082454d0>] __vfs_read+0x48/0x130
> [<ffff0000082467dc>] vfs_read+0x8c/0x148
> [<ffff000008247a34>] SyS_pread64+0x94/0xa8
> [<ffff0000080833b0>] el0_svc_naked+0x24/0x28
So this certainly looks like a kernel bug, but I don't think your patch is
the right way to fix it.
> Code: a88120c7 d503201f d503201f 36180082 (f8408423)
>
> Signed-off-by: Sameer Goel <sgoel@codeaurora.org>
> Tested-by: Shanker Donthineni <shankerd@codeaurora.org>
> ---
> arch/arm64/include/asm/io.h | 5 +++++
> arch/arm64/mm/ioremap.c | 31 +++++++++++++++++++++++++++++++
> 2 files changed, 36 insertions(+)
>
> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
> index 0c00c87..c869ea4 100644
> --- a/arch/arm64/include/asm/io.h
> +++ b/arch/arm64/include/asm/io.h
> @@ -183,6 +183,11 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
> #define iowrite32be(v,p) ({ __iowmb(); __raw_writel((__force __u32)cpu_to_be32(v), p); })
> #define iowrite64be(v,p) ({ __iowmb(); __raw_writeq((__force __u64)cpu_to_be64(v), p); })
>
> +extern void *xlate_dev_mem_ptr(phys_addr_t phys);
> +extern void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr);
> +
> +#define xlate_dev_mem_ptr xlate_dev_mem_ptr
> +#define unxlate_dev_mem_ptr unxlate_dev_mem_ptr
> #include <asm-generic/io.h>
>
> /*
> diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
> index c4c8cd4..ba7e63b 100644
> --- a/arch/arm64/mm/ioremap.c
> +++ b/arch/arm64/mm/ioremap.c
> @@ -24,6 +24,7 @@
> #include <linux/mm.h>
> #include <linux/vmalloc.h>
> #include <linux/io.h>
> +#include <linux/memblock.h>
>
> #include <asm/fixmap.h>
> #include <asm/tlbflush.h>
> @@ -105,6 +106,36 @@ void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size)
> EXPORT_SYMBOL(ioremap_cache);
>
> /*
> + * Convert a physical pointer to a virtual kernel pointer for /dev/mem
> + * access
> + */
> +void *xlate_dev_mem_ptr(phys_addr_t phys)
> +{
> + unsigned long start = phys & PAGE_MASK;
> + unsigned long offset = phys & ~PAGE_MASK;
> + void *vaddr;
> +
> + /* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
> + if (page_is_ram(start >> PAGE_SHIFT) && memblock_is_memory(phys))
> + return __va(phys);
> +
> + vaddr = ioremap_cache(start, PAGE_SIZE);
Blindly using ioremap like this looks unsafe, since we could accidentally
set conflict with the attributes of a mapping used by something else (e.g.
firmware running on another CPU).
I'd like to understand more about the crash, so we can see work out how to
fix this properly.
Will
^ permalink raw reply
* [PATCH v3 3/3] arm64: Silence first allocation with CONFIG_ARM64_MODULE_PLTS=y
From: Will Deacon @ 2017-05-03 11:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170427181902.28829-4-f.fainelli@gmail.com>
On Thu, Apr 27, 2017 at 11:19:02AM -0700, Florian Fainelli wrote:
> When CONFIG_ARM64_MODULE_PLTS is enabled, the first allocation using the
> module space fails, because the module is too big, and then the module
> allocation is attempted from vmalloc space. Silence the first allocation
> failure in that case by setting __GFP_NOWARN.
>
> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
> arch/arm64/kernel/module.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
I'm not sure what the merge plan is for these, but the arm64 bit here
looks fine to me:
Acked-by: Will Deacon <will.deacon@arm.com>
Will
> diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
> index 7f316982ce00..093c13541efb 100644
> --- a/arch/arm64/kernel/module.c
> +++ b/arch/arm64/kernel/module.c
> @@ -32,11 +32,16 @@
>
> void *module_alloc(unsigned long size)
> {
> + gfp_t gfp_mask = GFP_KERNEL;
> void *p;
>
> + /* Silence the initial allocation */
> + if (IS_ENABLED(CONFIG_ARM64_MODULE_PLTS))
> + gfp_mask |= __GFP_NOWARN;
> +
> p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base,
> module_alloc_base + MODULES_VSIZE,
> - GFP_KERNEL, PAGE_KERNEL_EXEC, 0,
> + gfp_mask, PAGE_KERNEL_EXEC, 0,
> NUMA_NO_NODE, __builtin_return_address(0));
>
> if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) &&
> --
> 2.9.3
>
^ permalink raw reply
* [PATCH V8 07/11] iommu: of: Handle IOMMU lookup failure with deferred probing or error
From: Sricharan R @ 2017-05-03 11:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <26defadf-6380-4af4-6323-b51198376bc1@codeaurora.org>
Hi,
On 5/3/2017 3:54 PM, Sricharan R wrote:
> Hi Robin,
>
> On 5/3/2017 3:24 PM, Robin Murphy wrote:
>> Hi Geert,
>>
>> On 02/05/17 19:35, Geert Uytterhoeven wrote:
>>> Hi Sricharan,
>>>
>>> On Fri, Feb 3, 2017 at 4:48 PM, Sricharan R <sricharan@codeaurora.org> wrote:
>>>> From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
>>>>
>>>> Failures to look up an IOMMU when parsing the DT iommus property need to
>>>> be handled separately from the .of_xlate() failures to support deferred
>>>> probing.
>>>>
>>>> The lack of a registered IOMMU can be caused by the lack of a driver for
>>>> the IOMMU, the IOMMU device probe not having been performed yet, having
>>>> been deferred, or having failed.
>>>>
>>>> The first case occurs when the device tree describes the bus master and
>>>> IOMMU topology correctly but no device driver exists for the IOMMU yet
>>>> or the device driver has not been compiled in. Return NULL, the caller
>>>> will configure the device without an IOMMU.
>>>>
>>>> The second and third cases are handled by deferring the probe of the bus
>>>> master device which will eventually get reprobed after the IOMMU.
>>>>
>>>> The last case is currently handled by deferring the probe of the bus
>>>> master device as well. A mechanism to either configure the bus master
>>>> device without an IOMMU or to fail the bus master device probe depending
>>>> on whether the IOMMU is optional or mandatory would be a good
>>>> enhancement.
>>>>
>>>> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
>>>> Signed-off-by: Laurent Pichart <laurent.pinchart+renesas@ideasonboard.com>
>>>> Signed-off-by: Sricharan R <sricharan@codeaurora.org>
>>>
>>> This patch broke Renesas R-Car Gen3 platforms in renesas-drivers.
>>> As the IOMMU nodes in DT are not yet enabled, all devices having iommus
>>> properties in DT now fail to probe.
>>
>> How exactly do they fail to probe? Per d7b0558230e4, if there are no ops
>> registered then they should merely defer until we reach the point of
>> giving up and ignoring the IOMMU. Is it just that you have no other
>> late-probing drivers or post-init module loads to kick the deferred
>> queue after that point? I did try to find a way to explicitly kick it
>> from a suitably late initcall, but there didn't seem to be any obvious
>> public interface - anyone have any suggestions?
>>
>> I think that's more of a general problem with the probe deferral
>> mechanism itself (I've seen the same thing happen with some of the
>> CoreSight stuff on Juno due to the number of inter-component
>> dependencies) rather than any specific fault of this series.
>>
>
> I was thinking of an additional check like below to avoid the
> situation ?
>
> From 499b6e662f60f23740b8880882b0a16f16434501 Mon Sep 17 00:00:00 2001
> From: Sricharan R <sricharan@codeaurora.org>
> Date: Wed, 3 May 2017 13:16:59 +0530
> Subject: [PATCH] iommu: of: Fix check for returning EPROBE_DEFER
>
> While returning EPROBE_DEFER for iommu masters
> take in to account of iommu nodes that could be
> marked in DT as 'status=disabled', in which case
> simply return NULL and let the master's probe
> continue rather than deferring.
>
> Signed-off-by: Sricharan R <sricharan@codeaurora.org>
> ---
> drivers/iommu/of_iommu.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> index 9f44ee8..e6e9bec 100644
> --- a/drivers/iommu/of_iommu.c
> +++ b/drivers/iommu/of_iommu.c
> @@ -118,6 +118,7 @@ static bool of_iommu_driver_present(struct device_node *np)
>
> ops = iommu_ops_from_fwnode(fwnode);
> if ((ops && !ops->of_xlate) ||
> + !of_device_is_available(iommu_spec->np) ||
> (!ops && !of_iommu_driver_present(iommu_spec->np)))
> return NULL;
>
While same as the other 'status=disabled' patch [1], better not to
defer the probe itself in the case ?
[1] https://patchwork.kernel.org/patch/9681211/
Regards,
Sricharan
--
"QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
^ permalink raw reply
* [PATCH] drivers/of_iommu: ignore SMMU DT nodes with status 'disabled'
From: Ard Biesheuvel @ 2017-05-03 10:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1c0463e6-f82f-1179-4f54-b2d3de63dc87@arm.com>
> On 3 May 2017, at 11:32, Robin Murphy <robin.murphy@arm.com> wrote:
>
>> On 28/04/17 14:22, Ard Biesheuvel wrote:
>>> On 28 April 2017 at 14:17, Will Deacon <will.deacon@arm.com> wrote:
>>>> On Fri, Apr 28, 2017 at 02:14:49PM +0100, Ard Biesheuvel wrote:
>>>>> On 28 April 2017 at 14:11, Will Deacon <will.deacon@arm.com> wrote:
>>>>> Hi Ard,
>>>>>
>>>>> [+ devicetree@]
>>>>>
>>>>>> On Fri, Apr 14, 2017 at 01:43:15PM +0100, Ard Biesheuvel wrote:
>>>>>> DT nodes may have a status property, and if they do, such nodes should
>>>>>> only be considered present if the status property is set to 'okay'.
>>>>>>
>>>>>> Currently, we call the init function of IOMMUs described by the device
>>>>>> tree without taking this into account, which may result in the output
>>>>>> below on systems where some SMMUs may be legally disabled.
>>>>>>
>>>>>> Failed to initialise IOMMU /smb/smmu at e0200000
>>>>>> Failed to initialise IOMMU /smb/smmu at e0c00000
>>>>>> arm-smmu e0a00000.smmu: probing hardware configuration...
>>>>>> arm-smmu e0a00000.smmu: SMMUv1 with:
>>>>>> arm-smmu e0a00000.smmu: stage 2 translation
>>>>>> arm-smmu e0a00000.smmu: coherent table walk
>>>>>> arm-smmu e0a00000.smmu: stream matching with 32 register groups, mask 0x7fff
>>>>>> arm-smmu e0a00000.smmu: 8 context banks (8 stage-2 only)
>>>>>> arm-smmu e0a00000.smmu: Supported page sizes: 0x60211000
>>>>>> arm-smmu e0a00000.smmu: Stage-2: 40-bit IPA -> 40-bit PA
>>>>>> Failed to initialise IOMMU /smb/smmu at e0600000
>>>>>> Failed to initialise IOMMU /smb/smmu at e0800000
>>>>>>
>>>>>> Since this is not an error condition, only call the init function if
>>>>>> the device is enabled, which also inhibits the spurious error messages.
>>>>>>
>>>>>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>>>>> ---
>>>>>> drivers/iommu/of_iommu.c | 2 +-
>>>>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
>>>>>> index 2683e9fc0dcf..2dd1206e6c0d 100644
>>>>>> --- a/drivers/iommu/of_iommu.c
>>>>>> +++ b/drivers/iommu/of_iommu.c
>>>>>> @@ -183,7 +183,7 @@ static int __init of_iommu_init(void)
>>>>>> for_each_matching_node_and_match(np, matches, &match) {
>>>>>> const of_iommu_init_fn init_fn = match->data;
>>>>>>
>>>>>> - if (init_fn(np))
>>>>>> + if (of_device_is_available(np) && init_fn(np))
>>>>>> pr_err("Failed to initialise IOMMU %s\n",
>>>>>> of_node_full_name(np));
>>>>>> }
>>>>>
>>>>> Is there a definition of what status = "disabled" is supposed to mean for an
>>>>> IOMMU? For example, that could mean that the firmware has pre-programmed the
>>>>> SMMU with particular translations or memory attributes (a bit like the
>>>>> CCA=1, CPM=1, DACS=0 case in ACPI IORT), or even disabled DMA traffic
>>>>> altogether.
>>>>>
>>>>> So I think we'd need an update to the generic IOMMU binding text to say
>>>>> exactly what the semantics are supposed to be here.
>>>>>
>>>>
>>>> I agree that it might make sense to describe the behavior of the IOMMU
>>>> when it is left in the state we found it in. But that is not the same
>>>> as status=disabled.
>>>>
>>>> The DTS subtree contains loads and loads of boilerplate
>>>> configurations, where only some pieces are enabled in the final image
>>>> by setting status=okay. So a node that has status 'disabled' should be
>>>> treated as 'not present', not as 'present but can be ignored under
>>>> assumptions such and such'
>>>>
>>>> In other words, I think we are talking about two different issues here.
>>>
>>> I'm not so sure... if we have a master device that has an iommus= property
>>> pointing to an IOMMU with status="disabled", I really don't know whether we
>>> should:
>>>
>>> 1. Assume the master can do DMA with a 1:1 mapping of memory and no
>>> changes to memory attributes
>>>
>>> 2. Assume the master can do DMA with a 1:1 mapping of memory, but
>>> potentially with changes to the attributes
>>>
>>> 3. Assume the master can do DMA, but with some pre-existing translation
>>> (what?)
>>>
>>> 4. Assume the master can't do DMA
>>>
>>> and I also don't know whether the "dma-coherent" property remains valid.
>>>
>>
>> Ah yes. Good point.
>>
>> So indeed, there should be some IOMMU specific status property that
>> can convey all of the above, or 1. and 4. at the minimum
>
> FWIW, the underlying issue being addressed here should be going away now
> anyway, since the now-queued probe deferral series obviates the init_fn
> early-device-creation bodge. I've been deliberately ignoring it for some
> time for precisely that reason ;)
>
Ok. I have also updated the Seattle firmware to remove the smmu nodes and the associated iommus/iommu-map properties entirely when disabling SMMU support in the firmware, which should address Will's concern regarding unspecified behavior of a disabled SMMU.
IOW, this patch can be disregarded. Thanks.
^ permalink raw reply
* [PATCH] arm64: Fix multiple 'asm-operand-widths' warnings
From: Mark Rutland @ 2017-05-03 10:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170502185212.GY128305@google.com>
On Tue, May 02, 2017 at 11:52:12AM -0700, Matthias Kaehlcke wrote:
> El Tue, May 02, 2017 at 06:29:48PM +0100 Mark Rutland ha dit:
> > On Mon, May 01, 2017 at 02:26:22PM -0700, Matthias Kaehlcke wrote:
> > > diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
> > > index 5308d696311b..7db143689694 100644
> > > --- a/arch/arm64/include/asm/uaccess.h
> > > +++ b/arch/arm64/include/asm/uaccess.h
> > > @@ -302,7 +302,7 @@ do { \
> > > " .previous\n" \
> > > _ASM_EXTABLE(1b, 3b) \
> > > : "+r" (err) \
> > > - : "r" (x), "r" (addr), "i" (-EFAULT))
> > > + : "r" ((__u64)x), "r" (addr), "i" (-EFAULT))
> > >
> >
> > For reference, do you have the warning for this case to hand?
> >
> > In __put_user_err() we make __pu_val the same type as *ptr, then we
> > switch on sizeof(*ptr), and pass __pu_val to __put_user_asm(), as x.
> > For cases 1, 2, and 4, we use "%w" as the register template.
> >
> > So I can't see why we'd need this cast in __put_user_err().
> >
> > I must be missing something.
>
> This is one of many instances:
>
> ./include/linux/pagemap.h:554:10: warning: value size does not match register size specified by the constraint and modifier [-Wasm-operand-widths]
> return __put_user(0, end);
> ^
> ./arch/arm64/include/asm/uaccess.h:338:2: note: expanded from macro '__put_user'
> __put_user_err((x), (ptr), __pu_err); \
> ^
> ./arch/arm64/include/asm/uaccess.h:326:38: note: expanded from macro '__put_user_err'
> __put_user_asm("str", "sttr", "%", __pu_val, (ptr), \
> ^
> ./include/linux/pagemap.h:554:10: note: use constraint modifier "w"
> ./arch/arm64/include/asm/uaccess.h:338:2: note: expanded from macro '__put_user'
> __put_user_err((x), (ptr), __pu_err); \
> ^
> ./arch/arm64/include/asm/uaccess.h:326:34: note: expanded from macro '__put_user_err'
> __put_user_asm("str", "sttr", "%", __pu_val, (ptr), \
> ^
Thanks for the log above!
> 'end' is a char pointer, it is not clear to me why we would end up in
> the width == 8 branch.
Indeed.
I took a look, and I think the issue is that clang instantiates the
assembly in all cases, producing the warning, *then* optimizes away the
unreachable cases.
If you ask clang to build the following:
----
#define __put_user(val, ptr) \
do { \
__typeof__(*(ptr)) __pu_val = (val); \
switch (sizeof(*(ptr))) { \
case 1: \
asm volatile ("strb %w1, %0" \
: "+Q" (*(ptr)) : "r" (__pu_val)); \
break; \
case 2: \
asm volatile ("strh %1, %0" \
: "+Q" (*(ptr)) : "r" (__pu_val)); \
break; \
case 4: \
asm volatile ("str %1, %0" \
: "+Q" (*(ptr)) : "r" (__pu_val)); \
break; \
case 8: \
asm volatile ("str %1, %0" \
: "+Q" (*(ptr)) : "r" (__pu_val)); \
break; \
} \
} while (0)
void put_char(char in, char *ptr)
{
__put_user(in, ptr);
}
----
It complains for all of the unmatched cases:
----
size-switch.c:26:2: warning: value size does not match register size specified by the constraint and modifier [-Wasm-operand-widths]
__put_user(in, ptr);
^
size-switch.c:11:28: note: expanded from macro '__put_user'
: "+Q" (*(ptr)) : "r" (__pu_val)); \
^
size-switch.c:26:2: note: use constraint modifier "w"
size-switch.c:10:23: note: expanded from macro '__put_user'
asm volatile ("strh %1, %0" \
^
size-switch.c:26:2: warning: value size does not match register size specified by the constraint and modifier [-Wasm-operand-widths]
__put_user(in, ptr);
^
size-switch.c:15:28: note: expanded from macro '__put_user'
: "+Q" (*(ptr)) : "r" (__pu_val)); \
^
size-switch.c:26:2: note: use constraint modifier "w"
size-switch.c:14:22: note: expanded from macro '__put_user'
asm volatile ("str %1, %0" \
^
size-switch.c:26:2: warning: value size does not match register size specified by the constraint and modifier [-Wasm-operand-widths]
__put_user(in, ptr);
^
size-switch.c:19:28: note: expanded from macro '__put_user'
: "+Q" (*(ptr)) : "r" (__pu_val)); \
^
size-switch.c:26:2: note: use constraint modifier "w"
size-switch.c:18:22: note: expanded from macro '__put_user'
asm volatile ("str %1, %0" \
^
3 warnings generated.
----
AFAICT, in all other cases where we switch(sizeof(...)), we (will) use
an explicit cast on the parameter, which placates clang.
I think the best option is to get rid of __pu_val, and have an explicit
cast of x in each case of the switch statement. I'll add that to my asm
fixups series, with your Reported-by.
Thanks,
Mark.
^ permalink raw reply
* [RFC/RFT PATCH 18/18] ARM/ARM64: PCI: Drop pci_fixup_irqs() usage for DT based host controllers
From: Lorenzo Pieralisi @ 2017-05-03 10:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAK8P3a3dT-PR69LrAc8_9tNkdj+LTztQ0pcJKyAV6DwykyXi4A@mail.gmail.com>
On Fri, Apr 28, 2017 at 03:05:44PM +0200, Arnd Bergmann wrote:
> On Wed, Apr 26, 2017 at 1:18 PM, Lorenzo Pieralisi
> <lorenzo.pieralisi@arm.com> wrote:
> > DT based PCI host controllers are currently relying on
> > pci_fixup_irqs() to assign legacy PCI irqs to devices. This is
> > broken in that pci_fixup_irqs() assign IRQs for all PCI devices
> > present in a given system some of which may well be enabled by
> > the time pci_fixup_irqs() is called (ie a system with multiple
> > host controllers). With the introduction of
> > struct pci_host_bridge.map_irq pointer it is possible to assign IRQs
> > for all devices originating from a PCI host bridge at probe time;
> > this is implemented through pci_assign_irq() that relies on the
> > struct pci_host_bridge.map_irq pointer to map IRQ for a given device.
> >
> > The benefits this brings are twofold:
> >
> > - the IRQ for a device is assigned once at probe time
> > - the IRQ assignment works also for hotplugged devices
> >
> > Remove pci_fixup_irqs() call from all DT based PCI host controller
> > drivers. The map_irq() and swizzle_irq() struct pci_host_bridge callbacks
> > are either set-up in the respective PCI host controller driver or
> > delegated to ARM/ARM64 pcibios_root_bridge_prepare() implementations,
> > where, upon DT probe detection, the functions are set to DT defaults (ie
> > of_irq_parse_and_map_pci() and pci_common_swizzle() respectively.
> >
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>
> Nice!
>
> > +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> > +{
> > + /*
> > + * Set-up IRQ mapping/swizzingly functions.
> > + * If the either function pointer is already set,
> > + * do not override any of them since it is a host
> > + * controller specific mapping/swizzling function.
> > + */
> > + if (!bridge->map_irq && !bridge->swizzle_irq) {
> > + struct device *parent = bridge->dev.parent;
> > + /*
> > + * If we have a parent pointer with a valid
> > + * OF node this means we are probing a PCI host
> > + * controller configured through DT firmware.
> > + */
> > + if (IS_ENABLED(CONFIG_OF) && parent && parent->of_node) {
> > + bridge->map_irq = of_irq_parse_and_map_pci;
> > + bridge->swizzle_irq = pci_common_swizzle;
> > + }
> > + }
> > +
> > + return 0;
> > +}
>
> I think it would be better to reduce the number of global functions defined
> by common code to be called from PCI core code, and instead use
> additional callback pointers from the pci_host_bridge operations.
Yes but this means duplicating the whole map_irq/swizzle_irq
initialization thing in all DT PCI host controllers, it is getting
quite cumbersome to be frank, we should try to consolidate DT PCI
host controllers code, it is becoming a bit unwieldy to manage and
there is too much code duplication.
> In particular, there are only very few existing users of
> pcibios_root_bridge_prepare() at the moment, so we should
> be able to get rid of those quite easily now.
I could do but please see my comment above.
> > diff --git a/drivers/pci/host/pcie-iproc.c b/drivers/pci/host/pcie-iproc.c
> > index 0f39bd2..bc9e36a 100644
> > --- a/drivers/pci/host/pcie-iproc.c
> > +++ b/drivers/pci/host/pcie-iproc.c
> > @@ -1205,7 +1205,8 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
> > struct device *dev;
> > int ret;
> > void *sysdata;
> > - struct pci_bus *bus, *child;
> > + struct pci_bus *child;
> > + struct pci_host_bridge *host;
> >
> > dev = pcie->dev;
> >
> > @@ -1252,15 +1253,30 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
> > sysdata = pcie;
> > #endif
> >
> > - bus = pci_create_root_bus(dev, 0, &iproc_pcie_ops, sysdata, res);
> > - if (!bus) {
>
> Could this be a separate patch?
Yes, I can split it from the pci_fixup_irqs() removal.
Thanks,
Lorenzo
^ permalink raw reply
* [PATCH 31/31] KVM: arm64: vgic-v3: Log which GICv3 system registers are trapped
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
In order to facilitate debug, let's log which class of GICv3 system
registers are trapped.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
virt/kvm/arm/vgic/vgic-v3.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 717219ab58a2..9110657b502c 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -407,7 +407,10 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
#endif
if (group0_trap || group1_trap || common_trap) {
- kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
+ kvm_info("GICv3 sysreg trapping enabled ([%s%s%s], reduced performance)\n",
+ group0_trap ? "G0" : "",
+ group1_trap ? "G1" : "",
+ common_trap ? "C" : "");
static_branch_enable(&vgic_v3_cpuif_trap);
}
--
2.11.0
^ permalink raw reply related
* [PATCH 30/31] KVM: arm64: Enable GICv3 common sysreg trapping via command-line
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
Now that we're able to safely handle common sysreg access, let's
give the user the opportunity to enable it by passing a specific
command-line option (vgic_v3.common_trap).
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
include/linux/irqchip/arm-gic-v3.h | 1 +
virt/kvm/arm/vgic/vgic-v3.c | 11 ++++++++++-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 7fef09bcf7b1..2692217ac667 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -403,6 +403,7 @@
#define ICH_HCR_EN (1 << 0)
#define ICH_HCR_UIE (1 << 1)
+#define ICH_HCR_TC (1 << 10)
#define ICH_HCR_TALL0 (1 << 11)
#define ICH_HCR_TALL1 (1 << 12)
#define ICH_HCR_EOIcount_SHIFT 27
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 445e86c8b00c..717219ab58a2 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -23,6 +23,7 @@
static bool group0_trap;
static bool group1_trap;
+static bool common_trap;
void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
{
@@ -246,6 +247,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
vgic_v3->vgic_hcr |= ICH_HCR_TALL0;
if (group1_trap)
vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
+ if (common_trap)
+ vgic_v3->vgic_hcr |= ICH_HCR_TC;
}
/* check for overlapping regions and for regions crossing the end of memory */
@@ -339,6 +342,12 @@ static int __init early_group1_trap_cfg(char *buf)
}
early_param("vgic_v3.group1_trap", early_group1_trap_cfg);
+static int __init early_common_trap_cfg(char *buf)
+{
+ return strtobool(buf, &common_trap);
+}
+early_param("vgic_v3.common_trap", early_common_trap_cfg);
+
/**
* vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
* @node: pointer to the DT node
@@ -397,7 +406,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
}
#endif
- if (group0_trap || group1_trap) {
+ if (group0_trap || group1_trap || common_trap) {
kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
static_branch_enable(&vgic_v3_cpuif_trap);
}
--
2.11.0
^ permalink raw reply related
* [PATCH 29/31] KVM: arm64: vgic-v3: Add ICV_PMR_EL1 handler
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
Add a handler for reading/writing the guest's view of the ICC_PMR_EL1
register, which is located in the ICH_VMCR_EL2.VPMR field.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
virt/kvm/arm/hyp/vgic-v3-sr.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 981201bf7a5e..4fbeeb54704e 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -848,6 +848,27 @@ static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu,
vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
}
+static void __hyp_text __vgic_v3_read_pmr(struct kvm_vcpu *vcpu,
+ u32 vmcr, int rt)
+{
+ vmcr &= ICH_VMCR_PMR_MASK;
+ vmcr >>= ICH_VMCR_PMR_SHIFT;
+ vcpu_set_reg(vcpu, rt, vmcr);
+}
+
+static void __hyp_text __vgic_v3_write_pmr(struct kvm_vcpu *vcpu,
+ u32 vmcr, int rt)
+{
+ u32 val = vcpu_get_reg(vcpu, rt);
+
+ val <<= ICH_VMCR_PMR_SHIFT;
+ val &= ICH_VMCR_PMR_MASK;
+ vmcr &= ~ICH_VMCR_PMR_MASK;
+ vmcr |= val;
+
+ write_gicreg(vmcr, ICH_VMCR_EL2);
+}
+
static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu,
u32 vmcr, int rt)
{
@@ -991,6 +1012,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
else
fn = __vgic_v3_write_ctlr;
break;
+ case SYS_ICC_PMR_EL1:
+ if (is_read)
+ fn = __vgic_v3_read_pmr;
+ else
+ fn = __vgic_v3_write_pmr;
+ break;
default:
return 0;
}
--
2.11.0
^ permalink raw reply related
* [PATCH 28/31] KVM: arm64: vgic-v3: Add ICV_CTLR_EL1 handler
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
Add a handler for reading/writing the guest's view of the ICV_CTLR_EL1
register. only EOIMode and CBPR are of interest here, as all the other
bits directly come from ICH_VTR_EL2 and are Read-Only.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
virt/kvm/arm/hyp/vgic-v3-sr.c | 46 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 3a5f54f445b9..981201bf7a5e 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -855,6 +855,46 @@ static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu,
vcpu_set_reg(vcpu, rt, val);
}
+static void __hyp_text __vgic_v3_read_ctlr(struct kvm_vcpu *vcpu,
+ u32 vmcr, int rt)
+{
+ u32 vtr, val;
+
+ vtr = read_gicreg(ICH_VTR_EL2);
+ /* PRIbits */
+ val = ((vtr >> 29) & 7) << ICC_CTLR_EL1_PRI_BITS_SHIFT;
+ /* IDbits */
+ val |= ((vtr >> 23) & 7) << ICC_CTLR_EL1_ID_BITS_SHIFT;
+ /* SEIS */
+ val |= ((vtr >> 22) & 1) << ICC_CTLR_EL1_SEIS_SHIFT;
+ /* A3V */
+ val |= ((vtr >> 21) & 1) << ICC_CTLR_EL1_A3V_SHIFT;
+ /* EOImode */
+ val |= ((vmcr & ICH_VMCR_EOIM_MASK) >> ICH_VMCR_EOIM_SHIFT) << ICC_CTLR_EL1_EOImode_SHIFT;
+ /* CBPR */
+ val |= (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT;
+
+ vcpu_set_reg(vcpu, rt, val);
+}
+
+static void __hyp_text __vgic_v3_write_ctlr(struct kvm_vcpu *vcpu,
+ u32 vmcr, int rt)
+{
+ u32 val = vcpu_get_reg(vcpu, rt);
+
+ if (val & ICC_CTLR_EL1_CBPR_MASK)
+ vmcr |= ICH_VMCR_CBPR_MASK;
+ else
+ vmcr &= ~ICH_VMCR_CBPR_MASK;
+
+ if (val & ICC_CTLR_EL1_EOImode_MASK)
+ vmcr |= ICH_VMCR_EOIM_MASK;
+ else
+ vmcr &= ~ICH_VMCR_EOIM_MASK;
+
+ write_gicreg(vmcr, ICH_VMCR_EL2);
+}
+
int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
{
int rt = kvm_vcpu_sys_get_rt(vcpu);
@@ -945,6 +985,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
case SYS_ICC_RPR_EL1:
fn = __vgic_v3_read_rpr;
break;
+ case SYS_ICC_CTLR_EL1:
+ if (is_read)
+ fn = __vgic_v3_read_ctlr;
+ else
+ fn = __vgic_v3_write_ctlr;
+ break;
default:
return 0;
}
--
2.11.0
^ permalink raw reply related
* [PATCH 27/31] KVM: arm64: vgic-v3: Add ICV_RPR_EL1 handler
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
Add a handler for reading the guest's view of the ICV_RPR_EL1
register, returning the highest active priority.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/sysreg.h | 1 +
virt/kvm/arm/hyp/vgic-v3-sr.c | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 9971c5c435a7..c4d48e403629 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -187,6 +187,7 @@
#define SYS_ICC_AP0Rn_EL1(n) sys_reg(3, 0, 12, 8, 4 | n)
#define SYS_ICC_AP1Rn_EL1(n) sys_reg(3, 0, 12, 9, n)
#define SYS_ICC_DIR_EL1 sys_reg(3, 0, 12, 11, 1)
+#define SYS_ICC_RPR_EL1 sys_reg(3, 0, 12, 11, 3)
#define SYS_ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
#define SYS_ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
#define SYS_ICC_EOIR1_EL1 sys_reg(3, 0, 12, 12, 1)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 563dd2d16c59..3a5f54f445b9 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -848,6 +848,13 @@ static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu,
vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
}
+static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu,
+ u32 vmcr, int rt)
+{
+ u32 val = __vgic_v3_get_highest_active_priority();
+ vcpu_set_reg(vcpu, rt, val);
+}
+
int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
{
int rt = kvm_vcpu_sys_get_rt(vcpu);
@@ -935,6 +942,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
case SYS_ICC_DIR_EL1:
fn = __vgic_v3_write_dir;
break;
+ case SYS_ICC_RPR_EL1:
+ fn = __vgic_v3_read_rpr;
+ break;
default:
return 0;
}
--
2.11.0
^ permalink raw reply related
* [PATCH 26/31] KVM: arm64: vgic-v3: Add ICV_DIR_EL1 handler
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
Add a handler for writing the guest's view of the ICC_DIR_EL1
register, performing the deactivation of an interrupt if EOImode
is set ot 1.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
virt/kvm/arm/hyp/vgic-v3-sr.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 9c639f57268b..563dd2d16c59 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -612,6 +612,26 @@ static void __hyp_text __vgic_v3_bump_eoicount(void)
write_gicreg(hcr, ICH_HCR_EL2);
}
+static void __hyp_text __vgic_v3_write_dir(struct kvm_vcpu *vcpu,
+ u32 vmcr, int rt)
+{
+ u32 vid = vcpu_get_reg(vcpu, rt);
+ u64 lr_val;
+ int lr;
+
+ /* No deactivate to be performed on an LPI */
+ if (vid >= VGIC_MIN_LPI)
+ return;
+
+ lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val);
+ if (lr == -1) {
+ __vgic_v3_bump_eoicount();
+ return;
+ }
+
+ __vgic_v3_clear_active_lr(lr, lr_val);
+}
+
static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
{
u32 vid = vcpu_get_reg(vcpu, rt);
@@ -912,6 +932,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
else
fn = __vgic_v3_write_bpr0;
break;
+ case SYS_ICC_DIR_EL1:
+ fn = __vgic_v3_write_dir;
+ break;
default:
return 0;
}
--
2.11.0
^ permalink raw reply related
* [PATCH 25/31] arm64: Add workaround for Cavium Thunder erratum 30115
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
From: David Daney <david.daney@cavium.com>
Some Cavium Thunder CPUs suffer a problem where a KVM guest may
inadvertently cause the host kernel to quit receiving interrupts.
Use the Group-0/1 trapping in order to deal with it.
[maz]: Adapted patch to the Group-0/1 trapping, reworked commit log
Signed-off-by: David Daney <david.daney@cavium.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
Documentation/arm64/silicon-errata.txt | 1 +
arch/arm64/Kconfig | 11 +++++++++++
arch/arm64/include/asm/cpucaps.h | 3 ++-
arch/arm64/kernel/cpu_errata.c | 21 +++++++++++++++++++++
virt/kvm/arm/vgic/vgic-v3.c | 7 +++++++
5 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
index 10f2dddbf449..f5f93dca54b7 100644
--- a/Documentation/arm64/silicon-errata.txt
+++ b/Documentation/arm64/silicon-errata.txt
@@ -62,6 +62,7 @@ stable kernels.
| Cavium | ThunderX GICv3 | #23154 | CAVIUM_ERRATUM_23154 |
| Cavium | ThunderX Core | #27456 | CAVIUM_ERRATUM_27456 |
| Cavium | ThunderX SMMUv2 | #27704 | N/A |
+| Cavium | ThunderX Core | #30115 | CAVIUM_ERRATUM_30115 |
| | | | |
| Freescale/NXP | LS2080A/LS1043A | A-008585 | FSL_ERRATUM_A008585 |
| | | | |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3dcd7ec69bca..0950b21e4d17 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -480,6 +480,17 @@ config CAVIUM_ERRATUM_27456
If unsure, say Y.
+config CAVIUM_ERRATUM_30115
+ bool "Cavium erratum 30115: Guest may disable interrupts in host"
+ default y
+ help
+ On ThunderX T88 pass 1.x through 2.2, T81 pass 1.0 through
+ 1.2, and T83 Pass 1.0, KVM guest execution may disable
+ interrupts in host. Trapping GICv3 group-1 accesses sidesteps
+ the issue.
+
+ If unsure, say Y.
+
config QCOM_FALKOR_ERRATUM_1003
bool "Falkor E1003: Incorrect translation due to ASID change"
default y
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index b3aab8a17868..8d2272c6822c 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -38,7 +38,8 @@
#define ARM64_WORKAROUND_REPEAT_TLBI 17
#define ARM64_WORKAROUND_QCOM_FALKOR_E1003 18
#define ARM64_WORKAROUND_858921 19
+#define ARM64_WORKAROUND_CAVIUM_30115 20
-#define ARM64_NCAPS 20
+#define ARM64_NCAPS 21
#endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 2ed2a7657711..0e27f86ee709 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -133,6 +133,27 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x00),
},
#endif
+#ifdef CONFIG_CAVIUM_ERRATUM_30115
+ {
+ /* Cavium ThunderX, T88 pass 1.x - 2.2 */
+ .desc = "Cavium erratum 30115",
+ .capability = ARM64_WORKAROUND_CAVIUM_30115,
+ MIDR_RANGE(MIDR_THUNDERX, 0x00,
+ (1 << MIDR_VARIANT_SHIFT) | 2),
+ },
+ {
+ /* Cavium ThunderX, T81 pass 1.0 - 1.2 */
+ .desc = "Cavium erratum 30115",
+ .capability = ARM64_WORKAROUND_CAVIUM_30115,
+ MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x02),
+ },
+ {
+ /* Cavium ThunderX, T83 pass 1.0 */
+ .desc = "Cavium erratum 30115",
+ .capability = ARM64_WORKAROUND_CAVIUM_30115,
+ MIDR_RANGE(MIDR_THUNDERX_83XX, 0x00, 0x00),
+ },
+#endif
{
.desc = "Mismatched cache line size",
.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 7c82c586d44a..445e86c8b00c 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -390,6 +390,13 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
if (kvm_vgic_global_state.vcpu_base == 0)
kvm_info("disabling GICv2 emulation\n");
+#ifdef CONFIG_ARM64
+ if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_30115)) {
+ group0_trap = true;
+ group1_trap = true;
+ }
+#endif
+
if (group0_trap || group1_trap) {
kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
static_branch_enable(&vgic_v3_cpuif_trap);
--
2.11.0
^ permalink raw reply related
* [PATCH 24/31] arm64: Add MIDR values for Cavium cn83XX SoCs
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
From: David Daney <david.daney@cavium.com>
Signed-off-by: David Daney <david.daney@cavium.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/cputype.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 0984d1b3a8f2..235e77d98261 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -86,6 +86,7 @@
#define CAVIUM_CPU_PART_THUNDERX 0x0A1
#define CAVIUM_CPU_PART_THUNDERX_81XX 0x0A2
+#define CAVIUM_CPU_PART_THUNDERX_83XX 0x0A3
#define BRCM_CPU_PART_VULCAN 0x516
@@ -96,6 +97,7 @@
#define MIDR_CORTEX_A73 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A73)
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
+#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
#define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1)
#ifndef __ASSEMBLY__
--
2.11.0
^ permalink raw reply related
* [PATCH 23/31] KVM: arm64: Enable GICv3 Group-0 sysreg trapping via command-line
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
Now that we're able to safely handle Group-0 sysreg access, let's
give the user the opportunity to enable it by passing a specific
command-line option (vgic_v3.group0_trap).
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
virt/kvm/arm/vgic/vgic-v3.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 812f179a6931..7c82c586d44a 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -327,6 +327,12 @@ int vgic_v3_map_resources(struct kvm *kvm)
DEFINE_STATIC_KEY_FALSE(vgic_v3_cpuif_trap);
+static int __init early_group0_trap_cfg(char *buf)
+{
+ return strtobool(buf, &group0_trap);
+}
+early_param("vgic_v3.group0_trap", early_group0_trap_cfg);
+
static int __init early_group1_trap_cfg(char *buf)
{
return strtobool(buf, &group1_trap);
--
2.11.0
^ permalink raw reply related
* [PATCH 22/31] KVM: arm64: vgic-v3: Enable trapping of Group-0 system registers
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
In order to be able to trap Group-0 GICv3 system registers, we need to
set ICH_HCR_EL2.TALL0 begore entering the guest. This is conditionnaly
done after having restored the guest's state, and cleared on exit.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
include/linux/irqchip/arm-gic-v3.h | 1 +
virt/kvm/arm/vgic/vgic-v3.c | 5 ++++-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index a1739843343e..7fef09bcf7b1 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -403,6 +403,7 @@
#define ICH_HCR_EN (1 << 0)
#define ICH_HCR_UIE (1 << 1)
+#define ICH_HCR_TALL0 (1 << 11)
#define ICH_HCR_TALL1 (1 << 12)
#define ICH_HCR_EOIcount_SHIFT 27
#define ICH_HCR_EOIcount_MASK (0x1f << ICH_HCR_EOIcount_SHIFT)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 71ecf448ca49..812f179a6931 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -21,6 +21,7 @@
#include "vgic.h"
+static bool group0_trap;
static bool group1_trap;
void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
@@ -241,6 +242,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
/* Get the show on the road... */
vgic_v3->vgic_hcr = ICH_HCR_EN;
+ if (group0_trap)
+ vgic_v3->vgic_hcr |= ICH_HCR_TALL0;
if (group1_trap)
vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
}
@@ -381,7 +384,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
if (kvm_vgic_global_state.vcpu_base == 0)
kvm_info("disabling GICv2 emulation\n");
- if (group1_trap) {
+ if (group0_trap || group1_trap) {
kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
static_branch_enable(&vgic_v3_cpuif_trap);
}
--
2.11.0
^ permalink raw reply related
* [PATCH 21/31] KVM: arm64: vgic-v3: Add misc Group-0 handlers
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
A number of Group-0 registers can be handled by the same accessors
as that of Group-1, so let's add the required system register encodings
and catch them in the dispatching function.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/sysreg.h | 4 ++++
virt/kvm/arm/hyp/vgic-v3-sr.c | 7 +++++++
2 files changed, 11 insertions(+)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index ba93bc7ac8e4..9971c5c435a7 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -180,7 +180,11 @@
#define SYS_VBAR_EL1 sys_reg(3, 0, 12, 0, 0)
+#define SYS_ICC_IAR0_EL1 sys_reg(3, 0, 12, 8, 0)
+#define SYS_ICC_EOIR0_EL1 sys_reg(3, 0, 12, 8, 1)
+#define SYS_ICC_HPPIR0_EL1 sys_reg(3, 0, 12, 8, 2)
#define SYS_ICC_BPR0_EL1 sys_reg(3, 0, 12, 8, 3)
+#define SYS_ICC_AP0Rn_EL1(n) sys_reg(3, 0, 12, 8, 4 | n)
#define SYS_ICC_AP1Rn_EL1(n) sys_reg(3, 0, 12, 9, n)
#define SYS_ICC_DIR_EL1 sys_reg(3, 0, 12, 11, 1)
#define SYS_ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 77d5d12389ec..9c639f57268b 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -848,9 +848,11 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
switch (sysreg) {
+ case SYS_ICC_IAR0_EL1:
case SYS_ICC_IAR1_EL1:
fn = __vgic_v3_read_iar;
break;
+ case SYS_ICC_EOIR0_EL1:
case SYS_ICC_EOIR1_EL1:
fn = __vgic_v3_write_eoir;
break;
@@ -866,30 +868,35 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
else
fn = __vgic_v3_write_bpr1;
break;
+ case SYS_ICC_AP0Rn_EL1(0):
case SYS_ICC_AP1Rn_EL1(0):
if (is_read)
fn = __vgic_v3_read_apxr0;
else
fn = __vgic_v3_write_apxr0;
break;
+ case SYS_ICC_AP0Rn_EL1(1):
case SYS_ICC_AP1Rn_EL1(1):
if (is_read)
fn = __vgic_v3_read_apxr1;
else
fn = __vgic_v3_write_apxr1;
break;
+ case SYS_ICC_AP0Rn_EL1(2):
case SYS_ICC_AP1Rn_EL1(2):
if (is_read)
fn = __vgic_v3_read_apxr2;
else
fn = __vgic_v3_write_apxr2;
break;
+ case SYS_ICC_AP0Rn_EL1(3):
case SYS_ICC_AP1Rn_EL1(3):
if (is_read)
fn = __vgic_v3_read_apxr3;
else
fn = __vgic_v3_write_apxr3;
break;
+ case SYS_ICC_HPPIR0_EL1:
case SYS_ICC_HPPIR1_EL1:
fn = __vgic_v3_read_hppir;
break;
--
2.11.0
^ permalink raw reply related
* [PATCH 20/31] KVM: arm64: vgic-v3: Add ICV_IGNREN0_EL1 handler
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
Add a handler for reading/writing the guest's view of the ICC_IGRPEN0_EL1
register, which is located in the ICH_VMCR_EL2.VENG0 field.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/sysreg.h | 1 +
virt/kvm/arm/hyp/vgic-v3-sr.c | 23 +++++++++++++++++++++++
2 files changed, 24 insertions(+)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index d20be0b28ca4..ba93bc7ac8e4 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -190,6 +190,7 @@
#define SYS_ICC_BPR1_EL1 sys_reg(3, 0, 12, 12, 3)
#define SYS_ICC_CTLR_EL1 sys_reg(3, 0, 12, 12, 4)
#define SYS_ICC_SRE_EL1 sys_reg(3, 0, 12, 12, 5)
+#define SYS_ICC_GRPEN0_EL1 sys_reg(3, 0, 12, 12, 6)
#define SYS_ICC_GRPEN1_EL1 sys_reg(3, 0, 12, 12, 7)
#define SYS_CONTEXTIDR_EL1 sys_reg(3, 0, 13, 0, 1)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index b21bb0c77ec2..77d5d12389ec 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -649,11 +649,28 @@ static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int
__vgic_v3_clear_active_lr(lr, lr_val);
}
+static void __hyp_text __vgic_v3_read_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+ vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG0_MASK));
+}
+
static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
{
vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
}
+static void __hyp_text __vgic_v3_write_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+ u64 val = vcpu_get_reg(vcpu, rt);
+
+ if (val & 1)
+ vmcr |= ICH_VMCR_ENG0_MASK;
+ else
+ vmcr &= ~ICH_VMCR_ENG0_MASK;
+
+ __vgic_v3_write_vmcr(vmcr);
+}
+
static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
{
u64 val = vcpu_get_reg(vcpu, rt);
@@ -876,6 +893,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
case SYS_ICC_HPPIR1_EL1:
fn = __vgic_v3_read_hppir;
break;
+ case SYS_ICC_GRPEN0_EL1:
+ if (is_read)
+ fn = __vgic_v3_read_igrpen0;
+ else
+ fn = __vgic_v3_write_igrpen0;
+ break;
case SYS_ICC_BPR0_EL1:
if (is_read)
fn = __vgic_v3_read_bpr0;
--
2.11.0
^ permalink raw reply related
* [PATCH 19/31] KVM: arm64: vgic-v3: Add ICV_BPR0_EL1 handler
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
Add a handler for reading/writing the guest's view of the ICC_BPR0_EL1
register, which is located in the ICH_VMCR_EL2.BPR0 field.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/sysreg.h | 1 +
virt/kvm/arm/hyp/vgic-v3-sr.c | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 37 insertions(+)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index bd000686194a..d20be0b28ca4 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -180,6 +180,7 @@
#define SYS_VBAR_EL1 sys_reg(3, 0, 12, 0, 0)
+#define SYS_ICC_BPR0_EL1 sys_reg(3, 0, 12, 8, 3)
#define SYS_ICC_AP1Rn_EL1(n) sys_reg(3, 0, 12, 9, n)
#define SYS_ICC_DIR_EL1 sys_reg(3, 0, 12, 11, 1)
#define SYS_ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index a27671b1e9af..b21bb0c77ec2 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -666,11 +666,41 @@ static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr,
__vgic_v3_write_vmcr(vmcr);
}
+static void __hyp_text __vgic_v3_read_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+ vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr0(vmcr));
+}
+
static void __hyp_text __vgic_v3_read_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
{
vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr1(vmcr));
}
+static void __hyp_text __vgic_v3_write_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+ u64 val = vcpu_get_reg(vcpu, rt);
+ u8 bpr_min = 7 - vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
+
+ /* Enforce BPR limiting */
+ if (val < bpr_min)
+ val = bpr_min;
+
+ val <<= ICH_VMCR_BPR0_SHIFT;
+ val &= ICH_VMCR_BPR0_MASK;
+ vmcr &= ~ICH_VMCR_BPR0_MASK;
+ vmcr |= val;
+
+ if (vmcr & ICH_VMCR_CBPR_MASK) {
+ val = __vgic_v3_get_bpr1(vmcr);
+ val <<= ICH_VMCR_BPR1_SHIFT;
+ val &= ICH_VMCR_BPR1_MASK;
+ vmcr &= ~ICH_VMCR_BPR1_MASK;
+ vmcr |= val;
+ }
+
+ __vgic_v3_write_vmcr(vmcr);
+}
+
static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
{
u64 val = vcpu_get_reg(vcpu, rt);
@@ -846,6 +876,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
case SYS_ICC_HPPIR1_EL1:
fn = __vgic_v3_read_hppir;
break;
+ case SYS_ICC_BPR0_EL1:
+ if (is_read)
+ fn = __vgic_v3_read_bpr0;
+ else
+ fn = __vgic_v3_write_bpr0;
+ break;
default:
return 0;
}
--
2.11.0
^ permalink raw reply related
* [PATCH 18/31] KVM: arm64: Enable GICv3 Group-1 sysreg trapping via command-line
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
Now that we're able to safely handle Group-1 sysreg access, let's
give the user the opportunity to enable it by passing a specific
command-line option (vgic_v3.group1_trap).
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
virt/kvm/arm/vgic/vgic-v3.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 547b8374fb64..71ecf448ca49 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -324,6 +324,12 @@ int vgic_v3_map_resources(struct kvm *kvm)
DEFINE_STATIC_KEY_FALSE(vgic_v3_cpuif_trap);
+static int __init early_group1_trap_cfg(char *buf)
+{
+ return strtobool(buf, &group1_trap);
+}
+early_param("vgic_v3.group1_trap", early_group1_trap_cfg);
+
/**
* vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
* @node: pointer to the DT node
@@ -375,6 +381,11 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
if (kvm_vgic_global_state.vcpu_base == 0)
kvm_info("disabling GICv2 emulation\n");
+ if (group1_trap) {
+ kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
+ static_branch_enable(&vgic_v3_cpuif_trap);
+ }
+
kvm_vgic_global_state.vctrl_base = NULL;
kvm_vgic_global_state.type = VGIC_V3;
kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS;
--
2.11.0
^ permalink raw reply related
* [PATCH 17/31] KVM: arm64: vgic-v3: Enable trapping of Group-1 system registers
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
In order to be able to trap Group-1 GICv3 system registers, we need to
set ICH_HCR_EL2.TALL1 begore entering the guest. This is conditionnaly
done after having restored the guest's state, and cleared on exit.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
include/linux/irqchip/arm-gic-v3.h | 1 +
virt/kvm/arm/hyp/vgic-v3-sr.c | 7 +++++++
virt/kvm/arm/vgic/vgic-v3.c | 4 ++++
3 files changed, 12 insertions(+)
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index c56d9bc2c904..a1739843343e 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -403,6 +403,7 @@
#define ICH_HCR_EN (1 << 0)
#define ICH_HCR_UIE (1 << 1)
+#define ICH_HCR_TALL1 (1 << 12)
#define ICH_HCR_EOIcount_SHIFT 27
#define ICH_HCR_EOIcount_MASK (0x1f << ICH_HCR_EOIcount_SHIFT)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index a521e105ade1..a27671b1e9af 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -257,6 +257,9 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
cpu_if->vgic_ap1r[0] = __vgic_v3_read_ap1rn(0);
}
} else {
+ if (static_branch_unlikely(&vgic_v3_cpuif_trap))
+ write_gicreg(0, ICH_HCR_EL2);
+
cpu_if->vgic_elrsr = 0xffff;
cpu_if->vgic_ap0r[0] = 0;
cpu_if->vgic_ap0r[1] = 0;
@@ -329,6 +332,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
for (i = 0; i < used_lrs; i++)
__gic_v3_set_lr(cpu_if->vgic_lr[i], i);
+ } else {
+ /* Always write ICH_HCR_EL2 to enable trapping */
+ if (static_branch_unlikely(&vgic_v3_cpuif_trap))
+ write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
}
/*
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 063526443781..547b8374fb64 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -21,6 +21,8 @@
#include "vgic.h"
+static bool group1_trap;
+
void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
{
struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
@@ -239,6 +241,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
/* Get the show on the road... */
vgic_v3->vgic_hcr = ICH_HCR_EN;
+ if (group1_trap)
+ vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
}
/* check for overlapping regions and for regions crossing the end of memory */
--
2.11.0
^ permalink raw reply related
* [PATCH 16/31] KVM: arm64: vgic-v3: Add ICV_HPPIR1_EL1 handler
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
Add a handler for reading the guest's view of the ICV_HPPIR1_EL1
register. This is a simple parsing of the available LRs, extracting the
highest available interrupt.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/sysreg.h | 1 +
virt/kvm/arm/hyp/vgic-v3-sr.c | 23 +++++++++++++++++++++++
2 files changed, 24 insertions(+)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index aad46b8eea5e..bd000686194a 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -185,6 +185,7 @@
#define SYS_ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
#define SYS_ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
#define SYS_ICC_EOIR1_EL1 sys_reg(3, 0, 12, 12, 1)
+#define SYS_ICC_HPPIR1_EL1 sys_reg(3, 0, 12, 12, 2)
#define SYS_ICC_BPR1_EL1 sys_reg(3, 0, 12, 12, 3)
#define SYS_ICC_CTLR_EL1 sys_reg(3, 0, 12, 12, 4)
#define SYS_ICC_SRE_EL1 sys_reg(3, 0, 12, 12, 5)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index b6803989da1f..a521e105ade1 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -754,6 +754,26 @@ static void __hyp_text __vgic_v3_write_apxr3(struct kvm_vcpu *vcpu,
__vgic_v3_write_apxrn(vcpu, rt, 3);
}
+static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu,
+ u32 vmcr, int rt)
+{
+ u64 lr_val;
+ int lr, lr_grp, grp;
+
+ grp = __vgic_v3_get_group(vcpu);
+
+ lr = __vgic_v3_highest_priority_lr(vcpu, vmcr, &lr_val);
+ if (lr == -1)
+ goto spurious;
+
+ lr_grp = !!(lr_val & ICH_LR_GROUP);
+ if (lr_grp != grp)
+ lr_val = ICC_IAR1_EL1_SPURIOUS;
+
+spurious:
+ vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
+}
+
int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
{
int rt = kvm_vcpu_sys_get_rt(vcpu);
@@ -816,6 +836,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
else
fn = __vgic_v3_write_apxr3;
break;
+ case SYS_ICC_HPPIR1_EL1:
+ fn = __vgic_v3_read_hppir;
+ break;
default:
return 0;
}
--
2.11.0
^ permalink raw reply related
* [PATCH 15/31] KVM: arm64: vgic-v3: Add ICV_AP1Rn_EL1 handler
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
Add a handler for reading/writing the guest's view of the ICV_AP1Rn_EL1
registers. We just map them to the corresponding ICH_AP1Rn_EL2 registers.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/sysreg.h | 1 +
virt/kvm/arm/hyp/vgic-v3-sr.c | 94 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 95 insertions(+)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 15c142ce991c..aad46b8eea5e 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -180,6 +180,7 @@
#define SYS_VBAR_EL1 sys_reg(3, 0, 12, 0, 0)
+#define SYS_ICC_AP1Rn_EL1(n) sys_reg(3, 0, 12, 9, n)
#define SYS_ICC_DIR_EL1 sys_reg(3, 0, 12, 11, 1)
#define SYS_ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
#define SYS_ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index a76351b3ad66..b6803989da1f 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -684,6 +684,76 @@ static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int
__vgic_v3_write_vmcr(vmcr);
}
+static void __hyp_text __vgic_v3_read_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
+{
+ u32 val;
+
+ if (!__vgic_v3_get_group(vcpu))
+ val = __vgic_v3_read_ap0rn(n);
+ else
+ val = __vgic_v3_read_ap1rn(n);
+
+ vcpu_set_reg(vcpu, rt, val);
+}
+
+static void __hyp_text __vgic_v3_write_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
+{
+ u32 val = vcpu_get_reg(vcpu, rt);
+
+ if (!__vgic_v3_get_group(vcpu))
+ __vgic_v3_write_ap0rn(val, n);
+ else
+ __vgic_v3_write_ap1rn(val, n);
+}
+
+static void __hyp_text __vgic_v3_read_apxr0(struct kvm_vcpu *vcpu,
+ u32 vmcr, int rt)
+{
+ __vgic_v3_read_apxrn(vcpu, rt, 0);
+}
+
+static void __hyp_text __vgic_v3_read_apxr1(struct kvm_vcpu *vcpu,
+ u32 vmcr, int rt)
+{
+ __vgic_v3_read_apxrn(vcpu, rt, 1);
+}
+
+static void __hyp_text __vgic_v3_read_apxr2(struct kvm_vcpu *vcpu,
+ u32 vmcr, int rt)
+{
+ __vgic_v3_read_apxrn(vcpu, rt, 2);
+}
+
+static void __hyp_text __vgic_v3_read_apxr3(struct kvm_vcpu *vcpu,
+ u32 vmcr, int rt)
+{
+ __vgic_v3_read_apxrn(vcpu, rt, 3);
+}
+
+static void __hyp_text __vgic_v3_write_apxr0(struct kvm_vcpu *vcpu,
+ u32 vmcr, int rt)
+{
+ __vgic_v3_write_apxrn(vcpu, rt, 0);
+}
+
+static void __hyp_text __vgic_v3_write_apxr1(struct kvm_vcpu *vcpu,
+ u32 vmcr, int rt)
+{
+ __vgic_v3_write_apxrn(vcpu, rt, 1);
+}
+
+static void __hyp_text __vgic_v3_write_apxr2(struct kvm_vcpu *vcpu,
+ u32 vmcr, int rt)
+{
+ __vgic_v3_write_apxrn(vcpu, rt, 2);
+}
+
+static void __hyp_text __vgic_v3_write_apxr3(struct kvm_vcpu *vcpu,
+ u32 vmcr, int rt)
+{
+ __vgic_v3_write_apxrn(vcpu, rt, 3);
+}
+
int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
{
int rt = kvm_vcpu_sys_get_rt(vcpu);
@@ -722,6 +792,30 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
else
fn = __vgic_v3_write_bpr1;
break;
+ case SYS_ICC_AP1Rn_EL1(0):
+ if (is_read)
+ fn = __vgic_v3_read_apxr0;
+ else
+ fn = __vgic_v3_write_apxr0;
+ break;
+ case SYS_ICC_AP1Rn_EL1(1):
+ if (is_read)
+ fn = __vgic_v3_read_apxr1;
+ else
+ fn = __vgic_v3_write_apxr1;
+ break;
+ case SYS_ICC_AP1Rn_EL1(2):
+ if (is_read)
+ fn = __vgic_v3_read_apxr2;
+ else
+ fn = __vgic_v3_write_apxr2;
+ break;
+ case SYS_ICC_AP1Rn_EL1(3):
+ if (is_read)
+ fn = __vgic_v3_read_apxr3;
+ else
+ fn = __vgic_v3_write_apxr3;
+ break;
default:
return 0;
}
--
2.11.0
^ permalink raw reply related
* [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170503104606.19342-1-marc.zyngier@arm.com>
Add a handler for writing the guest's view of the ICC_EOIR1_EL1
register. This involves dropping the priority of the interrupt,
and deactivating it if required (EOImode == 0).
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
include/linux/irqchip/arm-gic-v3.h | 2 +
virt/kvm/arm/hyp/vgic-v3-sr.c | 119 +++++++++++++++++++++++++++++++++++++
2 files changed, 121 insertions(+)
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 7610ea4e8337..c56d9bc2c904 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -403,6 +403,8 @@
#define ICH_HCR_EN (1 << 0)
#define ICH_HCR_UIE (1 << 1)
+#define ICH_HCR_EOIcount_SHIFT 27
+#define ICH_HCR_EOIcount_MASK (0x1f << ICH_HCR_EOIcount_SHIFT)
#define ICH_VMCR_CBPR_SHIFT 4
#define ICH_VMCR_CBPR_MASK (1 << ICH_VMCR_CBPR_SHIFT)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 49aad1de3ac8..a76351b3ad66 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
return lr;
}
+static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
+ int intid, u64 *lr_val)
+{
+ unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
+ int i;
+
+ for (i = 0; i < used_lrs; i++) {
+ u64 val = __gic_v3_get_lr(i);
+
+ if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
+ (val & ICH_LR_ACTIVE_BIT)) {
+ *lr_val = val;
+ return i;
+ }
+ }
+
+ *lr_val = ICC_IAR1_EL1_SPURIOUS;
+ return -1;
+}
+
static int __hyp_text __vgic_v3_get_highest_active_priority(void)
{
u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
@@ -490,6 +510,44 @@ static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
__vgic_v3_write_ap1rn(val | bit, apr);
}
+static int __hyp_text __vgic_v3_clear_highest_active_priority(void)
+{
+ u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
+ u8 nr_aprs = 1 << (nr_pre_bits - 5);
+ u32 hap = 0;
+ int i;
+
+ for (i = 0; i < nr_aprs; i++) {
+ u32 ap0, ap1;
+ int c0, c1;
+
+ ap0 = __vgic_v3_read_ap0rn(i);
+ ap1 = __vgic_v3_read_ap1rn(i);
+ if (!ap0 && !ap1) {
+ hap += 32;
+ continue;
+ }
+
+ c0 = ap0 ? __ffs(ap0) : 32;
+ c1 = ap1 ? __ffs(ap1) : 32;
+
+ /* Always clear the LSB, which is the highest priority */
+ if (c0 < c1) {
+ ap0 &= ap0 - 1;
+ __vgic_v3_write_ap0rn(ap0, i);
+ hap += c0;
+ } else {
+ ap1 &= ap1 - 1;
+ __vgic_v3_write_ap1rn(ap1, i);
+ hap += c1;
+ }
+
+ return hap << (8 - nr_pre_bits);
+ }
+
+ return GICv3_IDLE_PRIORITY;
+}
+
static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
{
u64 lr_val;
@@ -526,6 +584,64 @@ static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int r
vcpu_set_reg(vcpu, rt, ICC_IAR1_EL1_SPURIOUS);
}
+static void __hyp_text __vgic_v3_clear_active_lr(int lr, u64 lr_val)
+{
+ lr_val &= ~ICH_LR_ACTIVE_BIT;
+ if (lr_val & ICH_LR_HW) {
+ u32 pid;
+ pid = (lr_val & ICH_LR_PHYS_ID_MASK) >> ICH_LR_PHYS_ID_SHIFT;
+ gic_write_dir(pid);
+ }
+
+ __gic_v3_set_lr(lr_val, lr);
+}
+
+static void __hyp_text __vgic_v3_bump_eoicount(void)
+{
+ u32 hcr;
+
+ hcr = read_gicreg(ICH_HCR_EL2);
+ hcr += 1 << ICH_HCR_EOIcount_SHIFT;
+ write_gicreg(hcr, ICH_HCR_EL2);
+}
+
+static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+ u32 vid = vcpu_get_reg(vcpu, rt);
+ u64 lr_val;
+ u8 lr_prio, act_prio;
+ int lr, grp;
+
+ grp = __vgic_v3_get_group(vcpu);
+
+ /* Drop priority in any case */
+ act_prio = __vgic_v3_clear_highest_active_priority();
+
+ /* If EOIing an LPI, no deactivate to be performed */
+ if (vid >= VGIC_MIN_LPI)
+ return;
+
+ /* EOImode == 1, nothing to be done here */
+ if (vmcr & ICH_VMCR_EOIM_MASK)
+ return;
+
+ lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val);
+ if (lr == -1) {
+ __vgic_v3_bump_eoicount();
+ return;
+ }
+
+ lr_prio = (lr_val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
+
+ /* If priorities or group do not match, the guest has fscked-up. */
+ if (grp != !!(lr_val & ICH_LR_GROUP) ||
+ __vgic_v3_pri_to_pre(lr_prio, vmcr, grp) != act_prio)
+ return;
+
+ /* Let's now perform the deactivation */
+ __vgic_v3_clear_active_lr(lr, lr_val);
+}
+
static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
{
vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
@@ -591,6 +707,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
case SYS_ICC_IAR1_EL1:
fn = __vgic_v3_read_iar;
break;
+ case SYS_ICC_EOIR1_EL1:
+ fn = __vgic_v3_write_eoir;
+ break;
case SYS_ICC_GRPEN1_EL1:
if (is_read)
fn = __vgic_v3_read_igrpen1;
--
2.11.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