Skip to contentSkip to conversation

Infrastructure for interrupt handling.

PATCH New Arun Sharma 1 participant 1 message Jun 30, 2005

lore
Share & tools
lore
#0 lore raw

PATCH 8/10 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.

tools/ioemu/exec-all.h +2 -2
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/exec-all.h
@@ -573,7 +573,7 @@
 }
 #endif
 
-//#define DEBUG_UNUSED_IOPORT
-//#define DEBUG_IOPORT
+#define DEBUG_UNUSED_IOPORT
+#define DEBUG_IOPORT
 #define TARGET_VMX
 
tools/ioemu/hw/i8259.c +29 -0
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/hw/i8259.c
@@ -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)
tools/ioemu/target-i386-dm/helper2.c +12 -7
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/target-i386-dm/helper2.c
@@ -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);
xen/include/asm-x86/vmx.h +7 -2
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/include/asm-x86/vmx.h
@@ -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__ */
xen/arch/x86/vmx_vmcs.c +2 -0
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/arch/x86/vmx_vmcs.c
@@ -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]);
 
xen/include/asm-x86/vmx_virpit.h +1 -1
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/include/asm-x86/vmx_virpit.h
@@ -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*/
tools/ioemu/target-i386-dm/Makefile +2 -1
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/target-i386-dm/Makefile
@@ -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
tools/ioemu/hw/pc.c +3 -0
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/hw/pc.c
@@ -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)
xen/arch/x86/vmx_io.c +156 -73

260 lines not on this page · raw message

xen/arch/x86/vmx_intercept.c +2 -1
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/arch/x86/vmx_intercept.c
@@ -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;
 
tools/ioemu/hw/pci.c +15 -1
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 tools/ioemu/hw/pci.c
@@ -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;
xen/include/public/io/ioreq.h +3 -6
diff -r 96a4c0de6e53 -r 2d6fd3bba3c2 xen/include/public/io/ioreq.h
@@ -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;
 
tools/ioemu/hw/ioapic.c new file +704 -0

704 lines not on this page · raw message

tools/ioemu/hw/ioapic.h new file +128 -0

128 lines not on this page · raw message

xen/include/public/io/vmx_vlapic.h new file +57 -0

57 lines not on this page · raw message