For passed-through devices behind a vIOMMU, we'll need to translate writes to MSI vectors. Let the IRQ code register MSI doorbells, and add a simple way for other systems to check if an address is a doorbell. Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@xxxxxxx> --- arm/gic.c | 4 ++++ include/kvm/irq.h | 3 +++ irq.c | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/arm/gic.c b/arm/gic.c index bf7a22a9..c708031e 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -108,6 +108,10 @@ static int gic__create_its_frame(struct kvm *kvm, u64 its_frame_addr) }; int err; + err = irq__add_msi_doorbell(kvm, its_frame_addr, KVM_VGIC_V3_ITS_SIZE); + if (err) + return err; + err = ioctl(kvm->vm_fd, KVM_CREATE_DEVICE, &its_device); if (err) { fprintf(stderr, diff --git a/include/kvm/irq.h b/include/kvm/irq.h index a188a870..2a59257e 100644 --- a/include/kvm/irq.h +++ b/include/kvm/irq.h @@ -24,6 +24,9 @@ int irq__allocate_routing_entry(void); int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg, u32 device_id); void irq__update_msix_route(struct kvm *kvm, u32 gsi, struct msi_msg *msg); +int irq__add_msi_doorbell(struct kvm *kvm, u64 addr, u64 size); +bool irq__addr_is_msi_doorbell(struct kvm *kvm, u64 addr); + /* * The function takes two eventfd arguments, trigger_fd and resample_fd. If * resample_fd is <= 0, resampling is disabled and the IRQ is edge-triggered diff --git a/irq.c b/irq.c index a4ef75e4..a04f4d37 100644 --- a/irq.c +++ b/irq.c @@ -8,6 +8,14 @@ #include "kvm/irq.h" #include "kvm/kvm-arch.h" +struct kvm_msi_doorbell_region { + u64 start; + u64 end; + struct list_head head; +}; + +static LIST_HEAD(msi_doorbells); + static u8 next_line = KVM_IRQ_OFFSET; static int allocated_gsis = 0; @@ -147,6 +155,33 @@ void irq__update_msix_route(struct kvm *kvm, u32 gsi, struct msi_msg *msg) die_perror("KVM_SET_GSI_ROUTING"); } +int irq__add_msi_doorbell(struct kvm *kvm, u64 addr, u64 size) +{ + struct kvm_msi_doorbell_region *doorbell = malloc(sizeof(*doorbell)); + + if (!doorbell) + return -ENOMEM; + + doorbell->start = addr; + doorbell->end = addr + size - 1; + + list_add(&doorbell->head, &msi_doorbells); + + return 0; +} + +bool irq__addr_is_msi_doorbell(struct kvm *kvm, u64 addr) +{ + struct kvm_msi_doorbell_region *doorbell; + + list_for_each_entry(doorbell, &msi_doorbells, head) { + if (addr >= doorbell->start && addr <= doorbell->end) + return true; + } + + return false; +} + int irq__common_add_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd, int resample_fd) { -- 2.12.1 _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linuxfoundation.org/mailman/listinfo/virtualization