|
17 | 17 | #include <linux/irq.h>
|
18 | 18 | #include <linux/kexec.h>
|
19 | 19 | #include <linux/random.h>
|
| 20 | +#include <linux/seqlock.h> |
20 | 21 | #include <asm/processor.h>
|
21 | 22 | #include <asm/hypervisor.h>
|
22 | 23 | #include <asm/hyperv-tlfs.h>
|
@@ -166,6 +167,15 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_stimer0)
|
166 | 167 | }
|
167 | 168 |
|
168 | 169 | #ifdef CONFIG_HYPERV_VTL_MODE
|
| 170 | +#define REDIRECTED_VECTOR_UNDEF 0xffff |
| 171 | +static u32 redirected_proxy_intr[NR_HV_VTL_REDIRECTED_VECTORS] = { |
| 172 | + [0 ... NR_HV_VTL_REDIRECTED_VECTORS - 1] = REDIRECTED_VECTOR_UNDEF }; |
| 173 | + |
| 174 | +static DEFINE_RAW_SPINLOCK(redirected_proxy_intr_lock); |
| 175 | +static seqcount_raw_spinlock_t redirected_proxy_intr_seq = |
| 176 | + SEQCNT_RAW_SPINLOCK_ZERO(redirected_proxy_intr_seq, |
| 177 | + &redirected_proxy_intr_lock); |
| 178 | + |
169 | 179 | DEFINE_IDTENTRY_IRQ(hv_vtl_redirected_interrupt)
|
170 | 180 | {
|
171 | 181 | apic_eoi();
|
@@ -715,6 +725,83 @@ static bool hv_sev_es_hcall_finish(struct ghcb *ghcb, struct pt_regs *regs)
|
715 | 725 | }
|
716 | 726 | #endif
|
717 | 727 |
|
| 728 | +#ifdef CONFIG_HYPERV_VTL_MODE |
| 729 | +static int find_redirected_proxy_intr(u32 vector) |
| 730 | +{ |
| 731 | + int v; |
| 732 | + |
| 733 | + for (v = 0; v < ARRAY_SIZE(redirected_proxy_intr); v++) { |
| 734 | + if (redirected_proxy_intr[v] == vector) |
| 735 | + return v; |
| 736 | + } |
| 737 | + |
| 738 | + return -ENOENT; |
| 739 | +} |
| 740 | + |
| 741 | +static void redirected_proxy_intr_write_lock(unsigned long *flags) |
| 742 | +{ |
| 743 | + raw_spin_lock_irqsave(&redirected_proxy_intr_lock, *flags); |
| 744 | + write_seqcount_begin(&redirected_proxy_intr_seq); |
| 745 | +} |
| 746 | + |
| 747 | +static void redirected_proxy_intr_write_unlock(unsigned long *flags) |
| 748 | +{ |
| 749 | + write_seqcount_end(&redirected_proxy_intr_seq); |
| 750 | + raw_spin_unlock_irqrestore(&redirected_proxy_intr_lock, *flags); |
| 751 | +} |
| 752 | + |
| 753 | +int mshv_vtl_map_redirected_intr(u32 proxy_vector) |
| 754 | +{ |
| 755 | + int vec_idx; |
| 756 | + unsigned long flags; |
| 757 | + |
| 758 | + if (proxy_vector >= NR_VECTORS) |
| 759 | + return -EINVAL; |
| 760 | + |
| 761 | + redirected_proxy_intr_write_lock(&flags); |
| 762 | + |
| 763 | + /* Check if the vector is already redirected. */ |
| 764 | + vec_idx = find_redirected_proxy_intr(proxy_vector); |
| 765 | + if (vec_idx >= 0) { |
| 766 | + redirected_proxy_intr_write_unlock(&flags); |
| 767 | + /* Caller expects the hardware vector, not the array index. */ |
| 768 | + return vec_idx + FIRST_HV_VTL_REDIRECTED_VECTOR; |
| 769 | + } |
| 770 | + |
| 771 | + /* Now that we know it is not redirected, find a free slot. */ |
| 772 | + vec_idx = find_redirected_proxy_intr(REDIRECTED_VECTOR_UNDEF); |
| 773 | + if (vec_idx < 0) { |
| 774 | + redirected_proxy_intr_write_unlock(&flags); |
| 775 | + return -EBUSY; |
| 776 | + } |
| 777 | + |
| 778 | + redirected_proxy_intr[vec_idx] = proxy_vector; |
| 779 | + |
| 780 | + redirected_proxy_intr_write_unlock(&flags); |
| 781 | + |
| 782 | + /* Caller expects the hardware vector, not the array index. */ |
| 783 | + return vec_idx + FIRST_HV_VTL_REDIRECTED_VECTOR; |
| 784 | +} |
| 785 | + |
| 786 | +int mshv_vtl_unmap_redirected_intr(u32 hw_vector) |
| 787 | +{ |
| 788 | + unsigned long flags; |
| 789 | + int vec_idx = hw_vector - FIRST_HV_VTL_REDIRECTED_VECTOR; |
| 790 | + |
| 791 | + if (vec_idx < 0 || vec_idx >= ARRAY_SIZE(redirected_proxy_intr)) |
| 792 | + return -EINVAL; |
| 793 | + |
| 794 | + if (redirected_proxy_intr[vec_idx] == REDIRECTED_VECTOR_UNDEF) |
| 795 | + return -ENOENT; |
| 796 | + |
| 797 | + redirected_proxy_intr_write_lock(&flags); |
| 798 | + redirected_proxy_intr[vec_idx] = REDIRECTED_VECTOR_UNDEF; |
| 799 | + redirected_proxy_intr_write_unlock(&flags); |
| 800 | + |
| 801 | + return 0; |
| 802 | +} |
| 803 | +#endif /* CONFIG_HYPERV_VTL_MODE */ |
| 804 | + |
718 | 805 | const __initconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
|
719 | 806 | .name = "Microsoft Hyper-V",
|
720 | 807 | .detect = ms_hyperv_platform,
|
|
0 commit comments