direct-io.hg

view xen/arch/x86/x86_32/traps.c @ 8736:8aeb417387ca

Fix some more pfn/mfn/gmfn/gpfn inconsistencies. Fix some direct
uses of max_page variable to use the mfn_valid() predicate.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Feb 02 12:18:28 2006 +0100 (2006-02-02)
parents f1b361b05bf3
children 6f7c5439a6c4
line source
2 #include <xen/config.h>
3 #include <xen/domain_page.h>
4 #include <xen/init.h>
5 #include <xen/sched.h>
6 #include <xen/lib.h>
7 #include <xen/console.h>
8 #include <xen/mm.h>
9 #include <xen/irq.h>
10 #include <xen/symbols.h>
11 #include <asm/current.h>
12 #include <asm/flushtlb.h>
13 #include <asm/hvm/hvm.h>
14 #include <asm/hvm/support.h>
16 /* All CPUs have their own IDT to allow int80 direct trap. */
17 idt_entry_t *idt_tables[NR_CPUS] = { 0 };
19 void show_registers(struct cpu_user_regs *regs)
20 {
21 struct cpu_user_regs faultregs;
22 unsigned long faultcrs[8];
23 const char *context;
25 if ( HVM_DOMAIN(current) && regs->eflags == 0 )
26 {
27 context = "hvm";
28 hvm_load_cpu_guest_regs(current, &faultregs);
29 hvm_store_cpu_guest_ctrl_regs(current, faultcrs);
30 }
31 else
32 {
33 faultregs = *regs;
34 if ( GUEST_MODE(regs) )
35 {
36 context = "guest";
37 faultregs.ss &= 0xFFFF;
38 faultregs.ds &= 0xFFFF;
39 faultregs.es &= 0xFFFF;
40 faultregs.cs &= 0xFFFF;
41 }
42 else
43 {
44 context = "hypervisor";
45 faultregs.esp = (unsigned long)&regs->esp;
46 faultregs.ss = __HYPERVISOR_DS;
47 faultregs.ds = __HYPERVISOR_DS;
48 faultregs.es = __HYPERVISOR_DS;
49 faultregs.cs = __HYPERVISOR_CS;
50 }
51 __asm__ ("movw %%fs,%0 ; movw %%gs,%1"
52 : "=r" (faultregs.fs), "=r" (faultregs.gs) );
54 faultcrs[0] = read_cr0();
55 faultcrs[3] = read_cr3();
56 }
58 printk("CPU: %d\nEIP: %04x:[<%08x>]",
59 smp_processor_id(), faultregs.cs, faultregs.eip);
60 if ( !HVM_DOMAIN(current) && !GUEST_MODE(regs) )
61 print_symbol(" %s", faultregs.eip);
62 printk("\nEFLAGS: %08x CONTEXT: %s\n", faultregs.eflags, context);
63 printk("eax: %08x ebx: %08x ecx: %08x edx: %08x\n",
64 regs->eax, regs->ebx, regs->ecx, regs->edx);
65 printk("esi: %08x edi: %08x ebp: %08x esp: %08x\n",
66 regs->esi, regs->edi, regs->ebp, faultregs.esp);
67 printk("cr0: %08lx cr3: %08lx\n", faultcrs[0], faultcrs[3]);
68 printk("ds: %04x es: %04x fs: %04x gs: %04x "
69 "ss: %04x cs: %04x\n",
70 faultregs.ds, faultregs.es, faultregs.fs,
71 faultregs.gs, faultregs.ss, faultregs.cs);
73 show_stack(regs);
74 }
76 void show_page_walk(unsigned long addr)
77 {
78 unsigned long mfn = read_cr3() >> PAGE_SHIFT;
79 intpte_t *ptab, ent;
80 unsigned long pfn;
82 printk("Pagetable walk from %08lx:\n", addr);
84 #ifdef CONFIG_X86_PAE
85 ptab = map_domain_page(mfn);
86 ent = ptab[l3_table_offset(addr)];
87 pfn = get_gpfn_from_mfn((u32)(ent >> PAGE_SHIFT));
88 printk(" L3 = %"PRIpte" %08lx\n", ent, pfn);
89 unmap_domain_page(ptab);
90 if ( !(ent & _PAGE_PRESENT) )
91 return;
92 mfn = ent >> PAGE_SHIFT;
93 #endif
95 ptab = map_domain_page(mfn);
96 ent = ptab[l2_table_offset(addr)];
97 pfn = get_gpfn_from_mfn((u32)(ent >> PAGE_SHIFT));
98 printk(" L2 = %"PRIpte" %08lx %s\n", ent, pfn,
99 (ent & _PAGE_PSE) ? "(PSE)" : "");
100 unmap_domain_page(ptab);
101 if ( !(ent & _PAGE_PRESENT) || (ent & _PAGE_PSE) )
102 return;
103 mfn = ent >> PAGE_SHIFT;
105 ptab = map_domain_page(ent >> PAGE_SHIFT);
106 ent = ptab[l1_table_offset(addr)];
107 pfn = get_gpfn_from_mfn((u32)(ent >> PAGE_SHIFT));
108 printk(" L1 = %"PRIpte" %08lx\n", ent, pfn);
109 unmap_domain_page(ptab);
110 }
112 #define DOUBLEFAULT_STACK_SIZE 1024
113 static struct tss_struct doublefault_tss;
114 static unsigned char doublefault_stack[DOUBLEFAULT_STACK_SIZE];
116 asmlinkage void do_double_fault(void)
117 {
118 struct tss_struct *tss = &doublefault_tss;
119 unsigned int cpu = ((tss->back_link>>3)-__FIRST_TSS_ENTRY)>>1;
121 watchdog_disable();
123 console_force_unlock();
125 /* Find information saved during fault and dump it to the console. */
126 tss = &init_tss[cpu];
127 printk("CPU: %d\nEIP: %04x:[<%08x>]",
128 cpu, tss->cs, tss->eip);
129 print_symbol(" %s\n", tss->eip);
130 printk("EFLAGS: %08x\n", tss->eflags);
131 printk("CR3: %08x\n", tss->__cr3);
132 printk("eax: %08x ebx: %08x ecx: %08x edx: %08x\n",
133 tss->eax, tss->ebx, tss->ecx, tss->edx);
134 printk("esi: %08x edi: %08x ebp: %08x esp: %08x\n",
135 tss->esi, tss->edi, tss->ebp, tss->esp);
136 printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n",
137 tss->ds, tss->es, tss->fs, tss->gs, tss->ss);
138 printk("************************************\n");
139 printk("CPU%d DOUBLE FAULT -- system shutdown\n", cpu);
140 printk("System needs manual reset.\n");
141 printk("************************************\n");
143 /* Lock up the console to prevent spurious output from other CPUs. */
144 console_force_lock();
146 /* Wait for manual reset. */
147 for ( ; ; )
148 __asm__ __volatile__ ( "hlt" );
149 }
151 unsigned long do_iret(void)
152 {
153 struct cpu_user_regs *regs = guest_cpu_user_regs();
154 u32 eflags;
156 /* Check worst-case stack frame for overlap with Xen protected area. */
157 if ( unlikely(!access_ok(regs->esp, 40)) )
158 domain_crash_synchronous();
160 /* Pop and restore EAX (clobbered by hypercall). */
161 if ( unlikely(__copy_from_user(&regs->eax, (void __user *)regs->esp, 4)) )
162 domain_crash_synchronous();
163 regs->esp += 4;
165 /* Pop and restore CS and EIP. */
166 if ( unlikely(__copy_from_user(&regs->eip, (void __user *)regs->esp, 8)) )
167 domain_crash_synchronous();
168 regs->esp += 8;
170 /*
171 * Pop, fix up and restore EFLAGS. We fix up in a local staging area
172 * to avoid firing the BUG_ON(IOPL) check in arch_getdomaininfo_ctxt.
173 */
174 if ( unlikely(__copy_from_user(&eflags, (void __user *)regs->esp, 4)) )
175 domain_crash_synchronous();
176 regs->esp += 4;
177 regs->eflags = (eflags & ~X86_EFLAGS_IOPL) | X86_EFLAGS_IF;
179 if ( VM86_MODE(regs) )
180 {
181 /* Return to VM86 mode: pop and restore ESP,SS,ES,DS,FS and GS. */
182 if ( __copy_from_user(&regs->esp, (void __user *)regs->esp, 24) )
183 domain_crash_synchronous();
184 }
185 else if ( unlikely(RING_0(regs)) )
186 {
187 domain_crash_synchronous();
188 }
189 else if ( !RING_1(regs) )
190 {
191 /* Return to ring 2/3: pop and restore ESP and SS. */
192 if ( __copy_from_user(&regs->esp, (void __user *)regs->esp, 8) )
193 domain_crash_synchronous();
194 }
196 /* No longer in NMI context. */
197 clear_bit(_VCPUF_nmi_masked, &current->vcpu_flags);
199 /* Restore upcall mask from saved value. */
200 current->vcpu_info->evtchn_upcall_mask = regs->saved_upcall_mask;
202 /*
203 * The hypercall exit path will overwrite EAX with this return
204 * value.
205 */
206 return regs->eax;
207 }
209 BUILD_SMP_INTERRUPT(deferred_nmi, TRAP_deferred_nmi)
210 asmlinkage void smp_deferred_nmi(struct cpu_user_regs regs)
211 {
212 asmlinkage void do_nmi(struct cpu_user_regs *);
213 ack_APIC_irq();
214 do_nmi(&regs);
215 }
217 void __init percpu_traps_init(void)
218 {
219 struct tss_struct *tss = &doublefault_tss;
220 asmlinkage int hypercall(void);
222 if ( smp_processor_id() != 0 )
223 return;
225 /* CPU0 uses the master IDT. */
226 idt_tables[0] = idt_table;
228 /* The hypercall entry vector is only accessible from ring 1. */
229 _set_gate(idt_table+HYPERCALL_VECTOR, 14, 1, &hypercall);
231 set_intr_gate(TRAP_deferred_nmi, &deferred_nmi);
233 /*
234 * Make a separate task for double faults. This will get us debug output if
235 * we blow the kernel stack.
236 */
237 memset(tss, 0, sizeof(*tss));
238 tss->ds = __HYPERVISOR_DS;
239 tss->es = __HYPERVISOR_DS;
240 tss->ss = __HYPERVISOR_DS;
241 tss->esp = (unsigned long)
242 &doublefault_stack[DOUBLEFAULT_STACK_SIZE];
243 tss->__cr3 = __pa(idle_pg_table);
244 tss->cs = __HYPERVISOR_CS;
245 tss->eip = (unsigned long)do_double_fault;
246 tss->eflags = 2;
247 tss->bitmap = IOBMP_INVALID_OFFSET;
248 _set_tssldt_desc(
249 gdt_table + __DOUBLEFAULT_TSS_ENTRY - FIRST_RESERVED_GDT_ENTRY,
250 (unsigned long)tss, 235, 9);
252 set_task_gate(TRAP_double_fault, __DOUBLEFAULT_TSS_ENTRY<<3);
253 }
255 void init_int80_direct_trap(struct vcpu *v)
256 {
257 struct trap_info *ti = &v->arch.guest_context.trap_ctxt[0x80];
259 /*
260 * We can't virtualise interrupt gates, as there's no way to get
261 * the CPU to automatically clear the events_mask variable.
262 */
263 if ( TI_GET_IF(ti) )
264 return;
266 v->arch.int80_desc.a = (ti->cs << 16) | (ti->address & 0xffff);
267 v->arch.int80_desc.b =
268 (ti->address & 0xffff0000) | 0x8f00 | ((TI_GET_DPL(ti) & 3) << 13);
270 if ( v == current )
271 set_int80_direct_trap(v);
272 }
274 long do_set_callbacks(unsigned long event_selector,
275 unsigned long event_address,
276 unsigned long failsafe_selector,
277 unsigned long failsafe_address)
278 {
279 struct vcpu *d = current;
281 if ( !VALID_CODESEL(event_selector) || !VALID_CODESEL(failsafe_selector) )
282 return -EPERM;
284 d->arch.guest_context.event_callback_cs = event_selector;
285 d->arch.guest_context.event_callback_eip = event_address;
286 d->arch.guest_context.failsafe_callback_cs = failsafe_selector;
287 d->arch.guest_context.failsafe_callback_eip = failsafe_address;
289 return 0;
290 }
292 void hypercall_page_initialise(void *hypercall_page)
293 {
294 char *p;
295 int i;
297 /* Fill in all the transfer points with template machine code. */
298 for ( i = 0; i < (PAGE_SIZE / 32); i++ )
299 {
300 p = (char *)(hypercall_page + (i * 32));
301 *(u8 *)(p+ 0) = 0xb8; /* mov $<i>,%eax */
302 *(u32 *)(p+ 1) = i;
303 *(u16 *)(p+ 5) = 0x82cd; /* int $0x82 */
304 *(u8 *)(p+ 7) = 0xc3; /* ret */
305 }
307 /*
308 * HYPERVISOR_iret is special because it doesn't return and expects a
309 * special stack frame. Guests jump at this transfer point instead of
310 * calling it.
311 */
312 p = (char *)(hypercall_page + (__HYPERVISOR_iret * 32));
313 *(u8 *)(p+ 0) = 0x50; /* push %eax */
314 *(u8 *)(p+ 1) = 0xb8; /* mov $__HYPERVISOR_iret,%eax */
315 *(u32 *)(p+ 2) = __HYPERVISOR_iret;
316 *(u16 *)(p+ 6) = 0x82cd; /* int $0x82 */
317 }
319 /*
320 * Local variables:
321 * mode: C
322 * c-set-style: "BSD"
323 * c-basic-offset: 4
324 * tab-width: 4
325 * indent-tabs-mode: nil
326 * End:
327 */