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>
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...)           \