]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
inmates: Factor our interrupt library services
authorJan Kiszka <jan.kiszka@siemens.com>
Wed, 16 Jul 2014 19:49:25 +0000 (21:49 +0200)
committerJan Kiszka <jan.kiszka@siemens.com>
Mon, 21 Jul 2014 06:53:05 +0000 (08:53 +0200)
This simplifies registering interrupt handlers and also moves the EOI
ACK into library code. Only 64-bit support so far. Still, we need to fix
the definition of s64/u64 and make read/write_msr compatible with 32-bit
builds.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
inmates/demos/x86/Makefile
inmates/demos/x86/apic-demo.c
inmates/lib/x86/header.S
inmates/lib/x86/inmate.h
inmates/lib/x86/int.c [new file with mode: 0644]

index 4cae9ee3c208296fec38205ef6ddfa7002651914..893a3caf9fd0e1766aed367d2109e9a7ed503626 100644 (file)
@@ -20,6 +20,7 @@ tiny-demo-y := tiny-demo.o \
        $(LIBDIR)/header.o $(LIBDIR)/printk.o $(LIBDIR)/pm-timer.o
 
 apic-demo-y := apic-demo.o \
-       $(LIBDIR)/header.o $(LIBDIR)/printk.o $(LIBDIR)/pm-timer.o
+       $(LIBDIR)/header.o $(LIBDIR)/printk.o $(LIBDIR)/pm-timer.o \
+       $(LIBDIR)/int.o
 
 $(eval $(call DECLARE_TARGETS,$(INMATES)))
index 1796204b6eb65df0889eb7fb7a49bae60d5cf210..1a6dcc8de66ed8c315d2ebb03398d62e55464e06 100644 (file)
 #define NS_PER_MSEC            1000000UL
 #define NS_PER_SEC             1000000000UL
 
-#define NUM_IDT_DESC           33
 #define APIC_TIMER_VECTOR      32
 
-#define X2APIC_EOI             0x80b
-#define X2APIC_SPIV            0x80f
 #define X2APIC_LVTT            0x832
 #define X2APIC_TMICT           0x838
 #define X2APIC_TMCCT           0x839
 #define X2APIC_TDCR            0x83e
 
-#define APIC_EOI_ACK           0
-
-static u32 idt[NUM_IDT_DESC * 4];
 static unsigned long apic_frequency;
 static unsigned long expected_time;
 static unsigned long min = -1, max;
 
-struct desc_table_reg {
-       u16 limit;
-       u64 base;
-} __attribute__((packed));
-
-static inline unsigned long read_msr(unsigned int msr)
-{
-       u32 low, high;
-
-       asm volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
-       return low | ((unsigned long)high << 32);
-}
-
-static inline void write_msr(unsigned int msr, unsigned long val)
-{
-       asm volatile("wrmsr"
-               : /* no output */
-               : "c" (msr), "a" (val), "d" (val >> 32)
-               : "memory");
-}
-
-static inline void write_idtr(struct desc_table_reg *val)
-{
-       asm volatile("lidtq %0" : "=m" (*val));
-}
-
-void irq_handler(void)
+static void irq_handler(void)
 {
        unsigned long delta;
 
-       write_msr(X2APIC_EOI, APIC_EOI_ACK);
-
        delta = read_pm_timer() - expected_time;
        if (delta < min)
                min = delta;
@@ -89,12 +55,11 @@ void irq_handler(void)
 
 static void init_apic(void)
 {
-       unsigned long entry = (unsigned long)irq_entry + FSEGMENT_BASE;
-       struct desc_table_reg dtr;
        unsigned long start, end;
        unsigned long tmr;
 
-       write_msr(X2APIC_SPIV, 0x1ff);
+       int_init();
+       int_set_handler(APIC_TIMER_VECTOR, irq_handler);
 
        write_msr(X2APIC_TDCR, 3);
 
@@ -112,14 +77,6 @@ static void init_apic(void)
        printk("Calibrated APIC frequency: %lu kHz\n",
               (apic_frequency * 16 + 500) / 1000);
 
-       idt[APIC_TIMER_VECTOR * 4] = (entry & 0xffff) | (INMATE_CS64 << 16);
-       idt[APIC_TIMER_VECTOR * 4 + 1] = 0x8e00 | (entry & 0xffff0000);
-       idt[APIC_TIMER_VECTOR * 4 + 2] = entry >> 32;
-
-       dtr.limit = NUM_IDT_DESC * 16 - 1;
-       dtr.base = (u64)&idt;
-       write_idtr(&dtr);
-
        write_msr(X2APIC_LVTT, APIC_TIMER_VECTOR);
        expected_time = read_pm_timer();
        write_msr(X2APIC_TMICT, 1);
index 8881ffb24cd161198624229fc0679be871ed101f..7bac523b06df03001f233e93ea597bb0b2c3a93f 100644 (file)
@@ -92,36 +92,3 @@ pdpt:
        .align(4096)
 pd:
        .quad   0x0000000000000083
-
-
-       .global irq_entry
-       .balign 16
-irq_entry:
-       push %rax
-       push %rcx
-       push %rdx
-       push %rsi
-       push %rdi
-       push %r8
-       push %r9
-       push %r10
-       push %r11
-
-       call irq_handler - FSEGMENT_BASE
-
-       pop %r11
-       pop %r10
-       pop %r9
-       pop %r8
-       pop %rdi
-       pop %rsi
-       pop %rdx
-       pop %rcx
-       pop %rax
-
-       iretq
-
-
-/* to please linker if irq_entry remains unused */
-       .weak irq_handler
-irq_handler:
index 3aa3c2659774bbe4a311129c564733e60ad0315a..fe473acfd941d75cfacc114f5f4ddff680460aa0 100644 (file)
@@ -17,6 +17,8 @@
 #define INMATE_CS64            0x10
 #define INMATE_DS32            0x18
 
+#define X2APIC_ID              0x802
+
 #ifndef __ASSEMBLY__
 typedef signed char s8;
 typedef unsigned char u8;
@@ -27,8 +29,8 @@ typedef unsigned short u16;
 typedef signed int s32;
 typedef unsigned int u32;
 
-typedef signed long s64;
-typedef unsigned long u64;
+typedef signed long long s64;
+typedef unsigned long long u64;
 
 typedef s8 __s8;
 typedef u8 __u8;
@@ -68,6 +70,27 @@ static inline u32 inl(u16 port)
        return v;
 }
 
+static inline u64 read_msr(unsigned int msr)
+{
+       u32 low, high;
+
+       asm volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
+       return low | ((u64)high << 32);
+}
+
+static inline void write_msr(unsigned int msr, u64 val)
+{
+       asm volatile("wrmsr"
+               : /* no output */
+               : "c" (msr), "a" (val), "d" (val >> 32)
+               : "memory");
+}
+
+static inline unsigned int cpu_id(void)
+{
+       return read_msr(X2APIC_ID);
+}
+
 #include <jailhouse/hypercall.h>
 
 #define comm_region    ((struct jailhouse_comm_region *)COMM_REGION_BASE)
@@ -77,8 +100,10 @@ void printk(const char *fmt, ...);
 
 void *memset(void *s, int c, unsigned long n);
 
-extern u8 irq_entry[];
-void irq_handler(void);
+typedef void(*int_handler_t)(void);
+
+void int_init(void);
+void int_set_handler(unsigned int vector, int_handler_t handler);
 
 void inmate_main(void);
 
diff --git a/inmates/lib/x86/int.c b/inmates/lib/x86/int.c
new file mode 100644 (file)
index 0000000..d0c9cc4
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) Siemens AG, 2014
+ *
+ * Authors:
+ *  Jan Kiszka <jan.kiszka@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <inmate.h>
+
+#define NUM_IDT_DESC           64
+
+#define X2APIC_EOI             0x80b
+#define X2APIC_SPIV            0x80f
+
+#define APIC_EOI_ACK           0
+
+struct desc_table_reg {
+       u16 limit;
+       u64 base;
+} __attribute__((packed));
+
+static u32 idt[NUM_IDT_DESC * 4];
+static int_handler_t int_handler[NUM_IDT_DESC];
+
+extern u8 irq_entry[];
+
+static inline void write_idtr(struct desc_table_reg *val)
+{
+       asm volatile("lidt %0" : : "m" (*val));
+}
+
+void int_init(void)
+{
+       struct desc_table_reg dtr;
+
+       write_msr(X2APIC_SPIV, 0x1ff);
+
+       dtr.limit = NUM_IDT_DESC * 16 - 1;
+       dtr.base = (u64)&idt;
+       write_idtr(&dtr);
+}
+
+static void __attribute__((used)) handle_interrupt(unsigned int vector)
+{
+       int_handler[vector]();
+       write_msr(X2APIC_EOI, APIC_EOI_ACK);
+}
+
+void int_set_handler(unsigned int vector, int_handler_t handler)
+{
+       unsigned long entry = (unsigned long)irq_entry + vector * 16;
+
+       int_handler[vector] = handler;
+
+       idt[vector * 4] = (entry & 0xffff) | (INMATE_CS64 << 16);
+       idt[vector * 4 + 1] = 0x8e00 | (entry & 0xffff0000);
+       idt[vector * 4 + 2] = entry >> 32;
+}
+
+#ifdef __x86_64__
+asm(
+".macro irq_prologue vector\n\t"
+       "push %rdi\n\t"
+       "mov $vector,%rdi\n\t"
+       "jmp irq_common\n"
+".endm\n\t"
+
+       ".global irq_entry\n\t"
+       ".balign 16\n"
+"irq_entry:\n"
+"vector=0\n"
+".rept 64\n"
+       "irq_prologue vector\n\t"
+       "vector=vector+1\n\t"
+       ".balign 16\n\t"
+".endr\n"
+
+"irq_common:\n\t"
+       "push %rax\n\t"
+       "push %rcx\n\t"
+       "push %rdx\n\t"
+       "push %rsi\n\t"
+       "push %r8\n\t"
+       "push %r9\n\t"
+       "push %r10\n\t"
+       "push %r11\n\t"
+
+       "call handle_interrupt\n\t"
+
+       "pop %r11\n\t"
+       "pop %r10\n\t"
+       "pop %r9\n\t"
+       "pop %r8\n\t"
+       "pop %rsi\n\t"
+       "pop %rdx\n\t"
+       "pop %rcx\n\t"
+       "pop %rax\n\t"
+       "pop %rdi\n\t"
+
+       "iretq"
+);
+#else
+#error implement me!
+#endif