1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4 */
5
6 #ifndef __LS7A_KVM_IRQ_H
7 #define __LS7A_KVM_IRQ_H
8
9 #include <linux/mm_types.h>
10 #include <linux/hrtimer.h>
11 #include <linux/kvm_host.h>
12 #include <linux/spinlock.h>
13 #include <loongson.h>
14 #include <linux/seq_file.h>
15 #include "kvmcpu.h"
16
17 #include <kvm/iodev.h>
18
19 #define LS7A_APIC_NUM_PINS 64
20
21 #define LS7A_ROUTE_ENTRY_OFFSET 0x100
22 #define LS7A_INT_ID_OFFSET 0x0
23 #define LS7A_INT_ID_VAL 0x7000000UL
24 #define LS7A_INT_ID_VER 0x1f0001UL
25 #define LS7A_INT_MASK_OFFSET 0x20
26 #define LS7A_INT_EDGE_OFFSET 0x60
27 #define LS7A_INT_CLEAR_OFFSET 0x80
28 #define LS7A_INT_STATUS_OFFSET 0x3a0
29 #define LS7A_INT_POL_OFFSET 0x3e0
30 #define LS7A_HTMSI_EN_OFFSET 0x40
31 #define LS7A_HTMSI_VEC_OFFSET 0x200
32 #define LS7A_AUTO_CTRL0_OFFSET 0xc0
33 #define LS7A_AUTO_CTRL1_OFFSET 0xe0
34
35 #define LS7A_IOAPIC_GUEST_REG_BASE 0x10000000UL
36 #define LS7A_IOAPIC_GUEST_REG_BASE_ALIAS 0xe0010000000UL
37
38 #define LS7A_IOAPIC_NUM_PINS 32
39
40 typedef struct kvm_ls7a_ioapic_state {
41 u64 int_id;
42 /* 0x020 interrupt mask register */
43 u64 int_mask;
44 /* 0x040 1=msi */
45 u64 htmsi_en;
46 /* 0x060 edge=1 level =0 */
47 u64 intedge;
48 /* 0x080 for clean edge int,set 1 clean,set 0 is noused */
49 u64 intclr;
50 /* 0x0c0 */
51 u64 auto_crtl0;
52 /* 0x0e0 */
53 u64 auto_crtl1;
54 /* 0x100 - 0x140 */
55 u8 route_entry[64];
56 /* 0x200 - 0x240 */
57 u8 htmsi_vector[64];
58 /* 0x300 */
59 u64 intisr_chip0;
60 /* 0x320 */
61 u64 intisr_chip1;
62 /* edge detection */
63 u64 last_intirr;
64 /* 0x380 interrupt request register */
65 u64 intirr;
66 /* 0x3a0 interrupt service register */
67 u64 intisr;
68 /* 0x3e0 interrupt level polarity selection register,
69 * 0 for high level tirgger
70 */
71 u64 int_polarity;
72 } LS7AApicState;
73
74 struct ls7a_kvm_ioapic {
75 spinlock_t lock;
76 bool wakeup_needed;
77 unsigned pending_acks;
78 struct kvm *kvm;
79 struct kvm_ls7a_ioapic_state ls7a_ioapic;
80 struct kvm_io_device dev_ls7a_ioapic;
81 struct kvm_io_device ls7a_ioapic_alias;
82 void (*ack_notifier)(void *opaque, int irq);
83 unsigned long irq_states[LS7A_APIC_NUM_PINS];
84 };
85
ls7a_ioapic_irqchip(struct kvm *kvm)86 static inline struct ls7a_kvm_ioapic *ls7a_ioapic_irqchip(struct kvm *kvm)
87 {
88 return kvm->arch.v_ioapic;
89 }
90
ls7a_ioapic_in_kernel(struct kvm *kvm)91 static inline int ls7a_ioapic_in_kernel(struct kvm *kvm)
92 {
93 int ret;
94
95 ret = (ls7a_ioapic_irqchip(kvm) != NULL);
96 return ret;
97 }
98
99 int kvm_set_ls7a_ioapic(struct kvm *kvm, struct ls7a_ioapic_state *state);
100 int kvm_get_ls7a_ioapic(struct kvm *kvm, struct ls7a_ioapic_state *state);
101 int kvm_create_ls7a_ioapic(struct kvm *kvm);
102 void kvm_destroy_ls7a_ioapic(struct kvm *kvm);
103 int kvm_ls7a_ioapic_set_irq(struct kvm *kvm, int irq, int level);
104
105 void ls7a_ioapic_lock(struct ls7a_kvm_ioapic *s, unsigned long *flags);
106 void ls7a_ioapic_unlock(struct ls7a_kvm_ioapic *s, unsigned long *flags);
107 int kvm_ls7a_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi);
108 int kvm_ls7a_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,
109 int irq_source_id, int level, bool line_status);
110
111 void kvm_dump_ls7a_ioapic_state(struct seq_file *m, struct ls7a_kvm_ioapic *ioapic);
112 #endif
113