1 /*
2 * Copyright (c) 2016 Mike Belopuhov <mike@esdenera.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #ifndef _DEV_PV_HYPERVVAR_H_
18 #define _DEV_PV_HYPERVVAR_H_
19
20 /* #define HYPERV_DEBUG */
21
22 #ifdef HYPERV_DEBUG
23 #define DPRINTF(x...) printf(x)
24 #else
25 #define DPRINTF(x...)
26 #endif
27
28 struct hv_softc;
29
30 struct hv_msg {
31 uint64_t msg_flags;
32 #define MSGF_NOSLEEP 0x0001
33 #define MSGF_NOQUEUE 0x0002
34 #define MSGF_ORPHANED 0x0004
35 struct hypercall_postmsg_in msg_req; /* must be 8 byte aligned */
36 void *msg_rsp;
37 size_t msg_rsplen;
38 TAILQ_ENTRY(hv_msg) msg_entry;
39 };
40 TAILQ_HEAD(hv_queue, hv_msg);
41
42 struct hv_offer {
43 struct vmbus_chanmsg_choffer co_chan;
44 SIMPLEQ_ENTRY(hv_offer) co_entry;
45 };
46 SIMPLEQ_HEAD(hv_offers, hv_offer);
47
48 struct hv_ring_data {
49 struct vmbus_bufring *rd_ring;
50 uint32_t rd_size;
51 struct mutex rd_lock;
52 uint32_t rd_prod;
53 uint32_t rd_cons;
54 uint32_t rd_dsize;
55 };
56
57 struct hv_channel {
58 struct hv_softc *ch_sc;
59
60 int ch_state;
61 #define HV_CHANSTATE_OFFERED 1
62 #define HV_CHANSTATE_OPENED 2
63 #define HV_CHANSTATE_CLOSING 3
64 #define HV_CHANSTATE_CLOSED 4
65 uint32_t ch_id;
66
67 struct hv_guid ch_type;
68 struct hv_guid ch_inst;
69 char ch_ident[38];
70
71 void *ch_ring;
72 uint32_t ch_ring_gpadl;
73 u_long ch_ring_size;
74
75 struct hv_ring_data ch_wrd;
76 struct hv_ring_data ch_rrd;
77
78 uint32_t ch_vcpu;
79
80 void (*ch_handler)(void *);
81 void *ch_ctx;
82 struct evcount ch_evcnt;
83 struct taskq *ch_taskq;
84 struct task ch_task;
85
86 uint32_t ch_flags;
87 #define CHF_BATCHED 0x0001
88 #define CHF_MONITOR 0x0002
89
90 uint8_t ch_mgroup;
91 uint8_t ch_mindex;
92 struct hv_mon_param ch_monprm __attribute__((aligned(8)));
93
94 TAILQ_ENTRY(hv_channel) ch_entry;
95 };
96 TAILQ_HEAD(hv_channels, hv_channel);
97
98 struct hv_attach_args {
99 void *aa_parent;
100 bus_dma_tag_t aa_dmat;
101 struct hv_guid *aa_type;
102 struct hv_guid *aa_inst;
103 char *aa_ident;
104 struct hv_channel *aa_chan;
105 };
106
107 struct hv_dev {
108 struct hv_attach_args dv_aa;
109 SLIST_ENTRY(hv_dev) dv_entry;
110 };
111 SLIST_HEAD(hv_devices, hv_dev);
112
113 struct hv_softc {
114 struct device sc_dev;
115 struct pvbus_hv *sc_pvbus;
116 struct bus_dma_tag *sc_dmat;
117
118 void *sc_hc;
119 uint32_t sc_features;
120
121 uint32_t sc_flags;
122 #define HSF_CONNECTED 0x0001
123 #define HSF_OFFERS_DELIVERED 0x0002
124
125 int sc_idtvec;
126 int sc_proto;
127
128 /* CPU id to VCPU id mapping */
129 uint32_t sc_vcpus[1]; /* XXX: per-cpu */
130 /* Synthetic Interrupt Message Page (SIMP) */
131 void *sc_simp[1]; /* XXX: per-cpu */
132 /* Synthetic Interrupt Event Flags Page (SIEFP) */
133 void *sc_siep[1]; /* XXX: per-cpu */
134
135 /* Channel port events page */
136 void *sc_events;
137 u_long *sc_wevents; /* Write events */
138 u_long *sc_revents; /* Read events */
139
140 /* Monitor pages for parent<->child notifications */
141 struct vmbus_mnf *sc_monitor[2];
142
143 struct hv_queue sc_reqs; /* Request queue */
144 struct mutex sc_reqlck;
145 struct hv_queue sc_rsps; /* Response queue */
146 struct mutex sc_rsplck;
147
148 struct hv_offers sc_offers;
149 struct mutex sc_offerlck;
150
151 struct hv_channels sc_channels;
152 struct mutex sc_channelck;
153
154 volatile uint32_t sc_handle;
155
156 struct hv_devices sc_devs;
157 struct mutex sc_devlck;
158
159 struct task sc_sdtask; /* shutdown */
160
161 struct ksensordev sc_sensordev;
162 struct ksensor sc_sensor;
163 };
164
165 static __inline void
clear_bit(u_int b,volatile void * p)166 clear_bit(u_int b, volatile void *p)
167 {
168 atomic_clearbits_int(((volatile u_int *)p) + (b >> 5), 1 << (b & 0x1f));
169 }
170
171 static __inline void
set_bit(u_int b,volatile void * p)172 set_bit(u_int b, volatile void *p)
173 {
174 atomic_setbits_int(((volatile u_int *)p) + (b >> 5), 1 << (b & 0x1f));
175 }
176
177 static __inline int
test_bit(u_int b,volatile void * p)178 test_bit(u_int b, volatile void *p)
179 {
180 return !!(((volatile u_int *)p)[b >> 5] & (1 << (b & 0x1f)));
181 }
182
183 extern const struct hv_guid hv_guid_network;
184 extern const struct hv_guid hv_guid_ide;
185 extern const struct hv_guid hv_guid_scsi;
186 extern const struct hv_guid hv_guid_shutdown;
187 extern const struct hv_guid hv_guid_timesync;
188 extern const struct hv_guid hv_guid_heartbeat;
189 extern const struct hv_guid hv_guid_kvp;
190 #ifdef HYPERV_DEBUG
191 extern const struct hv_guid hv_guid_vss;
192 extern const struct hv_guid hv_guid_dynmem;
193 extern const struct hv_guid hv_guid_mouse;
194 extern const struct hv_guid hv_guid_kbd;
195 extern const struct hv_guid hv_guid_video;
196 extern const struct hv_guid hv_guid_fc;
197 extern const struct hv_guid hv_guid_fcopy;
198 extern const struct hv_guid hv_guid_pcie;
199 extern const struct hv_guid hv_guid_netdir;
200 extern const struct hv_guid hv_guid_rdesktop;
201 extern const struct hv_guid hv_guid_avma1;
202 extern const struct hv_guid hv_guid_avma2;
203 extern const struct hv_guid hv_guid_avma3;
204 extern const struct hv_guid hv_guid_avma4;
205 #endif /* HYPERV_DEBUG */
206
207 int hv_handle_alloc(struct hv_channel *, void *, uint32_t, uint32_t *);
208 void hv_handle_free(struct hv_channel *, uint32_t);
209 int hv_channel_open(struct hv_channel *, size_t, void *, size_t,
210 void (*)(void *), void *);
211 int hv_channel_close(struct hv_channel *);
212 int hv_channel_setdeferred(struct hv_channel *, const char *);
213 void hv_channel_schedule(struct hv_channel *);
214 void hv_evcount_attach(struct hv_channel *, const char *);
215 int hv_channel_send(struct hv_channel *, void *, uint32_t, uint64_t,
216 int, uint32_t);
217 int hv_channel_send_sgl(struct hv_channel *, struct vmbus_gpa *,
218 uint32_t, void *, uint32_t, uint64_t);
219 int hv_channel_send_prpl(struct hv_channel *, struct vmbus_gpa_range *,
220 uint32_t, void *, uint32_t, uint64_t);
221 int hv_channel_recv(struct hv_channel *, void *, uint32_t, uint32_t *,
222 uint64_t *, int);
223
224 #endif /* _DEV_PV_HYPERVVAR_H_ */
225