Loading drivers/virt/haven/hh_irq_lend.c +38 −11 Original line number Diff line number Diff line Loading @@ -4,11 +4,15 @@ * */ #include <linux/irq.h> #include <linux/module.h> #include <linux/notifier.h> #include <linux/spinlock.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <linux/haven/hh_irq_lend.h> #include <linux/haven/hh_rm_drv.h> #include <linux/spinlock.h> #include "hh_rm_drv_private.h" struct hh_irq_entry { hh_vmid_t vmid; Loading Loading @@ -116,23 +120,29 @@ static struct notifier_block hh_irq_lent_nb = { * hh_irq_lend: Lend a hardware interrupt to another VM * @label: vIRQ high-level label * @name: VM name to send interrupt to * @hw_irq: Hardware IRQ number to lend * @irq: Linux IRQ number to lend * @on_release: callback to invoke when other VM returns the * interrupt * @data: Argument to pass to on_release */ int hh_irq_lend(enum hh_irq_label label, enum hh_vm_names name, int hw_irq, hh_irq_handle_fn on_release, void *data) int irq, hh_irq_handle_fn on_release, void *data) { int ret; int ret, virq; unsigned long flags; struct hh_irq_entry *entry; struct irq_data *irq_data; if (label >= HH_IRQ_LABEL_MAX || !on_release) return -EINVAL; entry = &hh_irq_entries[label]; irq_data = irq_get_irq_data(irq); if (!irq_data) return -EINVAL; virq = irq_data->hwirq; spin_lock_irqsave(&hh_irq_lend_lock, flags); if (entry->state != HH_IRQ_STATE_NONE) { spin_unlock_irqrestore(&hh_irq_lend_lock, flags); Loading @@ -151,7 +161,7 @@ int hh_irq_lend(enum hh_irq_label label, enum hh_vm_names name, entry->state = HH_IRQ_STATE_WAIT_RELEASE; spin_unlock_irqrestore(&hh_irq_lend_lock, flags); return hh_rm_vm_irq_lend_notify(entry->vmid, hw_irq, label, return hh_rm_vm_irq_lend_notify(entry->vmid, virq, label, &entry->virq_handle); } EXPORT_SYMBOL(hh_irq_lend); Loading Loading @@ -231,17 +241,18 @@ EXPORT_SYMBOL(hh_irq_wait_for_lend); /** * hh_irq_accept: Register to receive interrupts with a lent vIRQ * @label: vIRQ high-level label * @hw_irq: HWIRQ# to associate vIRQ with. If don't care, use -1 * @irq: Linux IRQ# to associate vIRQ with. If don't care, use -1 * * If hw_irq is not -1, then returns 0 on success, <0 otherwise * If hw_irq is -1, then returns the HWIRQ# that vIRQ was registered * to or <0 for error. * Returns the Linux IRQ# that vIRQ was registered to on success. * Returns <0 on error * This function is not thread-safe w.r.t. IRQ lend state. Do not race with * with hh_irq_release or another hh_irq_accept with same label. */ int hh_irq_accept(enum hh_irq_label label, int hw_irq) int hh_irq_accept(enum hh_irq_label label, int irq) { struct hh_irq_entry *entry; const struct irq_data *irq_data; int virq; if (label >= HH_IRQ_LABEL_MAX) return -EINVAL; Loading @@ -251,7 +262,23 @@ int hh_irq_accept(enum hh_irq_label label, int hw_irq) if (entry->state != HH_IRQ_STATE_LENT) return -EINVAL; return hh_rm_vm_irq_accept(entry->virq_handle, hw_irq); if (irq != -1) { irq_data = irq_get_irq_data(irq); if (!irq_data) return -EINVAL; virq = irq_data->hwirq; } else virq = -1; virq = hh_rm_vm_irq_accept(entry->virq_handle, virq); if (virq < 0) return virq; if (irq == -1) irq = hh_rm_virq_to_linux_irq(virq - 32, GIC_SPI, IRQ_TYPE_LEVEL_HIGH); return irq; } EXPORT_SYMBOL(hh_irq_accept); Loading drivers/virt/haven/hh_rm_core.c +2 −1 Original line number Diff line number Diff line Loading @@ -642,7 +642,7 @@ void *hh_rm_call(hh_rm_msgid_t message_id, return ret; } static int hh_rm_virq_to_linux_irq(u32 virq, u32 type, u32 trigger) int hh_rm_virq_to_linux_irq(u32 virq, u32 type, u32 trigger) { struct irq_fwspec fwspec = {}; Loading @@ -654,6 +654,7 @@ static int hh_rm_virq_to_linux_irq(u32 virq, u32 type, u32 trigger) return irq_create_fwspec_mapping(&fwspec); } EXPORT_SYMBOL(hh_rm_virq_to_linux_irq); static int hh_rm_get_irq(struct hh_vm_get_hyp_res_resp_entry *res_entry) { Loading drivers/virt/haven/hh_rm_drv_private.h +2 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ #include <linux/types.h> #include <linux/haven/hh_msgq.h> #include <linux/haven/hh_rm_drv.h> #include <linux/haven/hh_common.h> Loading Loading @@ -280,6 +281,7 @@ struct hh_mem_notify_req_payload { /* End Message ID headers */ /* Common function declerations */ int hh_rm_virq_to_linux_irq(u32 virq, u32 type, u32 trigger); int hh_update_vm_prop_table(enum hh_vm_names vm_name, struct hh_vm_property *vm_prop); void *hh_rm_call(hh_rm_msgid_t message_id, Loading Loading
drivers/virt/haven/hh_irq_lend.c +38 −11 Original line number Diff line number Diff line Loading @@ -4,11 +4,15 @@ * */ #include <linux/irq.h> #include <linux/module.h> #include <linux/notifier.h> #include <linux/spinlock.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <linux/haven/hh_irq_lend.h> #include <linux/haven/hh_rm_drv.h> #include <linux/spinlock.h> #include "hh_rm_drv_private.h" struct hh_irq_entry { hh_vmid_t vmid; Loading Loading @@ -116,23 +120,29 @@ static struct notifier_block hh_irq_lent_nb = { * hh_irq_lend: Lend a hardware interrupt to another VM * @label: vIRQ high-level label * @name: VM name to send interrupt to * @hw_irq: Hardware IRQ number to lend * @irq: Linux IRQ number to lend * @on_release: callback to invoke when other VM returns the * interrupt * @data: Argument to pass to on_release */ int hh_irq_lend(enum hh_irq_label label, enum hh_vm_names name, int hw_irq, hh_irq_handle_fn on_release, void *data) int irq, hh_irq_handle_fn on_release, void *data) { int ret; int ret, virq; unsigned long flags; struct hh_irq_entry *entry; struct irq_data *irq_data; if (label >= HH_IRQ_LABEL_MAX || !on_release) return -EINVAL; entry = &hh_irq_entries[label]; irq_data = irq_get_irq_data(irq); if (!irq_data) return -EINVAL; virq = irq_data->hwirq; spin_lock_irqsave(&hh_irq_lend_lock, flags); if (entry->state != HH_IRQ_STATE_NONE) { spin_unlock_irqrestore(&hh_irq_lend_lock, flags); Loading @@ -151,7 +161,7 @@ int hh_irq_lend(enum hh_irq_label label, enum hh_vm_names name, entry->state = HH_IRQ_STATE_WAIT_RELEASE; spin_unlock_irqrestore(&hh_irq_lend_lock, flags); return hh_rm_vm_irq_lend_notify(entry->vmid, hw_irq, label, return hh_rm_vm_irq_lend_notify(entry->vmid, virq, label, &entry->virq_handle); } EXPORT_SYMBOL(hh_irq_lend); Loading Loading @@ -231,17 +241,18 @@ EXPORT_SYMBOL(hh_irq_wait_for_lend); /** * hh_irq_accept: Register to receive interrupts with a lent vIRQ * @label: vIRQ high-level label * @hw_irq: HWIRQ# to associate vIRQ with. If don't care, use -1 * @irq: Linux IRQ# to associate vIRQ with. If don't care, use -1 * * If hw_irq is not -1, then returns 0 on success, <0 otherwise * If hw_irq is -1, then returns the HWIRQ# that vIRQ was registered * to or <0 for error. * Returns the Linux IRQ# that vIRQ was registered to on success. * Returns <0 on error * This function is not thread-safe w.r.t. IRQ lend state. Do not race with * with hh_irq_release or another hh_irq_accept with same label. */ int hh_irq_accept(enum hh_irq_label label, int hw_irq) int hh_irq_accept(enum hh_irq_label label, int irq) { struct hh_irq_entry *entry; const struct irq_data *irq_data; int virq; if (label >= HH_IRQ_LABEL_MAX) return -EINVAL; Loading @@ -251,7 +262,23 @@ int hh_irq_accept(enum hh_irq_label label, int hw_irq) if (entry->state != HH_IRQ_STATE_LENT) return -EINVAL; return hh_rm_vm_irq_accept(entry->virq_handle, hw_irq); if (irq != -1) { irq_data = irq_get_irq_data(irq); if (!irq_data) return -EINVAL; virq = irq_data->hwirq; } else virq = -1; virq = hh_rm_vm_irq_accept(entry->virq_handle, virq); if (virq < 0) return virq; if (irq == -1) irq = hh_rm_virq_to_linux_irq(virq - 32, GIC_SPI, IRQ_TYPE_LEVEL_HIGH); return irq; } EXPORT_SYMBOL(hh_irq_accept); Loading
drivers/virt/haven/hh_rm_core.c +2 −1 Original line number Diff line number Diff line Loading @@ -642,7 +642,7 @@ void *hh_rm_call(hh_rm_msgid_t message_id, return ret; } static int hh_rm_virq_to_linux_irq(u32 virq, u32 type, u32 trigger) int hh_rm_virq_to_linux_irq(u32 virq, u32 type, u32 trigger) { struct irq_fwspec fwspec = {}; Loading @@ -654,6 +654,7 @@ static int hh_rm_virq_to_linux_irq(u32 virq, u32 type, u32 trigger) return irq_create_fwspec_mapping(&fwspec); } EXPORT_SYMBOL(hh_rm_virq_to_linux_irq); static int hh_rm_get_irq(struct hh_vm_get_hyp_res_resp_entry *res_entry) { Loading
drivers/virt/haven/hh_rm_drv_private.h +2 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ #include <linux/types.h> #include <linux/haven/hh_msgq.h> #include <linux/haven/hh_rm_drv.h> #include <linux/haven/hh_common.h> Loading Loading @@ -280,6 +281,7 @@ struct hh_mem_notify_req_payload { /* End Message ID headers */ /* Common function declerations */ int hh_rm_virq_to_linux_irq(u32 virq, u32 type, u32 trigger); int hh_update_vm_prop_table(enum hh_vm_names vm_name, struct hh_vm_property *vm_prop); void *hh_rm_call(hh_rm_msgid_t message_id, Loading