* RE: chapoly acceleration hardware [Was: Re: [RFC PATCH 00/18] crypto: wireguard using the existing crypto API]
From: Pascal Van Leeuwen @ 2019-09-26 13:52 UTC (permalink / raw)
To: Jason A. Donenfeld
Cc: Toke Høiland-Jørgensen, Catalin Marinas, Herbert Xu,
Arnd Bergmann, Ard Biesheuvel, Greg KH, Eric Biggers, Dave Taht,
Willy Tarreau, Samuel Neves, Will Deacon, Netdev,
Linux Crypto Mailing List, Andy Lutomirski, Marc Zyngier,
Dan Carpenter, Linus Torvalds, David Miller, linux-arm-kernel
In-Reply-To: <CAHmME9r5m7D-oMU6Lv_ZhEyWmrNscMr5HokzdK0wg2Ayzzbeow@mail.gmail.com>
> -----Original Message-----
> From: Jason A. Donenfeld <Jason@zx2c4.com>
> Sent: Thursday, September 26, 2019 1:07 PM
> To: Pascal Van Leeuwen <pvanleeuwen@verimatrix.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>; Linux Crypto Mailing List <linux-
> crypto@vger.kernel.org>; linux-arm-kernel <linux-arm-kernel@lists.infradead.org>;
> Herbert Xu <herbert@gondor.apana.org.au>; David Miller <davem@davemloft.net>; Greg KH
> <gregkh@linuxfoundation.org>; Linus Torvalds <torvalds@linux-foundation.org>; Samuel
> Neves <sneves@dei.uc.pt>; Dan Carpenter <dan.carpenter@oracle.com>; Arnd Bergmann
> <arnd@arndb.de>; Eric Biggers <ebiggers@google.com>; Andy Lutomirski <luto@kernel.org>;
> Will Deacon <will@kernel.org>; Marc Zyngier <maz@kernel.org>; Catalin Marinas
> <catalin.marinas@arm.com>; Willy Tarreau <w@1wt.eu>; Netdev <netdev@vger.kernel.org>;
> Toke Høiland-Jørgensen <toke@toke.dk>; Dave Taht <dave.taht@gmail.com>
> Subject: chapoly acceleration hardware [Was: Re: [RFC PATCH 00/18] crypto: wireguard
> using the existing crypto API]
>
> [CC +willy, toke, dave, netdev]
>
> Hi Pascal
>
> On Thu, Sep 26, 2019 at 12:19 PM Pascal Van Leeuwen
> <pvanleeuwen@verimatrix.com> wrote:
> > Actually, that assumption is factually wrong. I don't know if anything
> > is *publicly* available, but I can assure you the silicon is running in
> > labs already. And something will be publicly available early next year
> > at the latest. Which could nicely coincide with having Wireguard support
> > in the kernel (which I would also like to see happen BTW) ...
> >
> > Not "at some point". It will. Very soon. Maybe not in consumer or server
> > CPUs, but definitely in the embedded (networking) space.
> > And it *will* be much faster than the embedded CPU next to it, so it will
> > be worth using it for something like bulk packet encryption.
>
> Super! I was wondering if you could speak a bit more about the
> interface. My biggest questions surround latency. Will it be
> synchronous or asynchronous?
>
The hardware being external to the CPU and running in parallel with it,
obviously asynchronous.
> If the latter, why?
>
Because, as you probably already guessed, the round-trip latency is way
longer than the actual processing time, at least for small packets.
Partly because the only way to communicate between the CPU and the HW
accelerator (whether that is crypto, a GPU, a NIC, etc.) that doesn't
keep the CPU busy moving data is through memory, with the HW doing DMA.
And, as any programmer should now, round trip times to memory are huge
relative to the processing speed.
And partly because these accelerators are very similar to CPU's in
terms of architecture, doing pipelined processing and having multiple
of such pipelines in parallel. Except that these pipelines are not
working on low-level instructions but on full packets/blocks. So they
need to have many packets in flight to keep those pipelines fully
occupied. And packets need to move through the various pipeline stages,
so they incur the time needed to process them multiple times. (just
like e.g. a multiply instruction with a throughput of 1 per cycle
actually may need 4 or more cycles to actually provide its result)
Could you do that from a synchronous interface? In theory, probably,
if you would spawn a new thread for every new packet arriving and
rely on the scheduler to preempt the waiting threads. But you'd need
as many threads as the HW accelerator can have packets in flight,
while an async would need only 2 threads: one to handle the input to
the accelerator and one to handle the output (or at most one thread
per CPU, if you want to divide the workload)
Such a many-thread approach seems very inefficient to me.
> What will its latencies be?
>
Depends very much on the specific integration scenario (i.e. bus
speed, bus hierarchy, cache hierarchy, memory speed, etc.) but on
the order of a few thousand CPU clocks is not unheard of.
Which is an eternity for the CPU, but still only a few uSec in
human time. Not a problem unless you're a high-frequency trader and
every ns counts ...
It's not like the CPU would process those packets in zero time.
> How deep will its buffers be?
>
That of course depends on the specific accelerator implementation,
but possibly dozens of small packets in our case, as you'd need
at least width x depth packets in there to keep the pipes busy.
Just like a modern CPU needs hundreds of instructions in flight
to keep all its resources busy.
> The reason I ask is that a
> lot of crypto acceleration hardware of the past has been fast and
> having very deep buffers, but at great expense of latency.
>
Define "great expense". Everything is relative. The latency is very
high compared to per-packet processing time but at the same time it's
only on the order of a few uSec. Which may not even be significant on
the total time it takes for the packet to travel from input MAC to
output MAC, considering the CPU will still need to parse and classify
it and do pre- and postprocessing on it.
> In the networking context, keeping latency low is pretty important.
>
I've been doing this for IPsec for nearly 20 years now and I've never
heard anyone complain about our latency, so it must be OK.
We're also doing (fully inline, no CPU involved) MACsec cores, which
operate at layer 2 and I know it's a concern there for very specific
use cases (high frequency trading, precision time protocol, ...).
For "normal" VPN's though, a few uSec more or less should be a non-issue.
> Already
> WireGuard is multi-threaded which isn't super great all the time for
> latency (improvements are a work in progress). If you're involved with
> the design of the hardware, perhaps this is something you can help
> ensure winds up working well? For example, AES-NI is straightforward
> and good, but Intel can do that because they are the CPU. It sounds
> like your silicon will be adjacent. How do you envision this working
> in a low latency environment?
>
Depends on how low low-latency is. If you really need minimal latency,
you need an inline implementation. Which we can also provide, BTW :-)
Regards,
Pascal van Leeuwen
Silicon IP Architect, Multi-Protocol Engines @ Verimatrix
www.insidesecure.com
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/2] KVM: arm/arm64: Allow reporting non-ISV data aborts to userspace
From: Marc Zyngier @ 2019-09-26 13:47 UTC (permalink / raw)
To: Christoffer Dall, kvmarm
Cc: Peter Maydell, Daniel P. Berrangé, Suzuki K Poulose,
Heinrich Schuchardt, Alexander Graf, Julien Thierry,
Stefan Hajnoczi, James Morse, linux-arm-kernel
In-Reply-To: <20190909121337.27287-2-christoffer.dall@arm.com>
On 09/09/2019 13:13, Christoffer Dall wrote:
> For a long time, if a guest accessed memory outside of a memslot using
> any of the load/store instructions in the architecture which doesn't
> supply decoding information in the ESR_EL2 (the ISV bit is not set), the
> kernel would print the following message and terminate the VM as a
> result of returning -ENOSYS to userspace:
>
> load/store instruction decoding not implemented
>
> The reason behind this message is that KVM assumes that all accesses
> outside a memslot is an MMIO access which should be handled by
> userspace, and we originally expected to eventually implement some sort
> of decoding of load/store instructions where the ISV bit was not set.
>
> However, it turns out that many of the instructions which don't provide
> decoding information on abort are not safe to use for MMIO accesses, and
> the remaining few that would potentially make sense to use on MMIO
> accesses, such as those with register writeback, are not used in
> practice. It also turns out that fetching an instruction from guest
> memory can be a pretty horrible affair, involving stopping all CPUs on
> SMP systems, handling multiple corner cases of address translation in
> software, and more. It doesn't appear likely that we'll ever implement
> this in the kernel.
>
> What is much more common is that a user has misconfigured his/her guest
> and is actually not accessing an MMIO region, but just hitting some
> random hole in the IPA space. In this scenario, the error message above
> is almost misleading and has led to a great deal of confusion over the
> years.
>
> It is, nevertheless, ABI to userspace, and we therefore need to
> introduce a new capability that userspace explicitly enables to change
> behavior.
>
> This patch introduces KVM_CAP_ARM_NISV_TO_USER (NISV meaning Non-ISV)
> which does exactly that, and introduces a new exit reason to report the
> event to userspace. User space can then emulate an exception to the
> guest, restart the guest, suspend the guest, or take any other
> appropriate action as per the policy of the running system.
>
> Reported-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
> Signed-off-by: Christoffer Dall <christoffer.dall@arm.com>
> ---
> Documentation/virt/kvm/api.txt | 29 ++++++++++++++++++++++++++++
> arch/arm/include/asm/kvm_arm.h | 2 ++
> arch/arm/include/asm/kvm_emulate.h | 5 +++++
> arch/arm/include/asm/kvm_host.h | 8 ++++++++
> arch/arm64/include/asm/kvm_emulate.h | 5 +++++
> arch/arm64/include/asm/kvm_host.h | 8 ++++++++
> include/uapi/linux/kvm.h | 7 +++++++
> virt/kvm/arm/arm.c | 21 ++++++++++++++++++++
> virt/kvm/arm/mmio.c | 11 +++++++++--
> 9 files changed, 94 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/virt/kvm/api.txt b/Documentation/virt/kvm/api.txt
> index 2d067767b617..02501333f746 100644
> --- a/Documentation/virt/kvm/api.txt
> +++ b/Documentation/virt/kvm/api.txt
> @@ -4453,6 +4453,35 @@ Hyper-V SynIC state change. Notification is used to remap SynIC
> event/message pages and to enable/disable SynIC messages/events processing
> in userspace.
>
> + /* KVM_EXIT_ARM_NISV */
> + struct {
> + __u64 esr_iss;
> + __u64 fault_ipa;
> + } arm_nisv;
> +
> +Used on arm and arm64 systems. If a guest accesses memory not in a memslot,
> +KVM will typically return to userspace and ask it to do MMIO emulation on its
> +behalf. However, for certain classes of instructions, no instruction decode
> +(direction, length of memory access) is provided, and fetching and decoding
> +the instruction from the VM is overly complicated to live in the kernel.
> +
> +Historically, when this situation occurred, KVM would print a warning and kill
> +the VM. KVM assumed that if the guest accessed non-memslot memory, it was
> +trying to do I/O, which just couldn't be emulated, and the warning message was
> +phrased accordingly. However, what happened more often was that a guest bug
> +caused access outside the guest memory areas which should lead to a more
> +mearningful warning message and an external abort in the guest, if the access
meaningful?
> +did not fall within an I/O window.
> +
> +Userspace implementations can query for KVM_CAP_ARM_NISV_TO_USER, and enable
> +this capability at VM creation. Once this is done, these types of errors will
> +instead return to userspace with KVM_EXIT_ARM_NISV, with the valid bits from
> +the HSR (arm) and ESR_EL2 (arm64) in the esr_iss field, and the faulting IPA
> +in the fault_ipa field. Userspace can either fix up the access if it's
> +actually an I/O access by decoding the instruction from guest memory (if it's
> +very brave) and continue executing the guest, or it can decide to suspend,
> +dump, or restart the guest.
> +
> /* Fix the size of the union. */
> char padding[256];
> };
> diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
> index 0125aa059d5b..ce61b3b0058d 100644
> --- a/arch/arm/include/asm/kvm_arm.h
> +++ b/arch/arm/include/asm/kvm_arm.h
> @@ -162,6 +162,8 @@
> #define HSR_ISV (_AC(1, UL) << HSR_ISV_SHIFT)
> #define HSR_SRT_SHIFT (16)
> #define HSR_SRT_MASK (0xf << HSR_SRT_SHIFT)
> +#define HSR_CM (1 << 8)
> +#define HSR_WNR (1 << 6)
I think we already have that one (bizarrely placed after HSR_SSE).
> #define HSR_FSC (0x3f)
> #define HSR_FSC_TYPE (0x3c)
> #define HSR_SSE (1 << 21)
> diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
> index 40002416efec..e8ef349c04b4 100644
> --- a/arch/arm/include/asm/kvm_emulate.h
> +++ b/arch/arm/include/asm/kvm_emulate.h
> @@ -167,6 +167,11 @@ static inline bool kvm_vcpu_dabt_isvalid(struct kvm_vcpu *vcpu)
> return kvm_vcpu_get_hsr(vcpu) & HSR_ISV;
> }
>
> +static inline unsigned long kvm_vcpu_dabt_iss_nisv_sanitized(const struct kvm_vcpu *vcpu)
> +{
> + return kvm_vcpu_get_hsr(vcpu) & (HSR_CM | HSR_WNR | HSR_FSC);
> +}
> +
> static inline bool kvm_vcpu_dabt_iswrite(struct kvm_vcpu *vcpu)
> {
> return kvm_vcpu_get_hsr(vcpu) & HSR_WNR;
> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> index 8a37c8e89777..19a92c49039c 100644
> --- a/arch/arm/include/asm/kvm_host.h
> +++ b/arch/arm/include/asm/kvm_host.h
> @@ -76,6 +76,14 @@ struct kvm_arch {
>
> /* Mandated version of PSCI */
> u32 psci_version;
> +
> + /*
> + * If we encounter a data abort without valid instruction syndrome
> + * information, report this to user space. User space can (and
> + * should) opt in to this feature if KVM_CAP_ARM_NISV_TO_USER is
> + * supported.
> + */
> + bool return_nisv_io_abort_to_user;
> };
>
> #define KVM_NR_MEM_OBJS 40
> diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
> index d69c1efc63e7..a3c967988e1d 100644
> --- a/arch/arm64/include/asm/kvm_emulate.h
> +++ b/arch/arm64/include/asm/kvm_emulate.h
> @@ -258,6 +258,11 @@ static inline bool kvm_vcpu_dabt_isvalid(const struct kvm_vcpu *vcpu)
> return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_ISV);
> }
>
> +static inline unsigned long kvm_vcpu_dabt_iss_nisv_sanitized(const struct kvm_vcpu *vcpu)
> +{
> + return kvm_vcpu_get_hsr(vcpu) & (ESR_ELx_CM | ESR_ELx_WNR | ESR_ELx_FSC);
> +}
> +
> static inline bool kvm_vcpu_dabt_issext(const struct kvm_vcpu *vcpu)
> {
> return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SSE);
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index f656169db8c3..019bc560edc1 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -83,6 +83,14 @@ struct kvm_arch {
>
> /* Mandated version of PSCI */
> u32 psci_version;
> +
> + /*
> + * If we encounter a data abort without valid instruction syndrome
> + * information, report this to user space. User space can (and
> + * should) opt in to this feature if KVM_CAP_ARM_NISV_TO_USER is
> + * supported.
> + */
> + bool return_nisv_io_abort_to_user;
> };
>
> #define KVM_NR_MEM_OBJS 40
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 5e3f12d5359e..dd79235b6435 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -235,6 +235,7 @@ struct kvm_hyperv_exit {
> #define KVM_EXIT_S390_STSI 25
> #define KVM_EXIT_IOAPIC_EOI 26
> #define KVM_EXIT_HYPERV 27
> +#define KVM_EXIT_ARM_NISV 28
>
> /* For KVM_EXIT_INTERNAL_ERROR */
> /* Emulate instruction failed. */
> @@ -392,6 +393,11 @@ struct kvm_run {
> } eoi;
> /* KVM_EXIT_HYPERV */
> struct kvm_hyperv_exit hyperv;
> + /* KVM_EXIT_ARM_NISV */
> + struct {
> + __u64 esr_iss;
> + __u64 fault_ipa;
> + } arm_nisv;
> /* Fix the size of the union. */
> char padding[256];
> };
> @@ -996,6 +1002,7 @@ struct kvm_ppc_resize_hpt {
> #define KVM_CAP_ARM_PTRAUTH_ADDRESS 171
> #define KVM_CAP_ARM_PTRAUTH_GENERIC 172
> #define KVM_CAP_PMU_EVENT_FILTER 173
> +#define KVM_CAP_ARM_NISV_TO_USER 174
>
> #ifdef KVM_CAP_IRQ_ROUTING
>
> diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
> index 35a069815baf..7153504bb106 100644
> --- a/virt/kvm/arm/arm.c
> +++ b/virt/kvm/arm/arm.c
> @@ -98,6 +98,26 @@ int kvm_arch_check_processor_compat(void)
> return 0;
> }
>
> +int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
> + struct kvm_enable_cap *cap)
> +{
> + int r;
> +
> + if (cap->flags)
> + return -EINVAL;
> +
> + switch (cap->cap) {
> + case KVM_CAP_ARM_NISV_TO_USER:
> + r = 0;
> + kvm->arch.return_nisv_io_abort_to_user = true;
> + break;
> + default:
> + r = -EINVAL;
> + break;
> + }
> +
> + return r;
> +}
>
> /**
> * kvm_arch_init_vm - initializes a VM data structure
> @@ -196,6 +216,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
> case KVM_CAP_MP_STATE:
> case KVM_CAP_IMMEDIATE_EXIT:
> case KVM_CAP_VCPU_EVENTS:
> + case KVM_CAP_ARM_NISV_TO_USER:
> r = 1;
> break;
> case KVM_CAP_ARM_SET_DEVICE_ADDR:
> diff --git a/virt/kvm/arm/mmio.c b/virt/kvm/arm/mmio.c
> index 6af5c91337f2..7b92e2744fa7 100644
> --- a/virt/kvm/arm/mmio.c
> +++ b/virt/kvm/arm/mmio.c
> @@ -167,8 +167,15 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
> if (ret)
> return ret;
> } else {
> - kvm_err("load/store instruction decoding not implemented\n");
> - return -ENOSYS;
> + if (vcpu->kvm->arch.return_nisv_io_abort_to_user) {
> + run->exit_reason = KVM_EXIT_ARM_NISV;
> + run->arm_nisv.esr_iss = kvm_vcpu_dabt_iss_nisv_sanitized(vcpu);
> + run->arm_nisv.fault_ipa = fault_ipa;
> + return 0;
> + } else {
> + kvm_info("Encountered data abort outside memslots with no valid syndrome info\n");
Nit: you could lose the else clause, making this line a bit shorter.
More importantly, I'd like this to become a rate-limited output, just to
keep things sane. How about kvm_pr_unimpl()?
> + return -ENOSYS;
> + }
> }
>
> rt = vcpu->arch.mmio_decode.rt;
>
Other than this collection of nits, this looks pretty good, and I'd
really like to take this patch in 5.5.
Thanks,
M.
--
Jazz is not dead, it just smells funny...
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v8 5/6] PM / devfreq: Add PM QoS support
From: Leonard Crestez @ 2019-09-26 13:43 UTC (permalink / raw)
To: Chanwoo Choi, Matthias Kaehlcke
Cc: Artur Świgoń, Abel Vesa, Saravana Kannan,
linux-pm@vger.kernel.org, Viresh Kumar, dl-linux-imx,
Krzysztof Kozlowski, Lukasz Luba, Kyungmin Park, MyungJoo Ham,
Alexandre Bailon, Georgi Djakov,
linux-arm-kernel@lists.infradead.org, Jacky Bai
In-Reply-To: <5f12931b-92f8-15d8-8498-f02a7c2e999f@samsung.com>
On 2019-09-26 4:07 AM, Chanwoo Choi wrote:
> On 19. 9. 26. 오전 6:18, Leonard Crestez wrote:
>> On 25.09.2019 05:11, Chanwoo Choi wrote:
>>> On 19. 9. 24. 오후 7:11, Leonard Crestez wrote:
>>>> Register notifiers with the PM QoS framework in order to respond to
>>>> requests for DEV_PM_QOS_MIN_FREQUENCY and DEV_PM_QOS_MAX_FREQUENCY.
>>>>
>>>> No notifiers are added by this patch but PM QoS constraints can be
>>>> imposed externally (for example from other devices).
>>>>
>>>> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
>>>> Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
>>>> ---
>>>> drivers/devfreq/devfreq.c | 75 +++++++++++++++++++++++++++++++++++++++
>>>> include/linux/devfreq.h | 5 +++
>>>> 2 files changed, 80 insertions(+)
>>>>
>>>> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
>>>> index eee403e70c84..784f3e40536a 100644
>>>> --- a/drivers/devfreq/devfreq.c
>>>> +++ b/drivers/devfreq/devfreq.c
>>>> @@ -22,15 +22,18 @@
>>>> #include <linux/platform_device.h>
>>>> #include <linux/list.h>
>>>> #include <linux/printk.h>
>>>> #include <linux/hrtimer.h>
>>>> #include <linux/of.h>
>>>> +#include <linux/pm_qos.h>
>>>> #include "governor.h"
>>>>
>>>> #define CREATE_TRACE_POINTS
>>>> #include <trace/events/devfreq.h>
>>>>
>>>> +#define HZ_PER_KHZ 1000
>>>> +
>>>> static struct class *devfreq_class;
>>>>
>>>> /*
>>>> * devfreq core provides delayed work based load monitoring helper
>>>> * functions. Governors can use these or can implement their own
>>>> @@ -109,10 +112,11 @@ static unsigned long find_available_max_freq(struct devfreq *devfreq)
>>>> static void get_freq_range(struct devfreq *devfreq,
>>>> unsigned long *min_freq,
>>>> unsigned long *max_freq)
>>>> {
>>>> unsigned long *freq_table = devfreq->profile->freq_table;
>>>> + unsigned long qos_min_freq, qos_max_freq;
>>>>
>>>> lockdep_assert_held(&devfreq->lock);
>>>>
>>>> /*
>>>> * Init min/max frequency from freq table.
>>>> @@ -125,10 +129,18 @@ static void get_freq_range(struct devfreq *devfreq,
>>>> } else {
>>>> *min_freq = freq_table[devfreq->profile->max_state - 1];
>>>> *max_freq = freq_table[0];
>>>> }
>>>>
>>>> + /* constraints from PM QoS */
>>>
>>> As I commented on patch4,
>>> 'constraints' -> 'Constraint' because first verb have to be used
>>> as the sigular verbs.
>>
>> Already discussed for another patch; I will modify to "Apply constraints
>> from PM QoS" instead.
>
> I agree the new comment with 'Apply constraints ... '.
>
>>
>>> I prefer to use following comments:
>>>
>>> /* Constraint minimum/maximum frequency from PM QoS constraints */
>>>
>>>> + qos_min_freq = dev_pm_qos_read_value(devfreq->dev.parent,
>>>> + DEV_PM_QOS_MIN_FREQUENCY);
>>>> + qos_max_freq = dev_pm_qos_read_value(devfreq->dev.parent,
>>>> + DEV_PM_QOS_MIN_FREQUENCY);
>>>> + *min_freq = max(*min_freq, HZ_PER_KHZ * qos_min_freq);
>>>> + *max_freq = min(*max_freq, HZ_PER_KHZ * qos_max_freq);
>>>> +
>>>> /* constraints from sysfs */
>>>> *min_freq = max(*min_freq, devfreq->min_freq);
>>>> *max_freq = min(*max_freq, devfreq->max_freq);
>>>>
>>>> /* constraints from OPP interface */
>>>> @@ -606,10 +618,49 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
>>>> mutex_unlock(&devfreq->lock);
>>>>
>>>> return ret;
>>>> }
>>>>
>>>> +/**
>>>> + * qos_notifier_call() - Common handler for QoS constraints.
>>>> + * @devfreq: the devfreq instance.
>>>> + */
>>>> +static int qos_notifier_call(struct devfreq *devfreq)
>>>> +{
>>>> + int err;
>>>> +
>>>> + mutex_lock(&devfreq->lock);
>>>> + err = update_devfreq(devfreq);
>>>> + mutex_unlock(&devfreq->lock);
>>>> + if (err)
>>>> + dev_err(devfreq->dev.parent,
>>>> + "failed to update frequency for PM QoS constraints (%d)\n",
>>>
>>> Is it not over 80 char?
>>
>> Yes but coding style explicitly forbids breaking strings.
>>
>>>> + err);
>>>> +
>>>> + return NOTIFY_OK;
>>>> +}
>>>> +
>>>> +/**
>>>> + * qos_min_notifier_call() - Callback for QoS min_freq changes.
>>>> + * @nb: Should be devfreq->nb_min
>>>> + */
>>>> +static int qos_min_notifier_call(struct notifier_block *nb,
>>>> + unsigned long val, void *ptr)
>>>> +{
>>>> + return qos_notifier_call(container_of(nb, struct devfreq, nb_min));
>>>> +}
>>>> +
>>>> +/**
>>>> + * qos_max_notifier_call() - Callback for QoS max_freq changes.
>>>> + * @nb: Should be devfreq->nb_max
>>>> + */
>>>> +static int qos_max_notifier_call(struct notifier_block *nb,
>>>> + unsigned long val, void *ptr)
>>>> +{
>>>> + return qos_notifier_call(container_of(nb, struct devfreq, nb_max));
>>>> +}
>>>> +
>>>> /**
>>>> * devfreq_dev_release() - Callback for struct device to release the device.
>>>> * @dev: the devfreq device
>>>> *
>>>> * Remove devfreq from the list and release its resources.
>>>> @@ -620,10 +671,15 @@ static void devfreq_dev_release(struct device *dev)
>>>>
>>>> mutex_lock(&devfreq_list_lock);
>>>> list_del(&devfreq->node);
>>>> mutex_unlock(&devfreq_list_lock);
>>>>
>>>> + dev_pm_qos_remove_notifier(devfreq->dev.parent, &devfreq->nb_max,
>>>> + DEV_PM_QOS_MAX_FREQUENCY);
>>>> + dev_pm_qos_remove_notifier(devfreq->dev.parent, &devfreq->nb_min,
>>>> + DEV_PM_QOS_MIN_FREQUENCY);
>>>> +
>>>
>>> Just print error with dev_err() without stopping the release step.
>>>
>>> I prefer to handle the return value if kernel API provides
>>> the error code.
>
> How about?
Modified to dev_warn. This also applies to PATCH 6 so I replied there.
>>>> if (devfreq->profile->exit)
>>>> devfreq->profile->exit(devfreq->dev.parent);
>>>>
>>>> kfree(devfreq->time_in_state);
>>>> kfree(devfreq->trans_table);
>>>> @@ -733,10 +789,28 @@ struct devfreq *devfreq_add_device(struct device *dev,
>>>> if (err) {
>>>> put_device(&devfreq->dev);
>>>> goto err_out;
>>>> }
>>>>
>>>> + /*
>>>> + * Register notifiers for updates to min/max_freq after device is
>>>> + * initialized (and we can handle notifications) but before the
>>>> + * governor is started (which should do an initial enforcement of
>>>> + * constraints).
>>>> + */
>>>
>>> My previous comment is not enough why I prefer to remove it. Sorry.
>>> Actually, until now, the devfreq_add_device() don't have the detailed
>>> comments because the line code is not too long. But, at the present time,
>>> devfreq_add_device() is too long. It means that the detailed comment
>>> are necessary.
>>>
>>> So, I'll add the detailed comment for each step of devfreq_add_device()
>>> on separate patch to keep the same style. I'll send the patch to you
>>> for the review.
>>
>> This is very likely to result in merge conflicts, maybe wait for my
>> series to go in first?
>
> I'll send the separate patch after finished the review of these patches.
> So, if you agree, please remove this comment on this patch.
>
> You can review the detailed comments on separate patch when I send.
This patch already contains comments and they explain the code being
added. Doesn't it make more sense for comments and code to go in together?
I think the comment is a resonable explanation as to why notifiers are
registered at that specific step in the initialization sequence.
>>>> + devfreq->nb_min.notifier_call = qos_min_notifier_call;
>>>> + err = dev_pm_qos_add_notifier(devfreq->dev.parent, &devfreq->nb_min,
>>>> + DEV_PM_QOS_MIN_FREQUENCY);
>>>> + if (err)
>>>> + goto err_devfreq;
>>>> +
>>>> + devfreq->nb_max.notifier_call = qos_max_notifier_call;
>>>> + err = dev_pm_qos_add_notifier(devfreq->dev.parent, &devfreq->nb_max,
>>>> + DEV_PM_QOS_MAX_FREQUENCY);
>>>> + if (err)
>>>> + goto err_devfreq;
>>>> +
>>>> mutex_lock(&devfreq_list_lock);
>>>>
>>>> governor = try_then_request_governor(devfreq->governor_name);
>>>> if (IS_ERR(governor)) {
>>>> dev_err(dev, "%s: Unable to find governor for the device\n",
>>>> @@ -760,10 +834,11 @@ struct devfreq *devfreq_add_device(struct device *dev,
>>>>
>>>> return devfreq;
>>>>
>>>> err_init:
>>>> mutex_unlock(&devfreq_list_lock);
>>>> +err_devfreq:
>>>> devfreq_remove_device(devfreq);
>>>> return ERR_PTR(err);
>>>>
>>>> err_dev:
>>>> /*
>>>> diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
>>>> index c3cbc15fdf08..dac0dffeabb4 100644
>>>> --- a/include/linux/devfreq.h
>>>> +++ b/include/linux/devfreq.h
>>>> @@ -134,10 +134,12 @@ struct devfreq_dev_profile {
>>>> * @total_trans: Number of devfreq transitions
>>>> * @trans_table: Statistics of devfreq transitions
>>>> * @time_in_state: Statistics of devfreq states
>>>> * @last_stat_updated: The last time stat updated
>>>> * @transition_notifier_list: list head of DEVFREQ_TRANSITION_NOTIFIER notifier
>>>> + * @nb_min: Notifier block for DEV_PM_QOS_MIN_FREQUENCY
>>>> + * @nb_max: Notifier block for DEV_PM_QOS_MAX_FREQUENCY
>>>> *
>>>> * This structure stores the devfreq information for a give device.
>>>> *
>>>> * Note that when a governor accesses entries in struct devfreq in its
>>>> * functions except for the context of callbacks defined in struct
>>>> @@ -176,10 +178,13 @@ struct devfreq {
>>>> unsigned int *trans_table;
>>>> unsigned long *time_in_state;
>>>> unsigned long last_stat_updated;
>>>>
>>>> struct srcu_notifier_head transition_notifier_list;
>>>> +
>>>> + struct notifier_block nb_min;
>>>> + struct notifier_block nb_max;
>>>> };
>>>>
>>>> struct devfreq_freqs {
>>>> unsigned long old;
>>>> unsigned long new;
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 00/11] PCI dma-ranges parsing consolidation
From: Andrew Murray @ 2019-09-26 13:38 UTC (permalink / raw)
To: Rob Herring
Cc: Lorenzo Pieralisi, Ard Biesheuvel, Marc Zyngier, Marc Gonzalez,
Mans Rullgard, Bjorn Helgaas, PCI, Robin Murphy, Linux ARM
In-Reply-To: <CAL_JsqLtYYXCgGN6_t8SuPqPmQwhhRJXaf8+kxnKxLHbRQRaDQ@mail.gmail.com>
On Thu, Sep 26, 2019 at 08:11:16AM -0500, Rob Herring wrote:
> On Thu, Sep 26, 2019 at 6:20 AM Marc Gonzalez <marc.w.gonzalez@free.fr> wrote:
> >
> > [ Tweaking recipients list ]
> >
> > On 26/09/2019 10:49, Andrew Murray wrote:
> >
> > > On Tue, Sep 24, 2019 at 04:46:19PM -0500, Rob Herring wrote:
> > >
> > >> pci-rcar-gen2 is the only remaining driver doing its own dma-ranges
> > >> handling as it is still using the old ARM PCI functions. Looks like it
> > >> is the last one (in drivers/pci/).
> > >
> > > It also seems that pcie-tango is using of_pci_dma_range_parser_init
> > > and so parsing dma-ranges. Though it's using the dma_ranges for a
> > > slightly different purpose.
>
> Seems I missed that as I only grep'ed for for_each_of_pci_range...
>
> >
> > The rationale for that code can be found here:
> >
> > https://patchwork.kernel.org/patch/9915469/
> >
> > NB: 1) The PCIE_TANGO_SMP8759 Kconfig symbol is marked "depends on BROKEN",
> > and 2) The driver adds TAINT_CRAP,
> > and 3) The maker of the tango platform is dead.
>
Thanks for the context Marc, much appreciated.
Is there a path to make this driver not BROKEN? Or is this likely to bit rot?
> Given that and that I'd have to rework the probe to do the MSI range
> setup after pci_host_common_probe, I'm just going to leave this one
> alone.
I don't see any harm with that.
Thanks,
Andrew Murray
>
> Rob
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v2 4/4] arm64: Remove gettimeofday.S
From: Vincenzo Frascino @ 2019-09-26 13:38 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: ard.biesheuvel, catalin.marinas, ndesaulniers, tglx,
vincenzo.frascino, will
In-Reply-To: <20190926133805.52348-1-vincenzo.frascino@arm.com>
gettimeofday.S was originally removed with the introduction of the
support for Unified vDSOs in arm64 and replaced with the C
implementation.
The file seems again present in the repository due to a side effect of
rebase.
Remove the file again.
Cc: Will Deacon <will@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/kernel/vdso/gettimeofday.S | 0
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 arch/arm64/kernel/vdso/gettimeofday.S
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
deleted file mode 100644
index e69de29bb2d1..000000000000
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v2 3/4] arm64: vdso32: Fix compilation warning
From: Vincenzo Frascino @ 2019-09-26 13:38 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: ard.biesheuvel, catalin.marinas, ndesaulniers, tglx,
vincenzo.frascino, will
In-Reply-To: <20190926133805.52348-1-vincenzo.frascino@arm.com>
As reported by Will Deacon the following compilation warning appears
during the compilation of the vdso32:
In file included from ./arch/arm64/include/asm/thread_info.h:17:0,
from ./include/linux/thread_info.h:38,
from ./arch/arm64/include/asm/preempt.h:5,
from ./include/linux/preempt.h:78,
from ./include/linux/spinlock.h:51,
from ./include/linux/seqlock.h:36,
from ./include/linux/time.h:6,
from .../work/linux/lib/vdso/gettimeofday.c:7,
from <command-line>:0:
./arch/arm64/include/asm/memory.h: In function ‘__tag_set’:
./arch/arm64/include/asm/memory.h:233:15: warning: cast from pointer to
integer of different size [-Wpointer-to-int-cast]
u64 __addr = (u64)addr & ~__tag_shifted(0xff);
^
In file included from ./arch/arm64/include/asm/pgtable-hwdef.h:8:0,
from ./arch/arm64/include/asm/processor.h:34,
from ./arch/arm64/include/asm/elf.h:118,
from ./include/linux/elf.h:5,
from ./include/linux/elfnote.h:62,
from arch/arm64/kernel/vdso32/note.c:11:
./arch/arm64/include/asm/memory.h: In function ‘__tag_set’:
./arch/arm64/include/asm/memory.h:233:15: warning: cast from pointer to
integer of different size [-Wpointer-to-int-cast]
u64 __addr = (u64)addr & ~__tag_shifted(0xff);
^
This happens because few 64 bit compilation headers are included during
the generation of vdso32.
Fix the issue redefining the __tag_set function.
Note: This fix is meant to be temporary, a more comprehensive solution
based on the refactoring of the generic headers will be provided with a
future patch set. At that point it will be possible to revert this patch.
Cc: Will Deacon <will@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
---
arch/arm64/include/asm/memory.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index b61b50bf68b1..cfa9cd87af14 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -228,11 +228,16 @@ static inline unsigned long kaslr_offset(void)
#define __tag_get(addr) 0
#endif /* CONFIG_KASAN_SW_TAGS */
+#ifdef __aarch64__
static inline const void *__tag_set(const void *addr, u8 tag)
{
u64 __addr = (u64)addr & ~__tag_shifted(0xff);
return (const void *)(__addr | __tag_shifted(tag));
}
+#else
+/* Unused in compat vdso */
+#define __tag_set(addr, tag) 0
+#endif
/*
* Physical vs virtual RAM address space conversion. These are
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v2 2/4] arm64: vdso32: Detect binutils support for dmb ishld
From: Vincenzo Frascino @ 2019-09-26 13:38 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: ard.biesheuvel, catalin.marinas, ndesaulniers, tglx,
vincenzo.frascino, will
In-Reply-To: <20190926133805.52348-1-vincenzo.frascino@arm.com>
As reported by Will Deacon, older versions of binutils that do not
support certain types of memory barriers can cause build failure of the
vdso32 library.
Add a compilation time mechanism that detects if binutils supports those
instructions and configure the kernel accordingly.
Cc: Will Deacon <will@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
---
arch/arm64/Kbuild | 6 ++++++
arch/arm64/include/asm/vdso/compat_barrier.h | 2 +-
arch/arm64/kernel/vdso32/Makefile | 9 +++++++++
3 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/Kbuild b/arch/arm64/Kbuild
index d6465823b281..75cf8c796d0e 100644
--- a/arch/arm64/Kbuild
+++ b/arch/arm64/Kbuild
@@ -4,3 +4,9 @@ obj-$(CONFIG_NET) += net/
obj-$(CONFIG_KVM) += kvm/
obj-$(CONFIG_XEN) += xen/
obj-$(CONFIG_CRYPTO) += crypto/
+
+# as-instr-compat
+# Usage: cflags-y += $(call as-instr-compat,instr,option1,option2)
+
+as-instr-compat = $(call try-run,\
+ printf "%b\n" "$(1)" | $(COMPATCC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3))
diff --git a/arch/arm64/include/asm/vdso/compat_barrier.h b/arch/arm64/include/asm/vdso/compat_barrier.h
index fb60a88b5ed4..3fd8fd6d8fc2 100644
--- a/arch/arm64/include/asm/vdso/compat_barrier.h
+++ b/arch/arm64/include/asm/vdso/compat_barrier.h
@@ -20,7 +20,7 @@
#define dmb(option) __asm__ __volatile__ ("dmb " #option : : : "memory")
-#if __LINUX_ARM_ARCH__ >= 8
+#if __LINUX_ARM_ARCH__ >= 8 && defined(CONFIG_AS_DMB_ISHLD)
#define aarch32_smp_mb() dmb(ish)
#define aarch32_smp_rmb() dmb(ishld)
#define aarch32_smp_wmb() dmb(ishst)
diff --git a/arch/arm64/kernel/vdso32/Makefile b/arch/arm64/kernel/vdso32/Makefile
index 1fba0776ed40..22f0d31ea528 100644
--- a/arch/arm64/kernel/vdso32/Makefile
+++ b/arch/arm64/kernel/vdso32/Makefile
@@ -17,6 +17,8 @@ cc32-disable-warning = $(call try-run,\
$(COMPATCC) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
cc32-ldoption = $(call try-run,\
$(COMPATCC) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2))
+cc32-as-instr = $(call try-run,\
+ printf "%b\n" "$(1)" | $(COMPATCC) $(VDSO_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3))
# We cannot use the global flags to compile the vDSO files, the main reason
# being that the 32-bit compiler may be older than the main (64-bit) compiler
@@ -55,6 +57,7 @@ endif
VDSO_CAFLAGS += -fPIC -fno-builtin -fno-stack-protector
VDSO_CAFLAGS += -DDISABLE_BRANCH_PROFILING
+
# Try to compile for ARMv8. If the compiler is too old and doesn't support it,
# fall back to v7. There is no easy way to check for what architecture the code
# is being compiled, so define a macro specifying that (see arch/arm/Makefile).
@@ -91,6 +94,12 @@ VDSO_CFLAGS += -Wno-int-to-pointer-cast
VDSO_AFLAGS := $(VDSO_CAFLAGS)
VDSO_AFLAGS += -D__ASSEMBLY__
+# Check for binutils support for dmb ishld
+dmbinstr := $(call cc32-as-instr,dmb ishld,-DCONFIG_AS_DMB_ISHLD=1)
+
+VDSO_CFLAGS += $(dmbinstr)
+VDSO_AFLAGS += $(dmbinstr)
+
VDSO_LDFLAGS := $(VDSO_CPPFLAGS)
# From arm vDSO Makefile
VDSO_LDFLAGS += -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-soname=linux-vdso.so.1
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v2 1/4] arm64: vdso32: Introduce COMPAT_CC_IS_GCC
From: Vincenzo Frascino @ 2019-09-26 13:38 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: ard.biesheuvel, catalin.marinas, ndesaulniers, tglx,
vincenzo.frascino, will
In-Reply-To: <20190926133805.52348-1-vincenzo.frascino@arm.com>
As reported by Will Deacon the .config file and the generated
include/config/auto.conf can end up out of sync after a set of
commands since CONFIG_CROSS_COMPILE_COMPAT_VDSO is not updated
correctly.
The sequence can be reproduced as follows:
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
[...]
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig
[set CONFIG_CROSS_COMPILE_COMPAT_VDSO="arm-linux-gnueabihf-"]
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
Which results in:
arch/arm64/Makefile:62: CROSS_COMPILE_COMPAT not defined or empty,
the compat vDSO will not be built
even though the compat vDSO has been built:
$ file arch/arm64/kernel/vdso32/vdso.so
arch/arm64/kernel/vdso32/vdso.so: ELF 32-bit LSB pie executable, ARM,
EABI5 version 1 (SYSV), dynamically linked,
BuildID[sha1]=c67f6c786f2d2d6f86c71f708595594aa25247f6, stripped
A similar case that involves changing the configuration parameter multiple
times can be reconducted to the same family of problems.
The reason behind it comes from the fact that the master Makefile includes
that architecture Makefile twice, once before the syncconfig and one after.
Since the synchronization of the files happens only upon syncconfig, the
architecture Makefile included before this event does not see the change in
configuration.
As a consequence of this it is not possible to handle the cross compiler
definitions inside the architecture Makefile.
Address the problem removing CONFIG_CROSS_COMPILE_COMPAT_VDSO and moving
the detection of the correct compiler into Kconfig via COMPAT_CC_IS_GCC.
As a consequence of this it is not possible anymore to set the compat
cross compiler from menuconfig but it requires to be exported via
command line.
E.g.:
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
CROSS_COMPILE_COMPAT=arm-linux-gnueabihf
Cc: Will Deacon <will@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
---
arch/arm64/Kconfig | 5 ++++-
arch/arm64/Makefile | 15 ++-------------
2 files changed, 6 insertions(+), 14 deletions(-)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 37c610963eee..13e2d2e16af7 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -110,7 +110,7 @@ config ARM64
select GENERIC_STRNLEN_USER
select GENERIC_TIME_VSYSCALL
select GENERIC_GETTIMEOFDAY
- select GENERIC_COMPAT_VDSO if (!CPU_BIG_ENDIAN && COMPAT)
+ select GENERIC_COMPAT_VDSO if (!CPU_BIG_ENDIAN && COMPAT && COMPATCC_IS_GCC)
select HANDLE_DOMAIN_IRQ
select HARDIRQS_SW_RESEND
select HAVE_PCI
@@ -313,6 +313,9 @@ config KASAN_SHADOW_OFFSET
default 0xeffffff900000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
default 0xffffffffffffffff
+config COMPATCC_IS_GCC
+ def_bool $(success,$(CROSS_COMPILE_COMPAT)gcc --version | head -n 1 | grep -q arm)
+
source "arch/arm64/Kconfig.platforms"
menu "Kernel Features"
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 84a3d502c5a5..34f53eb11878 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -54,19 +54,8 @@ $(warning Detected assembler with broken .inst; disassembly will be unreliable)
endif
ifeq ($(CONFIG_GENERIC_COMPAT_VDSO), y)
- CROSS_COMPILE_COMPAT ?= $(CONFIG_CROSS_COMPILE_COMPAT_VDSO:"%"=%)
-
- ifeq ($(CONFIG_CC_IS_CLANG), y)
- $(warning CROSS_COMPILE_COMPAT is clang, the compat vDSO will not be built)
- else ifeq ($(strip $(CROSS_COMPILE_COMPAT)),)
- $(warning CROSS_COMPILE_COMPAT not defined or empty, the compat vDSO will not be built)
- else ifeq ($(shell which $(CROSS_COMPILE_COMPAT)gcc 2> /dev/null),)
- $(error $(CROSS_COMPILE_COMPAT)gcc not found, check CROSS_COMPILE_COMPAT)
- else
- export CROSS_COMPILE_COMPAT
- export CONFIG_COMPAT_VDSO := y
- compat_vdso := -DCONFIG_COMPAT_VDSO=1
- endif
+ export CONFIG_COMPAT_VDSO := y
+ compat_vdso := -DCONFIG_COMPAT_VDSO=1
endif
KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr) $(brokengasinst) \
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v2 0/4] arm64: vdso32: Address various issues
From: Vincenzo Frascino @ 2019-09-26 13:38 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: ard.biesheuvel, catalin.marinas, ndesaulniers, tglx,
vincenzo.frascino, will
In-Reply-To: <20190920142738.qlsjwguc6bpnez63@willie-the-truck>
Hi Will,
this patch series is meant to address the various compilation issues you
reported about arm64 vdso32. (This time for real I hope ;))
Please let me know if there is still something missing.
Thanks,
Vincenzo
Cc: Will Deacon <will@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
---
v2:
- Fixed binutils detection
- Addressed review comments
Vincenzo Frascino (4):
arm64: vdso32: Introduce COMPAT_CC_IS_GCC
arm64: vdso32: Detect binutils support for dmb ishld
arm64: vdso32: Fix compilation warning
arm64: Remove gettimeofday.S
arch/arm64/Kbuild | 6 ++++++
arch/arm64/Kconfig | 5 ++++-
arch/arm64/Makefile | 15 ++-------------
arch/arm64/include/asm/memory.h | 5 +++++
arch/arm64/include/asm/vdso/compat_barrier.h | 2 +-
arch/arm64/kernel/vdso/gettimeofday.S | 0
arch/arm64/kernel/vdso32/Makefile | 9 +++++++++
7 files changed, 27 insertions(+), 15 deletions(-)
delete mode 100644 arch/arm64/kernel/vdso/gettimeofday.S
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* RE: [PATCH v3 01/11] PCI: designware-ep: Add multiple PFs support for DWC
From: Gustavo Pimentel @ 2019-09-26 13:38 UTC (permalink / raw)
To: Andrew Murray, Xiaowei Bao, jingoohan1@gmail.com,
gustavo.pimentel@synopsys.com
Cc: mark.rutland@arm.com, Roy Zang, lorenzo.pieralisi@arm.com,
arnd@arndb.de, devicetree@vger.kernel.org,
linux-pci@vger.kernel.org, Z.q. Hou,
linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org,
kishon@ti.com, M.h. Lian, robh+dt@kernel.org,
linux-arm-kernel@lists.infradead.org, gregkh@linuxfoundation.org,
Leo Li, shawnguo@kernel.org, Mingkai Hu
In-Reply-To: <20190926102945.GD9720@e119886-lin.cambridge.arm.com>
On Thu, Sep 26, 2019 at 11:29:46, Andrew Murray <andrew.murray@arm.com>
wrote:
> On Tue, Sep 03, 2019 at 03:43:15AM +0000, Xiaowei Bao wrote:
> >
> >
> > > -----Original Message-----
> > > From: Andrew Murray <andrew.murray@arm.com>
> > > Sent: 2019年9月3日 0:26
> > > To: Xiaowei Bao <xiaowei.bao@nxp.com>
> > > Cc: robh+dt@kernel.org; mark.rutland@arm.com; shawnguo@kernel.org; Leo
> > > Li <leoyang.li@nxp.com>; kishon@ti.com; lorenzo.pieralisi@arm.com; M.h.
> > > Lian <minghuan.lian@nxp.com>; Mingkai Hu <mingkai.hu@nxp.com>; Roy
> > > Zang <roy.zang@nxp.com>; jingoohan1@gmail.com;
> > > gustavo.pimentel@synopsys.com; linux-pci@vger.kernel.org;
> > > devicetree@vger.kernel.org; linux-kernel@vger.kernel.org;
> > > linux-arm-kernel@lists.infradead.org; linuxppc-dev@lists.ozlabs.org;
> > > gregkh@linuxfoundation.org; Z.q. Hou <zhiqiang.hou@nxp.com>;
> > > arnd@arndb.de
> > > Subject: Re: [PATCH v3 01/11] PCI: designware-ep: Add multiple PFs support
> > > for DWC
> > >
> > > On Mon, Sep 02, 2019 at 11:17:06AM +0800, Xiaowei Bao wrote:
> > > > Add multiple PFs support for DWC, different PF have different config
> > > > space we use pf-offset property which get from the DTS to access the
> > > > different pF
> > >
> > > This needs to be updated as this no longer comes from the DT.
> >
> > Yes, thanks
> >
> > Thanks
> > Xiaowei
> >
> > >
> > > > config space.
> > > >
> > > > Signed-off-by: Xiaowei Bao <xiaowei.bao@nxp.com>
> > >
> > >
> > > We're assuming:
> > >
> > > - The offset address (func_offset) between PF's in the memory map can be
> > > different between different DWC implementations. And also that it's
> > > possible for DWC implementations to address PFs without using an offset.
> > >
> > > - The current approach is preferable to adding DWC EP driver callbacks
> > > for writing to the EP config space (e.g. a variant of dw_pcie_writew_dbi
> > > that takes a func number).
> >
> > Even if use the a variant of dw_pcie_writew_dbi, we also need a offset value form
> > different platform, due to the different platform may be have different implement
> > about this, so I am not sure how to implement the variant of dw_pcie_writew_dbi?
> >
> > >
> > > I'm keen to hear feedback from Jingoo/Gustavo on this.
> >
> > OK, expect the feedback.
>
> Hi Jingoo/Gustavo,
>
> I'm keen for your review/feedback on this.
Hi,
This ep section was created by Kishon initially, he is maintainer of it.
But it seems ok to me. I've seen the patch and sounds good to me. I've
given my Acked on version 4.
Regards,
Gustavo
>
> Thanks,
>
> Andrew Murray
>
> >
> > Thanks
> > Xiaowei
> >
> > >
> > > Thanks,
> > >
> > > Andrew Murray
> > >
> > > > ---
> > > > v2:
> > > > - Remove duplicate redundant code.
> > > > - Reimplement the PF config space access way.
> > > > v3:
> > > > - Integrate duplicate code for func_select.
> > > > - Move PCIE_ATU_FUNC_NUM(pf) (pf << 20) to ((pf) << 20).
> > > > - Add the comments for func_conf_select function.
> > > >
> > > > drivers/pci/controller/dwc/pcie-designware-ep.c | 123
> > > ++++++++++++++++--------
> > > > drivers/pci/controller/dwc/pcie-designware.c | 59 ++++++++----
> > > > drivers/pci/controller/dwc/pcie-designware.h | 18 +++-
> > > > 3 files changed, 142 insertions(+), 58 deletions(-)
> > > >
> > > > diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c
> > > > b/drivers/pci/controller/dwc/pcie-designware-ep.c
> > > > index 65f4792..eb851c2 100644
> > > > --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> > > > +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> > > > @@ -19,12 +19,26 @@ void dw_pcie_ep_linkup(struct dw_pcie_ep *ep)
> > > > pci_epc_linkup(epc);
> > > > }
> > > >
> > > > -static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno
> > > bar,
> > > > - int flags)
> > > > +static unsigned int dw_pcie_ep_func_select(struct dw_pcie_ep *ep, u8
> > > > +func_no) {
> > > > + unsigned int func_offset = 0;
> > > > +
> > > > + if (ep->ops->func_conf_select)
> > > > + func_offset = ep->ops->func_conf_select(ep, func_no);
> > > > +
> > > > + return func_offset;
> > > > +}
> > > > +
> > > > +static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, u8 func_no,
> > > > + enum pci_barno bar, int flags)
> > > > {
> > > > u32 reg;
> > > > + unsigned int func_offset = 0;
> > > > + struct dw_pcie_ep *ep = &pci->ep;
> > > > +
> > > > + func_offset = dw_pcie_ep_func_select(ep, func_no);
> > > >
> > > > - reg = PCI_BASE_ADDRESS_0 + (4 * bar);
> > > > + reg = func_offset + PCI_BASE_ADDRESS_0 + (4 * bar);
> > > > dw_pcie_dbi_ro_wr_en(pci);
> > > > dw_pcie_writel_dbi2(pci, reg, 0x0);
> > > > dw_pcie_writel_dbi(pci, reg, 0x0);
> > > > @@ -37,7 +51,12 @@ static void __dw_pcie_ep_reset_bar(struct dw_pcie
> > > > *pci, enum pci_barno bar,
> > > >
> > > > void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar) {
> > > > - __dw_pcie_ep_reset_bar(pci, bar, 0);
> > > > + u8 func_no, funcs;
> > > > +
> > > > + funcs = pci->ep.epc->max_functions;
> > > > +
> > > > + for (func_no = 0; func_no < funcs; func_no++)
> > > > + __dw_pcie_ep_reset_bar(pci, func_no, bar, 0);
> > > > }
> > > >
> > > > static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no,
> > > > @@ -45,28 +64,31 @@ static int dw_pcie_ep_write_header(struct pci_epc
> > > > *epc, u8 func_no, {
> > > > struct dw_pcie_ep *ep = epc_get_drvdata(epc);
> > > > struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> > > > + unsigned int func_offset = 0;
> > > > +
> > > > + func_offset = dw_pcie_ep_func_select(ep, func_no);
> > > >
> > > > dw_pcie_dbi_ro_wr_en(pci);
> > > > - dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, hdr->vendorid);
> > > > - dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, hdr->deviceid);
> > > > - dw_pcie_writeb_dbi(pci, PCI_REVISION_ID, hdr->revid);
> > > > - dw_pcie_writeb_dbi(pci, PCI_CLASS_PROG, hdr->progif_code);
> > > > - dw_pcie_writew_dbi(pci, PCI_CLASS_DEVICE,
> > > > + dw_pcie_writew_dbi(pci, func_offset + PCI_VENDOR_ID, hdr->vendorid);
> > > > + dw_pcie_writew_dbi(pci, func_offset + PCI_DEVICE_ID, hdr->deviceid);
> > > > + dw_pcie_writeb_dbi(pci, func_offset + PCI_REVISION_ID, hdr->revid);
> > > > + dw_pcie_writeb_dbi(pci, func_offset + PCI_CLASS_PROG,
> > > hdr->progif_code);
> > > > + dw_pcie_writew_dbi(pci, func_offset + PCI_CLASS_DEVICE,
> > > > hdr->subclass_code | hdr->baseclass_code << 8);
> > > > - dw_pcie_writeb_dbi(pci, PCI_CACHE_LINE_SIZE,
> > > > + dw_pcie_writeb_dbi(pci, func_offset + PCI_CACHE_LINE_SIZE,
> > > > hdr->cache_line_size);
> > > > - dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_VENDOR_ID,
> > > > + dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_VENDOR_ID,
> > > > hdr->subsys_vendor_id);
> > > > - dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_ID, hdr->subsys_id);
> > > > - dw_pcie_writeb_dbi(pci, PCI_INTERRUPT_PIN,
> > > > + dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_ID,
> > > hdr->subsys_id);
> > > > + dw_pcie_writeb_dbi(pci, func_offset + PCI_INTERRUPT_PIN,
> > > > hdr->interrupt_pin);
> > > > dw_pcie_dbi_ro_wr_dis(pci);
> > > >
> > > > return 0;
> > > > }
> > > >
> > > > -static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum
> > > pci_barno bar,
> > > > - dma_addr_t cpu_addr,
> > > > +static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no,
> > > > + enum pci_barno bar, dma_addr_t cpu_addr,
> > > > enum dw_pcie_as_type as_type)
> > > > {
> > > > int ret;
> > > > @@ -79,7 +101,7 @@ static int dw_pcie_ep_inbound_atu(struct
> > > dw_pcie_ep *ep, enum pci_barno bar,
> > > > return -EINVAL;
> > > > }
> > > >
> > > > - ret = dw_pcie_prog_inbound_atu(pci, free_win, bar, cpu_addr,
> > > > + ret = dw_pcie_prog_inbound_atu(pci, func_no, free_win, bar,
> > > > +cpu_addr,
> > > > as_type);
> > > > if (ret < 0) {
> > > > dev_err(pci->dev, "Failed to program IB window\n"); @@ -92,7
> > > +114,8
> > > > @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum
> > > pci_barno bar,
> > > > return 0;
> > > > }
> > > >
> > > > -static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, phys_addr_t
> > > > phys_addr,
> > > > +static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, u8 func_no,
> > > > + phys_addr_t phys_addr,
> > > > u64 pci_addr, size_t size)
> > > > {
> > > > u32 free_win;
> > > > @@ -104,8 +127,8 @@ static int dw_pcie_ep_outbound_atu(struct
> > > dw_pcie_ep *ep, phys_addr_t phys_addr,
> > > > return -EINVAL;
> > > > }
> > > >
> > > > - dw_pcie_prog_outbound_atu(pci, free_win, PCIE_ATU_TYPE_MEM,
> > > > - phys_addr, pci_addr, size);
> > > > + dw_pcie_prog_ep_outbound_atu(pci, func_no, free_win,
> > > PCIE_ATU_TYPE_MEM,
> > > > + phys_addr, pci_addr, size);
> > > >
> > > > set_bit(free_win, ep->ob_window_map);
> > > > ep->outbound_addr[free_win] = phys_addr; @@ -121,7 +144,7 @@
> > > static
> > > > void dw_pcie_ep_clear_bar(struct pci_epc *epc, u8 func_no,
> > > > enum pci_barno bar = epf_bar->barno;
> > > > u32 atu_index = ep->bar_to_atu[bar];
> > > >
> > > > - __dw_pcie_ep_reset_bar(pci, bar, epf_bar->flags);
> > > > + __dw_pcie_ep_reset_bar(pci, func_no, bar, epf_bar->flags);
> > > >
> > > > dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_INBOUND);
> > > > clear_bit(atu_index, ep->ib_window_map); @@ -137,14 +160,20 @@
> > > > static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no,
> > > > size_t size = epf_bar->size;
> > > > int flags = epf_bar->flags;
> > > > enum dw_pcie_as_type as_type;
> > > > - u32 reg = PCI_BASE_ADDRESS_0 + (4 * bar);
> > > > + u32 reg;
> > > > + unsigned int func_offset = 0;
> > > > +
> > > > + func_offset = dw_pcie_ep_func_select(ep, func_no);
> > > > +
> > > > + reg = PCI_BASE_ADDRESS_0 + (4 * bar) + func_offset;
> > > >
> > > > if (!(flags & PCI_BASE_ADDRESS_SPACE))
> > > > as_type = DW_PCIE_AS_MEM;
> > > > else
> > > > as_type = DW_PCIE_AS_IO;
> > > >
> > > > - ret = dw_pcie_ep_inbound_atu(ep, bar, epf_bar->phys_addr, as_type);
> > > > + ret = dw_pcie_ep_inbound_atu(ep, func_no, bar,
> > > > + epf_bar->phys_addr, as_type);
> > > > if (ret)
> > > > return ret;
> > > >
> > > > @@ -202,7 +231,7 @@ static int dw_pcie_ep_map_addr(struct pci_epc
> > > *epc, u8 func_no,
> > > > struct dw_pcie_ep *ep = epc_get_drvdata(epc);
> > > > struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> > > >
> > > > - ret = dw_pcie_ep_outbound_atu(ep, addr, pci_addr, size);
> > > > + ret = dw_pcie_ep_outbound_atu(ep, func_no, addr, pci_addr, size);
> > > > if (ret) {
> > > > dev_err(pci->dev, "Failed to enable address\n");
> > > > return ret;
> > > > @@ -216,11 +245,14 @@ static int dw_pcie_ep_get_msi(struct pci_epc
> > > *epc, u8 func_no)
> > > > struct dw_pcie_ep *ep = epc_get_drvdata(epc);
> > > > struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> > > > u32 val, reg;
> > > > + unsigned int func_offset = 0;
> > > >
> > > > if (!ep->msi_cap)
> > > > return -EINVAL;
> > > >
> > > > - reg = ep->msi_cap + PCI_MSI_FLAGS;
> > > > + func_offset = dw_pcie_ep_func_select(ep, func_no);
> > > > +
> > > > + reg = ep->msi_cap + func_offset + PCI_MSI_FLAGS;
> > > > val = dw_pcie_readw_dbi(pci, reg);
> > > > if (!(val & PCI_MSI_FLAGS_ENABLE))
> > > > return -EINVAL;
> > > > @@ -235,11 +267,14 @@ static int dw_pcie_ep_set_msi(struct pci_epc
> > > *epc, u8 func_no, u8 interrupts)
> > > > struct dw_pcie_ep *ep = epc_get_drvdata(epc);
> > > > struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> > > > u32 val, reg;
> > > > + unsigned int func_offset = 0;
> > > >
> > > > if (!ep->msi_cap)
> > > > return -EINVAL;
> > > >
> > > > - reg = ep->msi_cap + PCI_MSI_FLAGS;
> > > > + func_offset = dw_pcie_ep_func_select(ep, func_no);
> > > > +
> > > > + reg = ep->msi_cap + func_offset + PCI_MSI_FLAGS;
> > > > val = dw_pcie_readw_dbi(pci, reg);
> > > > val &= ~PCI_MSI_FLAGS_QMASK;
> > > > val |= (interrupts << 1) & PCI_MSI_FLAGS_QMASK; @@ -255,11 +290,14
> > > > @@ static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no)
> > > > struct dw_pcie_ep *ep = epc_get_drvdata(epc);
> > > > struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> > > > u32 val, reg;
> > > > + unsigned int func_offset = 0;
> > > >
> > > > if (!ep->msix_cap)
> > > > return -EINVAL;
> > > >
> > > > - reg = ep->msix_cap + PCI_MSIX_FLAGS;
> > > > + func_offset = dw_pcie_ep_func_select(ep, func_no);
> > > > +
> > > > + reg = ep->msix_cap + func_offset + PCI_MSIX_FLAGS;
> > > > val = dw_pcie_readw_dbi(pci, reg);
> > > > if (!(val & PCI_MSIX_FLAGS_ENABLE))
> > > > return -EINVAL;
> > > > @@ -274,11 +312,14 @@ static int dw_pcie_ep_set_msix(struct pci_epc
> > > *epc, u8 func_no, u16 interrupts)
> > > > struct dw_pcie_ep *ep = epc_get_drvdata(epc);
> > > > struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> > > > u32 val, reg;
> > > > + unsigned int func_offset = 0;
> > > >
> > > > if (!ep->msix_cap)
> > > > return -EINVAL;
> > > >
> > > > - reg = ep->msix_cap + PCI_MSIX_FLAGS;
> > > > + func_offset = dw_pcie_ep_func_select(ep, func_no);
> > > > +
> > > > + reg = ep->msix_cap + func_offset + PCI_MSIX_FLAGS;
> > > > val = dw_pcie_readw_dbi(pci, reg);
> > > > val &= ~PCI_MSIX_FLAGS_QSIZE;
> > > > val |= interrupts;
> > > > @@ -365,6 +406,7 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep
> > > *ep, u8 func_no,
> > > > struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> > > > struct pci_epc *epc = ep->epc;
> > > > unsigned int aligned_offset;
> > > > + unsigned int func_offset = 0;
> > > > u16 msg_ctrl, msg_data;
> > > > u32 msg_addr_lower, msg_addr_upper, reg;
> > > > u64 msg_addr;
> > > > @@ -374,20 +416,22 @@ int dw_pcie_ep_raise_msi_irq(struct
> > > dw_pcie_ep *ep, u8 func_no,
> > > > if (!ep->msi_cap)
> > > > return -EINVAL;
> > > >
> > > > + func_offset = dw_pcie_ep_func_select(ep, func_no);
> > > > +
> > > > /* Raise MSI per the PCI Local Bus Specification Revision 3.0, 6.8.1. */
> > > > - reg = ep->msi_cap + PCI_MSI_FLAGS;
> > > > + reg = ep->msi_cap + func_offset + PCI_MSI_FLAGS;
> > > > msg_ctrl = dw_pcie_readw_dbi(pci, reg);
> > > > has_upper = !!(msg_ctrl & PCI_MSI_FLAGS_64BIT);
> > > > - reg = ep->msi_cap + PCI_MSI_ADDRESS_LO;
> > > > + reg = ep->msi_cap + func_offset + PCI_MSI_ADDRESS_LO;
> > > > msg_addr_lower = dw_pcie_readl_dbi(pci, reg);
> > > > if (has_upper) {
> > > > - reg = ep->msi_cap + PCI_MSI_ADDRESS_HI;
> > > > + reg = ep->msi_cap + func_offset + PCI_MSI_ADDRESS_HI;
> > > > msg_addr_upper = dw_pcie_readl_dbi(pci, reg);
> > > > - reg = ep->msi_cap + PCI_MSI_DATA_64;
> > > > + reg = ep->msi_cap + func_offset + PCI_MSI_DATA_64;
> > > > msg_data = dw_pcie_readw_dbi(pci, reg);
> > > > } else {
> > > > msg_addr_upper = 0;
> > > > - reg = ep->msi_cap + PCI_MSI_DATA_32;
> > > > + reg = ep->msi_cap + func_offset + PCI_MSI_DATA_32;
> > > > msg_data = dw_pcie_readw_dbi(pci, reg);
> > > > }
> > > > aligned_offset = msg_addr_lower & (epc->mem->page_size - 1); @@
> > > > -406,11 +450,12 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep,
> > > > u8 func_no, }
> > > >
> > > > int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
> > > > - u16 interrupt_num)
> > > > + u16 interrupt_num)
> > > > {
> > > > struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> > > > struct pci_epc *epc = ep->epc;
> > > > u16 tbl_offset, bir;
> > > > + unsigned int func_offset = 0;
> > > > u32 bar_addr_upper, bar_addr_lower;
> > > > u32 msg_addr_upper, msg_addr_lower;
> > > > u32 reg, msg_data, vec_ctrl;
> > > > @@ -418,12 +463,14 @@ int dw_pcie_ep_raise_msix_irq(struct
> > > dw_pcie_ep *ep, u8 func_no,
> > > > void __iomem *msix_tbl;
> > > > int ret;
> > > >
> > > > - reg = ep->msix_cap + PCI_MSIX_TABLE;
> > > > + func_offset = dw_pcie_ep_func_select(ep, func_no);
> > > > +
> > > > + reg = ep->msix_cap + func_offset + PCI_MSIX_TABLE;
> > > > tbl_offset = dw_pcie_readl_dbi(pci, reg);
> > > > bir = (tbl_offset & PCI_MSIX_TABLE_BIR);
> > > > tbl_offset &= PCI_MSIX_TABLE_OFFSET;
> > > >
> > > > - reg = PCI_BASE_ADDRESS_0 + (4 * bir);
> > > > + reg = PCI_BASE_ADDRESS_0 + func_offset + (4 * bir);
> > > > bar_addr_upper = 0;
> > > > bar_addr_lower = dw_pcie_readl_dbi(pci, reg);
> > > > reg_u64 = (bar_addr_lower & PCI_BASE_ADDRESS_MEM_TYPE_MASK);
> > > @@
> > > > -559,13 +606,13 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
> > > > ep->epc = epc;
> > > > epc_set_drvdata(epc, ep);
> > > >
> > > > - if (ep->ops->ep_init)
> > > > - ep->ops->ep_init(ep);
> > > > -
> > > > ret = of_property_read_u8(np, "max-functions", &epc->max_functions);
> > > > if (ret < 0)
> > > > epc->max_functions = 1;
> > > >
> > > > + if (ep->ops->ep_init)
> > > > + ep->ops->ep_init(ep);
> > > > +
> > > > ret = __pci_epc_mem_init(epc, ep->phys_base, ep->addr_size,
> > > > ep->page_size);
> > > > if (ret < 0) {
> > > > diff --git a/drivers/pci/controller/dwc/pcie-designware.c
> > > > b/drivers/pci/controller/dwc/pcie-designware.c
> > > > index 143cb6c..ede2e75 100644
> > > > --- a/drivers/pci/controller/dwc/pcie-designware.c
> > > > +++ b/drivers/pci/controller/dwc/pcie-designware.c
> > > > @@ -238,9 +238,10 @@ static void dw_pcie_writel_ob_unroll(struct
> > > dw_pcie *pci, u32 index, u32 reg,
> > > > dw_pcie_writel_atu(pci, offset + reg, val); }
> > > >
> > > > -static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int
> > > index,
> > > > - int type, u64 cpu_addr,
> > > > - u64 pci_addr, u32 size)
> > > > +static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, u8
> > > func_no,
> > > > + int index, int type,
> > > > + u64 cpu_addr, u64 pci_addr,
> > > > + u32 size)
> > > > {
> > > > u32 retries, val;
> > > >
> > > > @@ -255,7 +256,7 @@ static void
> > > dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index,
> > > > dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
> > > > upper_32_bits(pci_addr));
> > > > dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
> > > > - type);
> > > > + type | PCIE_ATU_FUNC_NUM(func_no));
> > > > dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
> > > > PCIE_ATU_ENABLE);
> > > >
> > > > @@ -274,8 +275,9 @@ static void
> > > dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index,
> > > > dev_err(pci->dev, "Outbound iATU is not being enabled\n"); }
> > > >
> > > > -void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
> > > > - u64 cpu_addr, u64 pci_addr, u32 size)
> > > > +static void __dw_pcie_prog_outbound_atu(struct dw_pcie *pci, u8
> > > func_no,
> > > > + int index, int type, u64 cpu_addr,
> > > > + u64 pci_addr, u32 size)
> > > > {
> > > > u32 retries, val;
> > > >
> > > > @@ -283,8 +285,8 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie
> > > *pci, int index, int type,
> > > > cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
> > > >
> > > > if (pci->iatu_unroll_enabled) {
> > > > - dw_pcie_prog_outbound_atu_unroll(pci, index, type, cpu_addr,
> > > > - pci_addr, size);
> > > > + dw_pcie_prog_outbound_atu_unroll(pci, func_no, index, type,
> > > > + cpu_addr, pci_addr, size);
> > > > return;
> > > > }
> > > >
> > > > @@ -300,7 +302,8 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie
> > > *pci, int index, int type,
> > > > lower_32_bits(pci_addr));
> > > > dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET,
> > > > upper_32_bits(pci_addr));
> > > > - dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type);
> > > > + dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type |
> > > > + PCIE_ATU_FUNC_NUM(func_no));
> > > > dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE);
> > > >
> > > > /*
> > > > @@ -317,6 +320,21 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie
> > > *pci, int index, int type,
> > > > dev_err(pci->dev, "Outbound iATU is not being enabled\n"); }
> > > >
> > > > +void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
> > > > + u64 cpu_addr, u64 pci_addr, u32 size) {
> > > > + __dw_pcie_prog_outbound_atu(pci, 0, index, type,
> > > > + cpu_addr, pci_addr, size);
> > > > +}
> > > > +
> > > > +void dw_pcie_prog_ep_outbound_atu(struct dw_pcie *pci, u8 func_no, int
> > > index,
> > > > + int type, u64 cpu_addr, u64 pci_addr,
> > > > + u32 size)
> > > > +{
> > > > + __dw_pcie_prog_outbound_atu(pci, func_no, index, type,
> > > > + cpu_addr, pci_addr, size);
> > > > +}
> > > > +
> > > > static u32 dw_pcie_readl_ib_unroll(struct dw_pcie *pci, u32 index,
> > > > u32 reg) {
> > > > u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
> > > > @@ -332,8 +350,8 @@ static void dw_pcie_writel_ib_unroll(struct dw_pcie
> > > *pci, u32 index, u32 reg,
> > > > dw_pcie_writel_atu(pci, offset + reg, val); }
> > > >
> > > > -static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index,
> > > > - int bar, u64 cpu_addr,
> > > > +static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, u8
> > > func_no,
> > > > + int index, int bar, u64 cpu_addr,
> > > > enum dw_pcie_as_type as_type) {
> > > > int type;
> > > > @@ -355,8 +373,10 @@ static int dw_pcie_prog_inbound_atu_unroll(struct
> > > dw_pcie *pci, int index,
> > > > return -EINVAL;
> > > > }
> > > >
> > > > - dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
> > > type);
> > > > + dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
> > > type |
> > > > + PCIE_ATU_FUNC_NUM(func_no));
> > > > dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
> > > > + PCIE_ATU_FUNC_NUM_MATCH_EN |
> > > > PCIE_ATU_ENABLE |
> > > > PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
> > > >
> > > > @@ -377,14 +397,15 @@ static int
> > > dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index,
> > > > return -EBUSY;
> > > > }
> > > >
> > > > -int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int bar,
> > > > - u64 cpu_addr, enum dw_pcie_as_type as_type)
> > > > +int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
> > > > + int bar, u64 cpu_addr,
> > > > + enum dw_pcie_as_type as_type)
> > > > {
> > > > int type;
> > > > u32 retries, val;
> > > >
> > > > if (pci->iatu_unroll_enabled)
> > > > - return dw_pcie_prog_inbound_atu_unroll(pci, index, bar,
> > > > + return dw_pcie_prog_inbound_atu_unroll(pci, func_no, index, bar,
> > > > cpu_addr, as_type);
> > > >
> > > > dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT,
> > > PCIE_ATU_REGION_INBOUND |
> > > > @@ -403,9 +424,11 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie
> > > *pci, int index, int bar,
> > > > return -EINVAL;
> > > > }
> > > >
> > > > - dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type);
> > > > - dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE
> > > > - | PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
> > > > + dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type |
> > > > + PCIE_ATU_FUNC_NUM(func_no));
> > > > + dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE |
> > > > + PCIE_ATU_FUNC_NUM_MATCH_EN |
> > > > + PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
> > > >
> > > > /*
> > > > * Make sure ATU enable takes effect before any subsequent config
> > > > diff --git a/drivers/pci/controller/dwc/pcie-designware.h
> > > > b/drivers/pci/controller/dwc/pcie-designware.h
> > > > index 5a18e94..6aca0bb 100644
> > > > --- a/drivers/pci/controller/dwc/pcie-designware.h
> > > > +++ b/drivers/pci/controller/dwc/pcie-designware.h
> > > > @@ -71,9 +71,11 @@
> > > > #define PCIE_ATU_TYPE_IO 0x2
> > > > #define PCIE_ATU_TYPE_CFG0 0x4
> > > > #define PCIE_ATU_TYPE_CFG1 0x5
> > > > +#define PCIE_ATU_FUNC_NUM(pf) ((pf) << 20)
> > > > #define PCIE_ATU_CR2 0x908
> > > > #define PCIE_ATU_ENABLE BIT(31)
> > > > #define PCIE_ATU_BAR_MODE_ENABLE BIT(30)
> > > > +#define PCIE_ATU_FUNC_NUM_MATCH_EN BIT(19)
> > > > #define PCIE_ATU_LOWER_BASE 0x90C
> > > > #define PCIE_ATU_UPPER_BASE 0x910
> > > > #define PCIE_ATU_LIMIT 0x914
> > > > @@ -206,6 +208,14 @@ struct dw_pcie_ep_ops {
> > > > int (*raise_irq)(struct dw_pcie_ep *ep, u8 func_no,
> > > > enum pci_epc_irq_type type, u16 interrupt_num);
> > > > const struct pci_epc_features* (*get_features)(struct dw_pcie_ep
> > > > *ep);
> > > > + /*
> > > > + * Provide a method to implement the different func config space
> > > > + * access for different platform, if different func have different
> > > > + * offset, return the offset of func. if use write a register way
> > > > + * return a 0, and implement code in callback function of platform
> > > > + * driver.
> > > > + */
> > > > + unsigned int (*func_conf_select)(struct dw_pcie_ep *ep, u8 func_no);
> > > > };
> > > >
> > > > struct dw_pcie_ep {
> > > > @@ -277,8 +287,12 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci);
> > > > void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index,
> > > > int type, u64 cpu_addr, u64 pci_addr,
> > > > u32 size);
> > > > -int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int bar,
> > > > - u64 cpu_addr, enum dw_pcie_as_type as_type);
> > > > +void dw_pcie_prog_ep_outbound_atu(struct dw_pcie *pci, u8 func_no, int
> > > index,
> > > > + int type, u64 cpu_addr, u64 pci_addr,
> > > > + u32 size);
> > > > +int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
> > > > + int bar, u64 cpu_addr,
> > > > + enum dw_pcie_as_type as_type);
> > > > void dw_pcie_disable_atu(struct dw_pcie *pci, int index,
> > > > enum dw_pcie_region_type type);
> > > > void dw_pcie_setup(struct dw_pcie *pci);
> > > > --
> > > > 2.9.5
> > > >
> > > >
> > > > _______________________________________________
> > > > linux-arm-kernel mailing list
> > > > linux-arm-kernel@lists.infradead.org
> > > > https://urldefense.proofpoint.com/v2/url?u=https-3A__eur01.safelinks.protection.outlook.com_-3Furl-3Dhttp-253A-252F-252Flists&d=DwIDaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=bkWxpLoW-f-E3EdiDCCa0_h0PicsViasSlvIpzZvPxs&m=5KEPBnDGAa12Ywyt1Lmak3JdU8Sb2dXNFJ0Q8OZFOrk&s=SOL5A-18vfzblTMMJojZKBLwCjZIi9g5VBreF5sN1do&e=
> > > > .infradead.org%2Fmailman%2Flistinfo%2Flinux-arm-kernel&data=02%
> > > 7C0
> > > >
> > > 1%7Cxiaowei.bao%40nxp.com%7C99eef14a525040ed3eab08d72fc244f1%7C
> > > 686ea1d
> > > >
> > > 3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637030383769341270&sd
> > > ata=ck2EC
> > > > %2FJYCjWErvbUM%2FT%2BoVMANMwyLRI4gVRssdnd04w%3D&reser
> > > ved=0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 11/11] PCI: rcar: Use inbound resources for setup
From: Andrew Murray @ 2019-09-26 13:32 UTC (permalink / raw)
To: Rob Herring
Cc: Bjorn Helgaas, linux-pci, Lorenzo Pieralisi,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
Simon Horman
In-Reply-To: <CAL_Jsq+5cbPd_7Yoo6DvK9LFwf-npChWxRPMq-TtqFSALbXuDw@mail.gmail.com>
On Thu, Sep 26, 2019 at 07:53:20AM -0500, Rob Herring wrote:
> On Thu, Sep 26, 2019 at 3:47 AM Andrew Murray <andrew.murray@arm.com> wrote:
> >
> > On Tue, Sep 24, 2019 at 04:46:30PM -0500, Rob Herring wrote:
> > > Now that the helpers provide the inbound resources in the host bridge
> > > 'dma_ranges' resource list, convert Renesas R-Car PCIe host bridge to
> > > use the resource list to setup the inbound addresses.
> > >
> > > Cc: Simon Horman <horms@verge.net.au>
> > > Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > > Cc: Bjorn Helgaas <bhelgaas@google.com>
> > > Signed-off-by: Rob Herring <robh@kernel.org>
> > > ---
> > > drivers/pci/controller/pcie-rcar.c | 45 +++++++++++-------------------
> > > 1 file changed, 16 insertions(+), 29 deletions(-)
> > >
> > > diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c
> > > index b8d6e86a5539..453c931aaf77 100644
> > > --- a/drivers/pci/controller/pcie-rcar.c
> > > +++ b/drivers/pci/controller/pcie-rcar.c
> > > @@ -1014,16 +1014,16 @@ static int rcar_pcie_get_resources(struct rcar_pcie *pcie)
> > > }
> > >
> > > static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
> > > - struct of_pci_range *range,
> > > + struct resource_entry *entry,
> > > int *index)
> > > {
> > > - u64 restype = range->flags;
> > > - u64 cpu_addr = range->cpu_addr;
> > > - u64 cpu_end = range->cpu_addr + range->size;
> > > - u64 pci_addr = range->pci_addr;
> > > + u64 restype = entry->res->flags;
> > > + u64 cpu_addr = entry->res->start;
> > > + u64 cpu_end = entry->res->end;
> > > + u64 pci_addr = entry->res->start - entry->offset;
> > > u32 flags = LAM_64BIT | LAR_ENABLE;
> > > u64 mask;
> > > - u64 size;
> > > + u64 size = resource_size(entry->res);
> > > int idx = *index;
> > >
> > > if (restype & IORESOURCE_PREFETCH)
> > > @@ -1037,9 +1037,7 @@ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
> > > unsigned long nr_zeros = __ffs64(cpu_addr);
> > > u64 alignment = 1ULL << nr_zeros;
> > >
> > > - size = min(range->size, alignment);
> > > - } else {
> > > - size = range->size;
> > > + size = min(size, alignment);
> > > }
> >
> > AFAICT the (if cpu_addr > 0) is here because the result of __ffs64 is undefined
> > if no bits are set (according to the comment). However by removing the else
> > statement we no longer guarantee that nr_zeros is defined.
>
> You might want to read this again...
>
> The 'if (cpu_addr > 0) {' is still there and nr_zeros is only under
> that condition. We just init 'size' instead of setting it in the else
> clause.
Ah yes, apologies for the noise, thanks for your patience.
Andrew Murray
>
> Rob
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* RE: [PATCH v4 01/11] PCI: designware-ep: Add multiple PFs support for DWC
From: Gustavo Pimentel @ 2019-09-26 13:27 UTC (permalink / raw)
To: Xiaowei Bao, robh+dt@kernel.org, mark.rutland@arm.com,
shawnguo@kernel.org, leoyang.li@nxp.com, kishon@ti.com,
lorenzo.pieralisi@arm.com, minghuan.Lian@nxp.com,
mingkai.hu@nxp.com, roy.zang@nxp.com, jingoohan1@gmail.com,
gustavo.pimentel@synopsys.com, andrew.murray@arm.com,
linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20190924021849.3185-2-xiaowei.bao@nxp.com>
On Tue, Sep 24, 2019 at 3:18:39, Xiaowei Bao <xiaowei.bao@nxp.com> wrote:
> Add multiple PFs support for DWC, due to different PF have different
> config space, we use func_conf_select callback function to access
> the different PF's config space, the different chip company need to
> implement this callback function when use the DWC IP core and intend
> to support multiple PFs feature.
>
> Signed-off-by: Xiaowei Bao <xiaowei.bao@nxp.com>
> ---
> v2:
> - Remove duplicate redundant code.
> - Reimplement the PF config space access way.
> v3:
> - Integrate duplicate code for func_select.
> - Move PCIE_ATU_FUNC_NUM(pf) (pf << 20) to ((pf) << 20).
> - Add the comments for func_conf_select function.
> v4:
> - Correct the commit message.
>
> drivers/pci/controller/dwc/pcie-designware-ep.c | 123 ++++++++++++++++--------
> drivers/pci/controller/dwc/pcie-designware.c | 59 ++++++++----
> drivers/pci/controller/dwc/pcie-designware.h | 18 +++-
> 3 files changed, 142 insertions(+), 58 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index 65f4792..eb851c2 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -19,12 +19,26 @@ void dw_pcie_ep_linkup(struct dw_pcie_ep *ep)
> pci_epc_linkup(epc);
> }
>
> -static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar,
> - int flags)
> +static unsigned int dw_pcie_ep_func_select(struct dw_pcie_ep *ep, u8 func_no)
> +{
> + unsigned int func_offset = 0;
> +
> + if (ep->ops->func_conf_select)
> + func_offset = ep->ops->func_conf_select(ep, func_no);
> +
> + return func_offset;
> +}
> +
> +static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, u8 func_no,
> + enum pci_barno bar, int flags)
> {
> u32 reg;
> + unsigned int func_offset = 0;
> + struct dw_pcie_ep *ep = &pci->ep;
> +
> + func_offset = dw_pcie_ep_func_select(ep, func_no);
>
> - reg = PCI_BASE_ADDRESS_0 + (4 * bar);
> + reg = func_offset + PCI_BASE_ADDRESS_0 + (4 * bar);
> dw_pcie_dbi_ro_wr_en(pci);
> dw_pcie_writel_dbi2(pci, reg, 0x0);
> dw_pcie_writel_dbi(pci, reg, 0x0);
> @@ -37,7 +51,12 @@ static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar,
>
> void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)
> {
> - __dw_pcie_ep_reset_bar(pci, bar, 0);
> + u8 func_no, funcs;
> +
> + funcs = pci->ep.epc->max_functions;
> +
> + for (func_no = 0; func_no < funcs; func_no++)
> + __dw_pcie_ep_reset_bar(pci, func_no, bar, 0);
> }
>
> static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no,
> @@ -45,28 +64,31 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no,
> {
> struct dw_pcie_ep *ep = epc_get_drvdata(epc);
> struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> + unsigned int func_offset = 0;
> +
> + func_offset = dw_pcie_ep_func_select(ep, func_no);
>
> dw_pcie_dbi_ro_wr_en(pci);
> - dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, hdr->vendorid);
> - dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, hdr->deviceid);
> - dw_pcie_writeb_dbi(pci, PCI_REVISION_ID, hdr->revid);
> - dw_pcie_writeb_dbi(pci, PCI_CLASS_PROG, hdr->progif_code);
> - dw_pcie_writew_dbi(pci, PCI_CLASS_DEVICE,
> + dw_pcie_writew_dbi(pci, func_offset + PCI_VENDOR_ID, hdr->vendorid);
> + dw_pcie_writew_dbi(pci, func_offset + PCI_DEVICE_ID, hdr->deviceid);
> + dw_pcie_writeb_dbi(pci, func_offset + PCI_REVISION_ID, hdr->revid);
> + dw_pcie_writeb_dbi(pci, func_offset + PCI_CLASS_PROG, hdr->progif_code);
> + dw_pcie_writew_dbi(pci, func_offset + PCI_CLASS_DEVICE,
> hdr->subclass_code | hdr->baseclass_code << 8);
> - dw_pcie_writeb_dbi(pci, PCI_CACHE_LINE_SIZE,
> + dw_pcie_writeb_dbi(pci, func_offset + PCI_CACHE_LINE_SIZE,
> hdr->cache_line_size);
> - dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_VENDOR_ID,
> + dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_VENDOR_ID,
> hdr->subsys_vendor_id);
> - dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_ID, hdr->subsys_id);
> - dw_pcie_writeb_dbi(pci, PCI_INTERRUPT_PIN,
> + dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_ID, hdr->subsys_id);
> + dw_pcie_writeb_dbi(pci, func_offset + PCI_INTERRUPT_PIN,
> hdr->interrupt_pin);
> dw_pcie_dbi_ro_wr_dis(pci);
>
> return 0;
> }
>
> -static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,
> - dma_addr_t cpu_addr,
> +static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no,
> + enum pci_barno bar, dma_addr_t cpu_addr,
> enum dw_pcie_as_type as_type)
> {
> int ret;
> @@ -79,7 +101,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,
> return -EINVAL;
> }
>
> - ret = dw_pcie_prog_inbound_atu(pci, free_win, bar, cpu_addr,
> + ret = dw_pcie_prog_inbound_atu(pci, func_no, free_win, bar, cpu_addr,
> as_type);
> if (ret < 0) {
> dev_err(pci->dev, "Failed to program IB window\n");
> @@ -92,7 +114,8 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,
> return 0;
> }
>
> -static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, phys_addr_t phys_addr,
> +static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, u8 func_no,
> + phys_addr_t phys_addr,
> u64 pci_addr, size_t size)
> {
> u32 free_win;
> @@ -104,8 +127,8 @@ static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, phys_addr_t phys_addr,
> return -EINVAL;
> }
>
> - dw_pcie_prog_outbound_atu(pci, free_win, PCIE_ATU_TYPE_MEM,
> - phys_addr, pci_addr, size);
> + dw_pcie_prog_ep_outbound_atu(pci, func_no, free_win, PCIE_ATU_TYPE_MEM,
> + phys_addr, pci_addr, size);
>
> set_bit(free_win, ep->ob_window_map);
> ep->outbound_addr[free_win] = phys_addr;
> @@ -121,7 +144,7 @@ static void dw_pcie_ep_clear_bar(struct pci_epc *epc, u8 func_no,
> enum pci_barno bar = epf_bar->barno;
> u32 atu_index = ep->bar_to_atu[bar];
>
> - __dw_pcie_ep_reset_bar(pci, bar, epf_bar->flags);
> + __dw_pcie_ep_reset_bar(pci, func_no, bar, epf_bar->flags);
>
> dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_INBOUND);
> clear_bit(atu_index, ep->ib_window_map);
> @@ -137,14 +160,20 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no,
> size_t size = epf_bar->size;
> int flags = epf_bar->flags;
> enum dw_pcie_as_type as_type;
> - u32 reg = PCI_BASE_ADDRESS_0 + (4 * bar);
> + u32 reg;
> + unsigned int func_offset = 0;
> +
> + func_offset = dw_pcie_ep_func_select(ep, func_no);
> +
> + reg = PCI_BASE_ADDRESS_0 + (4 * bar) + func_offset;
>
> if (!(flags & PCI_BASE_ADDRESS_SPACE))
> as_type = DW_PCIE_AS_MEM;
> else
> as_type = DW_PCIE_AS_IO;
>
> - ret = dw_pcie_ep_inbound_atu(ep, bar, epf_bar->phys_addr, as_type);
> + ret = dw_pcie_ep_inbound_atu(ep, func_no, bar,
> + epf_bar->phys_addr, as_type);
> if (ret)
> return ret;
>
> @@ -202,7 +231,7 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no,
> struct dw_pcie_ep *ep = epc_get_drvdata(epc);
> struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
>
> - ret = dw_pcie_ep_outbound_atu(ep, addr, pci_addr, size);
> + ret = dw_pcie_ep_outbound_atu(ep, func_no, addr, pci_addr, size);
> if (ret) {
> dev_err(pci->dev, "Failed to enable address\n");
> return ret;
> @@ -216,11 +245,14 @@ static int dw_pcie_ep_get_msi(struct pci_epc *epc, u8 func_no)
> struct dw_pcie_ep *ep = epc_get_drvdata(epc);
> struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> u32 val, reg;
> + unsigned int func_offset = 0;
>
> if (!ep->msi_cap)
> return -EINVAL;
>
> - reg = ep->msi_cap + PCI_MSI_FLAGS;
> + func_offset = dw_pcie_ep_func_select(ep, func_no);
> +
> + reg = ep->msi_cap + func_offset + PCI_MSI_FLAGS;
> val = dw_pcie_readw_dbi(pci, reg);
> if (!(val & PCI_MSI_FLAGS_ENABLE))
> return -EINVAL;
> @@ -235,11 +267,14 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts)
> struct dw_pcie_ep *ep = epc_get_drvdata(epc);
> struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> u32 val, reg;
> + unsigned int func_offset = 0;
>
> if (!ep->msi_cap)
> return -EINVAL;
>
> - reg = ep->msi_cap + PCI_MSI_FLAGS;
> + func_offset = dw_pcie_ep_func_select(ep, func_no);
> +
> + reg = ep->msi_cap + func_offset + PCI_MSI_FLAGS;
> val = dw_pcie_readw_dbi(pci, reg);
> val &= ~PCI_MSI_FLAGS_QMASK;
> val |= (interrupts << 1) & PCI_MSI_FLAGS_QMASK;
> @@ -255,11 +290,14 @@ static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no)
> struct dw_pcie_ep *ep = epc_get_drvdata(epc);
> struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> u32 val, reg;
> + unsigned int func_offset = 0;
>
> if (!ep->msix_cap)
> return -EINVAL;
>
> - reg = ep->msix_cap + PCI_MSIX_FLAGS;
> + func_offset = dw_pcie_ep_func_select(ep, func_no);
> +
> + reg = ep->msix_cap + func_offset + PCI_MSIX_FLAGS;
> val = dw_pcie_readw_dbi(pci, reg);
> if (!(val & PCI_MSIX_FLAGS_ENABLE))
> return -EINVAL;
> @@ -274,11 +312,14 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts)
> struct dw_pcie_ep *ep = epc_get_drvdata(epc);
> struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> u32 val, reg;
> + unsigned int func_offset = 0;
>
> if (!ep->msix_cap)
> return -EINVAL;
>
> - reg = ep->msix_cap + PCI_MSIX_FLAGS;
> + func_offset = dw_pcie_ep_func_select(ep, func_no);
> +
> + reg = ep->msix_cap + func_offset + PCI_MSIX_FLAGS;
> val = dw_pcie_readw_dbi(pci, reg);
> val &= ~PCI_MSIX_FLAGS_QSIZE;
> val |= interrupts;
> @@ -365,6 +406,7 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
> struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> struct pci_epc *epc = ep->epc;
> unsigned int aligned_offset;
> + unsigned int func_offset = 0;
> u16 msg_ctrl, msg_data;
> u32 msg_addr_lower, msg_addr_upper, reg;
> u64 msg_addr;
> @@ -374,20 +416,22 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
> if (!ep->msi_cap)
> return -EINVAL;
>
> + func_offset = dw_pcie_ep_func_select(ep, func_no);
> +
> /* Raise MSI per the PCI Local Bus Specification Revision 3.0, 6.8.1. */
> - reg = ep->msi_cap + PCI_MSI_FLAGS;
> + reg = ep->msi_cap + func_offset + PCI_MSI_FLAGS;
> msg_ctrl = dw_pcie_readw_dbi(pci, reg);
> has_upper = !!(msg_ctrl & PCI_MSI_FLAGS_64BIT);
> - reg = ep->msi_cap + PCI_MSI_ADDRESS_LO;
> + reg = ep->msi_cap + func_offset + PCI_MSI_ADDRESS_LO;
> msg_addr_lower = dw_pcie_readl_dbi(pci, reg);
> if (has_upper) {
> - reg = ep->msi_cap + PCI_MSI_ADDRESS_HI;
> + reg = ep->msi_cap + func_offset + PCI_MSI_ADDRESS_HI;
> msg_addr_upper = dw_pcie_readl_dbi(pci, reg);
> - reg = ep->msi_cap + PCI_MSI_DATA_64;
> + reg = ep->msi_cap + func_offset + PCI_MSI_DATA_64;
> msg_data = dw_pcie_readw_dbi(pci, reg);
> } else {
> msg_addr_upper = 0;
> - reg = ep->msi_cap + PCI_MSI_DATA_32;
> + reg = ep->msi_cap + func_offset + PCI_MSI_DATA_32;
> msg_data = dw_pcie_readw_dbi(pci, reg);
> }
> aligned_offset = msg_addr_lower & (epc->mem->page_size - 1);
> @@ -406,11 +450,12 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
> }
>
> int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
> - u16 interrupt_num)
> + u16 interrupt_num)
> {
> struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> struct pci_epc *epc = ep->epc;
> u16 tbl_offset, bir;
> + unsigned int func_offset = 0;
> u32 bar_addr_upper, bar_addr_lower;
> u32 msg_addr_upper, msg_addr_lower;
> u32 reg, msg_data, vec_ctrl;
> @@ -418,12 +463,14 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
> void __iomem *msix_tbl;
> int ret;
>
> - reg = ep->msix_cap + PCI_MSIX_TABLE;
> + func_offset = dw_pcie_ep_func_select(ep, func_no);
> +
> + reg = ep->msix_cap + func_offset + PCI_MSIX_TABLE;
> tbl_offset = dw_pcie_readl_dbi(pci, reg);
> bir = (tbl_offset & PCI_MSIX_TABLE_BIR);
> tbl_offset &= PCI_MSIX_TABLE_OFFSET;
>
> - reg = PCI_BASE_ADDRESS_0 + (4 * bir);
> + reg = PCI_BASE_ADDRESS_0 + func_offset + (4 * bir);
> bar_addr_upper = 0;
> bar_addr_lower = dw_pcie_readl_dbi(pci, reg);
> reg_u64 = (bar_addr_lower & PCI_BASE_ADDRESS_MEM_TYPE_MASK);
> @@ -559,13 +606,13 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
> ep->epc = epc;
> epc_set_drvdata(epc, ep);
>
> - if (ep->ops->ep_init)
> - ep->ops->ep_init(ep);
> -
> ret = of_property_read_u8(np, "max-functions", &epc->max_functions);
> if (ret < 0)
> epc->max_functions = 1;
>
> + if (ep->ops->ep_init)
> + ep->ops->ep_init(ep);
> +
> ret = __pci_epc_mem_init(epc, ep->phys_base, ep->addr_size,
> ep->page_size);
> if (ret < 0) {
> diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
> index 143cb6c..ede2e75 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.c
> +++ b/drivers/pci/controller/dwc/pcie-designware.c
> @@ -238,9 +238,10 @@ static void dw_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg,
> dw_pcie_writel_atu(pci, offset + reg, val);
> }
>
> -static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index,
> - int type, u64 cpu_addr,
> - u64 pci_addr, u32 size)
> +static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, u8 func_no,
> + int index, int type,
> + u64 cpu_addr, u64 pci_addr,
> + u32 size)
> {
> u32 retries, val;
>
> @@ -255,7 +256,7 @@ static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index,
> dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
> upper_32_bits(pci_addr));
> dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
> - type);
> + type | PCIE_ATU_FUNC_NUM(func_no));
> dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
> PCIE_ATU_ENABLE);
>
> @@ -274,8 +275,9 @@ static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index,
> dev_err(pci->dev, "Outbound iATU is not being enabled\n");
> }
>
> -void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
> - u64 cpu_addr, u64 pci_addr, u32 size)
> +static void __dw_pcie_prog_outbound_atu(struct dw_pcie *pci, u8 func_no,
> + int index, int type, u64 cpu_addr,
> + u64 pci_addr, u32 size)
> {
> u32 retries, val;
>
> @@ -283,8 +285,8 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
> cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
>
> if (pci->iatu_unroll_enabled) {
> - dw_pcie_prog_outbound_atu_unroll(pci, index, type, cpu_addr,
> - pci_addr, size);
> + dw_pcie_prog_outbound_atu_unroll(pci, func_no, index, type,
> + cpu_addr, pci_addr, size);
> return;
> }
>
> @@ -300,7 +302,8 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
> lower_32_bits(pci_addr));
> dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET,
> upper_32_bits(pci_addr));
> - dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type);
> + dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type |
> + PCIE_ATU_FUNC_NUM(func_no));
> dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE);
>
> /*
> @@ -317,6 +320,21 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
> dev_err(pci->dev, "Outbound iATU is not being enabled\n");
> }
>
> +void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
> + u64 cpu_addr, u64 pci_addr, u32 size)
> +{
> + __dw_pcie_prog_outbound_atu(pci, 0, index, type,
> + cpu_addr, pci_addr, size);
> +}
> +
> +void dw_pcie_prog_ep_outbound_atu(struct dw_pcie *pci, u8 func_no, int index,
> + int type, u64 cpu_addr, u64 pci_addr,
> + u32 size)
> +{
> + __dw_pcie_prog_outbound_atu(pci, func_no, index, type,
> + cpu_addr, pci_addr, size);
> +}
> +
> static u32 dw_pcie_readl_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg)
> {
> u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
> @@ -332,8 +350,8 @@ static void dw_pcie_writel_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg,
> dw_pcie_writel_atu(pci, offset + reg, val);
> }
>
> -static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index,
> - int bar, u64 cpu_addr,
> +static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, u8 func_no,
> + int index, int bar, u64 cpu_addr,
> enum dw_pcie_as_type as_type)
> {
> int type;
> @@ -355,8 +373,10 @@ static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index,
> return -EINVAL;
> }
>
> - dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1, type);
> + dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1, type |
> + PCIE_ATU_FUNC_NUM(func_no));
> dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
> + PCIE_ATU_FUNC_NUM_MATCH_EN |
> PCIE_ATU_ENABLE |
> PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
>
> @@ -377,14 +397,15 @@ static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index,
> return -EBUSY;
> }
>
> -int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int bar,
> - u64 cpu_addr, enum dw_pcie_as_type as_type)
> +int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
> + int bar, u64 cpu_addr,
> + enum dw_pcie_as_type as_type)
> {
> int type;
> u32 retries, val;
>
> if (pci->iatu_unroll_enabled)
> - return dw_pcie_prog_inbound_atu_unroll(pci, index, bar,
> + return dw_pcie_prog_inbound_atu_unroll(pci, func_no, index, bar,
> cpu_addr, as_type);
>
> dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, PCIE_ATU_REGION_INBOUND |
> @@ -403,9 +424,11 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int bar,
> return -EINVAL;
> }
>
> - dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type);
> - dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE
> - | PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
> + dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type |
> + PCIE_ATU_FUNC_NUM(func_no));
> + dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE |
> + PCIE_ATU_FUNC_NUM_MATCH_EN |
> + PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
>
> /*
> * Make sure ATU enable takes effect before any subsequent config
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
> index 5a18e94..6aca0bb 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -71,9 +71,11 @@
> #define PCIE_ATU_TYPE_IO 0x2
> #define PCIE_ATU_TYPE_CFG0 0x4
> #define PCIE_ATU_TYPE_CFG1 0x5
> +#define PCIE_ATU_FUNC_NUM(pf) ((pf) << 20)
> #define PCIE_ATU_CR2 0x908
> #define PCIE_ATU_ENABLE BIT(31)
> #define PCIE_ATU_BAR_MODE_ENABLE BIT(30)
> +#define PCIE_ATU_FUNC_NUM_MATCH_EN BIT(19)
> #define PCIE_ATU_LOWER_BASE 0x90C
> #define PCIE_ATU_UPPER_BASE 0x910
> #define PCIE_ATU_LIMIT 0x914
> @@ -206,6 +208,14 @@ struct dw_pcie_ep_ops {
> int (*raise_irq)(struct dw_pcie_ep *ep, u8 func_no,
> enum pci_epc_irq_type type, u16 interrupt_num);
> const struct pci_epc_features* (*get_features)(struct dw_pcie_ep *ep);
> + /*
> + * Provide a method to implement the different func config space
> + * access for different platform, if different func have different
> + * offset, return the offset of func. if use write a register way
> + * return a 0, and implement code in callback function of platform
> + * driver.
> + */
> + unsigned int (*func_conf_select)(struct dw_pcie_ep *ep, u8 func_no);
> };
>
> struct dw_pcie_ep {
> @@ -277,8 +287,12 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci);
> void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index,
> int type, u64 cpu_addr, u64 pci_addr,
> u32 size);
> -int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int bar,
> - u64 cpu_addr, enum dw_pcie_as_type as_type);
> +void dw_pcie_prog_ep_outbound_atu(struct dw_pcie *pci, u8 func_no, int index,
> + int type, u64 cpu_addr, u64 pci_addr,
> + u32 size);
> +int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
> + int bar, u64 cpu_addr,
> + enum dw_pcie_as_type as_type);
> void dw_pcie_disable_atu(struct dw_pcie *pci, int index,
> enum dw_pcie_region_type type);
> void dw_pcie_setup(struct dw_pcie *pci);
> --
> 2.9.5
Acked-by: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] firmware: imx: Skip return value check for some special SCU firmware APIs
From: Leonard Crestez @ 2019-09-26 13:25 UTC (permalink / raw)
To: Marco Felsch, Anson Huang, Aisheng Dong
Cc: shawnguo@kernel.org, s.hauer@pengutronix.de,
linux-kernel@vger.kernel.org, dl-linux-imx, kernel@pengutronix.de,
festevam@gmail.com, linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190926100558.egils3ds37m3s5wo@pengutronix.de>
On 2019-09-26 1:06 PM, Marco Felsch wrote:
> On 19-09-26 08:03, Anson Huang wrote:
>>> On 19-09-25 18:07, Anson Huang wrote:
>>>> The SCU firmware does NOT always have return value stored in message
>>>> header's function element even the API has response data, those
>>>> special APIs are defined as void function in SCU firmware, so they
>>>> should be treated as return success always.
>>>>
>>>> +static const struct imx_sc_rpc_msg whitelist[] = {
>>>> + { .svc = IMX_SC_RPC_SVC_MISC, .func =
>>> IMX_SC_MISC_FUNC_UNIQUE_ID },
>>>> + { .svc = IMX_SC_RPC_SVC_MISC, .func =
>>>> +IMX_SC_MISC_FUNC_GET_BUTTON_STATUS }, };
>>>
>>> Is this going to be extended in the near future? I see some upcoming
>>> problems here if someone uses a different scu-fw<->kernel combination as
>>> nxp would suggest.
>>
>> Could be, but I checked the current APIs, ONLY these 2 will be used in Linux kernel, so
>> I ONLY add these 2 APIs for now.
>
> Okay.
>
>> However, after rethink, maybe we should add another imx_sc_rpc API for those special
>> APIs? To avoid checking it for all the APIs called which may impact some performance.
>> Still under discussion, if you have better idea, please advise, thanks!
My suggestion is to refactor the code and add a new API for the this "no
error value" convention. Internally they can call a common function with
flags.
> Adding a special api shouldn't be the right fix. Imagine if someone (not
> a nxp-developer) wants to add a new driver. How could he be expected to
> know which api he should use. The better abbroach would be to fix the
> scu-fw instead of adding quirks..
Right now developers who want to make SCFW calls in upstream need to
define the message struct in their driver based on protocol
documentation. This includes:
* Binary layout of the message (a packed struct)
* If the message has a response (already a bool flag)
* If an error code is returned (this patch adds support for it)
Since callers are already exposed to the binary protocol exposing them
to minor quirks of the calling convention also seems reasonable. Having
the low-level IPC code peek at message IDs seems like a hack; this
belong at a slightly higher level.
In older internal trees we use a very large amount of generated wrapper
functions. This hides calling convention details from callers but is
extremely ugly and verbose.
--
Regards,
Leonard
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [RFC PATCH 00/18] crypto: wireguard using the existing crypto API
From: Ard Biesheuvel @ 2019-09-26 13:15 UTC (permalink / raw)
To: Pascal Van Leeuwen
Cc: Jason A. Donenfeld, Catalin Marinas, Herbert Xu, Arnd Bergmann,
Eric Biggers, Greg KH, Samuel Neves, Will Deacon,
Linux Crypto Mailing List, Andy Lutomirski, Marc Zyngier,
Dan Carpenter, Linus Torvalds, David Miller, linux-arm-kernel
In-Reply-To: <MN2PR20MB29731267C4670FBD46D6C743CA860@MN2PR20MB2973.namprd20.prod.outlook.com>
On Thu, 26 Sep 2019 at 15:06, Pascal Van Leeuwen
<pvanleeuwen@verimatrix.com> wrote:
...
> >
> > My preference would be to address this by permitting per-request keys
> > in the AEAD layer. That way, we can instantiate the transform only
> > once, and just invoke it with the appropriate key on the hot path (and
> > avoid any per-keypair allocations)
> >
> This part I do not really understand. Why would you need to allocate a
> new transform if you change the key? Why can't you just call setkey()
> on the already allocated transform?
>
Because the single transform will be shared between all users running
on different CPUs etc, and so the key should not be part of the TFM
state but of the request state.
> >
> > It all depends on whether we are interested in supporting async
> > accelerators or not, and it is clear what my position is on this
> > point.
> >
> Maybe not for an initial upstream, but it should be a longer-term goal.
>
> >
> > What I *don't* want is to merge WireGuard with its own library based
> > crypto now, and extend that later for async accelerators once people
> > realize that we really do need that as well.
> >
> What's wrong with a step-by-step approach though? i.e. merge it with
> library calls now and then gradually work towards the goal of integrating
> (a tweaked version of) the Crypto API where that actually makes sense?
> Rome wasn't built in one day either ...
>
I should clarify: what I don't want is two frameworks in the kernel
for doing async crypto, the existing one plus a new library-based one.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 00/11] PCI dma-ranges parsing consolidation
From: Rob Herring @ 2019-09-26 13:11 UTC (permalink / raw)
To: Marc Gonzalez
Cc: Lorenzo Pieralisi, Ard Biesheuvel, Marc Zyngier, Mans Rullgard,
Bjorn Helgaas, PCI, Andrew Murray, Robin Murphy, Linux ARM
In-Reply-To: <036f298c-c65c-7da2-92dc-fc80892672c1@free.fr>
On Thu, Sep 26, 2019 at 6:20 AM Marc Gonzalez <marc.w.gonzalez@free.fr> wrote:
>
> [ Tweaking recipients list ]
>
> On 26/09/2019 10:49, Andrew Murray wrote:
>
> > On Tue, Sep 24, 2019 at 04:46:19PM -0500, Rob Herring wrote:
> >
> >> pci-rcar-gen2 is the only remaining driver doing its own dma-ranges
> >> handling as it is still using the old ARM PCI functions. Looks like it
> >> is the last one (in drivers/pci/).
> >
> > It also seems that pcie-tango is using of_pci_dma_range_parser_init
> > and so parsing dma-ranges. Though it's using the dma_ranges for a
> > slightly different purpose.
Seems I missed that as I only grep'ed for for_each_of_pci_range...
>
> The rationale for that code can be found here:
>
> https://patchwork.kernel.org/patch/9915469/
>
> NB: 1) The PCIE_TANGO_SMP8759 Kconfig symbol is marked "depends on BROKEN",
> and 2) The driver adds TAINT_CRAP,
> and 3) The maker of the tango platform is dead.
Given that and that I'd have to rework the probe to do the MSI range
setup after pci_host_common_probe, I'm just going to leave this one
alone.
Rob
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* RE: [RFC PATCH 00/18] crypto: wireguard using the existing crypto API
From: Pascal Van Leeuwen @ 2019-09-26 13:06 UTC (permalink / raw)
To: Ard Biesheuvel, Jason A. Donenfeld
Cc: Catalin Marinas, Herbert Xu, Arnd Bergmann, Eric Biggers, Greg KH,
Samuel Neves, Will Deacon, Linux Crypto Mailing List,
Andy Lutomirski, Marc Zyngier, Dan Carpenter, Linus Torvalds,
David Miller, linux-arm-kernel
In-Reply-To: <CAKv+Gu-RLRhwDahgvfvr2J9R+3GPM6vh4mjO73VcekusdzbuMA@mail.gmail.com>
> > In this case, the relevance is that the handshake in WireGuard is
> > extremely performance sensitive, in order to fend off DoS. One of the
> > big design gambits in WireGuard is – can we make it 1-RTT to reduce
> > the complexity of the state machine, but keep the crypto efficient
> > enough that this is still safe to do from a DoS perspective. The
> > protocol succeeds at this goal, but in many ways, just by a hair when
> > at scale, and so I’m really quite loathe to decrease handshake
> > performance.
> ...
> > Taken together, we simply can’t skimp on the implementations available
> > on the handshake layer, so we’ll need to add some form of
> > implementation selection, whether it’s the method Zinc uses ([2]), or
> > something else we cook up together.
> >
>
> So are you saying that the handshake timing constraints in the
> WireGuard protocol are so stringent that we can't run it securely on,
> e.g., an ARM CPU that lacks a NEON unit? Or given that you are not
> providing accelerated implementations of blake2s or Curve25519 for
> arm64, we can't run it securely on arm64 at all?
>
> Typically, I would prefer to only introduce different versions of the
> same algorithm if there is a clear performance benefit for an actual
> use case.
>
> Framing this as a security issue rather than a performance issue is
> slightly disingenuous, since people are less likely to challenge it.
> But the security of any VPN protocol worth its salt should not hinge
> on the performance delta between the reference C code and a version
> that was optimized for a particular CPU.
>
Fully agree with that last statement. Security of a protocol should
*never* depend on the performance of a particular implementation.
I may want to run this on a very constrained embedded system that
would necessarily be very slow, and I would still want that to be
secure. If this is true, it's pretty much a deal-breaker to me ...
Which would be a shame, because I really do like some of the other
things Wireguard does and just the effort of improving VPN in general.
> > Issue 2) Linus’ objection to the async API invasion is more correct
> > than he realizes.
> >
> > I could re-enumerate my objections to the API there, but I think we
> > all get it. It’s horrendous looking. Even the introduction of the
> > ivpad member (what on earth?) in the skb cb made me shutter.
>
> Your implementation of RFC7539 truncates the nonce to 64-bits, while
> RFC7539 defines a clear purpose for the bits you omit. Since the Zinc
> library is intended to be standalone (and you are proposing its use in
> other places, like big_keys.c), you might want to document your
> justification for doing so in the general case, instead of ridiculing
> the code I needed to write to work around this limitation.
>
From RFC7539:
"Some protocols may have unique per-invocation inputs that are not 96
bits in length. For example, IPsec may specify a 64-bit nonce. In
such a case, it is up to the protocol document to define how to
transform the protocol nonce into a 96-bit nonce, <<for example, by
concatenating a constant value.>>"
So concatenating zeroes within the protocol is fine (if you can live
with the security consequences) but a generic library function should
of course take all 96 bits as input(!) Actually, the rfc7539esp variant
already takes that part of the nonce from the key, not the IV. This
may be more convenient for use with Wireguard as well? Just force the
trailing nonce portion of the key to zeroes when calling setkey().
>
> My preference would be to address this by permitting per-request keys
> in the AEAD layer. That way, we can instantiate the transform only
> once, and just invoke it with the appropriate key on the hot path (and
> avoid any per-keypair allocations)
>
This part I do not really understand. Why would you need to allocate a
new transform if you change the key? Why can't you just call setkey()
on the already allocated transform?
>
> It all depends on whether we are interested in supporting async
> accelerators or not, and it is clear what my position is on this
> point.
>
Maybe not for an initial upstream, but it should be a longer-term goal.
>
> What I *don't* want is to merge WireGuard with its own library based
> crypto now, and extend that later for async accelerators once people
> realize that we really do need that as well.
>
What's wrong with a step-by-step approach though? i.e. merge it with
library calls now and then gradually work towards the goal of integrating
(a tweaked version of) the Crypto API where that actually makes sense?
Rome wasn't built in one day either ...
Regards,
Pascal van Leeuwen
Silicon IP Architect, Multi-Protocol Engines @ Verimatrix
www.insidesecure.com
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [RFC PATCH v4 2/5] ptp: Reorganize ptp_kvm modules to make it arch-independent.
From: Suzuki K Poulose @ 2019-09-26 13:06 UTC (permalink / raw)
To: Jianyong Wu, netdev, yangbo.lu, john.stultz, tglx, pbonzini,
sean.j.christopherson, maz, richardcochran, Mark.Rutland,
Will.Deacon
Cc: justin.he, kvm, Steve.Capper, linux-kernel, Kaly.Xin, nd, kvmarm,
linux-arm-kernel
In-Reply-To: <20190926114212.5322-3-jianyong.wu@arm.com>
Hi Jianyong,
On 26/09/2019 12:42, Jianyong Wu wrote:
> Currently, ptp_kvm modules implementation is only for x86 which includs
> large part of arch-specific code. This patch move all of those code
> into new arch related file in the same directory.
>
> Signed-off-by: Jianyong Wu <jianyong.wu@arm.com>
> ---
> drivers/ptp/Makefile | 1 +
> drivers/ptp/{ptp_kvm.c => kvm_ptp.c} | 77 ++++++------------------
> drivers/ptp/ptp_kvm_x86.c | 87 ++++++++++++++++++++++++++++
> include/asm-generic/ptp_kvm.h | 12 ++++
> 4 files changed, 118 insertions(+), 59 deletions(-)
> rename drivers/ptp/{ptp_kvm.c => kvm_ptp.c} (63%)
minor nit: Could we not skip renaming the file ? Given
you are following the ptp_kvm_* for the arch specific
files and the header files, wouldn't it be good to
keep ptp_kvm.c ?
Rest looks fine.
Cheers
Suzuki
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 11/11] PCI: rcar: Use inbound resources for setup
From: Rob Herring @ 2019-09-26 12:53 UTC (permalink / raw)
To: Andrew Murray
Cc: Bjorn Helgaas, linux-pci, Lorenzo Pieralisi,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
Simon Horman
In-Reply-To: <20190926084718.GA9720@e119886-lin.cambridge.arm.com>
On Thu, Sep 26, 2019 at 3:47 AM Andrew Murray <andrew.murray@arm.com> wrote:
>
> On Tue, Sep 24, 2019 at 04:46:30PM -0500, Rob Herring wrote:
> > Now that the helpers provide the inbound resources in the host bridge
> > 'dma_ranges' resource list, convert Renesas R-Car PCIe host bridge to
> > use the resource list to setup the inbound addresses.
> >
> > Cc: Simon Horman <horms@verge.net.au>
> > Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > Cc: Bjorn Helgaas <bhelgaas@google.com>
> > Signed-off-by: Rob Herring <robh@kernel.org>
> > ---
> > drivers/pci/controller/pcie-rcar.c | 45 +++++++++++-------------------
> > 1 file changed, 16 insertions(+), 29 deletions(-)
> >
> > diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c
> > index b8d6e86a5539..453c931aaf77 100644
> > --- a/drivers/pci/controller/pcie-rcar.c
> > +++ b/drivers/pci/controller/pcie-rcar.c
> > @@ -1014,16 +1014,16 @@ static int rcar_pcie_get_resources(struct rcar_pcie *pcie)
> > }
> >
> > static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
> > - struct of_pci_range *range,
> > + struct resource_entry *entry,
> > int *index)
> > {
> > - u64 restype = range->flags;
> > - u64 cpu_addr = range->cpu_addr;
> > - u64 cpu_end = range->cpu_addr + range->size;
> > - u64 pci_addr = range->pci_addr;
> > + u64 restype = entry->res->flags;
> > + u64 cpu_addr = entry->res->start;
> > + u64 cpu_end = entry->res->end;
> > + u64 pci_addr = entry->res->start - entry->offset;
> > u32 flags = LAM_64BIT | LAR_ENABLE;
> > u64 mask;
> > - u64 size;
> > + u64 size = resource_size(entry->res);
> > int idx = *index;
> >
> > if (restype & IORESOURCE_PREFETCH)
> > @@ -1037,9 +1037,7 @@ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
> > unsigned long nr_zeros = __ffs64(cpu_addr);
> > u64 alignment = 1ULL << nr_zeros;
> >
> > - size = min(range->size, alignment);
> > - } else {
> > - size = range->size;
> > + size = min(size, alignment);
> > }
>
> AFAICT the (if cpu_addr > 0) is here because the result of __ffs64 is undefined
> if no bits are set (according to the comment). However by removing the else
> statement we no longer guarantee that nr_zeros is defined.
You might want to read this again...
The 'if (cpu_addr > 0) {' is still there and nr_zeros is only under
that condition. We just init 'size' instead of setting it in the else
clause.
Rob
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [RFC PATCH 18/18] net: wireguard - switch to crypto API for packet encryption
From: Ard Biesheuvel @ 2019-09-26 12:34 UTC (permalink / raw)
To: Linus Torvalds
Cc: Jason A . Donenfeld, Catalin Marinas, Herbert Xu, Arnd Bergmann,
Eric Biggers, Greg KH, Samuel Neves, Linux Crypto Mailing List,
Andy Lutomirski, Marc Zyngier, Dan Carpenter, Will Deacon,
David Miller, Linux ARM
In-Reply-To: <CAKv+Gu_YOqvqJ4YC=ixBh-v4fiFTFNpEagHiTRU7Oq4PrhJPkw@mail.gmail.com>
On Thu, 26 Sep 2019 at 13:06, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>
> On Thu, 26 Sep 2019 at 00:15, Linus Torvalds
> <torvalds@linux-foundation.org> wrote:
> >
> > On Wed, Sep 25, 2019 at 9:14 AM Ard Biesheuvel
> > <ard.biesheuvel@linaro.org> wrote:
> > >
> > > Replace the chacha20poly1305() library calls with invocations of the
> > > RFC7539 AEAD, as implemented by the generic chacha20poly1305 template.
> >
> > Honestly, the other patches look fine to me from what I've seen (with
> > the small note I had in a separate email for 11/18), but this one I
> > consider just nasty, and a prime example of why people hate those
> > crypto lookup routines.
> >
> > Some of it is just the fundamental and pointless silly indirection,
> > that just makes things harder to read, less efficient, and less
> > straightforward.
> >
> > That's exemplified by this part of the patch:
> >
> > > struct noise_symmetric_key {
> > > - u8 key[NOISE_SYMMETRIC_KEY_LEN];
> > > + struct crypto_aead *tfm;
> >
> > which is just one of those "we know what we want and we just want to
> > use it directly" things, and then the crypto indirection comes along
> > and makes that simple inline allocation of a small constant size
> > (afaik it is CHACHA20POLY1305_KEY_SIZE, which is 32) be another
> > allocation entirely.
> >
> > And it's some random odd non-typed thing too, so then you have that
> > silly and stupid dynamic allocation using a name lookup:
> >
> > crypto_alloc_aead("rfc7539(chacha20,poly1305)", 0, CRYPTO_ALG_ASYNC);
> >
> > to create what used to be (and should be) a simple allocation that was
> > has a static type and was just part of the code.
> >
>
> That crypto_alloc_aead() call does a lot of things under the hood:
> - use an existing instantiation of rfc7539(chacha20,poly1305) if available,
> - look for modules that implement the whole transformation directly,
> - if none are found, instantiate the rfc7539 template, which will
> essentially do the above for chacha20 and poly1305, potentially using
> per-arch accelerated implementations if available (for either), or
> otherwise, fall back to the generic versions.
>
> What *I* see as the issue here is not that we need to do this at all,
> but that we have to do it for each value of the key. IMO, it would be
> much better to instantiate this thing only once, and have a way of
> passing a per-request key into it, permitting us to hide the whole
> thing behind the existing library interface.
>
Note that we don't have to do the whole dance for each new value of
the key: subsequent invocations will all succeed at step #1, and grab
the existing instantiation, but allocate a new TFM structure that
refers to it. It is this step that we should be able to omit as well
if the API is changed to allow per-request keys to be passed in via
the request structure.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v10 0/6] mm / virtio: Provide support for unused page reporting
From: Michal Hocko @ 2019-09-26 12:22 UTC (permalink / raw)
To: Alexander Duyck
Cc: Yang Zhang, Pankaj Gupta, kvm list, David Hildenbrand,
lcapitulino, linux-mm, Alexander Duyck, Andrea Arcangeli,
virtio-dev, Michael S. Tsirkin, Matthew Wilcox, Wang, Wei W,
Vlastimil Babka, Rik van Riel, Dan Williams, linux-arm-kernel,
Oscar Salvador, Nitesh Narayan Lal, Konrad Rzeszutek Wilk,
Dave Hansen, LKML, Paolo Bonzini, Andrew Morton, Mel Gorman
In-Reply-To: <CAKgT0UcYdA+LysVVO+8Beabsd-YBH+tNUKnQgaFmrZBW1xkFxA@mail.gmail.com>
On Tue 24-09-19 08:20:22, Alexander Duyck wrote:
> On Tue, Sep 24, 2019 at 7:23 AM Michal Hocko <mhocko@kernel.org> wrote:
> >
> > On Wed 18-09-19 10:52:25, Alexander Duyck wrote:
> > [...]
> > > In order to try and keep the time needed to find a non-reported page to
> > > a minimum we maintain a "reported_boundary" pointer. This pointer is used
> > > by the get_unreported_pages iterator to determine at what point it should
> > > resume searching for non-reported pages. In order to guarantee pages do
> > > not get past the scan I have modified add_to_free_list_tail so that it
> > > will not insert pages behind the reported_boundary.
> > >
> > > If another process needs to perform a massive manipulation of the free
> > > list, such as compaction, it can either reset a given individual boundary
> > > which will push the boundary back to the list_head, or it can clear the
> > > bit indicating the zone is actively processing which will result in the
> > > reporting process resetting all of the boundaries for a given zone.
> >
> > Is this any different from the previous version? The last review
> > feedback (both from me and Mel) was that we are not happy to have an
> > externally imposed constrains on how the page allocator is supposed to
> > maintain its free lists.
>
> The main change for v10 versus v9 is that I allow the page reporting
> boundary to be overridden. Specifically there are two approaches that
> can be taken.
>
> The first is to simply reset the iterator for whatever list is
> updated. What this will do is reset the iterator back to list_head and
> then you can do whatever you want with that specific list.
OK, this is slightly better than pushing the allocator to the corner.
The allocator really has to be under control of its data structures.
I would still be happier if the allocator wouldn't really have to bother
about somebody snooping its internal state to do its own thing. So
please make sure to describe why and how much this really matters.
> The other option is to simply clear the ZONE_PAGE_REPORTING_ACTIVE
> bit. That will essentially notify the page reporting code that any/all
> hints that were recorded have been discarded and that it needs to
> start over.
>
> All I am trying to do with this approach is reduce the work. Without
> doing this the code has to walk the entire free page list for the
> higher orders every iteration and that will not be cheap.
How expensive this will be?
> Admittedly
> it is a bit more invasive than the cut/splice logic used in compaction
> which is taking the pages it has already processed and moving them to
> the other end of the list. However, I have reduced things so that we
> only really are limiting where add_to_free_list_tail can place pages,
> and we are having to check/push back the boundaries if a reported page
> is removed from a free_list.
>
> > If this is really the only way to go forward then I would like to hear
> > very convincing arguments about other approaches not being feasible.
> > There are none in this cover letter unfortunately. This will be really a
> > hard sell without them.
>
> So I had considered several different approaches.
Thanks this is certainly useful and it would have been even more so if
you gave some rough numbers to quantify how much overhead for different
solutions we are talking about here.
--
Michal Hocko
SUSE Labs
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/4] arm64: vdso32: Introduce COMPAT_CC_IS_GCC
From: Vincenzo Frascino @ 2019-09-26 12:22 UTC (permalink / raw)
To: Catalin Marinas
Cc: ard.biesheuvel, ndesaulniers, linux-kernel, tglx, will,
linux-arm-kernel
In-Reply-To: <0ff3d5f4-11c9-4207-c6ab-2f8e9ee7de5e@arm.com>
On 9/26/19 11:56 AM, Vincenzo Frascino wrote:
> On 9/26/19 9:06 AM, Catalin Marinas wrote:
>> On Thu, Sep 26, 2019 at 07:03:50AM +0100, Vincenzo Frascino wrote:
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index 37c610963eee..afe8c948b493 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -110,7 +110,7 @@ config ARM64
>>> select GENERIC_STRNLEN_USER
>>> select GENERIC_TIME_VSYSCALL
>>> select GENERIC_GETTIMEOFDAY
>>> - select GENERIC_COMPAT_VDSO if (!CPU_BIG_ENDIAN && COMPAT)
>>> + select GENERIC_COMPAT_VDSO if (!CPU_BIG_ENDIAN && COMPAT && COMPAT_CC_IS_GCC)
>>> select HANDLE_DOMAIN_IRQ
>>> select HARDIRQS_SW_RESEND
>>> select HAVE_PCI
>>> @@ -313,6 +313,9 @@ config KASAN_SHADOW_OFFSET
>>> default 0xeffffff900000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
>>> default 0xffffffffffffffff
>>>
>>> +config COMPAT_CC_IS_GCC
>>> + def_bool $(success,$(CROSS_COMPILE_COMPAT)gcc --version | head -n 1 | grep -q arm)
>>
>> Nitpick: I prefer COMPATCC instead of COMPAT_CC for consistency with
>> HOSTCC.
>>
>
> Ok, will change this in v2.
>
>> Now, could we not generate a COMPATCC in the Makefile and use
>> $(COMPATCC) here instead of $(CROSS_COMPILE_COMPAT)gcc? It really
>> doesn't make sense to check that gcc is gcc.
>>
>
> All right, COMPATCC is already in the makefile, I will use it in here.
>
What you are proposing seems not possible because Kconfig runs first and then
the arch Makefile, hence compatcc does not take effect on the Kconfig. I will
post v2 with what I proposed, please feel free to comment if you have a better idea.
arch/arm64/configs/defconfig:726:warning: symbol value 'm' invalid for
REMOTEPROC
#
# configuration written to .config
#
make[1]: Leaving directory '/data1/Projects/LinuxKernel/linux-out'
make[1]: Entering directory '/data1/Projects/LinuxKernel/linux-out'
$COMPATCC is [arm-linux-gnueabihf-gcc]
GEN Makefile
>> A next step would be to check that COMPATCC can actually generate 32-bit
>> objects. But it's not essential at this stage.
>>
>
> We are already checking this making sure that arm is present in the triple (grep
> -q arm).
>
>>> diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
>>> index 84a3d502c5a5..34f53eb11878 100644
>>> --- a/arch/arm64/Makefile
>>> +++ b/arch/arm64/Makefile
>>> @@ -54,19 +54,8 @@ $(warning Detected assembler with broken .inst; disassembly will be unreliable)
>>> endif
>>>
>>> ifeq ($(CONFIG_GENERIC_COMPAT_VDSO), y)
>>> - CROSS_COMPILE_COMPAT ?= $(CONFIG_CROSS_COMPILE_COMPAT_VDSO:"%"=%)
>>> -
>>> - ifeq ($(CONFIG_CC_IS_CLANG), y)
>>> - $(warning CROSS_COMPILE_COMPAT is clang, the compat vDSO will not be built)
>>> - else ifeq ($(strip $(CROSS_COMPILE_COMPAT)),)
>>> - $(warning CROSS_COMPILE_COMPAT not defined or empty, the compat vDSO will not be built)
>>> - else ifeq ($(shell which $(CROSS_COMPILE_COMPAT)gcc 2> /dev/null),)
>>> - $(error $(CROSS_COMPILE_COMPAT)gcc not found, check CROSS_COMPILE_COMPAT)
>>> - else
>>> - export CROSS_COMPILE_COMPAT
>>> - export CONFIG_COMPAT_VDSO := y
>>> - compat_vdso := -DCONFIG_COMPAT_VDSO=1
>>> - endif
>>> + export CONFIG_COMPAT_VDSO := y
>>> + compat_vdso := -DCONFIG_COMPAT_VDSO=1
>>> endif
>>
>> Has CONFIG_CROSS_COMPILE_COMPAT_VDSO actually been removed from
>> lib/vdso/Kconfig? (I haven't checked the subsequent patches).
>>
>
--
Regards,
Vincenzo
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH] rtc: at91rm9200: use of_device_get_match_data()
From: Claudiu Beznea @ 2019-09-26 12:15 UTC (permalink / raw)
To: a.zummo, alexandre.belloni, nicolas.ferre, ludovic.desroches
Cc: linux-rtc, linux-kernel, linux-arm-kernel, Claudiu Beznea
Use of_device_get_match_data() since all platforms should now use DT
bindings. AVR32 architecture has been removed in
commit 26202873bb51 ("avr32: remove support for AVR32 architecture").
Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---
drivers/rtc/Kconfig | 1 +
drivers/rtc/rtc-at91rm9200.c | 19 +------------------
2 files changed, 2 insertions(+), 18 deletions(-)
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index e72f65b61176..d0b08b1ebcdf 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1433,6 +1433,7 @@ config RTC_DRV_PL031
config RTC_DRV_AT91RM9200
tristate "AT91RM9200 or some AT91SAM9 RTC"
depends on ARCH_AT91 || COMPILE_TEST
+ depends on OF
help
Driver for the internal RTC (Realtime Clock) module found on
Atmel AT91RM9200's and some AT91SAM9 chips. On AT91SAM9 chips
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index 82a54e93ff04..4dc413d07138 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -319,7 +319,6 @@ static const struct at91_rtc_config at91sam9x5_config = {
.use_shadow_imr = true,
};
-#ifdef CONFIG_OF
static const struct of_device_id at91_rtc_dt_ids[] = {
{
.compatible = "atmel,at91rm9200-rtc",
@@ -332,22 +331,6 @@ static const struct of_device_id at91_rtc_dt_ids[] = {
}
};
MODULE_DEVICE_TABLE(of, at91_rtc_dt_ids);
-#endif
-
-static const struct at91_rtc_config *
-at91_rtc_get_config(struct platform_device *pdev)
-{
- const struct of_device_id *match;
-
- if (pdev->dev.of_node) {
- match = of_match_node(at91_rtc_dt_ids, pdev->dev.of_node);
- if (!match)
- return NULL;
- return (const struct at91_rtc_config *)match->data;
- }
-
- return &at91rm9200_config;
-}
static const struct rtc_class_ops at91_rtc_ops = {
.read_time = at91_rtc_readtime,
@@ -367,7 +350,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
struct resource *regs;
int ret = 0;
- at91_rtc_config = at91_rtc_get_config(pdev);
+ at91_rtc_config = of_device_get_match_data(&pdev->dev);
if (!at91_rtc_config)
return -ENODEV;
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [RFC PATCH 00/18] crypto: wireguard using the existing crypto API
From: Ard Biesheuvel @ 2019-09-26 12:07 UTC (permalink / raw)
To: Jason A. Donenfeld
Cc: Catalin Marinas, Herbert Xu, Arnd Bergmann, Eric Biggers, Greg KH,
Samuel Neves, Will Deacon, Linux Crypto Mailing List,
Andy Lutomirski, Marc Zyngier, Dan Carpenter, Linus Torvalds,
David Miller, linux-arm-kernel
In-Reply-To: <CAHmME9oDhnv7aX77oEERof0TGihk4mDe9B_A3AntaTTVsg9aoA@mail.gmail.com>
On Thu, 26 Sep 2019 at 10:59, Jason A. Donenfeld <Jason@zx2c4.com> wrote:
>
...
>
> Instead what we’ve wound up with in this series is a Frankenstein’s
> monster of Zinc, which appears to have basically the same goal as
> Zinc, and even much of the same implementation just moved to a
> different directory, but then skimps on making it actually work well
> and introduces problems. (I’ll elucidate on some specific issues later
> in this email so that we can get on the same page with regards to
> security requirements for WireGuard.) I surmise from this Zinc-but-not
> series is that what actually is going on here is mostly some kind of
> power or leadership situation, which is what you’ve described to me
> also at various other points and in person.
I'm not sure what you are alluding to here. I have always been very
clear about what I like about Zinc and what I don't like about Zinc.
I agree that it makes absolutely no sense for casual, in-kernel crypto
to jump through all the hoops that the crypto API requires. But for
operating on big chunks of data on the kernel heap, we have an
existing API that we should leverage if we can, and fix if we need to
so that all its users can benefit.
> I also recognize that I am
> at least part way to blame for whatever dynamic there has stagnated
> this process; let me try to rectify that:
>
> A principle objection you’ve had is that Zinc moves to its own
> directory, with its own name, and tries to segment itself off from the
> rest of the crypto API’s infrastructure. You’ve always felt this
> should be mixed in with the rest of the crypto API’s infrastructure
> and directory structures in one way or another. Let’s do both of those
> things – put this in a directory structure you find appropriate and
> hook this into the rest of the crypto API’s infrastructure in a way
> you find appropriate. I might disagree, which is why Zinc does things
> the way it does, but I’m open to compromise and doing things more your
> way.
>
It doesn't have to be your way or my way. The whole point of being
part of this community is that we find solutions that work for
everyone, through discussion and iterative prototyping. Turning up out
of the blue with a 50,000 line patch set and a take-it-or-leave-it
attitude goes counter to that, and this is why we have made so little
progress over the past year.
But I am happy with your willingness to collaborate and find common
ground, which was also my motivation for spending a considerable
amount of time to prepare this patch set.
> Another objection you’ve had is that Zinc replaces many existing
> implementations with its own. Martin wasn’t happy about that either.
> So let’s not do that, and we’ll have some wholesale replacement of
> implementations in future patchsets at future dates discussed and
> benched and bikeshedded independently from this.
>
> Finally, perhaps most importantly, Zinc’s been my design rather than
> our design. Let’s do this together instead of me git-send-email(1)-ing
> a v37.
>
> If the process of doing that together will be fraught with difficulty,
> I’m still open to the “7 patch series” with the ugly cryptoapi.c
> approach, as described at the top.
If your aim is to write ugly code and use that as a munition
> But I think if we start with Zinc
> and whittle it down in accordance with the above, we’ll get something
> mutually acceptable, and somewhat similar to this series, with a few
> important exceptions, which illustrate some of the issues I see in
> this RFC:
>
> Issue 1) No fast implementations for the “it’s just functions” interface.
>
> This is a deal breaker. I know you disagree here and perhaps think all
> dynamic dispatch should be by loadable modules configured with
> userspace policy and lots of function pointers and dynamically
> composable DSL strings, as the current crypto API does it. But I think
> a lot of other people agree with me here (and they’ve chimed in
> before) that the branch predictor does things better, doesn’t have
> Spectre issues, and is very simple to read and understand. For
> reference, here’s what that kind of thing looks like: [2].
>
This is one of the issues in the 'fix it for everyone else as well'
category. If we can improve the crypto API to be less susceptible to
these issues (e.g., using static calls), everybody benefits. I'd be
happy to collaborate on that.
> In this case, the relevance is that the handshake in WireGuard is
> extremely performance sensitive, in order to fend off DoS. One of the
> big design gambits in WireGuard is – can we make it 1-RTT to reduce
> the complexity of the state machine, but keep the crypto efficient
> enough that this is still safe to do from a DoS perspective. The
> protocol succeeds at this goal, but in many ways, just by a hair when
> at scale, and so I’m really quite loathe to decrease handshake
> performance.
...
> Taken together, we simply can’t skimp on the implementations available
> on the handshake layer, so we’ll need to add some form of
> implementation selection, whether it’s the method Zinc uses ([2]), or
> something else we cook up together.
>
So are you saying that the handshake timing constraints in the
WireGuard protocol are so stringent that we can't run it securely on,
e.g., an ARM CPU that lacks a NEON unit? Or given that you are not
providing accelerated implementations of blake2s or Curve25519 for
arm64, we can't run it securely on arm64 at all?
Typically, I would prefer to only introduce different versions of the
same algorithm if there is a clear performance benefit for an actual
use case.
Framing this as a security issue rather than a performance issue is
slightly disingenuous, since people are less likely to challenge it.
But the security of any VPN protocol worth its salt should not hinge
on the performance delta between the reference C code and a version
that was optimized for a particular CPU.
> Issue 2) Linus’ objection to the async API invasion is more correct
> than he realizes.
>
> I could re-enumerate my objections to the API there, but I think we
> all get it. It’s horrendous looking. Even the introduction of the
> ivpad member (what on earth?) in the skb cb made me shutter.
Your implementation of RFC7539 truncates the nonce to 64-bits, while
RFC7539 defines a clear purpose for the bits you omit. Since the Zinc
library is intended to be standalone (and you are proposing its use in
other places, like big_keys.c), you might want to document your
justification for doing so in the general case, instead of ridiculing
the code I needed to write to work around this limitation.
> But
> there’s actually another issue at play:
>
> wg_noise_handshake_begin_session→derive_keys→symmetric_key_init is all
> part of the handshake. We cannot afford to allocate a brand new crypto
> object, parse the DSL string, connect all those function pointers,
> etc.
Parsing the string and connecting the function pointers happens only
once, and only when the transform needs to be instantiated from its
constituent parts. Subsequent invocations will just grab the existing
object.
> The allocations involved here aren’t really okay at all in that
> path. That’s why the cryptoapi.c idea above involves just using a pool
> of pre-allocated objects if we’re going to be using that API at all.
> Also keep in mind that WireGuard instances sometimes have hundreds of
> thousands of peers.
>
My preference would be to address this by permitting per-request keys
in the AEAD layer. That way, we can instantiate the transform only
once, and just invoke it with the appropriate key on the hot path (and
avoid any per-keypair allocations)
> I’d recommend leaving this synchronous as it exists now, as Linus
> suggested, and we can revisit that later down the road. There are a
> number of improvements to the async API we could make down the line
> that could make this viable in WireGuard. For example, I could imagine
> decoupling the creation of the cipher object from its keys and
> intermediate buffers, so that we could in fact allocate the cipher
> objects with their DSLs globally in a safe way, while allowing the
> keys and working buffers to come from elsewhere. This is deep plumbing
> into the async API, but I think we could get there in time.
>
My changes actually move all the rfc7539() intermediate buffers to the
stack, so the only remaining allocation is the per-keypair one.
> There’s also a degree of practicality: right now there is zero ChaPoly
> async acceleration hardware anywhere that would fit into the crypto
> API. At some point, it might come to exist and have incredible
> performance, and then we’ll both feel very motivated to make this work
> for WireGuard. But it might also not come to be (AES seems to have won
> over most of the industry), in which case, why hassle?
>
As I already pointed out, we have supported hardware already: CAAM is
in mainline, and Inside-Secure patches are on the list.
> Issue 3) WireGuard patch is out of date.
>
> This is my fault, because I haven’t posted in a long time. There are
> some important changes in the main WireGuard repo. I’ll roll another
> patch soon for this so we have something recent to work off of. Sorry
> about that.
>
This is the reason I included your WG patch verbatim, to make it
easier to rebase to newer versions. In fact, I never intended or
expected anything but discussion from this submission, let alone
anyone actually merging it :-)
> Issue 4) FPU register batching?
>
> When I introduced the simd_get/simd_put/simd_relax thing, people
> seemed to think it was a good idea. My benchmarks of it showed
> significant throughput improvements. Your patchset doesn’t have
> anything similar to this.
It uses the existing SIMD batching, and enhances it slightly for the
Poly1305/shash case.
> But on the other hand, last I spoke with the
> x86 FPU guys, I thought they might actually be in the process of
> making simd_get/put obsolete with some internal plumbing to make
> restoration lazier. I’ll see tglx later today and will poke him about
> this, as this might already be a non-issue.
>
We've already made improvements here for arm64 as well (and ARM
already used lazy restore). But I think it still makes sense to
amortize these calls over a reasonable chunk of data, i.e., a packet.
>
> So given the above, how would you like to proceed? My personal
> preference would be to see you start with the Zinc patchset and rename
> things and change the infrastructure to something that fits your
> preferences, and we can see what that looks like. Less appealing would
> be to do several iterations of you reworking Zinc from scratch and
> going through the exercises all over again, but if you prefer that I
> guess I could cope. Alternatively, maybe this is a lot to chew on, and
> we should just throw caution into the wind, implement cryptoapi.c for
> WireGuard (as described at the top), and add C functions to the crypto
> API sometime later? This is what I had envisioned in [1].
>
It all depends on whether we are interested in supporting async
accelerators or not, and it is clear what my position is on this
point.
I am not convinced that we need accelerated implementations of blake2s
and curve25519, but if we do, I'd like those to be implemented as
individual modules under arch/*/crypto, with some moduleloader fu for
weak symbols or static calls thrown in if we have to. Exposing them as
shashes seems unnecessary to me at this point.
My only objection to your simd get/put interface is that it uses a
typedef rather than a struct definition (although I also wonder how we
can avoid two instances living on the same call stack, unless we
forbid functions that take a struct simd* to call functions that don't
take one, but these are details we should be able to work out.)
What I *don't* want is to merge WireGuard with its own library based
crypto now, and extend that later for async accelerators once people
realize that we really do need that as well.
> And for the avoidance of doubt, or in case any of the above message
> belied something different, I really am happy and relieved to have an
> opportunity to work on this _with you_, and I am much more open than
> before to compromise and finding practical solutions to the past
> political issues. Also, if you’re into chat, we can always spec some
> of the nitty-gritty aspects out over IRC or even the old-fashioned
> telephone. Thanks again for pushing this forward.
>
My pleasure :-)
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: chapoly acceleration hardware [Was: Re: [RFC PATCH 00/18] crypto: wireguard using the existing crypto API]
From: Toke Høiland-Jørgensen @ 2019-09-26 11:38 UTC (permalink / raw)
To: Jason A. Donenfeld, Pascal Van Leeuwen
Cc: Catalin Marinas, Herbert Xu, Arnd Bergmann, Ard Biesheuvel,
Greg KH, Eric Biggers, Dave Taht, Willy Tarreau, Samuel Neves,
Will Deacon, Netdev, Linux Crypto Mailing List, Andy Lutomirski,
Marc Zyngier, Dan Carpenter, Linus Torvalds, David Miller,
linux-arm-kernel
In-Reply-To: <CAHmME9r5m7D-oMU6Lv_ZhEyWmrNscMr5HokzdK0wg2Ayzzbeow@mail.gmail.com>
"Jason A. Donenfeld" <Jason@zx2c4.com> writes:
> [CC +willy, toke, dave, netdev]
>
> Hi Pascal
>
> On Thu, Sep 26, 2019 at 12:19 PM Pascal Van Leeuwen
> <pvanleeuwen@verimatrix.com> wrote:
>> Actually, that assumption is factually wrong. I don't know if anything
>> is *publicly* available, but I can assure you the silicon is running in
>> labs already. And something will be publicly available early next year
>> at the latest. Which could nicely coincide with having Wireguard support
>> in the kernel (which I would also like to see happen BTW) ...
>>
>> Not "at some point". It will. Very soon. Maybe not in consumer or server
>> CPUs, but definitely in the embedded (networking) space.
>> And it *will* be much faster than the embedded CPU next to it, so it will
>> be worth using it for something like bulk packet encryption.
>
> Super! I was wondering if you could speak a bit more about the
> interface. My biggest questions surround latency. Will it be
> synchronous or asynchronous? If the latter, why? What will its
> latencies be? How deep will its buffers be? The reason I ask is that a
> lot of crypto acceleration hardware of the past has been fast and
> having very deep buffers, but at great expense of latency. In the
> networking context, keeping latency low is pretty important. Already
> WireGuard is multi-threaded which isn't super great all the time for
> latency (improvements are a work in progress). If you're involved with
> the design of the hardware, perhaps this is something you can help
> ensure winds up working well? For example, AES-NI is straightforward
> and good, but Intel can do that because they are the CPU. It sounds
> like your silicon will be adjacent. How do you envision this working
> in a low latency environment?
Being asynchronous doesn't *necessarily* have to hurt latency; you just
need the right queue back-pressure.
We already have multiple queues in the stack. With an async crypto
engine we would go from something like:
stack -> [qdisc] -> wg if -> [wireguard buffer] -> netdev driver ->
device -> [device buffer] -> wire
to
stack -> [qdisc] -> wg if -> [wireguard buffer] -> crypto stack ->
crypto device -> [crypto device buffer] -> wg post-crypto -> netdev
driver -> device -> [device buffer] -> wire
(where everything in [] is a packet queue).
The wireguard buffer is the source of the latency you're alluding to
above (the comment about multi-threaded behaviour), so we probably need
to fix that anyway. For the device buffer we have BQL to keep it at a
minimum. So that leaves the buffering in the crypto offload device. If
we add something like BQL to the crypto offload drivers, we could
conceivably avoid having that add a significant amount of latency. In
fact, doing so may benefit other users of crypto offloads as well, no?
Presumably ipsec has this same issue?
Caveat: I am fairly ignorant about the inner workings of the crypto
subsystem, so please excuse any inaccuracies in the above; the diagrams
are solely for illustrative purposes... :)
-Toke
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [RFC PATCH v4 5/5] kvm: arm64: Add capability check extension for ptp_kvm
From: Jianyong Wu @ 2019-09-26 11:42 UTC (permalink / raw)
To: netdev, yangbo.lu, john.stultz, tglx, pbonzini,
sean.j.christopherson, maz, richardcochran, Mark.Rutland,
Will.Deacon, suzuki.poulose
Cc: justin.he, kvm, Steve.Capper, jianyong.wu, linux-kernel, Kaly.Xin,
nd, kvmarm, linux-arm-kernel
In-Reply-To: <20190926114212.5322-1-jianyong.wu@arm.com>
Let userspace check if there is kvm ptp service in host.
before VMs migrate to a another host, VMM may check if this
cap is available to determine the migration behaviour.
Signed-off-by: Jianyong Wu <jianyong.wu@arm.com>
Suggested-by: Marc Zyngier <maz@kernel.org>
---
include/uapi/linux/kvm.h | 1 +
virt/kvm/arm/arm.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 2fe12b40d503..a0bff6002bd9 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -993,6 +993,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_ARM_SVE 170
#define KVM_CAP_ARM_PTRAUTH_ADDRESS 171
#define KVM_CAP_ARM_PTRAUTH_GENERIC 172
+#define KVM_CAP_ARM_KVM_PTP 173
#ifdef KVM_CAP_IRQ_ROUTING
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index bd5c55916d0d..80999985160b 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -201,6 +201,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_MP_STATE:
case KVM_CAP_IMMEDIATE_EXIT:
case KVM_CAP_VCPU_EVENTS:
+ case KVM_CAP_ARM_KVM_PTP:
r = 1;
break;
case KVM_CAP_ARM_SET_DEVICE_ADDR:
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
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