2019-06-03 07:44:50 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2016-03-25 00:04:53 +00:00
/*
* Copyright ( C ) 2015 , 2016 ARM Ltd .
*/
# include <linux/kvm.h>
# include <linux/kvm_host.h>
# include <trace/events/kvm.h>
2016-07-22 16:20:41 +00:00
# include <kvm/arm_vgic.h>
# include "vgic.h"
2016-03-25 00:04:53 +00:00
2016-07-22 16:20:41 +00:00
/**
* 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 )
2016-03-25 00:04:53 +00:00
{
2016-07-22 16:20:41 +00:00
unsigned int spi_id = e - > irqchip . pin + VGIC_NR_PRIVATE_IRQS ;
if ( ! vgic_valid_spi ( kvm , spi_id ) )
return - EINVAL ;
2017-05-16 12:41:18 +02:00
return kvm_vgic_inject_irq ( kvm , 0 , spi_id , level , NULL ) ;
2016-03-25 00:04:53 +00:00
}
2016-07-22 16:20:41 +00:00
/**
* kvm_set_routing_entry : populate a kvm routing entry
* from a user routing entry
*
2016-07-24 10:34:08 +01:00
* @ kvm : the VM this entry is applied to
2016-07-22 16:20:41 +00:00
* @ e : kvm kernel routing entry handle
* @ ue : user api routing entry handle
* return 0 on success , - EINVAL on errors .
*/
2016-07-24 10:34:08 +01:00
int kvm_set_routing_entry ( struct kvm * kvm ,
struct kvm_kernel_irq_routing_entry * e ,
const struct kvm_irq_routing_entry * ue )
2016-03-25 00:04:53 +00:00
{
2016-07-22 16:20:41 +00:00
int r = - EINVAL ;
switch ( ue - > type ) {
case KVM_IRQ_ROUTING_IRQCHIP :
e - > set = vgic_irqfd_set_irq ;
e - > irqchip . irqchip = ue - > u . irqchip . irqchip ;
e - > irqchip . pin = ue - > u . irqchip . pin ;
if ( ( e - > irqchip . pin > = KVM_IRQCHIP_NUM_PINS ) | |
( e - > irqchip . irqchip > = KVM_NR_IRQCHIPS ) )
goto out ;
break ;
2016-07-22 16:20:42 +00:00
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 ;
2016-07-22 16:20:41 +00:00
default :
goto out ;
}
r = 0 ;
out :
return r ;
2016-03-25 00:04:53 +00:00
}
2016-07-22 16:20:41 +00:00
/**
* kvm_set_msi : inject the MSI corresponding to the
* MSI routing entry
*
* This is the entry point for irqfd MSI injection
* and userspace MSI injection .
*/
int kvm_set_msi ( struct kvm_kernel_irq_routing_entry * e ,
struct kvm * kvm , int irq_source_id ,
int level , bool line_status )
2016-03-25 00:04:53 +00:00
{
2016-07-22 16:20:41 +00:00
struct kvm_msi msi ;
2016-03-25 00:04:53 +00:00
2016-07-22 16:20:41 +00:00
msi . address_lo = e - > msi . address_lo ;
msi . address_hi = e - > msi . address_hi ;
msi . data = e - > msi . data ;
msi . flags = e - > msi . flags ;
msi . devid = e - > msi . devid ;
2016-03-25 00:04:53 +00:00
2016-07-22 16:20:41 +00:00
if ( ! vgic_has_its ( kvm ) )
return - ENODEV ;
2016-03-25 00:04:53 +00:00
2017-02-02 20:30:03 -06:00
if ( ! level )
return - 1 ;
2016-07-22 16:20:41 +00:00
return vgic_its_inject_msi ( kvm , & msi ) ;
2016-03-25 00:04:53 +00:00
}
2016-07-22 16:20:41 +00:00
int kvm_vgic_setup_default_irq_routing ( struct kvm * kvm )
2016-03-25 00:04:53 +00:00
{
2016-07-22 16:20:41 +00:00
struct kvm_irq_routing_entry * entries ;
struct vgic_dist * dist = & kvm - > arch . vgic ;
u32 nr = dist - > nr_spis ;
int i , ret ;
2017-11-16 17:58:15 +00:00
entries = kcalloc ( nr , sizeof ( * entries ) , GFP_KERNEL ) ;
2016-07-22 16:20:41 +00:00
if ( ! entries )
return - ENOMEM ;
for ( i = 0 ; i < nr ; i + + ) {
entries [ i ] . gsi = i ;
entries [ i ] . type = KVM_IRQ_ROUTING_IRQCHIP ;
entries [ i ] . u . irqchip . irqchip = 0 ;
entries [ i ] . u . irqchip . pin = i ;
}
ret = kvm_set_irq_routing ( kvm , entries , nr , 0 ) ;
kfree ( entries ) ;
return ret ;
2016-03-25 00:04:53 +00:00
}