1 /*
2  * io.h: HVM IO support
3  *
4  * Copyright (c) 2004, Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * this program; If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef __ASM_X86_HVM_IO_H__
20 #define __ASM_X86_HVM_IO_H__
21 
22 #include <xen/pci.h>
23 #include <public/hvm/ioreq.h>
24 
25 #define NR_IO_HANDLERS 32
26 
27 typedef int (*hvm_mmio_read_t)(struct vcpu *v,
28                                unsigned long addr,
29                                unsigned int length,
30                                unsigned long *val);
31 typedef int (*hvm_mmio_write_t)(struct vcpu *v,
32                                 unsigned long addr,
33                                 unsigned int length,
34                                 unsigned long val);
35 typedef int (*hvm_mmio_check_t)(struct vcpu *v, unsigned long addr);
36 
37 struct hvm_mmio_ops {
38     hvm_mmio_check_t check;
39     hvm_mmio_read_t  read;
40     hvm_mmio_write_t write;
41 };
42 
hvm_mmio_first_byte(const ioreq_t * p)43 static inline paddr_t hvm_mmio_first_byte(const ioreq_t *p)
44 {
45     return unlikely(p->df) ?
46            p->addr - (p->count - 1ul) * p->size :
47            p->addr;
48 }
49 
hvm_mmio_last_byte(const ioreq_t * p)50 static inline paddr_t hvm_mmio_last_byte(const ioreq_t *p)
51 {
52     unsigned long size = p->size;
53 
54     return unlikely(p->df) ?
55            p->addr + size - 1:
56            p->addr + (p->count * size) - 1;
57 }
58 
59 typedef int (*portio_action_t)(
60     int dir, unsigned int port, unsigned int bytes, uint32_t *val);
61 
62 struct hvm_io_handler {
63     union {
64         struct {
65             const struct hvm_mmio_ops *ops;
66         } mmio;
67         struct {
68             unsigned int port, size;
69             portio_action_t action;
70         } portio;
71     };
72     const struct hvm_io_ops *ops;
73     uint8_t type;
74 };
75 
76 typedef int (*hvm_io_read_t)(const struct hvm_io_handler *,
77                              uint64_t addr,
78                              uint32_t size,
79                              uint64_t *data);
80 typedef int (*hvm_io_write_t)(const struct hvm_io_handler *,
81                               uint64_t addr,
82                               uint32_t size,
83                               uint64_t data);
84 typedef bool_t (*hvm_io_accept_t)(const struct hvm_io_handler *,
85                                   const ioreq_t *p);
86 typedef void (*hvm_io_complete_t)(const struct hvm_io_handler *);
87 
88 struct hvm_io_ops {
89     hvm_io_accept_t   accept;
90     hvm_io_read_t     read;
91     hvm_io_write_t    write;
92     hvm_io_complete_t complete;
93 };
94 
95 int hvm_process_io_intercept(const struct hvm_io_handler *handler,
96                              ioreq_t *p);
97 
98 int hvm_io_intercept(ioreq_t *p);
99 
100 struct hvm_io_handler *hvm_next_io_handler(struct domain *d);
101 
102 bool_t hvm_mmio_internal(paddr_t gpa);
103 
104 void register_mmio_handler(struct domain *d,
105                            const struct hvm_mmio_ops *ops);
106 
107 void register_portio_handler(
108     struct domain *d, unsigned int port, unsigned int size,
109     portio_action_t action);
110 
111 bool relocate_portio_handler(
112     struct domain *d, unsigned int old_port, unsigned int new_port,
113     unsigned int size);
114 
115 void send_timeoffset_req(unsigned long timeoff);
116 void send_invalidate_req(void);
117 bool handle_mmio_with_translation(unsigned long gla, unsigned long gpfn,
118                                   struct npfec);
119 bool handle_pio(uint16_t port, unsigned int size, int dir);
120 void hvm_interrupt_post(struct vcpu *v, int vector, int type);
121 void hvm_dpci_eoi(struct domain *d, unsigned int guest_irq,
122                   const union vioapic_redir_entry *ent);
123 void msix_write_completion(struct vcpu *);
124 
125 #ifdef CONFIG_HVM
126 void msixtbl_init(struct domain *d);
127 #else
msixtbl_init(struct domain * d)128 static inline void msixtbl_init(struct domain *d) {}
129 #endif
130 
131 /* Arch-specific MSI data for vPCI. */
132 struct vpci_arch_msi {
133     int pirq;
134 };
135 
136 /* Arch-specific MSI-X entry data for vPCI. */
137 struct vpci_arch_msix_entry {
138     int pirq;
139 };
140 
141 enum stdvga_cache_state {
142     STDVGA_CACHE_UNINITIALIZED,
143     STDVGA_CACHE_ENABLED,
144     STDVGA_CACHE_DISABLED
145 };
146 
147 struct hvm_hw_stdvga {
148     uint8_t sr_index;
149     uint8_t sr[8];
150     uint8_t gr_index;
151     uint8_t gr[9];
152     bool_t stdvga;
153     enum stdvga_cache_state cache;
154     uint32_t latch;
155     struct page_info *vram_page[64];  /* shadow of 0xa0000-0xaffff */
156     spinlock_t lock;
157 };
158 
159 void stdvga_init(struct domain *d);
160 void stdvga_deinit(struct domain *d);
161 
162 extern void hvm_dpci_msi_eoi(struct domain *d, int vector);
163 
164 /* Decode a PCI port IO access into a bus/slot/func/reg. */
165 unsigned int hvm_pci_decode_addr(unsigned int cf8, unsigned int addr,
166                                  pci_sbdf_t *sbdf);
167 
168 /*
169  * HVM port IO handler that performs forwarding of guest IO ports into machine
170  * IO ports.
171  */
172 void register_g2m_portio_handler(struct domain *d);
173 
174 /* HVM port IO handler for vPCI accesses. */
175 void register_vpci_portio_handler(struct domain *d);
176 
177 /* HVM MMIO handler for PCI MMCFG accesses. */
178 int register_vpci_mmcfg_handler(struct domain *d, paddr_t addr,
179                                 unsigned int start_bus, unsigned int end_bus,
180                                 unsigned int seg);
181 /* Destroy tracked MMCFG areas. */
182 void destroy_vpci_mmcfg(struct domain *d);
183 
184 /* Check if an address is between a MMCFG region for a domain. */
185 bool vpci_is_mmcfg_address(const struct domain *d, paddr_t addr);
186 
187 #endif /* __ASM_X86_HVM_IO_H__ */
188 
189 
190 /*
191  * Local variables:
192  * mode: C
193  * c-file-style: "BSD"
194  * c-basic-offset: 4
195  * tab-width: 4
196  * indent-tabs-mode: nil
197  * End:
198  */
199