debuggers.hg

annotate xen/arch/x86/traps.c @ 3635:ed902e5c4b49

bitkeeper revision 1.1159.212.62 (41fff40aESe4aWS82z_rLHeonXpxuQ)

More x86/64 stuff.
Signed-off-by: keir.fraser@cl.cam.ac.uk
author kaf24@scramble.cl.cam.ac.uk
date Tue Feb 01 21:26:34 2005 +0000 (2005-02-01)
parents 578b6c14e635
children 9a9c5a491401 e6af5d8f8b39 fd1dd0663b09
rev   line source
kaf24@1490 1 /******************************************************************************
kaf24@3635 2 * arch/x86/traps.c
kaf24@1490 3 *
kaf24@2114 4 * Modifications to Linux original are copyright (c) 2002-2004, K A Fraser
kaf24@1490 5 *
kaf24@1490 6 * This program is free software; you can redistribute it and/or modify
kaf24@1490 7 * it under the terms of the GNU General Public License as published by
kaf24@1490 8 * the Free Software Foundation; either version 2 of the License, or
kaf24@1490 9 * (at your option) any later version.
kaf24@1490 10 *
kaf24@1490 11 * This program is distributed in the hope that it will be useful,
kaf24@1490 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
kaf24@1490 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kaf24@1490 14 * GNU General Public License for more details.
kaf24@1490 15 *
kaf24@1490 16 * You should have received a copy of the GNU General Public License
kaf24@1490 17 * along with this program; if not, write to the Free Software
kaf24@1490 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
kaf24@1490 19 */
kaf24@1490 20
kaf24@1490 21 /*
kaf24@1490 22 * Copyright (C) 1991, 1992 Linus Torvalds
kaf24@1490 23 *
kaf24@1490 24 * Pentium III FXSR, SSE support
kaf24@1490 25 * Gareth Hughes <gareth@valinux.com>, May 2000
kaf24@1490 26 */
kaf24@1490 27
kaf24@1490 28 #include <xen/config.h>
kaf24@1490 29 #include <xen/init.h>
kaf24@1490 30 #include <xen/sched.h>
kaf24@1490 31 #include <xen/lib.h>
kaf24@1490 32 #include <xen/errno.h>
kaf24@1490 33 #include <xen/mm.h>
kaf24@2079 34 #include <xen/console.h>
ach61@2843 35 #include <asm/regs.h>
kaf24@1490 36 #include <xen/delay.h>
kaf24@2085 37 #include <xen/event.h>
kaf24@1490 38 #include <xen/spinlock.h>
kaf24@1490 39 #include <xen/irq.h>
kaf24@1490 40 #include <xen/perfc.h>
kaf24@2085 41 #include <xen/softirq.h>
kaf24@1787 42 #include <asm/shadow.h>
kaf24@1490 43 #include <asm/domain_page.h>
kaf24@1490 44 #include <asm/system.h>
kaf24@1490 45 #include <asm/io.h>
kaf24@1490 46 #include <asm/atomic.h>
kaf24@1490 47 #include <asm/desc.h>
kaf24@1490 48 #include <asm/debugreg.h>
kaf24@1490 49 #include <asm/smp.h>
kaf24@1490 50 #include <asm/flushtlb.h>
kaf24@1490 51 #include <asm/uaccess.h>
kaf24@1490 52 #include <asm/i387.h>
kaf24@3009 53 #include <asm/debugger.h>
kaf24@3375 54 #include <asm/msr.h>
kaf24@1490 55
kaf24@3372 56 /*
kaf24@3372 57 * opt_nmi: one of 'ignore', 'dom0', or 'fatal'.
kaf24@3372 58 * fatal: Xen prints diagnostic message and then hangs.
kaf24@3372 59 * dom0: The NMI is virtualised to DOM0.
kaf24@3372 60 * ignore: The NMI error is cleared and ignored.
kaf24@3372 61 */
kaf24@3372 62 #ifdef NDEBUG
kaf24@3372 63 char opt_nmi[10] = "dom0";
kaf24@3372 64 #else
kaf24@3372 65 char opt_nmi[10] = "fatal";
kaf24@3372 66 #endif
kaf24@3372 67 string_param("nmi", opt_nmi);
kaf24@3372 68
kaf24@3207 69 #define GUEST_FAULT(_r) (likely(VM86_MODE(_r) || !RING_0(_r)))
kaf24@3207 70
kaf24@1490 71 #define DOUBLEFAULT_STACK_SIZE 1024
kaf24@1490 72 static struct tss_struct doublefault_tss;
kaf24@1490 73 static unsigned char doublefault_stack[DOUBLEFAULT_STACK_SIZE];
kaf24@1490 74
kaf24@1594 75 asmlinkage int hypercall(void);
kaf24@1490 76
kaf24@1490 77 /* Master table, and the one used by CPU0. */
kaf24@3635 78 idt_entry_t idt_table[IDT_ENTRIES] = { {0, 0}, };
kaf24@1490 79 /* All other CPUs have their own copy. */
kaf24@3635 80 idt_entry_t *idt_tables[NR_CPUS] = { 0 };
kaf24@1490 81
kaf24@1490 82 asmlinkage void divide_error(void);
kaf24@1490 83 asmlinkage void debug(void);
kaf24@1490 84 asmlinkage void nmi(void);
kaf24@1490 85 asmlinkage void int3(void);
kaf24@1490 86 asmlinkage void overflow(void);
kaf24@1490 87 asmlinkage void bounds(void);
kaf24@1490 88 asmlinkage void invalid_op(void);
kaf24@1490 89 asmlinkage void device_not_available(void);
kaf24@1490 90 asmlinkage void coprocessor_segment_overrun(void);
kaf24@1490 91 asmlinkage void invalid_TSS(void);
kaf24@1490 92 asmlinkage void segment_not_present(void);
kaf24@1490 93 asmlinkage void stack_segment(void);
kaf24@1490 94 asmlinkage void general_protection(void);
kaf24@1490 95 asmlinkage void page_fault(void);
kaf24@1490 96 asmlinkage void coprocessor_error(void);
kaf24@1490 97 asmlinkage void simd_coprocessor_error(void);
kaf24@1490 98 asmlinkage void alignment_check(void);
kaf24@1490 99 asmlinkage void spurious_interrupt_bug(void);
kaf24@1490 100 asmlinkage void machine_check(void);
kaf24@1490 101
kaf24@1490 102 int kstack_depth_to_print = 8*20;
kaf24@1490 103
kaf24@1490 104 static inline int kernel_text_address(unsigned long addr)
kaf24@1490 105 {
kaf24@1490 106 if (addr >= (unsigned long) &_stext &&
kaf24@1490 107 addr <= (unsigned long) &_etext)
kaf24@1490 108 return 1;
kaf24@1490 109 return 0;
kaf24@1490 110
kaf24@1490 111 }
kaf24@1490 112
kaf24@3635 113 void show_guest_stack(void)
iap10@2479 114 {
iap10@2479 115 int i;
iap10@2479 116 execution_context_t *ec = get_execution_context();
iap10@2479 117 unsigned long *stack = (unsigned long *)ec->esp;
iap10@2479 118 printk("Guest EIP is %lx\n",ec->eip);
iap10@2479 119
iap10@2479 120 for ( i = 0; i < kstack_depth_to_print; i++ )
iap10@2479 121 {
iap10@2479 122 if ( ((long)stack & (STACK_SIZE-1)) == 0 )
iap10@2479 123 break;
iap10@2479 124 if ( i && ((i % 8) == 0) )
iap10@2479 125 printk("\n ");
iap10@2479 126 printk("%08lx ", *stack++);
iap10@2479 127 }
iap10@2479 128 printk("\n");
iap10@2479 129
iap10@2479 130 }
iap10@2479 131
iap10@2509 132 void show_trace(unsigned long *esp)
iap10@2509 133 {
iap10@2509 134 unsigned long *stack, addr;
iap10@2509 135 int i;
iap10@2509 136
iap10@2509 137 printk("Call Trace from ESP=%p: ", esp);
iap10@2509 138 stack = esp;
iap10@2509 139 i = 0;
iap10@2509 140 while (((long) stack & (STACK_SIZE-1)) != 0) {
iap10@2509 141 addr = *stack++;
iap10@2509 142 if (kernel_text_address(addr)) {
iap10@2509 143 if (i && ((i % 6) == 0))
iap10@2509 144 printk("\n ");
iap10@2509 145 printk("[<%08lx>] ", addr);
iap10@2509 146 i++;
iap10@2509 147 }
iap10@2509 148 }
iap10@2509 149 printk("\n");
iap10@2509 150 }
iap10@2509 151
kaf24@1490 152 void show_stack(unsigned long *esp)
kaf24@1490 153 {
iap10@2509 154 unsigned long *stack;
kaf24@1490 155 int i;
kaf24@1490 156
kaf24@1490 157 printk("Stack trace from ESP=%p:\n", esp);
kaf24@1490 158
kaf24@1490 159 stack = esp;
kaf24@1490 160 for ( i = 0; i < kstack_depth_to_print; i++ )
kaf24@1490 161 {
kaf24@1490 162 if ( ((long)stack & (STACK_SIZE-1)) == 0 )
kaf24@1490 163 break;
kaf24@1490 164 if ( i && ((i % 8) == 0) )
kaf24@1490 165 printk("\n ");
kaf24@1490 166 if ( kernel_text_address(*stack) )
kaf24@1490 167 printk("[%08lx] ", *stack++);
kaf24@1490 168 else
kaf24@1490 169 printk("%08lx ", *stack++);
kaf24@1490 170 }
kaf24@1490 171 printk("\n");
kaf24@1490 172
iap10@2509 173 show_trace( esp );
kaf24@1490 174 }
kaf24@1490 175
ach61@2843 176 void show_registers(struct xen_regs *regs)
kaf24@1490 177 {
kaf24@1490 178 unsigned long esp;
kaf24@2954 179 unsigned short ss, ds, es, fs, gs;
kaf24@1490 180
kaf24@3207 181 if ( GUEST_FAULT(regs) )
kaf24@1490 182 {
kaf24@1490 183 esp = regs->esp;
kaf24@2956 184 ss = regs->ss & 0xffff;
kaf24@2956 185 ds = regs->ds & 0xffff;
kaf24@2956 186 es = regs->es & 0xffff;
kaf24@2956 187 fs = regs->fs & 0xffff;
kaf24@2956 188 gs = regs->gs & 0xffff;
kaf24@2954 189 }
kaf24@2954 190 else
kaf24@2954 191 {
kaf24@2954 192 esp = (unsigned long)(&regs->esp);
kaf24@2954 193 ss = __HYPERVISOR_DS;
kaf24@2954 194 ds = __HYPERVISOR_DS;
kaf24@2954 195 es = __HYPERVISOR_DS;
kaf24@2954 196 fs = __HYPERVISOR_DS;
kaf24@2954 197 gs = __HYPERVISOR_DS;
kaf24@1490 198 }
kaf24@1490 199
kaf24@3635 200 printk("CPU: %d\nEIP: %04lx:[<%08lx>] \nEFLAGS: %08lx\n",
kaf24@2956 201 smp_processor_id(), 0xffff & regs->cs, regs->eip, regs->eflags);
kaf24@3635 202 printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
kaf24@1490 203 regs->eax, regs->ebx, regs->ecx, regs->edx);
kaf24@3635 204 printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
kaf24@1490 205 regs->esi, regs->edi, regs->ebp, esp);
kaf24@1490 206 printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n",
kaf24@2954 207 ds, es, fs, gs, ss);
kaf24@1490 208
kaf24@3127 209 show_stack((unsigned long *)&regs->esp);
kaf24@1490 210 }
kaf24@1490 211
kaf24@3079 212 /*
kaf24@3079 213 * This is called for faults at very unexpected times (e.g., when interrupts
kaf24@3079 214 * are disabled). In such situations we can't do much that is safe. We try to
kaf24@3079 215 * print out some tracing and then we just spin.
kaf24@3079 216 */
kaf24@3127 217 asmlinkage void fatal_trap(int trapnr, struct xen_regs *regs)
kaf24@1490 218 {
kaf24@3079 219 int cpu = smp_processor_id();
kaf24@3127 220 unsigned long cr2;
kaf24@3079 221 static char *trapstr[] = {
kaf24@3079 222 "divide error", "debug", "nmi", "bkpt", "overflow", "bounds",
kaf24@3079 223 "invalid operation", "device not available", "double fault",
kaf24@3079 224 "coprocessor segment", "invalid tss", "segment not found",
kaf24@3079 225 "stack error", "general protection fault", "page fault",
kaf24@3079 226 "spurious interrupt", "coprocessor error", "alignment check",
kaf24@3079 227 "machine check", "simd error"
kaf24@3079 228 };
kaf24@3079 229
kaf24@1490 230 show_registers(regs);
kaf24@3127 231
kaf24@3127 232 if ( trapnr == TRAP_page_fault )
kaf24@3127 233 {
kaf24@3127 234 __asm__ __volatile__ ("movl %%cr2,%0" : "=r" (cr2) : );
kaf24@3127 235 printk("Faulting linear address might be %08lx\n", cr2);
kaf24@3127 236 }
kaf24@3127 237
kaf24@3079 238 printk("************************************\n");
kaf24@3127 239 printk("CPU%d FATAL TRAP %d (%s), ERROR_CODE %04x%s.\n",
kaf24@3127 240 cpu, trapnr, trapstr[trapnr], regs->error_code,
kaf24@3079 241 (regs->eflags & X86_EFLAGS_IF) ? "" : ", IN INTERRUPT CONTEXT");
kaf24@3079 242 printk("System shutting down -- need manual reset.\n");
kaf24@3079 243 printk("************************************\n");
kaf24@3079 244
kaf24@3079 245 /* Lock up the console to prevent spurious output from other CPUs. */
kaf24@3079 246 console_force_lock();
kaf24@3079 247
kaf24@3079 248 /* Wait for manual reset. */
kaf24@3079 249 for ( ; ; )
kaf24@3079 250 __asm__ __volatile__ ( "hlt" );
kaf24@1490 251 }
kaf24@1490 252
kaf24@3090 253 static inline int do_trap(int trapnr, char *str,
kaf24@3127 254 struct xen_regs *regs,
kaf24@3127 255 int use_error_code)
kaf24@1490 256 {
cl349@2957 257 struct exec_domain *ed = current;
cl349@3085 258 struct trap_bounce *tb = &ed->thread.trap_bounce;
kaf24@1490 259 trap_info_t *ti;
kaf24@1490 260 unsigned long fixup;
kaf24@1490 261
kaf24@3127 262 DEBUGGER_trap_entry(trapnr, regs);
kaf24@3009 263
kaf24@3207 264 if ( !GUEST_FAULT(regs) )
kaf24@1628 265 goto xen_fault;
kaf24@1490 266
kaf24@1490 267 ti = current->thread.traps + trapnr;
kaf24@3127 268 tb->flags = TBF_EXCEPTION;
kaf24@3127 269 tb->cs = ti->cs;
kaf24@3127 270 tb->eip = ti->address;
kaf24@3127 271 if ( use_error_code )
kaf24@3127 272 {
kaf24@3127 273 tb->flags |= TBF_EXCEPTION_ERRCODE;
kaf24@3127 274 tb->error_code = regs->error_code;
kaf24@3127 275 }
kaf24@1490 276 if ( TI_GET_IF(ti) )
cl349@2959 277 ed->vcpu_info->evtchn_upcall_mask = 1;
kaf24@3090 278 return 0;
kaf24@1490 279
kaf24@1628 280 xen_fault:
kaf24@1490 281
kaf24@1490 282 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
kaf24@1490 283 {
kaf24@3635 284 DPRINTK("Trap %d: %08lx -> %08lx\n", trapnr, regs->eip, fixup);
kaf24@1490 285 regs->eip = fixup;
kaf24@3090 286 return 0;
kaf24@1490 287 }
kaf24@1490 288
kaf24@3127 289 DEBUGGER_trap_fatal(trapnr, regs);
cl349@2995 290
kaf24@1490 291 show_registers(regs);
kaf24@1490 292 panic("CPU%d FATAL TRAP: vector = %d (%s)\n"
kaf24@3127 293 "[error_code=%04x]\n",
kaf24@3127 294 smp_processor_id(), trapnr, str, regs->error_code);
kaf24@3090 295 return 0;
kaf24@1490 296 }
kaf24@1490 297
kaf24@1490 298 #define DO_ERROR_NOCODE(trapnr, str, name) \
kaf24@3127 299 asmlinkage int do_##name(struct xen_regs *regs) \
kaf24@1490 300 { \
kaf24@3127 301 return do_trap(trapnr, str, regs, 0); \
kaf24@1490 302 }
kaf24@1490 303
kaf24@1490 304 #define DO_ERROR(trapnr, str, name) \
kaf24@3127 305 asmlinkage int do_##name(struct xen_regs *regs) \
kaf24@1490 306 { \
kaf24@3127 307 return do_trap(trapnr, str, regs, 1); \
kaf24@1490 308 }
kaf24@1490 309
kaf24@1490 310 DO_ERROR_NOCODE( 0, "divide error", divide_error)
kaf24@2114 311 DO_ERROR_NOCODE( 4, "overflow", overflow)
kaf24@2114 312 DO_ERROR_NOCODE( 5, "bounds", bounds)
kaf24@2114 313 DO_ERROR_NOCODE( 6, "invalid operand", invalid_op)
kaf24@2114 314 DO_ERROR_NOCODE( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
kaf24@2114 315 DO_ERROR(10, "invalid TSS", invalid_TSS)
kaf24@2114 316 DO_ERROR(11, "segment not present", segment_not_present)
kaf24@2114 317 DO_ERROR(12, "stack segment", stack_segment)
kaf24@2114 318 DO_ERROR_NOCODE(16, "fpu error", coprocessor_error)
kaf24@2114 319 DO_ERROR(17, "alignment check", alignment_check)
kaf24@2114 320 DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
kaf24@1490 321
kaf24@3127 322 asmlinkage int do_int3(struct xen_regs *regs)
kaf24@1490 323 {
cl349@2957 324 struct exec_domain *ed = current;
cl349@3085 325 struct trap_bounce *tb = &ed->thread.trap_bounce;
kaf24@1490 326 trap_info_t *ti;
kaf24@1490 327
kaf24@3127 328 DEBUGGER_trap_entry(TRAP_int3, regs);
kaf24@1490 329
kaf24@3207 330 if ( !GUEST_FAULT(regs) )
kaf24@1490 331 {
kaf24@3127 332 DEBUGGER_trap_fatal(TRAP_int3, regs);
kaf24@3009 333 show_registers(regs);
kaf24@3127 334 panic("CPU%d FATAL TRAP: vector = 3 (Int3)\n", smp_processor_id());
kaf24@1490 335 }
kaf24@1490 336
kaf24@1490 337 ti = current->thread.traps + 3;
kaf24@3127 338 tb->flags = TBF_EXCEPTION;
kaf24@3127 339 tb->cs = ti->cs;
kaf24@3127 340 tb->eip = ti->address;
kaf24@1490 341 if ( TI_GET_IF(ti) )
cl349@2959 342 ed->vcpu_info->evtchn_upcall_mask = 1;
kaf24@3090 343
kaf24@3090 344 return 0;
kaf24@1490 345 }
kaf24@1490 346
kaf24@1490 347 asmlinkage void do_double_fault(void)
kaf24@1490 348 {
kaf24@1490 349 struct tss_struct *tss = &doublefault_tss;
kaf24@1490 350 unsigned int cpu = ((tss->back_link>>3)-__FIRST_TSS_ENTRY)>>1;
kaf24@1490 351
kaf24@1490 352 /* Disable the NMI watchdog. It's useless now. */
kaf24@1490 353 watchdog_on = 0;
kaf24@1490 354
kaf24@1490 355 /* Find information saved during fault and dump it to the console. */
kaf24@1490 356 tss = &init_tss[cpu];
kaf24@1518 357 printk("CPU: %d\nEIP: %04x:[<%08x>] \nEFLAGS: %08x\n",
kaf24@1490 358 cpu, tss->cs, tss->eip, tss->eflags);
kaf24@1518 359 printk("CR3: %08x\n", tss->__cr3);
kaf24@1518 360 printk("eax: %08x ebx: %08x ecx: %08x edx: %08x\n",
kaf24@1490 361 tss->eax, tss->ebx, tss->ecx, tss->edx);
kaf24@1518 362 printk("esi: %08x edi: %08x ebp: %08x esp: %08x\n",
kaf24@1490 363 tss->esi, tss->edi, tss->ebp, tss->esp);
kaf24@1490 364 printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n",
kaf24@1490 365 tss->ds, tss->es, tss->fs, tss->gs, tss->ss);
kaf24@1490 366 printk("************************************\n");
kaf24@1490 367 printk("CPU%d DOUBLE FAULT -- system shutdown\n", cpu);
kaf24@1490 368 printk("System needs manual reset.\n");
kaf24@1490 369 printk("************************************\n");
kaf24@1490 370
kaf24@1490 371 /* Lock up the console to prevent spurious output from other CPUs. */
kaf24@2079 372 console_force_lock();
kaf24@1490 373
kaf24@1490 374 /* Wait for manual reset. */
kaf24@3079 375 for ( ; ; )
kaf24@3079 376 __asm__ __volatile__ ( "hlt" );
kaf24@3079 377 }
kaf24@3079 378
kaf24@3127 379 asmlinkage void do_machine_check(struct xen_regs *regs)
kaf24@3079 380 {
kaf24@3127 381 fatal_trap(TRAP_machine_check, regs);
kaf24@1490 382 }
kaf24@1490 383
kaf24@3462 384 void propagate_page_fault(unsigned long addr, u16 error_code)
kaf24@3462 385 {
kaf24@3462 386 trap_info_t *ti;
kaf24@3443 387 struct exec_domain *ed = current;
kaf24@3443 388 struct trap_bounce *tb = &ed->thread.trap_bounce;
kaf24@3462 389
kaf24@3443 390 ti = ed->thread.traps + 14;
kaf24@3462 391 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE | TBF_EXCEPTION_CR2;
kaf24@3462 392 tb->cr2 = addr;
kaf24@3462 393 tb->error_code = error_code;
kaf24@3462 394 tb->cs = ti->cs;
kaf24@3462 395 tb->eip = ti->address;
kaf24@3462 396 if ( TI_GET_IF(ti) )
kaf24@3443 397 ed->vcpu_info->evtchn_upcall_mask = 1;
kaf24@3443 398
kaf24@3443 399 ed->mm.guest_cr2 = addr;
kaf24@3462 400 }
kaf24@3462 401
kaf24@3127 402 asmlinkage int do_page_fault(struct xen_regs *regs)
kaf24@1490 403 {
kaf24@1490 404 unsigned long off, addr, fixup;
cl349@2957 405 struct exec_domain *ed = current;
cl349@2957 406 struct domain *d = ed->domain;
kaf24@1490 407 extern int map_ldt_shadow_page(unsigned int);
cl349@2957 408 int cpu = ed->processor;
cl349@3036 409 int ret;
kaf24@1490 410
kaf24@1490 411 __asm__ __volatile__ ("movl %%cr2,%0" : "=r" (addr) : );
kaf24@1490 412
kaf24@3127 413 DEBUGGER_trap_entry(TRAP_page_fault, regs);
kaf24@3009 414
kaf24@1490 415 perfc_incrc(page_faults);
kaf24@1490 416
iap10@2458 417 if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
kaf24@2111 418 {
cl349@3186 419 LOCK_BIGLOCK(d);
kaf24@2663 420 if ( unlikely(ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va) &&
kaf24@2663 421 unlikely((addr >> L2_PAGETABLE_SHIFT) ==
kaf24@2663 422 ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l2_idx) )
kaf24@2375 423 {
cl349@2512 424 ptwr_flush(PTWR_PT_ACTIVE);
cl349@3036 425 UNLOCK_BIGLOCK(d);
kaf24@3090 426 return EXCRET_fault_fixed;
kaf24@2375 427 }
cl349@1860 428
kaf24@2375 429 if ( (addr < PAGE_OFFSET) &&
kaf24@3127 430 ((regs->error_code & 3) == 3) && /* write-protection fault */
kaf24@2375 431 ptwr_do_page_fault(addr) )
kaf24@3090 432 {
cl349@3112 433 if ( unlikely(ed->mm.shadow_mode) )
kaf24@3127 434 (void)shadow_fault(addr, regs->error_code);
cl349@3186 435 UNLOCK_BIGLOCK(d);
kaf24@3090 436 return EXCRET_fault_fixed;
kaf24@3090 437 }
cl349@3186 438 UNLOCK_BIGLOCK(d);
kaf24@2375 439 }
cl349@1860 440
cl349@2957 441 if ( unlikely(ed->mm.shadow_mode) &&
kaf24@3127 442 (addr < PAGE_OFFSET) && shadow_fault(addr, regs->error_code) )
kaf24@3090 443 return EXCRET_fault_fixed;
kaf24@1490 444
cl349@3036 445 if ( unlikely(addr >= LDT_VIRT_START(ed)) &&
cl349@3036 446 (addr < (LDT_VIRT_START(ed) + (ed->mm.ldt_ents*LDT_ENTRY_SIZE))) )
iap10@2611 447 {
iap10@2611 448 /*
iap10@2611 449 * Copy a mapping from the guest's LDT, if it is valid. Otherwise we
iap10@2611 450 * send the fault up to the guest OS to be handled.
iap10@2611 451 */
cl349@3036 452 LOCK_BIGLOCK(d);
cl349@3036 453 off = addr - LDT_VIRT_START(ed);
cl349@2957 454 addr = ed->mm.ldt_base + off;
cl349@3036 455 ret = map_ldt_shadow_page(off >> PAGE_SHIFT);
cl349@3036 456 UNLOCK_BIGLOCK(d);
cl349@3036 457 if ( likely(ret) )
kaf24@3090 458 return EXCRET_fault_fixed; /* successfully copied the mapping */
iap10@2611 459 }
iap10@2611 460
kaf24@3207 461 if ( !GUEST_FAULT(regs) )
kaf24@1628 462 goto xen_fault;
kaf24@1490 463
kaf24@3462 464 propagate_page_fault(addr, regs->error_code);
kaf24@3090 465 return 0;
kaf24@1490 466
kaf24@1628 467 xen_fault:
kaf24@1490 468
kaf24@1490 469 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
kaf24@1490 470 {
kaf24@1490 471 perfc_incrc(copy_user_faults);
cl349@2957 472 if ( !ed->mm.shadow_mode )
kaf24@3635 473 DPRINTK("Page fault: %08lx -> %08lx\n", regs->eip, fixup);
kaf24@1490 474 regs->eip = fixup;
kaf24@3090 475 return 0;
kaf24@1490 476 }
kaf24@1490 477
kaf24@3127 478 DEBUGGER_trap_fatal(TRAP_page_fault, regs);
cl349@2995 479
kaf24@1490 480 if ( addr >= PAGE_OFFSET )
kaf24@1490 481 {
kaf24@1490 482 unsigned long page;
kaf24@1490 483 page = l2_pgentry_val(idle_pg_table[addr >> L2_PAGETABLE_SHIFT]);
kaf24@1490 484 printk("*pde = %08lx\n", page);
kaf24@1490 485 if ( page & _PAGE_PRESENT )
kaf24@1490 486 {
kaf24@1490 487 page &= PAGE_MASK;
kaf24@1490 488 page = ((unsigned long *) __va(page))[(addr&0x3ff000)>>PAGE_SHIFT];
kaf24@1490 489 printk(" *pte = %08lx\n", page);
kaf24@1490 490 }
kaf24@1490 491 #ifdef MEMORY_GUARD
kaf24@3127 492 if ( !(regs->error_code & 1) )
kaf24@1490 493 printk(" -- POSSIBLY AN ACCESS TO FREED MEMORY? --\n");
kaf24@1490 494 #endif
kaf24@1490 495 }
kaf24@1490 496
kaf24@1490 497 show_registers(regs);
kaf24@1490 498 panic("CPU%d FATAL PAGE FAULT\n"
kaf24@3127 499 "[error_code=%04x]\n"
kaf24@1490 500 "Faulting linear address might be %08lx\n",
kaf24@3127 501 smp_processor_id(), regs->error_code, addr);
kaf24@3090 502 return 0;
kaf24@1490 503 }
kaf24@1490 504
kaf24@3349 505 static int emulate_privileged_op(struct xen_regs *regs)
kaf24@3349 506 {
kaf24@3443 507 extern long do_fpu_taskswitch(void);
kaf24@3443 508 extern void *decode_reg(struct xen_regs *regs, u8 b);
kaf24@3349 509
kaf24@3443 510 struct exec_domain *ed = current;
kaf24@3443 511 unsigned long *reg, eip = regs->eip;
kaf24@3443 512 u8 opcode;
kaf24@3443 513
kaf24@3443 514 if ( get_user(opcode, (u8 *)eip) )
kaf24@3443 515 goto page_fault;
kaf24@3443 516 eip += 1;
kaf24@3443 517 if ( (opcode & 0xff) != 0x0f )
kaf24@3443 518 goto fail;
kaf24@3349 519
kaf24@3443 520 if ( get_user(opcode, (u8 *)eip) )
kaf24@3443 521 goto page_fault;
kaf24@3443 522 eip += 1;
kaf24@3443 523
kaf24@3443 524 switch ( opcode )
kaf24@3349 525 {
kaf24@3443 526 case 0x06: /* CLTS */
kaf24@3443 527 (void)do_fpu_taskswitch();
kaf24@3443 528 break;
kaf24@3443 529
kaf24@3349 530 case 0x09: /* WBINVD */
kaf24@3443 531 if ( !IS_CAPABLE_PHYSDEV(ed->domain) )
kaf24@3349 532 {
kaf24@3349 533 DPRINTK("Non-physdev domain attempted WBINVD.\n");
kaf24@3443 534 goto fail;
kaf24@3349 535 }
kaf24@3349 536 wbinvd();
kaf24@3443 537 break;
kaf24@3443 538
kaf24@3443 539 case 0x20: /* MOV CR?,<reg> */
kaf24@3443 540 if ( get_user(opcode, (u8 *)eip) )
kaf24@3443 541 goto page_fault;
kaf24@3443 542 eip += 1;
kaf24@3443 543 if ( (opcode & 0xc0) != 0xc0 )
kaf24@3443 544 goto fail;
kaf24@3443 545 reg = decode_reg(regs, opcode);
kaf24@3443 546 switch ( (opcode >> 3) & 7 )
kaf24@3443 547 {
kaf24@3443 548 case 0: /* Read CR0 */
kaf24@3443 549 *reg =
kaf24@3443 550 (read_cr0() & ~X86_CR0_TS) |
kaf24@3443 551 (test_bit(EDF_GUEST_STTS, &ed->ed_flags) ? X86_CR0_TS : 0);
kaf24@3443 552 break;
kaf24@3443 553
kaf24@3443 554 case 2: /* Read CR2 */
kaf24@3443 555 *reg = ed->mm.guest_cr2;
kaf24@3443 556 break;
kaf24@3443 557
kaf24@3443 558 case 3: /* Read CR3 */
kaf24@3443 559 *reg = pagetable_val(ed->mm.pagetable);
kaf24@3443 560 break;
kaf24@3443 561
kaf24@3443 562 default:
kaf24@3443 563 goto fail;
kaf24@3443 564 }
kaf24@3443 565 break;
kaf24@3443 566
kaf24@3443 567 case 0x22: /* MOV <reg>,CR? */
kaf24@3443 568 if ( get_user(opcode, (u8 *)eip) )
kaf24@3443 569 goto page_fault;
kaf24@3443 570 eip += 1;
kaf24@3443 571 if ( (opcode & 0xc0) != 0xc0 )
kaf24@3443 572 goto fail;
kaf24@3443 573 reg = decode_reg(regs, opcode);
kaf24@3443 574 switch ( (opcode >> 3) & 7 )
kaf24@3443 575 {
kaf24@3443 576 case 0: /* Write CR0 */
kaf24@3443 577 if ( *reg & X86_CR0_TS ) /* XXX ignore all but TS bit */
kaf24@3443 578 (void)do_fpu_taskswitch;
kaf24@3443 579 break;
kaf24@3443 580
kaf24@3443 581 case 2: /* Write CR2 */
kaf24@3443 582 ed->mm.guest_cr2 = *reg;
kaf24@3443 583 break;
kaf24@3443 584
kaf24@3443 585 case 3: /* Write CR3 */
kaf24@3443 586 LOCK_BIGLOCK(ed->domain);
kaf24@3443 587 (void)new_guest_cr3(*reg);
kaf24@3443 588 UNLOCK_BIGLOCK(ed->domain);
kaf24@3443 589 break;
kaf24@3443 590
kaf24@3443 591 default:
kaf24@3443 592 goto fail;
kaf24@3443 593 }
kaf24@3443 594 break;
kaf24@3443 595
kaf24@3349 596 case 0x30: /* WRMSR */
kaf24@3443 597 if ( !IS_PRIV(ed->domain) )
kaf24@3349 598 {
kaf24@3349 599 DPRINTK("Non-priv domain attempted WRMSR.\n");
kaf24@3443 600 goto fail;
kaf24@3349 601 }
kaf24@3349 602 wrmsr(regs->ecx, regs->eax, regs->edx);
kaf24@3443 603 break;
kaf24@3349 604
kaf24@3349 605 case 0x32: /* RDMSR */
kaf24@3443 606 if ( !IS_PRIV(ed->domain) )
kaf24@3349 607 {
kaf24@3349 608 DPRINTK("Non-priv domain attempted RDMSR.\n");
kaf24@3443 609 goto fail;
kaf24@3349 610 }
kaf24@3349 611 rdmsr(regs->ecx, regs->eax, regs->edx);
kaf24@3443 612 break;
kaf24@3443 613
kaf24@3443 614 default:
kaf24@3443 615 goto fail;
kaf24@3349 616 }
kaf24@3349 617
kaf24@3443 618 regs->eip = eip;
kaf24@3443 619 return EXCRET_fault_fixed;
kaf24@3443 620
kaf24@3443 621 fail:
kaf24@3349 622 return 0;
kaf24@3443 623
kaf24@3443 624 page_fault:
kaf24@3443 625 propagate_page_fault(eip, 0);
kaf24@3443 626 return EXCRET_fault_fixed;
kaf24@3349 627 }
kaf24@3349 628
kaf24@3127 629 asmlinkage int do_general_protection(struct xen_regs *regs)
kaf24@1490 630 {
cl349@2957 631 struct exec_domain *ed = current;
cl349@2957 632 struct domain *d = ed->domain;
cl349@3086 633 struct trap_bounce *tb = &ed->thread.trap_bounce;
kaf24@1490 634 trap_info_t *ti;
kaf24@1490 635 unsigned long fixup;
kaf24@1490 636
kaf24@3127 637 DEBUGGER_trap_entry(TRAP_gp_fault, regs);
kaf24@3009 638
kaf24@3207 639 if ( regs->error_code & 1 )
kaf24@3207 640 goto hardware_gp;
kaf24@3207 641
kaf24@3207 642 if ( !GUEST_FAULT(regs) )
kaf24@1490 643 goto gp_in_kernel;
kaf24@1490 644
kaf24@1490 645 /*
kaf24@1490 646 * Cunning trick to allow arbitrary "INT n" handling.
kaf24@1490 647 *
kaf24@1490 648 * We set DPL == 0 on all vectors in the IDT. This prevents any INT <n>
kaf24@1490 649 * instruction from trapping to the appropriate vector, when that might not
kaf24@1490 650 * be expected by Xen or the guest OS. For example, that entry might be for
kaf24@1490 651 * a fault handler (unlike traps, faults don't increment EIP), or might
kaf24@1490 652 * expect an error code on the stack (which a software trap never
kaf24@1490 653 * provides), or might be a hardware interrupt handler that doesn't like
kaf24@1490 654 * being called spuriously.
kaf24@1490 655 *
kaf24@1490 656 * Instead, a GPF occurs with the faulting IDT vector in the error code.
kaf24@1490 657 * Bit 1 is set to indicate that an IDT entry caused the fault. Bit 0 is
kaf24@1490 658 * clear to indicate that it's a software fault, not hardware.
kaf24@1490 659 *
kaf24@1490 660 * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is
kaf24@1490 661 * okay because they can only be triggered by an explicit DPL-checked
kaf24@1490 662 * instruction. The DPL specified by the guest OS for these vectors is NOT
kaf24@1490 663 * CHECKED!!
kaf24@1490 664 */
kaf24@3127 665 if ( (regs->error_code & 3) == 2 )
kaf24@1490 666 {
kaf24@1490 667 /* This fault must be due to <INT n> instruction. */
kaf24@3127 668 ti = current->thread.traps + (regs->error_code>>3);
kaf24@3207 669 if ( TI_GET_DPL(ti) >= (VM86_MODE(regs) ? 3 : (regs->cs & 3)) )
kaf24@1490 670 {
kaf24@3127 671 tb->flags = TBF_EXCEPTION;
kaf24@1490 672 regs->eip += 2;
kaf24@1490 673 goto finish_propagation;
kaf24@1490 674 }
kaf24@1490 675 }
kaf24@1854 676
kaf24@3349 677 /* Emulate some simple privileged instructions when exec'ed in ring 1. */
kaf24@3349 678 if ( (regs->error_code == 0) &&
kaf24@3349 679 RING_1(regs) &&
kaf24@3349 680 emulate_privileged_op(regs) )
kaf24@3349 681 return 0;
kaf24@3349 682
kaf24@1854 683 #if defined(__i386__)
kaf24@2111 684 if ( VM_ASSIST(d, VMASST_TYPE_4gb_segments) &&
kaf24@3127 685 (regs->error_code == 0) &&
kaf24@2111 686 gpf_emulate_4gb(regs) )
kaf24@3090 687 return 0;
kaf24@1854 688 #endif
kaf24@3009 689
kaf24@1490 690 /* Pass on GPF as is. */
kaf24@1490 691 ti = current->thread.traps + 13;
kaf24@3127 692 tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE;
kaf24@3127 693 tb->error_code = regs->error_code;
kaf24@1490 694 finish_propagation:
kaf24@3081 695 tb->cs = ti->cs;
kaf24@3081 696 tb->eip = ti->address;
kaf24@1490 697 if ( TI_GET_IF(ti) )
cl349@2959 698 ed->vcpu_info->evtchn_upcall_mask = 1;
kaf24@3090 699 return 0;
kaf24@1490 700
kaf24@1490 701 gp_in_kernel:
kaf24@1490 702
kaf24@1490 703 if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
kaf24@1490 704 {
kaf24@3635 705 DPRINTK("GPF (%04x): %08lx -> %08lx\n",
kaf24@3127 706 regs->error_code, regs->eip, fixup);
kaf24@1490 707 regs->eip = fixup;
kaf24@3090 708 return 0;
kaf24@1490 709 }
kaf24@1490 710
kaf24@3127 711 DEBUGGER_trap_fatal(TRAP_gp_fault, regs);
cl349@2995 712
kaf24@3207 713 hardware_gp:
kaf24@3079 714 show_registers(regs);
kaf24@3127 715 panic("CPU%d GENERAL PROTECTION FAULT\n[error_code=%04x]\n",
kaf24@3127 716 smp_processor_id(), regs->error_code);
kaf24@3090 717 return 0;
kaf24@1490 718 }
kaf24@1490 719
ach61@2843 720 asmlinkage void mem_parity_error(struct xen_regs *regs)
kaf24@1490 721 {
kaf24@2079 722 console_force_unlock();
kaf24@3079 723 printk("\n\nNMI - MEMORY ERROR\n");
kaf24@3127 724 fatal_trap(TRAP_nmi, regs);
kaf24@1490 725 }
kaf24@1490 726
ach61@2843 727 asmlinkage void io_check_error(struct xen_regs *regs)
kaf24@1490 728 {
kaf24@2079 729 console_force_unlock();
kaf24@2079 730
kaf24@3079 731 printk("\n\nNMI - I/O ERROR\n");
kaf24@3127 732 fatal_trap(TRAP_nmi, regs);
kaf24@1490 733 }
kaf24@1490 734
ach61@2843 735 static void unknown_nmi_error(unsigned char reason, struct xen_regs * regs)
kaf24@1490 736 {
kaf24@1490 737 printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
kaf24@1490 738 printk("Dazed and confused, but trying to continue\n");
kaf24@1490 739 printk("Do you have a strange power saving mode enabled?\n");
kaf24@1490 740 }
kaf24@1490 741
ach61@2843 742 asmlinkage void do_nmi(struct xen_regs * regs, unsigned long reason)
kaf24@1490 743 {
kaf24@1490 744 ++nmi_count(smp_processor_id());
kaf24@1490 745
kaf24@1490 746 #if CONFIG_X86_LOCAL_APIC
kaf24@1490 747 if ( nmi_watchdog )
kaf24@1490 748 nmi_watchdog_tick(regs);
kaf24@1490 749 else
kaf24@1490 750 #endif
kaf24@1490 751 unknown_nmi_error((unsigned char)(reason&0xff), regs);
kaf24@1490 752 }
kaf24@1490 753
kaf24@2085 754 unsigned long nmi_softirq_reason;
kaf24@2085 755 static void nmi_softirq(void)
kaf24@2085 756 {
kaf24@2844 757 if ( dom0 == NULL )
kaf24@2085 758 return;
kaf24@2085 759
kaf24@2085 760 if ( test_and_clear_bit(0, &nmi_softirq_reason) )
cl349@2957 761 send_guest_virq(dom0->exec_domain[0], VIRQ_PARITY_ERR);
kaf24@2085 762
kaf24@2085 763 if ( test_and_clear_bit(1, &nmi_softirq_reason) )
cl349@2957 764 send_guest_virq(dom0->exec_domain[0], VIRQ_IO_ERR);
kaf24@2085 765 }
kaf24@2085 766
kaf24@3127 767 asmlinkage int math_state_restore(struct xen_regs *regs)
kaf24@1490 768 {
kaf24@1490 769 /* Prevent recursion. */
kaf24@1490 770 clts();
kaf24@1490 771
cl349@2957 772 if ( !test_bit(EDF_USEDFPU, &current->ed_flags) )
kaf24@1490 773 {
cl349@2957 774 if ( test_bit(EDF_DONEFPUINIT, &current->ed_flags) )
kaf24@1490 775 restore_fpu(current);
kaf24@1490 776 else
kaf24@1490 777 init_fpu();
cl349@2957 778 set_bit(EDF_USEDFPU, &current->ed_flags); /* so we fnsave on switch_to() */
kaf24@1490 779 }
kaf24@1490 780
cl349@2957 781 if ( test_and_clear_bit(EDF_GUEST_STTS, &current->ed_flags) )
kaf24@1490 782 {
kaf24@3081 783 struct trap_bounce *tb = &current->thread.trap_bounce;
kaf24@3127 784 tb->flags = TBF_EXCEPTION;
kaf24@3081 785 tb->cs = current->thread.traps[7].cs;
kaf24@3081 786 tb->eip = current->thread.traps[7].address;
kaf24@1490 787 }
kaf24@3090 788
kaf24@3090 789 return EXCRET_fault_fixed;
kaf24@1490 790 }
kaf24@1490 791
kaf24@3127 792 asmlinkage int do_debug(struct xen_regs *regs)
kaf24@1490 793 {
kaf24@1490 794 unsigned int condition;
cl349@3085 795 struct exec_domain *d = current;
kaf24@3081 796 struct trap_bounce *tb = &d->thread.trap_bounce;
kaf24@1490 797
kaf24@3127 798 DEBUGGER_trap_entry(TRAP_debug, regs);
kaf24@1490 799
kaf24@1490 800 __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
kaf24@1490 801
kaf24@1490 802 /* Mask out spurious debug traps due to lazy DR7 setting */
kaf24@1490 803 if ( (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) &&
kaf24@3081 804 (d->thread.debugreg[7] == 0) )
kaf24@1490 805 {
kaf24@1490 806 __asm__("movl %0,%%db7" : : "r" (0));
kaf24@3090 807 goto out;
kaf24@1490 808 }
kaf24@1490 809
kaf24@3207 810 if ( !GUEST_FAULT(regs) )
kaf24@1490 811 {
kaf24@1490 812 /* Clear TF just for absolute sanity. */
kaf24@1490 813 regs->eflags &= ~EF_TF;
kaf24@1490 814 /*
kaf24@1628 815 * We ignore watchpoints when they trigger within Xen. This may happen
kaf24@1628 816 * when a buffer is passed to us which previously had a watchpoint set
kaf24@1628 817 * on it. No need to bump EIP; the only faulting trap is an instruction
kaf24@1628 818 * breakpoint, which can't happen to us.
kaf24@1490 819 */
kaf24@3090 820 goto out;
kaf24@1490 821 }
kaf24@1490 822
kaf24@1490 823 /* Save debug status register where guest OS can peek at it */
kaf24@3081 824 d->thread.debugreg[6] = condition;
kaf24@1490 825
kaf24@3127 826 tb->flags = TBF_EXCEPTION;
kaf24@3081 827 tb->cs = d->thread.traps[1].cs;
kaf24@3081 828 tb->eip = d->thread.traps[1].address;
kaf24@3090 829
kaf24@3090 830 out:
kaf24@3090 831 return EXCRET_not_a_fault;
kaf24@1490 832 }
kaf24@1490 833
kaf24@3127 834 asmlinkage int do_spurious_interrupt_bug(struct xen_regs *regs)
kaf24@3090 835 {
kaf24@3090 836 return EXCRET_not_a_fault;
kaf24@3090 837 }
kaf24@1490 838
kaf24@1490 839 #define _set_gate(gate_addr,type,dpl,addr) \
kaf24@1490 840 do { \
kaf24@1490 841 int __d0, __d1; \
kaf24@1490 842 __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
kaf24@1490 843 "movw %4,%%dx\n\t" \
kaf24@1490 844 "movl %%eax,%0\n\t" \
kaf24@1490 845 "movl %%edx,%1" \
kaf24@1490 846 :"=m" (*((long *) (gate_addr))), \
kaf24@1490 847 "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
kaf24@1490 848 :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
kaf24@1490 849 "3" ((char *) (addr)),"2" (__HYPERVISOR_CS << 16)); \
kaf24@1490 850 } while (0)
kaf24@1490 851
kaf24@1490 852 void set_intr_gate(unsigned int n, void *addr)
kaf24@1490 853 {
kaf24@1490 854 _set_gate(idt_table+n,14,0,addr);
kaf24@1490 855 }
kaf24@1490 856
kaf24@1490 857 static void __init set_system_gate(unsigned int n, void *addr)
kaf24@1490 858 {
kaf24@1490 859 _set_gate(idt_table+n,14,3,addr);
kaf24@1490 860 }
kaf24@1490 861
kaf24@1490 862 static void set_task_gate(unsigned int n, unsigned int sel)
kaf24@1490 863 {
kaf24@1490 864 idt_table[n].a = sel << 16;
kaf24@1490 865 idt_table[n].b = 0x8500;
kaf24@1490 866 }
kaf24@1490 867
kaf24@1490 868 #define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
kaf24@1490 869 *((gate_addr)+1) = ((base) & 0xff000000) | \
kaf24@1490 870 (((base) & 0x00ff0000)>>16) | \
kaf24@1490 871 ((limit) & 0xf0000) | \
kaf24@1490 872 ((dpl)<<13) | \
kaf24@1490 873 (0x00408000) | \
kaf24@1490 874 ((type)<<8); \
kaf24@1490 875 *(gate_addr) = (((base) & 0x0000ffff)<<16) | \
kaf24@1490 876 ((limit) & 0x0ffff); }
kaf24@1490 877
kaf24@1490 878 #define _set_tssldt_desc(n,addr,limit,type) \
kaf24@1490 879 __asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
kaf24@1490 880 "movw %%ax,2(%2)\n\t" \
kaf24@1490 881 "rorl $16,%%eax\n\t" \
kaf24@1490 882 "movb %%al,4(%2)\n\t" \
kaf24@1490 883 "movb %4,5(%2)\n\t" \
kaf24@1490 884 "movb $0,6(%2)\n\t" \
kaf24@1490 885 "movb %%ah,7(%2)\n\t" \
kaf24@1490 886 "rorl $16,%%eax" \
kaf24@1490 887 : "=m"(*(n)) : "a" (addr), "r"(n), "ir"(limit), "i"(type))
kaf24@1490 888
kaf24@1490 889 void set_tss_desc(unsigned int n, void *addr)
kaf24@1490 890 {
kaf24@3113 891 _set_tssldt_desc(
kaf24@3113 892 gdt_table + __TSS(n),
kaf24@3113 893 (int)addr,
kaf24@3113 894 offsetof(struct tss_struct, __cacheline_filler) - 1,
kaf24@3113 895 0x89);
kaf24@1490 896 }
kaf24@1490 897
kaf24@1490 898 void __init trap_init(void)
kaf24@1490 899 {
kaf24@1490 900 /*
kaf24@1490 901 * Make a separate task for double faults. This will get us debug output if
kaf24@1490 902 * we blow the kernel stack.
kaf24@1490 903 */
kaf24@1490 904 struct tss_struct *tss = &doublefault_tss;
kaf24@1490 905 memset(tss, 0, sizeof(*tss));
kaf24@1490 906 tss->ds = __HYPERVISOR_DS;
kaf24@1490 907 tss->es = __HYPERVISOR_DS;
kaf24@1490 908 tss->ss = __HYPERVISOR_DS;
kaf24@1490 909 tss->esp = (unsigned long)
kaf24@1490 910 &doublefault_stack[DOUBLEFAULT_STACK_SIZE];
kaf24@1490 911 tss->__cr3 = __pa(idle_pg_table);
kaf24@1490 912 tss->cs = __HYPERVISOR_CS;
kaf24@1490 913 tss->eip = (unsigned long)do_double_fault;
kaf24@1490 914 tss->eflags = 2;
kaf24@3088 915 tss->bitmap = IOBMP_INVALID_OFFSET;
kaf24@1490 916 _set_tssldt_desc(gdt_table+__DOUBLEFAULT_TSS_ENTRY,
kaf24@1490 917 (int)tss, 235, 0x89);
kaf24@1490 918
kaf24@1490 919 /*
kaf24@1490 920 * Note that interrupt gates are always used, rather than trap gates. We
kaf24@1490 921 * must have interrupts disabled until DS/ES/FS/GS are saved because the
kaf24@1490 922 * first activation must have the "bad" value(s) for these registers and
kaf24@1490 923 * we may lose them if another activation is installed before they are
kaf24@1490 924 * saved. The page-fault handler also needs interrupts disabled until %cr2
kaf24@1490 925 * has been read and saved on the stack.
kaf24@1490 926 */
kaf24@3079 927 set_intr_gate(TRAP_divide_error,&divide_error);
kaf24@3079 928 set_intr_gate(TRAP_debug,&debug);
kaf24@3079 929 set_intr_gate(TRAP_nmi,&nmi);
kaf24@3079 930 set_system_gate(TRAP_int3,&int3); /* usable from all privileges */
kaf24@3079 931 set_system_gate(TRAP_overflow,&overflow); /* usable from all privileges */
kaf24@3079 932 set_intr_gate(TRAP_bounds,&bounds);
kaf24@3079 933 set_intr_gate(TRAP_invalid_op,&invalid_op);
kaf24@3079 934 set_intr_gate(TRAP_no_device,&device_not_available);
kaf24@3079 935 set_task_gate(TRAP_double_fault,__DOUBLEFAULT_TSS_ENTRY<<3);
kaf24@3079 936 set_intr_gate(TRAP_copro_seg,&coprocessor_segment_overrun);
kaf24@3079 937 set_intr_gate(TRAP_invalid_tss,&invalid_TSS);
kaf24@3079 938 set_intr_gate(TRAP_no_segment,&segment_not_present);
kaf24@3079 939 set_intr_gate(TRAP_stack_error,&stack_segment);
kaf24@3079 940 set_intr_gate(TRAP_gp_fault,&general_protection);
kaf24@3079 941 set_intr_gate(TRAP_page_fault,&page_fault);
kaf24@3079 942 set_intr_gate(TRAP_spurious_int,&spurious_interrupt_bug);
kaf24@3079 943 set_intr_gate(TRAP_copro_error,&coprocessor_error);
kaf24@3079 944 set_intr_gate(TRAP_alignment_check,&alignment_check);
kaf24@3079 945 set_intr_gate(TRAP_machine_check,&machine_check);
kaf24@3079 946 set_intr_gate(TRAP_simd_error,&simd_coprocessor_error);
kaf24@3633 947 set_intr_gate(TRAP_deferred_nmi,&nmi);
kaf24@1490 948
kaf24@1628 949 /* Only ring 1 can access Xen services. */
kaf24@1594 950 _set_gate(idt_table+HYPERCALL_VECTOR,14,1,&hypercall);
kaf24@1490 951
kaf24@1490 952 /* CPU0 uses the master IDT. */
kaf24@1490 953 idt_tables[0] = idt_table;
kaf24@1490 954
kaf24@1490 955 /*
kaf24@1490 956 * Should be a barrier for any external CPU state.
kaf24@1490 957 */
kaf24@1490 958 {
kaf24@1490 959 extern void cpu_init(void);
kaf24@1490 960 cpu_init();
kaf24@1490 961 }
kaf24@2085 962
kaf24@2085 963 open_softirq(NMI_SOFTIRQ, nmi_softirq);
kaf24@1490 964 }
kaf24@1490 965
kaf24@1490 966
kaf24@1490 967 long do_set_trap_table(trap_info_t *traps)
kaf24@1490 968 {
kaf24@1490 969 trap_info_t cur;
kaf24@1490 970 trap_info_t *dst = current->thread.traps;
kaf24@1490 971
cl349@3036 972 LOCK_BIGLOCK(current->domain);
cl349@3036 973
kaf24@1490 974 for ( ; ; )
kaf24@1490 975 {
kaf24@3177 976 if ( hypercall_preempt_check() )
kaf24@3177 977 {
cl349@3191 978 UNLOCK_BIGLOCK(current->domain);
kaf24@3187 979 return hypercall_create_continuation(
kaf24@3177 980 __HYPERVISOR_set_trap_table, 1, traps);
kaf24@3177 981 }
kaf24@3129 982
kaf24@1490 983 if ( copy_from_user(&cur, traps, sizeof(cur)) ) return -EFAULT;
kaf24@1490 984
kaf24@1490 985 if ( cur.address == 0 ) break;
kaf24@1490 986
kaf24@1490 987 if ( !VALID_CODESEL(cur.cs) ) return -EPERM;
kaf24@1490 988
kaf24@1490 989 memcpy(dst+cur.vector, &cur, sizeof(cur));
kaf24@1490 990 traps++;
kaf24@1490 991 }
kaf24@1490 992
cl349@3036 993 UNLOCK_BIGLOCK(current->domain);
cl349@3036 994
kaf24@1490 995 return 0;
kaf24@1490 996 }
kaf24@1490 997
kaf24@1490 998
kaf24@1490 999 long do_set_callbacks(unsigned long event_selector,
kaf24@1490 1000 unsigned long event_address,
kaf24@1490 1001 unsigned long failsafe_selector,
kaf24@1490 1002 unsigned long failsafe_address)
kaf24@1490 1003 {
cl349@3085 1004 struct exec_domain *d = current;
kaf24@1490 1005
kaf24@1490 1006 if ( !VALID_CODESEL(event_selector) || !VALID_CODESEL(failsafe_selector) )
kaf24@1490 1007 return -EPERM;
kaf24@1490 1008
kaf24@3081 1009 d->thread.event_selector = event_selector;
kaf24@3081 1010 d->thread.event_address = event_address;
kaf24@3081 1011 d->thread.failsafe_selector = failsafe_selector;
kaf24@3081 1012 d->thread.failsafe_address = failsafe_address;
kaf24@1490 1013
kaf24@1490 1014 return 0;
kaf24@1490 1015 }
kaf24@1490 1016
kaf24@1490 1017
cl349@2957 1018 long set_fast_trap(struct exec_domain *p, int idx)
kaf24@1490 1019 {
kaf24@1490 1020 trap_info_t *ti;
kaf24@1490 1021
kaf24@1490 1022 /* Index 0 is special: it disables fast traps. */
kaf24@1490 1023 if ( idx == 0 )
kaf24@1490 1024 {
kaf24@1490 1025 if ( p == current )
kaf24@1490 1026 CLEAR_FAST_TRAP(&p->thread);
kaf24@1490 1027 SET_DEFAULT_FAST_TRAP(&p->thread);
kaf24@1490 1028 return 0;
kaf24@1490 1029 }
kaf24@1490 1030
kaf24@1490 1031 /*
kaf24@1490 1032 * We only fast-trap vectors 0x20-0x2f, and vector 0x80.
kaf24@1490 1033 * The former range is used by Windows and MS-DOS.
kaf24@1490 1034 * Vector 0x80 is used by Linux and the BSD variants.
kaf24@1490 1035 */
kaf24@1490 1036 if ( (idx != 0x80) && ((idx < 0x20) || (idx > 0x2f)) )
kaf24@1490 1037 return -1;
kaf24@1490 1038
kaf24@1490 1039 ti = p->thread.traps + idx;
kaf24@1490 1040
kaf24@1490 1041 /*
kaf24@1490 1042 * We can't virtualise interrupt gates, as there's no way to get
kaf24@1490 1043 * the CPU to automatically clear the events_mask variable.
kaf24@1490 1044 */
kaf24@1490 1045 if ( TI_GET_IF(ti) )
kaf24@1490 1046 return -1;
kaf24@1490 1047
kaf24@1490 1048 if ( p == current )
kaf24@1490 1049 CLEAR_FAST_TRAP(&p->thread);
kaf24@1490 1050
kaf24@1490 1051 p->thread.fast_trap_idx = idx;
kaf24@1490 1052 p->thread.fast_trap_desc.a = (ti->cs << 16) | (ti->address & 0xffff);
kaf24@1490 1053 p->thread.fast_trap_desc.b =
kaf24@1490 1054 (ti->address & 0xffff0000) | 0x8f00 | (TI_GET_DPL(ti)&3)<<13;
kaf24@1490 1055
kaf24@1490 1056 if ( p == current )
kaf24@1490 1057 SET_FAST_TRAP(&p->thread);
kaf24@1490 1058
kaf24@1490 1059 return 0;
kaf24@1490 1060 }
kaf24@1490 1061
kaf24@1490 1062
kaf24@1490 1063 long do_set_fast_trap(int idx)
kaf24@1490 1064 {
kaf24@1490 1065 return set_fast_trap(current, idx);
kaf24@1490 1066 }
kaf24@1490 1067
kaf24@1490 1068
kaf24@1490 1069 long do_fpu_taskswitch(void)
kaf24@1490 1070 {
cl349@2957 1071 set_bit(EDF_GUEST_STTS, &current->ed_flags);
kaf24@1490 1072 stts();
kaf24@1490 1073 return 0;
kaf24@1490 1074 }
kaf24@1490 1075
kaf24@1490 1076
cl349@2957 1077 long set_debugreg(struct exec_domain *p, int reg, unsigned long value)
kaf24@1490 1078 {
kaf24@1490 1079 int i;
kaf24@1490 1080
kaf24@1490 1081 switch ( reg )
kaf24@1490 1082 {
kaf24@1490 1083 case 0:
kaf24@1490 1084 if ( value > (PAGE_OFFSET-4) ) return -EPERM;
kaf24@1490 1085 if ( p == current )
kaf24@1490 1086 __asm__ ( "movl %0, %%db0" : : "r" (value) );
kaf24@1490 1087 break;
kaf24@1490 1088 case 1:
kaf24@1490 1089 if ( value > (PAGE_OFFSET-4) ) return -EPERM;
kaf24@1490 1090 if ( p == current )
kaf24@1490 1091 __asm__ ( "movl %0, %%db1" : : "r" (value) );
kaf24@1490 1092 break;
kaf24@1490 1093 case 2:
kaf24@1490 1094 if ( value > (PAGE_OFFSET-4) ) return -EPERM;
kaf24@1490 1095 if ( p == current )
kaf24@1490 1096 __asm__ ( "movl %0, %%db2" : : "r" (value) );
kaf24@1490 1097 break;
kaf24@1490 1098 case 3:
kaf24@1490 1099 if ( value > (PAGE_OFFSET-4) ) return -EPERM;
kaf24@1490 1100 if ( p == current )
kaf24@1490 1101 __asm__ ( "movl %0, %%db3" : : "r" (value) );
kaf24@1490 1102 break;
kaf24@1490 1103 case 6:
kaf24@1490 1104 /*
kaf24@1490 1105 * DR6: Bits 4-11,16-31 reserved (set to 1).
kaf24@1490 1106 * Bit 12 reserved (set to 0).
kaf24@1490 1107 */
kaf24@1490 1108 value &= 0xffffefff; /* reserved bits => 0 */
kaf24@1490 1109 value |= 0xffff0ff0; /* reserved bits => 1 */
kaf24@1490 1110 if ( p == current )
kaf24@1490 1111 __asm__ ( "movl %0, %%db6" : : "r" (value) );
kaf24@1490 1112 break;
kaf24@1490 1113 case 7:
kaf24@1490 1114 /*
kaf24@1490 1115 * DR7: Bit 10 reserved (set to 1).
kaf24@1490 1116 * Bits 11-12,14-15 reserved (set to 0).
kaf24@1490 1117 * Privileged bits:
kaf24@1490 1118 * GD (bit 13): must be 0.
kaf24@1490 1119 * R/Wn (bits 16-17,20-21,24-25,28-29): mustn't be 10.
kaf24@1490 1120 * LENn (bits 18-19,22-23,26-27,30-31): mustn't be 10.
kaf24@1490 1121 */
kaf24@1490 1122 /* DR7 == 0 => debugging disabled for this domain. */
kaf24@1490 1123 if ( value != 0 )
kaf24@1490 1124 {
kaf24@1490 1125 value &= 0xffff27ff; /* reserved bits => 0 */
kaf24@1490 1126 value |= 0x00000400; /* reserved bits => 1 */
kaf24@1490 1127 if ( (value & (1<<13)) != 0 ) return -EPERM;
kaf24@1490 1128 for ( i = 0; i < 16; i += 2 )
kaf24@1490 1129 if ( ((value >> (i+16)) & 3) == 2 ) return -EPERM;
kaf24@1490 1130 }
kaf24@1490 1131 if ( p == current )
kaf24@1490 1132 __asm__ ( "movl %0, %%db7" : : "r" (value) );
kaf24@1490 1133 break;
kaf24@1490 1134 default:
kaf24@1490 1135 return -EINVAL;
kaf24@1490 1136 }
kaf24@1490 1137
kaf24@1490 1138 p->thread.debugreg[reg] = value;
kaf24@1490 1139 return 0;
kaf24@1490 1140 }
kaf24@1490 1141
kaf24@1490 1142 long do_set_debugreg(int reg, unsigned long value)
kaf24@1490 1143 {
kaf24@1490 1144 return set_debugreg(current, reg, value);
kaf24@1490 1145 }
kaf24@1490 1146
kaf24@1490 1147 unsigned long do_get_debugreg(int reg)
kaf24@1490 1148 {
kaf24@1490 1149 if ( (reg < 0) || (reg > 7) ) return -EINVAL;
kaf24@1490 1150 return current->thread.debugreg[reg];
kaf24@1490 1151 }