1 /* $NetBSD: hypervisor_machdep.c,v 1.3 2007/12/12 22:16:32 bouyer Exp $ */ 2 3 /* 4 * 5 * Copyright (c) 2004 Christian Limpach. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Christian Limpach. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /****************************************************************************** 35 * hypervisor.c 36 * 37 * Communication to/from hypervisor. 38 * 39 * Copyright (c) 2002-2004, K A Fraser 40 * 41 * Permission is hereby granted, free of charge, to any person obtaining a copy 42 * of this software and associated documentation files (the "Software"), to 43 * deal in the Software without restriction, including without limitation the 44 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 45 * sell copies of the Software, and to permit persons to whom the Software is 46 * furnished to do so, subject to the following conditions: 47 * 48 * The above copyright notice and this permission notice shall be included in 49 * all copies or substantial portions of the Software. 50 * 51 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 52 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 53 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 54 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 55 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 56 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 57 * DEALINGS IN THE SOFTWARE. 58 */ 59 60 61 #include <sys/cdefs.h> 62 __KERNEL_RCSID(0, "$NetBSD: hypervisor_machdep.c,v 1.3 2007/12/12 22:16:32 bouyer Exp $"); 63 64 #include <sys/param.h> 65 #include <sys/systm.h> 66 67 #include <xen/xen.h> 68 #include <xen/hypervisor.h> 69 #include <xen/evtchn.h> 70 #include <machine/atomic.h> 71 72 #include "opt_xen.h" 73 74 // #define PORT_DEBUG 4 75 // #define EARLY_DEBUG_EVENT 76 77 int stipending(void); 78 int 79 stipending() 80 { 81 uint32_t l1; 82 unsigned long l2; 83 unsigned int l1i, l2i, port; 84 volatile shared_info_t *s = HYPERVISOR_shared_info; 85 struct cpu_info *ci; 86 int ret; 87 88 ret = 0; 89 ci = curcpu(); 90 91 #if 0 92 if (HYPERVISOR_shared_info->events) 93 printf("stipending events %08lx mask %08lx ilevel %d\n", 94 HYPERVISOR_shared_info->events, 95 HYPERVISOR_shared_info->events_mask, ci->ci_ilevel); 96 #endif 97 98 #ifdef EARLY_DEBUG_EVENT 99 if (xen_atomic_test_bit(&s->evtchn_pending[0], debug_port)) { 100 xen_debug_handler(NULL); 101 xen_atomic_clear_bit(&s->evtchn_pending[0], debug_port); 102 } 103 #endif 104 105 /* 106 * we're only called after STIC, so we know that we'll have to 107 * STI at the end 108 */ 109 while (s->vcpu_info[0].evtchn_upcall_pending) { 110 cli(); 111 s->vcpu_info[0].evtchn_upcall_pending = 0; 112 /* NB. No need for a barrier here -- XCHG is a barrier 113 * on x86. */ 114 #ifdef XEN3 115 l1 = xen_atomic_xchg(&s->vcpu_info[0].evtchn_pending_sel, 0); 116 #else 117 l1 = xen_atomic_xchg(&s->evtchn_pending_sel, 0); 118 #endif 119 while ((l1i = ffs(l1)) != 0) { 120 l1i--; 121 l1 &= ~(1 << l1i); 122 123 l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i]; 124 /* 125 * mask and clear event. More efficient than calling 126 * hypervisor_mask/clear_event for each event. 127 */ 128 xen_atomic_setbits_l(&s->evtchn_mask[l1i], l2); 129 xen_atomic_clearbits_l(&s->evtchn_pending[l1i], l2); 130 while ((l2i = ffs(l2)) != 0) { 131 l2i--; 132 l2 &= ~(1 << l2i); 133 134 port = (l1i << 5) + l2i; 135 if (evtsource[port]) { 136 hypervisor_set_ipending( 137 evtsource[port]->ev_imask, 138 l1i, l2i); 139 evtsource[port]->ev_evcnt.ev_count++; 140 if (ret == 0 && ci->ci_ilevel < 141 evtsource[port]->ev_maxlevel) 142 ret = 1; 143 } 144 #ifdef DOM0OPS 145 else 146 xenevt_event(port); 147 #endif 148 } 149 } 150 sti(); 151 } 152 153 #if 0 154 if (ci->ci_ipending & 0x1) 155 printf("stipending events %08lx mask %08lx ilevel %d ipending %08x\n", 156 HYPERVISOR_shared_info->events, 157 HYPERVISOR_shared_info->events_mask, ci->ci_ilevel, 158 ci->ci_ipending); 159 #endif 160 161 return (ret); 162 } 163 164 void 165 do_hypervisor_callback(struct intrframe *regs) 166 { 167 uint32_t l1; 168 unsigned long l2; 169 unsigned int l1i, l2i, port; 170 volatile shared_info_t *s = HYPERVISOR_shared_info; 171 struct cpu_info *ci; 172 int level; 173 174 ci = curcpu(); 175 level = ci->ci_ilevel; 176 177 // DDD printf("do_hypervisor_callback\n"); 178 179 #ifdef EARLY_DEBUG_EVENT 180 if (xen_atomic_test_bit(&s->evtchn_pending[0], debug_port)) { 181 xen_debug_handler(NULL); 182 xen_atomic_clear_bit(&s->evtchn_pending[0], debug_port); 183 } 184 #endif 185 186 while (s->vcpu_info[0].evtchn_upcall_pending) { 187 s->vcpu_info[0].evtchn_upcall_pending = 0; 188 /* NB. No need for a barrier here -- XCHG is a barrier 189 * on x86. */ 190 #ifdef XEN3 191 l1 = xen_atomic_xchg(&s->vcpu_info[0].evtchn_pending_sel, 0); 192 #else 193 l1 = xen_atomic_xchg(&s->evtchn_pending_sel, 0); 194 #endif 195 while ((l1i = ffs(l1)) != 0) { 196 l1i--; 197 l1 &= ~(1 << l1i); 198 199 l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i]; 200 /* 201 * mask and clear the pending events. 202 * Doing it here for all event that will be processed 203 * avoids a race with stipending (which can be called 204 * though evtchn_do_event->splx) that could cause an event to 205 * be both processed and marked pending. 206 */ 207 xen_atomic_setbits_l(&s->evtchn_mask[l1i], l2); 208 xen_atomic_clearbits_l(&s->evtchn_pending[l1i], l2); 209 210 while ((l2i = ffs(l2)) != 0) { 211 l2i--; 212 l2 &= ~(1 << l2i); 213 214 port = (l1i << 5) + l2i; 215 #ifdef PORT_DEBUG 216 if (port == PORT_DEBUG) 217 printf("do_hypervisor_callback event %d\n", port); 218 #endif 219 if (evtsource[port]) 220 call_evtchn_do_event(port, regs); 221 #ifdef DOM0OPS 222 else 223 xenevt_event(port); 224 #endif 225 } 226 } 227 } 228 229 #ifdef DIAGNOSTIC 230 if (level != ci->ci_ilevel) 231 printf("hypervisor done %08x level %d/%d ipending %08x\n", 232 #ifdef XEN3 233 (uint)HYPERVISOR_shared_info->vcpu_info[0].evtchn_pending_sel, 234 #else 235 (uint)HYPERVISOR_shared_info->evtchn_pending_sel, 236 #endif 237 level, ci->ci_ilevel, ci->ci_ipending); 238 #endif 239 } 240 241 void 242 hypervisor_unmask_event(unsigned int ev) 243 { 244 volatile shared_info_t *s = HYPERVISOR_shared_info; 245 #ifdef PORT_DEBUG 246 if (ev == PORT_DEBUG) 247 printf("hypervisor_unmask_event %d\n", ev); 248 #endif 249 250 xen_atomic_clear_bit(&s->evtchn_mask[0], ev); 251 /* 252 * The following is basically the equivalent of 253 * 'hw_resend_irq'. Just like a real IO-APIC we 'lose the 254 * interrupt edge' if the channel is masked. 255 */ 256 if (xen_atomic_test_bit(&s->evtchn_pending[0], ev) && 257 #ifdef XEN3 258 !xen_atomic_test_and_set_bit(&s->vcpu_info[0].evtchn_pending_sel, ev>>5)) { 259 #else 260 !xen_atomic_test_and_set_bit(&s->evtchn_pending_sel, ev>>5)) { 261 #endif 262 xen_atomic_set_bit(&s->vcpu_info[0].evtchn_upcall_pending, 0); 263 if (!s->vcpu_info[0].evtchn_upcall_mask) 264 hypervisor_force_callback(); 265 } 266 } 267 268 void 269 hypervisor_mask_event(unsigned int ev) 270 { 271 volatile shared_info_t *s = HYPERVISOR_shared_info; 272 #ifdef PORT_DEBUG 273 if (ev == PORT_DEBUG) 274 printf("hypervisor_mask_event %d\n", ev); 275 #endif 276 277 xen_atomic_set_bit(&s->evtchn_mask[0], ev); 278 } 279 280 void 281 hypervisor_clear_event(unsigned int ev) 282 { 283 volatile shared_info_t *s = HYPERVISOR_shared_info; 284 #ifdef PORT_DEBUG 285 if (ev == PORT_DEBUG) 286 printf("hypervisor_clear_event %d\n", ev); 287 #endif 288 289 xen_atomic_clear_bit(&s->evtchn_pending[0], ev); 290 } 291 292 void 293 hypervisor_enable_ipl(unsigned int ipl) 294 { 295 u_int32_t l1, l2; 296 int l1i, l2i; 297 struct cpu_info *ci = curcpu(); 298 299 /* 300 * enable all events for ipl. As we only set an event in ipl_evt_mask 301 * for its lowest IPL, and pending IPLs are processed high to low, 302 * we know that all callback for this event have been processed. 303 */ 304 305 l1 = ci->ci_isources[ipl]->ipl_evt_mask1; 306 ci->ci_isources[ipl]->ipl_evt_mask1 = 0; 307 while ((l1i = ffs(l1)) != 0) { 308 l1i--; 309 l1 &= ~(1 << l1i); 310 l2 = ci->ci_isources[ipl]->ipl_evt_mask2[l1i]; 311 ci->ci_isources[ipl]->ipl_evt_mask2[l1i] = 0; 312 while ((l2i = ffs(l2)) != 0) { 313 int evtch; 314 315 l2i--; 316 l2 &= ~(1 << l2i); 317 318 evtch = (l1i << 5) + l2i; 319 hypervisor_enable_event(evtch); 320 } 321 } 322 } 323 324 void 325 hypervisor_set_ipending(u_int32_t iplmask, int l1, int l2) 326 { 327 int ipl; 328 struct cpu_info *ci = curcpu(); 329 330 /* set pending bit for the appropriate IPLs */ 331 ci->ci_ipending |= iplmask; 332 333 /* 334 * And set event pending bit for the lowest IPL. As IPL are handled 335 * from high to low, this ensure that all callbacks will have been 336 * called when we ack the event 337 */ 338 ipl = ffs(iplmask); 339 KASSERT(ipl > 0); 340 ipl--; 341 ci->ci_isources[ipl]->ipl_evt_mask1 |= 1 << l1; 342 ci->ci_isources[ipl]->ipl_evt_mask2[l1] |= 1 << l2; 343 } 344