From: Arun Sharma <arun.sharma@intel.com>
To: Ian Pratt <Ian.Pratt@cl.cam.ac.uk>,
Keir Fraser <Keir.Fraser@cl.cam.ac.uk>
Cc: xen-devel@lists.xensource.com
Subject: [PATCH][8/10] Infrastructure for interrupt handling.
Date: Wed, 29 Jun 2005 22:52:55 -0700 [thread overview]
Message-ID: <20050630055255.GA7454@intel.com> (raw)
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 <yunhong.jiang@intel.com>
Signed-off-by: Eddie Dong <eddie.dong@intel.com>
Signed-off-by: Arun Sharma <arun.sharma@intel.com>
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/exec-all.h
--- a/tools/ioemu/exec-all.h Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/exec-all.h Thu Jun 30 05:24:52 2005
@@ -573,7 +573,7 @@
}
#endif
-//#define DEBUG_UNUSED_IOPORT
-//#define DEBUG_IOPORT
+#define DEBUG_UNUSED_IOPORT
+#define DEBUG_IOPORT
#define TARGET_VMX
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/hw/i8259.c
--- a/tools/ioemu/hw/i8259.c Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/hw/i8259.c Thu Jun 30 05:24:52 2005
@@ -22,12 +22,16 @@
* THE SOFTWARE.
*/
#include "vl.h"
+#include "xc.h"
+#include <io/ioreq.h>
/* debug PIC */
//#define DEBUG_PIC
//#define DEBUG_IRQ_LATENCY
#define DEBUG_IRQ_COUNT
+
+extern void pit_reset_vmx_vectors();
typedef struct PicState {
uint8_t last_irr; /* edge detection */
@@ -121,6 +125,26 @@
}
}
+/* 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 @@
#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 @@
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 -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/target-i386-dm/helper2.c Thu Jun 30 05:24:52 2005
@@ -320,7 +320,7 @@
// 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 @@
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 @@
#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 -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/include/asm-x86/vmx.h
--- a/xen/include/asm-x86/vmx.h Thu Jun 30 04:32:55 2005
+++ b/xen/include/asm-x86/vmx.h Thu Jun 30 05:24:52 2005
@@ -339,14 +339,19 @@
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 -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/arch/x86/vmx_vmcs.c
--- a/xen/arch/x86/vmx_vmcs.c Thu Jun 30 04:32:55 2005
+++ b/xen/arch/x86/vmx_vmcs.c Thu Jun 30 05:24:52 2005
@@ -153,6 +153,8 @@
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 -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/include/asm-x86/vmx_virpit.h
--- a/xen/include/asm-x86/vmx_virpit.h Thu Jun 30 04:32:55 2005
+++ b/xen/include/asm-x86/vmx_virpit.h Thu Jun 30 05:24:52 2005
@@ -20,7 +20,7 @@
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 -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/target-i386-dm/Makefile
--- a/tools/ioemu/target-i386-dm/Makefile Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/target-i386-dm/Makefile Thu Jun 30 05:24:52 2005
@@ -188,7 +188,7 @@
#########################################################
-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 @@
# 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 -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/hw/pc.c Thu Jun 30 05:24:52 2005
@@ -543,6 +543,9 @@
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 -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/arch/x86/vmx_io.c
--- a/xen/arch/x86/vmx_io.c Thu Jun 30 04:32:55 2005
+++ b/xen/arch/x86/vmx_io.c Thu Jun 30 05:24:52 2005
@@ -22,6 +22,7 @@
#include <xen/lib.h>
#include <xen/errno.h>
#include <xen/trace.h>
+#include <xen/event.h>
#include <asm/current.h>
#include <asm/cpufeature.h>
@@ -29,10 +30,12 @@
#include <asm/msr.h>
#include <asm/vmx.h>
#include <asm/vmx_vmcs.h>
-#include <xen/event.h>
-#include <public/io/ioreq.h>
#include <asm/vmx_platform.h>
#include <asm/vmx_virpit.h>
+#include <asm/apic.h>
+
+#include <public/io/ioreq.h>
+#include <public/io/vmx_vlapic.h>
#ifdef CONFIG_VMX
#if defined (__i386__)
@@ -515,38 +518,100 @@
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)
-{
- vcpu_iodata_t *vio;
-
- vio = get_vio(d->domain, d->vcpu_id);
-
- if (vio == 0) {
- VMX_DBG_LOG(DBG_LEVEL_1,
- "bad shared page: %lx", (unsigned long) vio);
- domain_crash_synchronous();
- }
-
- return find_highest_irq((unsigned int *)&vio->vp_intr[0]);
-}
-
-static inline void clear_highest_bit(struct vcpu *d, int vector)
-{
- vcpu_iodata_t *vio;
-
- vio = get_vio(d->domain, d->vcpu_id);
-
- if (vio == 0) {
- VMX_DBG_LOG(DBG_LEVEL_1,
- "bad shared page: %lx", (unsigned long) vio);
- domain_crash_synchronous();
- }
-
- clear_bit(vector, &vio->vp_intr[0]);
+static inline int find_highest_pending_irq(struct vcpu *v, int *type)
+{
+ int result = -1;
+ if ((result = find_highest_pic_irq(v)) != -1){
+ *type = VLAPIC_DELIV_MODE_EXT;
+ return result;
+ }
+ return result;
+}
+
+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;
+
+ default:
+ printk("Not support interrupt type\n");
+ break;
+ }
+}
+
+static inline void
+enable_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);
+ }
+}
+
+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);
+ }
}
static inline int irq_masked(unsigned long eflags)
@@ -554,50 +619,68 @@
return ((eflags & X86_EFLAGS_IF) == 0);
}
-void vmx_intr_assist(struct vcpu *d)
-{
- 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);
-
- if (highest_vector == -1)
+void vmx_intr_assist(struct vcpu *v)
+{
+ int intr_type;
+ int highest_vector = find_highest_pending_irq(v, &intr_type);
+ unsigned long intr_fields, eflags, interruptibility, cpu_exec_control;
+
+ __vmread(CPU_BASED_VM_EXEC_CONTROL, &cpu_exec_control);
+
+ if (highest_vector == -1) {
+ disable_irq_window(cpu_exec_control);
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_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 -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/arch/x86/vmx_intercept.c
--- a/xen/arch/x86/vmx_intercept.c Thu Jun 30 04:32:55 2005
+++ b/xen/arch/x86/vmx_intercept.c Thu Jun 30 05:24:52 2005
@@ -213,7 +213,8 @@
{
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 -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/hw/pci.c
--- a/tools/ioemu/hw/pci.c Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/hw/pci.c Thu Jun 30 05:24:52 2005
@@ -53,6 +53,7 @@
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 @@
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 -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/include/public/io/ioreq.h
--- a/xen/include/public/io/ioreq.h Thu Jun 30 04:32:55 2005
+++ b/xen/include/public/io/ioreq.h Thu Jun 30 05:24:52 2005
@@ -49,14 +49,11 @@
#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 -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/hw/ioapic.c
--- /dev/null Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/hw/ioapic.c Thu Jun 30 05:24:52 2005
@@ -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("<ioapic_inj_irq> Ext interrupt\n");
+ return 0;
+ default:
+ IOAPIC_ERR("<ioapic_inj_irq> 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, "<ioapic_get_delivery_bitmask>: 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<<i);
+ else {
+ if (low_priority > 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 -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/hw/ioapic.h
--- /dev/null Thu Jun 30 04:32:55 2005
+++ b/tools/ioemu/hw/ioapic.h Thu Jun 30 05:24:52 2005
@@ -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 <io/ioreq.h>
+#include <io/vmx_vlapic.h>
+
+#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 -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/include/public/io/vmx_vlapic.h
--- /dev/null Thu Jun 30 04:32:55 2005
+++ b/xen/include/public/io/vmx_vlapic.h Thu Jun 30 05:24:52 2005
@@ -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_ */
reply other threads:[~2005-06-30 5:52 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20050630055255.GA7454@intel.com \
--to=arun.sharma@intel.com \
--cc=Ian.Pratt@cl.cam.ac.uk \
--cc=Keir.Fraser@cl.cam.ac.uk \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.