ia64/xen-unstable

view xen/arch/ia64/xen/xenmisc.c @ 9405:29dfadcc5029

[IA64] Followup to xen time cleanup

Clean up to xen time handler. Tristan #if 0 some code because it seems
redundant, which however is actually problematic logic as a reason for
an intermittent timer oops issue of dom0. So delete it now.

Also remove vcpu_wake, since wakeup current has nothing meaningful and
simply waste cpu cycle.

Signed-off-by: Kevin Tian <kevin.tian@intel.com>
author awilliam@xenbuild.aw
date Mon Mar 27 15:32:08 2006 -0700 (2006-03-27)
parents 9897a5e6385d
children cc94ab1e0de0
line source
1 /*
2 * Xen misc
3 *
4 * Functions/decls that are/may be needed to link with Xen because
5 * of x86 dependencies
6 *
7 * Copyright (C) 2004 Hewlett-Packard Co.
8 * Dan Magenheimer (dan.magenheimer@hp.com)
9 *
10 */
12 #include <linux/config.h>
13 #include <xen/sched.h>
14 #include <linux/efi.h>
15 #include <asm/processor.h>
16 #include <xen/serial.h>
17 #include <asm/io.h>
18 #include <xen/softirq.h>
19 #include <public/sched.h>
20 #include <asm/vhpt.h>
21 #include <asm/debugger.h>
22 #include <asm/vmx.h>
23 #include <asm/vmx_vcpu.h>
25 efi_memory_desc_t ia64_efi_io_md;
26 EXPORT_SYMBOL(ia64_efi_io_md);
27 unsigned long wait_init_idle;
28 int phys_proc_id[NR_CPUS];
29 unsigned long loops_per_jiffy = (1<<12); // from linux/init/main.c
31 /* FIXME: where these declarations should be there ? */
32 extern void load_region_regs(struct vcpu *);
33 extern void show_registers(struct pt_regs *regs);
35 void ia64_mca_init(void) { printf("ia64_mca_init() skipped (Machine check abort handling)\n"); }
36 void ia64_mca_cpu_init(void *x) { }
37 void ia64_patch_mckinley_e9(unsigned long a, unsigned long b) { }
38 void ia64_patch_vtop(unsigned long a, unsigned long b) { }
39 void hpsim_setup(char **x)
40 {
41 #ifdef CONFIG_SMP
42 init_smp_config();
43 #endif
44 }
46 // called from mem_init... don't think s/w I/O tlb is needed in Xen
47 //void swiotlb_init(void) { } ...looks like it IS needed
49 long
50 is_platform_hp_ski(void)
51 {
52 int i;
53 long cpuid[6];
55 for (i = 0; i < 5; ++i)
56 cpuid[i] = ia64_get_cpuid(i);
57 if ((cpuid[0] & 0xff) != 'H') return 0;
58 if ((cpuid[3] & 0xff) != 0x4) return 0;
59 if (((cpuid[3] >> 8) & 0xff) != 0x0) return 0;
60 if (((cpuid[3] >> 16) & 0xff) != 0x0) return 0;
61 if (((cpuid[3] >> 24) & 0x7) != 0x7) return 0;
62 return 1;
63 }
65 long
66 platform_is_hp_ski(void)
67 {
68 extern long running_on_sim;
69 return running_on_sim;
70 }
72 /* calls in xen/common code that are unused on ia64 */
74 void sync_lazy_execstate_cpu(unsigned int cpu) {}
76 #if 0
77 int grant_table_create(struct domain *d) { return 0; }
78 void grant_table_destroy(struct domain *d) { return; }
79 #endif
81 struct pt_regs *guest_cpu_user_regs(void) { return vcpu_regs(current); }
83 void raise_actimer_softirq(void)
84 {
85 raise_softirq(TIMER_SOFTIRQ);
86 }
88 unsigned long
89 gmfn_to_mfn_foreign(struct domain *d, unsigned long gpfn)
90 {
91 if (d == dom0)
92 return(gpfn);
93 else {
94 unsigned long pte = lookup_domain_mpa(d,gpfn << PAGE_SHIFT);
95 if (!pte) {
96 printk("gmfn_to_mfn_foreign: bad gpfn. spinning...\n");
97 while(1);
98 return 0;
99 }
100 return ((pte & _PFN_MASK) >> PAGE_SHIFT);
101 }
102 }
103 #if 0
104 u32
105 mfn_to_gmfn(struct domain *d, unsigned long frame)
106 {
107 // FIXME: is this right?
108 if ((frame << PAGE_SHIFT) & _PAGE_PPN_MASK) {
109 printk("mfn_to_gmfn: bad frame. spinning...\n");
110 while(1);
111 }
112 return frame;
113 }
114 #endif
116 ///////////////////////////////
117 // from arch/x86/flushtlb.c
118 ///////////////////////////////
120 u32 tlbflush_clock;
121 u32 tlbflush_time[NR_CPUS];
123 ///////////////////////////////
124 // from arch/x86/memory.c
125 ///////////////////////////////
128 void free_page_type(struct page_info *page, u32 type)
129 {
130 // dummy();
131 return;
132 }
134 int alloc_page_type(struct page_info *page, u32 type)
135 {
136 // dummy();
137 return 1;
138 }
140 ///////////////////////////////
141 //// misc memory stuff
142 ///////////////////////////////
144 unsigned long __get_free_pages(unsigned int mask, unsigned int order)
145 {
146 void *p = alloc_xenheap_pages(order);
148 memset(p,0,PAGE_SIZE<<order);
149 return (unsigned long)p;
150 }
152 void __free_pages(struct page_info *page, unsigned int order)
153 {
154 if (order) BUG();
155 free_xenheap_page(page);
156 }
158 void *pgtable_quicklist_alloc(void)
159 {
160 void *p;
161 p = alloc_xenheap_pages(0);
162 if (p)
163 clear_page(p);
164 return p;
165 }
167 void pgtable_quicklist_free(void *pgtable_entry)
168 {
169 free_xenheap_page(pgtable_entry);
170 }
172 ///////////////////////////////
173 // from arch/ia64/traps.c
174 ///////////////////////////////
176 int is_kernel_text(unsigned long addr)
177 {
178 extern char _stext[], _etext[];
179 if (addr >= (unsigned long) _stext &&
180 addr <= (unsigned long) _etext)
181 return 1;
183 return 0;
184 }
186 unsigned long kernel_text_end(void)
187 {
188 extern char _etext[];
189 return (unsigned long) _etext;
190 }
192 ///////////////////////////////
193 // from common/keyhandler.c
194 ///////////////////////////////
195 void dump_pageframe_info(struct domain *d)
196 {
197 printk("dump_pageframe_info not implemented\n");
198 }
200 ///////////////////////////////
201 // called from arch/ia64/head.S
202 ///////////////////////////////
204 void console_print(char *msg)
205 {
206 printk("console_print called, how did start_kernel return???\n");
207 }
209 void kernel_thread_helper(void)
210 {
211 printk("kernel_thread_helper not implemented\n");
212 dummy();
213 }
215 void sys_exit(void)
216 {
217 printk("sys_exit not implemented\n");
218 dummy();
219 }
221 ////////////////////////////////////
222 // called from unaligned.c
223 ////////////////////////////////////
225 void die_if_kernel(char *str, struct pt_regs *regs, long err) /* __attribute__ ((noreturn)) */
226 {
227 if (user_mode(regs))
228 return;
230 printk("%s: %s %ld\n", __func__, str, err);
231 debugtrace_dump();
232 show_registers(regs);
233 domain_crash_synchronous();
234 }
236 long
237 ia64_peek (struct task_struct *child, struct switch_stack *child_stack,
238 unsigned long user_rbs_end, unsigned long addr, long *val)
239 {
240 printk("ia64_peek: called, not implemented\n");
241 return 1;
242 }
244 long
245 ia64_poke (struct task_struct *child, struct switch_stack *child_stack,
246 unsigned long user_rbs_end, unsigned long addr, long val)
247 {
248 printk("ia64_poke: called, not implemented\n");
249 return 1;
250 }
252 void
253 ia64_sync_fph (struct task_struct *task)
254 {
255 printk("ia64_sync_fph: called, not implemented\n");
256 }
258 void
259 ia64_flush_fph (struct task_struct *task)
260 {
261 printk("ia64_flush_fph: called, not implemented\n");
262 }
264 ////////////////////////////////////
265 // called from irq_ia64.c:init_IRQ()
266 // (because CONFIG_IA64_HP_SIM is specified)
267 ////////////////////////////////////
268 void hpsim_irq_init(void) { }
271 // accomodate linux extable.c
272 //const struct exception_table_entry *
273 void *search_module_extables(unsigned long addr) { return NULL; }
274 void *__module_text_address(unsigned long addr) { return NULL; }
275 void *module_text_address(unsigned long addr) { return NULL; }
277 void cs10foo(void) {}
278 void cs01foo(void) {}
280 unsigned long context_switch_count = 0;
282 #include <asm/vcpu.h>
284 void context_switch(struct vcpu *prev, struct vcpu *next)
285 {
286 uint64_t spsr;
287 uint64_t pta;
289 local_irq_save(spsr);
290 // if(VMX_DOMAIN(prev)){
291 // vtm_domain_out(prev);
292 // }
293 context_switch_count++;
294 switch_to(prev,next,prev);
295 // if(VMX_DOMAIN(current)){
296 // vtm_domain_in(current);
297 // }
299 // leave this debug for now: it acts as a heartbeat when more than
300 // one domain is active
301 {
302 static long cnt[16] = { 50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50};
303 static int i = 100;
304 int id = ((struct vcpu *)current)->domain->domain_id & 0xf;
305 if (!cnt[id]--) { printk("%x",id); cnt[id] = 500000; }
306 if (!i--) { printk("+"); i = 1000000; }
307 }
309 if (VMX_DOMAIN(current)){
310 // vtm_domain_in(current);
311 vmx_load_all_rr(current);
312 }else{
313 extern char ia64_ivt;
314 ia64_set_iva(&ia64_ivt);
315 if (!is_idle_domain(current->domain)) {
316 ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) |
317 VHPT_ENABLED);
318 load_region_regs(current);
319 vcpu_load_kernel_regs(current);
320 if (vcpu_timer_expired(current))
321 vcpu_pend_timer(current);
322 }else {
323 /* When switching to idle domain, only need to disable vhpt
324 * walker. Then all accesses happen within idle context will
325 * be handled by TR mapping and identity mapping.
326 */
327 pta = ia64_get_pta();
328 ia64_set_pta(pta & ~VHPT_ENABLED);
329 }
330 }
332 local_irq_restore(spsr);
333 context_saved(prev);
334 }
336 void continue_running(struct vcpu *same)
337 {
338 /* nothing to do */
339 }
341 void arch_dump_domain_info(struct domain *d)
342 {
343 }
345 void panic_domain(struct pt_regs *regs, const char *fmt, ...)
346 {
347 va_list args;
348 char buf[128];
349 struct vcpu *v = current;
350 // static volatile int test = 1; // so can continue easily in debug
351 // extern spinlock_t console_lock;
352 // unsigned long flags;
354 loop:
355 printf("$$$$$ PANIC in domain %d (k6=0x%lx): ",
356 v->domain->domain_id,
357 __get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT]);
358 va_start(args, fmt);
359 (void)vsnprintf(buf, sizeof(buf), fmt, args);
360 va_end(args);
361 printf(buf);
362 if (regs) show_registers(regs);
363 if (regs) {
364 debugger_trap_fatal(0 /* don't care */, regs);
365 } else {
366 debugger_trap_immediate();
367 }
368 domain_pause_by_systemcontroller(current->domain);
369 v->domain->shutdown_code = SHUTDOWN_crash;
370 set_bit(_DOMF_shutdown, &v->domain->domain_flags);
371 if (v->domain->domain_id == 0) {
372 int i = 1000000000L;
373 // if domain0 crashes, just periodically print out panic
374 // message to make post-mortem easier
375 while(i--);
376 goto loop;
377 }
378 }
380 /* FIXME: for the forseeable future, all cpu's that enable VTi have split
381 * caches and all cpu's that have split caches enable VTi. This may
382 * eventually be untrue though. */
383 #define cpu_has_split_cache vmx_enabled
384 extern unsigned int vmx_enabled;
386 void sync_split_caches(void)
387 {
388 unsigned long ret, progress = 0;
390 if (cpu_has_split_cache) {
391 /* Sync d/i cache conservatively */
392 ret = ia64_pal_cache_flush(4, 0, &progress, NULL);
393 if ((ret!=PAL_STATUS_SUCCESS)&& (ret!=PAL_STATUS_UNIMPLEMENTED))
394 printk("PAL CACHE FLUSH failed\n");
395 else printk("Sync i/d cache for guest SUCC\n");
396 }
397 else printk("sync_split_caches ignored for CPU with no split cache\n");
398 }
400 ///////////////////////////////
401 // from arch/x86/mm.c
402 ///////////////////////////////
404 #ifdef VERBOSE
405 #define MEM_LOG(_f, _a...) \
406 printk("DOM%u: (file=mm.c, line=%d) " _f "\n", \
407 current->domain->domain_id , __LINE__ , ## _a )
408 #else
409 #define MEM_LOG(_f, _a...) ((void)0)
410 #endif
412 void cleanup_writable_pagetable(struct domain *d)
413 {
414 return;
415 }
417 void put_page_type(struct page_info *page)
418 {
419 u32 nx, x, y = page->u.inuse.type_info;
421 again:
422 do {
423 x = y;
424 nx = x - 1;
426 ASSERT((x & PGT_count_mask) != 0);
428 /*
429 * The page should always be validated while a reference is held. The
430 * exception is during domain destruction, when we forcibly invalidate
431 * page-table pages if we detect a referential loop.
432 * See domain.c:relinquish_list().
433 */
434 ASSERT((x & PGT_validated) ||
435 test_bit(_DOMF_dying, &page_get_owner(page)->domain_flags));
437 if ( unlikely((nx & PGT_count_mask) == 0) )
438 {
439 /* Record TLB information for flush later. Races are harmless. */
440 page->tlbflush_timestamp = tlbflush_current_time();
442 if ( unlikely((nx & PGT_type_mask) <= PGT_l4_page_table) &&
443 likely(nx & PGT_validated) )
444 {
445 /*
446 * Page-table pages must be unvalidated when count is zero. The
447 * 'free' is safe because the refcnt is non-zero and validated
448 * bit is clear => other ops will spin or fail.
449 */
450 if ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x,
451 x & ~PGT_validated)) != x) )
452 goto again;
453 /* We cleared the 'valid bit' so we do the clean up. */
454 free_page_type(page, x);
455 /* Carry on, but with the 'valid bit' now clear. */
456 x &= ~PGT_validated;
457 nx &= ~PGT_validated;
458 }
459 }
460 else if ( unlikely(((nx & (PGT_pinned | PGT_count_mask)) ==
461 (PGT_pinned | 1)) &&
462 ((nx & PGT_type_mask) != PGT_writable_page)) )
463 {
464 /* Page is now only pinned. Make the back pointer mutable again. */
465 nx |= PGT_va_mutable;
466 }
467 }
468 while ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x) );
469 }
472 int get_page_type(struct page_info *page, u32 type)
473 {
474 u32 nx, x, y = page->u.inuse.type_info;
476 again:
477 do {
478 x = y;
479 nx = x + 1;
480 if ( unlikely((nx & PGT_count_mask) == 0) )
481 {
482 MEM_LOG("Type count overflow on pfn %lx", page_to_mfn(page));
483 return 0;
484 }
485 else if ( unlikely((x & PGT_count_mask) == 0) )
486 {
487 if ( (x & (PGT_type_mask|PGT_va_mask)) != type )
488 {
489 if ( (x & PGT_type_mask) != (type & PGT_type_mask) )
490 {
491 /*
492 * On type change we check to flush stale TLB
493 * entries. This may be unnecessary (e.g., page
494 * was GDT/LDT) but those circumstances should be
495 * very rare.
496 */
497 cpumask_t mask =
498 page_get_owner(page)->domain_dirty_cpumask;
499 tlbflush_filter(mask, page->tlbflush_timestamp);
501 if ( unlikely(!cpus_empty(mask)) )
502 {
503 perfc_incrc(need_flush_tlb_flush);
504 flush_tlb_mask(mask);
505 }
506 }
508 /* We lose existing type, back pointer, and validity. */
509 nx &= ~(PGT_type_mask | PGT_va_mask | PGT_validated);
510 nx |= type;
512 /* No special validation needed for writable pages. */
513 /* Page tables and GDT/LDT need to be scanned for validity. */
514 if ( type == PGT_writable_page )
515 nx |= PGT_validated;
516 }
517 }
518 else
519 {
520 if ( unlikely((x & (PGT_type_mask|PGT_va_mask)) != type) )
521 {
522 if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) )
523 {
524 if ( current->domain == page_get_owner(page) )
525 {
526 /*
527 * This ensures functions like set_gdt() see up-to-date
528 * type info without needing to clean up writable p.t.
529 * state on the fast path.
530 */
531 LOCK_BIGLOCK(current->domain);
532 cleanup_writable_pagetable(current->domain);
533 y = page->u.inuse.type_info;
534 UNLOCK_BIGLOCK(current->domain);
535 /* Can we make progress now? */
536 if ( ((y & PGT_type_mask) == (type & PGT_type_mask)) ||
537 ((y & PGT_count_mask) == 0) )
538 goto again;
539 }
540 if ( ((x & PGT_type_mask) != PGT_l2_page_table) ||
541 ((type & PGT_type_mask) != PGT_l1_page_table) )
542 MEM_LOG("Bad type (saw %08x != exp %08x) "
543 "for mfn %016lx (pfn %016lx)",
544 x, type, page_to_mfn(page),
545 get_gpfn_from_mfn(page_to_mfn(page)));
546 return 0;
547 }
548 else if ( (x & PGT_va_mask) == PGT_va_mutable )
549 {
550 /* The va backpointer is mutable, hence we update it. */
551 nx &= ~PGT_va_mask;
552 nx |= type; /* we know the actual type is correct */
553 }
554 else if ( ((type & PGT_va_mask) != PGT_va_mutable) &&
555 ((type & PGT_va_mask) != (x & PGT_va_mask)) )
556 {
557 #ifdef CONFIG_X86_PAE
558 /* We use backptr as extra typing. Cannot be unknown. */
559 if ( (type & PGT_type_mask) == PGT_l2_page_table )
560 return 0;
561 #endif
562 /* This table is possibly mapped at multiple locations. */
563 nx &= ~PGT_va_mask;
564 nx |= PGT_va_unknown;
565 }
566 }
567 if ( unlikely(!(x & PGT_validated)) )
568 {
569 /* Someone else is updating validation of this page. Wait... */
570 while ( (y = page->u.inuse.type_info) == x )
571 cpu_relax();
572 goto again;
573 }
574 }
575 }
576 while ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x) );
578 if ( unlikely(!(nx & PGT_validated)) )
579 {
580 /* Try to validate page type; drop the new reference on failure. */
581 if ( unlikely(!alloc_page_type(page, type)) )
582 {
583 MEM_LOG("Error while validating mfn %lx (pfn %lx) for type %08x"
584 ": caf=%08x taf=%" PRtype_info,
585 page_to_mfn(page), get_gpfn_from_mfn(page_to_mfn(page)),
586 type, page->count_info, page->u.inuse.type_info);
587 /* Noone else can get a reference. We hold the only ref. */
588 page->u.inuse.type_info = 0;
589 return 0;
590 }
592 /* Noone else is updating simultaneously. */
593 __set_bit(_PGT_validated, &page->u.inuse.type_info);
594 }
596 return 1;
597 }