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