aboutsummaryrefslogtreecommitdiffstats
path: root/extras
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2005-02-11 18:04:56 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2005-02-11 18:04:56 +0000
commit054206d161ad06d19298132f1c3a54d2a1598270 (patch)
tree8e4829d2ba79a078e5175c2efc717e5fbcafcfb1 /extras
parent28268ccd6d678a5bff48c00acc014f6c9df639cc (diff)
downloadxen-054206d161ad06d19298132f1c3a54d2a1598270.tar.gz
xen-054206d161ad06d19298132f1c3a54d2a1598270.tar.bz2
xen-054206d161ad06d19298132f1c3a54d2a1598270.zip
bitkeeper revision 1.1185 (420cf3c8-bMMcsnH1kMVRwy5AQ-ecg)
Various mini-os and Xen fixes. The M2P table is now definitely accessible (read-only) from guest context. Signed-off-by: keir.fraser@cl.cam.ac.uk
Diffstat (limited to 'extras')
-rw-r--r--extras/mini-os/h/lib.h17
-rw-r--r--extras/mini-os/h/mm.h60
-rw-r--r--extras/mini-os/h/os.h22
-rw-r--r--extras/mini-os/h/types.h11
-rw-r--r--extras/mini-os/kernel.c2
-rw-r--r--extras/mini-os/lib/printf.c4
-rw-r--r--extras/mini-os/mm.c2
-rw-r--r--extras/mini-os/traps.c139
-rw-r--r--extras/mini-os/x86_64.S160
9 files changed, 316 insertions, 101 deletions
diff --git a/extras/mini-os/h/lib.h b/extras/mini-os/h/lib.h
index d9996a2f85..0b405ee006 100644
--- a/extras/mini-os/h/lib.h
+++ b/extras/mini-os/h/lib.h
@@ -55,22 +55,7 @@
#ifndef _LIB_H_
#define _LIB_H_
-
-/* variadic function support */
-typedef char *va_list;
-#define __va_size(type) \
- (((sizeof(type) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
-#ifdef __GNUC__
-#define va_start(ap, last) \
- ((ap) = (va_list)__builtin_next_arg(last))
-#else
-#define va_start(ap, last) \
- ((ap) = (va_list)&(last) + __va_size(last))
-#endif
-#define va_arg(ap, type) \
- (*(type *)((ap) += __va_size(type), (ap) - __va_size(type)))
-#define va_end(ap)
-
+#include <stdarg.h>
/* printing */
#define printk printf
diff --git a/extras/mini-os/h/mm.h b/extras/mini-os/h/mm.h
index 5c6224db28..c5f6ad4788 100644
--- a/extras/mini-os/h/mm.h
+++ b/extras/mini-os/h/mm.h
@@ -1,20 +1,8 @@
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
*
- * File: mm.h
- * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes:
- *
- * Date: Aug 2003
- *
- * Environment:
- * Description:
+ * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ * Copyright (c) 2005, Keir A Fraser
*
- ****************************************************************************
- * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
- ****************************************************************************
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
@@ -37,6 +25,48 @@
#ifndef _MM_H_
#define _MM_H_
+#ifdef __x86_64__
+
+#define L1_PAGETABLE_SHIFT 12
+#define L2_PAGETABLE_SHIFT 21
+#define L3_PAGETABLE_SHIFT 30
+#define L4_PAGETABLE_SHIFT 39
+
+#define L1_PAGETABLE_ENTRIES 512
+#define L2_PAGETABLE_ENTRIES 512
+#define L3_PAGETABLE_ENTRIES 512
+#define L4_PAGETABLE_ENTRIES 512
+
+/* These are page-table limitations. Current CPUs support only 40-bit phys. */
+#define PADDR_BITS 52
+#define VADDR_BITS 48
+#define PADDR_MASK ((1UL << PADDR_BITS)-1)
+#define VADDR_MASK ((1UL << VADDR_BITS)-1)
+
+#define pte_to_mfn(_pte) (((_pte) & (PADDR_MASK&PAGE_MASK)) >> PAGE_SHIFT)
+
+/* Given a virtual address, get an entry offset into a page table. */
+#define l1_table_offset(_a) \
+ (((_a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))
+#define l2_table_offset(_a) \
+ (((_a) >> L2_PAGETABLE_SHIFT) & (L2_PAGETABLE_ENTRIES - 1))
+#define l3_table_offset(_a) \
+ (((_a) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1))
+#define l4_table_offset(_a) \
+ (((_a) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 1))
+#endif
+
+#define _PAGE_PRESENT 0x001UL
+#define _PAGE_RW 0x002UL
+#define _PAGE_USER 0x004UL
+#define _PAGE_PWT 0x008UL
+#define _PAGE_PCD 0x010UL
+#define _PAGE_ACCESSED 0x020UL
+#define _PAGE_DIRTY 0x040UL
+#define _PAGE_PAT 0x080UL
+#define _PAGE_PSE 0x080UL
+#define _PAGE_GLOBAL 0x100UL
+
#define PAGE_SHIFT 12
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
@@ -72,6 +102,8 @@ static __inline__ unsigned long machine_to_phys(unsigned long machine)
#define to_phys(x) ((unsigned long)(x)-VIRT_START)
#define to_virt(x) ((void *)((unsigned long)(x)+VIRT_START))
+#define __va to_virt
+#define __pa to_phys
void init_mm(void);
unsigned long alloc_pages(int order);
diff --git a/extras/mini-os/h/os.h b/extras/mini-os/h/os.h
index 6a0447ca39..434dd992f6 100644
--- a/extras/mini-os/h/os.h
+++ b/extras/mini-os/h/os.h
@@ -29,6 +29,28 @@
#define __KERNEL_DS FLAT_KERNEL_DS
#define __KERNEL_SS FLAT_KERNEL_SS
+#define TRAP_divide_error 0
+#define TRAP_debug 1
+#define TRAP_nmi 2
+#define TRAP_int3 3
+#define TRAP_overflow 4
+#define TRAP_bounds 5
+#define TRAP_invalid_op 6
+#define TRAP_no_device 7
+#define TRAP_double_fault 8
+#define TRAP_copro_seg 9
+#define TRAP_invalid_tss 10
+#define TRAP_no_segment 11
+#define TRAP_stack_error 12
+#define TRAP_gp_fault 13
+#define TRAP_page_fault 14
+#define TRAP_spurious_int 15
+#define TRAP_copro_error 16
+#define TRAP_alignment_check 17
+#define TRAP_machine_check 18
+#define TRAP_simd_error 19
+#define TRAP_deferred_nmi 31
+
/* Everything below this point is not included by assembler (.S) files. */
#ifndef __ASSEMBLY__
diff --git a/extras/mini-os/h/types.h b/extras/mini-os/h/types.h
index 85ede91c13..7bf103ab9c 100644
--- a/extras/mini-os/h/types.h
+++ b/extras/mini-os/h/types.h
@@ -26,8 +26,13 @@ typedef signed short s16;
typedef unsigned short u16;
typedef signed int s32;
typedef unsigned int u32;
+#ifdef __i386__
typedef signed long long s64;
typedef unsigned long long u64;
+#elif defined(__x86_64__)
+typedef signed long s64;
+typedef unsigned long u64;
+#endif
typedef unsigned int size_t;
@@ -35,7 +40,13 @@ typedef unsigned int size_t;
typedef unsigned char u_char;
typedef unsigned int u_int;
typedef unsigned long u_long;
+#ifdef __i386__
typedef long long quad_t;
typedef unsigned long long u_quad_t;
typedef unsigned int uintptr_t;
+#elif defined(__x86_64__)
+typedef long quad_t;
+typedef unsigned long u_quad_t;
+typedef unsigned long uintptr_t;
+#endif
#endif /* _TYPES_H_ */
diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
index a794145e68..b6f89b8bbb 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/kernel.c
@@ -65,7 +65,7 @@ extern char shared_info[PAGE_SIZE];
static shared_info_t *map_shared_info(unsigned long pa)
{
if ( HYPERVISOR_update_va_mapping(
- (unsigned long)shared_info, pa | 3, UVMF_INVLPG) )
+ (unsigned long)shared_info, pa | 7, UVMF_INVLPG) )
{
printk("Failed to map shared_info!!\n");
*(int*)0=0;
diff --git a/extras/mini-os/lib/printf.c b/extras/mini-os/lib/printf.c
index f6232c4044..a08bb20e6c 100644
--- a/extras/mini-os/lib/printf.c
+++ b/extras/mini-os/lib/printf.c
@@ -341,7 +341,9 @@ reswitch: switch (ch = (u_char)*fmt++) {
case 'p':
ul = (uintptr_t)va_arg(ap, void *);
base = 16;
- sharpflag = (width == 0);
+ sharpflag = 0;
+ padc = '0';
+ width = sizeof(uintptr_t)*2;
goto nosign;
case 'q':
qflag = 1;
diff --git a/extras/mini-os/mm.c b/extras/mini-os/mm.c
index 2bc87a5165..40a80e2ccb 100644
--- a/extras/mini-os/mm.c
+++ b/extras/mini-os/mm.c
@@ -84,6 +84,7 @@ void init_mm(void)
*/
max_free_pfn = PFN_DOWN(to_phys(pgd));
+#ifdef __i386__
{
unsigned long *pgd = (unsigned long *)start_info.pt_base;
unsigned long pte;
@@ -110,6 +111,7 @@ void init_mm(void)
(u_long)to_virt(PFN_PHYS(start_pfn)), PFN_PHYS(start_pfn),
(u_long)to_virt(PFN_PHYS(max_free_pfn)), PFN_PHYS(max_free_pfn));
init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_free_pfn));
+#endif
/* Now initialise the physical->machine mapping table. */
diff --git a/extras/mini-os/traps.c b/extras/mini-os/traps.c
index 858c54d3f2..7000128230 100644
--- a/extras/mini-os/traps.c
+++ b/extras/mini-os/traps.c
@@ -15,7 +15,6 @@ void overflow(void);
void bounds(void);
void invalid_op(void);
void device_not_available(void);
-void double_fault(void);
void coprocessor_segment_overrun(void);
void invalid_TSS(void);
void segment_not_present(void);
@@ -33,111 +32,134 @@ extern void do_exit(void);
void dump_regs(struct pt_regs *regs)
{
- int in_kernel = 1;
unsigned long esp;
unsigned short ss;
+#ifdef __x86_64__
+ esp = regs->rsp;
+ ss = regs->ss;
+#else
esp = (unsigned long) (&regs->esp);
ss = __KERNEL_DS;
if (regs->cs & 2) {
- in_kernel = 0;
esp = regs->esp;
ss = regs->ss & 0xffff;
}
- printf("EIP: %04x:[<%p>]\n",
- 0xffff & regs->cs , regs->eip);
+#endif
+ printf("EIP: %04x:[<%p>] %08x\n",
+ 0xffff & regs->cs , regs->eip, regs->error_code);
printf("EFLAGS: %p\n",regs->eflags);
printf("eax: %p ebx: %p ecx: %p edx: %p\n",
regs->eax, regs->ebx, regs->ecx, regs->edx);
printf("esi: %p edi: %p ebp: %p esp: %p\n",
regs->esi, regs->edi, regs->ebp, esp);
+#ifdef __x86_64__
+ printf("r8 : %p r9 : %p r10: %p r11: %p\n",
+ regs->r8, regs->r9, regs->r10, regs->r11);
+ printf("r12: %p r13: %p r14: %p r15: %p\n",
+ regs->r12, regs->r13, regs->r14, regs->r15);
+#endif
printf("ds: %04x es: %04x ss: %04x\n",
regs->ds & 0xffff, regs->es & 0xffff, ss);
- printf("\n");
}
static __inline__ void dump_code(unsigned long eip)
{
- unsigned *ptr = (unsigned *)eip;
+ unsigned char *ptr = (unsigned char *)eip;
int x;
- printk("Bytes at eip:\n");
- for (x = -4; x < 5; x++)
- printf("%p", ptr[x]);
+ printk("Bytes at eip: ");
+ for ( x = -4; x < 5; x++ )
+ printf("%02x ", ptr[x]);
+ printk("\n");
}
-
-/*
- * C handlers here have their parameter-list constructed by the
- * assembler stubs above. Each one gets a pointer to a list
- * of register values (to be restored at end of exception).
- * Some will also receive an error code -- this is the code that
- * was generated by the processor for the underlying real exception.
- *
- * Note that the page-fault exception is special. It also receives
- * the faulting linear address. Normally this would be found in
- * register CR2, but that is not accessible in a virtualised OS.
- */
-
static void __inline__ do_trap(int trapnr, char *str,
- struct pt_regs * regs, long error_code)
+ struct pt_regs * regs)
{
- printk("FATAL: Unhandled Trap (see mini-os:traps.c)");
- printf("%d %s", trapnr, str);
+ printk("FATAL: Unhandled Trap %d (%s)\n", trapnr, str);
dump_regs(regs);
dump_code(regs->eip);
-
do_exit();
}
#define DO_ERROR(trapnr, str, name) \
-void do_##name(struct pt_regs * regs, long error_code) \
+void do_##name(struct pt_regs * regs) \
{ \
- do_trap(trapnr, str, regs, error_code); \
+ do_trap(trapnr, str, regs); \
}
#define DO_ERROR_INFO(trapnr, str, name, sicode, siaddr) \
-void do_##name(struct pt_regs * regs, long error_code) \
+void do_##name(struct pt_regs * regs) \
{ \
- do_trap(trapnr, str, regs, error_code); \
+ do_trap(trapnr, str, regs); \
}
DO_ERROR_INFO( 0, "divide error", divide_error, FPE_INTDIV, regs->eip)
- DO_ERROR( 3, "int3", int3)
- DO_ERROR( 4, "overflow", overflow)
- DO_ERROR( 5, "bounds", bounds)
- DO_ERROR_INFO( 6, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
- DO_ERROR( 7, "device not available", device_not_available)
- DO_ERROR( 8, "double fault", double_fault)
- DO_ERROR( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
- DO_ERROR(10, "invalid TSS", invalid_TSS)
- DO_ERROR(11, "segment not present", segment_not_present)
- DO_ERROR(12, "stack segment", stack_segment)
- DO_ERROR_INFO(17, "alignment check", alignment_check, BUS_ADRALN, 0)
- DO_ERROR(18, "machine check", machine_check)
-
- void do_page_fault(struct pt_regs *regs, long error_code,
- unsigned long address)
+DO_ERROR( 3, "int3", int3)
+DO_ERROR( 4, "overflow", overflow)
+DO_ERROR( 5, "bounds", bounds)
+DO_ERROR_INFO( 6, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
+DO_ERROR( 7, "device not available", device_not_available)
+DO_ERROR( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
+DO_ERROR(10, "invalid TSS", invalid_TSS)
+DO_ERROR(11, "segment not present", segment_not_present)
+DO_ERROR(12, "stack segment", stack_segment)
+DO_ERROR_INFO(17, "alignment check", alignment_check, BUS_ADRALN, 0)
+DO_ERROR(18, "machine check", machine_check)
+
+extern unsigned long virt_cr2;
+void do_page_fault(struct pt_regs *regs)
{
- printk("Page fault\n");
- printk("Address: 0x%p", address);
- printk("Error Code: 0x%p", error_code);
- printk("eip: \t 0x%p", regs->eip);
+ unsigned long addr = virt_cr2;
+ printk("Page fault at linear address %p\n", addr);
+ dump_regs(regs);
+ dump_code(regs->eip);
+#ifdef __x86_64__
+ {
+ unsigned long *tab = (unsigned long *)start_info.pt_base;
+ unsigned long page;
+
+ printk("Pagetable walk from %p:\n", tab);
+
+ page = tab[l4_table_offset(addr)];
+ tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
+ printk(" L4 = %p (%p)\n", page, tab);
+ if ( !(page & _PAGE_PRESENT) )
+ goto out;
+
+ page = tab[l3_table_offset(addr)];
+ tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
+ printk(" L3 = %p (%p)\n", page, tab);
+ if ( !(page & _PAGE_PRESENT) )
+ goto out;
+
+ page = tab[l2_table_offset(addr)];
+ tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
+ printk(" L2 = %p (%p) %s\n", page, tab,
+ (page & _PAGE_PSE) ? "(2MB)" : "");
+ if ( !(page & _PAGE_PRESENT) || (page & _PAGE_PSE) )
+ goto out;
+
+ page = tab[l1_table_offset(addr)];
+ printk(" L1 = %p\n", page);
+ }
+#endif
+ out:
do_exit();
}
-void do_general_protection(struct pt_regs * regs, long error_code)
+void do_general_protection(struct pt_regs *regs)
{
printk("GPF\n");
- printk("Error Code: 0x%p", error_code);
dump_regs(regs);
dump_code(regs->eip);
do_exit();
}
-void do_debug(struct pt_regs * regs, long error_code)
+void do_debug(struct pt_regs * regs)
{
printk("Debug exception\n");
#define TF_MASK 0x100
@@ -146,9 +168,7 @@ void do_debug(struct pt_regs * regs, long error_code)
do_exit();
}
-
-
-void do_coprocessor_error(struct pt_regs * regs, long error_code)
+void do_coprocessor_error(struct pt_regs * regs)
{
printk("Copro error\n");
dump_regs(regs);
@@ -161,14 +181,12 @@ void simd_math_error(void *eip)
printk("SIMD error\n");
}
-void do_simd_coprocessor_error(struct pt_regs * regs,
- long error_code)
+void do_simd_coprocessor_error(struct pt_regs * regs)
{
printk("SIMD copro error\n");
}
-void do_spurious_interrupt_bug(struct pt_regs * regs,
- long error_code)
+void do_spurious_interrupt_bug(struct pt_regs * regs)
{
}
@@ -189,7 +207,6 @@ static trap_info_t trap_table[] = {
{ 5, 3, __KERNEL_CS, _P (unsigned long)bounds },
{ 6, 0, __KERNEL_CS, _P (unsigned long)invalid_op },
{ 7, 0, __KERNEL_CS, _P (unsigned long)device_not_available },
- { 8, 0, __KERNEL_CS, _P (unsigned long)double_fault },
{ 9, 0, __KERNEL_CS, _P (unsigned long)coprocessor_segment_overrun },
{ 10, 0, __KERNEL_CS, _P (unsigned long)invalid_TSS },
{ 11, 0, __KERNEL_CS, _P (unsigned long)segment_not_present },
diff --git a/extras/mini-os/x86_64.S b/extras/mini-os/x86_64.S
index 4a4708ddd5..0f37d596f7 100644
--- a/extras/mini-os/x86_64.S
+++ b/extras/mini-os/x86_64.S
@@ -6,7 +6,42 @@
#define ENTRY(X) .globl X ; X :
.globl _start, shared_info
-
+
+#define SAVE_ALL \
+ cld; \
+ pushq %rdi; \
+ pushq %rsi; \
+ pushq %rdx; \
+ pushq %rcx; \
+ pushq %rax; \
+ pushq %r8; \
+ pushq %r9; \
+ pushq %r10; \
+ pushq %r11; \
+ pushq %rbx; \
+ pushq %rbp; \
+ pushq %r12; \
+ pushq %r13; \
+ pushq %r14; \
+ pushq %r15;
+
+#define RESTORE_ALL \
+ popq %r15; \
+ popq %r14; \
+ popq %r13; \
+ popq %r12; \
+ popq %rbp; \
+ popq %rbx; \
+ popq %r11; \
+ popq %r10; \
+ popq %r9; \
+ popq %r8; \
+ popq %rax; \
+ popq %rcx; \
+ popq %rdx; \
+ popq %rsi; \
+ popq %rdi
+
_start:
cld
movq stack_start(%rip),%rsp
@@ -23,56 +58,165 @@ shared_info:
.org 0x2000
ENTRY(hypervisor_callback)
+ popq %rcx
+ popq %r11
+ iretq
ENTRY(failsafe_callback)
- iret
-
+ popq %rcx
+ popq %r11
+ iretq
+
+error_code:
+ SAVE_ALL
+ movq %rsp,%rdi
+ movl 15*8+4(%rsp),%eax
+ leaq exception_table(%rip),%rdx
+ callq *(%rdx,%rax,8)
+ RESTORE_ALL
+ addq $8,%rsp
+ iretq
+
ENTRY(divide_error)
+ popq %rcx
+ popq %r11
pushq $0
-
+ movl $TRAP_divide_error,4(%rsp)
+ jmp error_code
+
ENTRY(coprocessor_error)
+ popq %rcx
+ popq %r11
pushq $0
+ movl $TRAP_copro_error,4(%rsp)
+ jmp error_code
ENTRY(simd_coprocessor_error)
+ popq %rcx
+ popq %r11
pushq $0
+ movl $TRAP_simd_error,4(%rsp)
+ jmp error_code
ENTRY(device_not_available)
- iret
+ popq %rcx
+ popq %r11
+ movl $TRAP_no_device,4(%rsp)
+ jmp error_code
ENTRY(debug)
+ popq %rcx
+ popq %r11
pushq $0
+ movl $TRAP_debug,4(%rsp)
+ jmp error_code
ENTRY(int3)
+ popq %rcx
+ popq %r11
pushq $0
+ movl $TRAP_int3,4(%rsp)
+ jmp error_code
ENTRY(overflow)
+ popq %rcx
+ popq %r11
pushq $0
+ movl $TRAP_overflow,4(%rsp)
+ jmp error_code
ENTRY(bounds)
+ popq %rcx
+ popq %r11
pushq $0
+ movl $TRAP_bounds,4(%rsp)
+ jmp error_code
ENTRY(invalid_op)
+ popq %rcx
+ popq %r11
pushq $0
+ movl $TRAP_invalid_op,4(%rsp)
+ jmp error_code
ENTRY(coprocessor_segment_overrun)
+ popq %rcx
+ popq %r11
pushq $0
-
-ENTRY(double_fault)
+ movl $TRAP_copro_seg,4(%rsp)
+ jmp error_code
ENTRY(invalid_TSS)
+ popq %rcx
+ popq %r11
+ movl $TRAP_invalid_tss,4(%rsp)
+ jmp error_code
ENTRY(segment_not_present)
+ popq %rcx
+ popq %r11
+ movl $TRAP_no_segment,4(%rsp)
+ jmp error_code
ENTRY(stack_segment)
+ popq %rcx
+ popq %r11
+ movl $TRAP_stack_error,4(%rsp)
+ jmp error_code
ENTRY(general_protection)
+ popq %rcx
+ popq %r11
+ movl $TRAP_gp_fault,4(%rsp)
+ jmp error_code
ENTRY(alignment_check)
+ popq %rcx
+ popq %r11
+ movl $TRAP_alignment_check,4(%rsp)
+ jmp error_code
+ENTRY(virt_cr2)
+ .quad 0
ENTRY(page_fault)
-
+ popq %rcx
+ popq %r11
+ popq virt_cr2(%rip)
+ movl $TRAP_page_fault,4(%rsp)
+ jmp error_code
+
ENTRY(machine_check)
+ popq %rcx
+ popq %r11
pushq $0
+ movl $TRAP_machine_check,4(%rsp)
+ jmp error_code
ENTRY(spurious_interrupt_bug)
+ popq %rcx
+ popq %r11
pushq $0
+ movl $TRAP_spurious_int,4(%rsp)
+ jmp error_code
+
+ENTRY(exception_table)
+ .quad do_divide_error
+ .quad do_debug
+ .quad 0 # nmi
+ .quad do_int3
+ .quad do_overflow
+ .quad do_bounds
+ .quad do_invalid_op
+ .quad 0
+ .quad 0
+ .quad do_coprocessor_segment_overrun
+ .quad do_invalid_TSS
+ .quad do_segment_not_present
+ .quad do_stack_segment
+ .quad do_general_protection
+ .quad do_page_fault
+ .quad do_spurious_interrupt_bug
+ .quad do_coprocessor_error
+ .quad do_alignment_check
+ .quad do_machine_check
+ .quad do_simd_coprocessor_error