1 /*-
2  * Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
3  * Copyright (c) 2017-2022 Intel Corporation.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28 
29 #ifndef VPIC_H
30 #define VPIC_H
31 
32 /**
33  * @file vpic.h
34  *
35  * @brief public APIs for virtual PIC
36  */
37 
38 
39 #define	ICU_IMR_OFFSET	1U
40 
41 /* Initialization control word 1. Written to even address. */
42 #define	ICW1_IC4	0x01U		/* ICW4 present */
43 #define	ICW1_SNGL	0x02U		/* 1 = single, 0 = cascaded */
44 #define	ICW1_ADI	0x04U		/* 1 = 4, 0 = 8 byte vectors */
45 #define	ICW1_LTIM	0x08U		/* 1 = level trigger, 0 = edge */
46 #define	ICW1_RESET	0x10U		/* must be 1 */
47 /* 0x20 - 0x80 - in 8080/8085 mode only */
48 
49 /* Initialization control word 2. Written to the odd address. */
50 /* No definitions, it is the base vector of the IDT for 8086 mode */
51 
52 /* Initialization control word 3. Written to the odd address. */
53 /* For a primary PIC, bitfield indicating a secondary PIC on given input */
54 /* For a secondary PIC, lower 3 bits are the PIC's ID binary id on primary PIC */
55 
56 /* Initialization control word 4. Written to the odd address. */
57 #define	ICW4_8086	0x01U		/* 1 = 8086, 0 = 8080 */
58 #define	ICW4_AEOI	0x02U		/* 1 = Auto EOI */
59 #define	ICW4_MS		0x04U		/* 1 = buffered primary PIC, 0 = secondary PIC*/
60 #define	ICW4_BUF	0x08U		/* 1 = enable buffer mode */
61 #define	ICW4_SFNM	0x10U		/* 1 = special fully nested mode */
62 
63 /* Operation control words.  Written after initialization. */
64 
65 /* Operation control word type 1 */
66 /*
67  * No definitions.  Written to the odd address.  Bitmask for interrupts.
68  * 1 = disabled.
69  */
70 
71 /* Operation control word type 2.  Bit 3 (0x08) must be zero. Even address. */
72 #define	OCW2_L0		0x01U		/* Level */
73 #define	OCW2_L1		0x02U
74 #define	OCW2_L2		0x04U
75 /* 0x08 must be 0 to select OCW2 vs OCW3 */
76 /* 0x10 must be 0 to select OCW2 vs ICW1 */
77 #define	OCW2_EOI	0x20U		/* 1 = EOI */
78 #define	OCW2_SL		0x40U		/* EOI mode */
79 #define	OCW2_R		0x80U		/* EOI mode */
80 
81 /* Operation control word type 3.  Bit 3 (0x08) must be set. Even address. */
82 #define	OCW3_RIS	0x01U		/* 1 = read IS, 0 = read IR */
83 #define	OCW3_RR		0x02U		/* register read */
84 #define	OCW3_P		0x04U		/* poll mode command */
85 /* 0x08 must be 1 to select OCW3 vs OCW2 */
86 #define	OCW3_SEL	0x08U		/* must be 1 */
87 /* 0x10 must be 0 to select OCW3 vs ICW1 */
88 #define	OCW3_SMM	0x20U		/* special mode mask */
89 #define	OCW3_ESMM	0x40U		/* enable SMM */
90 
91 #define	IO_ELCR1	0x4d0U
92 #define	IO_ELCR2	0x4d1U
93 
94 #define NR_VPIC_PINS_PER_CHIP	8U
95 #define NR_VPIC_PINS_TOTAL	16U
96 
97 enum vpic_wire_mode {
98 	VPIC_WIRE_INTR = 0,
99 	VPIC_WIRE_LAPIC,
100 	VPIC_WIRE_IOAPIC,
101 	VPIC_WIRE_NULL
102 };
103 
104 enum vpic_trigger {
105 	EDGE_TRIGGER,
106 	LEVEL_TRIGGER
107 };
108 
109 struct i8259_reg_state {
110 	bool		ready;
111 	uint8_t		icw_num;
112 	uint8_t		rd_cmd_reg;
113 
114 	bool		aeoi;
115 	bool		poll;
116 	bool		rotate;
117 	bool		sfn;		/* special fully-nested mode */
118 
119 	uint32_t	irq_base;
120 	uint8_t		request;	/* Interrupt Request Register (IIR) */
121 	uint8_t		service;	/* Interrupt Service (ISR) */
122 	uint8_t		mask;		/* Interrupt Mask Register (IMR) */
123 	uint8_t		smm;		/* special mask mode */
124 
125 	uint8_t		pin_state[8];	/* pin state for level */
126 	uint32_t	lowprio;	/* lowest priority irq */
127 
128 	bool		intr_raised;
129 	uint8_t		elc;
130 };
131 
132 struct acrn_vpic {
133 	spinlock_t	lock;
134 	struct i8259_reg_state	i8259[2];
135 };
136 
137 struct acrn_vm;
138 void vpic_init(struct acrn_vm *vm);
139 
140 /**
141  * @brief virtual PIC
142  *
143  * @addtogroup acrn_vpic ACRN vPIC
144  * @{
145  */
146 
147 /**
148  * @brief Set vPIC IRQ line status.
149  *
150  * @param[in] vpic      Pointer to target VM's vpic table
151  * @param[in] vgsi      GSI for the virtual interrupt
152  * @param[in] operation action options:GSI_SET_HIGH/GSI_SET_LOW/
153  *			GSI_RAISING_PULSE/GSI_FALLING_PULSE
154  */
155 void vpic_set_irqline(struct acrn_vpic *vpic, uint32_t vgsi, uint32_t operation);
156 
157 /**
158  * @brief Get pending virtual interrupts for vPIC.
159  *
160  * @param[in]    vpic   Pointer to target VM's vpic table
161  * @param[inout] vecptr Pointer to vector buffer and will be filled
162  *			with eligible vector if any.
163  */
164 void vpic_pending_intr(struct acrn_vpic *vpic, uint32_t *vecptr);
165 
166 /**
167  * @brief Accept virtual interrupt for vPIC.
168  *
169  * @param[in] vpic     Pointer to target VM's vpic table
170  * @param[in] vector Target virtual interrupt vector
171  *
172  * @pre vm != NULL
173  */
174 void vpic_intr_accepted(struct acrn_vpic *vpic, uint32_t vector);
175 void vpic_get_irqline_trigger_mode(const struct acrn_vpic *vpic, uint32_t vgsi, enum vpic_trigger *trigger);
176 uint32_t vpic_pincount(void);
177 struct acrn_vpic *vm_pic(const struct acrn_vm *vm);
178 
179 /**
180  * @}
181  */
182 /* End of acrn_vpic */
183 
184 #endif /* VPIC_H */
185