diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2005-02-11 18:04:56 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2005-02-11 18:04:56 +0000 |
commit | 054206d161ad06d19298132f1c3a54d2a1598270 (patch) | |
tree | 8e4829d2ba79a078e5175c2efc717e5fbcafcfb1 /extras | |
parent | 28268ccd6d678a5bff48c00acc014f6c9df639cc (diff) | |
download | xen-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.h | 17 | ||||
-rw-r--r-- | extras/mini-os/h/mm.h | 60 | ||||
-rw-r--r-- | extras/mini-os/h/os.h | 22 | ||||
-rw-r--r-- | extras/mini-os/h/types.h | 11 | ||||
-rw-r--r-- | extras/mini-os/kernel.c | 2 | ||||
-rw-r--r-- | extras/mini-os/lib/printf.c | 4 | ||||
-rw-r--r-- | extras/mini-os/mm.c | 2 | ||||
-rw-r--r-- | extras/mini-os/traps.c | 139 | ||||
-rw-r--r-- | extras/mini-os/x86_64.S | 160 |
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) (®s->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 |