1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* io.h: HVM IO support
*
* Copyright (c) 2004, Intel Corporation.
*/
#ifndef __ASM_X86_HVM_IO_H__
#define __ASM_X86_HVM_IO_H__
#include <xen/pci.h>
#include <public/hvm/ioreq.h>
#define NR_IO_HANDLERS 32
typedef int (*hvm_mmio_read_t)(struct vcpu *v,
unsigned long addr,
unsigned int length,
unsigned long *val);
typedef int (*hvm_mmio_write_t)(struct vcpu *v,
unsigned long addr,
unsigned int length,
unsigned long val);
typedef int (*hvm_mmio_check_t)(struct vcpu *v, unsigned long addr);
struct hvm_mmio_ops {
hvm_mmio_check_t check;
hvm_mmio_read_t read;
hvm_mmio_write_t write;
};
typedef int (*portio_action_t)(
int dir, unsigned int port, unsigned int bytes, uint32_t *val);
struct hvm_io_handler {
union {
struct {
const struct hvm_mmio_ops *ops;
} mmio;
struct {
unsigned int port, size;
portio_action_t action;
} portio;
};
const struct hvm_io_ops *ops;
uint8_t type;
};
typedef int (*hvm_io_read_t)(const struct hvm_io_handler *,
uint64_t addr,
uint32_t size,
uint64_t *data);
typedef int (*hvm_io_write_t)(const struct hvm_io_handler *,
uint64_t addr,
uint32_t size,
uint64_t data);
typedef bool_t (*hvm_io_accept_t)(const struct hvm_io_handler *,
const ioreq_t *p);
typedef void (*hvm_io_complete_t)(const struct hvm_io_handler *);
struct hvm_io_ops {
hvm_io_accept_t accept;
hvm_io_read_t read;
hvm_io_write_t write;
hvm_io_complete_t complete;
};
int hvm_process_io_intercept(const struct hvm_io_handler *handler,
ioreq_t *p);
int hvm_io_intercept(ioreq_t *p);
struct hvm_io_handler *hvm_next_io_handler(struct domain *d);
bool_t hvm_mmio_internal(paddr_t gpa);
void register_mmio_handler(struct domain *d,
const struct hvm_mmio_ops *ops);
void register_portio_handler(
struct domain *d, unsigned int port, unsigned int size,
portio_action_t action);
bool relocate_portio_handler(
struct domain *d, unsigned int old_port, unsigned int new_port,
unsigned int size);
void send_timeoffset_req(unsigned long timeoff);
bool handle_mmio_with_translation(unsigned long gla, unsigned long gpfn,
struct npfec);
bool handle_pio(uint16_t port, unsigned int size, int dir);
void hvm_interrupt_post(struct vcpu *v, int vector, int type);
void hvm_dpci_eoi(struct domain *d, unsigned int guest_irq);
void msix_write_completion(struct vcpu *);
#ifdef CONFIG_HVM
void msixtbl_init(struct domain *d);
#else
static inline void msixtbl_init(struct domain *d) {}
#endif
/* Arch-specific MSI data for vPCI. */
struct vpci_arch_msi {
int pirq;
bool bound;
};
/* Arch-specific MSI-X entry data for vPCI. */
struct vpci_arch_msix_entry {
int pirq;
};
enum stdvga_cache_state {
STDVGA_CACHE_UNINITIALIZED,
STDVGA_CACHE_ENABLED,
STDVGA_CACHE_DISABLED
};
struct hvm_hw_stdvga {
uint8_t sr_index;
uint8_t sr[8];
uint8_t gr_index;
uint8_t gr[9];
bool_t stdvga;
enum stdvga_cache_state cache;
uint32_t latch;
struct page_info *vram_page[64]; /* shadow of 0xa0000-0xaffff */
spinlock_t lock;
};
void stdvga_init(struct domain *d);
void stdvga_deinit(struct domain *d);
extern void hvm_dpci_msi_eoi(struct domain *d, int vector);
/* Decode a PCI port IO access into a bus/slot/func/reg. */
unsigned int hvm_pci_decode_addr(unsigned int cf8, unsigned int addr,
pci_sbdf_t *sbdf);
/*
* HVM port IO handler that performs forwarding of guest IO ports into machine
* IO ports.
*/
void register_g2m_portio_handler(struct domain *d);
/* HVM port IO handler for vPCI accesses. */
void register_vpci_portio_handler(struct domain *d);
/* HVM MMIO handler for PCI MMCFG accesses. */
int register_vpci_mmcfg_handler(struct domain *d, paddr_t addr,
unsigned int start_bus, unsigned int end_bus,
unsigned int seg);
/* Destroy tracked MMCFG areas. */
void destroy_vpci_mmcfg(struct domain *d);
/* Check if an address is between a MMCFG region for a domain. */
bool vpci_is_mmcfg_address(const struct domain *d, paddr_t addr);
#endif /* __ASM_X86_HVM_IO_H__ */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/
|