Re: KVM on ARM crashes with new VGIC v4.7-rc7

2016-07-22 Thread Marc Zyngier
On Fri, 22 Jul 2016 21:45:00 +0200
Andrew Jones  wrote:

> On Fri, Jul 22, 2016 at 07:06:36PM +0100, Marc Zyngier wrote:
> > On 22/07/16 18:38, Andrew Jones wrote:  
> > > On Fri, Jul 22, 2016 at 04:40:15PM +0100, Marc Zyngier wrote:  
> > >> On 22/07/16 15:35, Andrew Jones wrote:  
> > >>> On Fri, Jul 22, 2016 at 11:42:02AM +0100, Andre Przywara wrote:  
> >  Hi Stefan,
> > 
> >  On 22/07/16 06:57, Stefan Agner wrote:  
> > > Hi,
> > >
> > > I tried KVM on a Cortex-A7 platform (i.MX 7Dual SoC) and encountered
> > > this stack trace immediately after invoking qemu-system-arm:
> > >
> > > Unable to handle kernel paging request at virtual address ffe4
> > > pgd = 8ca52740
> > > [ffe4] *pgd=8080007003, *pmd=8ff7e003, *pte=
> > > Internal error: Oops: 207 [#1] SMP ARM
> > > Modules linked in:  
> > > CPU: 0 PID: 329 Comm: qemu-system-arm Tainted: GW  
> > > 4.7.0-rc7-00094-gea3ed2c #109
> > > Hardware name: Freescale i.MX7 Dual (Device Tree)
> > > task: 8ca3ee40 ti: 8d2b task.ti: 8d2b
> > > PC is at do_raw_spin_lock+0x8/0x1dc
> > > LR is at kvm_vgic_flush_hwstate+0x8c/0x224
> > > pc : [<8027c87c>]lr : [<802172d4>]psr: 60070013
> > > sp : 8d2b1e38  ip : 8d2b  fp : 0001
> > > r10: 8d2b  r9 : 0001  r8 : 8d2b8e54
> > > fec 30be.ethernet eth0: MDIO read timeout
> > > r7 : 8d2b8000  r6 : 8d2b8e74  r5 :   r4 : ffe0
> > > r3 : 4ead  r2 :   r1 :   r0 : ffe0
> > > Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
> > > Control: 30c5387d  Table: 8ca52740  DAC: fffd
> > > Process qemu-system-arm (pid: 329, stack limit = 0x8d2b0210)
> > > Stack: (0x8d2b1e38 to 0x8d2b2000)
> > > 1e20:   ffe0
> > > 
> > > 1e40: 8d2b8e74 8d2b8000 8d2b8e54 0001 8d2b 802172d4 8d2b8000
> > > 810074f8
> > > 1e60: 81007508 8ca5f800 8d284000 0001 8d2b 8020fbd4 8ce9a000
> > > 8ca5f800
> > > 1e80:  0001  00ff 8d284000  
> > > 7ffbfeff
> > > 1ea0: fffe  8d28b780  755fec6c  
> > > e000
> > > 1ec0: 8d2b8000  8d28b780  755fec6c 8020af90 
> > > 8023f248
> > > 1ee0: 000a 755fe98c 8d2b1f08 0008 8021aa84 e000 
> > > 
> > > 1f00: 8a00d860 8d28b780 80334f94  8d2b 80334748 
> > > 
> > > 1f20:  8d28b780 4000 0009 8d28b500 0024 8104ebee
> > > 80bc2ec4
> > > 1f40: 80bafa24 8034138c   80341248  755fec6c
> > > 007c1e70
> > > 1f60: 0009 4258 ae80 8d28b781 0009 8d28b780 ae80
> > > 
> > > 1f80: 8d2b  755fec6c 80334f94 007c1e70 322a7400 4258
> > > 0036
> > > 1fa0: 8021aa84 8021a900 007c1e70 322a7400 0009 ae80 
> > > 755feac0
> > > 1fc0: 007c1e70 322a7400 4258 0036 7e9aff58 01151da4 76f8b4c0
> > > 755fec6c
> > > 1fe0: 0038192c 755fea9c 00048ae7 7697d66c 60070010 0009 
> > > 
> > > [<8027c87c>] (do_raw_spin_lock) from [<802172d4>]
> > > (kvm_vgic_flush_hwstate+0x8c/0x224)
> > > [<802172d4>] (kvm_vgic_flush_hwstate) from [<8020fbd4>]
> > > (kvm_arch_vcpu_ioctl_run+0x110/0x478)
> > > [<8020fbd4>] (kvm_arch_vcpu_ioctl_run) from [<8020af90>]
> > > (kvm_vcpu_ioctl+0x2e0/0x6d4)
> > > [<8020af90>] (kvm_vcpu_ioctl) from [<80334748>]
> > > (do_vfs_ioctl+0xa0/0x8b8)
> > > [<80334748>] (do_vfs_ioctl) from [<80334f94>] (SyS_ioctl+0x34/0x5c)
> > > [<80334f94>] (SyS_ioctl) from [<8021a900>] (ret_fast_syscall+0x0/0x1c)
> > > Code: e49de004 ea09ea24 e92d47f0 e3043ead (e5902004)
> > > ---[ end trace cb88537fdc8fa206 ]---
> > >
> > > I use CONFIG_KVM_NEW_VGIC=y. This happens to me with a rather minimal
> > > qemu invocation (qemu-system-arm -enable-kvm -M virt -cpu host
> > > -nographic -serial stdio -kernel zImage).
> > >
> > > Using a bit older Qemu version 2.4.0.  
> > 
> >  I just tried with a self compiled QEMU 2.4.0 and the Ubuntu 14.04
> >  provided 2.0.0, it worked fine with Linus' current HEAD as a host 
> >  kernel
> >  on a Midway (Cortex-A15).  
> > >>>
> > >>> I can reproduce the issue with a latest QEMU build on AMD Seattle
> > >>> (I haven't tried anywhere else yet)
> > >>>  
> > 
> >  Can you try to disable the new VGIC, just to see if that's a 
> >  regression?  
> > >>>
> > >>> Disabling NEW_VGIC "fixes" guest boots.
> > >>>
> > >>> I'm not using defconfig for my host kernel. I'll do a couple more
> > >>> tests and provide a comparison of my config vs. a defconfig in
> > >>> a few minutes.  
> > >>
> > >> Damn. It is not 

Re: KVM on ARM crashes with new VGIC v4.7-rc7

2016-07-22 Thread Andrew Jones
On Fri, Jul 22, 2016 at 07:06:36PM +0100, Marc Zyngier wrote:
> On 22/07/16 18:38, Andrew Jones wrote:
> > On Fri, Jul 22, 2016 at 04:40:15PM +0100, Marc Zyngier wrote:
> >> On 22/07/16 15:35, Andrew Jones wrote:
> >>> On Fri, Jul 22, 2016 at 11:42:02AM +0100, Andre Przywara wrote:
>  Hi Stefan,
> 
>  On 22/07/16 06:57, Stefan Agner wrote:
> > Hi,
> >
> > I tried KVM on a Cortex-A7 platform (i.MX 7Dual SoC) and encountered
> > this stack trace immediately after invoking qemu-system-arm:
> >
> > Unable to handle kernel paging request at virtual address ffe4
> > pgd = 8ca52740
> > [ffe4] *pgd=8080007003, *pmd=8ff7e003, *pte=
> > Internal error: Oops: 207 [#1] SMP ARM
> > Modules linked in:  
> > CPU: 0 PID: 329 Comm: qemu-system-arm Tainted: GW  
> > 4.7.0-rc7-00094-gea3ed2c #109
> > Hardware name: Freescale i.MX7 Dual (Device Tree)
> > task: 8ca3ee40 ti: 8d2b task.ti: 8d2b
> > PC is at do_raw_spin_lock+0x8/0x1dc
> > LR is at kvm_vgic_flush_hwstate+0x8c/0x224
> > pc : [<8027c87c>]lr : [<802172d4>]psr: 60070013
> > sp : 8d2b1e38  ip : 8d2b  fp : 0001
> > r10: 8d2b  r9 : 0001  r8 : 8d2b8e54
> > fec 30be.ethernet eth0: MDIO read timeout
> > r7 : 8d2b8000  r6 : 8d2b8e74  r5 :   r4 : ffe0
> > r3 : 4ead  r2 :   r1 :   r0 : ffe0
> > Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
> > Control: 30c5387d  Table: 8ca52740  DAC: fffd
> > Process qemu-system-arm (pid: 329, stack limit = 0x8d2b0210)
> > Stack: (0x8d2b1e38 to 0x8d2b2000)
> > 1e20:   ffe0
> > 
> > 1e40: 8d2b8e74 8d2b8000 8d2b8e54 0001 8d2b 802172d4 8d2b8000
> > 810074f8
> > 1e60: 81007508 8ca5f800 8d284000 0001 8d2b 8020fbd4 8ce9a000
> > 8ca5f800
> > 1e80:  0001  00ff 8d284000  
> > 7ffbfeff
> > 1ea0: fffe  8d28b780  755fec6c  
> > e000
> > 1ec0: 8d2b8000  8d28b780  755fec6c 8020af90 
> > 8023f248
> > 1ee0: 000a 755fe98c 8d2b1f08 0008 8021aa84 e000 
> > 
> > 1f00: 8a00d860 8d28b780 80334f94  8d2b 80334748 
> > 
> > 1f20:  8d28b780 4000 0009 8d28b500 0024 8104ebee
> > 80bc2ec4
> > 1f40: 80bafa24 8034138c   80341248  755fec6c
> > 007c1e70
> > 1f60: 0009 4258 ae80 8d28b781 0009 8d28b780 ae80
> > 
> > 1f80: 8d2b  755fec6c 80334f94 007c1e70 322a7400 4258
> > 0036
> > 1fa0: 8021aa84 8021a900 007c1e70 322a7400 0009 ae80 
> > 755feac0
> > 1fc0: 007c1e70 322a7400 4258 0036 7e9aff58 01151da4 76f8b4c0
> > 755fec6c
> > 1fe0: 0038192c 755fea9c 00048ae7 7697d66c 60070010 0009 
> > 
> > [<8027c87c>] (do_raw_spin_lock) from [<802172d4>]
> > (kvm_vgic_flush_hwstate+0x8c/0x224)
> > [<802172d4>] (kvm_vgic_flush_hwstate) from [<8020fbd4>]
> > (kvm_arch_vcpu_ioctl_run+0x110/0x478)
> > [<8020fbd4>] (kvm_arch_vcpu_ioctl_run) from [<8020af90>]
> > (kvm_vcpu_ioctl+0x2e0/0x6d4)
> > [<8020af90>] (kvm_vcpu_ioctl) from [<80334748>]
> > (do_vfs_ioctl+0xa0/0x8b8)
> > [<80334748>] (do_vfs_ioctl) from [<80334f94>] (SyS_ioctl+0x34/0x5c)
> > [<80334f94>] (SyS_ioctl) from [<8021a900>] (ret_fast_syscall+0x0/0x1c)
> > Code: e49de004 ea09ea24 e92d47f0 e3043ead (e5902004)
> > ---[ end trace cb88537fdc8fa206 ]---
> >
> > I use CONFIG_KVM_NEW_VGIC=y. This happens to me with a rather minimal
> > qemu invocation (qemu-system-arm -enable-kvm -M virt -cpu host
> > -nographic -serial stdio -kernel zImage).
> >
> > Using a bit older Qemu version 2.4.0.
> 
>  I just tried with a self compiled QEMU 2.4.0 and the Ubuntu 14.04
>  provided 2.0.0, it worked fine with Linus' current HEAD as a host kernel
>  on a Midway (Cortex-A15).
> >>>
> >>> I can reproduce the issue with a latest QEMU build on AMD Seattle
> >>> (I haven't tried anywhere else yet)
> >>>
> 
>  Can you try to disable the new VGIC, just to see if that's a regression?
> >>>
> >>> Disabling NEW_VGIC "fixes" guest boots.
> >>>
> >>> I'm not using defconfig for my host kernel. I'll do a couple more
> >>> tests and provide a comparison of my config vs. a defconfig in
> >>> a few minutes.
> >>
> >> Damn. It is not failing for me, so it has to be a kernel config thing...
> >> If you can narrow it down to the difference with defconfig, that'd be
> >> tremendously helpful.
> > 
> > It's PAGE_SIZE; 64K doesn't work, 4K does, regardless of VA_BITS
> > selection.
> 
> root@flakes:~# zgrep 64K /proc/config.gz
> CONFIG_ARM64_64K_PAGES=y
> 

Re: KVM on ARM crashes with new VGIC v4.7-rc7

2016-07-22 Thread Marc Zyngier
On 22/07/16 18:56, Stefan Agner wrote:
> On 2016-07-22 10:49, Marc Zyngier wrote:
>> On 22/07/16 18:38, Andrew Jones wrote:
>>> On Fri, Jul 22, 2016 at 04:40:15PM +0100, Marc Zyngier wrote:
 On 22/07/16 15:35, Andrew Jones wrote:
> On Fri, Jul 22, 2016 at 11:42:02AM +0100, Andre Przywara wrote:
>> Hi Stefan,
>>
>> On 22/07/16 06:57, Stefan Agner wrote:
>>> Hi,
>>>
>>> I tried KVM on a Cortex-A7 platform (i.MX 7Dual SoC) and encountered
>>> this stack trace immediately after invoking qemu-system-arm:
>>>
>>> Unable to handle kernel paging request at virtual address ffe4
>>> pgd = 8ca52740
>>> [ffe4] *pgd=8080007003, *pmd=8ff7e003, *pte=
>>> Internal error: Oops: 207 [#1] SMP ARM
>>> Modules linked in:
>>> CPU: 0 PID: 329 Comm: qemu-system-arm Tainted: GW
>>> 4.7.0-rc7-00094-gea3ed2c #109
>>> Hardware name: Freescale i.MX7 Dual (Device Tree)
>>> task: 8ca3ee40 ti: 8d2b task.ti: 8d2b
>>> PC is at do_raw_spin_lock+0x8/0x1dc
>>> LR is at kvm_vgic_flush_hwstate+0x8c/0x224
>>> pc : [<8027c87c>]lr : [<802172d4>]psr: 60070013
>>> sp : 8d2b1e38  ip : 8d2b  fp : 0001
>>> r10: 8d2b  r9 : 0001  r8 : 8d2b8e54
>>> fec 30be.ethernet eth0: MDIO read timeout
>>> r7 : 8d2b8000  r6 : 8d2b8e74  r5 :   r4 : ffe0
>>> r3 : 4ead  r2 :   r1 :   r0 : ffe0
>>> Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
>>> Control: 30c5387d  Table: 8ca52740  DAC: fffd
>>> Process qemu-system-arm (pid: 329, stack limit = 0x8d2b0210)
>>> Stack: (0x8d2b1e38 to 0x8d2b2000)
>>> 1e20:   ffe0
>>> 
>>> 1e40: 8d2b8e74 8d2b8000 8d2b8e54 0001 8d2b 802172d4 8d2b8000
>>> 810074f8
>>> 1e60: 81007508 8ca5f800 8d284000 0001 8d2b 8020fbd4 8ce9a000
>>> 8ca5f800
>>> 1e80:  0001  00ff 8d284000  
>>> 7ffbfeff
>>> 1ea0: fffe  8d28b780  755fec6c  
>>> e000
>>> 1ec0: 8d2b8000  8d28b780  755fec6c 8020af90 
>>> 8023f248
>>> 1ee0: 000a 755fe98c 8d2b1f08 0008 8021aa84 e000 
>>> 
>>> 1f00: 8a00d860 8d28b780 80334f94  8d2b 80334748 
>>> 
>>> 1f20:  8d28b780 4000 0009 8d28b500 0024 8104ebee
>>> 80bc2ec4
>>> 1f40: 80bafa24 8034138c   80341248  755fec6c
>>> 007c1e70
>>> 1f60: 0009 4258 ae80 8d28b781 0009 8d28b780 ae80
>>> 
>>> 1f80: 8d2b  755fec6c 80334f94 007c1e70 322a7400 4258
>>> 0036
>>> 1fa0: 8021aa84 8021a900 007c1e70 322a7400 0009 ae80 
>>> 755feac0
>>> 1fc0: 007c1e70 322a7400 4258 0036 7e9aff58 01151da4 76f8b4c0
>>> 755fec6c
>>> 1fe0: 0038192c 755fea9c 00048ae7 7697d66c 60070010 0009 
>>> 
>>> [<8027c87c>] (do_raw_spin_lock) from [<802172d4>]
>>> (kvm_vgic_flush_hwstate+0x8c/0x224)
>>> [<802172d4>] (kvm_vgic_flush_hwstate) from [<8020fbd4>]
>>> (kvm_arch_vcpu_ioctl_run+0x110/0x478)
>>> [<8020fbd4>] (kvm_arch_vcpu_ioctl_run) from [<8020af90>]
>>> (kvm_vcpu_ioctl+0x2e0/0x6d4)
>>> [<8020af90>] (kvm_vcpu_ioctl) from [<80334748>]
>>> (do_vfs_ioctl+0xa0/0x8b8)
>>> [<80334748>] (do_vfs_ioctl) from [<80334f94>] (SyS_ioctl+0x34/0x5c)
>>> [<80334f94>] (SyS_ioctl) from [<8021a900>] (ret_fast_syscall+0x0/0x1c)
>>> Code: e49de004 ea09ea24 e92d47f0 e3043ead (e5902004)
>>> ---[ end trace cb88537fdc8fa206 ]---
>>>
>>> I use CONFIG_KVM_NEW_VGIC=y. This happens to me with a rather minimal
>>> qemu invocation (qemu-system-arm -enable-kvm -M virt -cpu host
>>> -nographic -serial stdio -kernel zImage).
>>>
>>> Using a bit older Qemu version 2.4.0.
>>
>> I just tried with a self compiled QEMU 2.4.0 and the Ubuntu 14.04
>> provided 2.0.0, it worked fine with Linus' current HEAD as a host kernel
>> on a Midway (Cortex-A15).
>
> I can reproduce the issue with a latest QEMU build on AMD Seattle
> (I haven't tried anywhere else yet)
>
>>
>> Can you try to disable the new VGIC, just to see if that's a regression?
>
> Disabling NEW_VGIC "fixes" guest boots.
>
> I'm not using defconfig for my host kernel. I'll do a couple more
> tests and provide a comparison of my config vs. a defconfig in
> a few minutes.

 Damn. It is not failing for me, so it has to be a kernel config thing...
 If you can narrow it down to the difference with defconfig, that'd be
 tremendously helpful.
>>>
>>> It's PAGE_SIZE; 64K doesn't work, 4K does, regardless of VA_BITS
>>> selection.
>>
>> That definitely doesn't match Stefan's report (32bit only 

Re: KVM on ARM crashes with new VGIC v4.7-rc7

2016-07-22 Thread Stefan Agner
On 2016-07-22 10:38, Andrew Jones wrote:
> On Fri, Jul 22, 2016 at 04:40:15PM +0100, Marc Zyngier wrote:
>> On 22/07/16 15:35, Andrew Jones wrote:
>> > On Fri, Jul 22, 2016 at 11:42:02AM +0100, Andre Przywara wrote:
>> >> Hi Stefan,
>> >>
>> >> On 22/07/16 06:57, Stefan Agner wrote:
>> >>> Hi,
>> >>>
>> >>> I tried KVM on a Cortex-A7 platform (i.MX 7Dual SoC) and encountered
>> >>> this stack trace immediately after invoking qemu-system-arm:
>> >>>
>> >>> Unable to handle kernel paging request at virtual address ffe4
>> >>> pgd = 8ca52740
>> >>> [ffe4] *pgd=8080007003, *pmd=8ff7e003, *pte=
>> >>> Internal error: Oops: 207 [#1] SMP ARM
>> >>> Modules linked in:
>> >>> CPU: 0 PID: 329 Comm: qemu-system-arm Tainted: GW
>> >>> 4.7.0-rc7-00094-gea3ed2c #109
>> >>> Hardware name: Freescale i.MX7 Dual (Device Tree)
>> >>> task: 8ca3ee40 ti: 8d2b task.ti: 8d2b
>> >>> PC is at do_raw_spin_lock+0x8/0x1dc
>> >>> LR is at kvm_vgic_flush_hwstate+0x8c/0x224
>> >>> pc : [<8027c87c>]lr : [<802172d4>]psr: 60070013
>> >>> sp : 8d2b1e38  ip : 8d2b  fp : 0001
>> >>> r10: 8d2b  r9 : 0001  r8 : 8d2b8e54
>> >>> fec 30be.ethernet eth0: MDIO read timeout
>> >>> r7 : 8d2b8000  r6 : 8d2b8e74  r5 :   r4 : ffe0
>> >>> r3 : 4ead  r2 :   r1 :   r0 : ffe0
>> >>> Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
>> >>> Control: 30c5387d  Table: 8ca52740  DAC: fffd
>> >>> Process qemu-system-arm (pid: 329, stack limit = 0x8d2b0210)
>> >>> Stack: (0x8d2b1e38 to 0x8d2b2000)
>> >>> 1e20:   ffe0
>> >>> 
>> >>> 1e40: 8d2b8e74 8d2b8000 8d2b8e54 0001 8d2b 802172d4 8d2b8000
>> >>> 810074f8
>> >>> 1e60: 81007508 8ca5f800 8d284000 0001 8d2b 8020fbd4 8ce9a000
>> >>> 8ca5f800
>> >>> 1e80:  0001  00ff 8d284000  
>> >>> 7ffbfeff
>> >>> 1ea0: fffe  8d28b780  755fec6c  
>> >>> e000
>> >>> 1ec0: 8d2b8000  8d28b780  755fec6c 8020af90 
>> >>> 8023f248
>> >>> 1ee0: 000a 755fe98c 8d2b1f08 0008 8021aa84 e000 
>> >>> 
>> >>> 1f00: 8a00d860 8d28b780 80334f94  8d2b 80334748 
>> >>> 
>> >>> 1f20:  8d28b780 4000 0009 8d28b500 0024 8104ebee
>> >>> 80bc2ec4
>> >>> 1f40: 80bafa24 8034138c   80341248  755fec6c
>> >>> 007c1e70
>> >>> 1f60: 0009 4258 ae80 8d28b781 0009 8d28b780 ae80
>> >>> 
>> >>> 1f80: 8d2b  755fec6c 80334f94 007c1e70 322a7400 4258
>> >>> 0036
>> >>> 1fa0: 8021aa84 8021a900 007c1e70 322a7400 0009 ae80 
>> >>> 755feac0
>> >>> 1fc0: 007c1e70 322a7400 4258 0036 7e9aff58 01151da4 76f8b4c0
>> >>> 755fec6c
>> >>> 1fe0: 0038192c 755fea9c 00048ae7 7697d66c 60070010 0009 
>> >>> 
>> >>> [<8027c87c>] (do_raw_spin_lock) from [<802172d4>]
>> >>> (kvm_vgic_flush_hwstate+0x8c/0x224)
>> >>> [<802172d4>] (kvm_vgic_flush_hwstate) from [<8020fbd4>]
>> >>> (kvm_arch_vcpu_ioctl_run+0x110/0x478)
>> >>> [<8020fbd4>] (kvm_arch_vcpu_ioctl_run) from [<8020af90>]
>> >>> (kvm_vcpu_ioctl+0x2e0/0x6d4)
>> >>> [<8020af90>] (kvm_vcpu_ioctl) from [<80334748>]
>> >>> (do_vfs_ioctl+0xa0/0x8b8)
>> >>> [<80334748>] (do_vfs_ioctl) from [<80334f94>] (SyS_ioctl+0x34/0x5c)
>> >>> [<80334f94>] (SyS_ioctl) from [<8021a900>] (ret_fast_syscall+0x0/0x1c)
>> >>> Code: e49de004 ea09ea24 e92d47f0 e3043ead (e5902004)
>> >>> ---[ end trace cb88537fdc8fa206 ]---
>> >>>
>> >>> I use CONFIG_KVM_NEW_VGIC=y. This happens to me with a rather minimal
>> >>> qemu invocation (qemu-system-arm -enable-kvm -M virt -cpu host
>> >>> -nographic -serial stdio -kernel zImage).
>> >>>
>> >>> Using a bit older Qemu version 2.4.0.
>> >>
>> >> I just tried with a self compiled QEMU 2.4.0 and the Ubuntu 14.04
>> >> provided 2.0.0, it worked fine with Linus' current HEAD as a host kernel
>> >> on a Midway (Cortex-A15).
>> >
>> > I can reproduce the issue with a latest QEMU build on AMD Seattle
>> > (I haven't tried anywhere else yet)
>> >
>> >>
>> >> Can you try to disable the new VGIC, just to see if that's a regression?
>> >
>> > Disabling NEW_VGIC "fixes" guest boots.

Same for me.

>> >
>> > I'm not using defconfig for my host kernel. I'll do a couple more
>> > tests and provide a comparison of my config vs. a defconfig in
>> > a few minutes.
>>
>> Damn. It is not failing for me, so it has to be a kernel config thing...
>> If you can narrow it down to the difference with defconfig, that'd be
>> tremendously helpful.
> 
> It's PAGE_SIZE; 64K doesn't work, 4K does, regardless of VA_BITS
> selection.

Just built a mutli_v7_defconfig, fails for me too.

Isn't 32-bit ARM always using 4K pages?

--
Stefan


___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu

Re: KVM on ARM crashes with new VGIC v4.7-rc7

2016-07-22 Thread Marc Zyngier
On 22/07/16 18:38, Andrew Jones wrote:
> On Fri, Jul 22, 2016 at 04:40:15PM +0100, Marc Zyngier wrote:
>> On 22/07/16 15:35, Andrew Jones wrote:
>>> On Fri, Jul 22, 2016 at 11:42:02AM +0100, Andre Przywara wrote:
 Hi Stefan,

 On 22/07/16 06:57, Stefan Agner wrote:
> Hi,
>
> I tried KVM on a Cortex-A7 platform (i.MX 7Dual SoC) and encountered
> this stack trace immediately after invoking qemu-system-arm:
>
> Unable to handle kernel paging request at virtual address ffe4
> pgd = 8ca52740
> [ffe4] *pgd=8080007003, *pmd=8ff7e003, *pte=
> Internal error: Oops: 207 [#1] SMP ARM
> Modules linked in:  
> CPU: 0 PID: 329 Comm: qemu-system-arm Tainted: GW  
> 4.7.0-rc7-00094-gea3ed2c #109
> Hardware name: Freescale i.MX7 Dual (Device Tree)
> task: 8ca3ee40 ti: 8d2b task.ti: 8d2b
> PC is at do_raw_spin_lock+0x8/0x1dc
> LR is at kvm_vgic_flush_hwstate+0x8c/0x224
> pc : [<8027c87c>]lr : [<802172d4>]psr: 60070013
> sp : 8d2b1e38  ip : 8d2b  fp : 0001
> r10: 8d2b  r9 : 0001  r8 : 8d2b8e54
> fec 30be.ethernet eth0: MDIO read timeout
> r7 : 8d2b8000  r6 : 8d2b8e74  r5 :   r4 : ffe0
> r3 : 4ead  r2 :   r1 :   r0 : ffe0
> Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
> Control: 30c5387d  Table: 8ca52740  DAC: fffd
> Process qemu-system-arm (pid: 329, stack limit = 0x8d2b0210)
> Stack: (0x8d2b1e38 to 0x8d2b2000)
> 1e20:   ffe0
> 
> 1e40: 8d2b8e74 8d2b8000 8d2b8e54 0001 8d2b 802172d4 8d2b8000
> 810074f8
> 1e60: 81007508 8ca5f800 8d284000 0001 8d2b 8020fbd4 8ce9a000
> 8ca5f800
> 1e80:  0001  00ff 8d284000  
> 7ffbfeff
> 1ea0: fffe  8d28b780  755fec6c  
> e000
> 1ec0: 8d2b8000  8d28b780  755fec6c 8020af90 
> 8023f248
> 1ee0: 000a 755fe98c 8d2b1f08 0008 8021aa84 e000 
> 
> 1f00: 8a00d860 8d28b780 80334f94  8d2b 80334748 
> 
> 1f20:  8d28b780 4000 0009 8d28b500 0024 8104ebee
> 80bc2ec4
> 1f40: 80bafa24 8034138c   80341248  755fec6c
> 007c1e70
> 1f60: 0009 4258 ae80 8d28b781 0009 8d28b780 ae80
> 
> 1f80: 8d2b  755fec6c 80334f94 007c1e70 322a7400 4258
> 0036
> 1fa0: 8021aa84 8021a900 007c1e70 322a7400 0009 ae80 
> 755feac0
> 1fc0: 007c1e70 322a7400 4258 0036 7e9aff58 01151da4 76f8b4c0
> 755fec6c
> 1fe0: 0038192c 755fea9c 00048ae7 7697d66c 60070010 0009 
> 
> [<8027c87c>] (do_raw_spin_lock) from [<802172d4>]
> (kvm_vgic_flush_hwstate+0x8c/0x224)
> [<802172d4>] (kvm_vgic_flush_hwstate) from [<8020fbd4>]
> (kvm_arch_vcpu_ioctl_run+0x110/0x478)
> [<8020fbd4>] (kvm_arch_vcpu_ioctl_run) from [<8020af90>]
> (kvm_vcpu_ioctl+0x2e0/0x6d4)
> [<8020af90>] (kvm_vcpu_ioctl) from [<80334748>]
> (do_vfs_ioctl+0xa0/0x8b8)
> [<80334748>] (do_vfs_ioctl) from [<80334f94>] (SyS_ioctl+0x34/0x5c)
> [<80334f94>] (SyS_ioctl) from [<8021a900>] (ret_fast_syscall+0x0/0x1c)
> Code: e49de004 ea09ea24 e92d47f0 e3043ead (e5902004)
> ---[ end trace cb88537fdc8fa206 ]---
>
> I use CONFIG_KVM_NEW_VGIC=y. This happens to me with a rather minimal
> qemu invocation (qemu-system-arm -enable-kvm -M virt -cpu host
> -nographic -serial stdio -kernel zImage).
>
> Using a bit older Qemu version 2.4.0.

 I just tried with a self compiled QEMU 2.4.0 and the Ubuntu 14.04
 provided 2.0.0, it worked fine with Linus' current HEAD as a host kernel
 on a Midway (Cortex-A15).
>>>
>>> I can reproduce the issue with a latest QEMU build on AMD Seattle
>>> (I haven't tried anywhere else yet)
>>>

 Can you try to disable the new VGIC, just to see if that's a regression?
>>>
>>> Disabling NEW_VGIC "fixes" guest boots.
>>>
>>> I'm not using defconfig for my host kernel. I'll do a couple more
>>> tests and provide a comparison of my config vs. a defconfig in
>>> a few minutes.
>>
>> Damn. It is not failing for me, so it has to be a kernel config thing...
>> If you can narrow it down to the difference with defconfig, that'd be
>> tremendously helpful.
> 
> It's PAGE_SIZE; 64K doesn't work, 4K does, regardless of VA_BITS
> selection.

That definitely doesn't match Stefan's report (32bit only has 4k). I'll
give 64k a go in a minute (but I remember doing some 64k stuff a couple
of weeks ago and everything was OK).

Thanks,

M.
-- 
Jazz is not dead. It just smells funny...
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu

Re: KVM on ARM crashes with new VGIC v4.7-rc7

2016-07-22 Thread Andrew Jones
On Fri, Jul 22, 2016 at 04:40:15PM +0100, Marc Zyngier wrote:
> On 22/07/16 15:35, Andrew Jones wrote:
> > On Fri, Jul 22, 2016 at 11:42:02AM +0100, Andre Przywara wrote:
> >> Hi Stefan,
> >>
> >> On 22/07/16 06:57, Stefan Agner wrote:
> >>> Hi,
> >>>
> >>> I tried KVM on a Cortex-A7 platform (i.MX 7Dual SoC) and encountered
> >>> this stack trace immediately after invoking qemu-system-arm:
> >>>
> >>> Unable to handle kernel paging request at virtual address ffe4
> >>> pgd = 8ca52740
> >>> [ffe4] *pgd=8080007003, *pmd=8ff7e003, *pte=
> >>> Internal error: Oops: 207 [#1] SMP ARM
> >>> Modules linked in:  
> >>> CPU: 0 PID: 329 Comm: qemu-system-arm Tainted: GW  
> >>> 4.7.0-rc7-00094-gea3ed2c #109
> >>> Hardware name: Freescale i.MX7 Dual (Device Tree)
> >>> task: 8ca3ee40 ti: 8d2b task.ti: 8d2b
> >>> PC is at do_raw_spin_lock+0x8/0x1dc
> >>> LR is at kvm_vgic_flush_hwstate+0x8c/0x224
> >>> pc : [<8027c87c>]lr : [<802172d4>]psr: 60070013
> >>> sp : 8d2b1e38  ip : 8d2b  fp : 0001
> >>> r10: 8d2b  r9 : 0001  r8 : 8d2b8e54
> >>> fec 30be.ethernet eth0: MDIO read timeout
> >>> r7 : 8d2b8000  r6 : 8d2b8e74  r5 :   r4 : ffe0
> >>> r3 : 4ead  r2 :   r1 :   r0 : ffe0
> >>> Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
> >>> Control: 30c5387d  Table: 8ca52740  DAC: fffd
> >>> Process qemu-system-arm (pid: 329, stack limit = 0x8d2b0210)
> >>> Stack: (0x8d2b1e38 to 0x8d2b2000)
> >>> 1e20:   ffe0
> >>> 
> >>> 1e40: 8d2b8e74 8d2b8000 8d2b8e54 0001 8d2b 802172d4 8d2b8000
> >>> 810074f8
> >>> 1e60: 81007508 8ca5f800 8d284000 0001 8d2b 8020fbd4 8ce9a000
> >>> 8ca5f800
> >>> 1e80:  0001  00ff 8d284000  
> >>> 7ffbfeff
> >>> 1ea0: fffe  8d28b780  755fec6c  
> >>> e000
> >>> 1ec0: 8d2b8000  8d28b780  755fec6c 8020af90 
> >>> 8023f248
> >>> 1ee0: 000a 755fe98c 8d2b1f08 0008 8021aa84 e000 
> >>> 
> >>> 1f00: 8a00d860 8d28b780 80334f94  8d2b 80334748 
> >>> 
> >>> 1f20:  8d28b780 4000 0009 8d28b500 0024 8104ebee
> >>> 80bc2ec4
> >>> 1f40: 80bafa24 8034138c   80341248  755fec6c
> >>> 007c1e70
> >>> 1f60: 0009 4258 ae80 8d28b781 0009 8d28b780 ae80
> >>> 
> >>> 1f80: 8d2b  755fec6c 80334f94 007c1e70 322a7400 4258
> >>> 0036
> >>> 1fa0: 8021aa84 8021a900 007c1e70 322a7400 0009 ae80 
> >>> 755feac0
> >>> 1fc0: 007c1e70 322a7400 4258 0036 7e9aff58 01151da4 76f8b4c0
> >>> 755fec6c
> >>> 1fe0: 0038192c 755fea9c 00048ae7 7697d66c 60070010 0009 
> >>> 
> >>> [<8027c87c>] (do_raw_spin_lock) from [<802172d4>]
> >>> (kvm_vgic_flush_hwstate+0x8c/0x224)
> >>> [<802172d4>] (kvm_vgic_flush_hwstate) from [<8020fbd4>]
> >>> (kvm_arch_vcpu_ioctl_run+0x110/0x478)
> >>> [<8020fbd4>] (kvm_arch_vcpu_ioctl_run) from [<8020af90>]
> >>> (kvm_vcpu_ioctl+0x2e0/0x6d4)
> >>> [<8020af90>] (kvm_vcpu_ioctl) from [<80334748>]
> >>> (do_vfs_ioctl+0xa0/0x8b8)
> >>> [<80334748>] (do_vfs_ioctl) from [<80334f94>] (SyS_ioctl+0x34/0x5c)
> >>> [<80334f94>] (SyS_ioctl) from [<8021a900>] (ret_fast_syscall+0x0/0x1c)
> >>> Code: e49de004 ea09ea24 e92d47f0 e3043ead (e5902004)
> >>> ---[ end trace cb88537fdc8fa206 ]---
> >>>
> >>> I use CONFIG_KVM_NEW_VGIC=y. This happens to me with a rather minimal
> >>> qemu invocation (qemu-system-arm -enable-kvm -M virt -cpu host
> >>> -nographic -serial stdio -kernel zImage).
> >>>
> >>> Using a bit older Qemu version 2.4.0.
> >>
> >> I just tried with a self compiled QEMU 2.4.0 and the Ubuntu 14.04
> >> provided 2.0.0, it worked fine with Linus' current HEAD as a host kernel
> >> on a Midway (Cortex-A15).
> > 
> > I can reproduce the issue with a latest QEMU build on AMD Seattle
> > (I haven't tried anywhere else yet)
> > 
> >>
> >> Can you try to disable the new VGIC, just to see if that's a regression?
> > 
> > Disabling NEW_VGIC "fixes" guest boots.
> > 
> > I'm not using defconfig for my host kernel. I'll do a couple more
> > tests and provide a comparison of my config vs. a defconfig in
> > a few minutes.
> 
> Damn. It is not failing for me, so it has to be a kernel config thing...
> If you can narrow it down to the difference with defconfig, that'd be
> tremendously helpful.

It's PAGE_SIZE; 64K doesn't work, 4K does, regardless of VA_BITS
selection.

Thanks,
drew
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 38/55] KVM: arm64: vgic-its: Read initial LPI pending table

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

The LPI pending status for a GICv3 redistributor is held in a table
in (guest) memory. To achieve reasonable performance, we cache the
pending bit in our struct vgic_irq. The initial pending state must be
read from guest memory upon enabling LPIs for this redistributor.
As we can't access the guest memory while we hold the lpi_list spinlock,
we create a snapshot of the LPI list and iterate over that.

Signed-off-by: Andre Przywara 
Reviewed-by: Marc Zyngier 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-its.c | 95 
 virt/kvm/arm/vgic/vgic.h |  5 +++
 2 files changed, 100 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 14f91ff..2881b84 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -67,6 +67,94 @@ struct its_itte {
  * supports more. Let's be restrictive here.
  */
 #define CBASER_ADDRESS(x)  ((x) & GENMASK_ULL(47, 12))
+#define PENDBASER_ADDRESS(x)   ((x) & GENMASK_ULL(47, 16))
+
+/*
+ * Create a snapshot of the current LPI list, so that we can enumerate all
+ * LPIs without holding any lock.
+ * Returns the array length and puts the kmalloc'ed array into intid_ptr.
+ */
+static int vgic_copy_lpi_list(struct kvm *kvm, u32 **intid_ptr)
+{
+   struct vgic_dist *dist = >arch.vgic;
+   struct vgic_irq *irq;
+   u32 *intids;
+   int irq_count = dist->lpi_list_count, i = 0;
+
+   /*
+* We use the current value of the list length, which may change
+* after the kmalloc. We don't care, because the guest shouldn't
+* change anything while the command handling is still running,
+* and in the worst case we would miss a new IRQ, which one wouldn't
+* expect to be covered by this command anyway.
+*/
+   intids = kmalloc_array(irq_count, sizeof(intids[0]), GFP_KERNEL);
+   if (!intids)
+   return -ENOMEM;
+
+   spin_lock(>lpi_list_lock);
+   list_for_each_entry(irq, >lpi_list_head, lpi_list) {
+   /* We don't need to "get" the IRQ, as we hold the list lock. */
+   intids[i] = irq->intid;
+   if (++i == irq_count)
+   break;
+   }
+   spin_unlock(>lpi_list_lock);
+
+   *intid_ptr = intids;
+   return irq_count;
+}
+
+/*
+ * Scan the whole LPI pending table and sync the pending bit in there
+ * with our own data structures. This relies on the LPI being
+ * mapped before.
+ */
+static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu)
+{
+   gpa_t pendbase = PENDBASER_ADDRESS(vcpu->arch.vgic_cpu.pendbaser);
+   struct vgic_irq *irq;
+   int last_byte_offset = -1;
+   int ret = 0;
+   u32 *intids;
+   int nr_irqs, i;
+
+   nr_irqs = vgic_copy_lpi_list(vcpu->kvm, );
+   if (nr_irqs < 0)
+   return nr_irqs;
+
+   for (i = 0; i < nr_irqs; i++) {
+   int byte_offset, bit_nr;
+   u8 pendmask;
+
+   byte_offset = intids[i] / BITS_PER_BYTE;
+   bit_nr = intids[i] % BITS_PER_BYTE;
+
+   /*
+* For contiguously allocated LPIs chances are we just read
+* this very same byte in the last iteration. Reuse that.
+*/
+   if (byte_offset != last_byte_offset) {
+   ret = kvm_read_guest(vcpu->kvm, pendbase + byte_offset,
+, 1);
+   if (ret) {
+   kfree(intids);
+   return ret;
+   }
+   last_byte_offset = byte_offset;
+   }
+
+   irq = vgic_get_irq(vcpu->kvm, NULL, intids[i]);
+   spin_lock(>irq_lock);
+   irq->pending = pendmask & (1U << bit_nr);
+   vgic_queue_irq_unlock(vcpu->kvm, irq);
+   vgic_put_irq(vcpu->kvm, irq);
+   }
+
+   kfree(intids);
+
+   return ret;
+}
 
 static unsigned long vgic_mmio_read_its_ctlr(struct kvm *vcpu,
 struct vgic_its *its,
@@ -403,6 +491,13 @@ static struct vgic_register_region its_registers[] = {
VGIC_ACCESS_32bit),
 };
 
+/* This is called on setting the LPI enable bit in the redistributor. */
+void vgic_enable_lpis(struct kvm_vcpu *vcpu)
+{
+   if (!(vcpu->arch.vgic_cpu.pendbaser & GICR_PENDBASER_PTZ))
+   its_sync_lpi_pending_table(vcpu);
+}
+
 static int vgic_its_init_its(struct kvm *kvm, struct vgic_its *its)
 {
struct vgic_io_device *iodev = >iodev;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 8192a29..ee348de 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -25,6 +25,7 @@
 #define 

[PATCH 34/55] KVM: arm64: vgic-its: Introduce ITS emulation file with MMIO framework

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

The ARM GICv3 ITS emulation code goes into a separate file, but needs
to be connected to the GICv3 emulation, of which it is an option.
The ITS MMIO handlers require the respective ITS pointer to be passed in,
so we amend the existing VGIC MMIO framework to let it cope with that.
Also we introduce the basic ITS data structure and initialize it, but
don't return any success yet, as we are not yet ready for the show.

Signed-off-by: Andre Przywara 
Reviewed-by: Marc Zyngier 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 include/kvm/arm_vgic.h   |  22 -
 virt/kvm/arm/vgic/vgic-its.c | 103 +++
 virt/kvm/arm/vgic/vgic-mmio-v3.c |  40 ++-
 virt/kvm/arm/vgic/vgic-mmio.c|  37 +++---
 virt/kvm/arm/vgic/vgic-mmio.h|  17 +--
 virt/kvm/arm/vgic/vgic.h |   7 +++
 6 files changed, 213 insertions(+), 13 deletions(-)
 create mode 100644 virt/kvm/arm/vgic/vgic-its.c

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index df2dec5..685f339 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -108,15 +108,35 @@ struct vgic_irq {
 };
 
 struct vgic_register_region;
+struct vgic_its;
+
+enum iodev_type {
+   IODEV_CPUIF,
+   IODEV_DIST,
+   IODEV_REDIST,
+   IODEV_ITS
+};
 
 struct vgic_io_device {
gpa_t base_addr;
-   struct kvm_vcpu *redist_vcpu;
+   union {
+   struct kvm_vcpu *redist_vcpu;
+   struct vgic_its *its;
+   };
const struct vgic_register_region *regions;
+   enum iodev_type iodev_type;
int nr_regions;
struct kvm_io_device dev;
 };
 
+struct vgic_its {
+   /* The base address of the ITS control register frame */
+   gpa_t   vgic_its_base;
+
+   boolenabled;
+   struct vgic_io_device   iodev;
+};
+
 struct vgic_dist {
boolin_kernel;
boolready;
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
new file mode 100644
index 000..4654d6e
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -0,0 +1,103 @@
+/*
+ * GICv3 ITS emulation
+ *
+ * Copyright (C) 2015,2016 ARM Ltd.
+ * Author: Andre Przywara 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see .
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "vgic.h"
+#include "vgic-mmio.h"
+
+#define REGISTER_ITS_DESC(off, rd, wr, length, acc)\
+{  \
+   .reg_offset = off,  \
+   .len = length,  \
+   .access_flags = acc,\
+   .its_read = rd, \
+   .its_write = wr,\
+}
+
+static unsigned long its_mmio_read_raz(struct kvm *kvm, struct vgic_its *its,
+  gpa_t addr, unsigned int len)
+{
+   return 0;
+}
+
+static void its_mmio_write_wi(struct kvm *kvm, struct vgic_its *its,
+ gpa_t addr, unsigned int len, unsigned long val)
+{
+   /* Ignore */
+}
+
+static struct vgic_register_region its_registers[] = {
+   REGISTER_ITS_DESC(GITS_CTLR,
+   its_mmio_read_raz, its_mmio_write_wi, 4,
+   VGIC_ACCESS_32bit),
+   REGISTER_ITS_DESC(GITS_IIDR,
+   its_mmio_read_raz, its_mmio_write_wi, 4,
+   VGIC_ACCESS_32bit),
+   REGISTER_ITS_DESC(GITS_TYPER,
+   its_mmio_read_raz, its_mmio_write_wi, 8,
+   VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+   REGISTER_ITS_DESC(GITS_CBASER,
+   its_mmio_read_raz, its_mmio_write_wi, 8,
+   VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+   REGISTER_ITS_DESC(GITS_CWRITER,
+   its_mmio_read_raz, its_mmio_write_wi, 8,
+   VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+   REGISTER_ITS_DESC(GITS_CREADR,
+   its_mmio_read_raz, its_mmio_write_wi, 8,
+   VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
+   REGISTER_ITS_DESC(GITS_BASER,
+   its_mmio_read_raz, 

[PATCH 47/55] KVM: arm64: vgic-its: Fix vgic_its_check_device_id BE handling

2016-07-22 Thread Marc Zyngier
The ITS tables are stored in LE format. If the host is reading
a L1 table entry to check its validity, it must convert it to
the CPU endianness.

Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-its.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index d6697c4..2ac5927 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -707,6 +707,8 @@ static bool vgic_its_check_device_id(struct kvm *kvm, 
struct vgic_its *its,
   _ptr, sizeof(indirect_ptr)))
return false;
 
+   indirect_ptr = le64_to_cpu(indirect_ptr);
+
/* check the valid bit of the first level entry */
if (!(indirect_ptr & BIT_ULL(63)))
return false;
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 44/55] irqchip/gicv3-its: Restore all cacheability attributes

2016-07-22 Thread Marc Zyngier
Let's restore some of the #defines that have been savagely dropped
by the introduction of the KVM ITS code, as pointlessly break
other users (including series that are already in -next).

Signed-off-by: Marc Zyngier 
---
 include/linux/irqchip/arm-gic-v3.h | 48 +++---
 1 file changed, 40 insertions(+), 8 deletions(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h 
b/include/linux/irqchip/arm-gic-v3.h
index 9442be7..700b421 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -146,8 +146,16 @@
 
 #define GICR_PROPBASER_InnerShareable  \
GIC_BASER_SHAREABILITY(GICR_PROPBASER, InnerShareable)
-#define GICR_PROPBASER_nC GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, nC)
-#define GICR_PROPBASER_WaWb GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WaWb)
+
+#define GICR_PROPBASER_nCnBGIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
nCnB)
+#define GICR_PROPBASER_nC  GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
nC)
+#define GICR_PROPBASER_RaWtGIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
RaWt)
+#define GICR_PROPBASER_RaWbGIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
RaWt)
+#define GICR_PROPBASER_WaWtGIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
WaWt)
+#define GICR_PROPBASER_WaWbGIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
WaWb)
+#define GICR_PROPBASER_RaWaWt  GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
RaWaWt)
+#define GICR_PROPBASER_RaWaWb  GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, 
RaWaWb)
+
 #define GICR_PROPBASER_IDBITS_MASK (0x1f)
 
 #define GICR_PENDBASER_SHAREABILITY_SHIFT  (10)
@@ -163,8 +171,16 @@
 
 #define GICR_PENDBASER_InnerShareable  \
GIC_BASER_SHAREABILITY(GICR_PENDBASER, InnerShareable)
-#define GICR_PENDBASER_nC GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, nC)
-#define GICR_PENDBASER_WaWb GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, WaWb)
+
+#define GICR_PENDBASER_nCnBGIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
nCnB)
+#define GICR_PENDBASER_nC  GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
nC)
+#define GICR_PENDBASER_RaWtGIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
RaWt)
+#define GICR_PENDBASER_RaWbGIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
RaWt)
+#define GICR_PENDBASER_WaWtGIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
WaWt)
+#define GICR_PENDBASER_WaWbGIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
WaWb)
+#define GICR_PENDBASER_RaWaWt  GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
RaWaWt)
+#define GICR_PENDBASER_RaWaWb  GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, 
RaWaWb)
+
 #define GICR_PENDBASER_PTZ BIT_ULL(62)
 
 /*
@@ -237,24 +253,40 @@
 
 #define GITS_CBASER_InnerShareable \
GIC_BASER_SHAREABILITY(GITS_CBASER, InnerShareable)
-#define GITS_CBASER_nC GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nC)
-#define GITS_CBASER_WaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWb)
+
+#define GITS_CBASER_nCnB   GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nCnB)
+#define GITS_CBASER_nC GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nC)
+#define GITS_CBASER_RaWt   GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWt)
+#define GITS_CBASER_RaWb   GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWt)
+#define GITS_CBASER_WaWt   GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWt)
+#define GITS_CBASER_WaWb   GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWb)
+#define GITS_CBASER_RaWaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, 
RaWaWt)
+#define GITS_CBASER_RaWaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, 
RaWaWb)
 
 #define GITS_BASER_NR_REGS 8
 
 #define GITS_BASER_VALID   (1UL << 63)
 #define GITS_BASER_INDIRECT(1ULL << 62)
+
 #define GITS_BASER_INNER_CACHEABILITY_SHIFT(59)
 #define GITS_BASER_OUTER_CACHEABILITY_SHIFT(53)
 #define GITS_BASER_INNER_CACHEABILITY_MASK \
GIC_BASER_CACHEABILITY(GITS_BASER, INNER, MASK)
+#define GITS_BASER_CACHEABILITY_MASK   
GITS_BASER_INNER_CACHEABILITY_MASK
 #define GITS_BASER_OUTER_CACHEABILITY_MASK \
GIC_BASER_CACHEABILITY(GITS_BASER, OUTER, MASK)
 #define GITS_BASER_SHAREABILITY_MASK   \
GIC_BASER_SHAREABILITY(GITS_BASER, SHAREABILITY_MASK)
 
-#define GITS_BASER_nC GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nC)
-#define GITS_BASER_WaWb GIC_BASER_CACHEABILITY(GITS_BASER, INNER, WaWb)
+#define GITS_BASER_nCnBGIC_BASER_CACHEABILITY(GITS_BASER, 
INNER, nCnB)
+#define GITS_BASER_nC  GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nC)
+#define GITS_BASER_RaWtGIC_BASER_CACHEABILITY(GITS_BASER, 
INNER, RaWt)
+#define GITS_BASER_RaWbGIC_BASER_CACHEABILITY(GITS_BASER, 
INNER, RaWt)
+#define 

[PATCH 52/55] KVM: arm64: vgic-its: Add pointer to corresponding kvm_device

2016-07-22 Thread Marc Zyngier
Going from the ITS structure to the corresponding KVM structure
would be quite handy at times. The kvm_device pointer that is
passed at create time is quite convenient for this, so let's
keep a copy of it in the vgic_its structure.

This will be put to a good use in subsequent patches.

Signed-off-by: Marc Zyngier 
---
 include/kvm/arm_vgic.h   | 1 +
 virt/kvm/arm/vgic/vgic-its.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 4e63a07..540da51 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -138,6 +138,7 @@ struct vgic_its {
boolenabled;
boolinitialized;
struct vgic_io_device   iodev;
+   struct kvm_device   *dev;
 
/* These registers correspond to GITS_BASER{0,1} */
u64 baser_device_table;
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index d6f68e9..dcae567 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1368,6 +1368,7 @@ static int vgic_its_create(struct kvm_device *dev, u32 
type)
dev->kvm->arch.vgic.has_its = true;
its->initialized = false;
its->enabled = false;
+   its->dev = dev;
 
its->baser_device_table = INITIAL_BASER_VALUE   |
((u64)GITS_BASER_TYPE_DEVICE << GITS_BASER_TYPE_SHIFT);
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 41/55] KVM: arm64: vgic-its: Implement MSI injection in ITS emulation

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

When userland wants to inject an MSI into the guest, it uses the
KVM_SIGNAL_MSI ioctl, which carries the doorbell address along with
the payload and the device ID.
With the help of the KVM IO bus framework we learn the corresponding
ITS from the doorbell address. We then use our wrapper functions to
iterate the linked lists and find the proper Interrupt Translation Table
Entry (ITTE) and thus the corresponding struct vgic_irq to finally set
the pending bit.
We also provide the handler for the ITS "INT" command, which allows a
guest to trigger an MSI via the ITS command queue. Since this one knows
about the right ITS already, we directly call the MMIO handler function
without using the kvm_io_bus framework.

Signed-off-by: Andre Przywara 
Reviewed-by: Marc Zyngier 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-its.c | 77 
 virt/kvm/arm/vgic/vgic.h |  6 
 2 files changed, 83 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 1408c88..d8e8f14 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -437,6 +437,65 @@ static unsigned long vgic_mmio_read_its_idregs(struct kvm 
*kvm,
return 0;
 }
 
+/*
+ * Find the target VCPU and the LPI number for a given devid/eventid pair
+ * and make this IRQ pending, possibly injecting it.
+ * Must be called with the its_lock mutex held.
+ */
+static void vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
+u32 devid, u32 eventid)
+{
+   struct its_itte *itte;
+
+   if (!its->enabled)
+   return;
+
+   itte = find_itte(its, devid, eventid);
+   /* Triggering an unmapped IRQ gets silently dropped. */
+   if (itte && its_is_collection_mapped(itte->collection)) {
+   struct kvm_vcpu *vcpu;
+
+   vcpu = kvm_get_vcpu(kvm, itte->collection->target_addr);
+   if (vcpu && vcpu->arch.vgic_cpu.lpis_enabled) {
+   spin_lock(>irq->irq_lock);
+   itte->irq->pending = true;
+   vgic_queue_irq_unlock(kvm, itte->irq);
+   }
+   }
+}
+
+/*
+ * Queries the KVM IO bus framework to get the ITS pointer from the given
+ * doorbell address.
+ * We then call vgic_its_trigger_msi() with the decoded data.
+ */
+int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
+{
+   u64 address;
+   struct kvm_io_device *kvm_io_dev;
+   struct vgic_io_device *iodev;
+
+   if (!vgic_has_its(kvm))
+   return -ENODEV;
+
+   if (!(msi->flags & KVM_MSI_VALID_DEVID))
+   return -EINVAL;
+
+   address = (u64)msi->address_hi << 32 | msi->address_lo;
+
+   kvm_io_dev = kvm_io_bus_get_dev(kvm, KVM_MMIO_BUS, address);
+   if (!kvm_io_dev)
+   return -ENODEV;
+
+   iodev = container_of(kvm_io_dev, struct vgic_io_device, dev);
+
+   mutex_lock(>its->its_lock);
+   vgic_its_trigger_msi(kvm, iodev->its, msi->devid, msi->data);
+   mutex_unlock(>its->its_lock);
+
+   return 0;
+}
+
 /* Requires the its_lock to be held. */
 static void its_free_itte(struct kvm *kvm, struct its_itte *itte)
 {
@@ -897,6 +956,21 @@ static int vgic_its_cmd_handle_movall(struct kvm *kvm, 
struct vgic_its *its,
 }
 
 /*
+ * The INT command injects the LPI associated with that DevID/EvID pair.
+ * Must be called with the its_lock mutex held.
+ */
+static int vgic_its_cmd_handle_int(struct kvm *kvm, struct vgic_its *its,
+  u64 *its_cmd)
+{
+   u32 msi_data = its_cmd_get_id(its_cmd);
+   u64 msi_devid = its_cmd_get_deviceid(its_cmd);
+
+   vgic_its_trigger_msi(kvm, its, msi_devid, msi_data);
+
+   return 0;
+}
+
+/*
  * This function is called with the its_cmd lock held, but the ITS data
  * structure lock dropped.
  */
@@ -932,6 +1006,9 @@ static int vgic_its_handle_command(struct kvm *kvm, struct 
vgic_its *its,
case GITS_CMD_MOVALL:
ret = vgic_its_cmd_handle_movall(kvm, its, its_cmd);
break;
+   case GITS_CMD_INT:
+   ret = vgic_its_cmd_handle_int(kvm, its, its_cmd);
+   break;
case GITS_CMD_INV:
ret = vgic_its_cmd_handle_inv(kvm, its, its_cmd);
break;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index ee348de..9d557f2 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -78,6 +78,7 @@ int vgic_v3_map_resources(struct kvm *kvm);
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
 bool vgic_has_its(struct kvm *kvm);
 void vgic_enable_lpis(struct kvm_vcpu *vcpu);
+int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi);
 #else
 static inline void 

[PATCH 39/55] KVM: arm64: vgic-its: Allow updates of LPI configuration table

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

The (system-wide) LPI configuration table is held in a table in
(guest) memory. To achieve reasonable performance, we cache this data
in our struct vgic_irq. If the guest updates the configuration data
(which consists of the enable bit and the priority value), it issues
an INV or INVALL command to allow us to update our information.
Provide functions that update that information for one LPI or all LPIs
mapped to a specific collection.

Signed-off-by: Andre Przywara 
Reviewed-by: Marc Zyngier 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-its.c | 39 +++
 1 file changed, 39 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 2881b84..6f43b3b 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -68,6 +68,45 @@ struct its_itte {
  */
 #define CBASER_ADDRESS(x)  ((x) & GENMASK_ULL(47, 12))
 #define PENDBASER_ADDRESS(x)   ((x) & GENMASK_ULL(47, 16))
+#define PROPBASER_ADDRESS(x)   ((x) & GENMASK_ULL(47, 12))
+
+#define GIC_LPI_OFFSET 8192
+
+#define LPI_PROP_ENABLE_BIT(p) ((p) & LPI_PROP_ENABLED)
+#define LPI_PROP_PRIORITY(p)   ((p) & 0xfc)
+
+/*
+ * Reads the configuration data for a given LPI from guest memory and
+ * updates the fields in struct vgic_irq.
+ * If filter_vcpu is not NULL, applies only if the IRQ is targeting this
+ * VCPU. Unconditionally applies if filter_vcpu is NULL.
+ */
+static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
+struct kvm_vcpu *filter_vcpu)
+{
+   u64 propbase = PROPBASER_ADDRESS(kvm->arch.vgic.propbaser);
+   u8 prop;
+   int ret;
+
+   ret = kvm_read_guest(kvm, propbase + irq->intid - GIC_LPI_OFFSET,
+, 1);
+
+   if (ret)
+   return ret;
+
+   spin_lock(>irq_lock);
+
+   if (!filter_vcpu || filter_vcpu == irq->target_vcpu) {
+   irq->priority = LPI_PROP_PRIORITY(prop);
+   irq->enabled = LPI_PROP_ENABLE_BIT(prop);
+
+   vgic_queue_irq_unlock(kvm, irq);
+   } else {
+   spin_unlock(>irq_lock);
+   }
+
+   return 0;
+}
 
 /*
  * Create a snapshot of the current LPI list, so that we can enumerate all
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 33/55] KVM: arm64: vgic: Handle ITS related GICv3 redistributor registers

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

In the GICv3 redistributor there are the PENDBASER and PROPBASER
registers which we did not emulate so far, as they only make sense
when having an ITS. In preparation for that emulate those MMIO
accesses by storing the 64-bit data written into it into a variable
which we later read in the ITS emulation.
We also sanitise the registers, making sure RES0 regions are respected
and checking for valid memory attributes.

Signed-off-by: Andre Przywara 
Reviewed-by: Marc Zyngier 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 include/kvm/arm_vgic.h   |  13 
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 153 ++-
 virt/kvm/arm/vgic/vgic-mmio.h|   8 ++
 virt/kvm/arm/vgic/vgic-v3.c  |  11 ++-
 4 files changed, 181 insertions(+), 4 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 450b4da..df2dec5 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -146,6 +146,14 @@ struct vgic_dist {
struct vgic_irq *spis;
 
struct vgic_io_device   dist_iodev;
+
+   /*
+* Contains the attributes and gpa of the LPI configuration table.
+* Since we report GICR_TYPER.CommonLPIAff as 0b00, we can share
+* one address across all redistributors.
+* GICv3 spec: 6.1.2 "LPI Configuration tables"
+*/
+   u64 propbaser;
 };
 
 struct vgic_v2_cpu_if {
@@ -200,6 +208,11 @@ struct vgic_cpu {
 */
struct vgic_io_device   rd_iodev;
struct vgic_io_device   sgi_iodev;
+
+   /* Contains the attributes and gpa of the LPI pending tables. */
+   u64 pendbaser;
+
+   bool lpis_enabled;
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index bfcafbd..278bfbb 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -29,6 +29,19 @@ static unsigned long extract_bytes(unsigned long data, 
unsigned int offset,
return (data >> (offset * 8)) & GENMASK_ULL(num * 8 - 1, 0);
 }
 
+/* allows updates of any half of a 64-bit register (or the whole thing) */
+static u64 update_64bit_reg(u64 reg, unsigned int offset, unsigned int len,
+   unsigned long val)
+{
+   int lower = (offset & 4) * 8;
+   int upper = lower + 8 * len - 1;
+
+   reg &= ~GENMASK_ULL(upper, lower);
+   val &= GENMASK_ULL(len * 8 - 1, 0);
+
+   return reg | ((u64)val << lower);
+}
+
 static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len)
 {
@@ -152,6 +165,142 @@ static unsigned long vgic_mmio_read_v3_idregs(struct 
kvm_vcpu *vcpu,
return 0;
 }
 
+/* We want to avoid outer shareable. */
+u64 vgic_sanitise_shareability(u64 field)
+{
+   switch (field) {
+   case GIC_BASER_OuterShareable:
+   return GIC_BASER_InnerShareable;
+   default:
+   return field;
+   }
+}
+
+/* Avoid any inner non-cacheable mapping. */
+u64 vgic_sanitise_inner_cacheability(u64 field)
+{
+   switch (field) {
+   case GIC_BASER_CACHE_nCnB:
+   case GIC_BASER_CACHE_nC:
+   return GIC_BASER_CACHE_RaWb;
+   default:
+   return field;
+   }
+}
+
+/* Non-cacheable or same-as-inner are OK. */
+u64 vgic_sanitise_outer_cacheability(u64 field)
+{
+   switch (field) {
+   case GIC_BASER_CACHE_SameAsInner:
+   case GIC_BASER_CACHE_nC:
+   return field;
+   default:
+   return GIC_BASER_CACHE_nC;
+   }
+}
+
+u64 vgic_sanitise_field(u64 reg, u64 field_mask, int field_shift,
+   u64 (*sanitise_fn)(u64))
+{
+   u64 field = (reg & field_mask) >> field_shift;
+
+   field = sanitise_fn(field) << field_shift;
+   return (reg & ~field_mask) | field;
+}
+
+#define PROPBASER_RES0_MASK\
+   (GENMASK_ULL(63, 59) | GENMASK_ULL(55, 52) | GENMASK_ULL(6, 5))
+#define PENDBASER_RES0_MASK\
+   (BIT_ULL(63) | GENMASK_ULL(61, 59) | GENMASK_ULL(55, 52) |  \
+GENMASK_ULL(15, 12) | GENMASK_ULL(6, 0))
+
+static u64 vgic_sanitise_pendbaser(u64 reg)
+{
+   reg = vgic_sanitise_field(reg, GICR_PENDBASER_SHAREABILITY_MASK,
+ GICR_PENDBASER_SHAREABILITY_SHIFT,
+ vgic_sanitise_shareability);
+   reg = vgic_sanitise_field(reg, GICR_PENDBASER_INNER_CACHEABILITY_MASK,
+ GICR_PENDBASER_INNER_CACHEABILITY_SHIFT,
+ vgic_sanitise_inner_cacheability);
+   reg = vgic_sanitise_field(reg, GICR_PENDBASER_OUTER_CACHEABILITY_MASK,
+   

[PATCH 35/55] KVM: arm64: vgic-its: Introduce new KVM ITS device

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

Introduce a new KVM device that represents an ARM Interrupt Translation
Service (ITS) controller. Since there can be multiple of this per guest,
we can't piggy back on the existing GICv3 distributor device, but create
a new type of KVM device.
On the KVM_CREATE_DEVICE ioctl we allocate and initialize the ITS data
structure and store the pointer in the kvm_device data.
Upon an explicit init ioctl from userland (after having setup the MMIO
address) we register the handlers with the kvm_io_bus framework.
Any reference to an ITS thus has to go via this interface.

Signed-off-by: Andre Przywara 
Reviewed-by: Marc Zyngier 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 Documentation/virtual/kvm/devices/arm-vgic.txt |  25 +++--
 arch/arm/kvm/arm.c |   1 +
 arch/arm64/include/uapi/asm/kvm.h  |   2 +
 include/kvm/arm_vgic.h |   3 +
 include/uapi/linux/kvm.h   |   2 +
 virt/kvm/arm/vgic/vgic-its.c   | 135 +
 virt/kvm/arm/vgic/vgic-kvm-device.c|   4 +-
 virt/kvm/arm/vgic/vgic-mmio-v3.c   |   2 +-
 virt/kvm/arm/vgic/vgic.h   |   3 +
 9 files changed, 168 insertions(+), 9 deletions(-)

diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt 
b/Documentation/virtual/kvm/devices/arm-vgic.txt
index 59541d4..89182f8 100644
--- a/Documentation/virtual/kvm/devices/arm-vgic.txt
+++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
@@ -4,16 +4,22 @@ ARM Virtual Generic Interrupt Controller (VGIC)
 Device types supported:
   KVM_DEV_TYPE_ARM_VGIC_V2 ARM Generic Interrupt Controller v2.0
   KVM_DEV_TYPE_ARM_VGIC_V3 ARM Generic Interrupt Controller v3.0
+  KVM_DEV_TYPE_ARM_VGIC_ITSARM Interrupt Translation Service Controller
 
-Only one VGIC instance may be instantiated through either this API or the
-legacy KVM_CREATE_IRQCHIP api.  The created VGIC will act as the VM interrupt
-controller, requiring emulated user-space devices to inject interrupts to the
-VGIC instead of directly to CPUs.
+Only one VGIC instance of the V2/V3 types above may be instantiated through
+either this API or the legacy KVM_CREATE_IRQCHIP api.  The created VGIC will
+act as the VM interrupt controller, requiring emulated user-space devices to
+inject interrupts to the VGIC instead of directly to CPUs.
 
 Creating a guest GICv3 device requires a host GICv3 as well.
 GICv3 implementations with hardware compatibility support allow a guest GICv2
 as well.
 
+Creating a virtual ITS controller requires a host GICv3 (but does not depend
+on having physical ITS controllers).
+There can be multiple ITS controllers per guest, each of them has to have
+a separate, non-overlapping MMIO region.
+
 Groups:
   KVM_DEV_ARM_VGIC_GRP_ADDR
   Attributes:
@@ -39,6 +45,13 @@ Groups:
   Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
   This address needs to be 64K aligned.
 
+KVM_VGIC_V3_ADDR_TYPE_ITS (rw, 64-bit)
+  Base address in the guest physical address space of the GICv3 ITS
+  control register frame. The ITS allows MSI(-X) interrupts to be
+  injected into guests. This extension is optional. If the kernel
+  does not support the ITS, the call returns -ENODEV.
+  Only valid for KVM_DEV_TYPE_ARM_VGIC_ITS.
+  This address needs to be 64K aligned and the region covers 128K.
 
   KVM_DEV_ARM_VGIC_GRP_DIST_REGS
   Attributes:
@@ -109,8 +122,8 @@ Groups:
   KVM_DEV_ARM_VGIC_GRP_CTRL
   Attributes:
 KVM_DEV_ARM_VGIC_CTRL_INIT
-  request the initialization of the VGIC, no additional parameter in
-  kvm_device_attr.addr.
+  request the initialization of the VGIC or ITS, no additional parameter
+  in kvm_device_attr.addr.
   Errors:
 -ENXIO: VGIC not properly configured as required prior to calling
  this attribute
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 972075c..fb4661c 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
diff --git a/arch/arm64/include/uapi/asm/kvm.h 
b/arch/arm64/include/uapi/asm/kvm.h
index f209ea1..3051f86 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -87,9 +87,11 @@ struct kvm_regs {
 /* Supported VGICv3 address types  */
 #define KVM_VGIC_V3_ADDR_TYPE_DIST 2
 #define KVM_VGIC_V3_ADDR_TYPE_REDIST   3
+#define KVM_VGIC_ITS_ADDR_TYPE 4
 
 #define KVM_VGIC_V3_DIST_SIZE  SZ_64K
 #define KVM_VGIC_V3_REDIST_SIZE(2 * SZ_64K)
+#define KVM_VGIC_V3_ITS_SIZE   (2 * SZ_64K)
 
 #define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
 #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h

[PATCH 51/55] KVM: arm64: vgic-its: Add collection allocator/destructor

2016-07-22 Thread Marc Zyngier
Instead of spreading random allocations all over the place,
consolidate allocation/init/freeing of collections in a pair
of constructor/destructor.

Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-its.c | 92 ++--
 1 file changed, 54 insertions(+), 38 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 2faf1f4..d6f68e9 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -581,14 +581,45 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, 
struct vgic_its *its,
return 0;
 }
 
-static void vgic_its_init_collection(struct vgic_its *its,
-struct its_collection *collection,
+static int vgic_its_alloc_collection(struct vgic_its *its,
+struct its_collection **colp,
 u32 coll_id)
 {
+   struct its_collection *collection;
+
+   collection = kzalloc(sizeof(*collection), GFP_KERNEL);
+
collection->collection_id = coll_id;
collection->target_addr = COLLECTION_NOT_MAPPED;
 
list_add_tail(>coll_list, >collection_list);
+   *colp = collection;
+
+   return 0;
+}
+
+static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
+{
+   struct its_collection *collection;
+   struct its_device *device;
+   struct its_itte *itte;
+
+   /*
+* Clearing the mapping for that collection ID removes the
+* entry from the list. If there wasn't any before, we can
+* go home early.
+*/
+   collection = find_collection(its, coll_id);
+   if (!collection)
+   return;
+
+   for_each_lpi_its(device, itte, its)
+   if (itte->collection &&
+   itte->collection->collection_id == coll_id)
+   itte->collection = NULL;
+
+   list_del(>coll_list);
+   kfree(collection);
 }
 
 /*
@@ -605,6 +636,7 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct 
vgic_its *its,
struct its_device *device;
struct its_collection *collection, *new_coll = NULL;
int lpi_nr;
+   int ret;
 
device = find_its_device(its, device_id);
if (!device)
@@ -612,9 +644,10 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, 
struct vgic_its *its,
 
collection = find_collection(its, coll_id);
if (!collection) {
-   new_coll = kzalloc(sizeof(struct its_collection), GFP_KERNEL);
-   if (!new_coll)
-   return -ENOMEM;
+   ret = vgic_its_alloc_collection(its, , coll_id);
+   if (ret)
+   return ret;
+   new_coll = collection;
}
 
if (subcmd == GITS_CMD_MAPTI)
@@ -623,27 +656,22 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, 
struct vgic_its *its,
lpi_nr = event_id;
if (lpi_nr < GIC_LPI_OFFSET ||
lpi_nr >= max_lpis_propbaser(kvm->arch.vgic.propbaser)) {
-   kfree(new_coll);
-   return E_ITS_MAPTI_PHYSICALID_OOR;
+   ret = E_ITS_MAPTI_PHYSICALID_OOR;
+   goto err;
}
 
itte = find_itte(its, device_id, event_id);
if (!itte) {
itte = kzalloc(sizeof(struct its_itte), GFP_KERNEL);
if (!itte) {
-   kfree(new_coll);
-   return -ENOMEM;
+   ret = -ENOMEM;
+   goto err;
}
 
itte->event_id  = event_id;
list_add_tail(>itte_list, >itt_head);
}
 
-   if (!collection) {
-   collection = new_coll;
-   vgic_its_init_collection(its, collection, coll_id);
-   }
-
itte->collection = collection;
itte->lpi = lpi_nr;
itte->irq = vgic_add_lpi(kvm, lpi_nr);
@@ -657,6 +685,10 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, 
struct vgic_its *its,
update_lpi_config(kvm, itte->irq, NULL);
 
return 0;
+err:
+   if (new_coll)
+   vgic_its_free_collection(its, coll_id);
+   return ret;
 }
 
 /* Requires the its_lock to be held. */
@@ -809,34 +841,18 @@ static int vgic_its_cmd_handle_mapc(struct kvm *kvm, 
struct vgic_its *its,
if (coll_id >= vgic_its_nr_collection_ids(its))
return E_ITS_MAPC_COLLECTION_OOR;
 
-   collection = find_collection(its, coll_id);
-
if (!valid) {
-   struct its_device *device;
-   struct its_itte *itte;
-   /*
-* Clearing the mapping for that collection ID removes the
-* entry from the list. If there wasn't any before, we can
-* go home early.
-*/
-   if (!collection)
-   return 0;
-
-   for_each_lpi_its(device, itte, its)

[PATCH 42/55] KVM: arm64: vgic-its: Enable ITS emulation as a virtual MSI controller

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

Now that all ITS emulation functionality is in place, we advertise
MSI functionality to userland and also the ITS device to the guest - if
userland has configured that.

Signed-off-by: Andre Przywara 
Reviewed-by: Marc Zyngier 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 Documentation/virtual/kvm/api.txt   |  2 +-
 arch/arm64/kvm/Kconfig  |  1 +
 arch/arm64/kvm/Makefile |  1 +
 arch/arm64/kvm/reset.c  |  6 ++
 include/kvm/arm_vgic.h  |  5 +
 virt/kvm/arm/vgic/vgic-init.c   |  3 +++
 virt/kvm/arm/vgic/vgic-kvm-device.c |  3 +++
 virt/kvm/arm/vgic/vgic-mmio-v3.c| 14 ++
 virt/kvm/arm/vgic/vgic.c|  8 
 virt/kvm/arm/vgic/vgic.h|  6 ++
 10 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/Documentation/virtual/kvm/api.txt 
b/Documentation/virtual/kvm/api.txt
index 6551311..07049ea 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2162,7 +2162,7 @@ after pausing the vcpu, but before it is resumed.
 4.71 KVM_SIGNAL_MSI
 
 Capability: KVM_CAP_SIGNAL_MSI
-Architectures: x86
+Architectures: x86 arm64
 Type: vm ioctl
 Parameters: struct kvm_msi (in)
 Returns: >0 on delivery, 0 if guest blocked the MSI, and -1 on error
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index aa2e34e..9d2eff0 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -36,6 +36,7 @@ config KVM
select HAVE_KVM_IRQFD
select KVM_ARM_VGIC_V3
select KVM_ARM_PMU if HW_PERF_EVENTS
+   select HAVE_KVM_MSI
---help---
  Support hosting virtualized guest machines.
  We don't support KVM with 16K page tables yet, due to the multiple
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index f00b2cd..a5b9664 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -29,5 +29,6 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-its.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
 kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index e95d4f6..5bc4608 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -86,6 +86,12 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long 
ext)
case KVM_CAP_VCPU_ATTRIBUTES:
r = 1;
break;
+   case KVM_CAP_MSI_DEVID:
+   if (!kvm)
+   r = -EINVAL;
+   else
+   r = kvm->arch.vgic.msis_require_devid;
+   break;
default:
r = 0;
}
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index a6ca326..4e63a07 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -163,6 +163,9 @@ struct vgic_dist {
/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
u32 vgic_model;
 
+   /* Do injected MSIs require an additional device ID? */
+   boolmsis_require_devid;
+
int nr_spis;
 
/* TODO: Consider moving to global state */
@@ -308,4 +311,6 @@ static inline int kvm_vgic_get_max_vcpus(void)
return kvm_vgic_global_state.max_gic_vcpus;
 }
 
+int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi);
+
 #endif /* __KVM_ARM_VGIC_H */
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 535e713..01a60dc 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -258,6 +258,9 @@ int vgic_init(struct kvm *kvm)
if (ret)
goto out;
 
+   if (vgic_has_its(kvm))
+   dist->msis_require_devid = true;
+
kvm_for_each_vcpu(i, vcpu, kvm)
kvm_vgic_vcpu_init(vcpu);
 
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c 
b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 561d2ba..1813f93 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -223,6 +223,9 @@ int kvm_register_vgic_device(unsigned long type)
case KVM_DEV_TYPE_ARM_VGIC_V3:
ret = kvm_register_device_ops(_arm_vgic_v3_ops,
  KVM_DEV_TYPE_ARM_VGIC_V3);
+   if (ret)
+   break;
+   ret = kvm_vgic_register_its_device();
break;
 #endif
}
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 84a301d..ff668e0 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ 

[PATCH 54/55] KVM: arm64: vgic-its: Make vgic_its_cmd_handle_mapi similar to other handlers

2016-07-22 Thread Marc Zyngier
vgic_its_cmd_handle_mapi has an extra "subcmd" argument, which is
already contained in the command buffer that all command handlers
obtain from the command queue. Let's drop it, as it is not that
useful.

Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-its.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 996e3e1..ec7e07b 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -688,7 +688,7 @@ static void vgic_its_free_collection(struct vgic_its *its, 
u32 coll_id)
  * Must be called with its_lock mutex held.
  */
 static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
-   u64 *its_cmd, u8 subcmd)
+   u64 *its_cmd)
 {
u32 device_id = its_cmd_get_deviceid(its_cmd);
u32 event_id = its_cmd_get_id(its_cmd);
@@ -711,7 +711,7 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct 
vgic_its *its,
new_coll = collection;
}
 
-   if (subcmd == GITS_CMD_MAPTI)
+   if (its_cmd_get_command(its_cmd) == GITS_CMD_MAPTI)
lpi_nr = its_cmd_get_physical_id(its_cmd);
else
lpi_nr = event_id;
@@ -999,11 +999,10 @@ static int vgic_its_cmd_handle_int(struct kvm *kvm, 
struct vgic_its *its,
 static int vgic_its_handle_command(struct kvm *kvm, struct vgic_its *its,
   u64 *its_cmd)
 {
-   u8 cmd = its_cmd_get_command(its_cmd);
int ret = -ENODEV;
 
mutex_lock(>its_lock);
-   switch (cmd) {
+   switch (its_cmd_get_command(its_cmd)) {
case GITS_CMD_MAPD:
ret = vgic_its_cmd_handle_mapd(kvm, its, its_cmd);
break;
@@ -1011,10 +1010,10 @@ static int vgic_its_handle_command(struct kvm *kvm, 
struct vgic_its *its,
ret = vgic_its_cmd_handle_mapc(kvm, its, its_cmd);
break;
case GITS_CMD_MAPI:
-   ret = vgic_its_cmd_handle_mapi(kvm, its, its_cmd, cmd);
+   ret = vgic_its_cmd_handle_mapi(kvm, its, its_cmd);
break;
case GITS_CMD_MAPTI:
-   ret = vgic_its_cmd_handle_mapi(kvm, its, its_cmd, cmd);
+   ret = vgic_its_cmd_handle_mapi(kvm, its, its_cmd);
break;
case GITS_CMD_MOVI:
ret = vgic_its_cmd_handle_movi(kvm, its, its_cmd);
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 55/55] KVM: arm64: vgic-its: Simplify MAPI error handling

2016-07-22 Thread Marc Zyngier
If we care to move all the checks that do not involve any memory
allocation, we can simplify the MAPI error handling. Let's do that,
it cannot hurt.

Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-its.c | 30 --
 1 file changed, 12 insertions(+), 18 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index ec7e07b..07411cf 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -697,36 +697,34 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, 
struct vgic_its *its,
struct its_device *device;
struct its_collection *collection, *new_coll = NULL;
int lpi_nr;
-   int ret;
 
device = find_its_device(its, device_id);
if (!device)
return E_ITS_MAPTI_UNMAPPED_DEVICE;
 
-   collection = find_collection(its, coll_id);
-   if (!collection) {
-   ret = vgic_its_alloc_collection(its, , coll_id);
-   if (ret)
-   return ret;
-   new_coll = collection;
-   }
-
if (its_cmd_get_command(its_cmd) == GITS_CMD_MAPTI)
lpi_nr = its_cmd_get_physical_id(its_cmd);
else
lpi_nr = event_id;
if (lpi_nr < GIC_LPI_OFFSET ||
-   lpi_nr >= max_lpis_propbaser(kvm->arch.vgic.propbaser)) {
-   ret = E_ITS_MAPTI_PHYSICALID_OOR;
-   goto err;
+   lpi_nr >= max_lpis_propbaser(kvm->arch.vgic.propbaser))
+   return E_ITS_MAPTI_PHYSICALID_OOR;
+
+   collection = find_collection(its, coll_id);
+   if (!collection) {
+   int ret = vgic_its_alloc_collection(its, , coll_id);
+   if (ret)
+   return ret;
+   new_coll = collection;
}
 
itte = find_itte(its, device_id, event_id);
if (!itte) {
itte = kzalloc(sizeof(struct its_itte), GFP_KERNEL);
if (!itte) {
-   ret = -ENOMEM;
-   goto err;
+   if (new_coll)
+   vgic_its_free_collection(its, coll_id);
+   return -ENOMEM;
}
 
itte->event_id  = event_id;
@@ -746,10 +744,6 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, 
struct vgic_its *its,
update_lpi_config(kvm, itte->irq, NULL);
 
return 0;
-err:
-   if (new_coll)
-   vgic_its_free_collection(its, coll_id);
-   return ret;
 }
 
 /* Requires the its_lock to be held. */
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 46/55] KVM: arm64: vgic-its: Fix handling of indirect tables

2016-07-22 Thread Marc Zyngier
The current code will fail on valid indirect tables, and happily
use the ones that are pointing out of the guest RAM. Funny what a
small "!" can do for you...

Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-its.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index f427fa2..d6697c4 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -702,9 +702,9 @@ static bool vgic_its_check_device_id(struct kvm *kvm, 
struct vgic_its *its,
return false;
 
/* Each 1st level entry is represented by a 64-bit value. */
-   if (!kvm_read_guest(kvm,
-   BASER_ADDRESS(r) + index * sizeof(indirect_ptr),
-   _ptr, sizeof(indirect_ptr)))
+   if (kvm_read_guest(kvm,
+  BASER_ADDRESS(r) + index * sizeof(indirect_ptr),
+  _ptr, sizeof(indirect_ptr)))
return false;
 
/* check the valid bit of the first level entry */
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 49/55] KVM: arm64: vgic-its: Validate the device table L1 entry

2016-07-22 Thread Marc Zyngier
Checking that the device_id fits if the table, and we must make
sure that the associated memory is also accessible.

Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-its.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 268a0c7..4943d6a 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -693,8 +693,17 @@ static bool vgic_its_check_device_id(struct kvm *kvm, 
struct vgic_its *its,
gfn_t gfn;
 
 
-   if (!(r & GITS_BASER_INDIRECT))
-   return device_id < (l1_tbl_size / GITS_BASER_ENTRY_SIZE(r));
+   if (!(r & GITS_BASER_INDIRECT)) {
+   phys_addr_t addr;
+
+   if (device_id >= (l1_tbl_size / GITS_BASER_ENTRY_SIZE(r)))
+   return false;
+
+   addr = BASER_ADDRESS(r) + device_id * GITS_BASER_ENTRY_SIZE(r);
+   gfn = addr >> PAGE_SHIFT;
+
+   return kvm_is_visible_gfn(kvm, gfn);
+   }
 
/* calculate and check the index into the 1st level */
index = device_id / (SZ_64K / GITS_BASER_ENTRY_SIZE(r));
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 48/55] KVM: arm64: vgic-its: Fix misleading nr_entries in vgic_its_check_device_id

2016-07-22 Thread Marc Zyngier
The nr_entries variable in vgic_its_check_device_id actually
describe the size of the L1 table, and not the number of
entries in this table.

Rename it to l1_tbl_size, so that we can now change the code
with a better understanding of what is what.

Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-its.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 2ac5927..268a0c7 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -687,18 +687,18 @@ static bool vgic_its_check_device_id(struct kvm *kvm, 
struct vgic_its *its,
 int device_id)
 {
u64 r = its->baser_device_table;
-   int nr_entries = GITS_BASER_NR_PAGES(r) * SZ_64K;
+   int l1_tbl_size = GITS_BASER_NR_PAGES(r) * SZ_64K;
int index;
u64 indirect_ptr;
gfn_t gfn;
 
 
if (!(r & GITS_BASER_INDIRECT))
-   return device_id < (nr_entries / GITS_BASER_ENTRY_SIZE(r));
+   return device_id < (l1_tbl_size / GITS_BASER_ENTRY_SIZE(r));
 
/* calculate and check the index into the 1st level */
index = device_id / (SZ_64K / GITS_BASER_ENTRY_SIZE(r));
-   if (index >= (nr_entries / sizeof(u64)))
+   if (index >= (l1_tbl_size / sizeof(u64)))
return false;
 
/* Each 1st level entry is represented by a 64-bit value. */
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 53/55] KVM: arm64: vgic-its: Turn device_id validation into generic ID validation

2016-07-22 Thread Marc Zyngier
There is no need to have separate functions to validate devices
and collections, as the architecture doesn't really distinguish the
two, and they are supposed to be managed the same way.

Let's turn the DevID checker into a generic one.

Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-its.c | 134 ---
 1 file changed, 62 insertions(+), 72 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index dcae567..996e3e1 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -581,12 +581,73 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, 
struct vgic_its *its,
return 0;
 }
 
+/*
+ * Check whether an ID can be stored into the corresponding guest table.
+ * For a direct table this is pretty easy, but gets a bit nasty for
+ * indirect tables. We check whether the resulting guest physical address
+ * is actually valid (covered by a memslot and guest accessbible).
+ * For this we have to read the respective first level entry.
+ */
+static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id)
+{
+   int l1_tbl_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
+   int index;
+   u64 indirect_ptr;
+   gfn_t gfn;
+
+   if (!(baser & GITS_BASER_INDIRECT)) {
+   phys_addr_t addr;
+
+   if (id >= (l1_tbl_size / GITS_BASER_ENTRY_SIZE(baser)))
+   return false;
+
+   addr = BASER_ADDRESS(baser) + id * GITS_BASER_ENTRY_SIZE(baser);
+   gfn = addr >> PAGE_SHIFT;
+
+   return kvm_is_visible_gfn(its->dev->kvm, gfn);
+   }
+
+   /* calculate and check the index into the 1st level */
+   index = id / (SZ_64K / GITS_BASER_ENTRY_SIZE(baser));
+   if (index >= (l1_tbl_size / sizeof(u64)))
+   return false;
+
+   /* Each 1st level entry is represented by a 64-bit value. */
+   if (kvm_read_guest(its->dev->kvm,
+  BASER_ADDRESS(baser) + index * sizeof(indirect_ptr),
+  _ptr, sizeof(indirect_ptr)))
+   return false;
+
+   indirect_ptr = le64_to_cpu(indirect_ptr);
+
+   /* check the valid bit of the first level entry */
+   if (!(indirect_ptr & BIT_ULL(63)))
+   return false;
+
+   /*
+* Mask the guest physical address and calculate the frame number.
+* Any address beyond our supported 48 bits of PA will be caught
+* by the actual check in the final step.
+*/
+   indirect_ptr &= GENMASK_ULL(51, 16);
+
+   /* Find the address of the actual entry */
+   index = id % (SZ_64K / GITS_BASER_ENTRY_SIZE(baser));
+   indirect_ptr += index * GITS_BASER_ENTRY_SIZE(baser);
+   gfn = indirect_ptr >> PAGE_SHIFT;
+
+   return kvm_is_visible_gfn(its->dev->kvm, gfn);
+}
+
 static int vgic_its_alloc_collection(struct vgic_its *its,
 struct its_collection **colp,
 u32 coll_id)
 {
struct its_collection *collection;
 
+   if (!vgic_its_check_id(its, its->baser_coll_table, coll_id))
+   return E_ITS_MAPC_COLLECTION_OOR;
+
collection = kzalloc(sizeof(*collection), GFP_KERNEL);
 
collection->collection_id = coll_id;
@@ -709,67 +770,6 @@ static void vgic_its_unmap_device(struct kvm *kvm, struct 
its_device *device)
 }
 
 /*
- * Check whether a device ID can be stored into the guest device tables.
- * For a direct table this is pretty easy, but gets a bit nasty for
- * indirect tables. We check whether the resulting guest physical address
- * is actually valid (covered by a memslot and guest accessbible).
- * For this we have to read the respective first level entry.
- */
-static bool vgic_its_check_device_id(struct kvm *kvm, struct vgic_its *its,
-int device_id)
-{
-   u64 r = its->baser_device_table;
-   int l1_tbl_size = GITS_BASER_NR_PAGES(r) * SZ_64K;
-   int index;
-   u64 indirect_ptr;
-   gfn_t gfn;
-
-
-   if (!(r & GITS_BASER_INDIRECT)) {
-   phys_addr_t addr;
-
-   if (device_id >= (l1_tbl_size / GITS_BASER_ENTRY_SIZE(r)))
-   return false;
-
-   addr = BASER_ADDRESS(r) + device_id * GITS_BASER_ENTRY_SIZE(r);
-   gfn = addr >> PAGE_SHIFT;
-
-   return kvm_is_visible_gfn(kvm, gfn);
-   }
-
-   /* calculate and check the index into the 1st level */
-   index = device_id / (SZ_64K / GITS_BASER_ENTRY_SIZE(r));
-   if (index >= (l1_tbl_size / sizeof(u64)))
-   return false;
-
-   /* Each 1st level entry is represented by a 64-bit value. */
-   if (kvm_read_guest(kvm,
-  BASER_ADDRESS(r) + index * sizeof(indirect_ptr),
-  _ptr, sizeof(indirect_ptr)))
-   return false;
-
-   indirect_ptr = 

[PATCH 45/55] KVM: arm64: vgic-its: Generalize use of vgic_get_irq_kref

2016-07-22 Thread Marc Zyngier
Instead of sprinkling raw kref_get() calls everytime we cannot
do a normal vgic_get_irq(), use the existing vgic_get_irq_kref(),
which does the same thing and is paired with a vgic_put_irq().

vgic_get_irq_kref is moved to vgic.h in order to be easily shared.

Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-its.c |  2 +-
 virt/kvm/arm/vgic/vgic.c | 10 +-
 virt/kvm/arm/vgic/vgic.h |  8 
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index d8e8f14..f427fa2 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -80,7 +80,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 
intid)
 * call vgic_put_irq() on the returned pointer once it's
 * finished with the IRQ.
 */
-   kref_get(>refcount);
+   vgic_get_irq_kref(irq);
 
goto out_unlock;
}
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 424cb9c..39f3358 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -71,7 +71,7 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 
intid)
 * This increases the refcount, the caller is expected to
 * call vgic_put_irq() later once it's finished with the IRQ.
 */
-   kref_get(>refcount);
+   vgic_get_irq_kref(irq);
goto out_unlock;
}
irq = NULL;
@@ -106,14 +106,6 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct 
kvm_vcpu *vcpu,
return NULL;
 }
 
-static void vgic_get_irq_kref(struct vgic_irq *irq)
-{
-   if (irq->intid < VGIC_MIN_LPI)
-   return;
-
-   kref_get(>refcount);
-}
-
 /*
  * We can't do anything in here, because we lack the kvm pointer to
  * lock and remove the item from the lpi_list. So we keep this function
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 9d40d7b..1d8e21d 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -64,6 +64,14 @@ int vgic_v2_map_resources(struct kvm *kvm);
 int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address,
 enum vgic_type);
 
+static inline void vgic_get_irq_kref(struct vgic_irq *irq)
+{
+   if (irq->intid < VGIC_MIN_LPI)
+   return;
+
+   kref_get(>refcount);
+}
+
 #ifdef CONFIG_KVM_ARM_VGIC_V3
 void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu);
 void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 50/55] KVM: arm64: vgic-its: Fix L2 entry validation for indirect tables

2016-07-22 Thread Marc Zyngier
When checking that the storage address of a device entry is valid,
it is critical to compute the actual address of the entry, rather
than relying on the beginning of the page to match a CPU page of
the same size: for example, if the guest places the table at the
last 64kB boundary of RAM, but RAM size isn't a multiple of 64kB...

Fix this by computing the actual offset of the device ID in the
L2 page, and check the corresponding GFN.

Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-its.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 4943d6a..2faf1f4 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -727,7 +727,12 @@ static bool vgic_its_check_device_id(struct kvm *kvm, 
struct vgic_its *its,
 * Any address beyond our supported 48 bits of PA will be caught
 * by the actual check in the final step.
 */
-   gfn = (indirect_ptr & GENMASK_ULL(51, 16)) >> PAGE_SHIFT;
+   indirect_ptr &= GENMASK_ULL(51, 16);
+
+   /* Find the address of the actual entry */
+   index = device_id % (SZ_64K / GITS_BASER_ENTRY_SIZE(r));
+   indirect_ptr += index * GITS_BASER_ENTRY_SIZE(r);
+   gfn = indirect_ptr >> PAGE_SHIFT;
 
return kvm_is_visible_gfn(kvm, gfn);
 }
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 15/55] arm64: KVM: Runtime detection of lower HYP offset

2016-07-22 Thread Marc Zyngier
Add the code that enables the switch to the lower HYP VA range.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm64/kernel/cpufeature.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 811773d..ffb3e14 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -726,6 +726,19 @@ static bool runs_at_el2(const struct 
arm64_cpu_capabilities *entry, int __unused
return is_kernel_in_hyp_mode();
 }
 
+static bool hyp_offset_low(const struct arm64_cpu_capabilities *entry,
+  int __unused)
+{
+   phys_addr_t idmap_addr = virt_to_phys(__hyp_idmap_text_start);
+
+   /*
+* Activate the lower HYP offset only if:
+* - the idmap doesn't clash with it,
+* - the kernel is not running at EL2.
+*/
+   return idmap_addr > GENMASK(VA_BITS - 2, 0) && !is_kernel_in_hyp_mode();
+}
+
 static const struct arm64_cpu_capabilities arm64_features[] = {
{
.desc = "GIC system register CPU interface",
@@ -803,6 +816,12 @@ static const struct arm64_cpu_capabilities 
arm64_features[] = {
.field_pos = ID_AA64PFR0_EL0_SHIFT,
.min_field_value = ID_AA64PFR0_EL0_32BIT_64BIT,
},
+   {
+   .desc = "Reduced HYP mapping offset",
+   .capability = ARM64_HYP_OFFSET_LOW,
+   .def_scope = SCOPE_SYSTEM,
+   .matches = hyp_offset_low,
+   },
{},
 };
 
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 40/55] KVM: arm64: vgic-its: Implement ITS command queue command handlers

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

The connection between a device, an event ID, the LPI number and the
associated CPU is stored in in-memory tables in a GICv3, but their
format is not specified by the spec. Instead software uses a command
queue in a ring buffer to let an ITS implementation use its own
format.
Implement handlers for the various ITS commands and let them store
the requested relation into our own data structures. Those data
structures are protected by the its_lock mutex.
Our internal ring buffer read and write pointers are protected by the
its_cmd mutex, so that only one VCPU per ITS can handle commands at
any given time.
Error handling is very basic at the moment, as we don't have a good
way of communicating errors to the guest (usually an SError).
The INT command handler is missing from this patch, as we gain the
capability of actually injecting MSIs into the guest only later on.

Signed-off-by: Andre Przywara 
Reviewed-by: Marc Zyngier 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-its.c | 661 ++-
 1 file changed, 660 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 6f43b3b..1408c88 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -33,6 +33,67 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+/*
+ * Creates a new (reference to a) struct vgic_irq for a given LPI.
+ * If this LPI is already mapped on another ITS, we increase its refcount
+ * and return a pointer to the existing structure.
+ * If this is a "new" LPI, we allocate and initialize a new struct vgic_irq.
+ * This function returns a pointer to the _unlocked_ structure.
+ */
+static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid)
+{
+   struct vgic_dist *dist = >arch.vgic;
+   struct vgic_irq *irq = vgic_get_irq(kvm, NULL, intid), *oldirq;
+
+   /* In this case there is no put, since we keep the reference. */
+   if (irq)
+   return irq;
+
+   irq = kzalloc(sizeof(struct vgic_irq), GFP_KERNEL);
+   if (!irq)
+   return NULL;
+
+   INIT_LIST_HEAD(>lpi_list);
+   INIT_LIST_HEAD(>ap_list);
+   spin_lock_init(>irq_lock);
+
+   irq->config = VGIC_CONFIG_EDGE;
+   kref_init(>refcount);
+   irq->intid = intid;
+
+   spin_lock(>lpi_list_lock);
+
+   /*
+* There could be a race with another vgic_add_lpi(), so we need to
+* check that we don't add a second list entry with the same LPI.
+*/
+   list_for_each_entry(oldirq, >lpi_list_head, lpi_list) {
+   if (oldirq->intid != intid)
+   continue;
+
+   /* Someone was faster with adding this LPI, lets use that. */
+   kfree(irq);
+   irq = oldirq;
+
+   /*
+* This increases the refcount, the caller is expected to
+* call vgic_put_irq() on the returned pointer once it's
+* finished with the IRQ.
+*/
+   kref_get(>refcount);
+
+   goto out_unlock;
+   }
+
+   list_add_tail(>lpi_list, >lpi_list_head);
+   dist->lpi_list_count++;
+
+out_unlock:
+   spin_unlock(>lpi_list_lock);
+
+   return irq;
+}
+
 struct its_device {
struct list_head dev_list;
 
@@ -63,15 +124,74 @@ struct its_itte {
 };
 
 /*
+ * Find and returns a device in the device table for an ITS.
+ * Must be called with the its_lock mutex held.
+ */
+static struct its_device *find_its_device(struct vgic_its *its, u32 device_id)
+{
+   struct its_device *device;
+
+   list_for_each_entry(device, >device_list, dev_list)
+   if (device_id == device->device_id)
+   return device;
+
+   return NULL;
+}
+
+/*
+ * Find and returns an interrupt translation table entry (ITTE) for a given
+ * Device ID/Event ID pair on an ITS.
+ * Must be called with the its_lock mutex held.
+ */
+static struct its_itte *find_itte(struct vgic_its *its, u32 device_id,
+ u32 event_id)
+{
+   struct its_device *device;
+   struct its_itte *itte;
+
+   device = find_its_device(its, device_id);
+   if (device == NULL)
+   return NULL;
+
+   list_for_each_entry(itte, >itt_head, itte_list)
+   if (itte->event_id == event_id)
+   return itte;
+
+   return NULL;
+}
+
+/* To be used as an iterator this macro misses the enclosing parentheses */
+#define for_each_lpi_its(dev, itte, its) \
+   list_for_each_entry(dev, &(its)->device_list, dev_list) \
+   list_for_each_entry(itte, &(dev)->itt_head, itte_list)
+
+/*
  * We only implement 48 bits of PA at the moment, although the ITS
  * supports more. Let's be restrictive here.
  */
+#define 

[PATCH 43/55] KVM: arm/arm64: Fix vGICv2 KVM_DEV_ARM_VGIC_GRP_CPU/DIST_REGS

2016-07-22 Thread Marc Zyngier
From: Eric Auger 

For VGICv2 save and restore the CPU interface registers
are accessed. Restore the modality which has been altered.
Also explicitly set the iodev_type for both the DIST and CPU
interface.

Signed-off-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-mmio-v2.c | 2 ++
 virt/kvm/arm/vgic/vgic-mmio.c| 4 +++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 4152348..b44b359 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -437,6 +437,7 @@ int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool 
is_write,
struct vgic_io_device dev = {
.regions = vgic_v2_cpu_registers,
.nr_regions = ARRAY_SIZE(vgic_v2_cpu_registers),
+   .iodev_type = IODEV_CPUIF,
};
 
return vgic_uaccess(vcpu, , is_write, offset, val);
@@ -448,6 +449,7 @@ int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool 
is_write,
struct vgic_io_device dev = {
.regions = vgic_v2_dist_registers,
.nr_regions = ARRAY_SIZE(vgic_v2_dist_registers),
+   .iodev_type = IODEV_DIST,
};
 
return vgic_uaccess(vcpu, , is_write, offset, val);
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 26be827..3bad3c5 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -484,7 +484,8 @@ static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct 
kvm_io_device *dev,
 
switch (iodev->iodev_type) {
case IODEV_CPUIF:
-   return 1;
+   data = region->read(vcpu, addr, len);
+   break;
case IODEV_DIST:
data = region->read(vcpu, addr, len);
break;
@@ -517,6 +518,7 @@ static int dispatch_mmio_write(struct kvm_vcpu *vcpu, 
struct kvm_io_device *dev,
 
switch (iodev->iodev_type) {
case IODEV_CPUIF:
+   region->write(vcpu, addr, len, data);
break;
case IODEV_DIST:
region->write(vcpu, addr, len, data);
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 14/55] arm/arm64: KVM: Export __hyp_text_start/end symbols

2016-07-22 Thread Marc Zyngier
Declare the __hyp_text_start/end symbols in asm/virt.h so that
they can be reused without having to declare them locally.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm/include/asm/virt.h   | 4 
 arch/arm/kvm/mmu.c| 2 --
 arch/arm64/include/asm/virt.h | 4 
 3 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/virt.h b/arch/arm/include/asm/virt.h
index d4ceaf5..a2e75b8 100644
--- a/arch/arm/include/asm/virt.h
+++ b/arch/arm/include/asm/virt.h
@@ -80,6 +80,10 @@ static inline bool is_kernel_in_hyp_mode(void)
return false;
 }
 
+/* The section containing the hypervisor idmap text */
+extern char __hyp_idmap_text_start[];
+extern char __hyp_idmap_text_end[];
+
 /* The section containing the hypervisor text */
 extern char __hyp_text_start[];
 extern char __hyp_text_end[];
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 679608f..f004e70 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -32,8 +32,6 @@
 
 #include "trace.h"
 
-extern char  __hyp_idmap_text_start[], __hyp_idmap_text_end[];
-
 static pgd_t *boot_hyp_pgd;
 static pgd_t *hyp_pgd;
 static pgd_t *merged_hyp_pgd;
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index dcbcf8d..88aa8ec 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -82,6 +82,10 @@ extern void verify_cpu_run_el(void);
 static inline void verify_cpu_run_el(void) {}
 #endif
 
+/* The section containing the hypervisor idmap text */
+extern char __hyp_idmap_text_start[];
+extern char __hyp_idmap_text_end[];
+
 /* The section containing the hypervisor text */
 extern char __hyp_text_start[];
 extern char __hyp_text_end[];
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 36/55] KVM: arm64: vgic-its: Implement basic ITS register handlers

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

Add emulation for some basic MMIO registers used in the ITS emulation.
This includes:
- GITS_{CTLR,TYPER,IIDR}
- ID registers
- GITS_{CBASER,CREADR,CWRITER}
  (which implement the ITS command buffer handling)
- GITS_BASER

Most of the handlers are pretty straight forward, only the CWRITER
handler is a bit more involved by taking the new its_cmd mutex and
then iterating over the command buffer.
The registers holding base addresses and attributes are sanitised before
storing them.

Signed-off-by: Andre Przywara 
Reviewed-by: Marc Zyngier 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 include/kvm/arm_vgic.h   |  16 ++
 virt/kvm/arm/vgic/vgic-its.c | 399 +--
 virt/kvm/arm/vgic/vgic-mmio-v3.c |   8 +-
 virt/kvm/arm/vgic/vgic-mmio.h|   6 +
 virt/kvm/arm/vgic/vgic.c |  12 +-
 5 files changed, 420 insertions(+), 21 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 8609fac..6186749 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define VGIC_V3_MAX_CPUS   255
 #define VGIC_V2_MAX_CPUS   8
@@ -136,6 +137,21 @@ struct vgic_its {
boolenabled;
boolinitialized;
struct vgic_io_device   iodev;
+
+   /* These registers correspond to GITS_BASER{0,1} */
+   u64 baser_device_table;
+   u64 baser_coll_table;
+
+   /* Protects the command queue */
+   struct mutexcmd_lock;
+   u64 cbaser;
+   u32 creadr;
+   u32 cwriter;
+
+   /* Protects the device and collection lists */
+   struct mutexits_lock;
+   struct list_headdevice_list;
+   struct list_headcollection_list;
 };
 
 struct vgic_dist {
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 6b47b36..11cfe2f 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -32,6 +33,329 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+struct its_device {
+   struct list_head dev_list;
+
+   /* the head for the list of ITTEs */
+   struct list_head itt_head;
+   u32 device_id;
+};
+
+#define COLLECTION_NOT_MAPPED ((u32)~0)
+
+struct its_collection {
+   struct list_head coll_list;
+
+   u32 collection_id;
+   u32 target_addr;
+};
+
+#define its_is_collection_mapped(coll) ((coll) && \
+   ((coll)->target_addr != COLLECTION_NOT_MAPPED))
+
+struct its_itte {
+   struct list_head itte_list;
+
+   struct its_collection *collection;
+   u32 lpi;
+   u32 event_id;
+};
+
+/*
+ * We only implement 48 bits of PA at the moment, although the ITS
+ * supports more. Let's be restrictive here.
+ */
+#define CBASER_ADDRESS(x)  ((x) & GENMASK_ULL(47, 12))
+
+static unsigned long vgic_mmio_read_its_ctlr(struct kvm *vcpu,
+struct vgic_its *its,
+gpa_t addr, unsigned int len)
+{
+   u32 reg = 0;
+
+   mutex_lock(>cmd_lock);
+   if (its->creadr == its->cwriter)
+   reg |= GITS_CTLR_QUIESCENT;
+   if (its->enabled)
+   reg |= GITS_CTLR_ENABLE;
+   mutex_unlock(>cmd_lock);
+
+   return reg;
+}
+
+static void vgic_mmio_write_its_ctlr(struct kvm *kvm, struct vgic_its *its,
+gpa_t addr, unsigned int len,
+unsigned long val)
+{
+   its->enabled = !!(val & GITS_CTLR_ENABLE);
+}
+
+static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm,
+ struct vgic_its *its,
+ gpa_t addr, unsigned int len)
+{
+   u64 reg = GITS_TYPER_PLPIS;
+
+   /*
+* We use linear CPU numbers for redistributor addressing,
+* so GITS_TYPER.PTA is 0.
+* Also we force all PROPBASER registers to be the same, so
+* CommonLPIAff is 0 as well.
+* To avoid memory waste in the guest, we keep the number of IDBits and
+* DevBits low - as least for the time being.
+*/
+   reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
+   reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
+
+   return extract_bytes(reg, addr & 7, len);
+}
+
+static unsigned long vgic_mmio_read_its_iidr(struct kvm *kvm,
+struct vgic_its *its,
+gpa_t addr, unsigned int len)
+{
+   return (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+}
+
+static unsigned long 

[PATCH 17/55] arm64: KVM: Simplify HYP init/teardown

2016-07-22 Thread Marc Zyngier
Now that we only have the "merged page tables" case to deal with,
there is a bunch of things we can simplify in the HYP code (both
at init and teardown time).

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm64/include/asm/kvm_host.h | 12 ++--
 arch/arm64/kvm/hyp-init.S | 61 +--
 arch/arm64/kvm/hyp/entry.S| 19 
 arch/arm64/kvm/hyp/hyp-entry.S| 15 ++
 arch/arm64/kvm/reset.c| 11 ---
 5 files changed, 26 insertions(+), 92 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index 49095fc..88462c3 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -48,7 +48,6 @@
 int __attribute_const__ kvm_target_cpu(void);
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
 int kvm_arch_dev_ioctl_check_extension(long ext);
-unsigned long kvm_hyp_reset_entry(void);
 void __extended_idmap_trampoline(phys_addr_t boot_pgd, phys_addr_t 
idmap_start);
 
 struct kvm_arch {
@@ -357,19 +356,14 @@ static inline void __cpu_init_hyp_mode(phys_addr_t 
boot_pgd_ptr,
 * Call initialization code, and switch to the full blown
 * HYP code.
 */
-   __kvm_call_hyp((void *)boot_pgd_ptr, pgd_ptr,
-  hyp_stack_ptr, vector_ptr);
+   __kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr);
 }
 
+void __kvm_hyp_teardown(void);
 static inline void __cpu_reset_hyp_mode(phys_addr_t boot_pgd_ptr,
phys_addr_t phys_idmap_start)
 {
-   /*
-* Call reset code, and switch back to stub hyp vectors.
-* Uses __kvm_call_hyp() to avoid kaslr's kvm_ksym_ref() translation.
-*/
-   __kvm_call_hyp((void *)kvm_hyp_reset_entry(),
-  boot_pgd_ptr, phys_idmap_start);
+   kvm_call_hyp(__kvm_hyp_teardown, phys_idmap_start);
 }
 
 static inline void kvm_arch_hardware_unsetup(void) {}
diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S
index a873a6d..6b29d3d 100644
--- a/arch/arm64/kvm/hyp-init.S
+++ b/arch/arm64/kvm/hyp-init.S
@@ -53,10 +53,9 @@ __invalid:
b   .
 
/*
-* x0: HYP boot pgd
-* x1: HYP pgd
-* x2: HYP stack
-* x3: HYP vectors
+* x0: HYP pgd
+* x1: HYP stack
+* x2: HYP vectors
 */
 __do_hyp_init:
 
@@ -110,71 +109,27 @@ __do_hyp_init:
msr sctlr_el2, x4
isb
 
-   /* Skip the trampoline dance if we merged the boot and runtime PGDs */
-   cmp x0, x1
-   b.eqmerged
-
-   /* MMU is now enabled. Get ready for the trampoline dance */
-   ldr x4, =TRAMPOLINE_VA
-   adr x5, target
-   bfi x4, x5, #0, #PAGE_SHIFT
-   br  x4
-
-target: /* We're now in the trampoline code, switch page tables */
-   msr ttbr0_el2, x1
-   isb
-
-   /* Invalidate the old TLBs */
-   tlbialle2
-   dsb sy
-
-merged:
/* Set the stack and new vectors */
+   kern_hyp_va x1
+   mov sp, x1
kern_hyp_va x2
-   mov sp, x2
-   kern_hyp_va x3
-   msr vbar_el2, x3
+   msr vbar_el2, x2
 
/* Hello, World! */
eret
 ENDPROC(__kvm_hyp_init)
 
/*
-* Reset kvm back to the hyp stub. This is the trampoline dance in
-* reverse. If kvm used an extended idmap, __extended_idmap_trampoline
-* calls this code directly in the idmap. In this case switching to the
-* boot tables is a no-op.
-*
-* x0: HYP boot pgd
-* x1: HYP phys_idmap_start
+* Reset kvm back to the hyp stub.
 */
 ENTRY(__kvm_hyp_reset)
-   /* We're in trampoline code in VA, switch back to boot page tables */
-   msr ttbr0_el2, x0
-   isb
-
-   /* Ensure the PA branch doesn't find a stale tlb entry or stale code. */
-   ic  iallu
-   tlbialle2
-   dsb sy
-   isb
-
-   /* Branch into PA space */
-   adr x0, 1f
-   bfi x1, x0, #0, #PAGE_SHIFT
-   br  x1
-
/* We're now in idmap, disable MMU */
-1: mrs x0, sctlr_el2
+   mrs x0, sctlr_el2
ldr x1, =SCTLR_ELx_FLAGS
bic x0, x0, x1  // Clear SCTL_M and etc
msr sctlr_el2, x0
isb
 
-   /* Invalidate the old TLBs */
-   tlbialle2
-   dsb sy
-
/* Install stub vectors */
adr_l   x0, __hyp_stub_vectors
msr vbar_el2, x0
diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
index 70254a6..ce9e5e5 100644
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -164,22 +164,3 @@ alternative_endif
 
eret
 ENDPROC(__fpsimd_guest_restore)
-
-/*
- * When using the extended idmap, we don't have a trampoline page we can use
- * while we switch 

[PATCH 10/55] arm64: KVM: Kill HYP_PAGE_OFFSET

2016-07-22 Thread Marc Zyngier
HYP_PAGE_OFFSET is not massively useful. And the way we use it
in KERN_HYP_VA is inconsistent with the equivalent operation in
EL2, where we use a mask instead.

Let's replace the uses of HYP_PAGE_OFFSET with HYP_PAGE_OFFSET_MASK,
and get rid of the pointless macro.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm64/include/asm/kvm_mmu.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 6149dfc..2f1e1ae 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -70,7 +70,6 @@
  */
 #define HYP_PAGE_OFFSET_SHIFT  VA_BITS
 #define HYP_PAGE_OFFSET_MASK   ((UL(1) << HYP_PAGE_OFFSET_SHIFT) - 1)
-#define HYP_PAGE_OFFSET(PAGE_OFFSET & HYP_PAGE_OFFSET_MASK)
 
 /*
  * Our virtual mapping for the idmap-ed MMU-enable code. Must be
@@ -104,7 +103,7 @@ alternative_endif
 #include 
 #include 
 
-#define KERN_TO_HYP(kva)   ((unsigned long)kva - PAGE_OFFSET + 
HYP_PAGE_OFFSET)
+#define KERN_TO_HYP(kva)   ((unsigned long)kva & HYP_PAGE_OFFSET_MASK)
 
 /*
  * We currently only support a 40bit IPA.
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 23/55] arm/arm64: KVM: Check that IDMAP doesn't intersect with VA range

2016-07-22 Thread Marc Zyngier
This is more of a safety measure than anything else: If we end-up
with an idmap page that intersect with the range picked for the
the HYP VA space, abort the KVM setup, as it is unsafe to go
further.

I cannot imagine it happening on 64bit (we have a mechanism to
work around it), but could potentially occur on a 32bit system with
the kernel loaded high enough in memory so that in conflicts with
the kernel VA.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm/kvm/mmu.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 0b36dd52..8a0aa37 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -1709,6 +1709,21 @@ int kvm_mmu_init(void)
 */
BUG_ON((hyp_idmap_start ^ (hyp_idmap_end - 1)) & PAGE_MASK);
 
+   kvm_info("IDMAP page: %lx\n", hyp_idmap_start);
+   kvm_info("HYP VA range: %lx:%lx\n",
+KERN_TO_HYP(PAGE_OFFSET), KERN_TO_HYP(~0UL));
+
+   if (hyp_idmap_start >= KERN_TO_HYP(PAGE_OFFSET) &&
+   hyp_idmap_start <  KERN_TO_HYP(~0UL)) {
+   /*
+* The idmap page is intersecting with the VA space,
+* it is not safe to continue further.
+*/
+   kvm_err("IDMAP intersecting with HYP VA, unable to continue\n");
+   err = -EINVAL;
+   goto out;
+   }
+
hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 
hyp_pgd_order);
if (!hyp_pgd) {
kvm_err("Hyp mode PGD not allocated\n");
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 28/55] KVM: Extend struct kvm_msi to hold a 32-bit device ID

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

The ARM GICv3 ITS MSI controller requires a device ID to be able to
assign the proper interrupt vector. On real hardware, this ID is
sampled from the bus. To be able to emulate an ITS controller, extend
the KVM MSI interface to let userspace provide such a device ID. For
PCI devices, the device ID is simply the 16-bit bus-device-function
triplet, which should be easily available to the userland tool.

Also there is a new KVM capability which advertises whether the
current VM requires a device ID to be set along with the MSI data.
This flag is still reported as not available everywhere, later we will
enable it when ITS emulation is used.

Signed-off-by: Andre Przywara 
Reviewed-by: Eric Auger 
Reviewed-by: Marc Zyngier 
Acked-by: Christoffer Dall 
Acked-by: Paolo Bonzini 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 Documentation/virtual/kvm/api.txt | 12 ++--
 include/uapi/linux/kvm.h  |  5 -
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/Documentation/virtual/kvm/api.txt 
b/Documentation/virtual/kvm/api.txt
index 09efa9e..6551311 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2175,10 +2175,18 @@ struct kvm_msi {
__u32 address_hi;
__u32 data;
__u32 flags;
-   __u8  pad[16];
+   __u32 devid;
+   __u8  pad[12];
 };
 
-No flags are defined so far. The corresponding field must be 0.
+flags: KVM_MSI_VALID_DEVID: devid contains a valid value
+devid: If KVM_MSI_VALID_DEVID is set, contains a unique device identifier
+   for the device that wrote the MSI message.
+   For PCI, this is usually a BFD identifier in the lower 16 bits.
+
+The per-VM KVM_CAP_MSI_DEVID capability advertises the need to provide
+the device ID. If this capability is not set, userland cannot rely on
+the kernel to allow the KVM_MSI_VALID_DEVID flag being set.
 
 
 4.71 KVM_CREATE_PIT2
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 05ebf47..7de96f5 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -866,6 +866,7 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_ARM_PMU_V3 126
 #define KVM_CAP_VCPU_ATTRIBUTES 127
 #define KVM_CAP_MAX_VCPU_ID 128
+#define KVM_CAP_MSI_DEVID 129
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1024,12 +1025,14 @@ struct kvm_one_reg {
__u64 addr;
 };
 
+#define KVM_MSI_VALID_DEVID(1U << 0)
 struct kvm_msi {
__u32 address_lo;
__u32 address_hi;
__u32 data;
__u32 flags;
-   __u8  pad[16];
+   __u32 devid;
+   __u8  pad[12];
 };
 
 struct kvm_arm_device_addr {
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 11/55] arm64: Add ARM64_HYP_OFFSET_LOW capability

2016-07-22 Thread Marc Zyngier
As we need to indicate to the rest of the kernel which region of
the HYP VA space is safe to use, add a capability that will
indicate that KVM should use the [VA_BITS-2:0] range.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm64/include/asm/cpufeature.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/cpufeature.h 
b/arch/arm64/include/asm/cpufeature.h
index 224efe7..d40edbb 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -36,8 +36,9 @@
 #define ARM64_HAS_VIRT_HOST_EXTN   11
 #define ARM64_WORKAROUND_CAVIUM_27456  12
 #define ARM64_HAS_32BIT_EL013
+#define ARM64_HYP_OFFSET_LOW   14
 
-#define ARM64_NCAPS14
+#define ARM64_NCAPS15
 
 #ifndef __ASSEMBLY__
 
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 30/55] KVM: kvm_io_bus: Add kvm_io_bus_get_dev() call

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

The kvm_io_bus framework is a nice place of holding information about
various MMIO regions for kernel emulated devices.
Add a call to retrieve the kvm_io_device structure which is associated
with a certain MMIO address. This avoids to duplicate kvm_io_bus'
knowledge of MMIO regions without having to fake MMIO calls if a user
needs the device a certain MMIO address belongs to.
This will be used by the ITS emulation to get the associated ITS device
when someone triggers an MSI via an ioctl from userspace.

Signed-off-by: Andre Przywara 
Reviewed-by: Eric Auger 
Reviewed-by: Marc Zyngier 
Acked-by: Christoffer Dall 
Acked-by: Paolo Bonzini 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 include/linux/kvm_host.h |  2 ++
 virt/kvm/kvm_main.c  | 24 
 2 files changed, 26 insertions(+)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 0640ee9..614a981 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -164,6 +164,8 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus 
bus_idx, gpa_t addr,
int len, struct kvm_io_device *dev);
 int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
  struct kvm_io_device *dev);
+struct kvm_io_device *kvm_io_bus_get_dev(struct kvm *kvm, enum kvm_bus bus_idx,
+gpa_t addr);
 
 #ifdef CONFIG_KVM_ASYNC_PF
 struct kvm_async_pf {
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index ef54b4c..bd2eb92 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -3496,6 +3496,30 @@ int kvm_io_bus_unregister_dev(struct kvm *kvm, enum 
kvm_bus bus_idx,
return r;
 }
 
+struct kvm_io_device *kvm_io_bus_get_dev(struct kvm *kvm, enum kvm_bus bus_idx,
+gpa_t addr)
+{
+   struct kvm_io_bus *bus;
+   int dev_idx, srcu_idx;
+   struct kvm_io_device *iodev = NULL;
+
+   srcu_idx = srcu_read_lock(>srcu);
+
+   bus = srcu_dereference(kvm->buses[bus_idx], >srcu);
+
+   dev_idx = kvm_io_bus_get_first_dev(bus, addr, 1);
+   if (dev_idx < 0)
+   goto out_unlock;
+
+   iodev = bus->range[dev_idx].dev;
+
+out_unlock:
+   srcu_read_unlock(>srcu, srcu_idx);
+
+   return iodev;
+}
+EXPORT_SYMBOL_GPL(kvm_io_bus_get_dev);
+
 static struct notifier_block kvm_cpu_notifier = {
.notifier_call = kvm_cpu_hotplug,
 };
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 20/55] arm: KVM: Simplify HYP init

2016-07-22 Thread Marc Zyngier
Just like for arm64, we can now make the HYP setup a lot simpler,
and we can now initialise it in one go (instead of the two
phases we currently have).

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm/include/asm/kvm_host.h | 15 +
 arch/arm/kvm/init.S | 49 -
 2 files changed, 14 insertions(+), 50 deletions(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 020f4eb..eafbfd5 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -250,18 +250,13 @@ static inline void __cpu_init_hyp_mode(phys_addr_t 
pgd_ptr,
 * code. The init code doesn't need to preserve these
 * registers as r0-r3 are already callee saved according to
 * the AAPCS.
-* Note that we slightly misuse the prototype by casing the
+* Note that we slightly misuse the prototype by casting the
 * stack pointer to a void *.
-*
-* We don't have enough registers to perform the full init in
-* one go.  Install the boot PGD first, and then install the
-* runtime PGD, stack pointer and vectors. The PGDs are always
-* passed as the third argument, in order to be passed into
-* r2-r3 to the init code (yes, this is compliant with the
-* PCS!).
-*/
 
-   kvm_call_hyp(NULL, 0, boot_pgd_ptr);
+* The PGDs are always passed as the third argument, in order
+* to be passed into r2-r3 to the init code (yes, this is
+* compliant with the PCS!).
+*/
 
kvm_call_hyp((void*)hyp_stack_ptr, vector_ptr, pgd_ptr);
 }
diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S
index 1f9ae17..b82a99d 100644
--- a/arch/arm/kvm/init.S
+++ b/arch/arm/kvm/init.S
@@ -32,23 +32,13 @@
  *   r2,r3 = Hypervisor pgd pointer
  *
  * The init scenario is:
- * - We jump in HYP with four parameters: boot HYP pgd, runtime HYP pgd,
- *   runtime stack, runtime vectors
- * - Enable the MMU with the boot pgd
- * - Jump to a target into the trampoline page (remember, this is the same
- *   physical page!)
- * - Now switch to the runtime pgd (same VA, and still the same physical
- *   page!)
+ * - We jump in HYP with 3 parameters: runtime HYP pgd, runtime stack,
+ *   runtime vectors
  * - Invalidate TLBs
  * - Set stack and vectors
+ * - Setup the page tables
+ * - Enable the MMU
  * - Profit! (or eret, if you only care about the code).
- *
- * As we only have four registers available to pass parameters (and we
- * need six), we split the init in two phases:
- * - Phase 1: r0 = 0, r1 = 0, r2,r3 contain the boot PGD.
- *   Provides the basic HYP init, and enable the MMU.
- * - Phase 2: r0 = ToS, r1 = vectors, r2,r3 contain the runtime PGD.
- *   Switches to the runtime PGD, set stack and vectors.
  */
 
.text
@@ -68,8 +58,11 @@ __kvm_hyp_init:
W(b).
 
 __do_hyp_init:
-   cmp r0, #0  @ We have a SP?
-   bne phase2  @ Yes, second stage init
+   @ Set stack pointer
+   mov sp, r0
+
+   @ Set HVBAR to point to the HYP vectors
+   mcr p15, 4, r1, c12, c0, 0  @ HVBAR
 
@ Set the HTTBR to point to the hypervisor PGD pointer passed
mcrrp15, 4, rr_lo_hi(r2, r3), c2
@@ -114,33 +107,9 @@ __do_hyp_init:
  THUMB(ldr r2, =(HSCTLR_M | HSCTLR_A | HSCTLR_TE)  )
orr r1, r1, r2
orr r0, r0, r1
-   isb
mcr p15, 4, r0, c1, c0, 0   @ HSCR
-
-   @ End of init phase-1
-   eret
-
-phase2:
-   @ Set stack pointer
-   mov sp, r0
-
-   @ Set HVBAR to point to the HYP vectors
-   mcr p15, 4, r1, c12, c0, 0  @ HVBAR
-
-   @ Jump to the trampoline page
-   ldr r0, =TRAMPOLINE_VA
-   adr r1, target
-   bfi r0, r1, #0, #PAGE_SHIFT
-   ret r0
-
-target:@ We're now in the trampoline code, switch page tables
-   mcrrp15, 4, rr_lo_hi(r2, r3), c2
isb
 
-   @ Invalidate the old TLBs
-   mcr p15, 4, r0, c8, c7, 0   @ TLBIALLH
-   dsb ish
-
eret
 
.ltorg
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 27/55] KVM: arm/arm64: vgic: Check return value for kvm_register_vgic_device

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

kvm_register_device_ops() can return an error, so lets check its return
value and propagate this up the call chain.

Signed-off-by: Andre Przywara 
Reviewed-by: Marc Zyngier 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 15 +--
 virt/kvm/arm/vgic/vgic-v2.c | 11 ---
 virt/kvm/arm/vgic/vgic-v3.c | 15 +--
 virt/kvm/arm/vgic/vgic.h|  2 +-
 4 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c 
b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 0130c4b..2f24f13 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -210,20 +210,24 @@ static void vgic_destroy(struct kvm_device *dev)
kfree(dev);
 }
 
-void kvm_register_vgic_device(unsigned long type)
+int kvm_register_vgic_device(unsigned long type)
 {
+   int ret = -ENODEV;
+
switch (type) {
case KVM_DEV_TYPE_ARM_VGIC_V2:
-   kvm_register_device_ops(_arm_vgic_v2_ops,
-   KVM_DEV_TYPE_ARM_VGIC_V2);
+   ret = kvm_register_device_ops(_arm_vgic_v2_ops,
+ KVM_DEV_TYPE_ARM_VGIC_V2);
break;
 #ifdef CONFIG_KVM_ARM_VGIC_V3
case KVM_DEV_TYPE_ARM_VGIC_V3:
-   kvm_register_device_ops(_arm_vgic_v3_ops,
-   KVM_DEV_TYPE_ARM_VGIC_V3);
+   ret = kvm_register_device_ops(_arm_vgic_v3_ops,
+ KVM_DEV_TYPE_ARM_VGIC_V3);
break;
 #endif
}
+
+   return ret;
 }
 
 /** vgic_attr_regs_access: allows user space to read/write VGIC registers
@@ -428,4 +432,3 @@ struct kvm_device_ops kvm_arm_vgic_v3_ops = {
 };
 
 #endif /* CONFIG_KVM_ARM_VGIC_V3 */
-
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index e31405e..079bf67 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -332,20 +332,25 @@ int vgic_v2_probe(const struct gic_kvm_info *info)
vtr = readl_relaxed(kvm_vgic_global_state.vctrl_base + GICH_VTR);
kvm_vgic_global_state.nr_lr = (vtr & 0x3f) + 1;
 
+   ret = kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
+   if (ret) {
+   kvm_err("Cannot register GICv2 KVM device\n");
+   iounmap(kvm_vgic_global_state.vctrl_base);
+   return ret;
+   }
+
ret = create_hyp_io_mappings(kvm_vgic_global_state.vctrl_base,
 kvm_vgic_global_state.vctrl_base +
 resource_size(>vctrl),
 info->vctrl.start);
-
if (ret) {
kvm_err("Cannot map VCTRL into hyp\n");
+   kvm_unregister_device_ops(KVM_DEV_TYPE_ARM_VGIC_V2);
iounmap(kvm_vgic_global_state.vctrl_base);
return ret;
}
 
kvm_vgic_global_state.can_emulate_gicv2 = true;
-   kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
-
kvm_vgic_global_state.vcpu_base = info->vcpu.start;
kvm_vgic_global_state.type = VGIC_V2;
kvm_vgic_global_state.max_gic_vcpus = VGIC_V2_MAX_CPUS;
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 346b4ad..e48a22e 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -296,6 +296,7 @@ out:
 int vgic_v3_probe(const struct gic_kvm_info *info)
 {
u32 ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
+   int ret;
 
/*
 * The ListRegs field is 5 bits, but there is a architectural
@@ -319,12 +320,22 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
} else {
kvm_vgic_global_state.vcpu_base = info->vcpu.start;
kvm_vgic_global_state.can_emulate_gicv2 = true;
-   kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
+   ret = kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V2);
+   if (ret) {
+   kvm_err("Cannot register GICv2 KVM device.\n");
+   return ret;
+   }
kvm_info("vgic-v2@%llx\n", info->vcpu.start);
}
+   ret = kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V3);
+   if (ret) {
+   kvm_err("Cannot register GICv3 KVM device.\n");
+   kvm_unregister_device_ops(KVM_DEV_TYPE_ARM_VGIC_V2);
+   return ret;
+   }
+
if (kvm_vgic_global_state.vcpu_base == 0)
kvm_info("disabling GICv2 emulation\n");
-   kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V3);
 
kvm_vgic_global_state.vctrl_base = NULL;
kvm_vgic_global_state.type = VGIC_V3;
diff --git a/virt/kvm/arm/vgic/vgic.h 

[PATCH 37/55] KVM: arm64: vgic-its: Connect LPIs to the VGIC emulation

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

LPIs are dynamically created (mapped) at guest runtime and their
actual number can be quite high, but is mostly assigned using a very
sparse allocation scheme. So arrays are not an ideal data structure
to hold the information.
We use a spin-lock protected linked list to hold all mapped LPIs,
represented by their struct vgic_irq. This lock is grouped between the
ap_list_lock and the vgic_irq lock in our locking order.
Also we store a pointer to that struct vgic_irq in our struct its_itte,
so we can easily access it.
Eventually we call our new vgic_get_lpi() from vgic_get_irq(), so
the VGIC code gets transparently access to LPIs.

Signed-off-by: Andre Przywara 
Reviewed-by: Marc Zyngier 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 include/kvm/arm_vgic.h|  6 +
 virt/kvm/arm/vgic/vgic-init.c |  3 +++
 virt/kvm/arm/vgic/vgic-its.c  |  5 
 virt/kvm/arm/vgic/vgic-v3.c   |  2 ++
 virt/kvm/arm/vgic/vgic.c  | 63 ++-
 5 files changed, 73 insertions(+), 6 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 6186749..a6ca326 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -77,6 +77,7 @@ enum vgic_irq_config {
 
 struct vgic_irq {
spinlock_t irq_lock;/* Protects the content of the struct */
+   struct list_head lpi_list;  /* Used to link all LPIs together */
struct list_head ap_list;
 
struct kvm_vcpu *vcpu;  /* SGIs and PPIs: The VCPU
@@ -193,6 +194,11 @@ struct vgic_dist {
 * GICv3 spec: 6.1.2 "LPI Configuration tables"
 */
u64 propbaser;
+
+   /* Protects the lpi_list and the count value below. */
+   spinlock_t  lpi_list_lock;
+   struct list_headlpi_list_head;
+   int lpi_list_count;
 };
 
 struct vgic_v2_cpu_if {
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index ac3c1a5..535e713 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -157,6 +157,9 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int 
nr_spis)
struct kvm_vcpu *vcpu0 = kvm_get_vcpu(kvm, 0);
int i;
 
+   INIT_LIST_HEAD(>lpi_list_head);
+   spin_lock_init(>lpi_list_lock);
+
dist->spis = kcalloc(nr_spis, sizeof(struct vgic_irq), GFP_KERNEL);
if (!dist->spis)
return  -ENOMEM;
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 11cfe2f..14f91ff 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -56,6 +56,7 @@ struct its_collection {
 struct its_itte {
struct list_head itte_list;
 
+   struct vgic_irq *irq;
struct its_collection *collection;
u32 lpi;
u32 event_id;
@@ -148,6 +149,10 @@ static unsigned long vgic_mmio_read_its_idregs(struct kvm 
*kvm,
 static void its_free_itte(struct kvm *kvm, struct its_itte *itte)
 {
list_del(>itte_list);
+
+   /* This put matches the get in vgic_add_lpi. */
+   vgic_put_irq(kvm, itte->irq);
+
kfree(itte);
 }
 
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 6f8f31f..0506543 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -81,6 +81,8 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
else
intid = val & GICH_LR_VIRTUALID;
irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+   if (!irq)   /* An LPI could have been unmapped. */
+   continue;
 
spin_lock(>irq_lock);
 
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index d3ba1b4..53299fc 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -36,7 +36,8 @@ struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
  * its->cmd_lock (mutex)
  *   its->its_lock (mutex)
  * vgic_cpu->ap_list_lock
- *   vgic_irq->irq_lock
+ *   kvm->lpi_list_lock
+ * vgic_irq->irq_lock
  *
  * If you need to take multiple locks, always take the upper lock first,
  * then the lower ones, e.g. first take the its_lock, then the irq_lock.
@@ -51,6 +52,41 @@ struct vgic_global __section(.hyp.text) 
kvm_vgic_global_state;
  * spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
  */
 
+/*
+ * Iterate over the VM's list of mapped LPIs to find the one with a
+ * matching interrupt ID and return a reference to the IRQ structure.
+ */
+static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid)
+{
+   struct vgic_dist *dist = >arch.vgic;
+   struct vgic_irq *irq = NULL;
+
+   spin_lock(>lpi_list_lock);
+
+   list_for_each_entry(irq, >lpi_list_head, lpi_list) {
+   if (irq->intid != intid)
+   continue;

[PATCH 12/55] arm64: KVM: Define HYP offset masks

2016-07-22 Thread Marc Zyngier
Define the two possible HYP VA regions in terms of VA_BITS,
and keep HYP_PAGE_OFFSET_MASK as a temporary compatibility
definition.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm64/include/asm/kvm_mmu.h | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 2f1e1ae..5e54323 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -68,8 +68,12 @@
  * functionality is already mapped as part of the main kernel
  * mappings, and none of this applies in that case.
  */
-#define HYP_PAGE_OFFSET_SHIFT  VA_BITS
-#define HYP_PAGE_OFFSET_MASK   ((UL(1) << HYP_PAGE_OFFSET_SHIFT) - 1)
+
+#define HYP_PAGE_OFFSET_HIGH_MASK  ((UL(1) << VA_BITS) - 1)
+#define HYP_PAGE_OFFSET_LOW_MASK   ((UL(1) << (VA_BITS - 1)) - 1)
+
+/* Temporary compat define */
+#define HYP_PAGE_OFFSET_MASK   HYP_PAGE_OFFSET_HIGH_MASK
 
 /*
  * Our virtual mapping for the idmap-ed MMU-enable code. Must be
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 18/55] arm/arm64: KVM: Drop boot_pgd

2016-07-22 Thread Marc Zyngier
Since we now only have one set of page tables, the concept of
boot_pgd is useless and can be removed. We still keep it as
an element of the "extended idmap" thing.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm/include/asm/kvm_host.h   |  8 +++-
 arch/arm/include/asm/kvm_mmu.h|  1 -
 arch/arm/kvm/arm.c| 15 +++
 arch/arm/kvm/mmu.c|  8 
 arch/arm64/include/asm/kvm_host.h |  6 ++
 arch/arm64/include/asm/kvm_mmu.h  |  1 -
 6 files changed, 8 insertions(+), 31 deletions(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 96387d4..020f4eb 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -241,8 +241,7 @@ int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const 
struct kvm_one_reg *);
 int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
int exception_index);
 
-static inline void __cpu_init_hyp_mode(phys_addr_t boot_pgd_ptr,
-  phys_addr_t pgd_ptr,
+static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
   unsigned long hyp_stack_ptr,
   unsigned long vector_ptr)
 {
@@ -272,12 +271,11 @@ static inline void __cpu_init_stage2(void)
kvm_call_hyp(__init_stage2_translation);
 }
 
-static inline void __cpu_reset_hyp_mode(phys_addr_t boot_pgd_ptr,
-   phys_addr_t phys_idmap_start)
+static inline void __cpu_reset_hyp_mode(phys_addr_t phys_idmap_start)
 {
/*
 * TODO
-* kvm_call_reset(boot_pgd_ptr, phys_idmap_start);
+* kvm_call_reset(phys_idmap_start);
 */
 }
 
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 6cb4d4d..5d161d1 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -65,7 +65,6 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct 
kvm_run *run);
 void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu);
 
 phys_addr_t kvm_mmu_get_httbr(void);
-phys_addr_t kvm_mmu_get_boot_httbr(void);
 phys_addr_t kvm_get_idmap_vector(void);
 phys_addr_t kvm_get_idmap_start(void);
 int kvm_mmu_init(void);
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index c74483f..0887cc1 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -1038,7 +1038,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
 
 static void cpu_init_hyp_mode(void *dummy)
 {
-   phys_addr_t boot_pgd_ptr;
phys_addr_t pgd_ptr;
unsigned long hyp_stack_ptr;
unsigned long stack_page;
@@ -1047,13 +1046,12 @@ static void cpu_init_hyp_mode(void *dummy)
/* Switch from the HYP stub to our own HYP init vector */
__hyp_set_vectors(kvm_get_idmap_vector());
 
-   boot_pgd_ptr = kvm_mmu_get_boot_httbr();
pgd_ptr = kvm_mmu_get_httbr();
stack_page = __this_cpu_read(kvm_arm_hyp_stack_page);
hyp_stack_ptr = stack_page + PAGE_SIZE;
vector_ptr = (unsigned long)kvm_ksym_ref(__kvm_hyp_vector);
 
-   __cpu_init_hyp_mode(boot_pgd_ptr, pgd_ptr, hyp_stack_ptr, vector_ptr);
+   __cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr);
__cpu_init_stage2();
 
kvm_arm_init_debug();
@@ -1075,15 +1073,8 @@ static void cpu_hyp_reinit(void)
 
 static void cpu_hyp_reset(void)
 {
-   phys_addr_t boot_pgd_ptr;
-   phys_addr_t phys_idmap_start;
-
-   if (!is_kernel_in_hyp_mode()) {
-   boot_pgd_ptr = kvm_mmu_get_boot_httbr();
-   phys_idmap_start = kvm_get_idmap_start();
-
-   __cpu_reset_hyp_mode(boot_pgd_ptr, phys_idmap_start);
-   }
+   if (!is_kernel_in_hyp_mode())
+   __cpu_reset_hyp_mode(kvm_get_idmap_start());
 }
 
 static void _kvm_arch_hardware_enable(void *discard)
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 80d3737..dd4ccc7 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -1685,14 +1685,6 @@ phys_addr_t kvm_mmu_get_httbr(void)
return virt_to_phys(hyp_pgd);
 }
 
-phys_addr_t kvm_mmu_get_boot_httbr(void)
-{
-   if (__kvm_cpu_uses_extended_idmap())
-   return virt_to_phys(merged_hyp_pgd);
-   else
-   return virt_to_phys(hyp_pgd);
-}
-
 phys_addr_t kvm_get_idmap_vector(void)
 {
return hyp_idmap_vector;
diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index 88462c3..6731d4e 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -347,8 +347,7 @@ int kvm_perf_teardown(void);
 
 struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
 
-static inline void __cpu_init_hyp_mode(phys_addr_t boot_pgd_ptr,
-  phys_addr_t pgd_ptr,
+static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
  

[PATCH 32/55] irqchip/gic-v3: Refactor and add GICv3 definitions

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

arm-gic-v3.h contains bit and register definitions for the GICv3 and ITS,
at least for the bits the we currently care about.
The ITS emulation needs more definitions, so add them and refactor
the memory attribute #defines to be more universally usable.
To avoid changing all users, we still provide some of the old definitons
defined with the help of the new macros.

Signed-off-by: Andre Przywara 
Reviewed-by: Marc Zyngier 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 include/linux/irqchip/arm-gic-v3.h | 180 -
 1 file changed, 120 insertions(+), 60 deletions(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h 
b/include/linux/irqchip/arm-gic-v3.h
index bfbd707..9442be7 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -112,34 +112,60 @@
 #define GICR_WAKER_ProcessorSleep  (1U << 1)
 #define GICR_WAKER_ChildrenAsleep  (1U << 2)
 
-#define GICR_PROPBASER_NonShareable(0U << 10)
-#define GICR_PROPBASER_InnerShareable  (1U << 10)
-#define GICR_PROPBASER_OuterShareable  (2U << 10)
-#define GICR_PROPBASER_SHAREABILITY_MASK (3UL << 10)
-#define GICR_PROPBASER_nCnB(0U << 7)
-#define GICR_PROPBASER_nC  (1U << 7)
-#define GICR_PROPBASER_RaWt(2U << 7)
-#define GICR_PROPBASER_RaWb(3U << 7)
-#define GICR_PROPBASER_WaWt(4U << 7)
-#define GICR_PROPBASER_WaWb(5U << 7)
-#define GICR_PROPBASER_RaWaWt  (6U << 7)
-#define GICR_PROPBASER_RaWaWb  (7U << 7)
-#define GICR_PROPBASER_CACHEABILITY_MASK (7U << 7)
-#define GICR_PROPBASER_IDBITS_MASK (0x1f)
-
-#define GICR_PENDBASER_NonShareable(0U << 10)
-#define GICR_PENDBASER_InnerShareable  (1U << 10)
-#define GICR_PENDBASER_OuterShareable  (2U << 10)
-#define GICR_PENDBASER_SHAREABILITY_MASK (3UL << 10)
-#define GICR_PENDBASER_nCnB(0U << 7)
-#define GICR_PENDBASER_nC  (1U << 7)
-#define GICR_PENDBASER_RaWt(2U << 7)
-#define GICR_PENDBASER_RaWb(3U << 7)
-#define GICR_PENDBASER_WaWt(4U << 7)
-#define GICR_PENDBASER_WaWb(5U << 7)
-#define GICR_PENDBASER_RaWaWt  (6U << 7)
-#define GICR_PENDBASER_RaWaWb  (7U << 7)
-#define GICR_PENDBASER_CACHEABILITY_MASK (7U << 7)
+#define GIC_BASER_CACHE_nCnB   0ULL
+#define GIC_BASER_CACHE_SameAsInner0ULL
+#define GIC_BASER_CACHE_nC 1ULL
+#define GIC_BASER_CACHE_RaWt   2ULL
+#define GIC_BASER_CACHE_RaWb   3ULL
+#define GIC_BASER_CACHE_WaWt   4ULL
+#define GIC_BASER_CACHE_WaWb   5ULL
+#define GIC_BASER_CACHE_RaWaWt 6ULL
+#define GIC_BASER_CACHE_RaWaWb 7ULL
+#define GIC_BASER_CACHE_MASK   7ULL
+#define GIC_BASER_NonShareable 0ULL
+#define GIC_BASER_InnerShareable   1ULL
+#define GIC_BASER_OuterShareable   2ULL
+#define GIC_BASER_SHAREABILITY_MASK3ULL
+
+#define GIC_BASER_CACHEABILITY(reg, inner_outer, type) \
+   (GIC_BASER_CACHE_##type << reg##_##inner_outer##_CACHEABILITY_SHIFT)
+
+#define GIC_BASER_SHAREABILITY(reg, type)  \
+   (GIC_BASER_##type << reg##_SHAREABILITY_SHIFT)
+
+#define GICR_PROPBASER_SHAREABILITY_SHIFT  (10)
+#define GICR_PROPBASER_INNER_CACHEABILITY_SHIFT(7)
+#define GICR_PROPBASER_OUTER_CACHEABILITY_SHIFT(56)
+#define GICR_PROPBASER_SHAREABILITY_MASK   \
+   GIC_BASER_SHAREABILITY(GICR_PROPBASER, SHAREABILITY_MASK)
+#define GICR_PROPBASER_INNER_CACHEABILITY_MASK \
+   GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, MASK)
+#define GICR_PROPBASER_OUTER_CACHEABILITY_MASK \
+   GIC_BASER_CACHEABILITY(GICR_PROPBASER, OUTER, MASK)
+#define GICR_PROPBASER_CACHEABILITY_MASK GICR_PROPBASER_INNER_CACHEABILITY_MASK
+
+#define GICR_PROPBASER_InnerShareable  \
+   GIC_BASER_SHAREABILITY(GICR_PROPBASER, InnerShareable)
+#define GICR_PROPBASER_nC GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, nC)
+#define GICR_PROPBASER_WaWb GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, WaWb)
+#define GICR_PROPBASER_IDBITS_MASK (0x1f)
+
+#define GICR_PENDBASER_SHAREABILITY_SHIFT  (10)
+#define GICR_PENDBASER_INNER_CACHEABILITY_SHIFT(7)
+#define GICR_PENDBASER_OUTER_CACHEABILITY_SHIFT(56)
+#define GICR_PENDBASER_SHAREABILITY_MASK   \
+   GIC_BASER_SHAREABILITY(GICR_PENDBASER, SHAREABILITY_MASK)
+#define GICR_PENDBASER_INNER_CACHEABILITY_MASK \
+   GIC_BASER_CACHEABILITY(GICR_PENDBASER, INNER, MASK)
+#define GICR_PENDBASER_OUTER_CACHEABILITY_MASK \
+   

[PATCH 31/55] KVM: arm/arm64: vgic: Add refcounting for IRQs

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

In the moment our struct vgic_irq's are statically allocated at guest
creation time. So getting a pointer to an IRQ structure is trivial and
safe. LPIs are more dynamic, they can be mapped and unmapped at any time
during the guest's _runtime_.
In preparation for supporting LPIs we introduce reference counting for
those structures using the kernel's kref infrastructure.
Since private IRQs and SPIs are statically allocated, we avoid actually
refcounting them, since they would never be released anyway.
But we take provisions to increase the refcount when an IRQ gets onto a
VCPU list and decrease it when it gets removed. Also this introduces
vgic_put_irq(), which wraps kref_put and hides the release function from
the callers.

Signed-off-by: Andre Przywara 
Reviewed-by: Marc Zyngier 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 include/kvm/arm_vgic.h   |  1 +
 virt/kvm/arm/vgic/vgic-init.c|  2 ++
 virt/kvm/arm/vgic/vgic-mmio-v2.c |  8 +++
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 20 ++--
 virt/kvm/arm/vgic/vgic-mmio.c| 25 ++-
 virt/kvm/arm/vgic/vgic-v2.c  |  1 +
 virt/kvm/arm/vgic/vgic-v3.c  |  1 +
 virt/kvm/arm/vgic/vgic.c | 52 
 virt/kvm/arm/vgic/vgic.h |  1 +
 9 files changed, 99 insertions(+), 12 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 5142e2a..450b4da 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -96,6 +96,7 @@ struct vgic_irq {
bool active;/* not used for LPIs */
bool enabled;
bool hw;/* Tied to HW IRQ */
+   struct kref refcount;   /* Used for LPIs */
u32 hwintid;/* HW INTID number */
union {
u8 targets; /* GICv2 target VCPUs mask */
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 90cae48..ac3c1a5 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -177,6 +177,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int 
nr_spis)
spin_lock_init(>irq_lock);
irq->vcpu = NULL;
irq->target_vcpu = vcpu0;
+   kref_init(>refcount);
if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
irq->targets = 0;
else
@@ -211,6 +212,7 @@ static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
irq->vcpu = NULL;
irq->target_vcpu = vcpu;
irq->targets = 1U << vcpu->vcpu_id;
+   kref_init(>refcount);
if (vgic_irq_is_sgi(i)) {
/* SGIs */
irq->enabled = 1;
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index a213936..4152348 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -102,6 +102,7 @@ static void vgic_mmio_write_sgir(struct kvm_vcpu 
*source_vcpu,
irq->source |= 1U << source_vcpu->vcpu_id;
 
vgic_queue_irq_unlock(source_vcpu->kvm, irq);
+   vgic_put_irq(source_vcpu->kvm, irq);
}
 }
 
@@ -116,6 +117,8 @@ static unsigned long vgic_mmio_read_target(struct kvm_vcpu 
*vcpu,
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
val |= (u64)irq->targets << (i * 8);
+
+   vgic_put_irq(vcpu->kvm, irq);
}
 
return val;
@@ -143,6 +146,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target);
 
spin_unlock(>irq_lock);
+   vgic_put_irq(vcpu->kvm, irq);
}
 }
 
@@ -157,6 +161,8 @@ static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu 
*vcpu,
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
val |= (u64)irq->source << (i * 8);
+
+   vgic_put_irq(vcpu->kvm, irq);
}
return val;
 }
@@ -178,6 +184,7 @@ static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu,
irq->pending = false;
 
spin_unlock(>irq_lock);
+   vgic_put_irq(vcpu->kvm, irq);
}
 }
 
@@ -201,6 +208,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
} else {
spin_unlock(>irq_lock);
}
+   vgic_put_irq(vcpu->kvm, irq);
}
 }
 
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index fc7b6c9..bfcafbd 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -80,15 +80,17 @@ static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu 

[PATCH 13/55] arm64: KVM: Refactor kern_hyp_va to deal with multiple offsets

2016-07-22 Thread Marc Zyngier
As we move towards a selectable HYP VA range, it is obvious that
we don't want to test a variable to find out if we need to use
the bottom VA range, the top VA range, or use the address as is
(for VHE).

Instead, we can expand our current helper to generate the right
mask or nop with code patching. We default to using the top VA
space, with alternatives to switch to the bottom one or to nop
out the instructions.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm64/include/asm/kvm_hyp.h | 11 ---
 arch/arm64/include/asm/kvm_mmu.h | 42 +---
 2 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
index 1d81f9a..cff5105 100644
--- a/arch/arm64/include/asm/kvm_hyp.h
+++ b/arch/arm64/include/asm/kvm_hyp.h
@@ -25,17 +25,6 @@
 
 #define __hyp_text __section(.hyp.text) notrace
 
-static inline unsigned long __kern_hyp_va(unsigned long v)
-{
-   asm volatile(ALTERNATIVE("and %0, %0, %1",
-"nop",
-ARM64_HAS_VIRT_HOST_EXTN)
-: "+r" (v) : "i" (HYP_PAGE_OFFSET_MASK));
-   return v;
-}
-
-#define kern_hyp_va(v) (typeof(v))(__kern_hyp_va((unsigned long)(v)))
-
 #define read_sysreg_elx(r,nvh,vh)  \
({  \
u64 reg;\
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 5e54323..2970537 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -90,13 +90,33 @@
 /*
  * Convert a kernel VA into a HYP VA.
  * reg: VA to be converted.
+ *
+ * This generates the following sequences:
+ * - High mask:
+ * and x0, x0, #HYP_PAGE_OFFSET_HIGH_MASK
+ * nop
+ * - Low mask:
+ * and x0, x0, #HYP_PAGE_OFFSET_HIGH_MASK
+ * and x0, x0, #HYP_PAGE_OFFSET_LOW_MASK
+ * - VHE:
+ * nop
+ * nop
+ *
+ * The "low mask" version works because the mask is a strict subset of
+ * the "high mask", hence performing the first mask for nothing.
+ * Should be completely invisible on any viable CPU.
  */
 .macro kern_hyp_va reg
-alternative_if_not ARM64_HAS_VIRT_HOST_EXTN
-   and \reg, \reg, #HYP_PAGE_OFFSET_MASK
+alternative_if_not ARM64_HAS_VIRT_HOST_EXTN
+   and \reg, \reg, #HYP_PAGE_OFFSET_HIGH_MASK
 alternative_else
nop
 alternative_endif
+alternative_if_not ARM64_HYP_OFFSET_LOW
+   nop
+alternative_else
+   and \reg, \reg, #HYP_PAGE_OFFSET_LOW_MASK
+alternative_endif
 .endm
 
 #else
@@ -107,7 +127,23 @@ alternative_endif
 #include 
 #include 
 
-#define KERN_TO_HYP(kva)   ((unsigned long)kva & HYP_PAGE_OFFSET_MASK)
+static inline unsigned long __kern_hyp_va(unsigned long v)
+{
+   asm volatile(ALTERNATIVE("and %0, %0, %1",
+"nop",
+ARM64_HAS_VIRT_HOST_EXTN)
+: "+r" (v)
+: "i" (HYP_PAGE_OFFSET_HIGH_MASK));
+   asm volatile(ALTERNATIVE("nop",
+"and %0, %0, %1",
+ARM64_HYP_OFFSET_LOW)
+: "+r" (v)
+: "i" (HYP_PAGE_OFFSET_LOW_MASK));
+   return v;
+}
+
+#define kern_hyp_va(v) (typeof(v))(__kern_hyp_va((unsigned long)(v)))
+#define KERN_TO_HYP(v) kern_hyp_va(v)
 
 /*
  * We currently only support a 40bit IPA.
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 08/55] arm64: KVM: Always reference __hyp_panic_string via its kernel VA

2016-07-22 Thread Marc Zyngier
__hyp_panic_string is passed via the HYP panic code to the panic
function, and is being "upgraded" to a kernel address, as it is
referenced by the HYP code (in a PC-relative way).

This is a bit silly, and we'd be better off obtaining the kernel
address and not mess with it at all. This patch implements this
with a tiny bit of asm glue, by forcing the string pointer to be
read from the literal pool.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm64/kvm/hyp/switch.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 437cfad..81f21a2 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -299,9 +299,16 @@ static const char __hyp_panic_string[] = "HYP 
panic:\nPS:%08llx PC:%016llx ESR:%
 
 static void __hyp_text __hyp_call_panic_nvhe(u64 spsr, u64 elr, u64 par)
 {
-   unsigned long str_va = (unsigned long)__hyp_panic_string;
+   unsigned long str_va;
 
-   __hyp_do_panic(hyp_kern_va(str_va),
+   /*
+* Force the panic string to be loaded from the literal pool,
+* making sure it is a kernel address and not a PC-relative
+* reference.
+*/
+   asm volatile("ldr %0, =__hyp_panic_string" : "=r" (str_va));
+
+   __hyp_do_panic(str_va,
   spsr,  elr,
   read_sysreg(esr_el2),   read_sysreg_el2(far),
   read_sysreg(hpfar_el2), par,
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 19/55] arm/arm64: KVM: Kill free_boot_hyp_pgd

2016-07-22 Thread Marc Zyngier
There is no way to free the boot PGD, because it doesn't exist
anymore as a standalone entity.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm/include/asm/kvm_mmu.h   |  1 -
 arch/arm/kvm/arm.c   |  4 
 arch/arm/kvm/mmu.c   | 30 +++---
 arch/arm64/include/asm/kvm_mmu.h |  1 -
 4 files changed, 7 insertions(+), 29 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 5d161d1..d5fd9fb 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -51,7 +51,6 @@
 
 int create_hyp_mappings(void *from, void *to, pgprot_t prot);
 int create_hyp_io_mappings(void *from, void *to, phys_addr_t);
-void free_boot_hyp_pgd(void);
 void free_hyp_pgds(void);
 
 void stage2_unmap_vm(struct kvm *kvm);
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 0887cc1..9b8c537 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -1323,10 +1323,6 @@ static int init_hyp_mode(void)
}
}
 
-#ifndef CONFIG_HOTPLUG_CPU
-   free_boot_hyp_pgd();
-#endif
-
/* set size of VMID supported by CPU */
kvm_vmid_bits = kvm_get_vmid_bits();
kvm_info("%d-bit VMID\n", kvm_vmid_bits);
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index dd4ccc7..0b36dd52 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -482,27 +482,6 @@ static void unmap_hyp_range(pgd_t *pgdp, phys_addr_t 
start, u64 size)
 }
 
 /**
- * free_boot_hyp_pgd - free HYP boot page tables
- *
- * Free the HYP boot page tables. The bounce page is also freed.
- */
-void free_boot_hyp_pgd(void)
-{
-   mutex_lock(_hyp_pgd_mutex);
-
-   if (boot_hyp_pgd) {
-   unmap_hyp_range(boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
-   free_pages((unsigned long)boot_hyp_pgd, hyp_pgd_order);
-   boot_hyp_pgd = NULL;
-   }
-
-   if (hyp_pgd)
-   unmap_hyp_range(hyp_pgd, hyp_idmap_start, PAGE_SIZE);
-
-   mutex_unlock(_hyp_pgd_mutex);
-}
-
-/**
  * free_hyp_pgds - free Hyp-mode page tables
  *
  * Assumes hyp_pgd is a page table used strictly in Hyp-mode and
@@ -516,11 +495,16 @@ void free_hyp_pgds(void)
 {
unsigned long addr;
 
-   free_boot_hyp_pgd();
-
mutex_lock(_hyp_pgd_mutex);
 
+   if (boot_hyp_pgd) {
+   unmap_hyp_range(boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
+   free_pages((unsigned long)boot_hyp_pgd, hyp_pgd_order);
+   boot_hyp_pgd = NULL;
+   }
+
if (hyp_pgd) {
+   unmap_hyp_range(hyp_pgd, hyp_idmap_start, PAGE_SIZE);
for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += 
PGDIR_SIZE)
unmap_hyp_range(hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr 
+= PGDIR_SIZE)
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 390acab..b89122e 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -156,7 +156,6 @@ static inline unsigned long __kern_hyp_va(unsigned long v)
 
 int create_hyp_mappings(void *from, void *to, pgprot_t prot);
 int create_hyp_io_mappings(void *from, void *to, phys_addr_t);
-void free_boot_hyp_pgd(void);
 void free_hyp_pgds(void);
 
 void stage2_unmap_vm(struct kvm *kvm);
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 26/55] KVM: arm/arm64: vgic: Move redistributor kvm_io_devices

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

Logically a GICv3 redistributor is assigned to a (v)CPU, so we should
aim to keep redistributor related variables out of our struct vgic_dist.

Let's start by replacing the redistributor related kvm_io_device array
with two members in our existing struct vgic_cpu, which are naturally
per-VCPU and thus don't require any allocation / freeing.
So apart from the better fit with the redistributor design this saves
some code as well.

Signed-off-by: Andre Przywara 
Reviewed-by: Eric Auger 
Reviewed-by: Marc Zyngier 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 include/kvm/arm_vgic.h   |  8 +++-
 virt/kvm/arm/vgic/vgic-init.c|  1 -
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 22 --
 3 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 1264037..5142e2a 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -145,7 +145,6 @@ struct vgic_dist {
struct vgic_irq *spis;
 
struct vgic_io_device   dist_iodev;
-   struct vgic_io_device   *redist_iodevs;
 };
 
 struct vgic_v2_cpu_if {
@@ -193,6 +192,13 @@ struct vgic_cpu {
struct list_head ap_list_head;
 
u64 live_lrs;
+
+   /*
+* Members below are used with GICv3 emulation only and represent
+* parts of the redistributor.
+*/
+   struct vgic_io_device   rd_iodev;
+   struct vgic_io_device   sgi_iodev;
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index a1442f7..90cae48 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -271,7 +271,6 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
dist->initialized = false;
 
kfree(dist->spis);
-   kfree(dist->redist_iodevs);
dist->nr_spis = 0;
 
mutex_unlock(>lock);
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index a0c515a..fc7b6c9 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -285,21 +285,14 @@ unsigned int vgic_v3_init_dist_iodev(struct 
vgic_io_device *dev)
 
 int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
 {
-   int nr_vcpus = atomic_read(>online_vcpus);
struct kvm_vcpu *vcpu;
-   struct vgic_io_device *devices;
int c, ret = 0;
 
-   devices = kmalloc(sizeof(struct vgic_io_device) * nr_vcpus * 2,
- GFP_KERNEL);
-   if (!devices)
-   return -ENOMEM;
-
kvm_for_each_vcpu(c, vcpu, kvm) {
gpa_t rd_base = redist_base_address + c * SZ_64K * 2;
gpa_t sgi_base = rd_base + SZ_64K;
-   struct vgic_io_device *rd_dev = [c * 2];
-   struct vgic_io_device *sgi_dev = [c * 2 + 1];
+   struct vgic_io_device *rd_dev = >arch.vgic_cpu.rd_iodev;
+   struct vgic_io_device *sgi_dev = >arch.vgic_cpu.sgi_iodev;
 
kvm_iodevice_init(_dev->dev, _io_gic_ops);
rd_dev->base_addr = rd_base;
@@ -335,14 +328,15 @@ int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t 
redist_base_address)
if (ret) {
/* The current c failed, so we start with the previous one. */
for (c--; c >= 0; c--) {
+   struct vgic_cpu *vgic_cpu;
+
+   vcpu = kvm_get_vcpu(kvm, c);
+   vgic_cpu = >arch.vgic_cpu;
kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
- [c * 2].dev);
+ _cpu->rd_iodev.dev);
kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
- [c * 2 + 1].dev);
+ _cpu->sgi_iodev.dev);
}
-   kfree(devices);
-   } else {
-   kvm->arch.vgic.redist_iodevs = devices;
}
 
return ret;
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 25/55] arm64: KVM: Clean up a condition

2016-07-22 Thread Marc Zyngier
From: Dan Carpenter 

My static checker complains that this condition looks like it should be
== instead of =.  This isn't a fast path, so we don't need to be fancy.

Signed-off-by: Dan Carpenter 
Signed-off-by: Marc Zyngier 
---
 arch/arm64/kvm/sys_regs.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index a57d650..b0b225c 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1546,7 +1546,7 @@ static void unhandled_cp_access(struct kvm_vcpu *vcpu,
struct sys_reg_params *params)
 {
u8 hsr_ec = kvm_vcpu_trap_get_class(vcpu);
-   int cp;
+   int cp = -1;
 
switch(hsr_ec) {
case ESR_ELx_EC_CP15_32:
@@ -1558,7 +1558,7 @@ static void unhandled_cp_access(struct kvm_vcpu *vcpu,
cp = 14;
break;
default:
-   WARN_ON((cp = -1));
+   WARN_ON(1);
}
 
kvm_err("Unsupported guest CP%d access at: %08lx\n",
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 29/55] KVM: arm/arm64: Extend arch CAP checks to allow per-VM capabilities

2016-07-22 Thread Marc Zyngier
From: Andre Przywara 

KVM capabilities can be a per-VM property, though ARM/ARM64 currently
does not pass on the VM pointer to the architecture specific
capability handlers.
Add a "struct kvm*" parameter to those function to later allow proper
per-VM capability reporting.

Signed-off-by: Andre Przywara 
Reviewed-by: Eric Auger 
Reviewed-by: Marc Zyngier 
Acked-by: Christoffer Dall 
Tested-by: Eric Auger 
Signed-off-by: Marc Zyngier 
---
 arch/arm/include/asm/kvm_host.h   | 2 +-
 arch/arm/kvm/arm.c| 2 +-
 arch/arm64/include/asm/kvm_host.h | 2 +-
 arch/arm64/kvm/reset.c| 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 58d0b69..de338d9 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -272,7 +272,7 @@ static inline void __cpu_reset_hyp_mode(unsigned long 
vector_ptr,
kvm_call_hyp((void *)virt_to_idmap(__kvm_hyp_reset), vector_ptr);
 }
 
-static inline int kvm_arch_dev_ioctl_check_extension(long ext)
+static inline int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext)
 {
return 0;
 }
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 7cf266c..972075c 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -201,7 +201,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
r = KVM_MAX_VCPUS;
break;
default:
-   r = kvm_arch_dev_ioctl_check_extension(ext);
+   r = kvm_arch_dev_ioctl_check_extension(kvm, ext);
break;
}
return r;
diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index 69d5cc2d..3eda975 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -47,7 +47,7 @@
 
 int __attribute_const__ kvm_target_cpu(void);
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
-int kvm_arch_dev_ioctl_check_extension(long ext);
+int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext);
 void __extended_idmap_trampoline(phys_addr_t boot_pgd, phys_addr_t 
idmap_start);
 
 struct kvm_arch {
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index 79f3248..e95d4f6 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -65,7 +65,7 @@ static bool cpu_has_32bit_el1(void)
  * We currently assume that the number of HW registers is uniform
  * across all CPUs (see cpuinfo_sanity_check).
  */
-int kvm_arch_dev_ioctl_check_extension(long ext)
+int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext)
 {
int r;
 
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 24/55] arm/arm64: Get rid of KERN_TO_HYP

2016-07-22 Thread Marc Zyngier
We have both KERN_TO_HYP and kern_hyp_va, which do the exact same
thing. Let's standardize on the latter.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm/include/asm/kvm_hyp.h   |  2 --
 arch/arm/include/asm/kvm_mmu.h   |  2 +-
 arch/arm/kvm/mmu.c   | 18 +-
 arch/arm64/include/asm/kvm_mmu.h |  1 -
 4 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/arch/arm/include/asm/kvm_hyp.h b/arch/arm/include/asm/kvm_hyp.h
index e38fce2..6eaff28 100644
--- a/arch/arm/include/asm/kvm_hyp.h
+++ b/arch/arm/include/asm/kvm_hyp.h
@@ -25,8 +25,6 @@
 
 #define __hyp_text __section(.hyp.text) notrace
 
-#define kern_hyp_va(v) (v)
-
 #define __ACCESS_CP15(CRn, Op1, CRm, Op2)  \
"mrc", "mcr", __stringify(p15, Op1, %0, CRn, CRm, Op2), u32
 #define __ACCESS_CP15_64(Op1, CRm) \
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 73c2818..3bb803d 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -26,7 +26,7 @@
  * We directly use the kernel VA for the HYP, as we can directly share
  * the mapping (HTTBR "covers" TTBR1).
  */
-#define KERN_TO_HYP(kva)   (kva)
+#define kern_hyp_va(kva)   (kva)
 
 /*
  * KVM_MMU_CACHE_MIN_PAGES is the number of stage2 page table translation 
levels.
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 8a0aa37..bda27b6 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -506,9 +506,9 @@ void free_hyp_pgds(void)
if (hyp_pgd) {
unmap_hyp_range(hyp_pgd, hyp_idmap_start, PAGE_SIZE);
for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += 
PGDIR_SIZE)
-   unmap_hyp_range(hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
+   unmap_hyp_range(hyp_pgd, kern_hyp_va(addr), PGDIR_SIZE);
for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr 
+= PGDIR_SIZE)
-   unmap_hyp_range(hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
+   unmap_hyp_range(hyp_pgd, kern_hyp_va(addr), PGDIR_SIZE);
 
free_pages((unsigned long)hyp_pgd, hyp_pgd_order);
hyp_pgd = NULL;
@@ -670,8 +670,8 @@ int create_hyp_mappings(void *from, void *to, pgprot_t prot)
 {
phys_addr_t phys_addr;
unsigned long virt_addr;
-   unsigned long start = KERN_TO_HYP((unsigned long)from);
-   unsigned long end = KERN_TO_HYP((unsigned long)to);
+   unsigned long start = kern_hyp_va((unsigned long)from);
+   unsigned long end = kern_hyp_va((unsigned long)to);
 
if (is_kernel_in_hyp_mode())
return 0;
@@ -705,8 +705,8 @@ int create_hyp_mappings(void *from, void *to, pgprot_t prot)
  */
 int create_hyp_io_mappings(void *from, void *to, phys_addr_t phys_addr)
 {
-   unsigned long start = KERN_TO_HYP((unsigned long)from);
-   unsigned long end = KERN_TO_HYP((unsigned long)to);
+   unsigned long start = kern_hyp_va((unsigned long)from);
+   unsigned long end = kern_hyp_va((unsigned long)to);
 
if (is_kernel_in_hyp_mode())
return 0;
@@ -1711,10 +1711,10 @@ int kvm_mmu_init(void)
 
kvm_info("IDMAP page: %lx\n", hyp_idmap_start);
kvm_info("HYP VA range: %lx:%lx\n",
-KERN_TO_HYP(PAGE_OFFSET), KERN_TO_HYP(~0UL));
+kern_hyp_va(PAGE_OFFSET), kern_hyp_va(~0UL));
 
-   if (hyp_idmap_start >= KERN_TO_HYP(PAGE_OFFSET) &&
-   hyp_idmap_start <  KERN_TO_HYP(~0UL)) {
+   if (hyp_idmap_start >= kern_hyp_va(PAGE_OFFSET) &&
+   hyp_idmap_start <  kern_hyp_va(~0UL)) {
/*
 * The idmap page is intersecting with the VA space,
 * it is not safe to continue further.
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 9226f8b..b6bb834 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -133,7 +133,6 @@ static inline unsigned long __kern_hyp_va(unsigned long v)
 }
 
 #define kern_hyp_va(v) (typeof(v))(__kern_hyp_va((unsigned long)(v)))
-#define KERN_TO_HYP(v) kern_hyp_va(v)
 
 /*
  * We currently only support a 40bit IPA.
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 22/55] arm/arm64: KVM: Prune unused #defines

2016-07-22 Thread Marc Zyngier
We can now remove a number of dead #defines, thanks to the trampoline
code being gone.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm/include/asm/kvm_mmu.h   |  9 -
 arch/arm64/include/asm/kvm_mmu.h | 10 --
 2 files changed, 19 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index d5fd9fb..73c2818 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -26,18 +26,9 @@
  * We directly use the kernel VA for the HYP, as we can directly share
  * the mapping (HTTBR "covers" TTBR1).
  */
-#define HYP_PAGE_OFFSET_MASK   UL(~0)
-#define HYP_PAGE_OFFSETPAGE_OFFSET
 #define KERN_TO_HYP(kva)   (kva)
 
 /*
- * Our virtual mapping for the boot-time MMU-enable code. Must be
- * shared across all the page-tables. Conveniently, we use the vectors
- * page, where no kernel data will ever be shared with HYP.
- */
-#define TRAMPOLINE_VA  UL(CONFIG_VECTORS_BASE)
-
-/*
  * KVM_MMU_CACHE_MIN_PAGES is the number of stage2 page table translation 
levels.
  */
 #define KVM_MMU_CACHE_MIN_PAGES2
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index b89122e..9226f8b 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -72,16 +72,6 @@
 #define HYP_PAGE_OFFSET_HIGH_MASK  ((UL(1) << VA_BITS) - 1)
 #define HYP_PAGE_OFFSET_LOW_MASK   ((UL(1) << (VA_BITS - 1)) - 1)
 
-/* Temporary compat define */
-#define HYP_PAGE_OFFSET_MASK   HYP_PAGE_OFFSET_HIGH_MASK
-
-/*
- * Our virtual mapping for the idmap-ed MMU-enable code. Must be
- * shared across all the page-tables. Conveniently, we use the last
- * possible page, where no kernel mapping will ever exist.
- */
-#define TRAMPOLINE_VA  (HYP_PAGE_OFFSET_MASK & PAGE_MASK)
-
 #ifdef __ASSEMBLY__
 
 #include 
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 21/55] arm: KVM: Allow hyp teardown

2016-07-22 Thread Marc Zyngier
So far, KVM was getting in the way of kexec on 32bit (and the arm64
kexec hackers couldn't be bothered to fix it on 32bit...).

With simpler page tables, tearing KVM down becomes very easy, so
let's just do it.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm/include/asm/kvm_asm.h|  2 ++
 arch/arm/include/asm/kvm_host.h   |  8 +++-
 arch/arm/kvm/arm.c|  3 ++-
 arch/arm/kvm/init.S   | 15 +++
 arch/arm64/include/asm/kvm_host.h |  3 ++-
 5 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
index 3d5a5cd..58faff5 100644
--- a/arch/arm/include/asm/kvm_asm.h
+++ b/arch/arm/include/asm/kvm_asm.h
@@ -66,6 +66,8 @@ extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
 extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
 
 extern void __init_stage2_translation(void);
+
+extern void __kvm_hyp_reset(unsigned long);
 #endif
 
 #endif /* __ARM_KVM_ASM_H__ */
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index eafbfd5..58d0b69 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -266,12 +266,10 @@ static inline void __cpu_init_stage2(void)
kvm_call_hyp(__init_stage2_translation);
 }
 
-static inline void __cpu_reset_hyp_mode(phys_addr_t phys_idmap_start)
+static inline void __cpu_reset_hyp_mode(unsigned long vector_ptr,
+   phys_addr_t phys_idmap_start)
 {
-   /*
-* TODO
-* kvm_call_reset(phys_idmap_start);
-*/
+   kvm_call_hyp((void *)virt_to_idmap(__kvm_hyp_reset), vector_ptr);
 }
 
 static inline int kvm_arch_dev_ioctl_check_extension(long ext)
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 9b8c537..7cf266c 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -1074,7 +1074,8 @@ static void cpu_hyp_reinit(void)
 static void cpu_hyp_reset(void)
 {
if (!is_kernel_in_hyp_mode())
-   __cpu_reset_hyp_mode(kvm_get_idmap_start());
+   __cpu_reset_hyp_mode(hyp_default_vectors,
+kvm_get_idmap_start());
 }
 
 static void _kvm_arch_hardware_enable(void *discard)
diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S
index b82a99d..bf89c91 100644
--- a/arch/arm/kvm/init.S
+++ b/arch/arm/kvm/init.S
@@ -112,6 +112,21 @@ __do_hyp_init:
 
eret
 
+   @ r0 : stub vectors address
+ENTRY(__kvm_hyp_reset)
+   /* We're now in idmap, disable MMU */
+   mrc p15, 4, r1, c1, c0, 0   @ HSCTLR
+   ldr r2, =(HSCTLR_M | HSCTLR_A | HSCTLR_C | HSCTLR_I)
+   bic r1, r1, r2
+   mcr p15, 4, r1, c1, c0, 0   @ HSCTLR
+
+   /* Install stub vectors */
+   mcr p15, 4, r0, c12, c0, 0  @ HVBAR
+   isb
+
+   eret
+ENDPROC(__kvm_hyp_reset)
+
.ltorg
 
.globl __kvm_hyp_init_end
diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index 6731d4e..69d5cc2d 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -359,7 +359,8 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
 }
 
 void __kvm_hyp_teardown(void);
-static inline void __cpu_reset_hyp_mode(phys_addr_t phys_idmap_start)
+static inline void __cpu_reset_hyp_mode(unsigned long vector_ptr,
+   phys_addr_t phys_idmap_start)
 {
kvm_call_hyp(__kvm_hyp_teardown, phys_idmap_start);
 }
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 16/55] arm/arm64: KVM: Always have merged page tables

2016-07-22 Thread Marc Zyngier
We're in a position where we can now always have "merged" page
tables, where both the runtime mapping and the idmap coexist.

This results in some code being removed, but there is more to come.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm/kvm/mmu.c | 74 +++---
 arch/arm64/kvm/reset.c | 31 +
 2 files changed, 41 insertions(+), 64 deletions(-)

diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index f004e70..80d3737 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -492,13 +492,12 @@ void free_boot_hyp_pgd(void)
 
if (boot_hyp_pgd) {
unmap_hyp_range(boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
-   unmap_hyp_range(boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
free_pages((unsigned long)boot_hyp_pgd, hyp_pgd_order);
boot_hyp_pgd = NULL;
}
 
if (hyp_pgd)
-   unmap_hyp_range(hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
+   unmap_hyp_range(hyp_pgd, hyp_idmap_start, PAGE_SIZE);
 
mutex_unlock(_hyp_pgd_mutex);
 }
@@ -1691,7 +1690,7 @@ phys_addr_t kvm_mmu_get_boot_httbr(void)
if (__kvm_cpu_uses_extended_idmap())
return virt_to_phys(merged_hyp_pgd);
else
-   return virt_to_phys(boot_hyp_pgd);
+   return virt_to_phys(hyp_pgd);
 }
 
 phys_addr_t kvm_get_idmap_vector(void)
@@ -1704,6 +1703,22 @@ phys_addr_t kvm_get_idmap_start(void)
return hyp_idmap_start;
 }
 
+static int kvm_map_idmap_text(pgd_t *pgd)
+{
+   int err;
+
+   /* Create the idmap in the boot page tables */
+   err =   __create_hyp_mappings(pgd,
+ hyp_idmap_start, hyp_idmap_end,
+ __phys_to_pfn(hyp_idmap_start),
+ PAGE_HYP_EXEC);
+   if (err)
+   kvm_err("Failed to idmap %lx-%lx\n",
+   hyp_idmap_start, hyp_idmap_end);
+
+   return err;
+}
+
 int kvm_mmu_init(void)
 {
int err;
@@ -1719,27 +1734,25 @@ int kvm_mmu_init(void)
BUG_ON((hyp_idmap_start ^ (hyp_idmap_end - 1)) & PAGE_MASK);
 
hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 
hyp_pgd_order);
-   boot_hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 
hyp_pgd_order);
-
-   if (!hyp_pgd || !boot_hyp_pgd) {
+   if (!hyp_pgd) {
kvm_err("Hyp mode PGD not allocated\n");
err = -ENOMEM;
goto out;
}
 
-   /* Create the idmap in the boot page tables */
-   err =   __create_hyp_mappings(boot_hyp_pgd,
- hyp_idmap_start, hyp_idmap_end,
- __phys_to_pfn(hyp_idmap_start),
- PAGE_HYP_EXEC);
+   if (__kvm_cpu_uses_extended_idmap()) {
+   boot_hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | 
__GFP_ZERO,
+hyp_pgd_order);
+   if (!boot_hyp_pgd) {
+   kvm_err("Hyp boot PGD not allocated\n");
+   err = -ENOMEM;
+   goto out;
+   }
 
-   if (err) {
-   kvm_err("Failed to idmap %lx-%lx\n",
-   hyp_idmap_start, hyp_idmap_end);
-   goto out;
-   }
+   err = kvm_map_idmap_text(boot_hyp_pgd);
+   if (err)
+   goto out;
 
-   if (__kvm_cpu_uses_extended_idmap()) {
merged_hyp_pgd = (pgd_t *)__get_free_page(GFP_KERNEL | 
__GFP_ZERO);
if (!merged_hyp_pgd) {
kvm_err("Failed to allocate extra HYP pgd\n");
@@ -1747,29 +1760,10 @@ int kvm_mmu_init(void)
}
__kvm_extend_hypmap(boot_hyp_pgd, hyp_pgd, merged_hyp_pgd,
hyp_idmap_start);
-   return 0;
-   }
-
-   /* Map the very same page at the trampoline VA */
-   err =   __create_hyp_mappings(boot_hyp_pgd,
- TRAMPOLINE_VA, TRAMPOLINE_VA + PAGE_SIZE,
- __phys_to_pfn(hyp_idmap_start),
- PAGE_HYP_EXEC);
-   if (err) {
-   kvm_err("Failed to map trampoline @%lx into boot HYP pgd\n",
-   TRAMPOLINE_VA);
-   goto out;
-   }
-
-   /* Map the same page again into the runtime page tables */
-   err =   __create_hyp_mappings(hyp_pgd,
- TRAMPOLINE_VA, TRAMPOLINE_VA + PAGE_SIZE,
- __phys_to_pfn(hyp_idmap_start),
- PAGE_HYP_EXEC);
-   if (err) {
-   kvm_err("Failed to map trampoline @%lx into runtime HYP pgd\n",

[PATCH 07/55] arm64: KVM: Merged page tables documentation

2016-07-22 Thread Marc Zyngier
Since dealing with VA ranges tends to hurt my brain badly, let's
start with a bit of documentation that will hopefully help
understanding what comes next...

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm64/include/asm/kvm_mmu.h | 40 +---
 1 file changed, 37 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index fdfbddb..6149dfc 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -29,10 +29,44 @@
  *
  * Instead, give the HYP mode its own VA region at a fixed offset from
  * the kernel by just masking the top bits (which are all ones for a
- * kernel address).
+ * kernel address). We need to find out how many bits to mask.
  *
- * ARMv8.1 (using VHE) does have a TTBR1_EL2, and doesn't use these
- * macros (the entire kernel runs at EL2).
+ * We want to build a set of page tables that cover both parts of the
+ * idmap (the trampoline page used to initialize EL2), and our normal
+ * runtime VA space, at the same time.
+ *
+ * Given that the kernel uses VA_BITS for its entire address space,
+ * and that half of that space (VA_BITS - 1) is used for the linear
+ * mapping, we can also limit the EL2 space to (VA_BITS - 1).
+ *
+ * The main question is "Within the VA_BITS space, does EL2 use the
+ * top or the bottom half of that space to shadow the kernel's linear
+ * mapping?". As we need to idmap the trampoline page, this is
+ * determined by the range in which this page lives.
+ *
+ * If the page is in the bottom half, we have to use the top half. If
+ * the page is in the top half, we have to use the bottom half:
+ *
+ * T = __virt_to_phys(__hyp_idmap_text_start)
+ * if (T & BIT(VA_BITS - 1))
+ * HYP_VA_MIN = 0  //idmap in upper half
+ * else
+ * HYP_VA_MIN = 1 << (VA_BITS - 1)
+ * HYP_VA_MAX = HYP_VA_MIN + (1 << (VA_BITS - 1)) - 1
+ *
+ * This of course assumes that the trampoline page exists within the
+ * VA_BITS range. If it doesn't, then it means we're in the odd case
+ * where the kernel idmap (as well as HYP) uses more levels than the
+ * kernel runtime page tables (as seen when the kernel is configured
+ * for 4k pages, 39bits VA, and yet memory lives just above that
+ * limit, forcing the idmap to use 4 levels of page tables while the
+ * kernel itself only uses 3). In this particular case, it doesn't
+ * matter which side of VA_BITS we use, as we're guaranteed not to
+ * conflict with anything.
+ *
+ * When using VHE, there are no separate hyp mappings and all KVM
+ * functionality is already mapped as part of the main kernel
+ * mappings, and none of this applies in that case.
  */
 #define HYP_PAGE_OFFSET_SHIFT  VA_BITS
 #define HYP_PAGE_OFFSET_MASK   ((UL(1) << HYP_PAGE_OFFSET_SHIFT) - 1)
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 09/55] arm/arm64: KVM: Remove hyp_kern_va helper

2016-07-22 Thread Marc Zyngier
hyp_kern_va is now completely unused, so let's remove it entirely.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm/include/asm/kvm_hyp.h   |  1 -
 arch/arm64/include/asm/kvm_hyp.h | 12 
 2 files changed, 13 deletions(-)

diff --git a/arch/arm/include/asm/kvm_hyp.h b/arch/arm/include/asm/kvm_hyp.h
index f0e8607..e38fce2 100644
--- a/arch/arm/include/asm/kvm_hyp.h
+++ b/arch/arm/include/asm/kvm_hyp.h
@@ -26,7 +26,6 @@
 #define __hyp_text __section(.hyp.text) notrace
 
 #define kern_hyp_va(v) (v)
-#define hyp_kern_va(v) (v)
 
 #define __ACCESS_CP15(CRn, Op1, CRm, Op2)  \
"mrc", "mcr", __stringify(p15, Op1, %0, CRn, CRm, Op2), u32
diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
index 44eaff7..1d81f9a 100644
--- a/arch/arm64/include/asm/kvm_hyp.h
+++ b/arch/arm64/include/asm/kvm_hyp.h
@@ -36,18 +36,6 @@ static inline unsigned long __kern_hyp_va(unsigned long v)
 
 #define kern_hyp_va(v) (typeof(v))(__kern_hyp_va((unsigned long)(v)))
 
-static inline unsigned long __hyp_kern_va(unsigned long v)
-{
-   u64 offset = PAGE_OFFSET - HYP_PAGE_OFFSET;
-   asm volatile(ALTERNATIVE("add %0, %0, %1",
-"nop",
-ARM64_HAS_VIRT_HOST_EXTN)
-: "+r" (v) : "r" (offset));
-   return v;
-}
-
-#define hyp_kern_va(v) (typeof(v))(__hyp_kern_va((unsigned long)(v)))
-
 #define read_sysreg_elx(r,nvh,vh)  \
({  \
u64 reg;\
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 03/55] arm/arm64: KVM: Enforce HYP read-only mapping of the kernel's rodata section

2016-07-22 Thread Marc Zyngier
In order to be able to use C code in HYP, we're now mapping the kernel's
rodata in HYP. It works absolutely fine, except that we're mapping it RWX,
which is not what it should be.

Add a new HYP_PAGE_RO protection, and pass it as the protection flags
when mapping the rodata section.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm/include/asm/pgtable.h| 1 +
 arch/arm/kvm/arm.c| 2 +-
 arch/arm64/include/asm/pgtable-prot.h | 1 +
 3 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 348caab..f332087 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -98,6 +98,7 @@ extern pgprot_t   pgprot_s2_device;
 #define PAGE_KERNEL_MOD_PROT(pgprot_kernel, L_PTE_XN)
 #define PAGE_KERNEL_EXEC   pgprot_kernel
 #define PAGE_HYP   _MOD_PROT(pgprot_kernel, L_PTE_HYP)
+#define PAGE_HYP_RO_MOD_PROT(pgprot_kernel, L_PTE_HYP | 
L_PTE_RDONLY | L_PTE_XN)
 #define PAGE_HYP_DEVICE_MOD_PROT(pgprot_hyp_device, L_PTE_HYP)
 #define PAGE_S2_MOD_PROT(pgprot_s2, L_PTE_S2_RDONLY)
 #define PAGE_S2_DEVICE _MOD_PROT(pgprot_s2_device, L_PTE_S2_RDONLY)
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 45dd6df..b308976 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -1300,7 +1300,7 @@ static int init_hyp_mode(void)
}
 
err = create_hyp_mappings(kvm_ksym_ref(__start_rodata),
- kvm_ksym_ref(__end_rodata), PAGE_HYP);
+ kvm_ksym_ref(__end_rodata), PAGE_HYP_RO);
if (err) {
kvm_err("Cannot map rodata section\n");
goto out_err;
diff --git a/arch/arm64/include/asm/pgtable-prot.h 
b/arch/arm64/include/asm/pgtable-prot.h
index 29fcb33..88db58c 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -56,6 +56,7 @@
 #define PAGE_KERNEL_EXEC_CONT  __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | 
PTE_WRITE | PTE_CONT)
 
 #define PAGE_HYP   __pgprot(_PAGE_DEFAULT | PTE_HYP)
+#define PAGE_HYP_RO__pgprot(_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY | 
PTE_HYP_XN)
 #define PAGE_HYP_DEVICE__pgprot(PROT_DEVICE_nGnRE | PTE_HYP)
 
 #define PAGE_S2__pgprot(PROT_DEFAULT | 
PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY)
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 05/55] arm/arm64: KVM: Make default HYP mappings non-excutable

2016-07-22 Thread Marc Zyngier
Structures that can be generally written to don't have any requirement
to be executable (quite the opposite). This includes the kvm and vcpu
structures, as well as the stacks.

Let's change the default to incorporate the XN flag.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm/include/asm/pgtable.h| 2 +-
 arch/arm64/include/asm/pgtable-prot.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 7487bf9..e0d76ba 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -97,7 +97,7 @@ extern pgprot_t   pgprot_s2_device;
 #define PAGE_READONLY_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | 
L_PTE_RDONLY)
 #define PAGE_KERNEL_MOD_PROT(pgprot_kernel, L_PTE_XN)
 #define PAGE_KERNEL_EXEC   pgprot_kernel
-#define PAGE_HYP   _MOD_PROT(pgprot_kernel, L_PTE_HYP)
+#define PAGE_HYP   _MOD_PROT(pgprot_kernel, L_PTE_HYP | L_PTE_XN)
 #define PAGE_HYP_EXEC  _MOD_PROT(pgprot_kernel, L_PTE_HYP | 
L_PTE_RDONLY)
 #define PAGE_HYP_RO_MOD_PROT(pgprot_kernel, L_PTE_HYP | 
L_PTE_RDONLY | L_PTE_XN)
 #define PAGE_HYP_DEVICE_MOD_PROT(pgprot_hyp_device, L_PTE_HYP)
diff --git a/arch/arm64/include/asm/pgtable-prot.h 
b/arch/arm64/include/asm/pgtable-prot.h
index 3802048..39f5252 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -55,7 +55,7 @@
 #define PAGE_KERNEL_EXEC   __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | 
PTE_WRITE)
 #define PAGE_KERNEL_EXEC_CONT  __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | 
PTE_WRITE | PTE_CONT)
 
-#define PAGE_HYP   __pgprot(_PAGE_DEFAULT | PTE_HYP)
+#define PAGE_HYP   __pgprot(_PAGE_DEFAULT | PTE_HYP | PTE_HYP_XN)
 #define PAGE_HYP_EXEC  __pgprot(_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY)
 #define PAGE_HYP_RO__pgprot(_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY | 
PTE_HYP_XN)
 #define PAGE_HYP_DEVICE__pgprot(PROT_DEVICE_nGnRE | PTE_HYP)
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PULL] KVM/ARM updates for Linux 4.8, take #1

2016-07-22 Thread Marc Zyngier
Paolo, Radim,

Please find below the first batch of 4.8 updates for KVM/ARM. Biggest
feature is the long awaited GICv3 ITS emulation, allowing MSIs to be
delivered into guests running on GICv3 HW. The other big feature is
the removal of the old vgic implementation. Less visible is the revamp
of the way we deal with the HYP initialization (by keeping an idmap
around), and making HYP page tables honor the kernel's own protection.

This may generate a few conflicts, all of which have been seen in
-next. 3 which are KVM specific (and pretty easy to resolve), and
another one in include/irqchip/arm-gic-v3.h. They should be resolved
as in -next.

Please pull!

M.

The following changes since commit 8ff7b956471faadb0f874a49e8603d43cb1e55d5:

  Merge tag 'kvm-s390-next-4.8-2' of 
git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD 
(2016-06-21 15:21:51 +0200)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git 
tags/kvm-arm-for-4.8

for you to fetch changes up to 3a88bded203591d4683aacdbb65cd0f549bc58cb:

  KVM: arm64: vgic-its: Simplify MAPI error handling (2016-07-18 18:15:20 +0100)


KVM/ARM changes for Linux 4.8

- GICv3 ITS emulation
- Simpler idmap management that fixes potential TLB conflicts
- Honor the kernel protection in HYP mode
- Removal of the old vgic implementation


Andre Przywara (17):
  KVM: arm/arm64: vgic: Move redistributor kvm_io_devices
  KVM: arm/arm64: vgic: Check return value for kvm_register_vgic_device
  KVM: Extend struct kvm_msi to hold a 32-bit device ID
  KVM: arm/arm64: Extend arch CAP checks to allow per-VM capabilities
  KVM: kvm_io_bus: Add kvm_io_bus_get_dev() call
  KVM: arm/arm64: vgic: Add refcounting for IRQs
  irqchip/gic-v3: Refactor and add GICv3 definitions
  KVM: arm64: vgic: Handle ITS related GICv3 redistributor registers
  KVM: arm64: vgic-its: Introduce ITS emulation file with MMIO framework
  KVM: arm64: vgic-its: Introduce new KVM ITS device
  KVM: arm64: vgic-its: Implement basic ITS register handlers
  KVM: arm64: vgic-its: Connect LPIs to the VGIC emulation
  KVM: arm64: vgic-its: Read initial LPI pending table
  KVM: arm64: vgic-its: Allow updates of LPI configuration table
  KVM: arm64: vgic-its: Implement ITS command queue command handlers
  KVM: arm64: vgic-its: Implement MSI injection in ITS emulation
  KVM: arm64: vgic-its: Enable ITS emulation as a virtual MSI controller

Dan Carpenter (1):
  arm64: KVM: Clean up a condition

Eric Auger (1):
  KVM: arm/arm64: Fix vGICv2 KVM_DEV_ARM_VGIC_GRP_CPU/DIST_REGS

Marc Zyngier (36):
  arm/arm64: KVM: Add a protection parameter to create_hyp_mappings
  arm64: Add PTE_HYP_XN page table flag
  arm/arm64: KVM: Enforce HYP read-only mapping of the kernel's rodata 
section
  arm/arm64: KVM: Map the HYP text as read-only
  arm/arm64: KVM: Make default HYP mappings non-excutable
  KVM: arm/arm64: The GIC is dead, long live the GIC
  arm64: KVM: Merged page tables documentation
  arm64: KVM: Always reference __hyp_panic_string via its kernel VA
  arm/arm64: KVM: Remove hyp_kern_va helper
  arm64: KVM: Kill HYP_PAGE_OFFSET
  arm64: Add ARM64_HYP_OFFSET_LOW capability
  arm64: KVM: Define HYP offset masks
  arm64: KVM: Refactor kern_hyp_va to deal with multiple offsets
  arm/arm64: KVM: Export __hyp_text_start/end symbols
  arm64: KVM: Runtime detection of lower HYP offset
  arm/arm64: KVM: Always have merged page tables
  arm64: KVM: Simplify HYP init/teardown
  arm/arm64: KVM: Drop boot_pgd
  arm/arm64: KVM: Kill free_boot_hyp_pgd
  arm: KVM: Simplify HYP init
  arm: KVM: Allow hyp teardown
  arm/arm64: KVM: Prune unused #defines
  arm/arm64: KVM: Check that IDMAP doesn't intersect with VA range
  arm/arm64: Get rid of KERN_TO_HYP
  irqchip/gicv3-its: Restore all cacheability attributes
  KVM: arm64: vgic-its: Generalize use of vgic_get_irq_kref
  KVM: arm64: vgic-its: Fix handling of indirect tables
  KVM: arm64: vgic-its: Fix vgic_its_check_device_id BE handling
  KVM: arm64: vgic-its: Fix misleading nr_entries in 
vgic_its_check_device_id
  KVM: arm64: vgic-its: Validate the device table L1 entry
  KVM: arm64: vgic-its: Fix L2 entry validation for indirect tables
  KVM: arm64: vgic-its: Add collection allocator/destructor
  KVM: arm64: vgic-its: Add pointer to corresponding kvm_device
  KVM: arm64: vgic-its: Turn device_id validation into generic ID validation
  KVM: arm64: vgic-its: Make vgic_its_cmd_handle_mapi similar to other 
handlers
  KVM: arm64: vgic-its: Simplify MAPI error handling

 Documentation/virtual/kvm/api.txt  |   14 +-
 

[PATCH 01/55] arm/arm64: KVM: Add a protection parameter to create_hyp_mappings

2016-07-22 Thread Marc Zyngier
Currently, create_hyp_mappings applies a "one size fits all" page
protection (PAGE_HYP). As we're heading towards separate protections
for different sections, let's make this protection a parameter, and
let the callers pass their prefered protection (PAGE_HYP for everyone
for the time being).

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm/include/asm/kvm_mmu.h   |  2 +-
 arch/arm/kvm/arm.c   | 13 +++--
 arch/arm/kvm/mmu.c   |  5 +++--
 arch/arm64/include/asm/kvm_mmu.h |  2 +-
 4 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index f9a6506..6cb4d4d 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -49,7 +49,7 @@
 #include 
 #include 
 
-int create_hyp_mappings(void *from, void *to);
+int create_hyp_mappings(void *from, void *to, pgprot_t prot);
 int create_hyp_io_mappings(void *from, void *to, phys_addr_t);
 void free_boot_hyp_pgd(void);
 void free_hyp_pgds(void);
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index f20ca84..45dd6df 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -122,7 +122,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
if (ret)
goto out_fail_alloc;
 
-   ret = create_hyp_mappings(kvm, kvm + 1);
+   ret = create_hyp_mappings(kvm, kvm + 1, PAGE_HYP);
if (ret)
goto out_free_stage2_pgd;
 
@@ -239,7 +239,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, 
unsigned int id)
if (err)
goto free_vcpu;
 
-   err = create_hyp_mappings(vcpu, vcpu + 1);
+   err = create_hyp_mappings(vcpu, vcpu + 1, PAGE_HYP);
if (err)
goto vcpu_uninit;
 
@@ -1293,14 +1293,14 @@ static int init_hyp_mode(void)
 * Map the Hyp-code called directly from the host
 */
err = create_hyp_mappings(kvm_ksym_ref(__hyp_text_start),
- kvm_ksym_ref(__hyp_text_end));
+ kvm_ksym_ref(__hyp_text_end), PAGE_HYP);
if (err) {
kvm_err("Cannot map world-switch code\n");
goto out_err;
}
 
err = create_hyp_mappings(kvm_ksym_ref(__start_rodata),
- kvm_ksym_ref(__end_rodata));
+ kvm_ksym_ref(__end_rodata), PAGE_HYP);
if (err) {
kvm_err("Cannot map rodata section\n");
goto out_err;
@@ -1311,7 +1311,8 @@ static int init_hyp_mode(void)
 */
for_each_possible_cpu(cpu) {
char *stack_page = (char *)per_cpu(kvm_arm_hyp_stack_page, cpu);
-   err = create_hyp_mappings(stack_page, stack_page + PAGE_SIZE);
+   err = create_hyp_mappings(stack_page, stack_page + PAGE_SIZE,
+ PAGE_HYP);
 
if (err) {
kvm_err("Cannot map hyp stack\n");
@@ -1323,7 +1324,7 @@ static int init_hyp_mode(void)
kvm_cpu_context_t *cpu_ctxt;
 
cpu_ctxt = per_cpu_ptr(kvm_host_cpu_state, cpu);
-   err = create_hyp_mappings(cpu_ctxt, cpu_ctxt + 1);
+   err = create_hyp_mappings(cpu_ctxt, cpu_ctxt + 1, PAGE_HYP);
 
if (err) {
kvm_err("Cannot map host CPU state: %d\n", err);
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 45c43ae..49cb5cc 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -679,12 +679,13 @@ static phys_addr_t kvm_kaddr_to_phys(void *kaddr)
  * create_hyp_mappings - duplicate a kernel virtual address range in Hyp mode
  * @from:  The virtual kernel start address of the range
  * @to:The virtual kernel end address of the range (exclusive)
+ * @prot:  The protection to be applied to this range
  *
  * The same virtual address as the kernel virtual address is also used
  * in Hyp-mode mapping (modulo HYP_PAGE_OFFSET) to the same underlying
  * physical pages.
  */
-int create_hyp_mappings(void *from, void *to)
+int create_hyp_mappings(void *from, void *to, pgprot_t prot)
 {
phys_addr_t phys_addr;
unsigned long virt_addr;
@@ -704,7 +705,7 @@ int create_hyp_mappings(void *from, void *to)
err = __create_hyp_mappings(hyp_pgd, virt_addr,
virt_addr + PAGE_SIZE,
__phys_to_pfn(phys_addr),
-   PAGE_HYP);
+   prot);
if (err)
return err;
}
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index f05ac27..fdfbddb 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -81,7 +81,7 @@ alternative_endif

[PATCH 04/55] arm/arm64: KVM: Map the HYP text as read-only

2016-07-22 Thread Marc Zyngier
There should be no reason for mapping the HYP text read/write.

As such, let's have a new set of flags (PAGE_HYP_EXEC) that allows
execution, but makes the page as read-only, and update the two call
sites that deal with mapping code.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm/include/asm/pgtable.h| 1 +
 arch/arm/kvm/arm.c| 2 +-
 arch/arm/kvm/mmu.c| 6 +++---
 arch/arm64/include/asm/pgtable-prot.h | 1 +
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index f332087..7487bf9 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -98,6 +98,7 @@ extern pgprot_t   pgprot_s2_device;
 #define PAGE_KERNEL_MOD_PROT(pgprot_kernel, L_PTE_XN)
 #define PAGE_KERNEL_EXEC   pgprot_kernel
 #define PAGE_HYP   _MOD_PROT(pgprot_kernel, L_PTE_HYP)
+#define PAGE_HYP_EXEC  _MOD_PROT(pgprot_kernel, L_PTE_HYP | 
L_PTE_RDONLY)
 #define PAGE_HYP_RO_MOD_PROT(pgprot_kernel, L_PTE_HYP | 
L_PTE_RDONLY | L_PTE_XN)
 #define PAGE_HYP_DEVICE_MOD_PROT(pgprot_hyp_device, L_PTE_HYP)
 #define PAGE_S2_MOD_PROT(pgprot_s2, L_PTE_S2_RDONLY)
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index b308976..c74483f 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -1293,7 +1293,7 @@ static int init_hyp_mode(void)
 * Map the Hyp-code called directly from the host
 */
err = create_hyp_mappings(kvm_ksym_ref(__hyp_text_start),
- kvm_ksym_ref(__hyp_text_end), PAGE_HYP);
+ kvm_ksym_ref(__hyp_text_end), PAGE_HYP_EXEC);
if (err) {
kvm_err("Cannot map world-switch code\n");
goto out_err;
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 49cb5cc..679608f 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -1733,7 +1733,7 @@ int kvm_mmu_init(void)
err =   __create_hyp_mappings(boot_hyp_pgd,
  hyp_idmap_start, hyp_idmap_end,
  __phys_to_pfn(hyp_idmap_start),
- PAGE_HYP);
+ PAGE_HYP_EXEC);
 
if (err) {
kvm_err("Failed to idmap %lx-%lx\n",
@@ -1756,7 +1756,7 @@ int kvm_mmu_init(void)
err =   __create_hyp_mappings(boot_hyp_pgd,
  TRAMPOLINE_VA, TRAMPOLINE_VA + PAGE_SIZE,
  __phys_to_pfn(hyp_idmap_start),
- PAGE_HYP);
+ PAGE_HYP_EXEC);
if (err) {
kvm_err("Failed to map trampoline @%lx into boot HYP pgd\n",
TRAMPOLINE_VA);
@@ -1767,7 +1767,7 @@ int kvm_mmu_init(void)
err =   __create_hyp_mappings(hyp_pgd,
  TRAMPOLINE_VA, TRAMPOLINE_VA + PAGE_SIZE,
  __phys_to_pfn(hyp_idmap_start),
- PAGE_HYP);
+ PAGE_HYP_EXEC);
if (err) {
kvm_err("Failed to map trampoline @%lx into runtime HYP pgd\n",
TRAMPOLINE_VA);
diff --git a/arch/arm64/include/asm/pgtable-prot.h 
b/arch/arm64/include/asm/pgtable-prot.h
index 88db58c..3802048 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -56,6 +56,7 @@
 #define PAGE_KERNEL_EXEC_CONT  __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | 
PTE_WRITE | PTE_CONT)
 
 #define PAGE_HYP   __pgprot(_PAGE_DEFAULT | PTE_HYP)
+#define PAGE_HYP_EXEC  __pgprot(_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY)
 #define PAGE_HYP_RO__pgprot(_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY | 
PTE_HYP_XN)
 #define PAGE_HYP_DEVICE__pgprot(PROT_DEVICE_nGnRE | PTE_HYP)
 
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 02/55] arm64: Add PTE_HYP_XN page table flag

2016-07-22 Thread Marc Zyngier
EL2 page tables can be configured to deny code from being
executed, which is done by setting bit 54 in the page descriptor.

It is the same bit as PTE_UXN, but the "USER" reference felt odd
in the hypervisor code.

Signed-off-by: Marc Zyngier 
Signed-off-by: Christoffer Dall 
---
 arch/arm64/include/asm/pgtable-hwdef.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/include/asm/pgtable-hwdef.h 
b/arch/arm64/include/asm/pgtable-hwdef.h
index 2813748..c3ae239 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -164,6 +164,7 @@
 #define PTE_CONT   (_AT(pteval_t, 1) << 52)/* Contiguous 
range */
 #define PTE_PXN(_AT(pteval_t, 1) << 53)/* 
Privileged XN */
 #define PTE_UXN(_AT(pteval_t, 1) << 54)/* User 
XN */
+#define PTE_HYP_XN (_AT(pteval_t, 1) << 54)/* HYP XN */
 
 /*
  * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
-- 
2.8.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [RFC v9 0/6] KVM: arm/arm64: gsi routing support

2016-07-22 Thread Radim Krčmář
2016-07-22 16:20+, Eric Auger:
> With the advent of GICv3 ITS in-kernel emulation, KVM MSI routing
> becomes mandated for proper VIRTIO-PCI vhost integration.

Changes to interfaces and common code look ok,

Acked-by: Radim Krčmář 

Good work.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[RFC v9 0/6] KVM: arm/arm64: gsi routing support

2016-07-22 Thread Eric Auger
With the advent of GICv3 ITS in-kernel emulation, KVM MSI routing
becomes mandated for proper VIRTIO-PCI vhost integration.

In QEMU, when the VIRTIO-PCI device is programmed with the MSI message,
we previously used direct_mapping trick: this consists in extracting the
IRQ ID found in the MSI message and associating an irqfd to that IRQ ID.
When vhost worker thread gets a new buffer it signals the irqfd and kvm
then injects this IRQ ID on guest. That way although the guest uses MSIs,
no MSI emulation is used.

This worked fine with GICv2m but does not work anymore with GICV3 ITS.
Indeed this latter implements IRQ translation: what is found in the MSI
message no more is the target IRQ ID but is an intermediate event ID used
in the translation process.

Hence true MSI routing is needed so that the vhost back channel irqfd is
associated to a dummy gsi ID, routed towards the programmed MSI. When KVM
injects the MSI through the in-kernel ITS emulation, the MSI is properly
translated and eventually the LPI ID associated to the event ID is injected
on guest.

MSI routing also mandates to integrate irqchip routing. The initial
implementation of irqfd on arm must be upgraded with the integration
of kvm irqchip.c code and the implementation of its standard hooks
in the architecture specific part.

In case KVM_SET_GSI_ROUTING ioctl is not called, a default routing
table with flat irqchip routing entries is built enabling to inject gsi
corresponding to the SPI indexes seen by the guest.

As soon as KVM_SET_GSI_ROUTING is called, user-space overwrites this
default routing table and is responsible for building the whole routing
table.

for arm/arm64 KVM_SET_GSI_ROUTING has a limited support:
- only applies to KVM_IRQFD and not to KVM_IRQ_LINE

- irqchip routing was tested on Calxeda midway (VFIO with irqfd)
  with and without explicit routing
- MSI routing was tested on AMD Overdrive and Cavium ThunderX

Code + dependencies can be found at:
https://github.com/eauger/linux/tree/v4.7-rc7-its-emul-v10-gsi-routing-v9

The series depends on

[1]: [PATCH v10 00/17] KVM: arm64: GICv3 ITS emulation
 http://www.spinics.net/lists/kvm/msg135687.html
   + [PATCH] KVM: arm/arm64: fix vGICv2 KVM_DEV_ARM_VGIC_GRP_CPU/DIST_REGS
[2]: [PATCH] KVM: arm/arm64: The GIC is dead, long live the GIC

hence the RFC.

GSI flat routing setup on QEMU can be found at:
https://lists.nongnu.org/archive/html/qemu-devel/2015-07/msg06262.html

History:
v8 -> v9:
- remove "[RFC v8 7/7] KVM: arm: Enable KVM_SIGNAL_MSI and MSI routing"
- fix spi id check at IRQ injection
- use default in irqchip switch(ue->type)

v7 -> v8:
- take into account Radim's comments:
  x rework kvm_kernel_irq_routing_entry and remove msi_msg now
replaced by a custom struct
  x check user entry flags depending on user entry type
  x I kept last patch although challenged by Radim. It can be dropped
according to the consensus.

v6 -> v7:
- take into account Drew's and Andre's comments
- new patch moving declarations of kvm_setup_default_irq_routing and
  kvm_setup_empty_irq_routing outside of kvm_host.h
- vgic_v2m_inject_msi moved in vgic-irqfd
- re-introduce irq.h
- add msi_ prefix to flags/devid kvm_kernel_irq_routing_entry fields
- move kvm_vgic_setup_default_irq_routing declaration in arm_vgic.h
  and definition in vgic-irqfd.c
- remove BUG_ON(!vgic_initialized(kvm) in vgic_irqfd_set_irq
- move KVM_IRQCHIP_NUM_PINS in arm_vgic.h and use VGIC_MAX_SPI instead
  of 1020

v5 -> v6:
- rebase on Andre's v8 + removal of old vgic
- tested on Cavium ThunderX

V4 -> v5:
- rebase on Andre's v7 + final new vgic code
- check msi->data is within SPI range in vgic_v2m_inject_msi
- squashed enable irq routing and default irqchip table patches
- handle default irqchip table allocation failure
- some rephrasing in doc & comment according to Christoffer's feedbacks
- lock issue reported by Pavel seems to have disappear after 4.2 (MSI injection
  fast path)

v3 -> v4:
- rebase on top of NEW-VGIC RFC and ITS emulation series v4. This is not
  a stable foundation yet. Hence the revert to RFC. This v4 mostly is a
  reflesh/reminder.
- rewrite the cover letter

v2 -> v3:
- don't use KVM_IRQ_ROUTING_EXTENDED_MSI type at uapi and kernel level anymore;
  use KVM_MSI_VALID_DEVID flag instead
- propagate user flags downto the kernel to make sure the userspace
  correctly set devid in GICv3 ITS case (still under discussion)

v1 -> v2:
- user API changed:
  x devid id passed in kvm_irq_routing_msi
  x kept the new routing entry type: KVM_IRQ_ROUTING_EXTENDED_MSI
- kvm_host.h: adopt Andre's proposal to replace the msi_msg by a struct
  composed of the msi_msg and devid in kvm_kernel_irq_routing_entry
- Fix bug reported by Pavel: Added KVM_IRQ_ROUTING_EXTENDED_MSI handling
  in eventfd.c
- added vgic_v2m_inject_msi in vgic-v2-emul.c as suggested by Andre
- fix bug reported by Andre: bad setting of msi.flags and msi.devid
  in kvm_send_userspace_msi
- avoid injecting reserved IRQ numbers in 

[RFC v9 1/6] KVM: api: Pass the devid in the msi routing entry

2016-07-22 Thread Eric Auger
On ARM, the MSI msg (address and data) comes along with
out-of-band device ID information. The device ID encodes the
device that writes the MSI msg. Let's convey the device id in
kvm_irq_routing_msi and use KVM_MSI_VALID_DEVID flag value in
kvm_irq_routing_entry to indicate the msi devid is populated.

Signed-off-by: Eric Auger 
Reviewed-by: Andre Przywara 

---

v6 -> v7:
- Added Andre's R-b

v4 -> v5:
- some rephrasing in api.txt according to Christoffer's comments
v2 -> v3:
- replace usage of KVM_IRQ_ROUTING_EXTENDED_MSI type by
  usage of KVM_MSI_VALID_DEVID flag
- add note about KVM_CAP_MSI_DEVID capability

v1 -> v2:
- devid id passed in kvm_irq_routing_msi instead of in
  kvm_irq_routing_entry

RFC -> PATCH
- remove kvm_irq_routing_extended_msi and use union instead
---
 Documentation/virtual/kvm/api.txt | 19 +--
 include/uapi/linux/kvm.h  |  5 -
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/Documentation/virtual/kvm/api.txt 
b/Documentation/virtual/kvm/api.txt
index f60b137..0065c8e 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1468,7 +1468,11 @@ struct kvm_irq_routing_entry {
 #define KVM_IRQ_ROUTING_S390_ADAPTER 3
 #define KVM_IRQ_ROUTING_HV_SINT 4
 
-No flags are specified so far, the corresponding field must be set to zero.
+flags:
+- KVM_MSI_VALID_DEVID: used along with KVM_IRQ_ROUTING_MSI
+  routing entry type, specifies that the devid field contains
+  a valid value.
+- zero otherwise
 
 struct kvm_irq_routing_irqchip {
__u32 irqchip;
@@ -1479,9 +1483,20 @@ struct kvm_irq_routing_msi {
__u32 address_lo;
__u32 address_hi;
__u32 data;
-   __u32 pad;
+   union {
+   __u32 pad;
+   __u32 devid;
+   };
 };
 
+devid: If KVM_MSI_VALID_DEVID is set, contains a unique device identifier
+   for the device that wrote the MSI message.
+   For PCI, this is usually a BFD identifier in the lower 16 bits.
+
+The per-VM KVM_CAP_MSI_DEVID capability advertises the requirement to
+provide the device ID. If this capability is not set, userland cannot
+rely on the kernel to allow the KVM_MSI_VALID_DEVID flag being set.
+
 struct kvm_irq_routing_s390_adapter {
__u64 ind_addr;
__u64 summary_addr;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index d8c4c32..eb22208 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -879,7 +879,10 @@ struct kvm_irq_routing_msi {
__u32 address_lo;
__u32 address_hi;
__u32 data;
-   __u32 pad;
+   union {
+   __u32 pad;
+   __u32 devid;
+   };
 };
 
 struct kvm_irq_routing_s390_adapter {
-- 
1.9.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[RFC v9 2/6] KVM: Add devid in kvm_kernel_irq_routing_entry

2016-07-22 Thread Eric Auger
Enhance kvm_kernel_irq_routing_entry to transport the device id
field, devid. A new flags field makes possible to indicate the
devid is valid. Those additions are used for ARM GICv3 ITS MSI
injection. The original struct msi_msg msi field is replaced by
a new custom structure that embeds the new fields.

Signed-off-by: Eric Auger 
Suggested-by: Radim Krčmář 

---
v7 -> v8:
- replace struct msi_msg by a new custom structure
- removed Christoffer's A-b

v6 -> v7:
- added msi_ prefix to flags and dev_id fields

v4 -> v5:
- add Christoffer's R-b

v2 -> v3:
- add flags

v1 -> v2:
- replace msi_msg field by a struct composed of msi_msg and devid

RFC -> PATCH:
- reword the commit message after change in first patch (uapi)
---
 include/linux/kvm_host.h | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index c87fe6f..e33e85e 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -317,7 +317,13 @@ struct kvm_kernel_irq_routing_entry {
unsigned irqchip;
unsigned pin;
} irqchip;
-   struct msi_msg msi;
+   struct {
+   u32 address_lo;
+   u32 address_hi;
+   u32 data;
+   u32 flags;
+   u32 devid;
+   } msi;
struct kvm_s390_adapter_int adapter;
struct kvm_hv_sint hv_sint;
};
-- 
1.9.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[RFC v9 5/6] KVM: arm/arm64: Enable irqchip routing

2016-07-22 Thread Eric Auger
This patch adds compilation and link against irqchip.

Main motivation behind using irqchip code is to enable MSI
routing code. In the future irqchip routing may also be useful
when targeting multiple irqchips.

Routing standard callbacks now are implemented in vgic-irqfd:
- kvm_set_routing_entry
- kvm_set_irq
- kvm_set_msi

They only are supported with new_vgic code.

Both HAVE_KVM_IRQCHIP and HAVE_KVM_IRQ_ROUTING are defined.
KVM_CAP_IRQ_ROUTING is advertised and KVM_SET_GSI_ROUTING is allowed.

So from now on IRQCHIP routing is enabled and a routing table entry
must exist for irqfd injection to succeed for a given SPI. This patch
builds a default flat irqchip routing table (gsi=irqchip.pin) covering
all the VGIC SPI indexes. This routing table is overwritten by the
first first user-space call to KVM_SET_GSI_ROUTING ioctl.

MSI routing setup is not yet allowed.

Signed-off-by: Eric Auger 

---
v8 -> v9
- fix bug when checking spi_id before irqfd injection

v7 -> v8:
- adapt to changes in kvm_kernel_irq_routing_entry

v6 -> v7:
- re-introduce irq.h
- use kvm_kernel_irq_routing_entry renamed fields: msi_flags, msi_devid
- moved kvm_vgic_setup_default_irq_routing declaration in arm_vgic.h and
  definition in vgic-irqfd.c
- correct double / in Makefile
- remove BUG_ON(!vgic_initialized(kvm) in vgic_irqfd_set_irq since
  in any case we have a lazy_init in update_irq_pending
- move KVM_IRQCHIP_NUM_PINS in arm_vgic.h
- use VGIC_MAX_SPI

v5 -> v6:
- rebase on top of Andre's v8 + removal of old vgic

v4 -> v5:
- vgic_irqfd.c was renamed into vgic-irqfd.c by Andre
- minor comment changes
- remove trace_kvm_set_irq since it is called in irqchip
- remove CONFIG_HAVE_KVM_MSI setting (done in KVM section)
- despite Christoffer's question, in kvm_set_msi, I kept the copy from
  the input "struct kvm_kernel_irq_routing_entry *e" imposed by the
  irqchip callback API into the struct kvm_msi * passed to
  vits_inject_msi. Since vits_inject_msi is directly called by
  kvm_send_userspace_msi which takes a struct kvm_msi*, makes sense
  to me to keep the copy.
- squash former [PATCH v4 5/7] KVM: arm/arm64: build a default routing
  table into that patch
- handle default routing table alloc failure

v3 -> v4:
- provide support only for new-vgic
- code previously in vgic.c now in vgic_irqfd.c

v2 -> v3:
- unconditionally set devid and KVM_MSI_VALID_DEVID flag as suggested
  by Andre (KVM_IRQ_ROUTING_EXTENDED_MSI type not used anymore)
- vgic_irqfd_set_irq now is static
- propagate flags
- add comments

v1 -> v2:
- fix bug reported by Andre related to msi.flags and msi.devid setting
  in kvm_send_userspace_msi
- avoid injecting reserved IRQ numbers in vgic_irqfd_set_irq

RFC -> PATCH
- reword api.txt:
  x move MSI routing comments in a subsequent patch,
  x clearly state GSI routing does not apply to KVM_IRQ_LINE
---
 Documentation/virtual/kvm/api.txt |  12 +++--
 arch/arm/kvm/Kconfig  |   2 +
 arch/arm/kvm/Makefile |   1 +
 arch/arm/kvm/irq.h|  19 
 arch/arm64/kvm/Kconfig|   2 +
 arch/arm64/kvm/Makefile   |   1 +
 arch/arm64/kvm/irq.h  |  19 
 include/kvm/arm_vgic.h|   7 +++
 virt/kvm/arm/vgic/vgic-init.c |   4 ++
 virt/kvm/arm/vgic/vgic-irqfd.c| 100 +++---
 virt/kvm/arm/vgic/vgic.c  |   7 ---
 11 files changed, 145 insertions(+), 29 deletions(-)
 create mode 100644 arch/arm/kvm/irq.h
 create mode 100644 arch/arm64/kvm/irq.h

diff --git a/Documentation/virtual/kvm/api.txt 
b/Documentation/virtual/kvm/api.txt
index 0065c8e..3bb60d3 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1433,13 +1433,16 @@ KVM_ASSIGN_DEV_IRQ. Partial deassignment of host or 
guest IRQ is allowed.
 4.52 KVM_SET_GSI_ROUTING
 
 Capability: KVM_CAP_IRQ_ROUTING
-Architectures: x86 s390
+Architectures: x86 s390 arm arm64
 Type: vm ioctl
 Parameters: struct kvm_irq_routing (in)
 Returns: 0 on success, -1 on error
 
 Sets the GSI routing table entries, overwriting any previously set entries.
 
+On arm/arm64, GSI routing has the following limitation:
+- GSI routing does not apply to KVM_IRQ_LINE but only to KVM_IRQFD.
+
 struct kvm_irq_routing {
__u32 nr;
__u32 flags;
@@ -2368,9 +2371,10 @@ Note that closing the resamplefd is not sufficient to 
disable the
 irqfd.  The KVM_IRQFD_FLAG_RESAMPLE is only necessary on assignment
 and need not be specified with KVM_IRQFD_FLAG_DEASSIGN.
 
-On ARM/ARM64, the gsi field in the kvm_irqfd struct specifies the Shared
-Peripheral Interrupt (SPI) index, such that the GIC interrupt ID is
-given by gsi + 32.
+On arm/arm64, gsi routing being supported, the following can happen:
+- in case no routing entry is associated to this gsi, injection fails
+- in case the gsi is associated to an irqchip routing entry,
+  irqchip.pin + 32 corresponds to the injected SPI ID.
 
 4.76 KVM_PPC_ALLOCATE_HTAB
 
diff 

[RFC v9 6/6] KVM: arm/arm64: Enable MSI routing

2016-07-22 Thread Eric Auger
Up to now, only irqchip routing entries could be set. This patch
adds the capability to insert MSI routing entries.

For ARM64, let's also increase KVM_MAX_IRQ_ROUTES to 4096: this
include SPI irqchip routes plus MSI routes. In the future this
might be extended.

Signed-off-by: Eric Auger 
Reviewed-by: Andre Przywara 

---
v8 -> v9:
- documentation specifies MSI routing only is supported with
  GICv3 ITS use case
- default used when checking ue->type

v7 -> v8:
- adapt to changes in kvm_kernel_irq_routing_entry and check the
  user entry flags according to the user entry type

v6 -> v7:
- added Andre's R-b

v2 -> v3:
- remove any reference to KVM_IRQ_ROUTING_EXTENDED_MSI type
- unconditionnaly uapi flags and devid downto the kernel
  routing entry struct
- handle KVM_MSI_VALID_DEVID flag in kvm_set_irq_routing
- note about KVM_CAP_MSI_DEVID moved in the first patch file
  of the series

v1 -> v2:
- adapt to new routing entry types

RFC -> PATCH:
- move api MSI routing updates into that patch file
- use new devid field of user api struct
---
 Documentation/virtual/kvm/api.txt |  3 +++
 include/linux/kvm_host.h  |  2 ++
 virt/kvm/arm/vgic/vgic-irqfd.c|  8 
 virt/kvm/irqchip.c| 24 +++-
 4 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/Documentation/virtual/kvm/api.txt 
b/Documentation/virtual/kvm/api.txt
index 3bb60d3..8501e75 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2375,6 +2375,9 @@ On arm/arm64, gsi routing being supported, the following 
can happen:
 - in case no routing entry is associated to this gsi, injection fails
 - in case the gsi is associated to an irqchip routing entry,
   irqchip.pin + 32 corresponds to the injected SPI ID.
+- in case the gsi is associated to an MSI routing entry, the MSI
+  message and device ID are translated into an LPI (support restricted
+  to GICv3 ITS in-kernel emulation).
 
 4.76 KVM_PPC_ALLOCATE_HTAB
 
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 49e8152..9fa4bc2 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1040,6 +1040,8 @@ static inline int mmu_notifier_retry(struct kvm *kvm, 
unsigned long mmu_seq)
 
 #ifdef CONFIG_S390
 #define KVM_MAX_IRQ_ROUTES 4096 //FIXME: we can have more than that...
+#elif defined(CONFIG_ARM64)
+#define KVM_MAX_IRQ_ROUTES 4096
 #else
 #define KVM_MAX_IRQ_ROUTES 1024
 #endif
diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
index 6e84d53..683a589 100644
--- a/virt/kvm/arm/vgic/vgic-irqfd.c
+++ b/virt/kvm/arm/vgic/vgic-irqfd.c
@@ -59,6 +59,14 @@ int kvm_set_routing_entry(struct 
kvm_kernel_irq_routing_entry *e,
(e->irqchip.irqchip >= KVM_NR_IRQCHIPS))
goto out;
break;
+   case KVM_IRQ_ROUTING_MSI:
+   e->set = kvm_set_msi;
+   e->msi.address_lo = ue->u.msi.address_lo;
+   e->msi.address_hi = ue->u.msi.address_hi;
+   e->msi.data = ue->u.msi.data;
+   e->msi.flags = ue->flags;
+   e->msi.devid = ue->u.msi.devid;
+   break;
default:
goto out;
}
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
index 0c00054..c620219 100644
--- a/virt/kvm/irqchip.c
+++ b/virt/kvm/irqchip.c
@@ -178,6 +178,7 @@ int kvm_set_irq_routing(struct kvm *kvm,
unsigned flags)
 {
struct kvm_irq_routing_table *new, *old;
+   struct kvm_kernel_irq_routing_entry *e;
u32 i, j, nr_rt_entries = 0;
int r;
 
@@ -201,23 +202,25 @@ int kvm_set_irq_routing(struct kvm *kvm,
new->chip[i][j] = -1;
 
for (i = 0; i < nr; ++i) {
-   struct kvm_kernel_irq_routing_entry *e;
-
r = -ENOMEM;
e = kzalloc(sizeof(*e), GFP_KERNEL);
if (!e)
goto out;
 
r = -EINVAL;
-   if (ue->flags) {
-   kfree(e);
-   goto out;
+   switch (ue->type) {
+   case KVM_IRQ_ROUTING_MSI:
+   if (ue->flags & ~KVM_MSI_VALID_DEVID)
+   goto free_entry;
+   break;
+   default:
+   if (ue->flags)
+   goto free_entry;
+   break;
}
r = setup_routing_entry(new, e, ue);
-   if (r) {
-   kfree(e);
-   goto out;
-   }
+   if (r)
+   goto free_entry;
++ue;
}
 
@@ -234,7 +237,10 @@ int kvm_set_irq_routing(struct kvm *kvm,
 
new = old;
r = 0;
+   goto out;
 
+free_entry:
+   kfree(e);
 out:
free_irq_routing_table(new);
 
-- 
1.9.1


[RFC v9 4/6] KVM: Move kvm_setup_default/empty_irq_routing declaration in arch specific header

2016-07-22 Thread Eric Auger
kvm_setup_default_irq_routing and kvm_setup_empty_irq_routing are
not used by generic code. So let's move the declarations in x86 irq.h
header instead of kvm_host.h.

Signed-off-by: Eric Auger 
Suggested-by: Andre Przywara 

---

- new patch in v7
---
 arch/x86/kvm/irq.h   | 3 +++
 include/linux/kvm_host.h | 2 --
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index 61ebdc1..035731e 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -120,4 +120,7 @@ void __kvm_migrate_timers(struct kvm_vcpu *vcpu);
 
 int apic_has_pending_timer(struct kvm_vcpu *vcpu);
 
+int kvm_setup_default_irq_routing(struct kvm *kvm);
+int kvm_setup_empty_irq_routing(struct kvm *kvm);
+
 #endif
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index e33e85e..49e8152 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1044,8 +1044,6 @@ static inline int mmu_notifier_retry(struct kvm *kvm, 
unsigned long mmu_seq)
 #define KVM_MAX_IRQ_ROUTES 1024
 #endif
 
-int kvm_setup_default_irq_routing(struct kvm *kvm);
-int kvm_setup_empty_irq_routing(struct kvm *kvm);
 int kvm_set_irq_routing(struct kvm *kvm,
const struct kvm_irq_routing_entry *entries,
unsigned nr,
-- 
1.9.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[RFC v9 3/6] KVM: irqchip: Convey devid to kvm_set_msi

2016-07-22 Thread Eric Auger
on ARM, a devid field is populated in kvm_msi struct in case the
flag is set to KVM_MSI_VALID_DEVID. Let's propagate both flags and
devid field in kvm_kernel_irq_routing_entry.

Signed-off-by: Eric Auger 
Reviewed-by: Andre Przywara 
Acked-by: Christoffer Dall 

---
v7 -> v8:
- adapt to changes in kvm_kernel_irq_routing_entry struct

v6 -> v7:
- use renamed msi_flags and msi_devid
- added Andre's R-b

v4 -> v5:
- Add Christoffer's R-b

v2 -> v3:
- do not set the type to KVM_IRQ_ROUTING_EXTENDED_MSI anymore as
  suggested by Andre
- correct msi->flags check
- propagate the flags
---
 virt/kvm/irqchip.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
index 8db197b..0c00054 100644
--- a/virt/kvm/irqchip.c
+++ b/virt/kvm/irqchip.c
@@ -62,12 +62,14 @@ int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi 
*msi)
 {
struct kvm_kernel_irq_routing_entry route;
 
-   if (!irqchip_in_kernel(kvm) || msi->flags != 0)
+   if (!irqchip_in_kernel(kvm) || (msi->flags & ~KVM_MSI_VALID_DEVID))
return -EINVAL;
 
route.msi.address_lo = msi->address_lo;
route.msi.address_hi = msi->address_hi;
route.msi.data = msi->data;
+   route.msi.flags = msi->flags;
+   route.msi.devid = msi->devid;
 
return kvm_set_msi(, kvm, KVM_USERSPACE_IRQ_SOURCE_ID, 1, false);
 }
-- 
1.9.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH] arm64: kvm: set cpsr before spsr on fault injection

2016-07-22 Thread Andrew Jones
On Fri, Jul 22, 2016 at 04:37:35PM +0100, Marc Zyngier wrote:
> On 22/07/16 15:38, Andrew Jones wrote:
> > We need to set cpsr before determining the spsr bank, as the bank
> > depends on the target exception level of the injection, not the
> > current mode of the vcpu. Normally this is one in the same (EL1),
> > but not when we manage to trap an EL0 fault. It still doesn't really
> > matter for the 64-bit EL0 case though, as vcpu_spsr() unconditionally
> > uses the EL1 bank for that. However the 32-bit EL0 case gets fun, as
> > that path will lead to the BUG() in vcpu_spsr32()
> > 
> > This patch fixes the assignment order and also modifies some white
> > space in order to better group pairs of lines that have strict order.
> > 
> > Signed-off-by: Andrew Jones 
> 
> Ouch. Nice catch. Can you find what's the earliest release this would
> cleanly apply to? Definitely deserves a CC stable.

stable/linux-4.5.y, which is the first to contain 8fc153cda9c9 "arm64:
KVM: Fix AArch64 guest userspace exception injection"

Thanks,
drew
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH] arm64: kvm: set cpsr before spsr on fault injection

2016-07-22 Thread Marc Zyngier
On 22/07/16 15:38, Andrew Jones wrote:
> We need to set cpsr before determining the spsr bank, as the bank
> depends on the target exception level of the injection, not the
> current mode of the vcpu. Normally this is one in the same (EL1),
> but not when we manage to trap an EL0 fault. It still doesn't really
> matter for the 64-bit EL0 case though, as vcpu_spsr() unconditionally
> uses the EL1 bank for that. However the 32-bit EL0 case gets fun, as
> that path will lead to the BUG() in vcpu_spsr32()
> 
> This patch fixes the assignment order and also modifies some white
> space in order to better group pairs of lines that have strict order.
> 
> Signed-off-by: Andrew Jones 

Ouch. Nice catch. Can you find what's the earliest release this would
cleanly apply to? Definitely deserves a CC stable.

Thanks,

M.
-- 
Jazz is not dead. It just smells funny...
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: KVM on ARM crashes with new VGIC v4.7-rc7

2016-07-22 Thread Auger Eric
Hi,

On 22/07/2016 17:40, Marc Zyngier wrote:
> On 22/07/16 15:35, Andrew Jones wrote:
>> On Fri, Jul 22, 2016 at 11:42:02AM +0100, Andre Przywara wrote:
>>> Hi Stefan,
>>>
>>> On 22/07/16 06:57, Stefan Agner wrote:
 Hi,

 I tried KVM on a Cortex-A7 platform (i.MX 7Dual SoC) and encountered
 this stack trace immediately after invoking qemu-system-arm:

 Unable to handle kernel paging request at virtual address ffe4
 pgd = 8ca52740
 [ffe4] *pgd=8080007003, *pmd=8ff7e003, *pte=
 Internal error: Oops: 207 [#1] SMP ARM
 Modules linked in:  
 CPU: 0 PID: 329 Comm: qemu-system-arm Tainted: GW  
 4.7.0-rc7-00094-gea3ed2c #109
 Hardware name: Freescale i.MX7 Dual (Device Tree)
 task: 8ca3ee40 ti: 8d2b task.ti: 8d2b
 PC is at do_raw_spin_lock+0x8/0x1dc
 LR is at kvm_vgic_flush_hwstate+0x8c/0x224
 pc : [<8027c87c>]lr : [<802172d4>]psr: 60070013
 sp : 8d2b1e38  ip : 8d2b  fp : 0001
 r10: 8d2b  r9 : 0001  r8 : 8d2b8e54
 fec 30be.ethernet eth0: MDIO read timeout
 r7 : 8d2b8000  r6 : 8d2b8e74  r5 :   r4 : ffe0
 r3 : 4ead  r2 :   r1 :   r0 : ffe0
 Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
 Control: 30c5387d  Table: 8ca52740  DAC: fffd
 Process qemu-system-arm (pid: 329, stack limit = 0x8d2b0210)
 Stack: (0x8d2b1e38 to 0x8d2b2000)
 1e20:   ffe0
 
 1e40: 8d2b8e74 8d2b8000 8d2b8e54 0001 8d2b 802172d4 8d2b8000
 810074f8
 1e60: 81007508 8ca5f800 8d284000 0001 8d2b 8020fbd4 8ce9a000
 8ca5f800
 1e80:  0001  00ff 8d284000  
 7ffbfeff
 1ea0: fffe  8d28b780  755fec6c  
 e000
 1ec0: 8d2b8000  8d28b780  755fec6c 8020af90 
 8023f248
 1ee0: 000a 755fe98c 8d2b1f08 0008 8021aa84 e000 
 
 1f00: 8a00d860 8d28b780 80334f94  8d2b 80334748 
 
 1f20:  8d28b780 4000 0009 8d28b500 0024 8104ebee
 80bc2ec4
 1f40: 80bafa24 8034138c   80341248  755fec6c
 007c1e70
 1f60: 0009 4258 ae80 8d28b781 0009 8d28b780 ae80
 
 1f80: 8d2b  755fec6c 80334f94 007c1e70 322a7400 4258
 0036
 1fa0: 8021aa84 8021a900 007c1e70 322a7400 0009 ae80 
 755feac0
 1fc0: 007c1e70 322a7400 4258 0036 7e9aff58 01151da4 76f8b4c0
 755fec6c
 1fe0: 0038192c 755fea9c 00048ae7 7697d66c 60070010 0009 
 
 [<8027c87c>] (do_raw_spin_lock) from [<802172d4>]
 (kvm_vgic_flush_hwstate+0x8c/0x224)
 [<802172d4>] (kvm_vgic_flush_hwstate) from [<8020fbd4>]
 (kvm_arch_vcpu_ioctl_run+0x110/0x478)
 [<8020fbd4>] (kvm_arch_vcpu_ioctl_run) from [<8020af90>]
 (kvm_vcpu_ioctl+0x2e0/0x6d4)
 [<8020af90>] (kvm_vcpu_ioctl) from [<80334748>]
 (do_vfs_ioctl+0xa0/0x8b8)
 [<80334748>] (do_vfs_ioctl) from [<80334f94>] (SyS_ioctl+0x34/0x5c)
 [<80334f94>] (SyS_ioctl) from [<8021a900>] (ret_fast_syscall+0x0/0x1c)
 Code: e49de004 ea09ea24 e92d47f0 e3043ead (e5902004)
 ---[ end trace cb88537fdc8fa206 ]---

 I use CONFIG_KVM_NEW_VGIC=y. This happens to me with a rather minimal
 qemu invocation (qemu-system-arm -enable-kvm -M virt -cpu host
 -nographic -serial stdio -kernel zImage).

 Using a bit older Qemu version 2.4.0.
>>>
>>> I just tried with a self compiled QEMU 2.4.0 and the Ubuntu 14.04
>>> provided 2.0.0, it worked fine with Linus' current HEAD as a host kernel
>>> on a Midway (Cortex-A15).
>>
>> I can reproduce the issue with a latest QEMU build on AMD Seattle
>> (I haven't tried anywhere else yet)
>>
>>>
>>> Can you try to disable the new VGIC, just to see if that's a regression?
>>
>> Disabling NEW_VGIC "fixes" guest boots.
>>
>> I'm not using defconfig for my host kernel. I'll do a couple more
>> tests and provide a comparison of my config vs. a defconfig in
>> a few minutes.
> 
> Damn. It is not failing for me, so it has to be a kernel config thing...
> If you can narrow it down to the difference with defconfig, that'd be
> tremendously helpful.
Yes I confirm I also use a defconfig based 4.7-rc7 host and I tried qemu
2.4.0 and latest and I can't reproduce either (AMD Overdrive).

Eric
> 
> Thanks,
> 
>   M.
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: KVM on ARM crashes with new VGIC v4.7-rc7

2016-07-22 Thread Marc Zyngier
On 22/07/16 15:35, Andrew Jones wrote:
> On Fri, Jul 22, 2016 at 11:42:02AM +0100, Andre Przywara wrote:
>> Hi Stefan,
>>
>> On 22/07/16 06:57, Stefan Agner wrote:
>>> Hi,
>>>
>>> I tried KVM on a Cortex-A7 platform (i.MX 7Dual SoC) and encountered
>>> this stack trace immediately after invoking qemu-system-arm:
>>>
>>> Unable to handle kernel paging request at virtual address ffe4
>>> pgd = 8ca52740
>>> [ffe4] *pgd=8080007003, *pmd=8ff7e003, *pte=
>>> Internal error: Oops: 207 [#1] SMP ARM
>>> Modules linked in:  
>>> CPU: 0 PID: 329 Comm: qemu-system-arm Tainted: GW  
>>> 4.7.0-rc7-00094-gea3ed2c #109
>>> Hardware name: Freescale i.MX7 Dual (Device Tree)
>>> task: 8ca3ee40 ti: 8d2b task.ti: 8d2b
>>> PC is at do_raw_spin_lock+0x8/0x1dc
>>> LR is at kvm_vgic_flush_hwstate+0x8c/0x224
>>> pc : [<8027c87c>]lr : [<802172d4>]psr: 60070013
>>> sp : 8d2b1e38  ip : 8d2b  fp : 0001
>>> r10: 8d2b  r9 : 0001  r8 : 8d2b8e54
>>> fec 30be.ethernet eth0: MDIO read timeout
>>> r7 : 8d2b8000  r6 : 8d2b8e74  r5 :   r4 : ffe0
>>> r3 : 4ead  r2 :   r1 :   r0 : ffe0
>>> Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
>>> Control: 30c5387d  Table: 8ca52740  DAC: fffd
>>> Process qemu-system-arm (pid: 329, stack limit = 0x8d2b0210)
>>> Stack: (0x8d2b1e38 to 0x8d2b2000)
>>> 1e20:   ffe0
>>> 
>>> 1e40: 8d2b8e74 8d2b8000 8d2b8e54 0001 8d2b 802172d4 8d2b8000
>>> 810074f8
>>> 1e60: 81007508 8ca5f800 8d284000 0001 8d2b 8020fbd4 8ce9a000
>>> 8ca5f800
>>> 1e80:  0001  00ff 8d284000  
>>> 7ffbfeff
>>> 1ea0: fffe  8d28b780  755fec6c  
>>> e000
>>> 1ec0: 8d2b8000  8d28b780  755fec6c 8020af90 
>>> 8023f248
>>> 1ee0: 000a 755fe98c 8d2b1f08 0008 8021aa84 e000 
>>> 
>>> 1f00: 8a00d860 8d28b780 80334f94  8d2b 80334748 
>>> 
>>> 1f20:  8d28b780 4000 0009 8d28b500 0024 8104ebee
>>> 80bc2ec4
>>> 1f40: 80bafa24 8034138c   80341248  755fec6c
>>> 007c1e70
>>> 1f60: 0009 4258 ae80 8d28b781 0009 8d28b780 ae80
>>> 
>>> 1f80: 8d2b  755fec6c 80334f94 007c1e70 322a7400 4258
>>> 0036
>>> 1fa0: 8021aa84 8021a900 007c1e70 322a7400 0009 ae80 
>>> 755feac0
>>> 1fc0: 007c1e70 322a7400 4258 0036 7e9aff58 01151da4 76f8b4c0
>>> 755fec6c
>>> 1fe0: 0038192c 755fea9c 00048ae7 7697d66c 60070010 0009 
>>> 
>>> [<8027c87c>] (do_raw_spin_lock) from [<802172d4>]
>>> (kvm_vgic_flush_hwstate+0x8c/0x224)
>>> [<802172d4>] (kvm_vgic_flush_hwstate) from [<8020fbd4>]
>>> (kvm_arch_vcpu_ioctl_run+0x110/0x478)
>>> [<8020fbd4>] (kvm_arch_vcpu_ioctl_run) from [<8020af90>]
>>> (kvm_vcpu_ioctl+0x2e0/0x6d4)
>>> [<8020af90>] (kvm_vcpu_ioctl) from [<80334748>]
>>> (do_vfs_ioctl+0xa0/0x8b8)
>>> [<80334748>] (do_vfs_ioctl) from [<80334f94>] (SyS_ioctl+0x34/0x5c)
>>> [<80334f94>] (SyS_ioctl) from [<8021a900>] (ret_fast_syscall+0x0/0x1c)
>>> Code: e49de004 ea09ea24 e92d47f0 e3043ead (e5902004)
>>> ---[ end trace cb88537fdc8fa206 ]---
>>>
>>> I use CONFIG_KVM_NEW_VGIC=y. This happens to me with a rather minimal
>>> qemu invocation (qemu-system-arm -enable-kvm -M virt -cpu host
>>> -nographic -serial stdio -kernel zImage).
>>>
>>> Using a bit older Qemu version 2.4.0.
>>
>> I just tried with a self compiled QEMU 2.4.0 and the Ubuntu 14.04
>> provided 2.0.0, it worked fine with Linus' current HEAD as a host kernel
>> on a Midway (Cortex-A15).
> 
> I can reproduce the issue with a latest QEMU build on AMD Seattle
> (I haven't tried anywhere else yet)
> 
>>
>> Can you try to disable the new VGIC, just to see if that's a regression?
> 
> Disabling NEW_VGIC "fixes" guest boots.
> 
> I'm not using defconfig for my host kernel. I'll do a couple more
> tests and provide a comparison of my config vs. a defconfig in
> a few minutes.

Damn. It is not failing for me, so it has to be a kernel config thing...
If you can narrow it down to the difference with defconfig, that'd be
tremendously helpful.

Thanks,

M.
-- 
Jazz is not dead. It just smells funny...
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 0/2] arm64: add pabt injection test

2016-07-22 Thread Andrew Jones
On Fri, Jul 22, 2016 at 10:43:21AM -0400, Andrew Jones wrote:
> Get arm emulation tests kick started by adding a couple pabt injection
> tests.
> 
> Andrew Jones (2):
>   arm64: add start_usr32
>   arm64: add pabt injection test
> 
>  arm/Makefile.arm64|  2 +-
>  arm/emul-abort.c  | 95 
> +++
>  arm/unittests.cfg | 25 +
>  lib/arm64/asm/processor.h |  1 +
>  lib/arm64/processor.c | 21 +--
>  5 files changed, 139 insertions(+), 5 deletions(-)
>  create mode 100644 arm/emul-abort.c

Eh, I forgot the kvm-unit-tests tags on these patches... Sorry.

> 
> -- 
> 1.8.3.1
> 
> ___
> kvmarm mailing list
> kvmarm@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [RFC v8 6/7] KVM: arm/arm64: Enable MSI routing

2016-07-22 Thread Auger Eric


On 22/07/2016 16:14, Radim Krčmář wrote:
> 2016-07-22 13:46+, Eric Auger:
>> Up to now, only irqchip routing entries could be set. This patch
>> adds the capability to insert MSI routing entries.
>>
>> For ARM64, let's also increase KVM_MAX_IRQ_ROUTES to 4096: this
>> include SPI irqchip routes plus MSI routes. In the future this
>> might be extended.
>>
>> Signed-off-by: Eric Auger 
>> Reviewed-by: Andre Przywara 
>>
>> ---
>> v7 -> v8:
>> - adapt to changes in kvm_kernel_irq_routing_entry and check the
>>   user entry flags according to the user entry type
>>
>> v6 -> v7:
>> - added Andre's R-b
>>
>> v2 -> v3:
>> - remove any reference to KVM_IRQ_ROUTING_EXTENDED_MSI type
>> - unconditionnaly uapi flags and devid downto the kernel
>>   routing entry struct
>> - handle KVM_MSI_VALID_DEVID flag in kvm_set_irq_routing
>> - note about KVM_CAP_MSI_DEVID moved in the first patch file
>>   of the series
>>
>> v1 -> v2:
>> - adapt to new routing entry types
>>
>> RFC -> PATCH:
>> - move api MSI routing updates into that patch file
>> - use new devid field of user api struct
>> ---
>> diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
>> @@ -201,23 +202,25 @@ int kvm_set_irq_routing(struct kvm *kvm,
>>  new->chip[i][j] = -1;
>>  
>>  for (i = 0; i < nr; ++i) {
>> -struct kvm_kernel_irq_routing_entry *e;
>> -
>>  r = -ENOMEM;
>>  e = kzalloc(sizeof(*e), GFP_KERNEL);
>>  if (!e)
>>  goto out;
>>  
>>  r = -EINVAL;
>> -if (ue->flags) {
>> -kfree(e);
>> -goto out;
>> +switch (ue->type) {
>> +case KVM_IRQ_ROUTING_IRQCHIP:
>> +if (ue->flags)
>> +goto free_entry;
>> +break;
>> +case KVM_IRQ_ROUTING_MSI:
>> +if (ue->flags & ~KVM_MSI_VALID_DEVID)
>> +goto free_entry;
>> +break;
> 
> The function is common for all arches and there are currently two other
> routing types (S390_ADAPTER and HV_SINT) that ought to be checked as
> well, so "default" instead of "KVM_IRQ_ROUTING_IRQCHIP" would be better.
Sure

Thanks

Eric
> 
>>  }
>>  r = setup_routing_entry(new, e, ue);
>> -if (r) {
>> -kfree(e);
>> -goto out;
>> -}
>> +if (r)
>> +goto free_entry;
>>  ++ue;
>>  }
>>  
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [RFC v8 5/7] KVM: arm/arm64: Enable irqchip routing

2016-07-22 Thread Auger Eric
Hi Radim

On 22/07/2016 16:24, Radim Krčmář wrote:
> 2016-07-22 13:46+, Eric Auger:
>> This patch adds compilation and link against irqchip.
>>
>> Main motivation behind using irqchip code is to enable MSI
>> routing code. In the future irqchip routing may also be useful
>> when targeting multiple irqchips.
>>
>> Routing standard callbacks now are implemented in vgic-irqfd:
>> - kvm_set_routing_entry
>> - kvm_set_irq
>> - kvm_set_msi
>>
>> They only are supported with new_vgic code.
>>
>> Both HAVE_KVM_IRQCHIP and HAVE_KVM_IRQ_ROUTING are defined.
>> KVM_CAP_IRQ_ROUTING is advertised and KVM_SET_GSI_ROUTING is allowed.
>>
>> So from now on IRQCHIP routing is enabled and a routing table entry
>> must exist for irqfd injection to succeed for a given SPI. This patch
>> builds a default flat irqchip routing table (gsi=irqchip.pin) covering
>> all the VGIC SPI indexes. This routing table is overwritten by the
>> first first user-space call to KVM_SET_GSI_ROUTING ioctl.
>>
>> MSI routing setup is not yet allowed.
>>
>> Signed-off-by: Eric Auger 
>>
>> ---
>> diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
>> @@ -17,36 +17,101 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>> +#include "vgic.h"
>>  
>> -int kvm_irq_map_gsi(struct kvm *kvm,
>> -struct kvm_kernel_irq_routing_entry *entries,
>> -int gsi)
>> +/**
>> + * vgic_irqfd_set_irq: inject the IRQ corresponding to the
>> + * irqchip routing entry
>> + *
>> + * This is the entry point for irqfd IRQ injection
>> + */
>> +static int vgic_irqfd_set_irq(struct kvm_kernel_irq_routing_entry *e,
>> +struct kvm *kvm, int irq_source_id,
>> +int level, bool line_status)
>>  {
>> -return 0;
>> +unsigned int spi_id = e->irqchip.pin + VGIC_NR_PRIVATE_IRQS;
>> +struct vgic_dist *dist = >arch.vgic;
>> +
>> +if (spi_id > min(dist->nr_spis, VGIC_MAX_SPI))
> 
> This is more strict that vgic_valid_spi(), because spi_id between
> "dist->nr_spis" and "dist->nr_spis + VGIC_NR_PRIVATE_IRQS" is not
> allowed, which probably wasn't intended.
Hum yes you're right. This is wrong.
> 
> And shouldn't nr_spis always be less that VGIC_MAX_SPI?
Correct. I will use vgic_valid_spi which was introduced to avoid such mixup.

Thanks for noticing

Eric
> 
> Thanks.
> 
>> +return -EINVAL;
>> +return kvm_vgic_inject_irq(kvm, 0, spi_id, level);
>>  }
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 2/2] arm64: add pabt injection test

2016-07-22 Thread Andrew Jones
Signed-off-by: Andrew Jones 
---
 arm/Makefile.arm64 |  2 +-
 arm/emul-abort.c   | 95 ++
 arm/unittests.cfg  | 25 ++
 3 files changed, 121 insertions(+), 1 deletion(-)
 create mode 100644 arm/emul-abort.c

diff --git a/arm/Makefile.arm64 b/arm/Makefile.arm64
index 0b0761c729c7..6a1a997bc26b 100644
--- a/arm/Makefile.arm64
+++ b/arm/Makefile.arm64
@@ -12,7 +12,7 @@ cflatobjs += lib/arm64/processor.o
 cflatobjs += lib/arm64/spinlock.o
 
 # arm64 specific tests
-tests =
+tests = $(TEST_DIR)/emul-abort.flat
 
 include $(TEST_DIR)/Makefile.common
 
diff --git a/arm/emul-abort.c b/arm/emul-abort.c
new file mode 100644
index ..cc2be586a422
--- /dev/null
+++ b/arm/emul-abort.c
@@ -0,0 +1,95 @@
+/*
+ * Test emulation of guest aborts
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include 
+#include 
+#include 
+#include 
+
+#define USAGE "usage: emul-abort \n"  \
+   "subtests:\n"   \
+   "   pabtinj-usr32-mem\n"\
+   "   pabtinj-usr64-mem\n"\
+   "   pabtinj-usr32-io\n" \
+   "   pabtinj-usr64-io"
+
+#define UNMAPPED_MEM   (PHYS_END + 64*1024)
+#define UNMAPPED_IO0xf01
+
+typedef void (*func_t)(void *arg);
+
+static unsigned long do_pabt, mode, far;
+static bool pass;
+
+static void finish_pabt(void)
+{
+   report("bad_addr=0x%08lx far=0x%08lx", pass, do_pabt, far);
+   exit(report_summary());
+}
+
+static void handle_pabt(struct pt_regs *regs, unsigned int esr)
+{
+   bool far_valid;
+
+   if (esr >> ESR_EL1_EC_SHIFT != ESR_EL1_EC_IABT_EL0)
+   return;
+
+   far_valid = get_far(esr, );
+
+   pass = far_valid && far == do_pabt;
+   pass = pass && regs->pc == do_pabt;
+   pass = pass && (regs->pstate & (PSR_MODE32_BIT | PSR_MODE_MASK)) == 
mode;
+
+   regs->pstate &= ~PSR_MODE32_BIT;
+   regs->pc = (unsigned long)finish_pabt;
+}
+
+static void pabtinj_test(bool is_64)
+{
+   unsigned long sp = (unsigned long)thread_stack_alloc();
+
+   if (is_64) {
+   install_exception_handler(EL0_SYNC_64, ESR_EL1_EC_IABT_EL0, 
handle_pabt);
+   start_usr((func_t)do_pabt, NULL, sp);
+   } else {
+   mode = PSR_MODE32_BIT;
+   install_exception_handler(EL0_SYNC_32, ESR_EL1_EC_IABT_EL0, 
handle_pabt);
+   start_usr32((func_t)do_pabt, NULL, sp);
+   }
+}
+
+void main(int ac, char **av)
+{
+   if (ac < 2)
+   report_abort(USAGE);
+
+   if (strncmp(av[1], "pabtinj-usr", 11) == 0) {
+
+   char *testname = av[1] + 11;
+   bool is_64 = false;
+
+   if (strncmp(testname, "32", 2) == 0)
+   is_64 = false;
+   else if (strncmp(testname, "64", 2) == 0)
+   is_64 = true;
+   else
+   report_abort(USAGE);
+
+   if (strcmp(testname + 2, "-mem") == 0)
+   do_pabt = UNMAPPED_MEM;
+   else if (strcmp(testname + 2, "-io") == 0)
+   do_pabt = UNMAPPED_IO;
+   else
+   report_abort(USAGE);
+
+   report_prefix_push(av[1]);
+   pabtinj_test(is_64);
+
+   } else {
+   report_abort(USAGE);
+   }
+}
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
index ffd12e5794aa..61c437f169c8 100644
--- a/arm/unittests.cfg
+++ b/arm/unittests.cfg
@@ -51,3 +51,28 @@ file = selftest.flat
 smp = $MAX_SMP
 extra_params = -append 'smp'
 groups = selftest
+
+# Emulation tests
+[emul-pabt-injection-usr32-mem]
+file = emul-abort.flat
+extra_params = -append 'pabtinj-usr32-mem'
+arch = arm64
+groups = emulation mode32
+
+[emul-pabt-injection-usr64-mem]
+file = emul-abort.flat
+extra_params = -append 'pabtinj-usr64-mem'
+arch = arm64
+groups = emulation mode64
+
+[emul-pabt-injection-usr32-io]
+file = emul-abort.flat
+extra_params = -append 'pabtinj-usr32-io'
+arch = arm64
+groups = emulation mode32
+
+[emul-pabt-injection-usr64-io]
+file = emul-abort.flat
+extra_params = -append 'pabtinj-usr64-io'
+arch = arm64
+groups = emulation mode64
-- 
1.8.3.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 0/2] arm64: add pabt injection test

2016-07-22 Thread Andrew Jones
Get arm emulation tests kick started by adding a couple pabt injection
tests.

Andrew Jones (2):
  arm64: add start_usr32
  arm64: add pabt injection test

 arm/Makefile.arm64|  2 +-
 arm/emul-abort.c  | 95 +++
 arm/unittests.cfg | 25 +
 lib/arm64/asm/processor.h |  1 +
 lib/arm64/processor.c | 21 +--
 5 files changed, 139 insertions(+), 5 deletions(-)
 create mode 100644 arm/emul-abort.c

-- 
1.8.3.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 1/2] arm64: add start_usr32

2016-07-22 Thread Andrew Jones
Signed-off-by: Andrew Jones 
---
 lib/arm64/asm/processor.h |  1 +
 lib/arm64/processor.c | 21 +
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 84d5c7ce752b..22687851379a 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -79,6 +79,7 @@ DEFINE_GET_SYSREG32(mpidr)
 #define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff))
 
 extern void start_usr(void (*func)(void *arg), void *arg, unsigned long 
sp_usr);
+extern void start_usr32(void (*func)(void *arg), void *arg, unsigned long 
sp_usr);
 extern bool is_user(void);
 
 #endif /* !__ASSEMBLY__ */
diff --git a/lib/arm64/processor.c b/lib/arm64/processor.c
index deeab4ec9c8a..a18a29e06dc4 100644
--- a/lib/arm64/processor.c
+++ b/lib/arm64/processor.c
@@ -192,6 +192,8 @@ void vector_handlers_default_init(vector_fn *handlers)
handlers[EL1H_IRQ]  = default_vector_irq_handler;
handlers[EL0_SYNC_64]   = default_vector_sync_handler;
handlers[EL0_IRQ_64]= default_vector_irq_handler;
+   handlers[EL0_SYNC_32]   = default_vector_sync_handler;
+   handlers[EL0_IRQ_32]= default_vector_irq_handler;
 }
 
 void do_handle_exception(enum vector v, struct pt_regs *regs, unsigned int esr)
@@ -233,7 +235,8 @@ void thread_info_init(struct thread_info *ti, unsigned int 
flags)
vector_handlers_default_init(ti->vector_handlers);
 }
 
-void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr)
+static void __start_usr(void (*func)(void *arg), void *arg,
+   unsigned long sp_usr, unsigned int spsr)
 {
sp_usr &= (~15UL); /* stack ptr needs 16-byte alignment */
 
@@ -243,10 +246,20 @@ void start_usr(void (*func)(void *arg), void *arg, 
unsigned long sp_usr)
"movx0, %0\n"
"msrsp_el0, %1\n"
"msrelr_el1, %2\n"
-   "movx3, xzr\n"  /* clear and "set" PSR_MODE_EL0t */
-   "msrspsr_el1, x3\n"
+   "msrspsr_el1, %3\n"
+   "isb\n"
"eret\n"
-   :: "r" (arg), "r" (sp_usr), "r" (func) : "x0", "x3");
+   :: "r" (arg), "r" (sp_usr), "r" (func), "r" (spsr) : "x0");
+}
+
+void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr)
+{
+   __start_usr(func, arg, sp_usr, 0);
+}
+
+void start_usr32(void (*func)(void *arg), void *arg, unsigned long sp_usr)
+{
+   __start_usr(func, arg, sp_usr, PSR_MODE32_BIT);
 }
 
 bool is_user(void)
-- 
1.8.3.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: KVM on ARM crashes with new VGIC v4.7-rc7

2016-07-22 Thread Andrew Jones
On Fri, Jul 22, 2016 at 11:42:02AM +0100, Andre Przywara wrote:
> Hi Stefan,
> 
> On 22/07/16 06:57, Stefan Agner wrote:
> > Hi,
> > 
> > I tried KVM on a Cortex-A7 platform (i.MX 7Dual SoC) and encountered
> > this stack trace immediately after invoking qemu-system-arm:
> > 
> > Unable to handle kernel paging request at virtual address ffe4
> > pgd = 8ca52740
> > [ffe4] *pgd=8080007003, *pmd=8ff7e003, *pte=
> > Internal error: Oops: 207 [#1] SMP ARM
> > Modules linked in:  
> > CPU: 0 PID: 329 Comm: qemu-system-arm Tainted: GW  
> > 4.7.0-rc7-00094-gea3ed2c #109
> > Hardware name: Freescale i.MX7 Dual (Device Tree)
> > task: 8ca3ee40 ti: 8d2b task.ti: 8d2b
> > PC is at do_raw_spin_lock+0x8/0x1dc
> > LR is at kvm_vgic_flush_hwstate+0x8c/0x224
> > pc : [<8027c87c>]lr : [<802172d4>]psr: 60070013
> > sp : 8d2b1e38  ip : 8d2b  fp : 0001
> > r10: 8d2b  r9 : 0001  r8 : 8d2b8e54
> > fec 30be.ethernet eth0: MDIO read timeout
> > r7 : 8d2b8000  r6 : 8d2b8e74  r5 :   r4 : ffe0
> > r3 : 4ead  r2 :   r1 :   r0 : ffe0
> > Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
> > Control: 30c5387d  Table: 8ca52740  DAC: fffd
> > Process qemu-system-arm (pid: 329, stack limit = 0x8d2b0210)
> > Stack: (0x8d2b1e38 to 0x8d2b2000)
> > 1e20:   ffe0
> > 
> > 1e40: 8d2b8e74 8d2b8000 8d2b8e54 0001 8d2b 802172d4 8d2b8000
> > 810074f8
> > 1e60: 81007508 8ca5f800 8d284000 0001 8d2b 8020fbd4 8ce9a000
> > 8ca5f800
> > 1e80:  0001  00ff 8d284000  
> > 7ffbfeff
> > 1ea0: fffe  8d28b780  755fec6c  
> > e000
> > 1ec0: 8d2b8000  8d28b780  755fec6c 8020af90 
> > 8023f248
> > 1ee0: 000a 755fe98c 8d2b1f08 0008 8021aa84 e000 
> > 
> > 1f00: 8a00d860 8d28b780 80334f94  8d2b 80334748 
> > 
> > 1f20:  8d28b780 4000 0009 8d28b500 0024 8104ebee
> > 80bc2ec4
> > 1f40: 80bafa24 8034138c   80341248  755fec6c
> > 007c1e70
> > 1f60: 0009 4258 ae80 8d28b781 0009 8d28b780 ae80
> > 
> > 1f80: 8d2b  755fec6c 80334f94 007c1e70 322a7400 4258
> > 0036
> > 1fa0: 8021aa84 8021a900 007c1e70 322a7400 0009 ae80 
> > 755feac0
> > 1fc0: 007c1e70 322a7400 4258 0036 7e9aff58 01151da4 76f8b4c0
> > 755fec6c
> > 1fe0: 0038192c 755fea9c 00048ae7 7697d66c 60070010 0009 
> > 
> > [<8027c87c>] (do_raw_spin_lock) from [<802172d4>]
> > (kvm_vgic_flush_hwstate+0x8c/0x224)
> > [<802172d4>] (kvm_vgic_flush_hwstate) from [<8020fbd4>]
> > (kvm_arch_vcpu_ioctl_run+0x110/0x478)
> > [<8020fbd4>] (kvm_arch_vcpu_ioctl_run) from [<8020af90>]
> > (kvm_vcpu_ioctl+0x2e0/0x6d4)
> > [<8020af90>] (kvm_vcpu_ioctl) from [<80334748>]
> > (do_vfs_ioctl+0xa0/0x8b8)
> > [<80334748>] (do_vfs_ioctl) from [<80334f94>] (SyS_ioctl+0x34/0x5c)
> > [<80334f94>] (SyS_ioctl) from [<8021a900>] (ret_fast_syscall+0x0/0x1c)
> > Code: e49de004 ea09ea24 e92d47f0 e3043ead (e5902004)
> > ---[ end trace cb88537fdc8fa206 ]---
> > 
> > I use CONFIG_KVM_NEW_VGIC=y. This happens to me with a rather minimal
> > qemu invocation (qemu-system-arm -enable-kvm -M virt -cpu host
> > -nographic -serial stdio -kernel zImage).
> > 
> > Using a bit older Qemu version 2.4.0.
> 
> I just tried with a self compiled QEMU 2.4.0 and the Ubuntu 14.04
> provided 2.0.0, it worked fine with Linus' current HEAD as a host kernel
> on a Midway (Cortex-A15).

I can reproduce the issue with a latest QEMU build on AMD Seattle
(I haven't tried anywhere else yet)

> 
> Can you try to disable the new VGIC, just to see if that's a regression?

Disabling NEW_VGIC "fixes" guest boots.

I'm not using defconfig for my host kernel. I'll do a couple more
tests and provide a comparison of my config vs. a defconfig in
a few minutes.

drew
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH] arm64: kvm: set cpsr before spsr on fault injection

2016-07-22 Thread Andrew Jones
We need to set cpsr before determining the spsr bank, as the bank
depends on the target exception level of the injection, not the
current mode of the vcpu. Normally this is one in the same (EL1),
but not when we manage to trap an EL0 fault. It still doesn't really
matter for the 64-bit EL0 case though, as vcpu_spsr() unconditionally
uses the EL1 bank for that. However the 32-bit EL0 case gets fun, as
that path will lead to the BUG() in vcpu_spsr32()

This patch fixes the assignment order and also modifies some white
space in order to better group pairs of lines that have strict order.

Signed-off-by: Andrew Jones 
---
 arch/arm64/kvm/inject_fault.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index e9e0e6db73f6..898c0e6aedd4 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -132,16 +132,14 @@ static u64 get_except_vector(struct kvm_vcpu *vcpu, enum 
exception_type type)
 static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long 
addr)
 {
unsigned long cpsr = *vcpu_cpsr(vcpu);
-   bool is_aarch32;
+   bool is_aarch32 = vcpu_mode_is_32bit(vcpu);
u32 esr = 0;
 
-   is_aarch32 = vcpu_mode_is_32bit(vcpu);
-
-   *vcpu_spsr(vcpu) = cpsr;
*vcpu_elr_el1(vcpu) = *vcpu_pc(vcpu);
-
*vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
+
*vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64;
+   *vcpu_spsr(vcpu) = cpsr;
 
vcpu_sys_reg(vcpu, FAR_EL1) = addr;
 
@@ -172,11 +170,11 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
unsigned long cpsr = *vcpu_cpsr(vcpu);
u32 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT);
 
-   *vcpu_spsr(vcpu) = cpsr;
*vcpu_elr_el1(vcpu) = *vcpu_pc(vcpu);
-
*vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
+
*vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64;
+   *vcpu_spsr(vcpu) = cpsr;
 
/*
 * Build an unknown exception, depending on the instruction
-- 
1.8.3.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [RFC v8 5/7] KVM: arm/arm64: Enable irqchip routing

2016-07-22 Thread Radim Krčmář
2016-07-22 13:46+, Eric Auger:
> This patch adds compilation and link against irqchip.
> 
> Main motivation behind using irqchip code is to enable MSI
> routing code. In the future irqchip routing may also be useful
> when targeting multiple irqchips.
> 
> Routing standard callbacks now are implemented in vgic-irqfd:
> - kvm_set_routing_entry
> - kvm_set_irq
> - kvm_set_msi
> 
> They only are supported with new_vgic code.
> 
> Both HAVE_KVM_IRQCHIP and HAVE_KVM_IRQ_ROUTING are defined.
> KVM_CAP_IRQ_ROUTING is advertised and KVM_SET_GSI_ROUTING is allowed.
> 
> So from now on IRQCHIP routing is enabled and a routing table entry
> must exist for irqfd injection to succeed for a given SPI. This patch
> builds a default flat irqchip routing table (gsi=irqchip.pin) covering
> all the VGIC SPI indexes. This routing table is overwritten by the
> first first user-space call to KVM_SET_GSI_ROUTING ioctl.
> 
> MSI routing setup is not yet allowed.
> 
> Signed-off-by: Eric Auger 
> 
> ---
> diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
> @@ -17,36 +17,101 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include "vgic.h"
>  
> -int kvm_irq_map_gsi(struct kvm *kvm,
> - struct kvm_kernel_irq_routing_entry *entries,
> - int gsi)
> +/**
> + * vgic_irqfd_set_irq: inject the IRQ corresponding to the
> + * irqchip routing entry
> + *
> + * This is the entry point for irqfd IRQ injection
> + */
> +static int vgic_irqfd_set_irq(struct kvm_kernel_irq_routing_entry *e,
> + struct kvm *kvm, int irq_source_id,
> + int level, bool line_status)
>  {
> - return 0;
> + unsigned int spi_id = e->irqchip.pin + VGIC_NR_PRIVATE_IRQS;
> + struct vgic_dist *dist = >arch.vgic;
> +
> + if (spi_id > min(dist->nr_spis, VGIC_MAX_SPI))

This is more strict that vgic_valid_spi(), because spi_id between
"dist->nr_spis" and "dist->nr_spis + VGIC_NR_PRIVATE_IRQS" is not
allowed, which probably wasn't intended.

And shouldn't nr_spis always be less that VGIC_MAX_SPI?

Thanks.

> + return -EINVAL;
> + return kvm_vgic_inject_irq(kvm, 0, spi_id, level);
>  }
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [RFC v7 7/7] KVM: arm: enable KVM_SIGNAL_MSI and MSI routing

2016-07-22 Thread Auger Eric


On 22/07/2016 15:56, Radim Krčmář wrote:
> 2016-07-22 15:52+0200, Auger Eric:
>> On 22/07/2016 15:39, Radim Krčmář wrote:
>>> 2016-07-21 23:10+0200, Auger Eric:
 On 21/07/2016 18:33, Radim Krčmář wrote:
> 2016-07-18 13:25+, Eric Auger:
>> If the ITS modality is not available, let's simply support MSI
>> injection by transforming the MSI.data into an SPI ID.
>>
>> This becomes possible to use KVM_SIGNAL_MSI ioctl and MSI
>> routing for arm too.
>>
>> Signed-off-by: Eric Auger 
>>
>> ---
>> diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c 
>> b/virt/kvm/arm/vgic/vgic-irqfd.c
>> +static int vgic_v2m_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
>> +{
>> +if (msi->flags & KVM_MSI_VALID_DEVID)
>> +return -EINVAL;
>> +if (!vgic_valid_spi(kvm, msi->data))
>> +return -EINVAL;
>> +
>> +return kvm_vgic_inject_irq(kvm, 0, msi->data, 1);
>
> Hm, this isn't very MSI related ...
>
> arm already has KVM_IRQ_LINE/kvm_vm_ioctl_irq_line with
> KVM_ARM_IRQ_TYPE_SPI that does
>   kvm_vgic_inject_irq(kvm, 0, irq_num, level)
>
> Is that interface lacking?

 You mean KVM_SIGNAL_MSI? Well at QEMU level, for ARM/ARM64 is doesn't.
>>>
>>> No, I meant KVM_IRQ_LINE, the one that is used to deliver SPI today.
>>> Or isn't it?
>>>
 For kvm-tools I guess, Andre manages without.

 My first feeling was it is part of the KVM API and we can implement it
 easily for GICv2M, as we do for GICv3 ITS . This can avoid a user app to
 do what QEMU implements as "kvm_gsi_direct_mapping" and manage the
 translation into the semantic of the ARM GSI.
>>>
>>> I think that reusing KVM_SIGNAL_MSI and KVM_IRQ_ROUTING_MSI for SPI is
>>> unfortunate.
>>>
>>> SPI only uses msi.data, which makes remaining fields in the msi struct
>>> arbitrary and [5/7] defined KVM_IRQ_ROUTING_IRQCHIP for SPI, so two
>>> route types now do the same, but only sometimes (without ITS), which
>>> makes the situation even less understandable ...
>>>
>>> Delivering SPI as KVM_IRQ_ROUTING_IRQCHIP seems more sensible and if we
>>> wanted ad-hoc delivery of KVM_IRQ_ROUTING_IRQCHIP, then I would prefer a
>>> new interface to two different meanings for KVM_SIGNAL_MSI:
>>> KVM_SIGNAL_MSI was created because we didn't have anything that could
>>> inject an interrupt without setting up a route with KVM_SET_GSI_ROUTING
>>> and we are still missing a generic interface to do that.
>>>
 But Well, if you prefer we do not implement it for GICv2M, since
 considered as far fetched I can remove this patch.
>>>
>>> I do, thanks.  Documentation in [6/7] was ahead and needs changing then.
>>
>> Argh just saw your reply after sending v8. Will respin immediatly.
>>
>> Sorry for the confusion
> 
> No problem.  Give me half an hour for a review, please. :)
Sure

Eric
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [RFC v7 7/7] KVM: arm: enable KVM_SIGNAL_MSI and MSI routing

2016-07-22 Thread Radim Krčmář
2016-07-22 15:52+0200, Auger Eric:
> On 22/07/2016 15:39, Radim Krčmář wrote:
>> 2016-07-21 23:10+0200, Auger Eric:
>>> On 21/07/2016 18:33, Radim Krčmář wrote:
 2016-07-18 13:25+, Eric Auger:
> If the ITS modality is not available, let's simply support MSI
> injection by transforming the MSI.data into an SPI ID.
>
> This becomes possible to use KVM_SIGNAL_MSI ioctl and MSI
> routing for arm too.
>
> Signed-off-by: Eric Auger 
>
> ---
> diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c 
> b/virt/kvm/arm/vgic/vgic-irqfd.c
> +static int vgic_v2m_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
> +{
> + if (msi->flags & KVM_MSI_VALID_DEVID)
> + return -EINVAL;
> + if (!vgic_valid_spi(kvm, msi->data))
> + return -EINVAL;
> +
> + return kvm_vgic_inject_irq(kvm, 0, msi->data, 1);

 Hm, this isn't very MSI related ...

 arm already has KVM_IRQ_LINE/kvm_vm_ioctl_irq_line with
 KVM_ARM_IRQ_TYPE_SPI that does
   kvm_vgic_inject_irq(kvm, 0, irq_num, level)

 Is that interface lacking?
>>>
>>> You mean KVM_SIGNAL_MSI? Well at QEMU level, for ARM/ARM64 is doesn't.
>> 
>> No, I meant KVM_IRQ_LINE, the one that is used to deliver SPI today.
>> Or isn't it?
>> 
>>> For kvm-tools I guess, Andre manages without.
>>>
>>> My first feeling was it is part of the KVM API and we can implement it
>>> easily for GICv2M, as we do for GICv3 ITS . This can avoid a user app to
>>> do what QEMU implements as "kvm_gsi_direct_mapping" and manage the
>>> translation into the semantic of the ARM GSI.
>> 
>> I think that reusing KVM_SIGNAL_MSI and KVM_IRQ_ROUTING_MSI for SPI is
>> unfortunate.
>> 
>> SPI only uses msi.data, which makes remaining fields in the msi struct
>> arbitrary and [5/7] defined KVM_IRQ_ROUTING_IRQCHIP for SPI, so two
>> route types now do the same, but only sometimes (without ITS), which
>> makes the situation even less understandable ...
>> 
>> Delivering SPI as KVM_IRQ_ROUTING_IRQCHIP seems more sensible and if we
>> wanted ad-hoc delivery of KVM_IRQ_ROUTING_IRQCHIP, then I would prefer a
>> new interface to two different meanings for KVM_SIGNAL_MSI:
>> KVM_SIGNAL_MSI was created because we didn't have anything that could
>> inject an interrupt without setting up a route with KVM_SET_GSI_ROUTING
>> and we are still missing a generic interface to do that.
>> 
>>> But Well, if you prefer we do not implement it for GICv2M, since
>>> considered as far fetched I can remove this patch.
>> 
>> I do, thanks.  Documentation in [6/7] was ahead and needs changing then.
> 
> Argh just saw your reply after sending v8. Will respin immediatly.
> 
> Sorry for the confusion

No problem.  Give me half an hour for a review, please. :)
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [RFC v7 7/7] KVM: arm: enable KVM_SIGNAL_MSI and MSI routing

2016-07-22 Thread Auger Eric
Hi Radim,

On 22/07/2016 15:39, Radim Krčmář wrote:
> 2016-07-21 23:10+0200, Auger Eric:
>> On 21/07/2016 18:33, Radim Krčmář wrote:
>>> 2016-07-18 13:25+, Eric Auger:
 If the ITS modality is not available, let's simply support MSI
 injection by transforming the MSI.data into an SPI ID.

 This becomes possible to use KVM_SIGNAL_MSI ioctl and MSI
 routing for arm too.

 Signed-off-by: Eric Auger 

 ---
 diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c 
 b/virt/kvm/arm/vgic/vgic-irqfd.c
 +static int vgic_v2m_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
 +{
 +  if (msi->flags & KVM_MSI_VALID_DEVID)
 +  return -EINVAL;
 +  if (!vgic_valid_spi(kvm, msi->data))
 +  return -EINVAL;
 +
 +  return kvm_vgic_inject_irq(kvm, 0, msi->data, 1);
>>>
>>> Hm, this isn't very MSI related ...
>>>
>>> arm already has KVM_IRQ_LINE/kvm_vm_ioctl_irq_line with
>>> KVM_ARM_IRQ_TYPE_SPI that does
>>>   kvm_vgic_inject_irq(kvm, 0, irq_num, level)
>>>
>>> Is that interface lacking?
>>
>> You mean KVM_SIGNAL_MSI? Well at QEMU level, for ARM/ARM64 is doesn't.
> 
> No, I meant KVM_IRQ_LINE, the one that is used to deliver SPI today.
> Or isn't it?
> 
>> For kvm-tools I guess, Andre manages without.
>>
>> My first feeling was it is part of the KVM API and we can implement it
>> easily for GICv2M, as we do for GICv3 ITS . This can avoid a user app to
>> do what QEMU implements as "kvm_gsi_direct_mapping" and manage the
>> translation into the semantic of the ARM GSI.
> 
> I think that reusing KVM_SIGNAL_MSI and KVM_IRQ_ROUTING_MSI for SPI is
> unfortunate.
> 
> SPI only uses msi.data, which makes remaining fields in the msi struct
> arbitrary and [5/7] defined KVM_IRQ_ROUTING_IRQCHIP for SPI, so two
> route types now do the same, but only sometimes (without ITS), which
> makes the situation even less understandable ...
> 
> Delivering SPI as KVM_IRQ_ROUTING_IRQCHIP seems more sensible and if we
> wanted ad-hoc delivery of KVM_IRQ_ROUTING_IRQCHIP, then I would prefer a
> new interface to two different meanings for KVM_SIGNAL_MSI:
> KVM_SIGNAL_MSI was created because we didn't have anything that could
> inject an interrupt without setting up a route with KVM_SET_GSI_ROUTING
> and we are still missing a generic interface to do that.
> 
>> But Well, if you prefer we do not implement it for GICv2M, since
>> considered as far fetched I can remove this patch.
> 
> I do, thanks.  Documentation in [6/7] was ahead and needs changing then.

Argh just saw your reply after sending v8. Will respin immediatly.

Sorry for the confusion

Thanks

Eric
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[RFC v8 3/7] KVM: irqchip: Convey devid to kvm_set_msi

2016-07-22 Thread Eric Auger
on ARM, a devid field is populated in kvm_msi struct in case the
flag is set to KVM_MSI_VALID_DEVID. Let's propagate both flags and
devid field in kvm_kernel_irq_routing_entry.

Signed-off-by: Eric Auger 
Reviewed-by: Andre Przywara 
Acked-by: Christoffer Dall 

---
v7 -> v8:
- adapt to changes in kvm_kernel_irq_routing_entry struct

v6 -> v7:
- use renamed msi_flags and msi_devid
- added Andre's R-b

v4 -> v5:
- Add Christoffer's R-b

v2 -> v3:
- do not set the type to KVM_IRQ_ROUTING_EXTENDED_MSI anymore as
  suggested by Andre
- correct msi->flags check
- propagate the flags
---
 virt/kvm/irqchip.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
index 8db197b..0c00054 100644
--- a/virt/kvm/irqchip.c
+++ b/virt/kvm/irqchip.c
@@ -62,12 +62,14 @@ int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi 
*msi)
 {
struct kvm_kernel_irq_routing_entry route;
 
-   if (!irqchip_in_kernel(kvm) || msi->flags != 0)
+   if (!irqchip_in_kernel(kvm) || (msi->flags & ~KVM_MSI_VALID_DEVID))
return -EINVAL;
 
route.msi.address_lo = msi->address_lo;
route.msi.address_hi = msi->address_hi;
route.msi.data = msi->data;
+   route.msi.flags = msi->flags;
+   route.msi.devid = msi->devid;
 
return kvm_set_msi(, kvm, KVM_USERSPACE_IRQ_SOURCE_ID, 1, false);
 }
-- 
1.9.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[RFC v8 0/7] KVM: arm/arm64: gsi routing support

2016-07-22 Thread Eric Auger
With the advent of GICv3 ITS in-kernel emulation, KVM MSI routing
becomes mandated for proper VIRTIO-PCI vhost integration.

In QEMU, when the VIRTIO-PCI device is programmed with the MSI message,
we previously used direct_mapping trick: this consists in extracting the
IRQ ID found in the MSI message and associating an irqfd to that IRQ ID.
When vhost worker thread gets a new buffer it signals the irqfd and kvm
then injects this IRQ ID on guest. That way although the guest uses MSIs,
no MSI emulation is used.

This worked fine with GICv2m but does not work anymore with GICV3 ITS.
Indeed this latter implements IRQ translation: what is found in the MSI
message no more is the target IRQ ID but is an intermediate event ID used
in the translation process.

Hence true MSI routing is needed so that the vhost back channel irqfd is
associated to a dummy gsi ID, routed towards the programmed MSI. When KVM
injects the MSI through the in-kernel ITS emulation, the MSI is properly
translated and eventually the LPI ID associated to the event ID is injected
on guest.

MSI routing also mandates to integrate irqchip routing. The initial
implementation of irqfd on arm must be upgraded with the integration
of kvm irqchip.c code and the implementation of its standard hooks
in the architecture specific part.

In case KVM_SET_GSI_ROUTING ioctl is not called, a default routing
table with flat irqchip routing entries is built enabling to inject gsi
corresponding to the SPI indexes seen by the guest.

As soon as KVM_SET_GSI_ROUTING is called, user-space overwrites this
default routing table and is responsible for building the whole routing
table.

for arm/arm64 KVM_SET_GSI_ROUTING has a limited support:
- only applies to KVM_IRQFD and not to KVM_IRQ_LINE

- irqchip routing was tested on Calxeda midway (VFIO with irqfd)
  with and without explicit routing
- MSI routing was tested on AMD Overdrive and Cavium ThunderX

Code + dependencies can be found at:
https://github.com/eauger/linux/tree/v4.7-rc7-its-emul-v10-gsi-routing-v8

The series depends on

[1]: [PATCH v10 00/17] KVM: arm64: GICv3 ITS emulation
 http://www.spinics.net/lists/kvm/msg135687.html
   + [PATCH] KVM: arm/arm64: fix vGICv2 KVM_DEV_ARM_VGIC_GRP_CPU/DIST_REGS
[2]: [PATCH] KVM: arm/arm64: The GIC is dead, long live the GIC

hence the RFC.

GSI flat routing setup on QEMU can be found at:
https://lists.nongnu.org/archive/html/qemu-devel/2015-07/msg06262.html

History:
v7 -> v8:
- take into account Radim's comments:
  x rework kvm_kernel_irq_routing_entry and remove msi_msg now
replaced by a custom struct
  x check user entry flags depending on user entry type
  x I kept last patch although challenged by Radim. It can be dropped
according to the consensus.

v6 -> v7:
- take into account Drew's and Andre's comments
- new patch moving declarations of kvm_setup_default_irq_routing and
  kvm_setup_empty_irq_routing outside of kvm_host.h
- vgic_v2m_inject_msi moved in vgic-irqfd
- re-introduce irq.h
- add msi_ prefix to flags/devid kvm_kernel_irq_routing_entry fields
- move kvm_vgic_setup_default_irq_routing declaration in arm_vgic.h
  and definition in vgic-irqfd.c
- remove BUG_ON(!vgic_initialized(kvm) in vgic_irqfd_set_irq
- move KVM_IRQCHIP_NUM_PINS in arm_vgic.h and use VGIC_MAX_SPI instead
  of 1020

v5 -> v6:
- rebase on Andre's v8 + removal of old vgic
- tested on Cavium ThunderX

V4 -> v5:
- rebase on Andre's v7 + final new vgic code
- check msi->data is within SPI range in vgic_v2m_inject_msi
- squashed enable irq routing and default irqchip table patches
- handle default irqchip table allocation failure
- some rephrasing in doc & comment according to Christoffer's feedbacks
- lock issue reported by Pavel seems to have disappear after 4.2 (MSI injection
  fast path)

v3 -> v4:
- rebase on top of NEW-VGIC RFC and ITS emulation series v4. This is not
  a stable foundation yet. Hence the revert to RFC. This v4 mostly is a
  reflesh/reminder.
- rewrite the cover letter

v2 -> v3:
- don't use KVM_IRQ_ROUTING_EXTENDED_MSI type at uapi and kernel level anymore;
  use KVM_MSI_VALID_DEVID flag instead
- propagate user flags downto the kernel to make sure the userspace
  correctly set devid in GICv3 ITS case (still under discussion)

v1 -> v2:
- user API changed:
  x devid id passed in kvm_irq_routing_msi
  x kept the new routing entry type: KVM_IRQ_ROUTING_EXTENDED_MSI
- kvm_host.h: adopt Andre's proposal to replace the msi_msg by a struct
  composed of the msi_msg and devid in kvm_kernel_irq_routing_entry
- Fix bug reported by Pavel: Added KVM_IRQ_ROUTING_EXTENDED_MSI handling
  in eventfd.c
- added vgic_v2m_inject_msi in vgic-v2-emul.c as suggested by Andre
- fix bug reported by Andre: bad setting of msi.flags and msi.devid
  in kvm_send_userspace_msi
- avoid injecting reserved IRQ numbers in vgic_irqfd_set_irq

RFC -> PATCH:
- clearly state limited support on arm/arm64:
  KVM_IRQ_LINE not impacted by GSI routing
- add default routing table feature (new patch 

[RFC v8 1/7] KVM: api: Pass the devid in the msi routing entry

2016-07-22 Thread Eric Auger
On ARM, the MSI msg (address and data) comes along with
out-of-band device ID information. The device ID encodes the
device that writes the MSI msg. Let's convey the device id in
kvm_irq_routing_msi and use KVM_MSI_VALID_DEVID flag value in
kvm_irq_routing_entry to indicate the msi devid is populated.

Signed-off-by: Eric Auger 
Reviewed-by: Andre Przywara 

---

v6 -> v7:
- Added Andre's R-b

v4 -> v5:
- some rephrasing in api.txt according to Christoffer's comments
v2 -> v3:
- replace usage of KVM_IRQ_ROUTING_EXTENDED_MSI type by
  usage of KVM_MSI_VALID_DEVID flag
- add note about KVM_CAP_MSI_DEVID capability

v1 -> v2:
- devid id passed in kvm_irq_routing_msi instead of in
  kvm_irq_routing_entry

RFC -> PATCH
- remove kvm_irq_routing_extended_msi and use union instead
---
 Documentation/virtual/kvm/api.txt | 19 +--
 include/uapi/linux/kvm.h  |  5 -
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/Documentation/virtual/kvm/api.txt 
b/Documentation/virtual/kvm/api.txt
index f60b137..0065c8e 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1468,7 +1468,11 @@ struct kvm_irq_routing_entry {
 #define KVM_IRQ_ROUTING_S390_ADAPTER 3
 #define KVM_IRQ_ROUTING_HV_SINT 4
 
-No flags are specified so far, the corresponding field must be set to zero.
+flags:
+- KVM_MSI_VALID_DEVID: used along with KVM_IRQ_ROUTING_MSI
+  routing entry type, specifies that the devid field contains
+  a valid value.
+- zero otherwise
 
 struct kvm_irq_routing_irqchip {
__u32 irqchip;
@@ -1479,9 +1483,20 @@ struct kvm_irq_routing_msi {
__u32 address_lo;
__u32 address_hi;
__u32 data;
-   __u32 pad;
+   union {
+   __u32 pad;
+   __u32 devid;
+   };
 };
 
+devid: If KVM_MSI_VALID_DEVID is set, contains a unique device identifier
+   for the device that wrote the MSI message.
+   For PCI, this is usually a BFD identifier in the lower 16 bits.
+
+The per-VM KVM_CAP_MSI_DEVID capability advertises the requirement to
+provide the device ID. If this capability is not set, userland cannot
+rely on the kernel to allow the KVM_MSI_VALID_DEVID flag being set.
+
 struct kvm_irq_routing_s390_adapter {
__u64 ind_addr;
__u64 summary_addr;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index d8c4c32..eb22208 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -879,7 +879,10 @@ struct kvm_irq_routing_msi {
__u32 address_lo;
__u32 address_hi;
__u32 data;
-   __u32 pad;
+   union {
+   __u32 pad;
+   __u32 devid;
+   };
 };
 
 struct kvm_irq_routing_s390_adapter {
-- 
1.9.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[RFC v8 5/7] KVM: arm/arm64: Enable irqchip routing

2016-07-22 Thread Eric Auger
This patch adds compilation and link against irqchip.

Main motivation behind using irqchip code is to enable MSI
routing code. In the future irqchip routing may also be useful
when targeting multiple irqchips.

Routing standard callbacks now are implemented in vgic-irqfd:
- kvm_set_routing_entry
- kvm_set_irq
- kvm_set_msi

They only are supported with new_vgic code.

Both HAVE_KVM_IRQCHIP and HAVE_KVM_IRQ_ROUTING are defined.
KVM_CAP_IRQ_ROUTING is advertised and KVM_SET_GSI_ROUTING is allowed.

So from now on IRQCHIP routing is enabled and a routing table entry
must exist for irqfd injection to succeed for a given SPI. This patch
builds a default flat irqchip routing table (gsi=irqchip.pin) covering
all the VGIC SPI indexes. This routing table is overwritten by the
first first user-space call to KVM_SET_GSI_ROUTING ioctl.

MSI routing setup is not yet allowed.

Signed-off-by: Eric Auger 

---
v7 -> v8:
- adapt to changes in kvm_kernel_irq_routing_entry

v6 -> v7:
- re-introduce irq.h
- use kvm_kernel_irq_routing_entry renamed fields: msi_flags, msi_devid
- moved kvm_vgic_setup_default_irq_routing declaration in arm_vgic.h and
  definition in vgic-irqfd.c
- correct double / in Makefile
- remove BUG_ON(!vgic_initialized(kvm) in vgic_irqfd_set_irq since
  in any case we have a lazy_init in update_irq_pending
- move KVM_IRQCHIP_NUM_PINS in arm_vgic.h
- use VGIC_MAX_SPI

v5 -> v6:
- rebase on top of Andre's v8 + removal of old vgic

v4 -> v5:
- vgic_irqfd.c was renamed into vgic-irqfd.c by Andre
- minor comment changes
- remove trace_kvm_set_irq since it is called in irqchip
- remove CONFIG_HAVE_KVM_MSI setting (done in KVM section)
- despite Christoffer's question, in kvm_set_msi, I kept the copy from
  the input "struct kvm_kernel_irq_routing_entry *e" imposed by the
  irqchip callback API into the struct kvm_msi * passed to
  vits_inject_msi. Since vits_inject_msi is directly called by
  kvm_send_userspace_msi which takes a struct kvm_msi*, makes sense
  to me to keep the copy.
- squash former [PATCH v4 5/7] KVM: arm/arm64: build a default routing
  table into that patch
- handle default routing table alloc failure

v3 -> v4:
- provide support only for new-vgic
- code previously in vgic.c now in vgic_irqfd.c

v2 -> v3:
- unconditionally set devid and KVM_MSI_VALID_DEVID flag as suggested
  by Andre (KVM_IRQ_ROUTING_EXTENDED_MSI type not used anymore)
- vgic_irqfd_set_irq now is static
- propagate flags
- add comments

v1 -> v2:
- fix bug reported by Andre related to msi.flags and msi.devid setting
  in kvm_send_userspace_msi
- avoid injecting reserved IRQ numbers in vgic_irqfd_set_irq

RFC -> PATCH
- reword api.txt:
  x move MSI routing comments in a subsequent patch,
  x clearly state GSI routing does not apply to KVM_IRQ_LINE
---
 Documentation/virtual/kvm/api.txt |  12 +++--
 arch/arm/kvm/Kconfig  |   2 +
 arch/arm/kvm/Makefile |   1 +
 arch/arm/kvm/irq.h|  19 +++
 arch/arm64/kvm/Kconfig|   2 +
 arch/arm64/kvm/Makefile   |   1 +
 arch/arm64/kvm/irq.h  |  19 +++
 include/kvm/arm_vgic.h|   7 +++
 virt/kvm/arm/vgic/vgic-init.c |   4 ++
 virt/kvm/arm/vgic/vgic-irqfd.c| 101 +++---
 virt/kvm/arm/vgic/vgic.c  |   7 ---
 11 files changed, 146 insertions(+), 29 deletions(-)
 create mode 100644 arch/arm/kvm/irq.h
 create mode 100644 arch/arm64/kvm/irq.h

diff --git a/Documentation/virtual/kvm/api.txt 
b/Documentation/virtual/kvm/api.txt
index 0065c8e..3bb60d3 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1433,13 +1433,16 @@ KVM_ASSIGN_DEV_IRQ. Partial deassignment of host or 
guest IRQ is allowed.
 4.52 KVM_SET_GSI_ROUTING
 
 Capability: KVM_CAP_IRQ_ROUTING
-Architectures: x86 s390
+Architectures: x86 s390 arm arm64
 Type: vm ioctl
 Parameters: struct kvm_irq_routing (in)
 Returns: 0 on success, -1 on error
 
 Sets the GSI routing table entries, overwriting any previously set entries.
 
+On arm/arm64, GSI routing has the following limitation:
+- GSI routing does not apply to KVM_IRQ_LINE but only to KVM_IRQFD.
+
 struct kvm_irq_routing {
__u32 nr;
__u32 flags;
@@ -2368,9 +2371,10 @@ Note that closing the resamplefd is not sufficient to 
disable the
 irqfd.  The KVM_IRQFD_FLAG_RESAMPLE is only necessary on assignment
 and need not be specified with KVM_IRQFD_FLAG_DEASSIGN.
 
-On ARM/ARM64, the gsi field in the kvm_irqfd struct specifies the Shared
-Peripheral Interrupt (SPI) index, such that the GIC interrupt ID is
-given by gsi + 32.
+On arm/arm64, gsi routing being supported, the following can happen:
+- in case no routing entry is associated to this gsi, injection fails
+- in case the gsi is associated to an irqchip routing entry,
+  irqchip.pin + 32 corresponds to the injected SPI ID.
 
 4.76 KVM_PPC_ALLOCATE_HTAB
 
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 

[RFC v8 2/7] KVM: Add devid in kvm_kernel_irq_routing_entry

2016-07-22 Thread Eric Auger
Enhance kvm_kernel_irq_routing_entry to transport the device id
field, devid. A new flags field makes possible to indicate the
devid is valid. Those additions are used for ARM GICv3 ITS MSI
injection. The original struct msi_msg msi field is replaced by
a new custom structure that embeds the new fields.

Signed-off-by: Eric Auger 
Suggested-by: Radim Krčmář 

---
v7 -> v8:
- replace struct msi_msg by a new custom structure
- removed Christoffer's A-b

v6 -> v7:
- added msi_ prefix to flags and dev_id fields

v4 -> v5:
- add Christoffer's R-b

v2 -> v3:
- add flags

v1 -> v2:
- replace msi_msg field by a struct composed of msi_msg and devid

RFC -> PATCH:
- reword the commit message after change in first patch (uapi)
---
 include/linux/kvm_host.h | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index c87fe6f..e33e85e 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -317,7 +317,13 @@ struct kvm_kernel_irq_routing_entry {
unsigned irqchip;
unsigned pin;
} irqchip;
-   struct msi_msg msi;
+   struct {
+   u32 address_lo;
+   u32 address_hi;
+   u32 data;
+   u32 flags;
+   u32 devid;
+   } msi;
struct kvm_s390_adapter_int adapter;
struct kvm_hv_sint hv_sint;
};
-- 
1.9.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[RFC v8 4/7] KVM: Move kvm_setup_default/empty_irq_routing declaration in arch specific header

2016-07-22 Thread Eric Auger
kvm_setup_default_irq_routing and kvm_setup_empty_irq_routing are
not used by generic code. So let's move the declarations in x86 irq.h
header instead of kvm_host.h.

Signed-off-by: Eric Auger 
Suggested-by: Andre Przywara 

---

- new patch in v7
---
 arch/x86/kvm/irq.h   | 3 +++
 include/linux/kvm_host.h | 2 --
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index 61ebdc1..035731e 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -120,4 +120,7 @@ void __kvm_migrate_timers(struct kvm_vcpu *vcpu);
 
 int apic_has_pending_timer(struct kvm_vcpu *vcpu);
 
+int kvm_setup_default_irq_routing(struct kvm *kvm);
+int kvm_setup_empty_irq_routing(struct kvm *kvm);
+
 #endif
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index e33e85e..49e8152 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1044,8 +1044,6 @@ static inline int mmu_notifier_retry(struct kvm *kvm, 
unsigned long mmu_seq)
 #define KVM_MAX_IRQ_ROUTES 1024
 #endif
 
-int kvm_setup_default_irq_routing(struct kvm *kvm);
-int kvm_setup_empty_irq_routing(struct kvm *kvm);
 int kvm_set_irq_routing(struct kvm *kvm,
const struct kvm_irq_routing_entry *entries,
unsigned nr,
-- 
1.9.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[RFC v8 7/7] KVM: arm: Enable KVM_SIGNAL_MSI and MSI routing

2016-07-22 Thread Eric Auger
If the ITS modality is not available, let's simply support MSI
injection by transforming the MSI.data into an SPI ID.

This becomes possible to use KVM_SIGNAL_MSI ioctl and MSI
routing for arm too.

Signed-off-by: Eric Auger 

---

v6 -> v7:
- move vgic_v2m_inject_msi into vgic-irqfd

v4 -> v5:
- on vgic_v2m_inject_msi check the msi->data is within the SPI range
- move KVM_HAVE_MSI in the KVM section (to be symetrical with ARM64)

v2 -> v3:
- reword the commit message
- add sanity check about devid provision

v1 -> v2:
- introduce vgic_v2m_inject_msi in vgic-v2-emul.c following Andre's
  advice
---
 arch/arm/kvm/Kconfig   |  1 +
 virt/kvm/arm/vgic/vgic-irqfd.c | 19 ++-
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 3e1cd04..90d0176 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -34,6 +34,7 @@ config KVM
select HAVE_KVM_IRQFD
select HAVE_KVM_IRQCHIP
select HAVE_KVM_IRQ_ROUTING
+   select HAVE_KVM_MSI
depends on ARM_VIRT_EXT && ARM_LPAE && ARM_ARCH_TIMER
---help---
  Support hosting virtualized guest machines.
diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
index 04ce19f..67fb3f3 100644
--- a/virt/kvm/arm/vgic/vgic-irqfd.c
+++ b/virt/kvm/arm/vgic/vgic-irqfd.c
@@ -77,6 +77,23 @@ out:
 }
 
 /**
+ * vgic_v2m_inject_msi: emulates GICv2M MSI injection by injecting
+ * the SPI ID matching the msi data
+ *
+ * @kvm: pointer to the kvm struct
+ * @msi: the msi struct handle
+ */
+static int vgic_v2m_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
+{
+   if (msi->flags & KVM_MSI_VALID_DEVID)
+   return -EINVAL;
+   if (!vgic_valid_spi(kvm, msi->data))
+   return -EINVAL;
+
+   return kvm_vgic_inject_irq(kvm, 0, msi->data, 1);
+}
+
+/**
  * kvm_set_msi: inject the MSI corresponding to the
  * MSI routing entry
  *
@@ -96,7 +113,7 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
msi.devid = e->msi.devid;
 
if (!vgic_has_its(kvm))
-   return -ENODEV;
+   return vgic_v2m_inject_msi(kvm, );
 
return vgic_its_inject_msi(kvm, );
 }
-- 
1.9.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[RFC v8 6/7] KVM: arm/arm64: Enable MSI routing

2016-07-22 Thread Eric Auger
Up to now, only irqchip routing entries could be set. This patch
adds the capability to insert MSI routing entries.

For ARM64, let's also increase KVM_MAX_IRQ_ROUTES to 4096: this
include SPI irqchip routes plus MSI routes. In the future this
might be extended.

Signed-off-by: Eric Auger 
Reviewed-by: Andre Przywara 

---
v7 -> v8:
- adapt to changes in kvm_kernel_irq_routing_entry and check the
  user entry flags according to the user entry type

v6 -> v7:
- added Andre's R-b

v2 -> v3:
- remove any reference to KVM_IRQ_ROUTING_EXTENDED_MSI type
- unconditionnaly uapi flags and devid downto the kernel
  routing entry struct
- handle KVM_MSI_VALID_DEVID flag in kvm_set_irq_routing
- note about KVM_CAP_MSI_DEVID moved in the first patch file
  of the series

v1 -> v2:
- adapt to new routing entry types

RFC -> PATCH:
- move api MSI routing updates into that patch file
- use new devid field of user api struct
---
 Documentation/virtual/kvm/api.txt |  5 +
 include/linux/kvm_host.h  |  2 ++
 virt/kvm/arm/vgic/vgic-irqfd.c|  8 
 virt/kvm/irqchip.c| 24 +++-
 4 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/Documentation/virtual/kvm/api.txt 
b/Documentation/virtual/kvm/api.txt
index 3bb60d3..60d4999 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2375,6 +2375,11 @@ On arm/arm64, gsi routing being supported, the following 
can happen:
 - in case no routing entry is associated to this gsi, injection fails
 - in case the gsi is associated to an irqchip routing entry,
   irqchip.pin + 32 corresponds to the injected SPI ID.
+- in case the gsi is associated to an MSI routing entry,
+  * without GICv3 ITS in-kernel emulation, MSI data matches the SPI ID
+of the injected SPI
+  * with GICv3 ITS in-kernel emulation, the MSI message and device ID
+are translated into an LPI.
 
 4.76 KVM_PPC_ALLOCATE_HTAB
 
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 49e8152..9fa4bc2 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1040,6 +1040,8 @@ static inline int mmu_notifier_retry(struct kvm *kvm, 
unsigned long mmu_seq)
 
 #ifdef CONFIG_S390
 #define KVM_MAX_IRQ_ROUTES 4096 //FIXME: we can have more than that...
+#elif defined(CONFIG_ARM64)
+#define KVM_MAX_IRQ_ROUTES 4096
 #else
 #define KVM_MAX_IRQ_ROUTES 1024
 #endif
diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
index 77be112..04ce19f 100644
--- a/virt/kvm/arm/vgic/vgic-irqfd.c
+++ b/virt/kvm/arm/vgic/vgic-irqfd.c
@@ -60,6 +60,14 @@ int kvm_set_routing_entry(struct 
kvm_kernel_irq_routing_entry *e,
(e->irqchip.irqchip >= KVM_NR_IRQCHIPS))
goto out;
break;
+   case KVM_IRQ_ROUTING_MSI:
+   e->set = kvm_set_msi;
+   e->msi.address_lo = ue->u.msi.address_lo;
+   e->msi.address_hi = ue->u.msi.address_hi;
+   e->msi.data = ue->u.msi.data;
+   e->msi.flags = ue->flags;
+   e->msi.devid = ue->u.msi.devid;
+   break;
default:
goto out;
}
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
index 0c00054..349ea6d 100644
--- a/virt/kvm/irqchip.c
+++ b/virt/kvm/irqchip.c
@@ -178,6 +178,7 @@ int kvm_set_irq_routing(struct kvm *kvm,
unsigned flags)
 {
struct kvm_irq_routing_table *new, *old;
+   struct kvm_kernel_irq_routing_entry *e;
u32 i, j, nr_rt_entries = 0;
int r;
 
@@ -201,23 +202,25 @@ int kvm_set_irq_routing(struct kvm *kvm,
new->chip[i][j] = -1;
 
for (i = 0; i < nr; ++i) {
-   struct kvm_kernel_irq_routing_entry *e;
-
r = -ENOMEM;
e = kzalloc(sizeof(*e), GFP_KERNEL);
if (!e)
goto out;
 
r = -EINVAL;
-   if (ue->flags) {
-   kfree(e);
-   goto out;
+   switch (ue->type) {
+   case KVM_IRQ_ROUTING_IRQCHIP:
+   if (ue->flags)
+   goto free_entry;
+   break;
+   case KVM_IRQ_ROUTING_MSI:
+   if (ue->flags & ~KVM_MSI_VALID_DEVID)
+   goto free_entry;
+   break;
}
r = setup_routing_entry(new, e, ue);
-   if (r) {
-   kfree(e);
-   goto out;
-   }
+   if (r)
+   goto free_entry;
++ue;
}
 
@@ -234,7 +237,10 @@ int kvm_set_irq_routing(struct kvm *kvm,
 
new = old;
r = 0;
+   goto out;
 
+free_entry:
+   kfree(e);
 out:
free_irq_routing_table(new);
 
-- 
1.9.1


Re: [RFC v7 7/7] KVM: arm: enable KVM_SIGNAL_MSI and MSI routing

2016-07-22 Thread Radim Krčmář
2016-07-21 23:10+0200, Auger Eric:
> On 21/07/2016 18:33, Radim Krčmář wrote:
>> 2016-07-18 13:25+, Eric Auger:
>>> If the ITS modality is not available, let's simply support MSI
>>> injection by transforming the MSI.data into an SPI ID.
>>>
>>> This becomes possible to use KVM_SIGNAL_MSI ioctl and MSI
>>> routing for arm too.
>>>
>>> Signed-off-by: Eric Auger 
>>>
>>> ---
>>> diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
>>> +static int vgic_v2m_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
>>> +{
>>> +   if (msi->flags & KVM_MSI_VALID_DEVID)
>>> +   return -EINVAL;
>>> +   if (!vgic_valid_spi(kvm, msi->data))
>>> +   return -EINVAL;
>>> +
>>> +   return kvm_vgic_inject_irq(kvm, 0, msi->data, 1);
>> 
>> Hm, this isn't very MSI related ...
>> 
>> arm already has KVM_IRQ_LINE/kvm_vm_ioctl_irq_line with
>> KVM_ARM_IRQ_TYPE_SPI that does
>>   kvm_vgic_inject_irq(kvm, 0, irq_num, level)
>> 
>> Is that interface lacking?
> 
> You mean KVM_SIGNAL_MSI? Well at QEMU level, for ARM/ARM64 is doesn't.

No, I meant KVM_IRQ_LINE, the one that is used to deliver SPI today.
Or isn't it?

> For kvm-tools I guess, Andre manages without.
> 
> My first feeling was it is part of the KVM API and we can implement it
> easily for GICv2M, as we do for GICv3 ITS . This can avoid a user app to
> do what QEMU implements as "kvm_gsi_direct_mapping" and manage the
> translation into the semantic of the ARM GSI.

I think that reusing KVM_SIGNAL_MSI and KVM_IRQ_ROUTING_MSI for SPI is
unfortunate.

SPI only uses msi.data, which makes remaining fields in the msi struct
arbitrary and [5/7] defined KVM_IRQ_ROUTING_IRQCHIP for SPI, so two
route types now do the same, but only sometimes (without ITS), which
makes the situation even less understandable ...

Delivering SPI as KVM_IRQ_ROUTING_IRQCHIP seems more sensible and if we
wanted ad-hoc delivery of KVM_IRQ_ROUTING_IRQCHIP, then I would prefer a
new interface to two different meanings for KVM_SIGNAL_MSI:
KVM_SIGNAL_MSI was created because we didn't have anything that could
inject an interrupt without setting up a route with KVM_SET_GSI_ROUTING
and we are still missing a generic interface to do that.

> But Well, if you prefer we do not implement it for GICv2M, since
> considered as far fetched I can remove this patch.

I do, thanks.  Documentation in [6/7] was ahead and needs changing then.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v11 06/10] genirq/msi-doorbell: msi_doorbell_safe

2016-07-22 Thread Thomas Gleixner
On Thu, 21 Jul 2016, Auger Eric wrote:
> On 20/07/2016 10:12, Thomas Gleixner wrote:
> > On Tue, 19 Jul 2016, Eric Auger wrote:
> >> +bool msi_doorbell_safe(void)
> >> +{
> >> +  struct irqchip_doorbell *db;
> >> +  bool irq_remapping = true;
> >> +
> >> +  mutex_lock(_doorbell_mutex);
> >> +  list_for_each_entry(db, _doorbell_list, next) {
> >> +  irq_remapping &= db->info.irq_remapping;
> > 
> > db->info.irq_remapping is set in msi_doorbell_register(). So you can keep 
> > book
> > about that there. No need to iterate here.
> Yes makes sense to store the info at registration time. Currently this
> function is not in any fast path but that's cleaner from a general
> perspective. I will need to do such iteration at un-registration though.

Two simple counter should be sufficient.

  nr_registered_bells;
  nr_remapped_bells;



Thanks,

tglx
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: KVM on ARM crashes with new VGIC v4.7-rc7

2016-07-22 Thread Andre Przywara
Hi Stefan,

On 22/07/16 06:57, Stefan Agner wrote:
> Hi,
> 
> I tried KVM on a Cortex-A7 platform (i.MX 7Dual SoC) and encountered
> this stack trace immediately after invoking qemu-system-arm:
> 
> Unable to handle kernel paging request at virtual address ffe4
> pgd = 8ca52740
> [ffe4] *pgd=8080007003, *pmd=8ff7e003, *pte=
> Internal error: Oops: 207 [#1] SMP ARM
> Modules linked in:  
> CPU: 0 PID: 329 Comm: qemu-system-arm Tainted: GW  
> 4.7.0-rc7-00094-gea3ed2c #109
> Hardware name: Freescale i.MX7 Dual (Device Tree)
> task: 8ca3ee40 ti: 8d2b task.ti: 8d2b
> PC is at do_raw_spin_lock+0x8/0x1dc
> LR is at kvm_vgic_flush_hwstate+0x8c/0x224
> pc : [<8027c87c>]lr : [<802172d4>]psr: 60070013
> sp : 8d2b1e38  ip : 8d2b  fp : 0001
> r10: 8d2b  r9 : 0001  r8 : 8d2b8e54
> fec 30be.ethernet eth0: MDIO read timeout
> r7 : 8d2b8000  r6 : 8d2b8e74  r5 :   r4 : ffe0
> r3 : 4ead  r2 :   r1 :   r0 : ffe0
> Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
> Control: 30c5387d  Table: 8ca52740  DAC: fffd
> Process qemu-system-arm (pid: 329, stack limit = 0x8d2b0210)
> Stack: (0x8d2b1e38 to 0x8d2b2000)
> 1e20:   ffe0
> 
> 1e40: 8d2b8e74 8d2b8000 8d2b8e54 0001 8d2b 802172d4 8d2b8000
> 810074f8
> 1e60: 81007508 8ca5f800 8d284000 0001 8d2b 8020fbd4 8ce9a000
> 8ca5f800
> 1e80:  0001  00ff 8d284000  
> 7ffbfeff
> 1ea0: fffe  8d28b780  755fec6c  
> e000
> 1ec0: 8d2b8000  8d28b780  755fec6c 8020af90 
> 8023f248
> 1ee0: 000a 755fe98c 8d2b1f08 0008 8021aa84 e000 
> 
> 1f00: 8a00d860 8d28b780 80334f94  8d2b 80334748 
> 
> 1f20:  8d28b780 4000 0009 8d28b500 0024 8104ebee
> 80bc2ec4
> 1f40: 80bafa24 8034138c   80341248  755fec6c
> 007c1e70
> 1f60: 0009 4258 ae80 8d28b781 0009 8d28b780 ae80
> 
> 1f80: 8d2b  755fec6c 80334f94 007c1e70 322a7400 4258
> 0036
> 1fa0: 8021aa84 8021a900 007c1e70 322a7400 0009 ae80 
> 755feac0
> 1fc0: 007c1e70 322a7400 4258 0036 7e9aff58 01151da4 76f8b4c0
> 755fec6c
> 1fe0: 0038192c 755fea9c 00048ae7 7697d66c 60070010 0009 
> 
> [<8027c87c>] (do_raw_spin_lock) from [<802172d4>]
> (kvm_vgic_flush_hwstate+0x8c/0x224)
> [<802172d4>] (kvm_vgic_flush_hwstate) from [<8020fbd4>]
> (kvm_arch_vcpu_ioctl_run+0x110/0x478)
> [<8020fbd4>] (kvm_arch_vcpu_ioctl_run) from [<8020af90>]
> (kvm_vcpu_ioctl+0x2e0/0x6d4)
> [<8020af90>] (kvm_vcpu_ioctl) from [<80334748>]
> (do_vfs_ioctl+0xa0/0x8b8)
> [<80334748>] (do_vfs_ioctl) from [<80334f94>] (SyS_ioctl+0x34/0x5c)
> [<80334f94>] (SyS_ioctl) from [<8021a900>] (ret_fast_syscall+0x0/0x1c)
> Code: e49de004 ea09ea24 e92d47f0 e3043ead (e5902004)
> ---[ end trace cb88537fdc8fa206 ]---
> 
> I use CONFIG_KVM_NEW_VGIC=y. This happens to me with a rather minimal
> qemu invocation (qemu-system-arm -enable-kvm -M virt -cpu host
> -nographic -serial stdio -kernel zImage).
> 
> Using a bit older Qemu version 2.4.0.

I just tried with a self compiled QEMU 2.4.0 and the Ubuntu 14.04
provided 2.0.0, it worked fine with Linus' current HEAD as a host kernel
on a Midway (Cortex-A15).

Can you try to disable the new VGIC, just to see if that's a regression?

Cheers,
Andre.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: KVM on ARM crashes with new VGIC v4.7-rc7

2016-07-22 Thread Marc Zyngier
On 22/07/16 06:57, Stefan Agner wrote:
> Hi,
> 
> I tried KVM on a Cortex-A7 platform (i.MX 7Dual SoC) and encountered
> this stack trace immediately after invoking qemu-system-arm:
> 
> Unable to handle kernel paging request at virtual address ffe4
> pgd = 8ca52740
> [ffe4] *pgd=8080007003, *pmd=8ff7e003, *pte=
> Internal error: Oops: 207 [#1] SMP ARM
> Modules linked in:  
> CPU: 0 PID: 329 Comm: qemu-system-arm Tainted: GW  
> 4.7.0-rc7-00094-gea3ed2c #109
> Hardware name: Freescale i.MX7 Dual (Device Tree)
> task: 8ca3ee40 ti: 8d2b task.ti: 8d2b
> PC is at do_raw_spin_lock+0x8/0x1dc
> LR is at kvm_vgic_flush_hwstate+0x8c/0x224
> pc : [<8027c87c>]lr : [<802172d4>]psr: 60070013
> sp : 8d2b1e38  ip : 8d2b  fp : 0001
> r10: 8d2b  r9 : 0001  r8 : 8d2b8e54
> fec 30be.ethernet eth0: MDIO read timeout
> r7 : 8d2b8000  r6 : 8d2b8e74  r5 :   r4 : ffe0
> r3 : 4ead  r2 :   r1 :   r0 : ffe0
> Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
> Control: 30c5387d  Table: 8ca52740  DAC: fffd
> Process qemu-system-arm (pid: 329, stack limit = 0x8d2b0210)
> Stack: (0x8d2b1e38 to 0x8d2b2000)
> 1e20:   ffe0
> 
> 1e40: 8d2b8e74 8d2b8000 8d2b8e54 0001 8d2b 802172d4 8d2b8000
> 810074f8
> 1e60: 81007508 8ca5f800 8d284000 0001 8d2b 8020fbd4 8ce9a000
> 8ca5f800
> 1e80:  0001  00ff 8d284000  
> 7ffbfeff
> 1ea0: fffe  8d28b780  755fec6c  
> e000
> 1ec0: 8d2b8000  8d28b780  755fec6c 8020af90 
> 8023f248
> 1ee0: 000a 755fe98c 8d2b1f08 0008 8021aa84 e000 
> 
> 1f00: 8a00d860 8d28b780 80334f94  8d2b 80334748 
> 
> 1f20:  8d28b780 4000 0009 8d28b500 0024 8104ebee
> 80bc2ec4
> 1f40: 80bafa24 8034138c   80341248  755fec6c
> 007c1e70
> 1f60: 0009 4258 ae80 8d28b781 0009 8d28b780 ae80
> 
> 1f80: 8d2b  755fec6c 80334f94 007c1e70 322a7400 4258
> 0036
> 1fa0: 8021aa84 8021a900 007c1e70 322a7400 0009 ae80 
> 755feac0
> 1fc0: 007c1e70 322a7400 4258 0036 7e9aff58 01151da4 76f8b4c0
> 755fec6c
> 1fe0: 0038192c 755fea9c 00048ae7 7697d66c 60070010 0009 
> 
> [<8027c87c>] (do_raw_spin_lock) from [<802172d4>]
> (kvm_vgic_flush_hwstate+0x8c/0x224)
> [<802172d4>] (kvm_vgic_flush_hwstate) from [<8020fbd4>]
> (kvm_arch_vcpu_ioctl_run+0x110/0x478)
> [<8020fbd4>] (kvm_arch_vcpu_ioctl_run) from [<8020af90>]
> (kvm_vcpu_ioctl+0x2e0/0x6d4)
> [<8020af90>] (kvm_vcpu_ioctl) from [<80334748>]
> (do_vfs_ioctl+0xa0/0x8b8)
> [<80334748>] (do_vfs_ioctl) from [<80334f94>] (SyS_ioctl+0x34/0x5c)
> [<80334f94>] (SyS_ioctl) from [<8021a900>] (ret_fast_syscall+0x0/0x1c)
> Code: e49de004 ea09ea24 e92d47f0 e3043ead (e5902004)
> ---[ end trace cb88537fdc8fa206 ]---
> 
> I use CONFIG_KVM_NEW_VGIC=y. This happens to me with a rather minimal
> qemu invocation (qemu-system-arm -enable-kvm -M virt -cpu host
> -nographic -serial stdio -kernel zImage).
> 
> Using a bit older Qemu version 2.4.0.
> 
> Is there something missing on my platform or is this a general KVM ARM
> issue?

Having compiled a 2.4.0 vintage QEMU, everything seems fine, and the
guest comes up:

maz@big-leg-emma:~$ ./qemu/build/arm-softmmu/qemu-system-arm -enable-kvm -M 
virt -m 512 -cpu host -nographic -serial mon:stdio -kernel /boot/zImage-test

(process:2867): GLib-WARNING **: 
/build/glib2.0-Ero3uS/glib2.0-2.48.0/./glib/gmem.c:483: custom memory 
allocation vtable not supported
[0.00] Booting Linux on physical CPU 0x0
[0.00] Linux version 4.7.0-rc7 (maz@approximate) (gcc version 5.2.1 
20151005 (Linaro GCC 5.2-2015.11) ) #6281 SMP PREEMPT Fri Jul 22 10:01:56 BST 
2016
[0.00] CPU: ARMv7 Processor [410fc074] revision 4 (ARMv7), cr=30c5387d
[0.00] CPU: div instructions available: patching division code
[0.00] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing 
instruction cache
[0.00] Machine model: linux,dummy-virt
[0.00] efi: Getting EFI parameters from FDT:
[0.00] efi: UEFI not found.
[0.00] Forcing write-allocate cache policy for SMP
[0.00] Memory policy: Data cache writealloc
[0.00] psci: probing for conduit method from DT.
[0.00] psci: PSCIv0.2 detected in firmware.
[0.00] psci: Using standard PSCI v0.2 function IDs
[0.00] psci: Trusted OS migration not required
[0.00] percpu: Embedded 14 pages/cpu @cfde4000 s27456 r8192 d21696 
u57344
[0.00] Built 1 zonelists in Zone order, mobility grouping on.  Total 
pages: 65024

So something is amiss somewhere else. Are you sure about the qemu
version? Built from source or packaged by a distro?

Could you send me your config? Also, can you put some 

Re: KVM on ARM crashes with new VGIC v4.7-rc7

2016-07-22 Thread Stefan Agner
Hi Marc,

On 2016-07-22 00:47, Marc Zyngier wrote:
> Hi Stefan,
> 
> On 22/07/16 06:57, Stefan Agner wrote:
>> Hi,
>>
>> I tried KVM on a Cortex-A7 platform (i.MX 7Dual SoC) and encountered
>> this stack trace immediately after invoking qemu-system-arm:
>>
>> Unable to handle kernel paging request at virtual address ffe4
>> pgd = 8ca52740
>> [ffe4] *pgd=8080007003, *pmd=8ff7e003, *pte=
>> Internal error: Oops: 207 [#1] SMP ARM
>> Modules linked in:
>> CPU: 0 PID: 329 Comm: qemu-system-arm Tainted: GW
>> 4.7.0-rc7-00094-gea3ed2c #109
>> Hardware name: Freescale i.MX7 Dual (Device Tree)
>> task: 8ca3ee40 ti: 8d2b task.ti: 8d2b
>> PC is at do_raw_spin_lock+0x8/0x1dc
>> LR is at kvm_vgic_flush_hwstate+0x8c/0x224
>> pc : [<8027c87c>]lr : [<802172d4>]psr: 60070013
>> sp : 8d2b1e38  ip : 8d2b  fp : 0001
>> r10: 8d2b  r9 : 0001  r8 : 8d2b8e54
>> fec 30be.ethernet eth0: MDIO read timeout
>> r7 : 8d2b8000  r6 : 8d2b8e74  r5 :   r4 : ffe0
>> r3 : 4ead  r2 :   r1 :   r0 : ffe0
>> Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
>> Control: 30c5387d  Table: 8ca52740  DAC: fffd
>> Process qemu-system-arm (pid: 329, stack limit = 0x8d2b0210)
>> Stack: (0x8d2b1e38 to 0x8d2b2000)
>> 1e20:   ffe0
>> 
>> 1e40: 8d2b8e74 8d2b8000 8d2b8e54 0001 8d2b 802172d4 8d2b8000
>> 810074f8
>> 1e60: 81007508 8ca5f800 8d284000 0001 8d2b 8020fbd4 8ce9a000
>> 8ca5f800
>> 1e80:  0001  00ff 8d284000  
>> 7ffbfeff
>> 1ea0: fffe  8d28b780  755fec6c  
>> e000
>> 1ec0: 8d2b8000  8d28b780  755fec6c 8020af90 
>> 8023f248
>> 1ee0: 000a 755fe98c 8d2b1f08 0008 8021aa84 e000 
>> 
>> 1f00: 8a00d860 8d28b780 80334f94  8d2b 80334748 
>> 
>> 1f20:  8d28b780 4000 0009 8d28b500 0024 8104ebee
>> 80bc2ec4
>> 1f40: 80bafa24 8034138c   80341248  755fec6c
>> 007c1e70
>> 1f60: 0009 4258 ae80 8d28b781 0009 8d28b780 ae80
>> 
>> 1f80: 8d2b  755fec6c 80334f94 007c1e70 322a7400 4258
>> 0036
>> 1fa0: 8021aa84 8021a900 007c1e70 322a7400 0009 ae80 
>> 755feac0
>> 1fc0: 007c1e70 322a7400 4258 0036 7e9aff58 01151da4 76f8b4c0
>> 755fec6c
>> 1fe0: 0038192c 755fea9c 00048ae7 7697d66c 60070010 0009 
>> 
>> [<8027c87c>] (do_raw_spin_lock) from [<802172d4>]
>> (kvm_vgic_flush_hwstate+0x8c/0x224)
>> [<802172d4>] (kvm_vgic_flush_hwstate) from [<8020fbd4>]
>> (kvm_arch_vcpu_ioctl_run+0x110/0x478)
>> [<8020fbd4>] (kvm_arch_vcpu_ioctl_run) from [<8020af90>]
>> (kvm_vcpu_ioctl+0x2e0/0x6d4)
>> [<8020af90>] (kvm_vcpu_ioctl) from [<80334748>]
>> (do_vfs_ioctl+0xa0/0x8b8)
>> [<80334748>] (do_vfs_ioctl) from [<80334f94>] (SyS_ioctl+0x34/0x5c)
>> [<80334f94>] (SyS_ioctl) from [<8021a900>] (ret_fast_syscall+0x0/0x1c)
>> Code: e49de004 ea09ea24 e92d47f0 e3043ead (e5902004)
>> ---[ end trace cb88537fdc8fa206 ]---
>>
>> I use CONFIG_KVM_NEW_VGIC=y. This happens to me with a rather minimal
>> qemu invocation (qemu-system-arm -enable-kvm -M virt -cpu host
>> -nographic -serial stdio -kernel zImage).
>>
>> Using a bit older Qemu version 2.4.0.
>>
>> Is there something missing on my platform or is this a general KVM ARM
>> issue?
> 
> This looks like a genuine bug, and I suspect this is triggered by having
> an older QEMU that predates the explicit vgic init, hence relying on the
> "init at first run". But in the meantime, could you dump me the bit of
> kernel log that shows the KVM initialization, just in case I spot
> something odd there?

# dmesg | grep -C 2 kvm  
[0.303848] RPC: Registered tcp transport module.
[0.303880] RPC: Registered tcp NFSv4.1 backchannel transport module.
[0.307238] kvm [1]: 8-bit VMID
[0.307273] kvm [1]: Hyp mode initialized successfully
[0.307713] kvm [1]: virtual timer IRQ18
[0.312511] futex hash table entries: 512 (order: 3, 32768 bytes)
[0.315230] workingset: timestamp_bits=28 max_order=17 bucket_order=0

--
Stefan
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: KVM on ARM crashes with new VGIC v4.7-rc7

2016-07-22 Thread Marc Zyngier
On 22/07/16 08:52, Auger Eric wrote:
> Hi Marc,
> 
> On 22/07/2016 09:47, Marc Zyngier wrote:
>> Hi Stefan,
>>
>> On 22/07/16 06:57, Stefan Agner wrote:
>>> Hi,
>>>
>>> I tried KVM on a Cortex-A7 platform (i.MX 7Dual SoC) and encountered
>>> this stack trace immediately after invoking qemu-system-arm:
>>>
>>> Unable to handle kernel paging request at virtual address ffe4
>>> pgd = 8ca52740
>>> [ffe4] *pgd=8080007003, *pmd=8ff7e003, *pte=
>>> Internal error: Oops: 207 [#1] SMP ARM
>>> Modules linked in:  
>>> CPU: 0 PID: 329 Comm: qemu-system-arm Tainted: GW  
>>> 4.7.0-rc7-00094-gea3ed2c #109
>>> Hardware name: Freescale i.MX7 Dual (Device Tree)
>>> task: 8ca3ee40 ti: 8d2b task.ti: 8d2b
>>> PC is at do_raw_spin_lock+0x8/0x1dc
>>> LR is at kvm_vgic_flush_hwstate+0x8c/0x224
>>> pc : [<8027c87c>]lr : [<802172d4>]psr: 60070013
>>> sp : 8d2b1e38  ip : 8d2b  fp : 0001
>>> r10: 8d2b  r9 : 0001  r8 : 8d2b8e54
>>> fec 30be.ethernet eth0: MDIO read timeout
>>> r7 : 8d2b8000  r6 : 8d2b8e74  r5 :   r4 : ffe0
>>> r3 : 4ead  r2 :   r1 :   r0 : ffe0
>>> Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
>>> Control: 30c5387d  Table: 8ca52740  DAC: fffd
>>> Process qemu-system-arm (pid: 329, stack limit = 0x8d2b0210)
>>> Stack: (0x8d2b1e38 to 0x8d2b2000)
>>> 1e20:   ffe0
>>> 
>>> 1e40: 8d2b8e74 8d2b8000 8d2b8e54 0001 8d2b 802172d4 8d2b8000
>>> 810074f8
>>> 1e60: 81007508 8ca5f800 8d284000 0001 8d2b 8020fbd4 8ce9a000
>>> 8ca5f800
>>> 1e80:  0001  00ff 8d284000  
>>> 7ffbfeff
>>> 1ea0: fffe  8d28b780  755fec6c  
>>> e000
>>> 1ec0: 8d2b8000  8d28b780  755fec6c 8020af90 
>>> 8023f248
>>> 1ee0: 000a 755fe98c 8d2b1f08 0008 8021aa84 e000 
>>> 
>>> 1f00: 8a00d860 8d28b780 80334f94  8d2b 80334748 
>>> 
>>> 1f20:  8d28b780 4000 0009 8d28b500 0024 8104ebee
>>> 80bc2ec4
>>> 1f40: 80bafa24 8034138c   80341248  755fec6c
>>> 007c1e70
>>> 1f60: 0009 4258 ae80 8d28b781 0009 8d28b780 ae80
>>> 
>>> 1f80: 8d2b  755fec6c 80334f94 007c1e70 322a7400 4258
>>> 0036
>>> 1fa0: 8021aa84 8021a900 007c1e70 322a7400 0009 ae80 
>>> 755feac0
>>> 1fc0: 007c1e70 322a7400 4258 0036 7e9aff58 01151da4 76f8b4c0
>>> 755fec6c
>>> 1fe0: 0038192c 755fea9c 00048ae7 7697d66c 60070010 0009 
>>> 
>>> [<8027c87c>] (do_raw_spin_lock) from [<802172d4>]
>>> (kvm_vgic_flush_hwstate+0x8c/0x224)
>>> [<802172d4>] (kvm_vgic_flush_hwstate) from [<8020fbd4>]
>>> (kvm_arch_vcpu_ioctl_run+0x110/0x478)
>>> [<8020fbd4>] (kvm_arch_vcpu_ioctl_run) from [<8020af90>]
>>> (kvm_vcpu_ioctl+0x2e0/0x6d4)
>>> [<8020af90>] (kvm_vcpu_ioctl) from [<80334748>]
>>> (do_vfs_ioctl+0xa0/0x8b8)
>>> [<80334748>] (do_vfs_ioctl) from [<80334f94>] (SyS_ioctl+0x34/0x5c)
>>> [<80334f94>] (SyS_ioctl) from [<8021a900>] (ret_fast_syscall+0x0/0x1c)
>>> Code: e49de004 ea09ea24 e92d47f0 e3043ead (e5902004)
>>> ---[ end trace cb88537fdc8fa206 ]---
>>>
>>> I use CONFIG_KVM_NEW_VGIC=y. This happens to me with a rather minimal
>>> qemu invocation (qemu-system-arm -enable-kvm -M virt -cpu host
>>> -nographic -serial stdio -kernel zImage).
>>>
>>> Using a bit older Qemu version 2.4.0.
>>>
>>> Is there something missing on my platform or is this a general KVM ARM
>>> issue?
>>
>> This looks like a genuine bug, and I suspect this is triggered by having
>> an older QEMU that predates the explicit vgic init, hence relying on the
>> "init at first run". But in the meantime, could you dump me the bit of
>> kernel log that shows the KVM initialization, just in case I spot
>> something odd there?
> Had the same idea but QEMU v2.4.0 has the commit:
> 
> hw/intc/arm_gic: Initialize the vgic in the realize function
> (f0bb55890a173cb1e9e87d608647cac70f8f9dd4)

Fair enough. I'm (slowly) rebuilding a v2.4.0 QEMU on my A7 board, and
hopefully I'll be able to reproduce this sucker.

Thanks,

M.
-- 
Jazz is not dead. It just smells funny...
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: KVM on ARM crashes with new VGIC v4.7-rc7

2016-07-22 Thread Auger Eric
Hi Marc,

On 22/07/2016 09:47, Marc Zyngier wrote:
> Hi Stefan,
> 
> On 22/07/16 06:57, Stefan Agner wrote:
>> Hi,
>>
>> I tried KVM on a Cortex-A7 platform (i.MX 7Dual SoC) and encountered
>> this stack trace immediately after invoking qemu-system-arm:
>>
>> Unable to handle kernel paging request at virtual address ffe4
>> pgd = 8ca52740
>> [ffe4] *pgd=8080007003, *pmd=8ff7e003, *pte=
>> Internal error: Oops: 207 [#1] SMP ARM
>> Modules linked in:  
>> CPU: 0 PID: 329 Comm: qemu-system-arm Tainted: GW  
>> 4.7.0-rc7-00094-gea3ed2c #109
>> Hardware name: Freescale i.MX7 Dual (Device Tree)
>> task: 8ca3ee40 ti: 8d2b task.ti: 8d2b
>> PC is at do_raw_spin_lock+0x8/0x1dc
>> LR is at kvm_vgic_flush_hwstate+0x8c/0x224
>> pc : [<8027c87c>]lr : [<802172d4>]psr: 60070013
>> sp : 8d2b1e38  ip : 8d2b  fp : 0001
>> r10: 8d2b  r9 : 0001  r8 : 8d2b8e54
>> fec 30be.ethernet eth0: MDIO read timeout
>> r7 : 8d2b8000  r6 : 8d2b8e74  r5 :   r4 : ffe0
>> r3 : 4ead  r2 :   r1 :   r0 : ffe0
>> Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
>> Control: 30c5387d  Table: 8ca52740  DAC: fffd
>> Process qemu-system-arm (pid: 329, stack limit = 0x8d2b0210)
>> Stack: (0x8d2b1e38 to 0x8d2b2000)
>> 1e20:   ffe0
>> 
>> 1e40: 8d2b8e74 8d2b8000 8d2b8e54 0001 8d2b 802172d4 8d2b8000
>> 810074f8
>> 1e60: 81007508 8ca5f800 8d284000 0001 8d2b 8020fbd4 8ce9a000
>> 8ca5f800
>> 1e80:  0001  00ff 8d284000  
>> 7ffbfeff
>> 1ea0: fffe  8d28b780  755fec6c  
>> e000
>> 1ec0: 8d2b8000  8d28b780  755fec6c 8020af90 
>> 8023f248
>> 1ee0: 000a 755fe98c 8d2b1f08 0008 8021aa84 e000 
>> 
>> 1f00: 8a00d860 8d28b780 80334f94  8d2b 80334748 
>> 
>> 1f20:  8d28b780 4000 0009 8d28b500 0024 8104ebee
>> 80bc2ec4
>> 1f40: 80bafa24 8034138c   80341248  755fec6c
>> 007c1e70
>> 1f60: 0009 4258 ae80 8d28b781 0009 8d28b780 ae80
>> 
>> 1f80: 8d2b  755fec6c 80334f94 007c1e70 322a7400 4258
>> 0036
>> 1fa0: 8021aa84 8021a900 007c1e70 322a7400 0009 ae80 
>> 755feac0
>> 1fc0: 007c1e70 322a7400 4258 0036 7e9aff58 01151da4 76f8b4c0
>> 755fec6c
>> 1fe0: 0038192c 755fea9c 00048ae7 7697d66c 60070010 0009 
>> 
>> [<8027c87c>] (do_raw_spin_lock) from [<802172d4>]
>> (kvm_vgic_flush_hwstate+0x8c/0x224)
>> [<802172d4>] (kvm_vgic_flush_hwstate) from [<8020fbd4>]
>> (kvm_arch_vcpu_ioctl_run+0x110/0x478)
>> [<8020fbd4>] (kvm_arch_vcpu_ioctl_run) from [<8020af90>]
>> (kvm_vcpu_ioctl+0x2e0/0x6d4)
>> [<8020af90>] (kvm_vcpu_ioctl) from [<80334748>]
>> (do_vfs_ioctl+0xa0/0x8b8)
>> [<80334748>] (do_vfs_ioctl) from [<80334f94>] (SyS_ioctl+0x34/0x5c)
>> [<80334f94>] (SyS_ioctl) from [<8021a900>] (ret_fast_syscall+0x0/0x1c)
>> Code: e49de004 ea09ea24 e92d47f0 e3043ead (e5902004)
>> ---[ end trace cb88537fdc8fa206 ]---
>>
>> I use CONFIG_KVM_NEW_VGIC=y. This happens to me with a rather minimal
>> qemu invocation (qemu-system-arm -enable-kvm -M virt -cpu host
>> -nographic -serial stdio -kernel zImage).
>>
>> Using a bit older Qemu version 2.4.0.
>>
>> Is there something missing on my platform or is this a general KVM ARM
>> issue?
> 
> This looks like a genuine bug, and I suspect this is triggered by having
> an older QEMU that predates the explicit vgic init, hence relying on the
> "init at first run". But in the meantime, could you dump me the bit of
> kernel log that shows the KVM initialization, just in case I spot
> something odd there?
Had the same idea but QEMU v2.4.0 has the commit:

hw/intc/arm_gic: Initialize the vgic in the realize function
(f0bb55890a173cb1e9e87d608647cac70f8f9dd4)

Eric
> 
> I'll try and dig a QEMU of that particular vintage to reproduce it.
> 
> Thanks for the heads up!
> 
>   M.
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


  1   2   >