* [RFC 8/8] KVM: arm/arm64: Emulate the EL1 phys timer register access
From: Christoffer Dall @ 2017-01-09 12:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482772326-29110-9-git-send-email-jintack@cs.columbia.edu>
On Mon, Dec 26, 2016 at 12:12:06PM -0500, Jintack Lim wrote:
> Emulate read and write operations to CNTP_TVAL, CNTP_CVAL and CNTP_CTL.
> Now the VM is able to use the EL1 physical timer.
>
> Signed-off-by: Jintack Lim <jintack@cs.columbia.edu>
> ---
> arch/arm64/kvm/sys_regs.c | 35 ++++++++++++++++++++++++++++++++---
> include/kvm/arm_arch_timer.h | 3 +++
> virt/kvm/arm/arch_timer.c | 4 ++--
> 3 files changed, 37 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index fd9e747..7cef94f 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -824,7 +824,15 @@ static bool access_cntp_tval(struct kvm_vcpu *vcpu,
> struct sys_reg_params *p,
> const struct sys_reg_desc *r)
> {
> - kvm_inject_undefined(vcpu);
> + struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
> + cycle_t now = kvm_phys_timer_read();
> +
> + if (p->is_write) {
> + ptimer->cnt_cval = p->regval + now;
> + kvm_timer_emulate(vcpu, ptimer);
Hmm, do we really need those calls here?
I guess I'm a little confused about exactly what the kvm_timer_emulate()
function is supposed to do, and it feels to me like these handlers
should just record what the guest is asking the kernel to do and the
logic of handling the additional timer should be moved into the run path
as much as possible.
Thanks,
-Christoffer
> + } else
> + p->regval = ptimer->cnt_cval - now;
> +
> return true;
> }
>
> @@ -832,7 +840,21 @@ static bool access_cntp_ctl(struct kvm_vcpu *vcpu,
> struct sys_reg_params *p,
> const struct sys_reg_desc *r)
> {
> - kvm_inject_undefined(vcpu);
> + struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
> +
> + if (p->is_write) {
> + /* ISTATUS bit is read-only */
> + ptimer->cnt_ctl = p->regval & ~ARCH_TIMER_CTRL_IT_STAT;
> + kvm_timer_emulate(vcpu, ptimer);
> + } else {
> + cycle_t now = kvm_phys_timer_read();
> +
> + p->regval = ptimer->cnt_ctl;
> + /* Set ISTATUS bit if it's expired */
> + if (ptimer->cnt_cval <= now)
> + p->regval |= ARCH_TIMER_CTRL_IT_STAT;
> + }
> +
> return true;
> }
>
> @@ -840,7 +862,14 @@ static bool access_cntp_cval(struct kvm_vcpu *vcpu,
> struct sys_reg_params *p,
> const struct sys_reg_desc *r)
> {
> - kvm_inject_undefined(vcpu);
> + struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
> +
> + if (p->is_write) {
> + ptimer->cnt_cval = p->regval;
> + kvm_timer_emulate(vcpu, ptimer);
> + } else
> + p->regval = ptimer->cnt_cval;
> +
> return true;
> }
>
> diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
> index 04ed9c1..776579b 100644
> --- a/include/kvm/arm_arch_timer.h
> +++ b/include/kvm/arm_arch_timer.h
> @@ -75,6 +75,9 @@ bool kvm_timer_should_fire(struct kvm_vcpu *vcpu,
> struct arch_timer_context *timer_ctx);
> void kvm_timer_schedule(struct kvm_vcpu *vcpu);
> void kvm_timer_unschedule(struct kvm_vcpu *vcpu);
> +void kvm_timer_emulate(struct kvm_vcpu *vcpu, struct arch_timer_context *timer);
> +
> +cycle_t kvm_phys_timer_read(void);
>
> void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu);
>
> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
> index be8d953..7a161f8 100644
> --- a/virt/kvm/arm/arch_timer.c
> +++ b/virt/kvm/arm/arch_timer.c
> @@ -39,7 +39,7 @@ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
> vcpu_vtimer(vcpu)->active_cleared_last = false;
> }
>
> -static cycle_t kvm_phys_timer_read(void)
> +cycle_t kvm_phys_timer_read(void)
> {
> return timecounter->cc->read(timecounter->cc);
> }
> @@ -258,7 +258,7 @@ static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
> * Schedule the background timer for the emulated timer. The background timer
> * runs whenever vcpu is runnable and the timer is not expired.
> */
> -static void kvm_timer_emulate(struct kvm_vcpu *vcpu,
> +void kvm_timer_emulate(struct kvm_vcpu *vcpu,
> struct arch_timer_context *timer_ctx)
> {
> struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
> --
> 1.9.1
>
>
^ permalink raw reply
* [PATCH v2 1/5] ARM: davinci_all_defconfig: enable DA8xx pinconf
From: Sekhar Nori @ 2017-01-09 12:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483677228-2325-2-git-send-email-david@lechnology.com>
On Friday 06 January 2017 10:03 AM, David Lechner wrote:
> This enables the DA8xx pinconf driver by default. It is needed by LEGO
> MINDSTORMS EV3.
Missing your sign-off. I cannot apply that myself. Please resend.
Thanks,
Sekhar
^ permalink raw reply
* [PATCH v2 2/5] ARM: davinci_all_defconfig: Enable PWM modules
From: Sekhar Nori @ 2017-01-09 12:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483677228-2325-3-git-send-email-david@lechnology.com>
On Friday 06 January 2017 10:03 AM, David Lechner wrote:
> This enables PWM and the TI ECAP and EHRWPM modules. These are used on LEGO
> MINDSTORMS EV3.
Here too. Please resend with sign-off.
Thanks,
Sekhar
^ permalink raw reply
* [PATCH 1/2] ARM: hyp-stub: improve ABI
From: Russell King - ARM Linux @ 2017-01-09 12:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170103095149.GA14242@cbox>
On Tue, Jan 03, 2017 at 10:51:49AM +0100, Christoffer Dall wrote:
> Hi Russell,
>
> On Thu, Dec 15, 2016 at 06:57:18PM +0000, Russell King - ARM Linux wrote:
> > What's also coming clear is that there's very few people who understand
> > all the interactions here, and the whole thing seems to be an undocumented
> > mess.
>
> I think the hyp stub has just served a very limited purpose so far, and
> therefore is a somewhat immature implementation. Now we've discovered a
> need to clean it up, and we're all for that. Again, I don't think the
> problem is any larger than that, we just need to fix it, and it seems to
> me everyone is willing to work on that.
What I want to see is some documentation of the hyp-stub, so that there
can be some element of confidence that changes there are properly
coordinated. As I said in a follow up email:
| Either we need more people to have an understanding (so if one of them
| gets run over by a bus, we're not left floundering around) or we need
| it to be documented - even if it's just a simple comment "the ABI in
| this file is shared with XYZ, if you change the ABI here, also update
| XYZ too."
> Marc even offered to work on your suggestion to support the general
> hyp ABI commands in KVM.
... which is pointless, because it's a duplication of the effort I've
already put in. My patches already do the:
#define HVC_GET_VECTORS 0
#define HVC_SET_VECTORS 1
#define HVC_SOFT_RESTART 2
thing which ARM64 does, passing the arguments in via the appropriate
registers. However, such a change is a major revision of hyp-stub's
ABI, which completely changes the way it works.
The issue here is that there seems to be only one person, Marc, who
understands that the KVM hypervisor also needs to be updated - everyone
else I've talked to was of the opinion that hyp-stub's ABI is limited
to hyp-stub.S. That's worse than "I don't know" because it leads to
exactly the situation that my patches created: the two ABIs going out
of step.
What I'm asking for is a patch to add some sort of documentation ASAP
which ensures that this important non-obvious information isn't limited
to just one person. As I mentioned in the quote above, it can be as
simple as merely pointing each file at its counterparts which have to
be updated at the same time.
Longer term, I'd like to see the existing hypervisor documentation in
Documentation/virtual/kvm/hypercalls.txt updated with the ARM details.
According to that document, KVM effectively only exists on PPC and x86
at the present time...
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* [PATCH v2 3/5] ARM: davinci_all_defconfig: enable iio and ADS7950
From: Sekhar Nori @ 2017-01-09 12:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483677228-2325-4-git-send-email-david@lechnology.com>
On Friday 06 January 2017 10:03 AM, David Lechner wrote:
> This enables the iio subsystem and the TI ADS7950 driver. This is used by
> LEGO MINDSTORMS EV3, which has an ADS7957 chip.
Can you add your sign-off?
> ---
>
> The CONFIG_TI_ADS7950 driver is currently in iio/testing, so some coordination
> may be needed before picking up this patch.
>
> arch/arm/configs/davinci_all_defconfig | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig
> index 2b1967a..a899876 100644
> --- a/arch/arm/configs/davinci_all_defconfig
> +++ b/arch/arm/configs/davinci_all_defconfig
> @@ -200,6 +200,13 @@ CONFIG_TI_EDMA=y
> CONFIG_MEMORY=y
> CONFIG_TI_AEMIF=m
> CONFIG_DA8XX_DDRCTL=y
> +CONFIG_IIO=m
> +CONFIG_IIO_BUFFER_CB=m
> +CONFIG_IIO_SW_DEVICE=m
> +CONFIG_IIO_SW_TRIGGER=m
> +CONFIG_TI_ADS7950=m
Can you separate this from rest of the patch. I would like to enable
this option only after I can find the symbol in linux-next.
> +CONFIG_IIO_HRTIMER_TRIGGER=m
> +CONFIG_IIO_SYSFS_TRIGGER=m
Need CONFIG_IIO_TRIGGER=y also for these two options to take effect.
Thanks,
Sekhar
^ permalink raw reply
* [PATCH 2/2] media: rc: add driver for IR remote receiver on MT7623 SoC
From: Sean Young @ 2017-01-09 12:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483931601.16976.48.camel@mtkswgap22>
On Mon, Jan 09, 2017 at 11:13:21AM +0800, Sean Wang wrote:
> I had another question. I found multiple and same IR messages being
> received when using SONY remote controller. Should driver needs to
> report each message or only one of these to the upper layer ?
In general the driver shouldn't try to change any IR message, this should
be done in rc-core if necessary.
rc-core should handle this correctly. If the same key is received twice
within IR_KEYPRESS_TIMEOUT (250ms) then it not reported to the input
layer.
Thanks
Sean
^ permalink raw reply
* [PATCH 1/2] ARM: hyp-stub: improve ABI
From: Russell King - ARM Linux @ 2017-01-09 12:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <72f93940-cf87-fd91-90f2-760b7ff050fb@arm.com>
On Thu, Dec 15, 2016 at 11:18:48AM +0000, Marc Zyngier wrote:
> On 14/12/16 10:46, Russell King wrote:
> > Improve the hyp-stub ABI to allow it to do more than just get/set the
> > vectors. We follow the example in ARM64, where r0 is used as an opcode
> > with the other registers as an argument.
> >
> > Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> > ---
> > arch/arm/kernel/hyp-stub.S | 27 ++++++++++++++++++++++-----
> > 1 file changed, 22 insertions(+), 5 deletions(-)
> >
> > diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S
> > index 15d073ae5da2..f3e9ba5fb642 100644
> > --- a/arch/arm/kernel/hyp-stub.S
> > +++ b/arch/arm/kernel/hyp-stub.S
> > @@ -22,6 +22,9 @@
> > #include <asm/assembler.h>
> > #include <asm/virt.h>
> >
> > +#define HVC_GET_VECTORS 0
> > +#define HVC_SET_VECTORS 1
> > +
> > #ifndef ZIMAGE
> > /*
> > * For the kernel proper, we need to find out the CPU boot mode long after
> > @@ -202,9 +205,19 @@ ARM_BE8(orr r7, r7, #(1 << 25)) @ HSCTLR.EE
> > ENDPROC(__hyp_stub_install_secondary)
> >
> > __hyp_stub_do_trap:
> > - cmp r0, #-1
> > - mrceq p15, 4, r0, c12, c0, 0 @ get HVBAR
> > - mcrne p15, 4, r0, c12, c0, 0 @ set HVBAR
> > + teq r0, #HVC_GET_VECTORS
> > + bne 1f
> > + mrc p15, 4, r0, c12, c0, 0 @ get HVBAR
> > + b __hyp_stub_exit
> > +
> > +1: teq r0, #HVC_SET_VECTORS
> > + bne 1f
> > + mcr p15, 4, r1, c12, c0, 0 @ set HVBAR
> > + b __hyp_stub_exit
> > +
> > +1: mov r0, #-1
> > +
> > +__hyp_stub_exit:
> > __ERET
> > ENDPROC(__hyp_stub_do_trap)
> >
> > @@ -231,10 +244,14 @@ ENDPROC(__hyp_stub_do_trap)
> > * initialisation entry point.
> > */
> > ENTRY(__hyp_get_vectors)
> > - mov r0, #-1
> > + mov r0, #HVC_GET_VECTORS
>
> This breaks the KVM implementation of __hyp_get_vectors, easily fixed
> with the following patchlet:
>
> diff --git a/arch/arm/include/asm/virt.h b/arch/arm/include/asm/virt.h
> index a2e75b8..0fe637e 100644
> --- a/arch/arm/include/asm/virt.h
> +++ b/arch/arm/include/asm/virt.h
> @@ -89,6 +89,14 @@ extern char __hyp_text_start[];
> extern char __hyp_text_end[];
> #endif
>
> +#else
> +
> +/* Only assembly code should need those */
> +
> +#define HVC_GET_VECTORS 0
> +#define HVC_SET_VECTORS 1
> +#define HVC_SOFT_RESTART 2
> +
> #endif /* __ASSEMBLY__ */
>
> #endif /* ! VIRT_H */
> diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S
> index ebc26f8..1c6888f 100644
> --- a/arch/arm/kernel/hyp-stub.S
> +++ b/arch/arm/kernel/hyp-stub.S
> @@ -22,10 +22,6 @@
> #include <asm/assembler.h>
> #include <asm/virt.h>
>
> -#define HVC_GET_VECTORS 0
> -#define HVC_SET_VECTORS 1
> -#define HVC_SOFT_RESTART 2
> -
> #ifndef ZIMAGE
> /*
> * For the kernel proper, we need to find out the CPU boot mode long after
> diff --git a/arch/arm/kvm/hyp/hyp-entry.S b/arch/arm/kvm/hyp/hyp-entry.S
> index 96beb53..1f8db7d 100644
> --- a/arch/arm/kvm/hyp/hyp-entry.S
> +++ b/arch/arm/kvm/hyp/hyp-entry.S
> @@ -127,7 +127,7 @@ hyp_hvc:
> pop {r0, r1, r2}
>
> /* Check for __hyp_get_vectors */
> - cmp r0, #-1
> + cmp r0, #HVC_GET_VECTORS
> mrceq p15, 4, r0, c12, c0, 0 @ get HVBAR
> beq 1f
I don't think this is sufficient - the kdump case for ARM will still be
broken after these patches.
The new soft-restart ABI introduced by my patch 2 passes in:
r0 = HVC_SOFT_RESTART
r1 = non-zero
r2 = undefined
r3 = function pointer
and the assumption is that r3 will be preserved if the HVC call does
nothing - which probably isn't a safe assumption.
With these arguments passed to the KVM stub (which may be in place at
the point of a kdump), we end up executing this code:
push {lr}
mov lr, r0
mov r0, r1
mov r1, r2
mov r2, r3
THUMB( orr lr, #1)
blx lr @ Call the HYP function
This will result in an attempt to branch to address 2 or 3, which isn't
sane - a panic in the host kernel (eg due to a NULL pointer deref with
panic_on_oops enabled) will then cause kdump to try to execute code from
a stupid address.
So, we need KVM's stub to be (a) better documented so this stuff is
obvious, and (b) updated so that kdump stands a chance of working even
if the KVM stub is still in place at the point the host kernel panics.
Another reason why documentation is important here is that we need to
make it clear to alternative hypervisors that the host kernel may issue
a HVC call at any moment due to a crash with particular arguments, and
that the host kernel expects a certain behaviour in that case, and that
the hypervisor does not crash.
For example, how will Xen behave - is introducing these changes going
to cause a regression with Xen? Does anyone even know the answer to
that? From what I can see, it seems we'll end up calling Xen's
hypervisor with a random r12 value (which it uses as a reason code)
but without the 0xea1 immediate constant in the HVC instruction.
Beyond that, I've no idea.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* [PATCH v2 7/7] uapi: export all headers under uapi directories
From: Christoph Hellwig @ 2017-01-09 12:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483695839-18660-8-git-send-email-nicolas.dichtel@6wind.com>
On Fri, Jan 06, 2017 at 10:43:59AM +0100, Nicolas Dichtel wrote:
> Regularly, when a new header is created in include/uapi/, the developer
> forgets to add it in the corresponding Kbuild file. This error is usually
> detected after the release is out.
>
> In fact, all headers under uapi directories should be exported, thus it's
> useless to have an exhaustive list.
>
> After this patch, the following files, which were not exported, are now
> exported (with make headers_install_all):
... snip ...
> linux/genwqe/.install
> linux/genwqe/..install.cmd
> linux/cifs/.install
> linux/cifs/..install.cmd
I'm pretty sure these should not be exported!
^ permalink raw reply
* [PATCH 1/2] ARM: hyp-stub: improve ABI
From: Marc Zyngier @ 2017-01-09 13:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170109125431.GY14217@n2100.armlinux.org.uk>
On 09/01/17 12:54, Russell King - ARM Linux wrote:
> On Thu, Dec 15, 2016 at 11:18:48AM +0000, Marc Zyngier wrote:
>> On 14/12/16 10:46, Russell King wrote:
>>> Improve the hyp-stub ABI to allow it to do more than just get/set the
>>> vectors. We follow the example in ARM64, where r0 is used as an opcode
>>> with the other registers as an argument.
>>>
>>> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
>>> ---
>>> arch/arm/kernel/hyp-stub.S | 27 ++++++++++++++++++++++-----
>>> 1 file changed, 22 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S
>>> index 15d073ae5da2..f3e9ba5fb642 100644
>>> --- a/arch/arm/kernel/hyp-stub.S
>>> +++ b/arch/arm/kernel/hyp-stub.S
>>> @@ -22,6 +22,9 @@
>>> #include <asm/assembler.h>
>>> #include <asm/virt.h>
>>>
>>> +#define HVC_GET_VECTORS 0
>>> +#define HVC_SET_VECTORS 1
>>> +
>>> #ifndef ZIMAGE
>>> /*
>>> * For the kernel proper, we need to find out the CPU boot mode long after
>>> @@ -202,9 +205,19 @@ ARM_BE8(orr r7, r7, #(1 << 25)) @ HSCTLR.EE
>>> ENDPROC(__hyp_stub_install_secondary)
>>>
>>> __hyp_stub_do_trap:
>>> - cmp r0, #-1
>>> - mrceq p15, 4, r0, c12, c0, 0 @ get HVBAR
>>> - mcrne p15, 4, r0, c12, c0, 0 @ set HVBAR
>>> + teq r0, #HVC_GET_VECTORS
>>> + bne 1f
>>> + mrc p15, 4, r0, c12, c0, 0 @ get HVBAR
>>> + b __hyp_stub_exit
>>> +
>>> +1: teq r0, #HVC_SET_VECTORS
>>> + bne 1f
>>> + mcr p15, 4, r1, c12, c0, 0 @ set HVBAR
>>> + b __hyp_stub_exit
>>> +
>>> +1: mov r0, #-1
>>> +
>>> +__hyp_stub_exit:
>>> __ERET
>>> ENDPROC(__hyp_stub_do_trap)
>>>
>>> @@ -231,10 +244,14 @@ ENDPROC(__hyp_stub_do_trap)
>>> * initialisation entry point.
>>> */
>>> ENTRY(__hyp_get_vectors)
>>> - mov r0, #-1
>>> + mov r0, #HVC_GET_VECTORS
>>
>> This breaks the KVM implementation of __hyp_get_vectors, easily fixed
>> with the following patchlet:
>>
>> diff --git a/arch/arm/include/asm/virt.h b/arch/arm/include/asm/virt.h
>> index a2e75b8..0fe637e 100644
>> --- a/arch/arm/include/asm/virt.h
>> +++ b/arch/arm/include/asm/virt.h
>> @@ -89,6 +89,14 @@ extern char __hyp_text_start[];
>> extern char __hyp_text_end[];
>> #endif
>>
>> +#else
>> +
>> +/* Only assembly code should need those */
>> +
>> +#define HVC_GET_VECTORS 0
>> +#define HVC_SET_VECTORS 1
>> +#define HVC_SOFT_RESTART 2
>> +
>> #endif /* __ASSEMBLY__ */
>>
>> #endif /* ! VIRT_H */
>> diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S
>> index ebc26f8..1c6888f 100644
>> --- a/arch/arm/kernel/hyp-stub.S
>> +++ b/arch/arm/kernel/hyp-stub.S
>> @@ -22,10 +22,6 @@
>> #include <asm/assembler.h>
>> #include <asm/virt.h>
>>
>> -#define HVC_GET_VECTORS 0
>> -#define HVC_SET_VECTORS 1
>> -#define HVC_SOFT_RESTART 2
>> -
>> #ifndef ZIMAGE
>> /*
>> * For the kernel proper, we need to find out the CPU boot mode long after
>> diff --git a/arch/arm/kvm/hyp/hyp-entry.S b/arch/arm/kvm/hyp/hyp-entry.S
>> index 96beb53..1f8db7d 100644
>> --- a/arch/arm/kvm/hyp/hyp-entry.S
>> +++ b/arch/arm/kvm/hyp/hyp-entry.S
>> @@ -127,7 +127,7 @@ hyp_hvc:
>> pop {r0, r1, r2}
>>
>> /* Check for __hyp_get_vectors */
>> - cmp r0, #-1
>> + cmp r0, #HVC_GET_VECTORS
>> mrceq p15, 4, r0, c12, c0, 0 @ get HVBAR
>> beq 1f
>
> I don't think this is sufficient - the kdump case for ARM will still be
> broken after these patches.
>
> The new soft-restart ABI introduced by my patch 2 passes in:
>
> r0 = HVC_SOFT_RESTART
> r1 = non-zero
> r2 = undefined
> r3 = function pointer
>
> and the assumption is that r3 will be preserved if the HVC call does
> nothing - which probably isn't a safe assumption.
>
> With these arguments passed to the KVM stub (which may be in place at
> the point of a kdump), we end up executing this code:
>
> push {lr}
>
> mov lr, r0
> mov r0, r1
> mov r1, r2
> mov r2, r3
>
> THUMB( orr lr, #1)
> blx lr @ Call the HYP function
>
> This will result in an attempt to branch to address 2 or 3, which isn't
> sane - a panic in the host kernel (eg due to a NULL pointer deref with
> panic_on_oops enabled) will then cause kdump to try to execute code from
> a stupid address.
>
> So, we need KVM's stub to be (a) better documented so this stuff is
> obvious, and (b) updated so that kdump stands a chance of working even
> if the KVM stub is still in place at the point the host kernel panics.
>
> Another reason why documentation is important here is that we need to
> make it clear to alternative hypervisors that the host kernel may issue
> a HVC call at any moment due to a crash with particular arguments, and
> that the host kernel expects a certain behaviour in that case, and that
> the hypervisor does not crash.
>
> For example, how will Xen behave - is introducing these changes going
> to cause a regression with Xen? Does anyone even know the answer to
> that? From what I can see, it seems we'll end up calling Xen's
> hypervisor with a random r12 value (which it uses as a reason code)
> but without the 0xea1 immediate constant in the HVC instruction.
> Beyond that, I've no idea.
I fail to see why you would issue a hyp stub hypercall if you're booted
under *any* hypervisor. The only way you can have a valid hyp stub is
because the kernel was booted at EL2/HYP. If you're running under Xen,
KVM or whatever other hypervisor, you're booted at EL1/SVC, you only
have the hypercall API exposed by that hypervisor, and nothing else. You
can't even install the stub the first place.
So any code path that tries to tear down KVM would better check that the
kernel was entered at HYP. If it doesn't, it is broken.
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH 1/2] ARM: hyp-stub: improve ABI
From: Russell King - ARM Linux @ 2017-01-09 13:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <e16d9b76-49ce-ae22-60f9-f2000d1862af@arm.com>
On Mon, Jan 09, 2017 at 01:14:31PM +0000, Marc Zyngier wrote:
> On 09/01/17 12:54, Russell King - ARM Linux wrote:
> > I don't think this is sufficient - the kdump case for ARM will still be
> > broken after these patches.
> >
> > The new soft-restart ABI introduced by my patch 2 passes in:
> >
> > r0 = HVC_SOFT_RESTART
> > r1 = non-zero
> > r2 = undefined
> > r3 = function pointer
> >
> > and the assumption is that r3 will be preserved if the HVC call does
> > nothing - which probably isn't a safe assumption.
> >
> > With these arguments passed to the KVM stub (which may be in place at
> > the point of a kdump), we end up executing this code:
> >
> > push {lr}
> >
> > mov lr, r0
> > mov r0, r1
> > mov r1, r2
> > mov r2, r3
> >
> > THUMB( orr lr, #1)
> > blx lr @ Call the HYP function
> >
> > This will result in an attempt to branch to address 2 or 3, which isn't
> > sane - a panic in the host kernel (eg due to a NULL pointer deref with
> > panic_on_oops enabled) will then cause kdump to try to execute code from
> > a stupid address.
> >
> > So, we need KVM's stub to be (a) better documented so this stuff is
> > obvious, and (b) updated so that kdump stands a chance of working even
> > if the KVM stub is still in place at the point the host kernel panics.
> >
> > Another reason why documentation is important here is that we need to
> > make it clear to alternative hypervisors that the host kernel may issue
> > a HVC call at any moment due to a crash with particular arguments, and
> > that the host kernel expects a certain behaviour in that case, and that
> > the hypervisor does not crash.
> >
> > For example, how will Xen behave - is introducing these changes going
> > to cause a regression with Xen? Does anyone even know the answer to
> > that? From what I can see, it seems we'll end up calling Xen's
> > hypervisor with a random r12 value (which it uses as a reason code)
> > but without the 0xea1 immediate constant in the HVC instruction.
> > Beyond that, I've no idea.
>
> I fail to see why you would issue a hyp stub hypercall if you're booted
> under *any* hypervisor. The only way you can have a valid hyp stub is
> because the kernel was booted at EL2/HYP. If you're running under Xen,
> KVM or whatever other hypervisor, you're booted at EL1/SVC, you only
> have the hypercall API exposed by that hypervisor, and nothing else. You
> can't even install the stub the first place.
>
> So any code path that tries to tear down KVM would better check that the
> kernel was entered at HYP. If it doesn't, it is broken.
Let me refresh your memory. This thread is about kexec/kdump on 32-bit
ARM of the _host_ kernel, which will be entered in HYP mode.
I've never used Xen, so I've no idea about it. I'm merely pointing out
the possibilities as I see them.
Let me repeat the on-going theme here. Documentation. Documentation.
Documentation. Documentation. Documentation. Documentation.
Documentation. Documentation. Documentation. Documentation.
Documentation. Documentation. Documentation. Documentation.
Documentation. Documentation. Documentation. Documentation.
Documentation. Documentation. Documentation. Documentation.
Documentation. Documentation. Documentation. Documentation.
Is the message getting through yet? Can you see the waste of time
the lack of documentation is having yet - not only my time, but your
time replying to these emails.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* [PATCH v3 5/5] drm/rockchip: Implement CRC debugfs API
From: Tomeu Vizoso @ 2017-01-09 13:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOw6vbLAwzrwfHdny=-RYrUE7wBksqwkOxatJ1=_HMojQLPm4w@mail.gmail.com>
On 6 January 2017 at 16:56, Sean Paul <seanpaul@chromium.org> wrote:
> On Fri, Jan 6, 2017 at 9:30 AM, Tomeu Vizoso <tomeu.vizoso@collabora.com> wrote:
>> Implement the .set_crc_source() callback and call the DP helpers
>> accordingly to start and stop CRC capture.
>>
>> This is only done if this CRTC is currently using the eDP connector.
>>
>> v3: Remove superfluous check on rockchip_crtc_state->output_type
>>
>> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>> ---
>>
>> drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 48 +++++++++++++++++++++++++++++
>> 1 file changed, 48 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> index fb5f001f51c3..5e19bef6d5b4 100644
>> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
>> @@ -19,6 +19,7 @@
>> #include <drm/drm_crtc_helper.h>
>> #include <drm/drm_flip_work.h>
>> #include <drm/drm_plane_helper.h>
>> +#include <drm/bridge/analogix_dp.h>
>>
>> #include <linux/kernel.h>
>> #include <linux/module.h>
>> @@ -1105,6 +1106,52 @@ static void vop_crtc_destroy_state(struct drm_crtc *crtc,
>> kfree(s);
>> }
>>
>> +static struct drm_connector *vop_get_edp_connector(struct vop *vop)
>> +{
>> + struct drm_crtc *crtc = &vop->crtc;
>> + struct drm_connector *connector;
>> +
>> + mutex_lock(&crtc->dev->mode_config.mutex);
>> + drm_for_each_connector(connector, crtc->dev)
>> + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
>> + mutex_unlock(&crtc->dev->mode_config.mutex);
>> + return connector;
>> + }
>> + mutex_unlock(&crtc->dev->mode_config.mutex);
>> +
>> + return NULL;
>> +}
>> +
>> +static int vop_crtc_set_crc_source(struct drm_crtc *crtc,
>> + const char *source_name, size_t *values_cnt)
>> +{
>> + struct vop *vop = to_vop(crtc);
>> + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
>> + struct drm_connector *connector;
>> + int ret;
>> +
>> + connector = vop_get_edp_connector(vop);
>> + if (!connector)
>> + return -EINVAL;
>> +
>> + *values_cnt = 3;
>> +
>> + if (source_name &&
>> + strcmp(source_name, "auto") == 0) {
>> +
>> + if (s->output_type != DRM_MODE_CONNECTOR_eDP)
>> + return -EINVAL;
>> +
>> + ret = analogix_dp_start_crc(connector);
>
> To pick up my thoughts from 1/5, you could do the following instead:
>
> analogix_dp_start_crc(drm_crtc_index(crtc));
Well, I still need the dpaux to access the dpcd, so that would have to be:
analogix_dp_start_crc(connector, drm_crtc_index(crtc));
Regards,
Tomeu
>> + } else if (!source_name)
>> +
>> + ret = analogix_dp_stop_crc(connector);
>> + else
>> + ret = -EINVAL;
>> +
>> + return ret;
>> +}
>> +
>> static const struct drm_crtc_funcs vop_crtc_funcs = {
>> .set_config = drm_atomic_helper_set_config,
>> .page_flip = drm_atomic_helper_page_flip,
>> @@ -1112,6 +1159,7 @@ static const struct drm_crtc_funcs vop_crtc_funcs = {
>> .reset = vop_crtc_reset,
>> .atomic_duplicate_state = vop_crtc_duplicate_state,
>> .atomic_destroy_state = vop_crtc_destroy_state,
>> + .set_crc_source = vop_crtc_set_crc_source,
>> };
>>
>> static void vop_fb_unref_worker(struct drm_flip_work *work, void *val)
>> --
>> 2.9.3
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
>
>
> --
> Sean Paul, Software Engineer, Google / Chromium OS
^ permalink raw reply
* [PATCH 1/2] ARM: hyp-stub: improve ABI
From: Christoffer Dall @ 2017-01-09 13:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170109122639.GX14217@n2100.armlinux.org.uk>
On Mon, Jan 09, 2017 at 12:26:39PM +0000, Russell King - ARM Linux wrote:
> On Tue, Jan 03, 2017 at 10:51:49AM +0100, Christoffer Dall wrote:
> > Hi Russell,
> >
> > On Thu, Dec 15, 2016 at 06:57:18PM +0000, Russell King - ARM Linux wrote:
> > > What's also coming clear is that there's very few people who understand
> > > all the interactions here, and the whole thing seems to be an undocumented
> > > mess.
> >
> > I think the hyp stub has just served a very limited purpose so far, and
> > therefore is a somewhat immature implementation. Now we've discovered a
> > need to clean it up, and we're all for that. Again, I don't think the
> > problem is any larger than that, we just need to fix it, and it seems to
> > me everyone is willing to work on that.
>
> What I want to see is some documentation of the hyp-stub, so that there
> can be some element of confidence that changes there are properly
> coordinated. As I said in a follow up email:
>
> | Either we need more people to have an understanding (so if one of them
> | gets run over by a bus, we're not left floundering around) or we need
> | it to be documented - even if it's just a simple comment "the ABI in
> | this file is shared with XYZ, if you change the ABI here, also update
> | XYZ too."
>
> > Marc even offered to work on your suggestion to support the general
> > hyp ABI commands in KVM.
>
> ... which is pointless, because it's a duplication of the effort I've
> already put in. My patches already do the:
>
> #define HVC_GET_VECTORS 0
> #define HVC_SET_VECTORS 1
> #define HVC_SOFT_RESTART 2
>
> thing which ARM64 does, passing the arguments in via the appropriate
> registers. However, such a change is a major revision of hyp-stub's
> ABI, which completely changes the way it works.
Sorry, I'm afraid I might have been unclear. What I meant with "general
hyp ABI commands in KVM" was, that if there's a need for KVM to support
the operations (using a unified and documented ABI) that the hyp stub
supports, then we could add that in KVM as well. I thought your patches
added the functionality for the hyp stub, and Marc would add whichever
remaining pieces in the KVM side.
[...]
>
> Longer term, I'd like to see the existing hypervisor documentation in
> Documentation/virtual/kvm/hypercalls.txt updated with the ARM details.
> According to that document, KVM effectively only exists on PPC and x86
> at the present time...
>
I'm afraid I don't think this is right place to document this behavior.
There's a difference between an internal ABI between code running in two
CPU modes but both part of the same kernel, and a hypervisor running
a guest OS on top.
I believe that Documentation/virtual/kvm/hypercalls.txt documents the
latter case (i.e. guest hypercalls supported by the KVM host
hypervisor), not the former case, and these things should not be
combined.
I would suggest adding something like
Documentation/virtual/kvm/arm/hyp-abi.txt instead.
-Christoffer
^ permalink raw reply
* [PATCH 1/2] ARM: hyp-stub: improve ABI
From: Marc Zyngier @ 2017-01-09 13:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170109132026.GZ14217@n2100.armlinux.org.uk>
On 09/01/17 13:20, Russell King - ARM Linux wrote:
> On Mon, Jan 09, 2017 at 01:14:31PM +0000, Marc Zyngier wrote:
>> On 09/01/17 12:54, Russell King - ARM Linux wrote:
>>> I don't think this is sufficient - the kdump case for ARM will still be
>>> broken after these patches.
>>>
>>> The new soft-restart ABI introduced by my patch 2 passes in:
>>>
>>> r0 = HVC_SOFT_RESTART
>>> r1 = non-zero
>>> r2 = undefined
>>> r3 = function pointer
>>>
>>> and the assumption is that r3 will be preserved if the HVC call does
>>> nothing - which probably isn't a safe assumption.
>>>
>>> With these arguments passed to the KVM stub (which may be in place at
>>> the point of a kdump), we end up executing this code:
>>>
>>> push {lr}
>>>
>>> mov lr, r0
>>> mov r0, r1
>>> mov r1, r2
>>> mov r2, r3
>>>
>>> THUMB( orr lr, #1)
>>> blx lr @ Call the HYP function
>>>
>>> This will result in an attempt to branch to address 2 or 3, which isn't
>>> sane - a panic in the host kernel (eg due to a NULL pointer deref with
>>> panic_on_oops enabled) will then cause kdump to try to execute code from
>>> a stupid address.
>>>
>>> So, we need KVM's stub to be (a) better documented so this stuff is
>>> obvious, and (b) updated so that kdump stands a chance of working even
>>> if the KVM stub is still in place at the point the host kernel panics.
>>>
>>> Another reason why documentation is important here is that we need to
>>> make it clear to alternative hypervisors that the host kernel may issue
>>> a HVC call at any moment due to a crash with particular arguments, and
>>> that the host kernel expects a certain behaviour in that case, and that
>>> the hypervisor does not crash.
>>>
>>> For example, how will Xen behave - is introducing these changes going
>>> to cause a regression with Xen? Does anyone even know the answer to
>>> that? From what I can see, it seems we'll end up calling Xen's
>>> hypervisor with a random r12 value (which it uses as a reason code)
>>> but without the 0xea1 immediate constant in the HVC instruction.
>>> Beyond that, I've no idea.
>>
>> I fail to see why you would issue a hyp stub hypercall if you're booted
>> under *any* hypervisor. The only way you can have a valid hyp stub is
>> because the kernel was booted at EL2/HYP. If you're running under Xen,
>> KVM or whatever other hypervisor, you're booted at EL1/SVC, you only
>> have the hypercall API exposed by that hypervisor, and nothing else. You
>> can't even install the stub the first place.
>>
>> So any code path that tries to tear down KVM would better check that the
>> kernel was entered at HYP. If it doesn't, it is broken.
>
> Let me refresh your memory. This thread is about kexec/kdump on 32-bit
> ARM of the _host_ kernel, which will be entered in HYP mode.
>
> I've never used Xen, so I've no idea about it. I'm merely pointing out
> the possibilities as I see them.
>
> Let me repeat the on-going theme here. Documentation. Documentation.
> Documentation. Documentation. Documentation. Documentation.
> Documentation. Documentation. Documentation. Documentation.
> Documentation. Documentation. Documentation. Documentation.
> Documentation. Documentation. Documentation. Documentation.
> Documentation. Documentation. Documentation. Documentation.
> Documentation. Documentation. Documentation. Documentation.
>
> Is the message getting through yet? Can you see the waste of time
> the lack of documentation is having yet - not only my time, but your
> time replying to these emails.
I'm all for more documentation. Once we agree on what the API is going
to be (as you're about to change it), I'll be happy to write something up.
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v4 0/5] drm/dp: Implement CRC debugfs API
From: Tomeu Vizoso @ 2017-01-09 13:32 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
this series builds up on the API for exposing captured CRCs through
debugfs.
It adds new DP helpers for starting and stopping CRC capture and gets
the Rockchip driver to use it.
Also had to add a connector backpointer to the drm_dp_aux struct so we could
wait for the right vblank and store the CRCs afterwards, I will be glad
to hear about better alternatives.
With these patches, tests in IGT such as kms_pipe_crc_basic and
kms_plane do pass on RK3288.
In this v4, "drm/dp: add helpers for capture of frame CRCs" has been
modified to address some of the comments from Sean Paul.
Thanks,
Tomeu
Tomeu Vizoso (5):
drm/dp: add connector backpointer to drm_dp_aux
drm/bridge: analogix_dp: set connector to drm_dp_aux
drm/dp: add helpers for capture of frame CRCs
drm/bridge: analogix_dp: add helpers for capture of frame CRCs
drm/rockchip: Implement CRC debugfs API
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 34 ++++--
drivers/gpu/drm/drm_dp_helper.c | 129 +++++++++++++++++++++
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 42 +++++++
include/drm/bridge/analogix_dp.h | 3 +
include/drm/drm_dp_helper.h | 9 ++
5 files changed, 209 insertions(+), 8 deletions(-)
--
2.9.3
^ permalink raw reply
* [PATCH v4 5/5] drm/rockchip: Implement CRC debugfs API
From: Tomeu Vizoso @ 2017-01-09 13:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170109133237.17413-1-tomeu.vizoso@collabora.com>
Implement the .set_crc_source() callback and call the DP helpers
accordingly to start and stop CRC capture.
This is only done if this CRTC is currently using the eDP connector.
v3: Remove superfluous check on rockchip_crtc_state->output_type
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
---
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 42 +++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index fb5f001f51c3..6e5eb1aa182a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -19,6 +19,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_flip_work.h>
#include <drm/drm_plane_helper.h>
+#include <drm/bridge/analogix_dp.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -1105,6 +1106,46 @@ static void vop_crtc_destroy_state(struct drm_crtc *crtc,
kfree(s);
}
+static struct drm_connector *vop_get_edp_connector(struct vop *vop)
+{
+ struct drm_crtc *crtc = &vop->crtc;
+ struct drm_connector *connector;
+
+ mutex_lock(&crtc->dev->mode_config.mutex);
+ drm_for_each_connector(connector, crtc->dev)
+ if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+ mutex_unlock(&crtc->dev->mode_config.mutex);
+ return connector;
+ }
+ mutex_unlock(&crtc->dev->mode_config.mutex);
+
+ return NULL;
+}
+
+static int vop_crtc_set_crc_source(struct drm_crtc *crtc,
+ const char *source_name, size_t *values_cnt)
+{
+ struct vop *vop = to_vop(crtc);
+ struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
+ struct drm_connector *connector;
+ int ret;
+
+ connector = vop_get_edp_connector(vop);
+ if (!connector)
+ return -EINVAL;
+
+ *values_cnt = 3;
+
+ if (source_name && strcmp(source_name, "auto") == 0)
+ ret = analogix_dp_start_crc(connector);
+ else if (!source_name)
+ ret = analogix_dp_stop_crc(connector);
+ else
+ ret = -EINVAL;
+
+ return ret;
+}
+
static const struct drm_crtc_funcs vop_crtc_funcs = {
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
@@ -1112,6 +1153,7 @@ static const struct drm_crtc_funcs vop_crtc_funcs = {
.reset = vop_crtc_reset,
.atomic_duplicate_state = vop_crtc_duplicate_state,
.atomic_destroy_state = vop_crtc_destroy_state,
+ .set_crc_source = vop_crtc_set_crc_source,
};
static void vop_fb_unref_worker(struct drm_flip_work *work, void *val)
--
2.9.3
^ permalink raw reply related
* [PATCH v7 00/19] KVM PCIe/MSI passthrough on ARM/ARM64 and IOVA reserved regions
From: Eric Auger @ 2017-01-09 13:45 UTC (permalink / raw)
To: linux-arm-kernel
Following LPC discussions, we now report reserved regions through
the iommu-group sysfs reserved_regions attribute file.
Reserved regions are populated through the IOMMU get_resv_region
callback (former get_dm_regions), now implemented by amd-iommu,
intel-iommu and arm-smmu:
- the intel-iommu reports the [0xfee00000 - 0xfeefffff] MSI window
as a reserved region and RMRR regions as direct-mapped regions.
- the amd-iommu reports device direct mapped regions, the MSI region
and HT regions.
- the arm-smmu reports the MSI window (arbitrarily located at
0x8000000 and 1MB large).
Unsafe interrupt assignment is tested by enumerating all MSI irq
domains and checking MSI remapping is supported in the above hierarchy.
This check is done in case we detect the iommu translates MSI
(an IOMMU_RESV_MSI window exists). Otherwise the IRQ remapping
capability is checked at IOMMU level. Obviously this is a defensive
IRQ safety assessment: Assuming there are several MSI controllers
in the system and at least one does not implement IRQ remapping,
the assignment will be considered as unsafe (even if this controller
is not acessible from the assigned devices).
The two first patches stem from Robin's branch:
http://linux-arm.org/git?p=linux-rm.git;a=shortlog;h=refs/heads/iommu/misc
They are likely to be pulled separately.
Best Regards
Eric
Git: complete series available at
https://github.com/eauger/linux/tree/v4.10-rc3-reserved-v7
History:
PATCHv6 -> PATCHv7:
- "iommu/dma: Implement PCI allocation optimisation" was added to apply
"iommu/dma: Allow MSI-only cookies"
- report Intel RMRR as direct-mapped regions
- report the type in the iommu group sysfs reserved_regions file
- do not merge regions of different types when building the list
of reserved regions
- intgerate Robin's "iommu/dma: Allow MSI-only cookies" last
version
- update Documentation/ABI/testing/sysfs-kernel-iommu_groups
- rename IOMMU_RESV_NOMAP into IOMMU_RESV_RESERVED
PATCHv5 -> PATCHv6
- Introduce IRQ_DOMAIN_FLAG_MSI as suggested by Marc
- irq_domain_is_msi, irq_domain_is_msi_remap,
irq_domain_hierarchical_is_msi_remap,
- set IRQ_DOMAIN_FLAG_MSI in msi_create_irq_domain
- fix compil issue on i386
- rework test at VFIO level
RFCv4 -> PATCHv5
- fix IRQ security assessment by looking at irq domain parents
- check DOMAIN_BUS_FSL_MC_MSI irq domains
- AMD MSI and HT regions are exposed in iommu group sysfs
RFCv3 -> RFCv4:
- arm-smmu driver does not register PCI host bridge windows as
reserved regions anymore
- Implement reserved region get/put callbacks also in arm-smmuv3
- take the iommu_group lock on iommu_get_group_resv_regions
- add a type field in iommu_resv_region instead of using prot
- init the region list_head in iommu_alloc_resv_region, also
add type parameter
- iommu_insert_resv_region manage overlaps and sort reserved
windows
- address IRQ safety assessment by enumerating all the MSI irq
domains and checking the MSI_REMAP flag
- update Documentation/ABI/testing/sysfs-kernel-iommu_groups
RFC v2 -> v3:
- switch to an iommu-group sysfs API
- use new dummy allocator provided by Robin
- dummy allocator initialized by vfio-iommu-type1 after enumerating
the reserved regions
- at the moment ARM MSI base address/size is left unchanged compared
to v2
- we currently report reserved regions and not usable IOVA regions as
requested by Alex
RFC v1 -> v2:
- fix intel_add_reserved_regions
- add mutex lock/unlock in vfio_iommu_type1
Eric Auger (17):
iommu: Rename iommu_dm_regions into iommu_resv_regions
iommu: Add a new type field in iommu_resv_region
iommu: iommu_alloc_resv_region
iommu: Only map direct mapped regions
iommu: iommu_get_group_resv_regions
iommu: Implement reserved_regions iommu-group sysfs file
iommu/vt-d: Implement reserved region get/put callbacks
iommu/amd: Declare MSI and HT regions as reserved IOVA regions
iommu/arm-smmu: Implement reserved region get/put callbacks
iommu/arm-smmu-v3: Implement reserved region get/put callbacks
irqdomain: Add irq domain MSI and MSI_REMAP flags
genirq/msi: Set IRQ_DOMAIN_FLAG_MSI on MSI domain creation
irqdomain: irq_domain_check_msi_remap
irqchip/gicv3-its: Sets IRQ_DOMAIN_FLAG_MSI_REMAP
vfio/type1: Allow transparent MSI IOVA allocation
vfio/type1: Check MSI remapping at irq domain level
iommu/arm-smmu: Do not advertise IOMMU_CAP_INTR_REMAP anymore
Robin Murphy (2):
iommu/dma: Implement PCI allocation optimisation
iommu/dma: Allow MSI-only cookies
.../ABI/testing/sysfs-kernel-iommu_groups | 12 ++
drivers/iommu/amd_iommu.c | 54 ++++---
drivers/iommu/arm-smmu-v3.c | 30 +++-
drivers/iommu/arm-smmu.c | 30 +++-
drivers/iommu/dma-iommu.c | 138 ++++++++++++----
drivers/iommu/intel-iommu.c | 92 ++++++++---
drivers/iommu/iommu.c | 179 +++++++++++++++++++--
drivers/irqchip/irq-gic-v3-its.c | 1 +
drivers/vfio/vfio_iommu_type1.c | 37 ++++-
include/linux/dma-iommu.h | 6 +
include/linux/iommu.h | 46 ++++--
include/linux/irqdomain.h | 36 +++++
kernel/irq/irqdomain.c | 39 +++++
kernel/irq/msi.c | 4 +-
14 files changed, 606 insertions(+), 98 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH v7 01/19] iommu/dma: Implement PCI allocation optimisation
From: Eric Auger @ 2017-01-09 13:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483969570-3154-1-git-send-email-eric.auger@redhat.com>
From: Robin Murphy <robin.murphy@arm.com>
Whilst PCI devices may have 64-bit DMA masks, they still benefit from
using 32-bit addresses wherever possible in order to avoid DAC (PCI) or
longer address packets (PCIe), which may incur a performance overhead.
Implement the same optimisation as other allocators by trying to get a
32-bit address first, only falling back to the full mask if that fails.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/dma-iommu.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 2db0d64..a59ca47 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -204,19 +204,28 @@ int dma_direction_to_prot(enum dma_data_direction dir, bool coherent)
}
static struct iova *__alloc_iova(struct iommu_domain *domain, size_t size,
- dma_addr_t dma_limit)
+ dma_addr_t dma_limit, struct device *dev)
{
struct iova_domain *iovad = cookie_iovad(domain);
unsigned long shift = iova_shift(iovad);
unsigned long length = iova_align(iovad, size) >> shift;
+ struct iova *iova = NULL;
if (domain->geometry.force_aperture)
dma_limit = min(dma_limit, domain->geometry.aperture_end);
+
+ /* Try to get PCI devices a SAC address */
+ if (dma_limit > DMA_BIT_MASK(32) && dev_is_pci(dev))
+ iova = alloc_iova(iovad, length, DMA_BIT_MASK(32) >> shift,
+ true);
/*
* Enforce size-alignment to be safe - there could perhaps be an
* attribute to control this per-device, or at least per-domain...
*/
- return alloc_iova(iovad, length, dma_limit >> shift, true);
+ if (!iova)
+ iova = alloc_iova(iovad, length, dma_limit >> shift, true);
+
+ return iova;
}
/* The IOVA allocator knows what we mapped, so just unmap whatever that was */
@@ -369,7 +378,7 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
if (!pages)
return NULL;
- iova = __alloc_iova(domain, size, dev->coherent_dma_mask);
+ iova = __alloc_iova(domain, size, dev->coherent_dma_mask, dev);
if (!iova)
goto out_free_pages;
@@ -440,7 +449,7 @@ static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
struct iova_domain *iovad = cookie_iovad(domain);
size_t iova_off = iova_offset(iovad, phys);
size_t len = iova_align(iovad, size + iova_off);
- struct iova *iova = __alloc_iova(domain, len, dma_get_mask(dev));
+ struct iova *iova = __alloc_iova(domain, len, dma_get_mask(dev), dev);
if (!iova)
return DMA_ERROR_CODE;
@@ -598,7 +607,7 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
prev = s;
}
- iova = __alloc_iova(domain, iova_len, dma_get_mask(dev));
+ iova = __alloc_iova(domain, iova_len, dma_get_mask(dev), dev);
if (!iova)
goto out_restore_sg;
@@ -675,7 +684,7 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
if (!msi_page)
return NULL;
- iova = __alloc_iova(domain, iovad->granule, dma_get_mask(dev));
+ iova = __alloc_iova(domain, iovad->granule, dma_get_mask(dev), dev);
if (!iova)
goto out_free_page;
--
1.9.1
^ permalink raw reply related
* [PATCH v7 02/19] iommu/dma: Allow MSI-only cookies
From: Eric Auger @ 2017-01-09 13:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483969570-3154-1-git-send-email-eric.auger@redhat.com>
From: Robin Murphy <robin.murphy@arm.com>
IOMMU domain users such as VFIO face a similar problem to DMA API ops
with regard to mapping MSI messages in systems where the MSI write is
subject to IOMMU translation. With the relevant infrastructure now in
place for managed DMA domains, it's actually really simple for other
users to piggyback off that and reap the benefits without giving up
their own IOVA management, and without having to reinvent their own
wheel in the MSI layer.
Allow such users to opt into automatic MSI remapping by dedicating a
region of their IOVA space to a managed cookie, and extend the mapping
routine to implement a trivial linear allocator in such cases, to avoid
the needless overhead of a full-blown IOVA domain.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/dma-iommu.c | 119 +++++++++++++++++++++++++++++++++++++---------
include/linux/dma-iommu.h | 6 +++
2 files changed, 102 insertions(+), 23 deletions(-)
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index a59ca47..008ad88 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -37,15 +37,50 @@ struct iommu_dma_msi_page {
phys_addr_t phys;
};
+enum iommu_dma_cookie_type {
+ IOMMU_DMA_IOVA_COOKIE,
+ IOMMU_DMA_MSI_COOKIE,
+};
+
struct iommu_dma_cookie {
- struct iova_domain iovad;
- struct list_head msi_page_list;
- spinlock_t msi_lock;
+ enum iommu_dma_cookie_type type;
+ union {
+ /* Full allocator for IOMMU_DMA_IOVA_COOKIE */
+ struct iova_domain iovad;
+ /* Trivial linear page allocator for IOMMU_DMA_MSI_COOKIE */
+ dma_addr_t msi_iova;
+ };
+ struct list_head msi_page_list;
+ spinlock_t msi_lock;
};
+static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie)
+{
+ if (cookie->type == IOMMU_DMA_IOVA_COOKIE)
+ return cookie->iovad.granule;
+ return PAGE_SIZE;
+}
+
static inline struct iova_domain *cookie_iovad(struct iommu_domain *domain)
{
- return &((struct iommu_dma_cookie *)domain->iova_cookie)->iovad;
+ struct iommu_dma_cookie *cookie = domain->iova_cookie;
+
+ if (cookie->type == IOMMU_DMA_IOVA_COOKIE)
+ return &cookie->iovad;
+ return NULL;
+}
+
+static struct iommu_dma_cookie *cookie_alloc(enum iommu_dma_cookie_type type)
+{
+ struct iommu_dma_cookie *cookie;
+
+ cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
+ if (cookie) {
+ spin_lock_init(&cookie->msi_lock);
+ INIT_LIST_HEAD(&cookie->msi_page_list);
+ cookie->type = type;
+ }
+ return cookie;
}
int iommu_dma_init(void)
@@ -62,25 +97,53 @@ int iommu_dma_init(void)
*/
int iommu_get_dma_cookie(struct iommu_domain *domain)
{
+ if (domain->iova_cookie)
+ return -EEXIST;
+
+ domain->iova_cookie = cookie_alloc(IOMMU_DMA_IOVA_COOKIE);
+ if (!domain->iova_cookie)
+ return -ENOMEM;
+
+ return 0;
+}
+EXPORT_SYMBOL(iommu_get_dma_cookie);
+
+/**
+ * iommu_get_msi_cookie - Acquire just MSI remapping resources
+ * @domain: IOMMU domain to prepare
+ * @base: Start address of IOVA region for MSI mappings
+ *
+ * Users who manage their own IOVA allocation and do not want DMA API support,
+ * but would still like to take advantage of automatic MSI remapping, can use
+ * this to initialise their own domain appropriately. Users should reserve a
+ * contiguous IOVA region, starting at @base, large enough to accommodate the
+ * number of PAGE_SIZE mappings necessary to cover every MSI doorbell address
+ * used by the devices attached to @domain.
+ */
+int iommu_get_msi_cookie(struct iommu_domain *domain, dma_addr_t base)
+{
struct iommu_dma_cookie *cookie;
+ if (domain->type != IOMMU_DOMAIN_UNMANAGED)
+ return -EINVAL;
+
if (domain->iova_cookie)
return -EEXIST;
- cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
+ cookie = cookie_alloc(IOMMU_DMA_MSI_COOKIE);
if (!cookie)
return -ENOMEM;
- spin_lock_init(&cookie->msi_lock);
- INIT_LIST_HEAD(&cookie->msi_page_list);
+ cookie->msi_iova = base;
domain->iova_cookie = cookie;
return 0;
}
-EXPORT_SYMBOL(iommu_get_dma_cookie);
+EXPORT_SYMBOL(iommu_get_msi_cookie);
/**
* iommu_put_dma_cookie - Release a domain's DMA mapping resources
- * @domain: IOMMU domain previously prepared by iommu_get_dma_cookie()
+ * @domain: IOMMU domain previously prepared by iommu_get_dma_cookie() or
+ * iommu_get_msi_cookie()
*
* IOMMU drivers should normally call this from their domain_free callback.
*/
@@ -92,7 +155,7 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)
if (!cookie)
return;
- if (cookie->iovad.granule)
+ if (cookie->type == IOMMU_DMA_IOVA_COOKIE && cookie->iovad.granule)
put_iova_domain(&cookie->iovad);
list_for_each_entry_safe(msi, tmp, &cookie->msi_page_list, list) {
@@ -137,11 +200,12 @@ static void iova_reserve_pci_windows(struct pci_dev *dev,
int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
u64 size, struct device *dev)
{
- struct iova_domain *iovad = cookie_iovad(domain);
+ struct iommu_dma_cookie *cookie = domain->iova_cookie;
+ struct iova_domain *iovad = &cookie->iovad;
unsigned long order, base_pfn, end_pfn;
- if (!iovad)
- return -ENODEV;
+ if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE)
+ return -EINVAL;
/* Use the smallest supported page size for IOVA granularity */
order = __ffs(domain->pgsize_bitmap);
@@ -671,11 +735,12 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
{
struct iommu_dma_cookie *cookie = domain->iova_cookie;
struct iommu_dma_msi_page *msi_page;
- struct iova_domain *iovad = &cookie->iovad;
+ struct iova_domain *iovad = cookie_iovad(domain);
struct iova *iova;
int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
+ size_t size = cookie_msi_granule(cookie);
- msi_addr &= ~(phys_addr_t)iova_mask(iovad);
+ msi_addr &= ~(phys_addr_t)(size - 1);
list_for_each_entry(msi_page, &cookie->msi_page_list, list)
if (msi_page->phys == msi_addr)
return msi_page;
@@ -684,13 +749,18 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
if (!msi_page)
return NULL;
- iova = __alloc_iova(domain, iovad->granule, dma_get_mask(dev), dev);
- if (!iova)
- goto out_free_page;
-
msi_page->phys = msi_addr;
- msi_page->iova = iova_dma_addr(iovad, iova);
- if (iommu_map(domain, msi_page->iova, msi_addr, iovad->granule, prot))
+ if (iovad) {
+ iova = __alloc_iova(domain, size, dma_get_mask(dev), dev);
+ if (!iova)
+ goto out_free_page;
+ msi_page->iova = iova_dma_addr(iovad, iova);
+ } else {
+ msi_page->iova = cookie->msi_iova;
+ cookie->msi_iova += size;
+ }
+
+ if (iommu_map(domain, msi_page->iova, msi_addr, size, prot))
goto out_free_iova;
INIT_LIST_HEAD(&msi_page->list);
@@ -698,7 +768,10 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
return msi_page;
out_free_iova:
- __free_iova(iovad, iova);
+ if (iovad)
+ __free_iova(iovad, iova);
+ else
+ cookie->msi_iova -= size;
out_free_page:
kfree(msi_page);
return NULL;
@@ -739,7 +812,7 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
msg->data = ~0U;
} else {
msg->address_hi = upper_32_bits(msi_page->iova);
- msg->address_lo &= iova_mask(&cookie->iovad);
+ msg->address_lo &= cookie_msi_granule(cookie) - 1;
msg->address_lo += lower_32_bits(msi_page->iova);
}
}
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index 7f7e9a7..28df844 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -27,6 +27,7 @@
/* Domain management interface for IOMMU drivers */
int iommu_get_dma_cookie(struct iommu_domain *domain);
+int iommu_get_msi_cookie(struct iommu_domain *domain, dma_addr_t base);
void iommu_put_dma_cookie(struct iommu_domain *domain);
/* Setup call for arch DMA mapping code */
@@ -86,6 +87,11 @@ static inline int iommu_get_dma_cookie(struct iommu_domain *domain)
return -ENODEV;
}
+static inline int iommu_get_msi_cookie(struct iommu_domain *domain, dma_addr_t base)
+{
+ return -ENODEV;
+}
+
static inline void iommu_put_dma_cookie(struct iommu_domain *domain)
{
}
--
1.9.1
^ permalink raw reply related
* [PATCH v7 03/19] iommu: Rename iommu_dm_regions into iommu_resv_regions
From: Eric Auger @ 2017-01-09 13:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483969570-3154-1-git-send-email-eric.auger@redhat.com>
We want to extend the callbacks used for dm regions and
use them for reserved regions. Reserved regions can be
- directly mapped regions
- regions that cannot be iommu mapped (PCI host bridge windows, ...)
- MSI regions (because they belong to another address space or because
they are not translated by the IOMMU and need special handling)
So let's rename the struct and also the callbacks.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Acked-by: Robin Murphy <robin.murphy@arm.com>
---
v3 -> v4:
- add Robin's A-b
---
drivers/iommu/amd_iommu.c | 20 ++++++++++----------
drivers/iommu/iommu.c | 22 +++++++++++-----------
include/linux/iommu.h | 29 +++++++++++++++--------------
3 files changed, 36 insertions(+), 35 deletions(-)
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 3ef0f42..f7a024f 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -3161,8 +3161,8 @@ static bool amd_iommu_capable(enum iommu_cap cap)
return false;
}
-static void amd_iommu_get_dm_regions(struct device *dev,
- struct list_head *head)
+static void amd_iommu_get_resv_regions(struct device *dev,
+ struct list_head *head)
{
struct unity_map_entry *entry;
int devid;
@@ -3172,7 +3172,7 @@ static void amd_iommu_get_dm_regions(struct device *dev,
return;
list_for_each_entry(entry, &amd_iommu_unity_map, list) {
- struct iommu_dm_region *region;
+ struct iommu_resv_region *region;
if (devid < entry->devid_start || devid > entry->devid_end)
continue;
@@ -3195,18 +3195,18 @@ static void amd_iommu_get_dm_regions(struct device *dev,
}
}
-static void amd_iommu_put_dm_regions(struct device *dev,
+static void amd_iommu_put_resv_regions(struct device *dev,
struct list_head *head)
{
- struct iommu_dm_region *entry, *next;
+ struct iommu_resv_region *entry, *next;
list_for_each_entry_safe(entry, next, head, list)
kfree(entry);
}
-static void amd_iommu_apply_dm_region(struct device *dev,
+static void amd_iommu_apply_resv_region(struct device *dev,
struct iommu_domain *domain,
- struct iommu_dm_region *region)
+ struct iommu_resv_region *region)
{
struct dma_ops_domain *dma_dom = to_dma_ops_domain(to_pdomain(domain));
unsigned long start, end;
@@ -3230,9 +3230,9 @@ static void amd_iommu_apply_dm_region(struct device *dev,
.add_device = amd_iommu_add_device,
.remove_device = amd_iommu_remove_device,
.device_group = amd_iommu_device_group,
- .get_dm_regions = amd_iommu_get_dm_regions,
- .put_dm_regions = amd_iommu_put_dm_regions,
- .apply_dm_region = amd_iommu_apply_dm_region,
+ .get_resv_regions = amd_iommu_get_resv_regions,
+ .put_resv_regions = amd_iommu_put_resv_regions,
+ .apply_resv_region = amd_iommu_apply_resv_region,
.pgsize_bitmap = AMD_IOMMU_PGSIZES,
};
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index dbe7f65..1cee5c3 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -318,7 +318,7 @@ static int iommu_group_create_direct_mappings(struct iommu_group *group,
struct device *dev)
{
struct iommu_domain *domain = group->default_domain;
- struct iommu_dm_region *entry;
+ struct iommu_resv_region *entry;
struct list_head mappings;
unsigned long pg_size;
int ret = 0;
@@ -331,14 +331,14 @@ static int iommu_group_create_direct_mappings(struct iommu_group *group,
pg_size = 1UL << __ffs(domain->pgsize_bitmap);
INIT_LIST_HEAD(&mappings);
- iommu_get_dm_regions(dev, &mappings);
+ iommu_get_resv_regions(dev, &mappings);
/* We need to consider overlapping regions for different devices */
list_for_each_entry(entry, &mappings, list) {
dma_addr_t start, end, addr;
- if (domain->ops->apply_dm_region)
- domain->ops->apply_dm_region(dev, domain, entry);
+ if (domain->ops->apply_resv_region)
+ domain->ops->apply_resv_region(dev, domain, entry);
start = ALIGN(entry->start, pg_size);
end = ALIGN(entry->start + entry->length, pg_size);
@@ -358,7 +358,7 @@ static int iommu_group_create_direct_mappings(struct iommu_group *group,
}
out:
- iommu_put_dm_regions(dev, &mappings);
+ iommu_put_resv_regions(dev, &mappings);
return ret;
}
@@ -1559,20 +1559,20 @@ int iommu_domain_set_attr(struct iommu_domain *domain,
}
EXPORT_SYMBOL_GPL(iommu_domain_set_attr);
-void iommu_get_dm_regions(struct device *dev, struct list_head *list)
+void iommu_get_resv_regions(struct device *dev, struct list_head *list)
{
const struct iommu_ops *ops = dev->bus->iommu_ops;
- if (ops && ops->get_dm_regions)
- ops->get_dm_regions(dev, list);
+ if (ops && ops->get_resv_regions)
+ ops->get_resv_regions(dev, list);
}
-void iommu_put_dm_regions(struct device *dev, struct list_head *list)
+void iommu_put_resv_regions(struct device *dev, struct list_head *list)
{
const struct iommu_ops *ops = dev->bus->iommu_ops;
- if (ops && ops->put_dm_regions)
- ops->put_dm_regions(dev, list);
+ if (ops && ops->put_resv_regions)
+ ops->put_resv_regions(dev, list);
}
/* Request that a device is direct mapped by the IOMMU */
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 0ff5111..bfecb8b 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -118,13 +118,13 @@ enum iommu_attr {
};
/**
- * struct iommu_dm_region - descriptor for a direct mapped memory region
+ * struct iommu_resv_region - descriptor for a reserved memory region
* @list: Linked list pointers
* @start: System physical start address of the region
* @length: Length of the region in bytes
* @prot: IOMMU Protection flags (READ/WRITE/...)
*/
-struct iommu_dm_region {
+struct iommu_resv_region {
struct list_head list;
phys_addr_t start;
size_t length;
@@ -150,9 +150,9 @@ struct iommu_dm_region {
* @device_group: find iommu group for a particular device
* @domain_get_attr: Query domain attributes
* @domain_set_attr: Change domain attributes
- * @get_dm_regions: Request list of direct mapping requirements for a device
- * @put_dm_regions: Free list of direct mapping requirements for a device
- * @apply_dm_region: Temporary helper call-back for iova reserved ranges
+ * @get_resv_regions: Request list of reserved regions for a device
+ * @put_resv_regions: Free list of reserved regions for a device
+ * @apply_resv_region: Temporary helper call-back for iova reserved ranges
* @domain_window_enable: Configure and enable a particular window for a domain
* @domain_window_disable: Disable a particular window for a domain
* @domain_set_windows: Set the number of windows for a domain
@@ -184,11 +184,12 @@ struct iommu_ops {
int (*domain_set_attr)(struct iommu_domain *domain,
enum iommu_attr attr, void *data);
- /* Request/Free a list of direct mapping requirements for a device */
- void (*get_dm_regions)(struct device *dev, struct list_head *list);
- void (*put_dm_regions)(struct device *dev, struct list_head *list);
- void (*apply_dm_region)(struct device *dev, struct iommu_domain *domain,
- struct iommu_dm_region *region);
+ /* Request/Free a list of reserved regions for a device */
+ void (*get_resv_regions)(struct device *dev, struct list_head *list);
+ void (*put_resv_regions)(struct device *dev, struct list_head *list);
+ void (*apply_resv_region)(struct device *dev,
+ struct iommu_domain *domain,
+ struct iommu_resv_region *region);
/* Window handling functions */
int (*domain_window_enable)(struct iommu_domain *domain, u32 wnd_nr,
@@ -233,8 +234,8 @@ extern size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long io
extern void iommu_set_fault_handler(struct iommu_domain *domain,
iommu_fault_handler_t handler, void *token);
-extern void iommu_get_dm_regions(struct device *dev, struct list_head *list);
-extern void iommu_put_dm_regions(struct device *dev, struct list_head *list);
+extern void iommu_get_resv_regions(struct device *dev, struct list_head *list);
+extern void iommu_put_resv_regions(struct device *dev, struct list_head *list);
extern int iommu_request_dm_for_dev(struct device *dev);
extern int iommu_attach_group(struct iommu_domain *domain,
@@ -443,12 +444,12 @@ static inline void iommu_set_fault_handler(struct iommu_domain *domain,
{
}
-static inline void iommu_get_dm_regions(struct device *dev,
+static inline void iommu_get_resv_regions(struct device *dev,
struct list_head *list)
{
}
-static inline void iommu_put_dm_regions(struct device *dev,
+static inline void iommu_put_resv_regions(struct device *dev,
struct list_head *list)
{
}
--
1.9.1
^ permalink raw reply related
* [PATCH v7 04/19] iommu: Add a new type field in iommu_resv_region
From: Eric Auger @ 2017-01-09 13:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483969570-3154-1-git-send-email-eric.auger@redhat.com>
We introduce a new field to differentiate the reserved region
types and specialize the apply_resv_region implementation.
Legacy direct mapped regions have IOMMU_RESV_DIRECT type.
We introduce 2 new reserved memory types:
- IOMMU_RESV_MSI will characterize MSI regions that are mapped
- IOMMU_RESV_RESERVED characterize regions that cannot by mapped.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v6 -> v7:
- rename IOMMU_RESV_NOMAP into IOMMU_RESV_RESERVED
---
drivers/iommu/amd_iommu.c | 1 +
include/linux/iommu.h | 7 +++++++
2 files changed, 8 insertions(+)
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index f7a024f..5f7ea4f 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -3186,6 +3186,7 @@ static void amd_iommu_get_resv_regions(struct device *dev,
region->start = entry->address_start;
region->length = entry->address_end - entry->address_start;
+ region->type = IOMMU_RESV_DIRECT;
if (entry->prot & IOMMU_PROT_IR)
region->prot |= IOMMU_READ;
if (entry->prot & IOMMU_PROT_IW)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index bfecb8b..233a6bf 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -117,18 +117,25 @@ enum iommu_attr {
DOMAIN_ATTR_MAX,
};
+/* These are the possible reserved region types */
+#define IOMMU_RESV_DIRECT (1 << 0)
+#define IOMMU_RESV_RESERVED (1 << 1)
+#define IOMMU_RESV_MSI (1 << 2)
+
/**
* struct iommu_resv_region - descriptor for a reserved memory region
* @list: Linked list pointers
* @start: System physical start address of the region
* @length: Length of the region in bytes
* @prot: IOMMU Protection flags (READ/WRITE/...)
+ * @type: Type of the reserved region
*/
struct iommu_resv_region {
struct list_head list;
phys_addr_t start;
size_t length;
int prot;
+ int type;
};
#ifdef CONFIG_IOMMU_API
--
1.9.1
^ permalink raw reply related
* [PATCH v7 05/19] iommu: iommu_alloc_resv_region
From: Eric Auger @ 2017-01-09 13:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483969570-3154-1-git-send-email-eric.auger@redhat.com>
Introduce a new helper serving the purpose to allocate a reserved
region. This will be used in iommu driver implementing reserved
region callbacks.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v3 -> v4:
- add INIT_LIST_HEAD(®ion->list)
- use int for prot param and add int type param
- remove implementation outside of CONFIG_IOMMU_API
---
drivers/iommu/iommu.c | 18 ++++++++++++++++++
include/linux/iommu.h | 2 ++
2 files changed, 20 insertions(+)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 1cee5c3..927878d 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1575,6 +1575,24 @@ void iommu_put_resv_regions(struct device *dev, struct list_head *list)
ops->put_resv_regions(dev, list);
}
+struct iommu_resv_region *iommu_alloc_resv_region(phys_addr_t start,
+ size_t length,
+ int prot, int type)
+{
+ struct iommu_resv_region *region;
+
+ region = kzalloc(sizeof(*region), GFP_KERNEL);
+ if (!region)
+ return NULL;
+
+ INIT_LIST_HEAD(®ion->list);
+ region->start = start;
+ region->length = length;
+ region->prot = prot;
+ region->type = type;
+ return region;
+}
+
/* Request that a device is direct mapped by the IOMMU */
int iommu_request_dm_for_dev(struct device *dev)
{
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 233a6bf..f6bb55d3 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -244,6 +244,8 @@ extern void iommu_set_fault_handler(struct iommu_domain *domain,
extern void iommu_get_resv_regions(struct device *dev, struct list_head *list);
extern void iommu_put_resv_regions(struct device *dev, struct list_head *list);
extern int iommu_request_dm_for_dev(struct device *dev);
+extern struct iommu_resv_region *
+iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot, int type);
extern int iommu_attach_group(struct iommu_domain *domain,
struct iommu_group *group);
--
1.9.1
^ permalink raw reply related
* [PATCH v7 06/19] iommu: Only map direct mapped regions
From: Eric Auger @ 2017-01-09 13:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483969570-3154-1-git-send-email-eric.auger@redhat.com>
As we introduced new reserved region types which do not require
mapping, let's make sure we only map direct mapped regions.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v3 -> v4:
- use region's type and reword commit message and title
---
drivers/iommu/iommu.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 927878d..41c1906 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -343,6 +343,9 @@ static int iommu_group_create_direct_mappings(struct iommu_group *group,
start = ALIGN(entry->start, pg_size);
end = ALIGN(entry->start + entry->length, pg_size);
+ if (entry->type != IOMMU_RESV_DIRECT)
+ continue;
+
for (addr = start; addr < end; addr += pg_size) {
phys_addr_t phys_addr;
--
1.9.1
^ permalink raw reply related
* [PATCH v7 07/19] iommu: iommu_get_group_resv_regions
From: Eric Auger @ 2017-01-09 13:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483969570-3154-1-git-send-email-eric.auger@redhat.com>
Introduce iommu_get_group_resv_regions whose role consists in
enumerating all devices from the group and collecting their
reserved regions. The list is sorted and overlaps between
regions of the same type are handled by merging the regions.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v6 -> v7:
- avoid merge of regions of different type
v3 -> v4:
- take the iommu_group lock in iommu_get_group_resv_regions
- the list now is sorted and overlaps are checked
NOTE:
- we do not move list elements from device to group list since
the iommu_put_resv_regions() could not be called.
- at the moment I did not introduce any iommu_put_group_resv_regions
since it simply consists in voiding/freeing the list
---
drivers/iommu/iommu.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/iommu.h | 8 +++++
2 files changed, 106 insertions(+)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 41c1906..640056b 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -133,6 +133,104 @@ static ssize_t iommu_group_show_name(struct iommu_group *group, char *buf)
return sprintf(buf, "%s\n", group->name);
}
+/**
+ * iommu_insert_resv_region - Insert a new region in the
+ * list of reserved regions.
+ * @new: new region to insert
+ * @regions: list of regions
+ *
+ * The new element is sorted by address with respect to the other
+ * regions of the same type. In case it overlaps with another
+ * region of the same type, regions are merged. In case it
+ * overlaps with another region of different type, regions are
+ * not merged.
+ */
+static int iommu_insert_resv_region(struct iommu_resv_region *new,
+ struct list_head *regions)
+{
+ struct iommu_resv_region *region;
+ phys_addr_t start = new->start;
+ phys_addr_t end = new->start + new->length - 1;
+ struct list_head *pos = regions->next;
+
+ while (pos != regions) {
+ struct iommu_resv_region *entry =
+ list_entry(pos, struct iommu_resv_region, list);
+ phys_addr_t a = entry->start;
+ phys_addr_t b = entry->start + entry->length - 1;
+ int type = entry->type;
+
+ if (end < a) {
+ goto insert;
+ } else if (start > b) {
+ pos = pos->next;
+ } else if ((start >= a) && (end <= b)) {
+ if (new->type == type)
+ goto done;
+ else
+ pos = pos->next;
+ } else {
+ if (new->type == type) {
+ phys_addr_t new_start = min(a, start);
+ phys_addr_t new_end = max(b, end);
+
+ list_del(&entry->list);
+ entry->start = new_start;
+ entry->length = new_end - new_start + 1;
+ iommu_insert_resv_region(entry, regions);
+ } else {
+ pos = pos->next;
+ }
+ }
+ }
+insert:
+ region = iommu_alloc_resv_region(new->start, new->length,
+ new->prot, new->type);
+ if (!region)
+ return -ENOMEM;
+
+ list_add_tail(®ion->list, pos);
+done:
+ return 0;
+}
+
+static int
+iommu_insert_device_resv_regions(struct list_head *dev_resv_regions,
+ struct list_head *group_resv_regions)
+{
+ struct iommu_resv_region *entry;
+ int ret;
+
+ list_for_each_entry(entry, dev_resv_regions, list) {
+ ret = iommu_insert_resv_region(entry, group_resv_regions);
+ if (ret)
+ break;
+ }
+ return ret;
+}
+
+int iommu_get_group_resv_regions(struct iommu_group *group,
+ struct list_head *head)
+{
+ struct iommu_device *device;
+ int ret = 0;
+
+ mutex_lock(&group->mutex);
+ list_for_each_entry(device, &group->devices, list) {
+ struct list_head dev_resv_regions;
+
+ INIT_LIST_HEAD(&dev_resv_regions);
+ iommu_get_resv_regions(device->dev, &dev_resv_regions);
+ ret = iommu_insert_device_resv_regions(&dev_resv_regions, head);
+ iommu_put_resv_regions(device->dev, &dev_resv_regions);
+ if (ret)
+ break;
+ }
+ mutex_unlock(&group->mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(iommu_get_group_resv_regions);
+
static IOMMU_GROUP_ATTR(name, S_IRUGO, iommu_group_show_name, NULL);
static void iommu_group_release(struct kobject *kobj)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index f6bb55d3..bec3730 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -246,6 +246,8 @@ extern void iommu_set_fault_handler(struct iommu_domain *domain,
extern int iommu_request_dm_for_dev(struct device *dev);
extern struct iommu_resv_region *
iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot, int type);
+extern int iommu_get_group_resv_regions(struct iommu_group *group,
+ struct list_head *head);
extern int iommu_attach_group(struct iommu_domain *domain,
struct iommu_group *group);
@@ -463,6 +465,12 @@ static inline void iommu_put_resv_regions(struct device *dev,
{
}
+static inline int iommu_get_group_resv_regions(struct iommu_group *group,
+ struct list_head *head)
+{
+ return -ENODEV;
+}
+
static inline int iommu_request_dm_for_dev(struct device *dev)
{
return -ENODEV;
--
1.9.1
^ permalink raw reply related
* [PATCH v7 08/19] iommu: Implement reserved_regions iommu-group sysfs file
From: Eric Auger @ 2017-01-09 13:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483969570-3154-1-git-send-email-eric.auger@redhat.com>
A new iommu-group sysfs attribute file is introduced. It contains
the list of reserved regions for the iommu-group. Each reserved
region is described on a separate line:
- first field is the start IOVA address,
- second is the end IOVA address,
- third is the type.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v6 -> v7:
- also report the type of the reserved region as a string
- updated ABI documentation
v3 -> v4:
- add cast to long long int when printing to avoid warning on
i386
- change S_IRUGO into 0444
- remove sort. The list is natively sorted now.
The file layout is inspired of /sys/bus/pci/devices/BDF/resource.
I also read Documentation/filesystems/sysfs.txt so I expect this
to be frowned upon.
---
.../ABI/testing/sysfs-kernel-iommu_groups | 12 +++++++
drivers/iommu/iommu.c | 38 ++++++++++++++++++++++
2 files changed, 50 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-kernel-iommu_groups b/Documentation/ABI/testing/sysfs-kernel-iommu_groups
index 9b31556..35c64e0 100644
--- a/Documentation/ABI/testing/sysfs-kernel-iommu_groups
+++ b/Documentation/ABI/testing/sysfs-kernel-iommu_groups
@@ -12,3 +12,15 @@ Description: /sys/kernel/iommu_groups/ contains a number of sub-
file if the IOMMU driver has chosen to register a more
common name for the group.
Users:
+
+What: /sys/kernel/iommu_groups/reserved_regions
+Date: January 2017
+KernelVersion: v4.11
+Contact: Eric Auger <eric.auger@redhat.com>
+Description: /sys/kernel/iommu_groups/reserved_regions list IOVA
+ regions that are reserved. Not necessarily all
+ reserved regions are listed. This is typically used to
+ output direct-mapped, MSI, non mappable regions. Each
+ region is described on a single line: the 1st field is
+ the base IOVA, the second is the end IOVA and the third
+ field describes the type of the region.
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 640056b..0123daa 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -68,6 +68,12 @@ struct iommu_group_attribute {
const char *buf, size_t count);
};
+static const char * const iommu_group_resv_type_string[] = {
+ [IOMMU_RESV_DIRECT] = "direct",
+ [IOMMU_RESV_RESERVED] = "reserved",
+ [IOMMU_RESV_MSI] = "msi",
+};
+
#define IOMMU_GROUP_ATTR(_name, _mode, _show, _store) \
struct iommu_group_attribute iommu_group_attr_##_name = \
__ATTR(_name, _mode, _show, _store)
@@ -231,8 +237,33 @@ int iommu_get_group_resv_regions(struct iommu_group *group,
}
EXPORT_SYMBOL_GPL(iommu_get_group_resv_regions);
+static ssize_t iommu_group_show_resv_regions(struct iommu_group *group,
+ char *buf)
+{
+ struct iommu_resv_region *region, *next;
+ struct list_head group_resv_regions;
+ char *str = buf;
+
+ INIT_LIST_HEAD(&group_resv_regions);
+ iommu_get_group_resv_regions(group, &group_resv_regions);
+
+ list_for_each_entry_safe(region, next, &group_resv_regions, list) {
+ str += sprintf(str, "0x%016llx 0x%016llx %s\n",
+ (long long int)region->start,
+ (long long int)(region->start +
+ region->length - 1),
+ iommu_group_resv_type_string[region->type]);
+ kfree(region);
+ }
+
+ return (str - buf);
+}
+
static IOMMU_GROUP_ATTR(name, S_IRUGO, iommu_group_show_name, NULL);
+static IOMMU_GROUP_ATTR(reserved_regions, 0444,
+ iommu_group_show_resv_regions, NULL);
+
static void iommu_group_release(struct kobject *kobj)
{
struct iommu_group *group = to_iommu_group(kobj);
@@ -247,6 +278,8 @@ static void iommu_group_release(struct kobject *kobj)
if (group->default_domain)
iommu_domain_free(group->default_domain);
+ iommu_group_remove_file(group, &iommu_group_attr_reserved_regions);
+
kfree(group->name);
kfree(group);
}
@@ -310,6 +343,11 @@ struct iommu_group *iommu_group_alloc(void)
*/
kobject_put(&group->kobj);
+ ret = iommu_group_create_file(group,
+ &iommu_group_attr_reserved_regions);
+ if (ret)
+ return ERR_PTR(ret);
+
pr_debug("Allocated group %d\n", group->id);
return group;
--
1.9.1
^ permalink raw reply related
* [PATCH v7 09/19] iommu/vt-d: Implement reserved region get/put callbacks
From: Eric Auger @ 2017-01-09 13:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1483969570-3154-1-git-send-email-eric.auger@redhat.com>
This patch registers the [FEE0_0000h - FEF0_000h] 1MB MSI
range as a reserved region and RMRR regions as direct regions.
This will allow to report those reserved regions in the
iommu-group sysfs.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v6 -> v7:
- report RMRR regions as direct regions
- Due to the usage of rcu_read_lock, the rmrr reserved region
allocation is done on rmrr allocation.
- use IOMMU_RESV_RESERVED
RFCv2 -> RFCv3:
- use get/put_resv_region callbacks.
RFC v1 -> RFC v2:
- fix intel_iommu_add_reserved_regions name
- use IOAPIC_RANGE_START and IOAPIC_RANGE_END defines
- return if the MSI region is already registered;
---
drivers/iommu/intel-iommu.c | 92 ++++++++++++++++++++++++++++++++++++---------
1 file changed, 74 insertions(+), 18 deletions(-)
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 8a18525..bce59a5 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -440,6 +440,7 @@ struct dmar_rmrr_unit {
u64 end_address; /* reserved end address */
struct dmar_dev_scope *devices; /* target devices */
int devices_cnt; /* target device count */
+ struct iommu_resv_region *resv; /* reserved region handle */
};
struct dmar_atsr_unit {
@@ -4246,27 +4247,40 @@ static inline void init_iommu_pm_ops(void) {}
int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
{
struct acpi_dmar_reserved_memory *rmrr;
+ int prot = DMA_PTE_READ|DMA_PTE_WRITE;
struct dmar_rmrr_unit *rmrru;
+ size_t length;
rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
if (!rmrru)
- return -ENOMEM;
+ goto out;
rmrru->hdr = header;
rmrr = (struct acpi_dmar_reserved_memory *)header;
rmrru->base_address = rmrr->base_address;
rmrru->end_address = rmrr->end_address;
+
+ length = rmrr->end_address - rmrr->base_address + 1;
+ rmrru->resv = iommu_alloc_resv_region(rmrr->base_address, length, prot,
+ IOMMU_RESV_DIRECT);
+ if (!rmrru->resv)
+ goto free_rmrru;
+
rmrru->devices = dmar_alloc_dev_scope((void *)(rmrr + 1),
((void *)rmrr) + rmrr->header.length,
&rmrru->devices_cnt);
- if (rmrru->devices_cnt && rmrru->devices == NULL) {
- kfree(rmrru);
- return -ENOMEM;
- }
+ if (rmrru->devices_cnt && rmrru->devices == NULL)
+ goto free_all;
list_add(&rmrru->list, &dmar_rmrr_units);
return 0;
+free_all:
+ kfree(rmrru->resv);
+free_rmrru:
+ kfree(rmrru);
+out:
+ return -ENOMEM;
}
static struct dmar_atsr_unit *dmar_find_atsr(struct acpi_dmar_atsr *atsr)
@@ -4480,6 +4494,7 @@ static void intel_iommu_free_dmars(void)
list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
list_del(&rmrru->list);
dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt);
+ kfree(rmrru->resv);
kfree(rmrru);
}
@@ -5203,6 +5218,45 @@ static void intel_iommu_remove_device(struct device *dev)
iommu_device_unlink(iommu->iommu_dev, dev);
}
+static void intel_iommu_get_resv_regions(struct device *device,
+ struct list_head *head)
+{
+ struct iommu_resv_region *reg;
+ struct dmar_rmrr_unit *rmrr;
+ struct device *i_dev;
+ int i;
+
+ rcu_read_lock();
+ for_each_rmrr_units(rmrr) {
+ for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
+ i, i_dev) {
+ if (i_dev != device)
+ continue;
+
+ list_add_tail(&rmrr->resv->list, head);
+ }
+ }
+ rcu_read_unlock();
+
+ reg = iommu_alloc_resv_region(IOAPIC_RANGE_START,
+ IOAPIC_RANGE_END - IOAPIC_RANGE_START + 1,
+ 0, IOMMU_RESV_RESERVED);
+ if (!reg)
+ return;
+ list_add_tail(®->list, head);
+}
+
+static void intel_iommu_put_resv_regions(struct device *dev,
+ struct list_head *head)
+{
+ struct iommu_resv_region *entry, *next;
+
+ list_for_each_entry_safe(entry, next, head, list) {
+ if (entry->type == IOMMU_RESV_RESERVED)
+ kfree(entry);
+ }
+}
+
#ifdef CONFIG_INTEL_IOMMU_SVM
#define MAX_NR_PASID_BITS (20)
static inline unsigned long intel_iommu_get_pts(struct intel_iommu *iommu)
@@ -5333,19 +5387,21 @@ struct intel_iommu *intel_svm_device_to_iommu(struct device *dev)
#endif /* CONFIG_INTEL_IOMMU_SVM */
static const struct iommu_ops intel_iommu_ops = {
- .capable = intel_iommu_capable,
- .domain_alloc = intel_iommu_domain_alloc,
- .domain_free = intel_iommu_domain_free,
- .attach_dev = intel_iommu_attach_device,
- .detach_dev = intel_iommu_detach_device,
- .map = intel_iommu_map,
- .unmap = intel_iommu_unmap,
- .map_sg = default_iommu_map_sg,
- .iova_to_phys = intel_iommu_iova_to_phys,
- .add_device = intel_iommu_add_device,
- .remove_device = intel_iommu_remove_device,
- .device_group = pci_device_group,
- .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
+ .capable = intel_iommu_capable,
+ .domain_alloc = intel_iommu_domain_alloc,
+ .domain_free = intel_iommu_domain_free,
+ .attach_dev = intel_iommu_attach_device,
+ .detach_dev = intel_iommu_detach_device,
+ .map = intel_iommu_map,
+ .unmap = intel_iommu_unmap,
+ .map_sg = default_iommu_map_sg,
+ .iova_to_phys = intel_iommu_iova_to_phys,
+ .add_device = intel_iommu_add_device,
+ .remove_device = intel_iommu_remove_device,
+ .get_resv_regions = intel_iommu_get_resv_regions,
+ .put_resv_regions = intel_iommu_put_resv_regions,
+ .device_group = pci_device_group,
+ .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
};
static void quirk_iommu_g4x_gfx(struct pci_dev *dev)
--
1.9.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox