ia64/xen-unstable
changeset 7660:9bb7a75f120f
This patch add virtual IOAPIC support for VMX guest.
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Signed-off-by: Xin Li <xin.b.li@intel.com>
Signed-off-by: Eddie Dong <eddie.dong@intel.com>
Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Signed-off-by: Xin Li <xin.b.li@intel.com>
Signed-off-by: Eddie Dong <eddie.dong@intel.com>
Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Mon Nov 07 16:36:27 2005 +0100 (2005-11-07) |
parents | 781b6dd73e4c |
children | 63aeaa2152d8 |
files | xen/arch/x86/dm/i8259.c xen/arch/x86/dm/vmx_vioapic.c xen/arch/x86/vmx_intercept.c xen/arch/x86/vmx_vlapic.c xen/arch/x86/vmx_vmcs.c xen/include/asm-x86/vmx_platform.h xen/include/asm-x86/vmx_vioapic.h xen/include/asm-x86/vmx_vmcs.h |
line diff
1.1 --- a/xen/arch/x86/dm/i8259.c Mon Nov 07 16:35:46 2005 +0100 1.2 +++ b/xen/arch/x86/dm/i8259.c Mon Nov 07 16:36:27 2005 +0100 1.3 @@ -33,6 +33,7 @@ 1.4 #include <asm/vmx.h> 1.5 #include <public/io/vmx_vpic.h> 1.6 #include <asm/current.h> 1.7 +#include <asm/vmx_vioapic.h> 1.8 #include <asm/vmx_vlapic.h> 1.9 1.10 /* set irq level. If an edge is detected, then the IRR is set to 1 */ 1.11 @@ -124,6 +125,7 @@ void pic_set_irq_new(void *opaque, int i 1.12 { 1.13 struct vmx_virpic *s = opaque; 1.14 1.15 + vmx_vioapic_set_irq(current->domain, irq, level); 1.16 pic_set_irq1(&s->pics[irq >> 3], irq & 7, level); 1.17 /* used for IOAPIC irqs */ 1.18 if (s->alt_irq_func) 1.19 @@ -135,6 +137,7 @@ void do_pic_irqs (struct vmx_virpic *s, 1.20 { 1.21 s->pics[1].irr |= (uint8_t)(irqs >> 8); 1.22 s->pics[0].irr |= (uint8_t) irqs; 1.23 + vmx_vioapic_do_irqs(current->domain, irqs); 1.24 pic_update_irq(s); 1.25 } 1.26 1.27 @@ -142,6 +145,7 @@ void do_pic_irqs_clear (struct vmx_virpi 1.28 { 1.29 s->pics[1].irr &= ~(uint8_t)(irqs >> 8); 1.30 s->pics[0].irr &= ~(uint8_t) irqs; 1.31 + vmx_vioapic_do_irqs_clear(current->domain, irqs); 1.32 pic_update_irq(s); 1.33 } 1.34 1.35 @@ -521,7 +525,13 @@ int cpu_get_pic_interrupt(struct vcpu *v 1.36 1.37 int is_pit_irq(struct vcpu *v, int irq, int type) 1.38 { 1.39 - int pit_vec = v->domain->arch.vmx_platform.vmx_pic.pics[0].irq_base; 1.40 + int pit_vec; 1.41 + 1.42 + if (type == VLAPIC_DELIV_MODE_EXT) 1.43 + pit_vec = v->domain->arch.vmx_platform.vmx_pic.pics[0].irq_base; 1.44 + else 1.45 + pit_vec = 1.46 + v->domain->arch.vmx_platform.vmx_vioapic.redirtbl[0].RedirForm.vector; 1.47 1.48 return (irq == pit_vec); 1.49 }
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/xen/arch/x86/dm/vmx_vioapic.c Mon Nov 07 16:36:27 2005 +0100 2.3 @@ -0,0 +1,608 @@ 2.4 +/* 2.5 +* Copyright (C) 2001 MandrakeSoft S.A. 2.6 +* 2.7 +* MandrakeSoft S.A. 2.8 +* 43, rue d'Aboukir 2.9 +* 75002 Paris - France 2.10 +* http://www.linux-mandrake.com/ 2.11 +* http://www.mandrakesoft.com/ 2.12 +* 2.13 +* This library is free software; you can redistribute it and/or 2.14 +* modify it under the terms of the GNU Lesser General Public 2.15 +* License as published by the Free Software Foundation; either 2.16 +* version 2 of the License, or (at your option) any later version. 2.17 +* 2.18 +* This library is distributed in the hope that it will be useful, 2.19 +* but WITHOUT ANY WARRANTY; without even the implied warranty of 2.20 +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2.21 +* Lesser General Public License for more details. 2.22 +* 2.23 +* You should have received a copy of the GNU Lesser General Public 2.24 +* License along with this library; if not, write to the Free Software 2.25 +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 2.26 +*/ 2.27 + 2.28 +/* 2.29 +* Yunhong Jiang <yunhong.jiang@intel.com> 2.30 +* Ported to xen by using virtual IRQ line. 2.31 +*/ 2.32 + 2.33 +#include <asm/vmx_vioapic.h> 2.34 +#include <asm/vmx_platform.h> 2.35 + 2.36 +#include <xen/config.h> 2.37 +#include <xen/types.h> 2.38 +#include <xen/mm.h> 2.39 +#include <xen/xmalloc.h> 2.40 +#include <xen/lib.h> 2.41 +#include <xen/errno.h> 2.42 +#include <xen/sched.h> 2.43 +#include <public/io/ioreq.h> 2.44 +#include <asm/vmx.h> 2.45 +#include <public/io/vmx_vpic.h> 2.46 +#include <asm/current.h> 2.47 + 2.48 +static void ioapic_enable(vmx_vioapic_t *s, uint8_t enable) 2.49 +{ 2.50 + if (enable) 2.51 + s->flags |= IOAPIC_ENABLE_FLAG; 2.52 + else 2.53 + s->flags &= ~IOAPIC_ENABLE_FLAG; 2.54 +} 2.55 + 2.56 +static void ioapic_dump_redir(vmx_vioapic_t *s, uint8_t entry) 2.57 +{ 2.58 + ASSERT(s); 2.59 + 2.60 + RedirStatus redir = s->redirtbl[entry]; 2.61 + 2.62 + VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_dump_redir " 2.63 + "entry %x vector %x deliver_mod %x destmode %x delivestatus %x " 2.64 + "polarity %x remote_irr %x trigmod %x mask %x dest_id %x\n", 2.65 + entry, redir.RedirForm.vector, redir.RedirForm.deliver_mode, 2.66 + redir.RedirForm.destmode, redir.RedirForm.delivestatus, 2.67 + redir.RedirForm.polarity, redir.RedirForm.remoteirr, 2.68 + redir.RedirForm.trigmod, redir.RedirForm.mask, 2.69 + redir.RedirForm.dest_id); 2.70 +} 2.71 + 2.72 +#ifdef VMX_DOMAIN_SAVE_RESTORE 2.73 +void ioapic_save(QEMUFile* f, void* opaque) 2.74 +{ 2.75 + printk("no implementation for ioapic_save\n"); 2.76 +} 2.77 + 2.78 +int ioapic_load(QEMUFile* f, void* opaque, int version_id) 2.79 +{ 2.80 + printk("no implementation for ioapic_load\n"); 2.81 + return 0; 2.82 +} 2.83 +#endif 2.84 + 2.85 +static unsigned long vmx_vioapic_read_indirect(struct vmx_vioapic *s, 2.86 + unsigned long addr, 2.87 + unsigned long length) 2.88 +{ 2.89 + unsigned long result = 0; 2.90 + 2.91 + ASSERT(s); 2.92 + 2.93 + switch (s->ioregsel) { 2.94 + case IOAPIC_REG_VERSION: 2.95 + result = ((((IOAPIC_NUM_PINS-1) & 0xff) << 16) 2.96 + | (IOAPIC_VERSION_ID & 0x0f)); 2.97 + break; 2.98 + 2.99 +#ifndef __ia64__ 2.100 + case IOAPIC_REG_APIC_ID: 2.101 + result = ((s->id & 0xf) << 24); 2.102 + break; 2.103 + 2.104 + case IOAPIC_REG_ARB_ID: 2.105 + /* XXX how arb_id used on p4? */ 2.106 + result = ((s->id & 0xf) << 24); 2.107 + break; 2.108 +#endif 2.109 + 2.110 + default: 2.111 + { 2.112 + uint32_t redir_index = 0; 2.113 + uint64_t redir_content = 0; 2.114 + 2.115 + redir_index = (s->ioregsel - 0x10) >> 1; 2.116 + 2.117 + if (redir_index >= 0 && redir_index < IOAPIC_NUM_PINS) { 2.118 + redir_content = s->redirtbl[redir_index].value; 2.119 + 2.120 + result = (s->ioregsel & 0x1)? 2.121 + (redir_content >> 32) & 0xffffffff : 2.122 + redir_content & 0xffffffff; 2.123 + } else { 2.124 + printk("upic_mem_readl:undefined ioregsel %x\n", 2.125 + s->ioregsel); 2.126 + domain_crash_synchronous(); 2.127 + } 2.128 + break; 2.129 + } 2.130 + } /* switch */ 2.131 + 2.132 + return result; 2.133 +} 2.134 + 2.135 +static unsigned long vmx_vioapic_read(struct vcpu *v, 2.136 + unsigned long addr, 2.137 + unsigned long length) 2.138 +{ 2.139 + struct vmx_vioapic *s = &(v->domain->arch.vmx_platform.vmx_vioapic); 2.140 + uint32_t result = 0; 2.141 + 2.142 + VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "vmx_vioapic_read addr %lx\n", addr); 2.143 + 2.144 + ASSERT(s); 2.145 + 2.146 + addr &= 0xff; 2.147 + 2.148 + switch (addr) { 2.149 + case IOAPIC_REG_SELECT: 2.150 + result = s->ioregsel; 2.151 + break; 2.152 + 2.153 + case IOAPIC_REG_WINDOW: 2.154 + result = vmx_vioapic_read_indirect(s, addr, length); 2.155 + break; 2.156 + 2.157 + default: 2.158 + break; 2.159 + } 2.160 + 2.161 + return result; 2.162 +} 2.163 + 2.164 +static void vmx_vioapic_write_indirect(struct vmx_vioapic *s, 2.165 + unsigned long addr, 2.166 + unsigned long length, 2.167 + unsigned long val) 2.168 +{ 2.169 + switch (s->ioregsel) { 2.170 + case IOAPIC_REG_VERSION: 2.171 + printk("vmx_vioapic_write_indirect: version register read only\n"); 2.172 + break; 2.173 + 2.174 +#ifndef __ia64__ 2.175 + case IOAPIC_REG_APIC_ID: 2.176 + s->id = (val >> 24) & 0xf; 2.177 + break; 2.178 + 2.179 + case IOAPIC_REG_ARB_ID: 2.180 + s->arb_id = val; 2.181 + break; 2.182 +#endif 2.183 + 2.184 + default: 2.185 + { 2.186 + uint32_t redir_index = 0; 2.187 + 2.188 + VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "vmx_vioapic_write_indirect " 2.189 + "change redir index %x val %lx\n", 2.190 + redir_index, val); 2.191 + 2.192 + redir_index = (s->ioregsel - 0x10) >> 1; 2.193 + 2.194 + if (redir_index >= 0 && redir_index < IOAPIC_NUM_PINS) { 2.195 + uint64_t redir_content; 2.196 + 2.197 + redir_content = s->redirtbl[redir_index].value; 2.198 + 2.199 + if (s->ioregsel & 0x1) 2.200 + redir_content = (((uint64_t)val & 0xffffffff) << 32) | 2.201 + (redir_content & 0xffffffff); 2.202 + else 2.203 + redir_content = ((redir_content >> 32) << 32) | 2.204 + (val & 0xffffffff); 2.205 + s->redirtbl[redir_index].value = redir_content; 2.206 + } else { 2.207 + printk("vmx_vioapic_write_indirect " 2.208 + "error register %x\n", s->ioregsel); 2.209 + } 2.210 + break; 2.211 + } 2.212 + } /* switch */ 2.213 +} 2.214 + 2.215 +static void vmx_vioapic_write(struct vcpu *v, 2.216 + unsigned long addr, 2.217 + unsigned long length, 2.218 + unsigned long val) 2.219 +{ 2.220 + vmx_vioapic_t *s = &(v->domain->arch.vmx_platform.vmx_vioapic); 2.221 + 2.222 + ASSERT(s); 2.223 + 2.224 + addr &= 0xff; 2.225 + 2.226 + switch (addr) { 2.227 + case IOAPIC_REG_SELECT: 2.228 + s->ioregsel = val; 2.229 + break; 2.230 + 2.231 + case IOAPIC_REG_WINDOW: 2.232 + vmx_vioapic_write_indirect(s, addr, length, val); 2.233 + break; 2.234 + 2.235 +#ifdef __ia64__ 2.236 + case IOAPIC_REG_EOI: 2.237 + ioapic_update_EOI(v->domain, val); 2.238 + break; 2.239 +#endif 2.240 + 2.241 + default: 2.242 + break; 2.243 + } 2.244 +} 2.245 + 2.246 +static int vmx_vioapic_range(struct vcpu *v, unsigned long addr) 2.247 +{ 2.248 + vmx_vioapic_t *s = &(v->domain->arch.vmx_platform.vmx_vioapic); 2.249 + 2.250 + if ((s->flags & IOAPIC_ENABLE_FLAG) && 2.251 + (addr >= s->base_address && 2.252 + (addr <= s->base_address + IOAPIC_MEM_LENGTH))) 2.253 + return 1; 2.254 + else 2.255 + return 0; 2.256 +} 2.257 + 2.258 +struct vmx_mmio_handler vioapic_mmio_handler = { 2.259 + .check_handler = vmx_vioapic_range, 2.260 + .read_handler = vmx_vioapic_read, 2.261 + .write_handler = vmx_vioapic_write 2.262 +}; 2.263 + 2.264 +static void vmx_vioapic_reset(vmx_vioapic_t *s) 2.265 +{ 2.266 + int i; 2.267 + 2.268 + memset(s, 0, sizeof(vmx_vioapic_t)); 2.269 + 2.270 + for (i = 0; i < IOAPIC_NUM_PINS; i++) 2.271 + s->redirtbl[i].RedirForm.mask = 0x1; 2.272 +} 2.273 + 2.274 +static void ioapic_update_config(vmx_vioapic_t *s, 2.275 + unsigned long address, 2.276 + uint8_t enable) 2.277 +{ 2.278 + ASSERT(s); 2.279 + 2.280 + ioapic_enable(s, enable); 2.281 + 2.282 + if (address != s->base_address) 2.283 + s->base_address = address; 2.284 +} 2.285 + 2.286 +static int ioapic_inj_irq(vmx_vioapic_t *s, 2.287 + struct vlapic * target, 2.288 + uint8_t vector, 2.289 + uint8_t trig_mode, 2.290 + uint8_t delivery_mode) 2.291 +{ 2.292 + int result = 0; 2.293 + 2.294 + ASSERT(s && target); 2.295 + 2.296 + VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_inj_irq " 2.297 + "irq %d trig %d delive mode %d\n", 2.298 + vector, trig_mode, delivery_mode); 2.299 + 2.300 + switch (delivery_mode) { 2.301 + case VLAPIC_DELIV_MODE_FIXED: 2.302 + case VLAPIC_DELIV_MODE_LPRI: 2.303 + if (test_and_set_bit(vector, &target->irr[0]) && trig_mode == 1) { 2.304 + /* the level interrupt should not happen before it is cleard */ 2.305 + printk("<ioapic_inj_irq> level interrupt happen before cleard\n"); 2.306 + } 2.307 + if (trig_mode) 2.308 + test_and_set_bit(vector, &target->tmr[0]); 2.309 + result = 1; 2.310 + break; 2.311 + default: 2.312 + printk("<ioapic_inj_irq> error delivery mode %d\n", 2.313 + delivery_mode); 2.314 + break; 2.315 + } 2.316 + 2.317 + return result; 2.318 +} 2.319 + 2.320 +#ifndef __ia64__ 2.321 +static int ioapic_match_logical_addr(vmx_vioapic_t *s, int number, uint8_t dest) 2.322 +{ 2.323 + int result = 0; 2.324 + 2.325 + ASSERT(s && s->lapic_info[number]); 2.326 + 2.327 + VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_match_logical_addr " 2.328 + "number %i dest %x\n", 2.329 + number, dest); 2.330 + 2.331 + switch (((s->lapic_info[number]->dest_format >> 28) & 0xf)) { 2.332 + case 0xf: 2.333 + result = 2.334 + (dest & ((s->lapic_info[number]->logical_dest >> 24) & 0xff)) != 0; 2.335 + break; 2.336 + case 0x0: 2.337 + /* Should we support flat cluster mode ?*/ 2.338 + if ( ((s->lapic_info[number]->logical_dest >> 28) 2.339 + == ((dest >> 0x4) & 0xf)) && 2.340 + (((s->lapic_info[number]->logical_dest >> 24) & 0xf) 2.341 + & (dest & 0xf)) ) 2.342 + result = 1; 2.343 + break; 2.344 + default: 2.345 + printk("error DFR value for %x local apic\n", number); 2.346 + break; 2.347 + } 2.348 + 2.349 + return result; 2.350 +} 2.351 +#else 2.352 +extern int ioapic_match_logical_addr(vmx_vioapic_t *s, int number, uint8_t dest); 2.353 +#endif 2.354 + 2.355 +static uint32_t ioapic_get_delivery_bitmask(vmx_vioapic_t *s, 2.356 + uint16_t dest, 2.357 + uint8_t dest_mode, 2.358 + uint8_t vector, 2.359 + uint8_t delivery_mode) 2.360 +{ 2.361 + uint32_t mask = 0; 2.362 + int i; 2.363 + 2.364 + VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask " 2.365 + "dest %d dest_mode %d " 2.366 + "vector %d del_mode %d, lapic_count %d\n", 2.367 + dest, dest_mode, vector, delivery_mode, s->lapic_count); 2.368 + 2.369 + ASSERT(s); 2.370 + 2.371 + if (dest_mode == 0) { /* Physical mode */ 2.372 + for (i = 0; i < s->lapic_count; i++) { 2.373 + if (s->lapic_info[i]->id == dest) { 2.374 + mask = 1 << i; 2.375 + break; 2.376 + } 2.377 + } 2.378 + } else { 2.379 + /* logical destination. call match_logical_addr for each APIC. */ 2.380 + if (dest != 0) { 2.381 + for (i=0; i< s->lapic_count; i++) { 2.382 + if ( s->lapic_info[i] && 2.383 + ioapic_match_logical_addr(s, i, dest) ) { 2.384 + mask |= (1<<i); 2.385 + } 2.386 + } 2.387 + } 2.388 + } 2.389 + 2.390 + VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask " 2.391 + "mask %x\n", mask); 2.392 + 2.393 + return mask; 2.394 +} 2.395 + 2.396 +static void ioapic_deliver(vmx_vioapic_t *s, int irqno) 2.397 +{ 2.398 + uint16_t dest = s->redirtbl[irqno].RedirForm.dest_id; 2.399 + uint8_t dest_mode = s->redirtbl[irqno].RedirForm.destmode; 2.400 + uint8_t delivery_mode = s->redirtbl[irqno].RedirForm.deliver_mode; 2.401 + uint8_t vector = s->redirtbl[irqno].RedirForm.vector; 2.402 + uint8_t trig_mode = s->redirtbl[irqno].RedirForm.trigmod; 2.403 + uint32_t deliver_bitmask; 2.404 + 2.405 + VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "IOAPIC deliver: " 2.406 + "dest %x dest_mode %x delivery_mode %x vector %x trig_mode %x\n", 2.407 + dest, dest_mode, delivery_mode, vector, trig_mode); 2.408 + 2.409 + deliver_bitmask = 2.410 + ioapic_get_delivery_bitmask(s, dest, dest_mode, vector, delivery_mode); 2.411 + 2.412 + if (!deliver_bitmask) { 2.413 + VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic deliver " 2.414 + "no target on destination\n"); 2.415 + 2.416 + return; 2.417 + } 2.418 + 2.419 + switch (delivery_mode) { 2.420 + case VLAPIC_DELIV_MODE_LPRI: 2.421 + { 2.422 + struct vlapic* target; 2.423 + 2.424 + target = apic_round_robin( 2.425 + s->domain, dest_mode, vector, deliver_bitmask); 2.426 + ioapic_inj_irq(s, target, vector, trig_mode, delivery_mode); 2.427 + break; 2.428 + } 2.429 + 2.430 + case VLAPIC_DELIV_MODE_FIXED: 2.431 + case VLAPIC_DELIV_MODE_EXT: 2.432 + { 2.433 + uint8_t bit; 2.434 + for (bit = 0; bit < s->lapic_count; bit++) { 2.435 + if (deliver_bitmask & (1 << bit)) { 2.436 + if (s->lapic_info[bit]) { 2.437 + ioapic_inj_irq(s, s->lapic_info[bit], 2.438 + vector, trig_mode, delivery_mode); 2.439 + } 2.440 + } 2.441 + } 2.442 + break; 2.443 + } 2.444 + 2.445 + case VLAPIC_DELIV_MODE_SMI: 2.446 + case VLAPIC_DELIV_MODE_NMI: 2.447 + case VLAPIC_DELIV_MODE_INIT: 2.448 + case VLAPIC_DELIV_MODE_STARTUP: 2.449 + default: 2.450 + printk("Not support delivey mode %d\n", delivery_mode); 2.451 + break; 2.452 + } 2.453 +} 2.454 + 2.455 +static int ioapic_get_highest_irq(vmx_vioapic_t *s) 2.456 +{ 2.457 + uint32_t irqs; 2.458 + 2.459 + ASSERT(s); 2.460 + 2.461 + irqs = s->irr & ~s->isr; 2.462 + return __fls(irqs); 2.463 +} 2.464 + 2.465 + 2.466 +static void service_ioapic(vmx_vioapic_t *s) 2.467 +{ 2.468 + int irqno; 2.469 + 2.470 + while ((irqno = ioapic_get_highest_irq(s)) != -1) { 2.471 + 2.472 + VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "service_ioapic " 2.473 + "highest irqno %x\n", irqno); 2.474 + 2.475 + if (!s->redirtbl[irqno].RedirForm.mask) { 2.476 + ioapic_deliver(s, irqno); 2.477 + } 2.478 + 2.479 + if (s->redirtbl[irqno].RedirForm.trigmod == IOAPIC_LEVEL_TRIGGER) { 2.480 + s->isr |= (1 << irqno); 2.481 + } 2.482 + 2.483 + s->irr &= ~(1 << irqno); 2.484 + } 2.485 +} 2.486 + 2.487 +void vmx_vioapic_do_irqs(struct domain *d, uint16_t irqs) 2.488 +{ 2.489 + vmx_vioapic_t *s = &(d->arch.vmx_platform.vmx_vioapic); 2.490 + 2.491 + if (!vmx_apic_support(d)) 2.492 + return; 2.493 + 2.494 + s->irr |= irqs; 2.495 + service_ioapic(s); 2.496 +} 2.497 + 2.498 +void vmx_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs) 2.499 +{ 2.500 + vmx_vioapic_t *s = &(d->arch.vmx_platform.vmx_vioapic); 2.501 + 2.502 + if (!vmx_apic_support(d)) 2.503 + return; 2.504 + 2.505 + s->irr &= ~irqs; 2.506 + service_ioapic(s); 2.507 +} 2.508 + 2.509 +void vmx_vioapic_set_irq(struct domain *d, int irq, int level) 2.510 +{ 2.511 + vmx_vioapic_t *s = &(d->arch.vmx_platform.vmx_vioapic); 2.512 + 2.513 + if (!vmx_apic_support(d)) 2.514 + return ; 2.515 + 2.516 + VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_set_irq " 2.517 + "irq %x level %x\n", irq, level); 2.518 + 2.519 + if (irq < 0 || irq >= IOAPIC_NUM_PINS) { 2.520 + printk("ioapic_set_irq irq %x is illegal\n", irq); 2.521 + domain_crash_synchronous(); 2.522 + } 2.523 + 2.524 + if (!IOAPICEnabled(s) || s->redirtbl[irq].RedirForm.mask) 2.525 + return; 2.526 + 2.527 + ioapic_dump_redir(s, irq); 2.528 + 2.529 + if (irq >= 0 && irq < IOAPIC_NUM_PINS) { 2.530 + uint32_t bit = 1 << irq; 2.531 + if (s->redirtbl[irq].RedirForm.trigmod == IOAPIC_LEVEL_TRIGGER) { 2.532 + if (level) 2.533 + s->irr |= bit; 2.534 + else 2.535 + s->irr &= ~bit; 2.536 + } else { 2.537 + if (level) 2.538 + /* XXX No irr clear for edge interrupt */ 2.539 + s->irr |= bit; 2.540 + } 2.541 + } 2.542 + 2.543 + service_ioapic(s); 2.544 +} 2.545 + 2.546 +/* XXX If level interrupt, use vector->irq table for performance */ 2.547 +static int get_redir_num(vmx_vioapic_t *s, int vector) 2.548 +{ 2.549 + int i = 0; 2.550 + 2.551 + ASSERT(s); 2.552 + 2.553 + for(i = 0; i < IOAPIC_NUM_PINS - 1; i++) { 2.554 + if (s->redirtbl[i].RedirForm.vector == vector) 2.555 + return i; 2.556 + } 2.557 + 2.558 + return -1; 2.559 +} 2.560 + 2.561 +void ioapic_update_EOI(struct domain *d, int vector) 2.562 +{ 2.563 + vmx_vioapic_t *s = &(d->arch.vmx_platform.vmx_vioapic); 2.564 + int redir_num; 2.565 + 2.566 + if ((redir_num = get_redir_num(s, vector)) == -1) { 2.567 + printk("Can't find redir item for %d EOI \n", vector); 2.568 + return; 2.569 + } 2.570 + 2.571 + if (!test_and_clear_bit(redir_num, &s->isr)) { 2.572 + printk("redir %d not set for %d EOI\n", redir_num, vector); 2.573 + return; 2.574 + } 2.575 +} 2.576 + 2.577 +int vmx_vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v) 2.578 +{ 2.579 + vmx_vioapic_t *s = &(v->domain->arch.vmx_platform.vmx_vioapic); 2.580 + 2.581 + if (v->vcpu_id != s->lapic_count) { 2.582 + printk("vmx_vioapic_add_lapic " 2.583 + "cpu_id not match vcpu_id %x lapic_count %x\n", 2.584 + v->vcpu_id, s->lapic_count); 2.585 + domain_crash_synchronous(); 2.586 + } 2.587 + 2.588 + s->lapic_info[s->lapic_count ++] = vlapic; 2.589 + 2.590 + return s->lapic_count; 2.591 +} 2.592 + 2.593 +vmx_vioapic_t * vmx_vioapic_init(struct domain *d) 2.594 +{ 2.595 + int i = 0; 2.596 + vmx_vioapic_t *s = &(d->arch.vmx_platform.vmx_vioapic); 2.597 + 2.598 + VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "vmx_vioapic_init\n"); 2.599 + 2.600 + vmx_vioapic_reset(s); 2.601 + 2.602 + s->domain = d; 2.603 + 2.604 + for (i = 0; i < MAX_LAPIC_NUM; i++) 2.605 + s->lapic_info[i] = NULL; 2.606 + 2.607 + /* Remove after GFW ready */ 2.608 + ioapic_update_config(s, IOAPIC_DEFAULT_BASE_ADDRESS, 1); 2.609 + 2.610 + return s; 2.611 +}
3.1 --- a/xen/arch/x86/vmx_intercept.c Mon Nov 07 16:35:46 2005 +0100 3.2 +++ b/xen/arch/x86/vmx_intercept.c Mon Nov 07 16:36:27 2005 +0100 3.3 @@ -34,12 +34,14 @@ 3.4 #ifdef CONFIG_VMX 3.5 3.6 extern struct vmx_mmio_handler vlapic_mmio_handler; 3.7 +extern struct vmx_mmio_handler vioapic_mmio_handler; 3.8 3.9 -#define VMX_MMIO_HANDLER_NR 1 3.10 +#define VMX_MMIO_HANDLER_NR 2 3.11 3.12 struct vmx_mmio_handler *vmx_mmio_handlers[VMX_MMIO_HANDLER_NR] = 3.13 { 3.14 - &vlapic_mmio_handler 3.15 + &vlapic_mmio_handler, 3.16 + &vioapic_mmio_handler 3.17 }; 3.18 3.19 static inline void vmx_mmio_access(struct vcpu *v,
4.1 --- a/xen/arch/x86/vmx_vlapic.c Mon Nov 07 16:35:46 2005 +0100 4.2 +++ b/xen/arch/x86/vmx_vlapic.c Mon Nov 07 16:36:27 2005 +0100 4.3 @@ -307,6 +307,11 @@ vlapic_EOI_set(struct vlapic *vlapic) 4.4 4.5 vlapic_clear_isr(vlapic, vector); 4.6 vlapic_update_ppr(vlapic); 4.7 + 4.8 + if (test_and_clear_bit(vector, &vlapic->tmr[0])) { 4.9 + extern void ioapic_update_EOI(struct domain *d, int vector); 4.10 + ioapic_update_EOI(vlapic->domain, vector); 4.11 + } 4.12 } 4.13 4.14 int vlapic_check_vector(struct vlapic *vlapic, 4.15 @@ -969,6 +974,8 @@ static int vlapic_reset(struct vlapic *v 4.16 4.17 vlapic->spurious_vec = 0xff; 4.18 4.19 + vmx_vioapic_add_lapic(vlapic, v); 4.20 + 4.21 init_ac_timer(&vlapic->vlapic_timer, 4.22 vlapic_timer_fn, vlapic, v->processor); 4.23
5.1 --- a/xen/arch/x86/vmx_vmcs.c Mon Nov 07 16:35:46 2005 +0100 5.2 +++ b/xen/arch/x86/vmx_vmcs.c Mon Nov 07 16:36:27 2005 +0100 5.3 @@ -28,6 +28,7 @@ 5.4 #include <asm/processor.h> 5.5 #include <asm/msr.h> 5.6 #include <asm/vmx.h> 5.7 +#include <asm/vmx_vioapic.h> 5.8 #include <asm/flushtlb.h> 5.9 #include <xen/event.h> 5.10 #include <xen/kernel.h> 5.11 @@ -255,6 +256,7 @@ static void vmx_setup_platform(struct do 5.12 5.13 if ( vmx_apic_support(d) ) { 5.14 spin_lock_init(&d->arch.vmx_platform.round_robin_lock); 5.15 + vmx_vioapic_init(d); 5.16 } 5.17 } 5.18
6.1 --- a/xen/include/asm-x86/vmx_platform.h Mon Nov 07 16:35:46 2005 +0100 6.2 +++ b/xen/include/asm-x86/vmx_platform.h Mon Nov 07 16:36:27 2005 +0100 6.3 @@ -24,6 +24,7 @@ 6.4 #include <asm/e820.h> 6.5 #include <asm/vmx_virpit.h> 6.6 #include <asm/vmx_intercept.h> 6.7 +#include <asm/vmx_vioapic.h> 6.8 #include <public/io/vmx_vpic.h> 6.9 6.10 #define MAX_OPERAND_NUM 2 6.11 @@ -85,6 +86,7 @@ struct vmx_platform { 6.12 struct vmx_virpit vmx_pit; 6.13 struct vmx_io_handler vmx_io_handler; 6.14 struct vmx_virpic vmx_pic; 6.15 + struct vmx_vioapic vmx_vioapic; 6.16 unsigned char round_info[256]; 6.17 spinlock_t round_robin_lock; 6.18 int interrupt_request;
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/xen/include/asm-x86/vmx_vioapic.h Mon Nov 07 16:36:27 2005 +0100 7.3 @@ -0,0 +1,136 @@ 7.4 +/* 7.5 + * 7.6 + * Copyright (C) 2001 MandrakeSoft S.A. 7.7 + * 7.8 + * MandrakeSoft S.A. 7.9 + * 43, rue d'Aboukir 7.10 + * 75002 Paris - France 7.11 + * http://www.linux-mandrake.com/ 7.12 + * http://www.mandrakesoft.com/ 7.13 + * 7.14 + * This library is free software; you can redistribute it and/or 7.15 + * modify it under the terms of the GNU Lesser General Public 7.16 + * License as published by the Free Software Foundation; either 7.17 + * version 2 of the License, or (at your option) any later version. 7.18 + * 7.19 + * This library is distributed in the hope that it will be useful, 7.20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 7.21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 7.22 + * Lesser General Public License for more details. 7.23 + * 7.24 + * You should have received a copy of the GNU Lesser General Public 7.25 + * License along with this library; if not, write to the Free Software 7.26 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 7.27 + */ 7.28 + 7.29 +#ifndef _IOAPIC_H_ 7.30 +#define _IOAPIC_H_ 7.31 + 7.32 +#include <xen/config.h> 7.33 +#include <xen/types.h> 7.34 +#include <xen/smp.h> 7.35 + 7.36 +#ifndef __ia64__ 7.37 +#define IOAPIC_VERSION_ID 0x11 7.38 +#else 7.39 +#define IOAPIC_VERSION_ID 0x21 7.40 +#endif 7.41 + 7.42 +#define IOAPIC_NUM_PINS 24 7.43 +#define MAX_LAPIC_NUM 32 7.44 + 7.45 +#define IOAPIC_LEVEL_TRIGGER 1 7.46 + 7.47 +#define IOAPIC_DEFAULT_BASE_ADDRESS 0xfec00000 7.48 +#define IOAPIC_MEM_LENGTH 0x100 7.49 + 7.50 +#define IOAPIC_ENABLE_MASK 0x0 7.51 +#define IOAPIC_ENABLE_FLAG (1 << IOAPIC_ENABLE_MASK) 7.52 +#define IOAPICEnabled(s) (s->flags & IOAPIC_ENABLE_FLAG) 7.53 + 7.54 +#define IOAPIC_REG_SELECT 0x0 7.55 +#define IOAPIC_REG_WINDOW 0x10 7.56 + 7.57 +#ifdef __ia64__ 7.58 +#define IOAPIC_REG_ASSERTION 0x20 7.59 +#define IOAPIC_REG_EOI 0x40 7.60 +#endif 7.61 + 7.62 +#ifndef __ia64__ 7.63 +#define IOAPIC_REG_APIC_ID 0x0 7.64 +#define IOAPIC_REG_ARB_ID 0x2 7.65 +#endif 7.66 + 7.67 +#define IOAPIC_REG_VERSION 0x1 7.68 + 7.69 +#ifdef __ia64__ 7.70 +typedef union RedirStatus 7.71 +{ 7.72 + uint64_t value; 7.73 + struct { 7.74 + uint16_t dest_id; 7.75 + uint8_t reserved[3]; 7.76 + uint8_t reserve:7; 7.77 + uint8_t mask:1; /* interrupt mask*/ 7.78 + uint8_t trigmod:1; 7.79 + uint8_t remoteirr:1; 7.80 + uint8_t polarity:1; 7.81 + uint8_t delivestatus:1; 7.82 + uint8_t destmode:1; 7.83 + uint8_t deliver_mode:3; 7.84 + uint8_t vector; 7.85 + } RedirForm; 7.86 +} RedirStatus; 7.87 +#else 7.88 +typedef union RedirStatus 7.89 +{ 7.90 + uint64_t value; 7.91 + struct { 7.92 + uint8_t vector; 7.93 + uint8_t deliver_mode:3; 7.94 + uint8_t destmode:1; 7.95 + uint8_t delivestatus:1; 7.96 + uint8_t polarity:1; 7.97 + uint8_t remoteirr:1; 7.98 + uint8_t trigmod:1; 7.99 + uint8_t mask:1; /* interrupt mask*/ 7.100 + uint8_t reserve:7; 7.101 + uint8_t reserved[4]; 7.102 + uint8_t dest_id; 7.103 + } RedirForm; 7.104 +} RedirStatus; 7.105 +#endif 7.106 + 7.107 +#define IOAPIC_MEM_LENGTH 0x100 7.108 +#define IOAPIC_ENABLE_MASK 0x0 7.109 +#define IOAPIC_ENABLE_FLAG (1 << IOAPIC_ENABLE_MASK) 7.110 +#define MAX_LAPIC_NUM 32 7.111 + 7.112 +typedef struct vmx_vioapic { 7.113 + uint32_t ioregsel; 7.114 + uint32_t irr; 7.115 + uint32_t isr; /* This is used for level trigger */ 7.116 + uint32_t flags; 7.117 + uint32_t lapic_count; 7.118 + uint32_t id; 7.119 + uint32_t arb_id; 7.120 + unsigned long base_address; 7.121 + RedirStatus redirtbl[IOAPIC_NUM_PINS]; 7.122 + struct vlapic *lapic_info[MAX_LAPIC_NUM]; 7.123 + struct domain *domain; 7.124 +} vmx_vioapic_t; 7.125 + 7.126 +vmx_vioapic_t *vmx_vioapic_init(struct domain *d); 7.127 + 7.128 +void vmx_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs); 7.129 +void vmx_vioapic_do_irqs(struct domain *d, uint16_t irqs); 7.130 +void vmx_vioapic_set_irq(struct domain *d, int irq, int level); 7.131 + 7.132 +int vmx_vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v); 7.133 + 7.134 +#ifdef VMX_DOMAIN_SAVE_RESTORE 7.135 +void ioapic_save(QEMUFile* f, void* opaque); 7.136 +int ioapic_load(QEMUFile* f, void* opaque, int version_id); 7.137 +#endif 7.138 + 7.139 +#endif
8.1 --- a/xen/include/asm-x86/vmx_vmcs.h Mon Nov 07 16:35:46 2005 +0100 8.2 +++ b/xen/include/asm-x86/vmx_vmcs.h Mon Nov 07 16:36:27 2005 +0100 8.3 @@ -284,7 +284,8 @@ enum vmcs_field { 8.4 #define DBG_LEVEL_VMMU (1 << 5) 8.5 #define DBG_LEVEL_VLAPIC (1 << 6) 8.6 #define DBG_LEVEL_VLAPIC_TIMER (1 << 7) 8.7 -#define DBG_LEVEL_VLAPIC_INTERRUPT (1 << 7) 8.8 +#define DBG_LEVEL_VLAPIC_INTERRUPT (1 << 8) 8.9 +#define DBG_LEVEL_IOAPIC (1 << 9) 8.10 8.11 extern unsigned int opt_vmx_debug_level; 8.12 #define VMX_DBG_LOG(level, _f, _a...) \