From 382ed0e218e62f8159e6c836cc4abd0793070c51 Mon Sep 17 00:00:00 2001 From: "arun.sharma@intel.com[kaf24]" Date: Thu, 30 Jun 2005 08:09:40 +0000 Subject: bitkeeper revision 1.1780 (42c3a8c4tqEOpGy663gWO35k5QwZTw) [PATCH] Infrastructure for interrupt handling. Infrastructure for interrupt handling. - support interruptibility - handle interrupt window exiting control appropriately - Add ioapic device models imported from Bochs under LGPL - generalize the interrupt architecture to support both PIC/APIC This patch is necessary to fix several bugs on 32 bit VMX and prepares the ground for adding a local APIC device model in the hypervisor. Signed-off-by: Yunhong Jiang Signed-off-by: Eddie Dong Signed-off-by: Arun Sharma --- .rootkeys | 3 + tools/ioemu/exec-all.h | 4 +- tools/ioemu/hw/i8259.c | 29 ++ tools/ioemu/hw/ioapic.c | 704 +++++++++++++++++++++++++++++++++++ tools/ioemu/hw/ioapic.h | 128 +++++++ tools/ioemu/hw/pc.c | 3 + tools/ioemu/hw/pci.c | 16 +- tools/ioemu/target-i386-dm/Makefile | 3 +- tools/ioemu/target-i386-dm/helper2.c | 19 +- xen/arch/x86/vmx_intercept.c | 3 +- xen/arch/x86/vmx_io.c | 201 +++++++--- xen/arch/x86/vmx_vmcs.c | 2 + xen/include/asm-x86/vmx.h | 9 +- xen/include/asm-x86/vmx_virpit.h | 2 +- xen/include/public/io/ioreq.h | 9 +- xen/include/public/io/vmx_vlapic.h | 57 +++ 16 files changed, 1112 insertions(+), 80 deletions(-) create mode 100644 tools/ioemu/hw/ioapic.c create mode 100644 tools/ioemu/hw/ioapic.h create mode 100644 xen/include/public/io/vmx_vlapic.h diff --git a/.rootkeys b/.rootkeys index 9fcca1ceb0..f2bdb4dee4 100644 --- a/.rootkeys +++ b/.rootkeys @@ -681,6 +681,8 @@ 428d0d84zbtT2C8Xci_SqMP5bZ-wcQ tools/ioemu/hw/i8254.c 428d0d84KlR61OwSzjF0-L4iz58dfQ tools/ioemu/hw/i8259.c 428d0d84auhZx6c5Kv3WrfM2UZvqHA tools/ioemu/hw/ide.c +42c3a8bcqaiyuOWldKc1vXUP12-1Bg tools/ioemu/hw/ioapic.c +42c3a8bcMP67Od-xEnQaYAHahibD_w tools/ioemu/hw/ioapic.h 428d0d84WSlhNzdrcb-f-Lg-W9dniQ tools/ioemu/hw/iommu.c 428d0d84ri8ZtvhB6RJr1YNejjNWIQ tools/ioemu/hw/lance.c 428d0d84cxFFgDv5fBFrlxGoCiy6Nw tools/ioemu/hw/m48t08.c @@ -1570,6 +1572,7 @@ 40f5623cTZ80EwjWUBlh44A9F9i_Lg xen/include/public/io/netif.h 41d40e9b8zCk5VDqhVbuQyhc7G3lqA xen/include/public/io/ring.h 41ee5e8c6mLxIx82KPsbpt_uts_vSA xen/include/public/io/usbif.h +42c3a8bcUFXJKVc8tWCFilICv2cNaA xen/include/public/io/vmx_vlapic.h 4051db79512nOCGweabrFWO2M2h5ng xen/include/public/physdev.h 42b742f7Lzy8SKKG25L_-fgk5FHA2Q xen/include/public/policy_ops.h 40589968wmhPmV5-ENbBYmMjnedgKw xen/include/public/sched_ctl.h diff --git a/tools/ioemu/exec-all.h b/tools/ioemu/exec-all.h index ac0533982d..e32207b7c3 100644 --- a/tools/ioemu/exec-all.h +++ b/tools/ioemu/exec-all.h @@ -573,7 +573,7 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) } #endif -//#define DEBUG_UNUSED_IOPORT -//#define DEBUG_IOPORT +#define DEBUG_UNUSED_IOPORT +#define DEBUG_IOPORT #define TARGET_VMX diff --git a/tools/ioemu/hw/i8259.c b/tools/ioemu/hw/i8259.c index 75f0391097..e0e26e7a70 100644 --- a/tools/ioemu/hw/i8259.c +++ b/tools/ioemu/hw/i8259.c @@ -22,6 +22,8 @@ * THE SOFTWARE. */ #include "vl.h" +#include "xc.h" +#include /* debug PIC */ //#define DEBUG_PIC @@ -29,6 +31,8 @@ //#define DEBUG_IRQ_LATENCY #define DEBUG_IRQ_COUNT +extern void pit_reset_vmx_vectors(); + typedef struct PicState { uint8_t last_irr; /* edge detection */ uint8_t irr; /* interrupt request register */ @@ -121,6 +125,26 @@ static int pic_get_irq(PicState *s) } } +/* pic[1] is connected to pin2 of pic[0] */ +#define CASCADE_IRQ 2 + +static void shared_page_update() +{ + extern shared_iopage_t *shared_page; + uint8_t * pmask = (uint8_t *)&(shared_page->sp_global.pic_mask[0]); + int index; + + index = pics[0].irq_base/8; + pmask[index] = pics[0].imr; + index = pics[1].irq_base/8; + + if ( pics[0].imr & (1 << CASCADE_IRQ) ) { + pmask[index] = 0xff; + } else { + pmask[index] = pics[1].imr; + } +} + /* raise irq to CPU if necessary. must be called every time the active irq may change */ static void pic_update_irq(void) @@ -150,14 +174,18 @@ static void pic_update_irq(void) #endif cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD); } + shared_page_update(); } #ifdef DEBUG_IRQ_LATENCY int64_t irq_time[16]; #endif +extern void ioapic_legacy_irq(int irq, int level); + void pic_set_irq(int irq, int level) { + ioapic_legacy_irq(irq, level); #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT) if (level != irq_level[irq]) { #if defined(DEBUG_PIC) @@ -255,6 +283,7 @@ static void pic_reset(void *opaque) tmp = s->elcr_mask; memset(s, 0, sizeof(PicState)); s->elcr_mask = tmp; + shared_page_update(); } static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val) diff --git a/tools/ioemu/hw/ioapic.c b/tools/ioemu/hw/ioapic.c new file mode 100644 index 0000000000..b15e6d1fb6 --- /dev/null +++ b/tools/ioemu/hw/ioapic.c @@ -0,0 +1,704 @@ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001 MandrakeSoft S.A. +// +// MandrakeSoft S.A. +// 43, rue d'Aboukir +// 75002 Paris - France +// http://www.linux-mandrake.com/ +// http://www.mandrakesoft.com/ +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "vl.h" +#include "ioapic.h" + +#ifdef __OS +#undef __OS +#endif +#ifdef __i386__ +#define __OS "l" +#else +#define __OS "q" +#endif +#define ADDR (*(volatile long *) addr) + +#ifdef IOAPIC_DEBUG +#define IOAPIC_LOG(a...) fprintf(logfile, ##a) +#else +#define IOAPIC_LOG(a...) +#endif + +static IOAPICState *ioapic; + +#define IOAPIC_ERR(a...) fprintf(logfile, ##a) +static __inline__ int test_and_set_bit(long nr, volatile void * addr) +{ + long oldbit; + + __asm__ __volatile__( + "bts"__OS" %2,%1\n\tsbb"__OS" %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr) : "memory"); + return oldbit; +} + +static __inline__ int test_and_clear_bit(long nr, volatile void * addr) +{ + long oldbit; + + __asm__ __volatile__( LOCK_PREFIX + "btr"__OS" %2,%1\n\tsbb"__OS" %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"dIr" (nr) : "memory"); + return oldbit; +} + +static __inline__ void clear_bit(long nr, volatile void * addr) +{ + __asm__ __volatile__( + "btr"__OS" %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +static inline +void get_shareinfo_apic_msg(vlapic_info *share_info){ + while(test_and_set_bit(VL_STATE_MSG_LOCK, &share_info->vl_state)){}; +} + +static inline +void put_shareinfo_apic_msg(vlapic_info *share_info){ + clear_bit(VL_STATE_MSG_LOCK, &share_info->vl_state); +} +static inline +void get_shareinfo_eoi(vlapic_info *share_info){ + while(test_and_set_bit(VL_STATE_EOI_LOCK, &share_info->vl_state)){}; +} + +static inline +void put_shareinfo_eoi(vlapic_info *share_info){ + clear_bit(VL_STATE_EOI_LOCK, &share_info->vl_state); +} + + +static inline +void get_shareinfo_ext(vlapic_info *share_info){ + while(test_and_set_bit(VL_STATE_EXT_LOCK, &share_info->vl_state)); +} + +static inline +void put_shareinfo_ext(vlapic_info *share_info){ + clear_bit(VL_STATE_EXT_LOCK, &share_info->vl_state); +} + + +static __inline__ int test_bit(int nr, uint32_t value){ + return value & (1 << nr); +} + +static void ioapic_enable(IOAPICState *s, uint8_t enable) +{ + if (!enable ^ IOAPICEnabled(s)) return; + if(enable) + s->flags |= IOAPIC_ENABLE_FLAG; + else + s->flags &= ~IOAPIC_ENABLE_FLAG; +} + +#ifdef IOAPIC_DEBUG +static void +ioapic_dump_redir(IOAPICState *s, uint8_t entry) +{ + if (!s) + return; + + RedirStatus redir = s->redirtbl[entry]; + + fprintf(logfile, "entry %x: " + "vector %x deliver_mod %x destmode %x delivestatus %x " + "polarity %x remote_irr %x trigmod %x mask %x dest_id %x\n", + entry, + redir.RedirForm.vector, redir.RedirForm.deliver_mode, + redir.RedirForm.destmode, redir.RedirForm.delivestatus, + redir.RedirForm.polarity, redir.RedirForm.remoteirr, + redir.RedirForm.trigmod, redir.RedirForm.mask, + redir.RedirForm.dest_id); +} + +static void +ioapic_dump_shareinfo(IOAPICState *s , int number) +{ + if (!s || !s->lapic_info[number]) + return; + vlapic_info *m = s->lapic_info[number]; + IOAPIC_LOG("lapic_info %x : " + "vl_lapic_id %x vl_logical_dest %x vl_dest_format %x vl_arb_id %x\n", + number, m->vl_lapic_id, m->vl_logical_dest, m->vl_dest_format, m->vl_arb_id ); +} +#endif + +static void +ioapic_save(QEMUFile* f,void* opaque) +{ + IOAPIC_ERR("no implementation for ioapic_save\n"); +} + +static +int ioapic_load(QEMUFile* f,void* opaque,int version_id) +{ + IOAPIC_ERR("no implementation for ioapic_load\n"); + return 0; +} + +uint32_t +ioapic_mem_readb(void *opaque, target_phys_addr_t addr) +{ + IOAPIC_ERR("ioapic_mem_readb\n"); + return 0; +} + +uint32_t +ioapic_mem_readw(void *opaque, target_phys_addr_t addr) +{ + IOAPIC_ERR("ioapic_mem_readw\n"); + return 0; +} + +static +void ioapic_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + IOAPIC_ERR("ioapic_mem_writeb\n"); +} + +static +void ioapic_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + IOAPIC_ERR("ioapic_mem_writew\n"); +} + +static +uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr) +{ + unsigned short ioregsel; + IOAPICState *s = opaque; + uint32_t result = 0; + uint32_t redir_index = 0; + uint64_t redir_content = 0; + + IOAPIC_LOG("apic_mem_readl addr %x\n", addr); + if (!s){ + IOAPIC_ERR("null pointer for apic_mem_readl\n"); + return result; + } + + addr &= 0xff; + if(addr == 0x00){ + result = s->ioregsel; + return result; + }else if (addr != 0x10){ + IOAPIC_ERR("apic_mem_readl address error\n"); + return result; + } + + ioregsel = s->ioregsel; + + switch (ioregsel){ + case IOAPIC_REG_APIC_ID: + result = ((s->id & 0xf) << 24); + break; + case IOAPIC_REG_VERSION: + result = ((((IOAPIC_NUM_PINS-1) & 0xff) << 16) + | (IOAPIC_VERSION_ID & 0x0f)); + break; + case IOAPIC_REG_ARB_ID: + //FIXME + result = ((s->id & 0xf) << 24); + break; + default: + redir_index = (ioregsel - 0x10) >> 1; + if (redir_index >= 0 && redir_index < IOAPIC_NUM_PINS){ + redir_content = s->redirtbl[redir_index].value; + result = (ioregsel & 0x1)? + (redir_content >> 32) & 0xffffffff : + redir_content & 0xffffffff; + }else{ + IOAPIC_ERR( + "upic_mem_readl:undefined ioregsel %x\n", + ioregsel); + } + } + return result; +} + +static +void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + IOAPICState *s = opaque; + uint32_t redir_index = 0; + uint64_t redir_content; + + IOAPIC_LOG("apic_mem_writel addr %x val %x\n", addr, val); + + if (!s){ + IOAPIC_ERR("apic_mem_writel: null opaque\n"); + return; + } + + addr &= 0xff; + if (addr == 0x00){ + s->ioregsel = val; + return; + }else if (addr != 0x10){ + IOAPIC_ERR("apic_mem_writel: unsupported address\n"); + } + + switch (s->ioregsel){ + case IOAPIC_REG_APIC_ID: + s->id = (val >> 24) & 0xf; + break; + case IOAPIC_REG_VERSION: + IOAPIC_ERR("apic_mem_writel: version register read only\n"); + break; + case IOAPIC_REG_ARB_ID: + s->arb_id = val; + break; + default: + redir_index = (s->ioregsel - 0x10) >> 1; +// IOAPIC_LOG("apic_mem_write: change redir :index %x before %lx, val %x\n", redir_index, s->redirtbl[redir_index].value, val); + if (redir_index >= 0 && redir_index < IOAPIC_NUM_PINS){ + redir_content = s->redirtbl[redir_index].value; + if (s->ioregsel & 0x1) + redir_content = (((uint64_t)val & 0xffffffff) << 32) | (redir_content & 0xffffffff); + else + redir_content = ((redir_content >> 32) << 32) | (val & 0xffffffff); + s->redirtbl[redir_index].value = redir_content; + }else { + IOAPIC_ERR("apic_mem_writel: error register\n"); + } + //IOAPIC_LOG("after value is %lx\n", s->redirtbl[redir_index].value); + } +} + +static CPUReadMemoryFunc *ioapic_mem_read[3] = { + ioapic_mem_readb, + ioapic_mem_readw, + ioapic_mem_readl, +}; + +static CPUWriteMemoryFunc *ioapic_mem_write[3] = { + ioapic_mem_writeb, + ioapic_mem_writew, + ioapic_mem_writel, +}; + +void +IOAPICReset(IOAPICState *s) +{ + int i; + if (!s) + return ; + + memset(s, 0, sizeof(IOAPICState)); + + for (i = 0; i < IOAPIC_NUM_PINS; i++) + s->redirtbl[i].RedirForm.mask = 0x1; +// IOAPIC_LOG("after Reset %lx\n", s->redirtbl[0].value); +} + +void +ioapic_update_config(IOAPICState *s, unsigned long address, uint8_t enable) +{ + int ioapic_mem; + if (!s) + return; + + ioapic_enable(s, enable); + + if (address != s->base_address){ + ioapic_mem = cpu_register_io_memory(0, ioapic_mem_read, ioapic_mem_write, s); + cpu_register_physical_memory(address, IOAPIC_MEM_LENGTH, ioapic_mem); + s->base_address = ioapic_mem; + } +} + +#define direct_intr(mode) \ + (mode == VLAPIC_DELIV_MODE_SMI || \ + mode == VLAPIC_DELIV_MODE_NMI || \ + mode == VLAPIC_DELIV_MODE_INIT ||\ + mode == VLAPIC_DELIV_MODE_STARTUP) + +int +ioapic_inj_irq(IOAPICState *s, uint8_t dest, uint8_t vector, uint8_t trig_mode, uint8_t delivery_mode) +{ + int msg_count; + if (!s || !s->lapic_info[dest]){ + IOAPIC_ERR("ioapic_inj_irq NULL parameter\n"); + return 0; + } + IOAPIC_LOG("ioapic_inj_irq %d , trig %d delive mode %d\n", + vector, trig_mode, delivery_mode); + switch(delivery_mode){ + case VLAPIC_DELIV_MODE_FIXED: + case VLAPIC_DELIV_MODE_LPRI: + get_shareinfo_apic_msg(s->lapic_info[dest]); + msg_count = s->lapic_info[dest]->apic_msg_count; + s->lapic_info[dest]->vl_apic_msg[msg_count].deliv_mode = delivery_mode; + s->lapic_info[dest]->vl_apic_msg[msg_count].level = trig_mode; + s->lapic_info[dest]->vl_apic_msg[msg_count].vector = vector; + s->lapic_info[dest]->vl_apic_msg[msg_count].vector = vector; + s->lapic_info[dest]->apic_msg_count ++; + put_shareinfo_apic_msg(s->lapic_info[dest]); + break; + case VLAPIC_DELIV_MODE_EXT: +/* get_shareinfo_ext(s->lapic_info[dest]); + test_and_set_bit(vector, &s->lapic_info[dest]->vl_ext_intr[0]); + put_shareinfo_ext(s->lapic_info[dest]);*/ + IOAPIC_ERR(" Ext interrupt\n"); + return 0; + default: + IOAPIC_ERR(" error delivery mode\n"); + break; + } + return 1; +} + +int +ioapic_match_logical_addr(IOAPICState *s, int number, uint8_t address) +{ + if(!s || !s->lapic_info[number]){ + IOAPIC_ERR("ioapic_match_logical_addr NULL parameter: " + "number: %i s %p address %x\n", + number, s, address); + return 0; + } + IOAPIC_LOG("ioapic_match_logical_addr number %i address %x\n", + number, address); + + if (((s->lapic_info[number]->vl_dest_format >> 28 ) & 0xf) != 0xf) { + IOAPIC_ERR("ioapic_match_logical_addr: cluster model not implemented still%x" + ,s->lapic_info[number]->vl_dest_format); +#ifdef IOAPIC_DEBUG + ioapic_dump_shareinfo(s, number); +#endif + return 0; + } + return ((address & ((s->lapic_info[number]->vl_logical_dest >> 24) & 0xff)) != 0); +} + +int +ioapic_get_apr_lowpri(IOAPICState *s, int number) +{ + if(!s || !s->lapic_info[number]){ + IOAPIC_ERR("ioapic_get_apr_lowpri NULL parameter\n"); + return 0; + } + return s->lapic_info[number]->vl_arb_id; +} + +uint32_t +ioapic_get_delivery_bitmask(IOAPICState *s, +uint8_t dest, uint8_t dest_mode, uint8_t vector, uint8_t delivery_mode) +{ + uint32_t mask = 0; + int low_priority = 256, selected = -1, i; + fprintf(logfile, ": dest %d dest_mode %d" + "vector %d del_mode %d, lapic_count %d\n", + dest, dest_mode, vector, delivery_mode, s->lapic_count); + if (!s) return mask; + if (dest_mode == 0) { //Physical mode + if ((dest < s->lapic_count) && s->lapic_info[dest]) + mask = 1 << dest; + } + else { + /* logical destination. call match_logical_addr for each APIC. */ + if (dest == 0) return 0; + for (i=0; i< s->lapic_count; i++) { + //FIXME focus one, since no such issue on IPF, shoudl we add it? + if ( s->lapic_info[i] && ioapic_match_logical_addr(s, i, dest)){ + if (delivery_mode != APIC_DM_LOWPRI) + mask |= (1< ioapic_get_apr_lowpri(s, i)){ + low_priority = ioapic_get_apr_lowpri(s, i); + selected = i; + } + fprintf(logfile, "%d low_priority %d apr %d select %d\n", + i, low_priority, ioapic_get_apr_lowpri(s, i), selected); + } + } + } + if (delivery_mode == APIC_DM_LOWPRI && (selected != -1)) + mask |= (1<< selected); + } + return mask; +} + +void +ioapic_deliver(IOAPICState *s, int irqno){ + uint8_t dest = s->redirtbl[irqno].RedirForm.dest_id; + uint8_t dest_mode = s->redirtbl[irqno].RedirForm.destmode; + uint8_t delivery_mode = s->redirtbl[irqno].RedirForm.deliver_mode; + uint8_t vector = s->redirtbl[irqno].RedirForm.vector; + uint8_t trig_mode = s->redirtbl[irqno].RedirForm.trigmod; + uint8_t bit; + uint32_t deliver_bitmask; + + IOAPIC_LOG("IOAPIC deliver: " + "dest %x dest_mode %x delivery_mode %x vector %x trig_mode %x\n", + dest, dest_mode, delivery_mode, vector, trig_mode); + + deliver_bitmask = + ioapic_get_delivery_bitmask(s, dest, dest_mode, vector, delivery_mode); + + IOAPIC_LOG("ioapic_get_delivery_bitmask return %x\n", deliver_bitmask); + if (!deliver_bitmask){ + IOAPIC_ERR("Ioapic deliver, no target on destination\n"); + return ; + } + + switch (delivery_mode){ + case VLAPIC_DELIV_MODE_FIXED: + case VLAPIC_DELIV_MODE_LPRI: + case VLAPIC_DELIV_MODE_EXT: + break; + case VLAPIC_DELIV_MODE_SMI: + case VLAPIC_DELIV_MODE_NMI: + case VLAPIC_DELIV_MODE_INIT: + case VLAPIC_DELIV_MODE_STARTUP: + default: + IOAPIC_ERR("Not support delivey mode %d\n", delivery_mode); + return ; + } + + for (bit = 0; bit < s->lapic_count; bit++){ + if (deliver_bitmask & (1 << bit)){ + if (s->lapic_info[bit]){ + ioapic_inj_irq(s, bit, vector, trig_mode, delivery_mode); + } + } + } +} + +static inline int __fls(u32 word) +{ + int bit; + __asm__("bsrl %1,%0" + :"=r" (bit) + :"rm" (word)); + return word ? bit : -1; +} + +#if 0 +static __inline__ int find_highest_bit(unsigned long *data, int length){ + while(length && !data[--length]); + return __fls(data[length]) + 32 * length; +} +#endif +int +ioapic_get_highest_irq(IOAPICState *s){ + uint32_t irqs; + if (!s) + return -1; + irqs = s->irr & ~s->isr; + return __fls(irqs); +} + + +void +service_ioapic(IOAPICState *s){ + int irqno; + + while((irqno = ioapic_get_highest_irq(s)) != -1){ + IOAPIC_LOG("service_ioapic: highest irqno %x\n", irqno); + + if (!s->redirtbl[irqno].RedirForm.mask) + ioapic_deliver(s, irqno); + + if (s->redirtbl[irqno].RedirForm.trigmod == IOAPIC_LEVEL_TRIGGER){ + s->isr |= (1 << irqno); + } + // clear_bit(irqno, &s->irr); + s->irr &= ~(1 << irqno); + } +} + +void +ioapic_update_irq(IOAPICState *s) +{ + s->INTR = 1; +} + +void +ioapic_set_irq(IOAPICState *s, int irq, int level) +{ + IOAPIC_LOG("ioapic_set_irq %x %x\n", irq, level); + + /* Timer interrupt implemented on HV side */ + if(irq == 0x0) return; + if (!s){ + fprintf(logfile, "ioapic_set_irq null parameter\n"); + return; + } + if (!IOAPICEnabled(s) || s->redirtbl[irq].RedirForm.mask) + return; +#ifdef IOAPIC_DEBUG + ioapic_dump_redir(s, irq); +#endif + if (irq >= 0 && irq < IOAPIC_NUM_PINS){ + uint32_t bit = 1 << irq; + if (s->redirtbl[irq].RedirForm.trigmod == IOAPIC_LEVEL_TRIGGER){ + if(level) + s->irr |= bit; + else + s->irr &= ~bit; + }else{ + if(level) + /* XXX No irr clear for edge interrupt */ + s->irr |= bit; + } + } + + ioapic_update_irq(s); +} + +void +ioapic_legacy_irq(int irq, int level) +{ + ioapic_set_irq(ioapic, irq, level); +} + +static inline int find_highest_bit(u32 *data, int length){ + while(length && !data[--length]); + return __fls(data[length]) + 32 * length; +} + +int +get_redir_num(IOAPICState *s, int vector){ + int i = 0; + if(!s){ + IOAPIC_ERR("Null parameter for get_redir_num\n"); + return -1; + } + for(; i < IOAPIC_NUM_PINS-1; i++){ + if (s->redirtbl[i].RedirForm.vector == vector) + return i; + } + return -1; +} + +void +ioapic_update_EOI() +{ + int i = 0; + uint32_t isr_info ; + uint32_t vector; + IOAPICState *s = ioapic; + + isr_info = s->isr; + + for (i = 0; i < s->lapic_count; i++){ + if (!s->lapic_info[i] || + !test_bit(VL_STATE_EOI, s->lapic_info[i]->vl_state)) + continue; + get_shareinfo_eoi(s->lapic_info[i]); + while((vector = find_highest_bit((unsigned int *)&s->lapic_info[i]->vl_eoi[0],VLAPIC_INT_COUNT_32)) != -1){ + int redir_num; + if ((redir_num = get_redir_num(s, vector)) == -1){ + IOAPIC_ERR("Can't find redir item for %d EOI \n", vector); + continue; + } + if (!test_and_clear_bit(redir_num, &s->isr)){ + IOAPIC_ERR("redir %d not set for %d EOI\n", redir_num, vector); + continue; + } + clear_bit(vector, &s->lapic_info[i]->vl_eoi[0]); + } + clear_bit(VL_STATE_EOI, &s->lapic_info[i]->vl_state); + put_shareinfo_eoi(s->lapic_info[i]); + } +} + + +void +ioapic_init_apic_info(IOAPICState *s) +{ +#ifdef IOAPIC_DEBUG + fprintf(logfile, "ioapic_init_apic_info\n"); + if (!s) + return; +#endif + +#if 0 + if (!vio || !(vio->vl_number)){ + fprintf(logfile, "null vio or o vl number\n"); + return; + } + + for (i = 0; i < MAX_LAPIC_NUM; i++) s->lapic_info[i] = NULL; + + s->lapic_count = vio->vl_number; + for (i = 0; i < vio->vl_number; i++) + s->lapic_info[i] = vio->vl_info + i; +#endif + +} + +void +ioapic_intack(IOAPICState *s) +{ +#ifdef IOAPIC_DEBUG + if (!s){ + fprintf(logfile, "ioapic_intack null parameter\n"); + return; + } +#endif + if (!s) s->INTR = 0; +} + +int +ioapic_has_intr() +{ + return ioapic->INTR; +} + +void +do_ioapic() +{ + service_ioapic(ioapic); + ioapic_intack(ioapic); +} + +IOAPICState * +IOAPICInit( ) +{ + IOAPICState *s; + + s = qemu_mallocz(sizeof(IOAPICState)); + if (!s){ + fprintf(logfile, "IOAPICInit: malloc failed\n"); + return NULL; + } + + IOAPICReset(s); + ioapic_init_apic_info(s); + register_savevm("ioapic", 0, 1, ioapic_save, ioapic_load, s); + /* Remove after GFW ready */ + ioapic_update_config(s, 0xfec00000, 1); + + ioapic = s; + return s; +} diff --git a/tools/ioemu/hw/ioapic.h b/tools/ioemu/hw/ioapic.h new file mode 100644 index 0000000000..a243b7f59d --- /dev/null +++ b/tools/ioemu/hw/ioapic.h @@ -0,0 +1,128 @@ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001 MandrakeSoft S.A. +// +// MandrakeSoft S.A. +// 43, rue d'Aboukir +// 75002 Paris - France +// http://www.linux-mandrake.com/ +// http://www.mandrakesoft.com/ +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef __IOAPIC_H +#define __IOAPIC_H + +#include "xc.h" +#include +#include + +#define IOAPIC_NUM_PINS 24 +#define IOAPIC_VERSION_ID 0x11 +#define IOAPIC_LEVEL_TRIGGER 1 +#define APIC_DM_FIXED 0 +#define APIC_DM_LOWPRI 1 + + + +#ifdef CONFIG_SMP +#define LOCK_PREFIX "lock ; " +#else +#define LOCK_PREFIX "" +#endif + +#ifdef __I386__ +#define __OS "q" +#define __OP "r" +#else +#define __OS "l" /* Operation Suffix */ +#define __OP "e" /* Operand Prefix */ +#endif + +#define ADDR (*(volatile long *) addr) +#if 0 +#endif +extern void *shared_page; +extern FILE *logfile; +#ifdef __BIGENDIAN__ +typedef union RedirStatus +{ + uint64_t value; + struct { + uint8_t dest_id; + uint8_t reserved[4]; + uint8_t reserve:7; + uint8_t mask:1; /* interrupt mask*/ + uint8_t trigmod:1; + uint8_t remoteirr:1; + uint8_t polarity:1; + uint8_t delivestatus:1; + uint8_t destmode:1; + uint8_t deliver_mode:3; + uint8_t vector; + }RedirForm; +}RedirStatus; +#else +typedef union RedirStatus +{ + uint64_t value; + struct { + uint8_t vector; + uint8_t deliver_mode:3; + uint8_t destmode:1; + uint8_t delivestatus:1; + uint8_t polarity:1; + uint8_t remoteirr:1; + uint8_t trigmod:1; + uint8_t mask:1; /* interrupt mask*/ + uint8_t reserve:7; + uint8_t reserved[4]; + uint8_t dest_id; + }RedirForm; +}RedirStatus; +#endif +/* + * IOAPICState stands for a instance of a IOAPIC + */ + +/* FIXME tmp before working with Local APIC */ +#define IOAPIC_MEM_LENGTH 0x100 +#define IOAPIC_ENABLE_MASK 0x0 +#define IOAPIC_ENABLE_FLAG (1 << IOAPIC_ENABLE_MASK) +#define MAX_LAPIC_NUM 32 + +struct IOAPICState{ + uint32_t INTR; + uint32_t id; + uint32_t arb_id; + uint32_t flags; + unsigned long base_address; + uint32_t irr; + uint32_t isr; /* This is used for level trigger */ + uint8_t vector_irr[256]; + RedirStatus redirtbl[IOAPIC_NUM_PINS]; + uint32_t ioregsel; + uint32_t lapic_count; + vlapic_info *lapic_info[MAX_LAPIC_NUM]; +}; +#define IOAPIC_REG_APIC_ID 0x0 +#define IOAPIC_REG_VERSION 0x1 +#define IOAPIC_REG_ARB_ID 0x2 +#define IOAPICEnabled(s) (s->flags & IOAPIC_ENABLE_FLAG) + +typedef struct IOAPICState IOAPICState; + +#endif diff --git a/tools/ioemu/hw/pc.c b/tools/ioemu/hw/pc.c index 70cafc55f1..3c7e62722e 100644 --- a/tools/ioemu/hw/pc.c +++ b/tools/ioemu/hw/pc.c @@ -543,6 +543,9 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device, pci_ne2000_init(pci_bus, &nd_table[i]); } pci_piix3_ide_init(pci_bus, bs_table); +#ifdef APIC_SUPPORT + IOAPICInit(); +#endif } else { nb_nics1 = nb_nics; if (nb_nics1 > NE2000_NB_MAX) diff --git a/tools/ioemu/hw/pci.c b/tools/ioemu/hw/pci.c index 2fed66f0a1..aeec38b0dc 100644 --- a/tools/ioemu/hw/pci.c +++ b/tools/ioemu/hw/pci.c @@ -53,6 +53,7 @@ target_phys_addr_t pci_mem_base; static int pci_irq_index; static uint32_t pci_irq_levels[4][PCI_IRQ_WORDS]; static PCIBus *first_bus; +extern FILE *logfile; static PCIBus *pci_register_bus(void) { @@ -569,13 +570,26 @@ static void piix3_reset(PIIX3State *d) pci_conf[0xae] = 0x00; } +#define PIIX_CONFIG_XBCS 0x4f +void piix3_write_config(PCIDevice *d, + uint32_t address, uint32_t val, int len) +{ + if ((PIIX3State *)d != piix3_state){ + fprintf(logfile, "piix3_write_config: error PCIDevice\n"); + return; + } + + pci_default_write_config(d, address, val, len); +} + + void piix3_init(PCIBus *bus) { PIIX3State *d; uint8_t *pci_conf; d = (PIIX3State *)pci_register_device(bus, "PIIX3", sizeof(PIIX3State), - -1, NULL, NULL); + -1, NULL, piix3_write_config); register_savevm("PIIX3", 0, 1, generic_pci_save, generic_pci_load, d); piix3_state = d; diff --git a/tools/ioemu/target-i386-dm/Makefile b/tools/ioemu/target-i386-dm/Makefile index 23743167e0..3cb11c9705 100644 --- a/tools/ioemu/target-i386-dm/Makefile +++ b/tools/ioemu/target-i386-dm/Makefile @@ -188,7 +188,7 @@ endif ######################################################### -DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE +DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DAPIC_SUPPORT LIBS+=-lm -L../../libxc -lxc ifndef CONFIG_USER_ONLY LIBS+=-lz @@ -246,6 +246,7 @@ endif # must use static linking to avoid leaving stuff in virtual address space VL_OBJS=vl.o exec.o monitor.o osdep.o block.o readline.o pci.o console.o VL_OBJS+=block-cow.o block-qcow.o block-vmdk.o block-cloop.o aes.o +VL_OBJS+=ioapic.o #VL_OBJS+= block-cloop.o SOUND_HW = sb16.o diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c index a53c04cbff..732065efa0 100644 --- a/tools/ioemu/target-i386-dm/helper2.c +++ b/tools/ioemu/target-i386-dm/helper2.c @@ -320,7 +320,7 @@ do_interrupt(CPUState *env, int vector) // Send a message on the event channel. Add the vector to the shared mem // page. - intr = &(shared_page->vcpu_iodata[0].vp_intr[0]); + intr = &(shared_page->sp_global.pic_intr[0]); atomic_set_bit(vector, intr); if (loglevel & CPU_LOG_INT) fprintf(logfile, "injecting vector: %x\n", vector); @@ -345,11 +345,11 @@ int main_loop(void) FD_ZERO(&rfds); while (1) { - if (vm_running) { - if (shutdown_requested) { - break; + if (vm_running) { + if (shutdown_requested) { + break; + } } - } /* Wait up to one seconds. */ tv.tv_sec = 0; @@ -370,14 +370,19 @@ int main_loop(void) #endif main_loop_wait(0); - +#ifdef APIC_SUPPORT + ioapic_update_EOI(); +#endif cpu_timer_handler(env); if (env->interrupt_request & CPU_INTERRUPT_HARD) { env->interrupt_request &= ~CPU_INTERRUPT_HARD; vector = cpu_get_pic_interrupt(env); do_interrupt(env, vector); } - +#ifdef APIC_SUPPORT + if (ioapic_has_intr()) + do_ioapic(); +#endif if (env->send_event) { int ret; ret = xc_evtchn_send(xc_handle, ioreq_port); diff --git a/xen/arch/x86/vmx_intercept.c b/xen/arch/x86/vmx_intercept.c index 1ed715ffcc..c68195090b 100644 --- a/xen/arch/x86/vmx_intercept.c +++ b/xen/arch/x86/vmx_intercept.c @@ -213,7 +213,8 @@ void vmx_hooks_assist(struct vcpu *d) { vcpu_iodata_t * vio = get_vio(d->domain, d->vcpu_id); ioreq_t *p = &vio->vp_ioreq; - unsigned long *intr = &(vio->vp_intr[0]); + shared_iopage_t *sp = get_sp(d->domain); + u64 *intr = &(sp->sp_global.pic_intr[0]); struct vmx_virpit_t *vpit = &(d->domain->arch.vmx_platform.vmx_pit); int rw_mode; diff --git a/xen/arch/x86/vmx_io.c b/xen/arch/x86/vmx_io.c index daa2d7d471..364fa38c76 100644 --- a/xen/arch/x86/vmx_io.c +++ b/xen/arch/x86/vmx_io.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -29,10 +30,12 @@ #include #include #include -#include -#include #include #include +#include + +#include +#include #ifdef CONFIG_VMX #if defined (__i386__) @@ -515,38 +518,100 @@ static __inline__ int find_highest_irq(u32 *pintr) return __fls(pintr[0]); } +#define BSP_CPU(d) (!(d->vcpu_id)) +static inline void clear_extint(struct vcpu *v) +{ + global_iodata_t *spg; + int i; + spg = &get_sp(v->domain)->sp_global; + + for(i = 0; i < INTR_LEN; i++) + spg->pic_intr[i] = 0; +} + +static inline void clear_highest_bit(struct vcpu *v, int vector) +{ + global_iodata_t *spg; + + spg = &get_sp(v->domain)->sp_global; + + clear_bit(vector, &spg->pic_intr[0]); +} + +static inline int find_highest_pic_irq(struct vcpu *v) +{ + u64 intr[INTR_LEN]; + global_iodata_t *spg; + int i; + + if(!BSP_CPU(v)) + return -1; + + spg = &get_sp(v->domain)->sp_global; + + for(i = 0; i < INTR_LEN; i++){ + intr[i] = spg->pic_intr[i] & ~spg->pic_mask[i]; + } + + return find_highest_irq((u32 *)&intr[0]); +} + /* * Return 0-255 for pending irq. * -1 when no pending. */ -static inline int find_highest_pending_irq(struct vcpu *d) +static inline int find_highest_pending_irq(struct vcpu *v, int *type) { - vcpu_iodata_t *vio; + int result = -1; + if ((result = find_highest_pic_irq(v)) != -1){ + *type = VLAPIC_DELIV_MODE_EXT; + return result; + } + return result; +} - vio = get_vio(d->domain, d->vcpu_id); +static inline void +interrupt_post_injection(struct vcpu * v, int vector, int type) +{ + struct vmx_virpit_t *vpit = &(v->domain->arch.vmx_platform.vmx_pit); + switch(type) + { + case VLAPIC_DELIV_MODE_EXT: + if (vpit->pending_intr_nr && vector == vpit->vector) + vpit->pending_intr_nr--; + else + clear_highest_bit(v, vector); + + if (vector == vpit->vector && !vpit->first_injected){ + vpit->first_injected = 1; + vpit->pending_intr_nr = 0; + } + if (vector == vpit->vector) + vpit->inject_point = NOW(); + break; - if (vio == 0) { - VMX_DBG_LOG(DBG_LEVEL_1, - "bad shared page: %lx", (unsigned long) vio); - domain_crash_synchronous(); + default: + printk("Not support interrupt type\n"); + break; } - - return find_highest_irq((unsigned int *)&vio->vp_intr[0]); } -static inline void clear_highest_bit(struct vcpu *d, int vector) +static inline void +enable_irq_window(unsigned long cpu_exec_control) { - vcpu_iodata_t *vio; - - vio = get_vio(d->domain, d->vcpu_id); + if (!(cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING)) { + cpu_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING; + __vmwrite(CPU_BASED_VM_EXEC_CONTROL, cpu_exec_control); + } +} - if (vio == 0) { - VMX_DBG_LOG(DBG_LEVEL_1, - "bad shared page: %lx", (unsigned long) vio); - domain_crash_synchronous(); +static inline void +disable_irq_window(unsigned long cpu_exec_control) +{ + if ( cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING ) { + cpu_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING; + __vmwrite(CPU_BASED_VM_EXEC_CONTROL, cpu_exec_control); } - - clear_bit(vector, &vio->vp_intr[0]); } static inline int irq_masked(unsigned long eflags) @@ -554,50 +619,68 @@ static inline int irq_masked(unsigned long eflags) return ((eflags & X86_EFLAGS_IF) == 0); } -void vmx_intr_assist(struct vcpu *d) +void vmx_intr_assist(struct vcpu *v) { - int highest_vector = find_highest_pending_irq(d); - unsigned long intr_fields, eflags; - struct vmx_virpit_t *vpit = &(d->domain->arch.vmx_platform.vmx_pit); + int intr_type; + int highest_vector = find_highest_pending_irq(v, &intr_type); + unsigned long intr_fields, eflags, interruptibility, cpu_exec_control; - if (highest_vector == -1) - return; + __vmread(CPU_BASED_VM_EXEC_CONTROL, &cpu_exec_control); - __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields); - if (intr_fields & INTR_INFO_VALID_MASK) { - VMX_DBG_LOG(DBG_LEVEL_1, "vmx_intr_assist: intr_fields: %lx", - intr_fields); + if (highest_vector == -1) { + disable_irq_window(cpu_exec_control); return; } - __vmread(GUEST_RFLAGS, &eflags); - if (irq_masked(eflags)) { - VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, eflags: %lx", - highest_vector, eflags); - return; - } - - if (vpit->pending_intr_nr && highest_vector == vpit->vector) - vpit->pending_intr_nr--; - else - clear_highest_bit(d, highest_vector); - - /* close the window between guest PIT initialization and sti */ - if (highest_vector == vpit->vector && !vpit->first_injected){ - vpit->first_injected = 1; - vpit->pending_intr_nr = 0; - } - - intr_fields = (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR | highest_vector); - __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields); - - __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0); - - TRACE_3D(TRC_VMX_INT, d->domain->domain_id, highest_vector, 0); - if (highest_vector == vpit->vector) - vpit->inject_point = NOW(); - - return; + __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields); + + if (intr_fields & INTR_INFO_VALID_MASK) { + VMX_DBG_LOG(DBG_LEVEL_1, "vmx_intr_assist: intr_fields: %lx", + intr_fields); + return; + } + + __vmread(GUEST_INTERRUPTIBILITY_INFO, &interruptibility); + + if (interruptibility) { + enable_irq_window(cpu_exec_control); + VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, interruptibility: %lx", + highest_vector, interruptibility); + return; + } + + __vmread(GUEST_RFLAGS, &eflags); + + switch (intr_type) { + case VLAPIC_DELIV_MODE_EXT: + if (irq_masked(eflags)) { + enable_irq_window(cpu_exec_control); + VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, eflags: %lx", + highest_vector, eflags); + return; + } + + intr_fields = (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR + | highest_vector); + __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields); + __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0); + + TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0); + break; + case VLAPIC_DELIV_MODE_FIXED: + case VLAPIC_DELIV_MODE_LPRI: + case VLAPIC_DELIV_MODE_SMI: + case VLAPIC_DELIV_MODE_NMI: + case VLAPIC_DELIV_MODE_INIT: + case VLAPIC_DELIV_MODE_STARTUP: + default: + printk("Unsupported interrupt type\n"); + BUG(); + break; + } + + interrupt_post_injection(v, highest_vector, intr_type); + return; } void vmx_do_resume(struct vcpu *d) diff --git a/xen/arch/x86/vmx_vmcs.c b/xen/arch/x86/vmx_vmcs.c index 160a88ca36..fc2376ba76 100644 --- a/xen/arch/x86/vmx_vmcs.c +++ b/xen/arch/x86/vmx_vmcs.c @@ -153,6 +153,8 @@ int vmx_setup_platform(struct vcpu *d, struct cpu_user_regs *regs) p = map_domain_page(mpfn); d->domain->arch.vmx_platform.shared_page_va = (unsigned long)p; + VMX_DBG_LOG(DBG_LEVEL_1, "eport: %x\n", iopacket_port(d->domain)); + clear_bit(iopacket_port(d->domain), &d->domain->shared_info->evtchn_mask[0]); diff --git a/xen/include/asm-x86/vmx.h b/xen/include/asm-x86/vmx.h index 66974a156c..43e89bf873 100644 --- a/xen/include/asm-x86/vmx.h +++ b/xen/include/asm-x86/vmx.h @@ -339,14 +339,19 @@ static inline int vmx_paging_enabled(struct vcpu *v) return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG); } +static inline shared_iopage_t *get_sp(struct domain *d) +{ + return (shared_iopage_t *) d->arch.vmx_platform.shared_page_va; +} + static inline vcpu_iodata_t *get_vio(struct domain *d, unsigned long cpu) { - return &((shared_iopage_t *) d->arch.vmx_platform.shared_page_va)->vcpu_iodata[cpu]; + return &get_sp(d)->vcpu_iodata[cpu]; } static inline int iopacket_port(struct domain *d) { - return ((shared_iopage_t *) d->arch.vmx_platform.shared_page_va)->sp_global.eport; + return get_sp(d)->sp_global.eport; } #endif /* __ASM_X86_VMX_H__ */ diff --git a/xen/include/asm-x86/vmx_virpit.h b/xen/include/asm-x86/vmx_virpit.h index 1ba907cf3c..6a0a4edab7 100644 --- a/xen/include/asm-x86/vmx_virpit.h +++ b/xen/include/asm-x86/vmx_virpit.h @@ -20,7 +20,7 @@ struct vmx_virpit_t { int vector; /* the pit irq vector */ unsigned int period; /* the frequency. e.g. 10ms*/ unsigned int channel; /* the pit channel, counter 0~2 */ - unsigned long *intr_bitmap; + u64 *intr_bitmap; unsigned int pending_intr_nr; /* the couner for pending timer interrupts */ unsigned long long inject_point; /* the time inject virt intr */ struct ac_timer pit_timer; /* periodic timer for mode 2*/ diff --git a/xen/include/public/io/ioreq.h b/xen/include/public/io/ioreq.h index 52f2afcb33..c06718b010 100644 --- a/xen/include/public/io/ioreq.h +++ b/xen/include/public/io/ioreq.h @@ -49,14 +49,11 @@ typedef struct { #define MAX_VECTOR 256 #define BITS_PER_BYTE 8 -#define INTR_LEN (MAX_VECTOR/(BITS_PER_BYTE * sizeof(unsigned long))) +#define INTR_LEN (MAX_VECTOR/(BITS_PER_BYTE * sizeof(u64))) -/* We only track the master PIC state here */ typedef struct { - uint16_t irr; /* interrupt request register */ - uint16_t imr; /* interrupt mask register */ - uint16_t isr; /* interrupt service register */ - + u64 pic_intr[INTR_LEN]; + u64 pic_mask[INTR_LEN]; int eport; /* Event channel port */ } global_iodata_t; diff --git a/xen/include/public/io/vmx_vlapic.h b/xen/include/public/io/vmx_vlapic.h new file mode 100644 index 0000000000..c414329628 --- /dev/null +++ b/xen/include/public/io/vmx_vlapic.h @@ -0,0 +1,57 @@ +#ifndef _VMX_VLAPIC_H +#define _VMX_VLAPIC_H + +/* + We extended one bit for PIC type + */ +#define VLAPIC_DELIV_MODE_FIXED 0x0 +#define VLAPIC_DELIV_MODE_LPRI 0x1 +#define VLAPIC_DELIV_MODE_SMI 0x2 +#define VLAPIC_DELIV_MODE_NMI 0x4 +#define VLAPIC_DELIV_MODE_INIT 0x5 +#define VLAPIC_DELIV_MODE_STARTUP 0x6 +#define VLAPIC_DELIV_MODE_EXT 0x7 +#define VLAPIC_DELIV_MODE_MASK 0x8 + +#define VLAPIC_MSG_LEVEL 4 + +#define INTR_EXT 0 +#define INTR_APIC 1 +#define INTR_LAPIC 2 + +#define VL_STATE_EOI 1 +#define VL_STATE_EXT_LOCK 2 +#define VL_STATE_MSG_LOCK 3 +#define VL_STATE_EOI_LOCK 3 + +#define VLOCAL_APIC_MAX_INTS 256 +#define VLAPIC_INT_COUNT (VLOCAL_APIC_MAX_INTS/(BITS_PER_BYTE * sizeof(u64))) +#define VLAPIC_INT_COUNT_32 (VLOCAL_APIC_MAX_INTS/(BITS_PER_BYTE * sizeof(u32))) + +struct vapic_bus_message{ + u8 deliv_mode:4; /* deliver mode, including fixed, LPRI, etc */ + u8 level:1; /* level or edge */ + u8 trig_mod:1; /* assert or disassert */ + u8 reserved:2; + u8 vector; +}; + +typedef struct { + /* interrupt for PIC and ext type IOAPIC interrupt */ + u64 vl_ext_intr[VLAPIC_INT_COUNT]; + u64 vl_ext_intr_mask[VLAPIC_INT_COUNT]; + u64 vl_apic_intr[VLAPIC_INT_COUNT]; + u64 vl_apic_tmr[VLAPIC_INT_COUNT]; + u64 vl_eoi[VLAPIC_INT_COUNT]; + u32 vl_lapic_id; + u32 direct_intr; + u32 vl_apr; + u32 vl_logical_dest; + u32 vl_dest_format; + u32 vl_arb_id; + u32 vl_state; + u32 apic_msg_count; + struct vapic_bus_message vl_apic_msg[24]; +} vlapic_info; + +#endif /* _VMX_VLAPIC_H_ */ -- cgit v1.2.3