[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Merged.
# HG changeset patch # User emellor@xxxxxxxxxxxxxxxxxxxxxx # Node ID a38c292e8390370ec9473a6444bd63be7e437afe # Parent 40bb46f599d93a8605740bc5800d5e61d8cc1198 # Parent 1f87f39aa0e19527976780a9aab473d9fe191b8a Merged. diff -r 40bb46f599d9 -r a38c292e8390 .hgignore --- a/.hgignore Tue Jan 10 15:21:00 2006 +++ b/.hgignore Tue Jan 24 16:54:34 2006 @@ -163,6 +163,7 @@ ^tools/xenstore/xenstore-read$ ^tools/xenstore/xenstore-rm$ ^tools/xenstore/xenstore-write$ +^tools/xenstore/xenstore-ls$ ^tools/xenstore/xenstored$ ^tools/xenstore/xenstored_test$ ^tools/xenstore/xs_crashme$ @@ -171,7 +172,6 @@ ^tools/xenstore/xs_tdb_dump$ ^tools/xenstore/xs_test$ ^tools/xenstore/xs_watch_stress$ -^tools/xenstore/xsls$ ^tools/xentrace/setsize$ ^tools/xentrace/tbctl$ ^tools/xentrace/xenctx$ diff -r 40bb46f599d9 -r a38c292e8390 docs/man/xm.pod.1 --- a/docs/man/xm.pod.1 Tue Jan 10 15:21:00 2006 +++ b/docs/man/xm.pod.1 Tue Jan 24 16:54:34 2006 @@ -374,7 +374,7 @@ configured VCPU count is an error. Trying to set-vcpus to < 1 will be quietly ignored. -=item B<vpcu-list> I<[domain-id]> +=item B<vcpu-list> I<[domain-id]> Lists VCPU information for a specific domain. If no domain is specified, VCPU information for all domains will be provided. diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_ia64 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_ia64 Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_ia64 Tue Jan 24 16:54:34 2006 @@ -91,8 +91,7 @@ # CONFIG_IA64_PAGE_SIZE_64KB is not set CONFIG_IA64_L1_CACHE_SHIFT=7 # CONFIG_NUMA is not set -CONFIG_VIRTUAL_MEM_MAP=y -CONFIG_HOLES_IN_ZONE=y +CONFIG_VIRTUAL_MEM_MAP=n CONFIG_IA64_CYCLONE=y CONFIG_IOSAPIC=y CONFIG_FORCE_MAX_ZONEORDER=18 diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S Tue Jan 24 16:54:34 2006 @@ -76,7 +76,9 @@ DF_MASK = 0x00000400 NT_MASK = 0x00004000 VM_MASK = 0x00020000 - +/* Pseudo-eflags. */ +NMI_MASK = 0x80000000 + /* Offsets into shared_info_t. */ #define evtchn_upcall_pending /* 0 */ #define evtchn_upcall_mask 1 @@ -305,8 +307,8 @@ je ldt_ss # returning to user-space with LDT SS #endif /* XEN */ restore_nocheck: - testl $VM_MASK, EFLAGS(%esp) - jnz resume_vm86 + testl $(VM_MASK|NMI_MASK), EFLAGS(%esp) + jnz hypervisor_iret movb EVENT_MASK(%esp), %al notb %al # %al == ~saved_mask XEN_GET_VCPU_INFO(%esi) @@ -328,11 +330,11 @@ .long 1b,iret_exc .previous -resume_vm86: - XEN_UNBLOCK_EVENTS(%esi) +hypervisor_iret: + andl $~NMI_MASK, EFLAGS(%esp) RESTORE_REGS movl %eax,(%esp) - movl $__HYPERVISOR_switch_vm86,%eax + movl $__HYPERVISOR_iret,%eax int $0x82 ud2 @@ -691,6 +693,15 @@ call do_debug jmp ret_from_exception +ENTRY(nmi) + pushl %eax + SAVE_ALL + xorl %edx,%edx # zero error code + movl %esp,%eax # pt_regs pointer + call do_nmi + orl $NMI_MASK, EFLAGS(%esp) + jmp restore_all + #if 0 /* XEN */ /* * NMI is doubly nasty. It can happen _while_ we're handling diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/i386/kernel/io_apic.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/io_apic.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/io_apic.c Tue Jan 24 16:54:34 2006 @@ -622,9 +622,11 @@ try_to_freeze(PF_FREEZE); if (time_after(jiffies, prev_balance_time+balanced_irq_interval)) { + preempt_disable(); do_irq_balance(); prev_balance_time = jiffies; time_remaining = balanced_irq_interval; + preempt_enable(); } } return 0; diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c Tue Jan 24 16:54:34 2006 @@ -506,18 +506,11 @@ static void io_check_error(unsigned char reason, struct pt_regs * regs) { - unsigned long i; - printk("NMI: IOCK error (debug interrupt?)\n"); show_registers(regs); /* Re-enable the IOCK line, wait for a few seconds */ - reason = (reason & 0xf) | 8; - outb(reason, 0x61); - i = 2000; - while (--i) udelay(1000); - reason &= ~8; - outb(reason, 0x61); + clear_io_check_error(reason); } static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) @@ -647,12 +640,6 @@ do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL); } #endif - -static inline void conditional_sti(struct pt_regs *regs) -{ - if (regs->eflags & (X86_EFLAGS_IF|VM_MASK)) - local_irq_enable(); -} /* * Our handling of the processor debug registers is non-trivial. @@ -686,9 +673,9 @@ if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, SIGTRAP) == NOTIFY_STOP) return; - /* It's safe to allow irq's after DR6 has been saved */ - conditional_sti(regs); + if (regs->eflags & X86_EFLAGS_IF) + local_irq_enable(); /* Mask out spurious debug traps due to lazy DR7 setting */ if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/i386/mm/init.c --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c Tue Jan 24 16:54:34 2006 @@ -65,7 +65,7 @@ { pud_t *pud; pmd_t *pmd_table; - + #ifdef CONFIG_X86_PAE pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); make_lowmem_page_readonly(pmd_table); diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/kernel/reboot.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Tue Jan 24 16:54:34 2006 @@ -290,15 +290,15 @@ const char **vec, unsigned int len) { char *str; - struct xenbus_transaction *xbt; + xenbus_transaction_t xbt; int err; if (shutting_down != SHUTDOWN_INVALID) return; again: - xbt = xenbus_transaction_start(); - if (IS_ERR(xbt)) + err = xenbus_transaction_start(&xbt); + if (err) return; str = (char *)xenbus_read(xbt, "control", "shutdown", NULL); /* Ignore read errors and empty reads. */ @@ -339,12 +339,12 @@ unsigned int len) { char sysrq_key = '\0'; - struct xenbus_transaction *xbt; + xenbus_transaction_t xbt; int err; again: - xbt = xenbus_transaction_start(); - if (IS_ERR(xbt)) + err = xenbus_transaction_start(&xbt); + if (err) return; if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) { printk(KERN_ERR "Unable to read sysrq code in " diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c Tue Jan 24 16:54:34 2006 @@ -526,7 +526,7 @@ unsigned long __init e820_end_of_ram(void) { - unsigned long max_end_pfn; + unsigned long max_end_pfn; if (xen_override_max_pfn == 0) { max_end_pfn = xen_start_info->nr_pages; @@ -612,7 +612,7 @@ { end_user_pfn = memparse(p, from); end_user_pfn >>= PAGE_SHIFT; - xen_override_max_pfn = (unsigned long) end_user_pfn; + xen_override_max_pfn = (unsigned long) end_user_pfn; } /* diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S Tue Jan 24 16:54:34 2006 @@ -57,7 +57,7 @@ #ifndef CONFIG_PREEMPT #define retint_kernel retint_restore_args #endif - + /* * C code is not supposed to know about undefined top of stack. Every time * a C function with an pt_regs argument is called from the SYSCALL based @@ -65,7 +65,7 @@ * RESTORE_TOP_OF_STACK syncs the syscall state after any possible ptregs * manipulation. */ - + /* %rsp:at FRAMEEND */ .macro FIXUP_TOP_OF_STACK tmp movq $__USER_CS,CS(%rsp) @@ -121,19 +121,19 @@ .endm /* - * Must be consistent with the definition in arch_x86_64.h: - * struct switch_to_user { + * Must be consistent with the definition in arch-x86_64.h: + * struct iret_context { * u64 rax, r11, rcx, flags, rip, cs, rflags, rsp, ss; * }; * #define VGCF_IN_SYSCALL (1<<8) */ - .macro SWITCH_TO_USER flag + .macro HYPERVISOR_IRET flag subq $8*4,%rsp # reuse rip, cs, rflags, rsp, ss in the stack movq %rax,(%rsp) movq %r11,1*8(%rsp) movq %rcx,2*8(%rsp) # we saved %rcx upon exceptions movq $\flag,3*8(%rsp) - movq $__HYPERVISOR_switch_to_user,%rax + movq $__HYPERVISOR_iret,%rax syscall .endm @@ -225,7 +225,7 @@ jnz sysret_careful XEN_UNBLOCK_EVENTS(%rsi) RESTORE_ARGS 0,8,0 - SWITCH_TO_USER VGCF_IN_SYSCALL + HYPERVISOR_IRET VGCF_IN_SYSCALL /* Handle reschedules */ /* edx: work, edi: workmask */ @@ -417,7 +417,6 @@ RESTORE_REST jmp int_ret_from_sys_call CFI_ENDPROC - /* * Interrupt entry/exit. @@ -479,7 +478,7 @@ orb $3,1*8(%rsp) iretq user_mode: - SWITCH_TO_USER 0 + HYPERVISOR_IRET 0 /* edi: workmask, edx: work */ retint_careful: @@ -720,6 +719,18 @@ call evtchn_do_upcall jmp error_exit +#ifdef CONFIG_X86_LOCAL_APIC +ENTRY(nmi) + zeroentry do_nmi_callback +ENTRY(do_nmi_callback) + addq $8, %rsp + call do_nmi + RESTORE_REST + XEN_BLOCK_EVENTS(%rsi) + GET_THREAD_INFO(%rcx) + jmp retint_restore_args +#endif + ALIGN restore_all_enable_events: XEN_UNBLOCK_EVENTS(%rsi) # %rsi is already set up... @@ -734,7 +745,7 @@ orb $3,1*8(%rsp) iretq crit_user_mode: - SWITCH_TO_USER 0 + HYPERVISOR_IRET 0 14: XEN_LOCKED_BLOCK_EVENTS(%rsi) XEN_PUT_VCPU_INFO(%rsi) diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head64.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head64.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head64.c Tue Jan 24 16:54:34 2006 @@ -68,13 +68,13 @@ static void __init setup_boot_cpu_data(void) { - int dummy, eax; + unsigned int dummy, eax; /* get vendor info */ - cpuid(0, &boot_cpu_data.cpuid_level, - (int *)&boot_cpu_data.x86_vendor_id[0], - (int *)&boot_cpu_data.x86_vendor_id[8], - (int *)&boot_cpu_data.x86_vendor_id[4]); + cpuid(0, (unsigned int *)&boot_cpu_data.cpuid_level, + (unsigned int *)&boot_cpu_data.x86_vendor_id[0], + (unsigned int *)&boot_cpu_data.x86_vendor_id[8], + (unsigned int *)&boot_cpu_data.x86_vendor_id[4]); /* get cpu type */ cpuid(1, &eax, &dummy, &dummy, @@ -109,7 +109,6 @@ if (s != NULL) setup_early_printk(s); #endif - #ifdef CONFIG_DISCONTIGMEM s = strstr(saved_command_line, "numa="); if (s != NULL) diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/io_apic.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/io_apic.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/io_apic.c Tue Jan 24 16:54:34 2006 @@ -255,10 +255,8 @@ return 1; } - __setup("noapic", disable_ioapic_setup); __setup("apic", enable_ioapic_setup); - #include <asm/pci-direct.h> #include <linux/pci_ids.h> @@ -1146,6 +1144,7 @@ v = inb(0x4d1) << 8 | inb(0x4d0); printk(KERN_DEBUG "... PIC ELCR: %04x\n", v); } + #endif /* 0 */ #else @@ -1191,6 +1190,7 @@ * Clear the IO-APIC before rebooting: */ clear_IO_APIC(); + #ifndef CONFIG_XEN disconnect_bsp_APIC(); #endif @@ -1202,6 +1202,7 @@ * * by Matt Domsch <Matt_Domsch@xxxxxxxx> Tue Dec 21 12:25:05 CST 1999 */ + #ifndef CONFIG_XEN static void __init setup_ioapic_ids_from_mpc (void) { diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/irq.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/irq.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/irq.c Tue Jan 24 16:54:34 2006 @@ -9,18 +9,15 @@ * x86_64-specific irq controller code. (e.g. i8259.c and * io_apic.c.) */ + +#include <linux/kernel_stat.h> +#include <linux/interrupt.h> +#include <linux/seq_file.h> +#include <linux/module.h> #include <asm/uaccess.h> -#include <linux/module.h> -#include <linux/seq_file.h> -#include <linux/interrupt.h> -#include <linux/kernel_stat.h> - -/* - * Interrupt statistics: - */ +#include <asm/io_apic.h> atomic_t irq_err_count; - #ifdef CONFIG_X86_IO_APIC #ifdef APIC_MISMATCH_DEBUG atomic_t irq_mis_count; diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/ldt.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/ldt.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/ldt.c Tue Jan 24 16:54:34 2006 @@ -62,6 +62,7 @@ if (reload) { #ifdef CONFIG_SMP cpumask_t mask; + preempt_disable(); #endif make_pages_readonly(pc->ldt, (pc->size * LDT_ENTRY_SIZE) / @@ -201,6 +202,7 @@ struct user_desc ldt_info; error = -EINVAL; + if (bytecount != sizeof(ldt_info)) goto out; error = -EFAULT; diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c Tue Jan 24 16:54:34 2006 @@ -62,6 +62,7 @@ #include <asm-xen/xen-public/physdev.h> #include "setup_arch_pre.h" #include <asm/hypervisor.h> +#include <asm-xen/xen-public/nmi.h> #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) #define PFN_PHYS(x) ((x) << PAGE_SHIFT) #define end_pfn_map end_pfn @@ -304,7 +305,6 @@ } #endif - static __init void parse_cmdline_early (char ** cmdline_p) { char c = ' ', *to = command_line, *from = COMMAND_LINE; @@ -379,6 +379,7 @@ acpi_skip_timer_override = 1; #endif #endif + #ifndef CONFIG_XEN if (!memcmp(from, "nolapic", 7) || !memcmp(from, "disableapic", 11)) @@ -391,7 +392,8 @@ skip_ioapic_setup = 0; ioapic_force = 1; } -#endif +#endif + if (!memcmp(from, "mem=", 4)) parse_memopt(from+4, &from); @@ -588,7 +590,7 @@ HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables); - ARCH_SETUP + ARCH_SETUP #else ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); drive_info = DRIVE_INFO; @@ -612,7 +614,7 @@ init_mm.end_code = (unsigned long) &_etext; init_mm.end_data = (unsigned long) &_edata; #ifdef CONFIG_XEN - init_mm.brk = start_pfn << PAGE_SHIFT; + init_mm.brk = start_pfn << PAGE_SHIFT; #else init_mm.brk = (unsigned long) &_end; @@ -667,7 +669,6 @@ /* reserve ebda region */ reserve_ebda_region(); #endif - #ifdef CONFIG_SMP /* @@ -790,8 +791,6 @@ } - - if ( ! (xen_start_info->flags & SIF_INITDOMAIN)) { acpi_disabled = 1; @@ -835,7 +834,7 @@ * and also for regions reported as reserved by the e820. */ probe_roms(); - e820_reserve_resources(); + e820_reserve_resources(); #endif request_resource(&iomem_resource, &video_ram_resource); diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c Tue Jan 24 16:54:34 2006 @@ -33,6 +33,7 @@ #ifdef CONFIG_XEN #include <asm/hypervisor.h> #endif + char x86_boot_params[BOOT_PARAM_SIZE] __initdata = {0,}; cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE; @@ -165,7 +166,6 @@ } #endif - void pda_init(int cpu) { struct x8664_pda *pda = &cpu_pda[cpu]; @@ -175,9 +175,10 @@ #ifndef CONFIG_XEN wrmsrl(MSR_GS_BASE, cpu_pda + cpu); #else - HYPERVISOR_set_segment_base(SEGBASE_GS_KERNEL, - (unsigned long)(cpu_pda + cpu)); -#endif + HYPERVISOR_set_segment_base(SEGBASE_GS_KERNEL, + (unsigned long)(cpu_pda + cpu)); +#endif + pda->me = pda; pda->cpunumber = cpu; pda->irqcount = -1; @@ -201,6 +202,7 @@ } switch_pt(); + pda->irqstackptr += IRQSTACKSIZE-64; } diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smp.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smp.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smp.c Tue Jan 24 16:54:34 2006 @@ -30,8 +30,9 @@ #include <asm/apicdef.h> #ifdef CONFIG_XEN #include <asm-xen/evtchn.h> - -#else +#endif + +#ifndef CONFIG_XEN /* * Smarter SMP flushing macros. * c/o Linus Torvalds. diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c Tue Jan 24 16:54:34 2006 @@ -559,9 +559,11 @@ printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n"); printk("You probably have a hardware problem with your RAM chips\n"); +#if 0 /* XEN */ /* Clear and disable the memory parity error line. */ reason = (reason & 0xf) | 4; outb(reason, 0x61); +#endif /* XEN */ } static void io_check_error(unsigned char reason, struct pt_regs * regs) @@ -569,12 +571,14 @@ printk("NMI: IOCK error (debug interrupt?)\n"); show_registers(regs); +#if 0 /* XEN */ /* Re-enable the IOCK line, wait for a few seconds */ reason = (reason & 0xf) | 8; outb(reason, 0x61); mdelay(2000); reason &= ~8; outb(reason, 0x61); +#endif /* XEN */ } static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) @@ -890,7 +894,6 @@ asmlinkage void math_state_restore(void) { struct task_struct *me = current; - /* clts(); */ /* 'clts' is done for us by Xen during virtual trap. */ if (!used_math()) diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c Tue Jan 24 16:54:34 2006 @@ -153,7 +153,6 @@ pgd = (pgd_t *)per_cpu(cur_pgd, smp_processor_id()); preempt_enable(); pgd += pgd_index(address); - printk("PGD %lx ", pgd_val(*pgd)); if (bad_address(pgd)) goto bad; if (!pgd_present(*pgd)) goto ret; @@ -258,7 +257,6 @@ pgd = (pgd_t *)per_cpu(cur_pgd, smp_processor_id()); preempt_enable(); pgd += pgd_index(address); - pgd_ref = pgd_offset_k(address); if (pgd_none(*pgd_ref)) return -1; diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c --- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c Tue Jan 24 16:54:34 2006 @@ -40,14 +40,14 @@ #include <asm/proto.h> #include <asm/smp.h> +#ifndef Dprintk +#define Dprintk(x...) +#endif + extern unsigned long *contiguous_bitmap; #if defined(CONFIG_SWIOTLB) extern void swiotlb_init(void); -#endif - -#ifndef Dprintk -#define Dprintk(x...) #endif extern char _stext[]; @@ -200,9 +200,9 @@ static inline pud_t *pud_offset_u(unsigned long address) { - pud_t *pud = level3_user_pgt; - - return pud + pud_index(address); + pud_t *pud = level3_user_pgt; + + return pud + pud_index(address); } static void set_pte_phys(unsigned long vaddr, @@ -215,34 +215,27 @@ Dprintk("set_pte_phys %lx to %lx\n", vaddr, phys); - pgd = (user_mode ? pgd_offset_u(vaddr) : pgd_offset_k(vaddr)); - + pgd = (user_mode ? pgd_offset_u(vaddr) : pgd_offset_k(vaddr)); if (pgd_none(*pgd)) { printk("PGD FIXMAP MISSING, it should be setup in head.S!\n"); return; } - - pud = (user_mode ? pud_offset_u(vaddr) : pud_offset(pgd, vaddr)); - + pud = (user_mode ? pud_offset_u(vaddr) : pud_offset(pgd, vaddr)); if (pud_none(*pud)) { pmd = (pmd_t *) spp_getpage(); - - make_page_readonly(pmd); - xen_pmd_pin(__pa(pmd)); + make_page_readonly(pmd); + xen_pmd_pin(__pa(pmd)); set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER)); if (pmd != pmd_offset(pud, 0)) { printk("PAGETABLE BUG #01! %p <-> %p\n", pmd, pmd_offset(pud,0)); return; } } - pmd = pmd_offset(pud, vaddr); - if (pmd_none(*pmd)) { pte = (pte_t *) spp_getpage(); - make_page_readonly(pte); - - xen_pte_pin(__pa(pte)); + make_page_readonly(pte); + xen_pte_pin(__pa(pte)); set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER)); if (pte != pte_offset_kernel(pmd, 0)) { printk("PAGETABLE BUG #02!\n"); @@ -252,11 +245,10 @@ new_pte = pfn_pte(phys >> PAGE_SHIFT, prot); pte = pte_offset_kernel(pmd, vaddr); - if (!pte_none(*pte) && pte_val(*pte) != (pte_val(new_pte) & __supported_pte_mask)) pte_ERROR(*pte); - set_pte(pte, new_pte); + set_pte(pte, new_pte); /* * It's enough to flush this one mapping. @@ -284,11 +276,11 @@ if (pud_none(*pud)) { pmd = (pmd_t *) spp_getpage(); - make_page_readonly(pmd); - xen_pmd_pin(__pa(pmd)); + make_page_readonly(pmd); + xen_pmd_pin(__pa(pmd)); set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER)); - + if (pmd != pmd_offset(pud, 0)) { printk("PAGETABLE BUG #01! %p <-> %p\n", pmd, pmd_offset(pud,0)); return; @@ -298,8 +290,8 @@ if (pmd_none(*pmd)) { pte = (pte_t *) spp_getpage(); - make_page_readonly(pte); - xen_pte_pin(__pa(pte)); + make_page_readonly(pte); + xen_pte_pin(__pa(pte)); set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER)); if (pte != pte_offset_kernel(pmd, 0)) { @@ -311,12 +303,12 @@ new_pte = pfn_pte_ma(phys >> PAGE_SHIFT, prot); pte = pte_offset_kernel(pmd, vaddr); - /* - * Note that the pte page is already RO, thus we want to use - * xen_l1_entry_update(), not set_pte(). - */ - xen_l1_entry_update(pte, - pfn_pte_ma(phys >> PAGE_SHIFT, prot)); + /* + * Note that the pte page is already RO, thus we want to use + * xen_l1_entry_update(), not set_pte(). + */ + xen_l1_entry_update(pte, + pfn_pte_ma(phys >> PAGE_SHIFT, prot)); /* * It's enough to flush this one mapping. @@ -347,7 +339,6 @@ } } - /* * At this point it only supports vsyscall area. */ @@ -360,18 +351,18 @@ return; } - set_pte_phys(address, phys, prot, SET_FIXMAP_USER); + set_pte_phys(address, phys, prot, SET_FIXMAP_USER); } unsigned long __initdata table_start, tables_space; unsigned long get_machine_pfn(unsigned long addr) { - pud_t* pud = pud_offset_k(addr); - pmd_t* pmd = pmd_offset(pud, addr); - pte_t *pte = pte_offset_kernel(pmd, addr); - - return pte_mfn(*pte); + pud_t* pud = pud_offset_k(addr); + pmd_t* pmd = pmd_offset(pud, addr); + pte_t *pte = pte_offset_kernel(pmd, addr); + + return pte_mfn(*pte); } static __init void *alloc_static_page(unsigned long *phys) @@ -411,12 +402,11 @@ static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned long end) { - long i, j, k; - unsigned long paddr; + long i, j, k; + unsigned long paddr; i = pud_index(address); pud = pud + i; - for (; i < PTRS_PER_PUD; pud++, i++) { unsigned long pmd_phys; pmd_t *pmd; @@ -429,38 +419,37 @@ } pmd = alloc_static_page(&pmd_phys); - early_make_page_readonly(pmd); - xen_pmd_pin(pmd_phys); + early_make_page_readonly(pmd); + xen_pmd_pin(pmd_phys); set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE)); - for (j = 0; j < PTRS_PER_PMD; pmd++, j++) { - unsigned long pte_phys; - pte_t *pte, *pte_save; + unsigned long pte_phys; + pte_t *pte, *pte_save; if (paddr >= end) { for (; j < PTRS_PER_PMD; j++, pmd++) set_pmd(pmd, __pmd(0)); break; } - pte = alloc_static_page(&pte_phys); - pte_save = pte; - for (k = 0; k < PTRS_PER_PTE; pte++, k++, paddr += PTE_SIZE) { - if ((paddr >= end) || - ((paddr >> PAGE_SHIFT) >= - xen_start_info->nr_pages)) { - __set_pte(pte, __pte(0)); - continue; - } - if (make_readonly(paddr)) { - __set_pte(pte, - __pte(paddr | (_KERNPG_TABLE & ~_PAGE_RW))); - continue; - } - __set_pte(pte, __pte(paddr | _KERNPG_TABLE)); - } - pte = pte_save; - early_make_page_readonly(pte); - xen_pte_pin(pte_phys); + pte = alloc_static_page(&pte_phys); + pte_save = pte; + for (k = 0; k < PTRS_PER_PTE; pte++, k++, paddr += PTE_SIZE) { + if ((paddr >= end) || + ((paddr >> PAGE_SHIFT) >= + xen_start_info->nr_pages)) { + __set_pte(pte, __pte(0)); + continue; + } + if (make_readonly(paddr)) { + __set_pte(pte, + __pte(paddr | (_KERNPG_TABLE & ~_PAGE_RW))); + continue; + } + __set_pte(pte, __pte(paddr | _KERNPG_TABLE)); + } + pte = pte_save; + early_make_page_readonly(pte); + xen_pte_pin(pte_phys); set_pmd(pmd, __pmd(pte_phys | _KERNPG_TABLE)); } } @@ -506,7 +495,7 @@ level3_kernel_pgt[pud_index(__START_KERNEL_map)] = __pud(__pa_symbol(level2_kernel_pgt) | _KERNPG_TABLE | _PAGE_USER); - memcpy((void *)level2_kernel_pgt, page, PAGE_SIZE); + memcpy((void *)level2_kernel_pgt, page, PAGE_SIZE); early_make_page_readonly(init_level4_pgt); early_make_page_readonly(init_level4_user_pgt); @@ -618,7 +607,7 @@ void zap_low_mappings(void) { - /* this is not required for Xen */ + /* this is not required for Xen */ #if 0 swap_low_mappings(); #endif @@ -629,11 +618,11 @@ { { unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; - /* unsigned int max_dma; */ - /* max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; */ - /* if (end_pfn < max_dma) */ + /* unsigned int max_dma; */ + /* max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; */ + /* if (end_pfn < max_dma) */ zones_size[ZONE_DMA] = end_pfn; -#if 0 +#if 0 else { zones_size[ZONE_DMA] = max_dma; zones_size[ZONE_NORMAL] = end_pfn - max_dma; @@ -642,16 +631,16 @@ free_area_init(zones_size); } - set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info); - HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); - - memset(empty_zero_page, 0, sizeof(empty_zero_page)); + set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info); + HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); + + memset(empty_zero_page, 0, sizeof(empty_zero_page)); init_mm.context.pinned = 1; #ifdef CONFIG_XEN_PHYSDEV_ACCESS { int i; - /* Setup mapping of lower 1st MB */ + /* Setup mapping of lower 1st MB */ for (i = 0; i < NR_FIX_ISAMAPS; i++) if (xen_start_info->flags & SIF_PRIVILEGED) set_fixmap(FIX_ISAMAP_BEGIN - i, i * PAGE_SIZE); @@ -701,7 +690,7 @@ static inline int page_is_ram (unsigned long pagenr) { - return 1; + return 1; } static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules, @@ -790,10 +779,10 @@ void free_initmem(void) { #ifdef __DO_LATER__ - /* - * Some pages can be pinned, but some are not. Unpinning such pages - * triggers BUG(). - */ + /* + * Some pages can be pinned, but some are not. Unpinning such pages + * triggers BUG(). + */ unsigned long addr; addr = (unsigned long)(&__init_begin); @@ -801,12 +790,12 @@ ClearPageReserved(virt_to_page(addr)); set_page_count(virt_to_page(addr), 1); memset((void *)(addr & ~(PAGE_SIZE-1)), 0xcc, PAGE_SIZE); - xen_pte_unpin(__pa(addr)); - make_page_writable(__va(__pa(addr))); - /* - * Make pages from __PAGE_OFFSET address as well - */ - make_page_writable((void *)addr); + xen_pte_unpin(__pa(addr)); + make_page_writable(__va(__pa(addr))); + /* + * Make pages from __PAGE_OFFSET address as well + */ + make_page_writable((void *)addr); free_page(addr); totalram_pages++; } @@ -856,7 +845,7 @@ if (pgd_none(*pgd)) return 0; - pud = pud_offset_k(addr); + pud = pud_offset_k(addr); if (pud_none(*pud)) return 0; diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Tue Jan 24 16:54:34 2006 @@ -544,7 +544,7 @@ kfree(pending_grant_handles); kfree(pending_vaddrs); printk("%s: out of memory\n", __FUNCTION__); - return -1; + return -ENOMEM; } blkif_interface_init(); diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/blkback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Tue Jan 24 16:54:34 2006 @@ -19,16 +19,8 @@ #include <asm-xen/gnttab.h> #include <asm-xen/driver_util.h> -#if 0 -#define ASSERT(_p) \ - if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \ - __LINE__, __FILE__); *(int*)0=0; } -#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \ - __FILE__ , __LINE__ , ## _a ) -#else -#define ASSERT(_p) ((void)0) -#define DPRINTK(_f, _a...) ((void)0) -#endif +#define DPRINTK(_f, _a...) pr_debug("(file=%s, line=%d) " _f, \ + __FILE__ , __LINE__ , ## _a ) struct vbd { blkif_vdev_t handle; /* what the domain refers to this vbd as */ diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c Tue Jan 24 16:54:34 2006 @@ -11,7 +11,6 @@ #define vbd_sz(_v) ((_v)->bdev->bd_part ? \ (_v)->bdev->bd_part->nr_sects : (_v)->bdev->bd_disk->capacity) -#define bdev_put(_b) blkdev_put(_b) unsigned long vbd_size(struct vbd *vbd) { @@ -69,7 +68,7 @@ void vbd_free(struct vbd *vbd) { if (vbd->bdev) - bdev_put(vbd->bdev); + blkdev_put(vbd->bdev); vbd->bdev = NULL; } diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Tue Jan 24 16:54:34 2006 @@ -24,12 +24,9 @@ #include <asm-xen/xenbus.h> #include "common.h" - -#if 0 #undef DPRINTK #define DPRINTK(fmt, args...) \ - printk("blkback/xenbus (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) -#endif + pr_debug("blkback/xenbus (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) struct backend_info @@ -302,7 +299,7 @@ */ static void connect(struct backend_info *be) { - struct xenbus_transaction *xbt; + xenbus_transaction_t xbt; int err; struct xenbus_device *dev = be->dev; @@ -310,10 +307,9 @@ /* Supply the information about the device the frontend needs */ again: - xbt = xenbus_transaction_start(); - - if (IS_ERR(xbt)) { - err = PTR_ERR(xbt); + err = xenbus_transaction_start(&xbt); + + if (err) { xenbus_dev_fatal(dev, err, "starting transaction"); return; } diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Tue Jan 24 16:54:34 2006 @@ -35,14 +35,6 @@ * IN THE SOFTWARE. */ -#if 1 -#define ASSERT(p) \ - if (!(p)) { printk("Assertion '%s' failed, line %d, file %s", #p , \ - __LINE__, __FILE__); *(int*)0=0; } -#else -#define ASSERT(_p) -#endif - #include <linux/version.h> #include "block.h" #include <linux/cdrom.h> @@ -161,7 +153,7 @@ struct blkfront_info *info) { const char *message = NULL; - struct xenbus_transaction *xbt; + xenbus_transaction_t xbt; int err; /* Create shared ring, alloc event channel. */ @@ -170,8 +162,8 @@ goto out; again: - xbt = xenbus_transaction_start(); - if (IS_ERR(xbt)) { + err = xenbus_transaction_start(&xbt); + if (err) { xenbus_dev_fatal(dev, err, "starting transaction"); goto destroy_blkring; } @@ -551,7 +543,7 @@ lsect = fsect + (bvec->bv_len >> 9) - 1; /* install a grant reference. */ ref = gnttab_claim_grant_reference(&gref_head); - ASSERT(ref != -ENOSPC); + BUG_ON(ref == -ENOSPC); gnttab_grant_foreign_access_ref( ref, diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/blkfront/block.h --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Tue Jan 24 16:54:34 2006 @@ -69,11 +69,7 @@ #define WPRINTK(fmt, args...) ((void)0) #endif -#if 0 -#define DPRINTK(_f, _a...) printk ( KERN_ALERT _f , ## _a ) -#else -#define DPRINTK(_f, _a...) ((void)0) -#endif +#define DPRINTK(_f, _a...) pr_debug ( _f , ## _a ) #if 0 #define DPRINTK_IOCTL(_f, _a...) printk ( KERN_ALERT _f , ## _a ) diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/blktap/common.h --- a/linux-2.6-xen-sparse/drivers/xen/blktap/common.h Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h Tue Jan 24 16:54:34 2006 @@ -19,16 +19,8 @@ #include <asm-xen/gnttab.h> #include <asm-xen/driver_util.h> -#if 0 -#define ASSERT(_p) \ - if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \ - __LINE__, __FILE__); *(int*)0=0; } -#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \ - __FILE__ , __LINE__ , ## _a ) -#else -#define ASSERT(_p) ((void)0) -#define DPRINTK(_f, _a...) ((void)0) -#endif +#define DPRINTK(_f, _a...) pr_debug("(file=%s, line=%d) " _f, \ + __FILE__ , __LINE__ , ## _a ) #define WPRINTK(fmt, args...) printk(KERN_WARNING "blk_tap: " fmt, ##args) diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/netback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Tue Jan 24 16:54:34 2006 @@ -22,16 +22,8 @@ #include <asm-xen/gnttab.h> #include <asm-xen/driver_util.h> -#if 0 -#define ASSERT(_p) \ - if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \ - __LINE__, __FILE__); *(int*)0=0; } -#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \ - __FILE__ , __LINE__ , ## _a ) -#else -#define ASSERT(_p) ((void)0) -#define DPRINTK(_f, _a...) ((void)0) -#endif +#define DPRINTK(_f, _a...) pr_debug("(file=%s, line=%d) " _f, \ + __FILE__ , __LINE__ , ## _a ) #define IPRINTK(fmt, args...) \ printk(KERN_INFO "xen_net: " fmt, ##args) #define WPRINTK(fmt, args...) \ diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/netback/loopback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c Tue Jan 24 16:54:34 2006 @@ -27,6 +27,7 @@ #include <linux/inetdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> +#include <linux/ethtool.h> #include <net/dst.h> static int nloopbacks = 8; @@ -122,6 +123,12 @@ /*dev->mtu = 16*1024;*/ } +static struct ethtool_ops network_ethtool_ops = +{ + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, +}; + static int __init make_loopback(int i) { struct net_device *dev1, *dev2; @@ -140,6 +147,8 @@ dev1->features |= NETIF_F_NO_CSUM; dev2->features |= NETIF_F_IP_CSUM; + + SET_ETHTOOL_OPS(dev2, &network_ethtool_ops); /* * Initialise a dummy MAC address for the 'dummy backend' interface. We diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Tue Jan 24 16:54:34 2006 @@ -120,7 +120,7 @@ { netif_t *netif = netdev_priv(dev); - ASSERT(skb->dev == dev); + BUG_ON(skb->dev != dev); /* Drop the packet if the target domain has no receive buffers. */ if (!netif->active || diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Tue Jan 24 16:54:34 2006 @@ -154,13 +154,8 @@ }; #endif -#ifdef DEBUG -#define DPRINTK(fmt, args...) \ - printk(KERN_ALERT "netfront (%s:%d) " fmt, __FUNCTION__, \ - __LINE__, ##args) -#else -#define DPRINTK(fmt, args...) ((void)0) -#endif +#define DPRINTK(fmt, args...) pr_debug("netfront (%s:%d) " fmt, \ + __FUNCTION__, __LINE__, ##args) #define IPRINTK(fmt, args...) \ printk(KERN_INFO "netfront: " fmt, ##args) #define WPRINTK(fmt, args...) \ @@ -260,7 +255,7 @@ struct netfront_info *info) { const char *message; - struct xenbus_transaction *xbt; + xenbus_transaction_t xbt; int err; err = xen_net_read_mac(dev, info->mac); @@ -275,8 +270,8 @@ goto out; again: - xbt = xenbus_transaction_start(); - if (IS_ERR(xbt)) { + err = xenbus_transaction_start(&xbt); + if (err) { xenbus_dev_fatal(dev, err, "starting transaction"); goto destroy_ring; } diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/tpmback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Tue Jan 24 16:54:34 2006 @@ -17,16 +17,8 @@ #include <asm/io.h> #include <asm/pgalloc.h> -#if 0 -#define ASSERT(_p) \ - if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \ - __LINE__, __FILE__); *(int*)0=0; } -#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \ - __FILE__ , __LINE__ , ## _a ) -#else -#define ASSERT(_p) ((void)0) -#define DPRINTK(_f, _a...) ((void)0) -#endif +#define DPRINTK(_f, _a...) pr_debug("(file=%s, line=%d) " _f, \ + __FILE__ , __LINE__ , ## _a ) typedef struct tpmif_st { struct list_head tpmif_list; @@ -84,11 +76,6 @@ #define MMAP_VADDR(t,_req) ((t)->mmap_vstart + ((_req) * PAGE_SIZE)) -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - #endif /* __TPMIF__BACKEND__COMMON_H__ */ /* diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Tue Jan 24 16:54:34 2006 @@ -78,7 +78,7 @@ memset(be, 0, sizeof(*be)); - be->is_instance_set = FALSE; + be->is_instance_set = 0; be->dev = dev; dev->data = be; @@ -89,7 +89,7 @@ goto fail; } - err = xenbus_switch_state(dev, NULL, XenbusStateInitWait); + err = xenbus_switch_state(dev, XBT_NULL, XenbusStateInitWait); if (err) { goto fail; } @@ -109,7 +109,7 @@ = container_of(watch, struct backend_info, backend_watch); struct xenbus_device *dev = be->dev; - err = xenbus_scanf(NULL, dev->nodename, + err = xenbus_scanf(XBT_NULL, dev->nodename, "instance","%li", &instance); if (XENBUS_EXIST_ERR(err)) { return; @@ -120,7 +120,7 @@ return; } - if (be->is_instance_set != FALSE && be->instance != instance) { + if (be->is_instance_set != 0 && be->instance != instance) { printk(KERN_WARNING "tpmback: changing instance (from %ld to %ld) " "not allowed.\n", @@ -128,7 +128,7 @@ return; } - if (be->is_instance_set == FALSE) { + if (be->is_instance_set == 0) { be->tpmif = tpmif_find(dev->otherend_id, instance); if (IS_ERR(be->tpmif)) { @@ -138,7 +138,7 @@ return; } be->instance = instance; - be->is_instance_set = TRUE; + be->is_instance_set = 1; /* * There's an unfortunate problem: @@ -177,7 +177,7 @@ break; case XenbusStateClosing: - xenbus_switch_state(dev, NULL, XenbusStateClosing); + xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing); break; case XenbusStateClosed: @@ -230,15 +230,14 @@ static void connect(struct backend_info *be) { - struct xenbus_transaction *xbt; + xenbus_transaction_t xbt; int err; struct xenbus_device *dev = be->dev; unsigned long ready = 1; again: - xbt = xenbus_transaction_start(); - if (IS_ERR(xbt)) { - err = PTR_ERR(xbt); + err = xenbus_transaction_start(&xbt); + if (err) { xenbus_dev_fatal(be->dev, err, "starting transaction"); return; } diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Tue Jan 24 16:54:34 2006 @@ -54,14 +54,6 @@ #undef DEBUG -#if 1 -#define ASSERT(_p) \ - if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \ - __LINE__, __FILE__); *(int*)0=0; } -#else -#define ASSERT(_p) -#endif - /* locally visible variables */ static grant_ref_t gref_head; static struct tpm_private my_private; @@ -80,12 +72,8 @@ const u8 * buf, size_t count, int userbuffer, void *remember); -#if DEBUG #define DPRINTK(fmt, args...) \ - printk(KERN_ALERT "xen_tpm_fr (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args) -#else -#define DPRINTK(fmt, args...) ((void)0) -#endif + pr_debug("xen_tpm_fr (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args) #define IPRINTK(fmt, args...) \ printk(KERN_INFO "xen_tpm_fr: " fmt, ##args) #define WPRINTK(fmt, args...) \ @@ -102,11 +90,8 @@ copied = txb->size; } if (isuserbuffer) { - if (copy_from_user(txb->data, - src, - copied)) { + if (copy_from_user(txb->data, src, copied)) return -EFAULT; - } } else { memcpy(txb->data, src, copied); } @@ -196,15 +181,12 @@ static int tpm_fe_send_upperlayer(const u8 * buf, size_t count, const void *ptr) { - int rc; + int rc = 0; down(&upperlayer_lock); - if (upperlayer_tpmfe && upperlayer_tpmfe->receive) { + if (upperlayer_tpmfe && upperlayer_tpmfe->receive) rc = upperlayer_tpmfe->receive(buf, count, ptr); - } else { - rc = 0; - } up(&upperlayer_lock); return rc; @@ -253,8 +235,8 @@ static void destroy_tpmring(struct tpmfront_info *info, struct tpm_private *tp) { - tpmif_set_connected_state(tp, FALSE); - if ( tp->tx != NULL ) { + tpmif_set_connected_state(tp, 0); + if (tp->tx != NULL) { gnttab_end_foreign_access(info->ring_ref, 0, (unsigned long)tp->tx); tp->tx = NULL; @@ -271,7 +253,7 @@ { const char *message = NULL; int err; - struct xenbus_transaction *xbt; + xenbus_transaction_t xbt; err = setup_tpmring(dev, info); if (err) { @@ -280,8 +262,8 @@ } again: - xbt = xenbus_transaction_start(); - if (IS_ERR(xbt)) { + err = xenbus_transaction_start(&xbt); + if (err) { xenbus_dev_fatal(dev, err, "starting transaction"); goto destroy_tpmring; } @@ -341,15 +323,15 @@ break; case XenbusStateConnected: - tpmif_set_connected_state(tp, TRUE); + tpmif_set_connected_state(tp, 1); break; case XenbusStateClosing: - tpmif_set_connected_state(tp, FALSE); + tpmif_set_connected_state(tp, 0); break; case XenbusStateClosed: - if (tp->is_suspended == FALSE) { + if (tp->is_suspended == 0) { device_unregister(&dev->dev); } break; @@ -364,7 +346,7 @@ struct tpmfront_info *info; int handle; - err = xenbus_scanf(NULL, dev->nodename, + err = xenbus_scanf(XBT_NULL, dev->nodename, "handle", "%i", &handle); if (XENBUS_EXIST_ERR(err)) return err; @@ -409,20 +391,19 @@ tpmfront_suspend(struct xenbus_device *dev) { struct tpm_private *tp = &my_private; - u32 ctr = 0; + u32 ctr; /* lock, so no app can send */ down(&suspend_lock); - tp->is_suspended = TRUE; - - while (atomic_read(&tp->tx_busy) && ctr <= 25) { + tp->is_suspended = 1; + + for (ctr = 0; atomic_read(&tp->tx_busy) && ctr <= 25; ctr++) { if ((ctr % 10) == 0) printk("TPM-FE [INFO]: Waiting for outstanding request.\n"); /* * Wait for a request to be responded to. */ interruptible_sleep_on_timeout(&tp->wait_q, 100); - ctr++; } if (atomic_read(&tp->tx_busy)) { @@ -440,16 +421,13 @@ tpmfront_resume(struct xenbus_device *dev) { struct tpmfront_info *info = dev->data; - int err = talk_to_backend(dev, info); - - - return err; + return talk_to_backend(dev, info); } static void tpmif_connect(u16 evtchn, domid_t domid) { - int err = 0; + int err; struct tpm_private *tp = &my_private; tp->evtchn = evtchn; @@ -493,12 +471,8 @@ { unsigned int i; - i = 0; - while (i < TPMIF_TX_RING_SIZE) { + for (i = 0; i < TPMIF_TX_RING_SIZE; i++) tp->tx_buffers[i] = tx_buffer_alloc(); - i++; - } - return 1; } @@ -521,9 +495,7 @@ goto exit; } - i = 0; - while (i < TPMIF_TX_RING_SIZE && - offset < received) { + for (i = 0; i < TPMIF_TX_RING_SIZE && offset < received; i++) { struct tx_buffer *txb = tp->tx_buffers[i]; tpmif_tx_request_t *tx; unsigned int tocopy; @@ -539,7 +511,6 @@ gnttab_release_grant_reference(&gref_head, tx->ref); offset += tocopy; - i++; } tpm_fe_send_upperlayer(buffer, received, tp->tx_remember); @@ -583,19 +554,18 @@ return -EBUSY; } - if (tp->is_connected != TRUE) { + if (tp->is_connected != 1) { spin_unlock_irq(&tp->tx_lock); return -EIO; } - i = 0; - while (count > 0 && i < TPMIF_TX_RING_SIZE) { + for (i = 0; count > 0 && i < TPMIF_TX_RING_SIZE; i++) { struct tx_buffer *txb = tp->tx_buffers[i]; int copied; if (NULL == txb) { - DPRINTK("txb (i=%d) is NULL. buffers initilized?\n", i); - DPRINTK("Not transmitting anything!\n"); + DPRINTK("txb (i=%d) is NULL. buffers initilized?\n" + "Not transmitting anything!\n", i); spin_unlock_irq(&tp->tx_lock); return -EFAULT; } @@ -603,6 +573,7 @@ isuserbuffer); if (copied < 0) { /* An error occurred */ + spin_unlock_irq(&tp->tx_lock); return copied; } count -= copied; @@ -618,9 +589,10 @@ txb->data[0],txb->data[1],txb->data[2],txb->data[3]); /* get the granttable reference for this page */ - tx->ref = gnttab_claim_grant_reference( &gref_head ); - - if(-ENOSPC == tx->ref ) { + tx->ref = gnttab_claim_grant_reference(&gref_head); + + if (-ENOSPC == tx->ref) { + spin_unlock_irq(&tp->tx_lock); DPRINTK(" Grant table claim reference failed in func:%s line:%d file:%s\n", __FUNCTION__, __LINE__, __FILE__); return -ENOSPC; } @@ -628,7 +600,6 @@ tp->backend_id, (tx->addr >> PAGE_SHIFT), 0 /*RW*/); - i++; wmb(); } @@ -672,7 +643,7 @@ * should disconnect - assumption is that we will resume * The semaphore keeps apps from sending. */ - if (is_connected == FALSE && tp->is_suspended == TRUE) { + if (is_connected == 0 && tp->is_suspended == 1) { return; } @@ -681,8 +652,8 @@ * after being suspended - now resuming. * This also removes the suspend state. */ - if (is_connected == TRUE && tp->is_suspended == TRUE) { - tp->is_suspended = FALSE; + if (is_connected == 1 && tp->is_suspended == 1) { + tp->is_suspended = 0; /* unlock, so apps can resume sending */ up(&suspend_lock); } diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h Tue Jan 24 16:54:34 2006 @@ -1,10 +1,5 @@ #ifndef TPM_FRONT_H #define TPM_FRONT_H - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif struct tpm_private { tpmif_tx_interface_t *tx; diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c Tue Jan 24 16:54:34 2006 @@ -34,13 +34,8 @@ /* xenbus_probe.c */ extern char *kasprintf(const char *fmt, ...); -#if 0 #define DPRINTK(fmt, args...) \ - printk("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) -#else -#define DPRINTK(fmt, args...) ((void)0) -#endif - + pr_debug("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) int xenbus_watch_path(struct xenbus_device *dev, const char *path, struct xenbus_watch *watch, @@ -87,7 +82,7 @@ int xenbus_switch_state(struct xenbus_device *dev, - struct xenbus_transaction *xbt, + xenbus_transaction_t xbt, XenbusState state) { /* We check whether the state is currently set to the given value, and diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Tue Jan 24 16:54:34 2006 @@ -47,7 +47,7 @@ struct xenbus_dev_transaction { struct list_head list; - struct xenbus_transaction *handle; + xenbus_transaction_t handle; }; struct xenbus_dev_data { @@ -147,13 +147,11 @@ } if (u->u.msg.type == XS_TRANSACTION_START) { - trans->handle = (struct xenbus_transaction *) - simple_strtoul(reply, NULL, 0); + trans->handle = simple_strtoul(reply, NULL, 0); list_add(&trans->list, &u->transactions); } else if (u->u.msg.type == XS_TRANSACTION_END) { list_for_each_entry(trans, &u->transactions, list) - if ((unsigned long)trans->handle == - (unsigned long)u->u.msg.tx_id) + if (trans->handle == u->u.msg.tx_id) break; BUG_ON(&trans->list == &u->transactions); list_del(&trans->list); diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Tue Jan 24 16:54:34 2006 @@ -27,12 +27,8 @@ * IN THE SOFTWARE. */ -#if 0 #define DPRINTK(fmt, args...) \ - printk("xenbus_probe (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) -#else -#define DPRINTK(fmt, args...) ((void)0) -#endif + pr_debug("xenbus_probe (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) #include <linux/kernel.h> #include <linux/err.h> @@ -470,12 +466,17 @@ DPRINTK("%s", info->nodename); - if (!strncmp(xendev->nodename, info->nodename, len)) { - info->dev = xendev; - get_device(dev); - return 1; - } - return 0; + /* Match the info->nodename path, or any subdirectory of that path. */ + if (strncmp(xendev->nodename, info->nodename, len)) + return 0; + + /* If the node name is longer, ensure it really is a subdirectory. */ + if ((strlen(xendev->nodename) > len) && (xendev->nodename[len] != '/')) + return 0; + + info->dev = xendev; + get_device(dev); + return 1; } static void xenbus_cleanup_devices(const char *path, struct bus_type *bus) diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Tue Jan 24 16:54:34 2006 @@ -190,7 +190,7 @@ } /* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */ -static void *xs_talkv(struct xenbus_transaction *t, +static void *xs_talkv(xenbus_transaction_t t, enum xsd_sockmsg_type type, const struct kvec *iovec, unsigned int num_vecs, @@ -201,7 +201,7 @@ unsigned int i; int err; - msg.tx_id = (u32)(unsigned long)t; + msg.tx_id = t; msg.req_id = 0; msg.type = type; msg.len = 0; @@ -242,7 +242,7 @@ } /* Simplified version of xs_talkv: single message. */ -static void *xs_single(struct xenbus_transaction *t, +static void *xs_single(xenbus_transaction_t t, enum xsd_sockmsg_type type, const char *string, unsigned int *len) @@ -309,7 +309,7 @@ return ret; } -char **xenbus_directory(struct xenbus_transaction *t, +char **xenbus_directory(xenbus_transaction_t t, const char *dir, const char *node, unsigned int *num) { char *strings, *path; @@ -329,7 +329,7 @@ EXPORT_SYMBOL(xenbus_directory); /* Check if a path exists. Return 1 if it does. */ -int xenbus_exists(struct xenbus_transaction *t, +int xenbus_exists(xenbus_transaction_t t, const char *dir, const char *node) { char **d; @@ -347,7 +347,7 @@ * Returns a kmalloced value: call free() on it after use. * len indicates length in bytes. */ -void *xenbus_read(struct xenbus_transaction *t, +void *xenbus_read(xenbus_transaction_t t, const char *dir, const char *node, unsigned int *len) { char *path; @@ -366,7 +366,7 @@ /* Write the value of a single file. * Returns -err on failure. */ -int xenbus_write(struct xenbus_transaction *t, +int xenbus_write(xenbus_transaction_t t, const char *dir, const char *node, const char *string) { const char *path; @@ -389,7 +389,7 @@ EXPORT_SYMBOL(xenbus_write); /* Create a new directory. */ -int xenbus_mkdir(struct xenbus_transaction *t, +int xenbus_mkdir(xenbus_transaction_t t, const char *dir, const char *node) { char *path; @@ -406,7 +406,7 @@ EXPORT_SYMBOL(xenbus_mkdir); /* Destroy a file or directory (directories must be empty). */ -int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node) +int xenbus_rm(xenbus_transaction_t t, const char *dir, const char *node) { char *path; int ret; @@ -424,30 +424,28 @@ /* Start a transaction: changes by others will not be seen during this * transaction, and changes will not be visible to others until end. */ -struct xenbus_transaction *xenbus_transaction_start(void) +int xenbus_transaction_start(xenbus_transaction_t *t) { char *id_str; - unsigned long id; down_read(&xs_state.suspend_mutex); id_str = xs_single(XBT_NULL, XS_TRANSACTION_START, "", NULL); if (IS_ERR(id_str)) { up_read(&xs_state.suspend_mutex); - return (struct xenbus_transaction *)id_str; - } - - id = simple_strtoul(id_str, NULL, 0); + return PTR_ERR(id_str); + } + + *t = simple_strtoul(id_str, NULL, 0); kfree(id_str); - - return (struct xenbus_transaction *)id; + return 0; } EXPORT_SYMBOL(xenbus_transaction_start); /* End a transaction. * If abandon is true, transaction is discarded instead of committed. */ -int xenbus_transaction_end(struct xenbus_transaction *t, int abort) +int xenbus_transaction_end(xenbus_transaction_t t, int abort) { char abortstr[2]; int err; @@ -466,7 +464,7 @@ EXPORT_SYMBOL(xenbus_transaction_end); /* Single read and scanf: returns -errno or num scanned. */ -int xenbus_scanf(struct xenbus_transaction *t, +int xenbus_scanf(xenbus_transaction_t t, const char *dir, const char *node, const char *fmt, ...) { va_list ap; @@ -489,7 +487,7 @@ EXPORT_SYMBOL(xenbus_scanf); /* Single printf and write: returns -errno or 0. */ -int xenbus_printf(struct xenbus_transaction *t, +int xenbus_printf(xenbus_transaction_t t, const char *dir, const char *node, const char *fmt, ...) { va_list ap; @@ -515,7 +513,7 @@ EXPORT_SYMBOL(xenbus_printf); /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */ -int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...) +int xenbus_gather(xenbus_transaction_t t, const char *dir, ...) { va_list ap; const char *name; diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h Tue Jan 24 16:54:34 2006 @@ -32,6 +32,7 @@ #include <asm-xen/xen-public/xen.h> #include <asm-xen/xen-public/sched.h> +#include <asm-xen/xen-public/nmi.h> #define _hypercall0(type, name) \ ({ \ @@ -300,6 +301,14 @@ SHUTDOWN_suspend, srec); } +static inline int +HYPERVISOR_nmi_op( + unsigned long op, + unsigned long arg) +{ + return _hypercall2(int, nmi_op, op, arg); +} + #endif /* __HYPERCALL_H__ */ /* diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h Tue Jan 24 16:54:34 2006 @@ -29,6 +29,7 @@ extern void hypervisor_callback(void); extern void failsafe_callback(void); +extern void nmi(void); static void __init machine_specific_arch_setup(void) { @@ -36,5 +37,7 @@ __KERNEL_CS, (unsigned long)hypervisor_callback, __KERNEL_CS, (unsigned long)failsafe_callback); + HYPERVISOR_nmi_op(XENNMI_register_callback, (unsigned long)&nmi); + machine_specific_modify_cpu_capabilities(&boot_cpu_data); } diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h Tue Jan 24 16:54:34 2006 @@ -287,9 +287,9 @@ } static inline int -HYPERVISOR_switch_to_user(void) -{ - return _hypercall0(int, switch_to_user); +HYPERVISOR_iret(void) +{ + return _hypercall0(int, iret); } static inline int @@ -305,6 +305,14 @@ { return _hypercall3(int, sched_op, SCHEDOP_shutdown, SHUTDOWN_suspend, srec); +} + +static inline int +HYPERVISOR_nmi_op( + unsigned long op, + unsigned long arg) +{ + return _hypercall2(int, nmi_op, op, arg); } #endif /* __HYPERCALL_H__ */ diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h Tue Jan 24 16:54:34 2006 @@ -35,6 +35,7 @@ extern void hypervisor_callback(void); extern void failsafe_callback(void); +extern void nmi(void); static void __init machine_specific_arch_setup(void) { @@ -43,5 +44,9 @@ (unsigned long) failsafe_callback, (unsigned long) system_call); +#ifdef CONFIG_X86_LOCAL_APIC + HYPERVISOR_nmi_op(XENNMI_register_callback, (unsigned long)&nmi); +#endif + machine_specific_modify_cpu_capabilities(&boot_cpu_data); } diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h Tue Jan 24 16:54:34 2006 @@ -417,12 +417,7 @@ Other CPUs get synced lazily via the page fault handler. */ static inline pud_t *pud_offset_k(unsigned long address) { - unsigned long addr; - - addr = pgd_val(init_level4_pgt[pud_index(address)]); - addr &= PHYSICAL_PAGE_MASK; /* machine physical */ - addr = machine_to_phys(addr); - return __pud_offset_k((pud_t *)__va(addr), address); + return pud_offset(pgd_offset_k(address), address); } /* PMD - Level 2 access */ diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/include/asm-xen/xenbus.h --- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Tue Jan 24 16:54:34 2006 @@ -37,7 +37,7 @@ #include <asm-xen/xen-public/io/xenbus.h> #include <asm-xen/xen-public/io/xs_wire.h> -#define XBT_NULL NULL +#define XBT_NULL 0 /* Register callback to watch this node. */ struct xenbus_watch @@ -102,35 +102,35 @@ int xenbus_register_backend(struct xenbus_driver *drv); void xenbus_unregister_driver(struct xenbus_driver *drv); -struct xenbus_transaction; - -char **xenbus_directory(struct xenbus_transaction *t, +typedef u32 xenbus_transaction_t; + +char **xenbus_directory(xenbus_transaction_t t, const char *dir, const char *node, unsigned int *num); -void *xenbus_read(struct xenbus_transaction *t, +void *xenbus_read(xenbus_transaction_t t, const char *dir, const char *node, unsigned int *len); -int xenbus_write(struct xenbus_transaction *t, +int xenbus_write(xenbus_transaction_t t, const char *dir, const char *node, const char *string); -int xenbus_mkdir(struct xenbus_transaction *t, +int xenbus_mkdir(xenbus_transaction_t t, const char *dir, const char *node); -int xenbus_exists(struct xenbus_transaction *t, +int xenbus_exists(xenbus_transaction_t t, const char *dir, const char *node); -int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node); -struct xenbus_transaction *xenbus_transaction_start(void); -int xenbus_transaction_end(struct xenbus_transaction *t, int abort); +int xenbus_rm(xenbus_transaction_t t, const char *dir, const char *node); +int xenbus_transaction_start(xenbus_transaction_t *t); +int xenbus_transaction_end(xenbus_transaction_t t, int abort); /* Single read and scanf: returns -errno or num scanned if > 0. */ -int xenbus_scanf(struct xenbus_transaction *t, +int xenbus_scanf(xenbus_transaction_t t, const char *dir, const char *node, const char *fmt, ...) __attribute__((format(scanf, 4, 5))); /* Single printf and write: returns -errno or 0. */ -int xenbus_printf(struct xenbus_transaction *t, +int xenbus_printf(xenbus_transaction_t t, const char *dir, const char *node, const char *fmt, ...) __attribute__((format(printf, 4, 5))); /* Generic read function: NULL-terminated triples of name, * sprintf-style type string, and pointer. Returns 0 or errno.*/ -int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...); +int xenbus_gather(xenbus_transaction_t t, const char *dir, ...); /* notifer routines for when the xenstore comes up */ int register_xenstore_notifier(struct notifier_block *nb); @@ -196,7 +196,7 @@ * XenbusStateClosing, and the error will be saved in the store. */ int xenbus_switch_state(struct xenbus_device *dev, - struct xenbus_transaction *xbt, + xenbus_transaction_t xbt, XenbusState new_state); diff -r 40bb46f599d9 -r a38c292e8390 tools/examples/xmexample.vti --- a/tools/examples/xmexample.vti Tue Jan 10 15:21:00 2006 +++ b/tools/examples/xmexample.vti Tue Jan 24 16:54:34 2006 @@ -21,7 +21,7 @@ memory = 256 # A name for your domain. All domains must have different names. -name = "ExampleVMXDomain" +name = "ExampleVTIDomain" # List of which CPUS this domain is allowed to use, default Xen picks #cpus = "" # leave to Xen to pick @@ -30,7 +30,11 @@ # Optionally define mac and/or bridge for the network interfaces. # Random MACs are assigned if not given. -#vif = [ 'mac=00:16:3e:00:00:11, bridge=xen-br0' ] +#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0' ] +# type=ioemu specify the NIC is an ioemu device not netfront +vif = [ 'type=ioemu, bridge=xenbr0' ] +# for multiple NICs in device model, 3 in this example +#vif = [ 'type=ioemu, bridge=xenbr0', 'type=ioemu', 'type=ioemu'] #---------------------------------------------------------------------------- # Define the disk devices you want the domain to have access to, and @@ -53,7 +57,7 @@ #============================================================================ # New stuff -device_model = '/usr/' + arch_libdir + '/xen/bin/qemu-dm.debug' +device_model = '/usr/' + arch_libdir + '/xen/bin/qemu-dm' # Advanced users only. Don't touch if you don't know what you're doing memmap = '/usr/lib/xen/boot/mem-map.sxp' diff -r 40bb46f599d9 -r a38c292e8390 tools/firmware/vmxassist/acpi_madt.c --- a/tools/firmware/vmxassist/acpi_madt.c Tue Jan 10 15:21:00 2006 +++ b/tools/firmware/vmxassist/acpi_madt.c Tue Jan 24 16:54:34 2006 @@ -55,7 +55,6 @@ get_hvm_info_table(void) { struct hvm_info_table *t; - int i; if (table != NULL) return table; diff -r 40bb46f599d9 -r a38c292e8390 tools/ioemu/audio/audio.c --- a/tools/ioemu/audio/audio.c Tue Jan 10 15:21:00 2006 +++ b/tools/ioemu/audio/audio.c Tue Jan 24 16:54:34 2006 @@ -257,11 +257,11 @@ switch (hw->fmt) { case AUD_FMT_S16: case AUD_FMT_S8: - memset (buf, len << hw->shift, 0x00); + memset (buf, 0x00, len << hw->shift); break; case AUD_FMT_U8: - memset (buf, len << hw->shift, 0x80); + memset (buf, 0x80, len << hw->shift); break; case AUD_FMT_U16: diff -r 40bb46f599d9 -r a38c292e8390 tools/ioemu/audio/noaudio.c --- a/tools/ioemu/audio/noaudio.c Tue Jan 10 15:21:00 2006 +++ b/tools/ioemu/audio/noaudio.c Tue Jan 24 16:54:34 2006 @@ -41,7 +41,6 @@ { NoVoice *no = (NoVoice *) hw; int rpos, live, decr, samples; - uint8_t *dst; st_sample_t *src; int64_t now = qemu_get_clock (vm_clock); int64_t ticks = now - no->old_ticks; @@ -82,7 +81,6 @@ static int no_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt) { - NoVoice *no = (NoVoice *) hw; hw->freq = freq; hw->nchannels = nchannels; hw->fmt = fmt; diff -r 40bb46f599d9 -r a38c292e8390 tools/ioemu/cpu.h --- a/tools/ioemu/cpu.h Tue Jan 10 15:21:00 2006 +++ b/tools/ioemu/cpu.h Tue Jan 24 16:54:34 2006 @@ -63,6 +63,9 @@ /* MSDOS compatibility mode FPU exception support */ void cpu_set_ferr(CPUX86State *s); +/* helper2.c */ +void cpu_x86_set_a20(CPUX86State *env, int a20_state); + #if defined(__i386__) || defined(__x86_64__) #define TARGET_PAGE_BITS 12 #elif defined(__ia64__) diff -r 40bb46f599d9 -r a38c292e8390 tools/ioemu/hw/pc.c --- a/tools/ioemu/hw/pc.c Tue Jan 10 15:21:00 2006 +++ b/tools/ioemu/hw/pc.c Tue Jan 24 16:54:34 2006 @@ -382,8 +382,6 @@ { char buf[1024]; int ret, linux_boot, initrd_size, i, nb_nics1; - unsigned long bios_offset, vga_bios_offset; - int bios_size, isa_bios_size; PCIBus *pci_bus; extern void * shared_vram; diff -r 40bb46f599d9 -r a38c292e8390 tools/ioemu/vl.c --- a/tools/ioemu/vl.c Tue Jan 10 15:21:00 2006 +++ b/tools/ioemu/vl.c Tue Jan 24 16:54:34 2006 @@ -1204,7 +1204,7 @@ return -1; } strcat(path, "/console/tty"); - if (!xs_write(xs, NULL, path, pts, strlen(pts))) { + if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) { fprintf(logfile, "xs_write for console fail"); return -1; } diff -r 40bb46f599d9 -r a38c292e8390 tools/ioemu/vl.h --- a/tools/ioemu/vl.h Tue Jan 10 15:21:00 2006 +++ b/tools/ioemu/vl.h Tue Jan 24 16:54:34 2006 @@ -354,6 +354,9 @@ void qemu_get_timer(QEMUFile *f, QEMUTimer *ts); void qemu_put_timer(QEMUFile *f, QEMUTimer *ts); +/* port-e9.c */ +void port_e9_init(void); + /* block.c */ typedef struct BlockDriverState BlockDriverState; typedef struct BlockDriver BlockDriver; diff -r 40bb46f599d9 -r a38c292e8390 tools/libxc/xc_ia64_stubs.c --- a/tools/libxc/xc_ia64_stubs.c Tue Jan 10 15:21:00 2006 +++ b/tools/libxc/xc_ia64_stubs.c Tue Jan 24 16:54:34 2006 @@ -23,7 +23,8 @@ } int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, - uint32_t max_factor, uint32_t flags, int (*suspend)(void)) + uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */, + int (*suspend)(int domid)) { PERROR("xc_linux_save not implemented\n"); return -1; @@ -664,15 +665,7 @@ goto error_out; } - if ( xc_vcpu_getcontext(xc_handle, domid, 0, ctxt) ){ - PERROR("Could not get vcpu context"); - goto error_out; - } - - if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) ) { - ERROR("Domain is already constructed"); - goto error_out; - } + memset(ctxt, 0, sizeof(*ctxt)); if ( setup_guest(xc_handle, domid, (unsigned long)memsize, image, image_size, control_evtchn, store_evtchn, store_mfn ) < 0 ){ diff -r 40bb46f599d9 -r a38c292e8390 tools/libxc/xc_linux_build.c --- a/tools/libxc/xc_linux_build.c Tue Jan 10 15:21:00 2006 +++ b/tools/libxc/xc_linux_build.c Tue Jan 24 16:54:34 2006 @@ -33,10 +33,8 @@ #endif #ifdef __ia64__ -#define already_built(ctxt) (0) #define get_tot_pages xc_get_max_pages #else -#define already_built(ctxt) ((ctxt)->ctrlreg[3] != 0) #define get_tot_pages xc_get_tot_pages #endif @@ -800,17 +798,7 @@ goto error_out; } - if ( xc_vcpu_getcontext(xc_handle, domid, 0, ctxt) ) - { - PERROR("Could not get vcpu context"); - goto error_out; - } - - if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) || already_built(ctxt) ) - { - ERROR("Domain is already constructed"); - goto error_out; - } + memset(ctxt, 0, sizeof(*ctxt)); if ( setup_guest(xc_handle, domid, image, image_size, initrd_gfd, initrd_size, nr_pages, @@ -865,6 +853,8 @@ ctxt->user_regs.esi = vstartinfo_start; ctxt->user_regs.eflags = 1 << 9; /* Interrupt Enable */ + ctxt->flags = VGCF_IN_KERNEL; + /* FPU is set up to default initial state. */ memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt)); diff -r 40bb46f599d9 -r a38c292e8390 tools/libxc/xc_linux_restore.c --- a/tools/libxc/xc_linux_restore.c Tue Jan 10 15:21:00 2006 +++ b/tools/libxc/xc_linux_restore.c Tue Jan 24 16:54:34 2006 @@ -170,13 +170,6 @@ } - /* Only have to worry about vcpu 0 even for SMP */ - if (xc_vcpu_getcontext( xc_handle, dom, 0, &ctxt)) { - ERR("Could not get vcpu context"); - goto out; - } - - /* Read the saved P2M frame list */ if(!(p2m_frame_list = malloc(P2M_FL_SIZE))) { ERR("Couldn't allocate p2m_frame_list array"); diff -r 40bb46f599d9 -r a38c292e8390 tools/libxc/xc_vmx_build.c --- a/tools/libxc/xc_vmx_build.c Tue Jan 10 15:21:00 2006 +++ b/tools/libxc/xc_vmx_build.c Tue Jan 24 16:54:34 2006 @@ -651,18 +651,7 @@ goto error_out; } - if ( xc_vcpu_getcontext(xc_handle, domid, 0, ctxt) ) - { - PERROR("Could not get vcpu context"); - goto error_out; - } - - if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) || - (ctxt->ctrlreg[3] != 0) ) - { - ERROR("Domain is already constructed"); - goto error_out; - } + memset(ctxt, 0, sizeof(*ctxt)); if ( setup_guest(xc_handle, domid, memsize, image, image_size, nr_pages, ctxt, op.u.getdomaininfo.shared_info_frame, control_evtchn, diff -r 40bb46f599d9 -r a38c292e8390 tools/libxc/xenguest.h --- a/tools/libxc/xenguest.h Tue Jan 10 15:21:00 2006 +++ b/tools/libxc/xenguest.h Tue Jan 24 16:54:34 2006 @@ -21,9 +21,9 @@ * @parm dom the id of the domain * @return 0 on success, -1 on failure */ -int xc_linux_save(int xc_handle, int fd, uint32_t dom, uint32_t max_iters, +int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */, - int (*suspend)(int)); + int (*suspend)(int domid)); /** diff -r 40bb46f599d9 -r a38c292e8390 tools/python/xen/lowlevel/xs/xs.c --- a/tools/python/xen/lowlevel/xs/xs.c Tue Jan 10 15:21:00 2006 +++ b/tools/python/xen/lowlevel/xs/xs.c Tue Jan 24 16:54:34 2006 @@ -66,7 +66,7 @@ static int parse_transaction_path(XsHandle *self, PyObject *args, struct xs_handle **xh, - struct xs_transaction_handle **th, + xs_transaction_t *th, char **path); @@ -83,7 +83,7 @@ static PyObject *xspy_read(XsHandle *self, PyObject *args) { struct xs_handle *xh; - struct xs_transaction_handle *th; + xs_transaction_t th; char *path; char *xsval; @@ -120,7 +120,7 @@ { static char *arg_spec = "sss#"; struct xs_handle *xh = xshandle(self); - struct xs_transaction_handle *th; + xs_transaction_t th; char *thstr; char *path; char *data; @@ -132,7 +132,7 @@ if (!PyArg_ParseTuple(args, arg_spec, &thstr, &path, &data, &data_n)) return NULL; - th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + th = strtoul(thstr, NULL, 16); Py_BEGIN_ALLOW_THREADS result = xs_write(xh, th, path, data, data_n); @@ -155,7 +155,7 @@ static PyObject *xspy_ls(XsHandle *self, PyObject *args) { struct xs_handle *xh; - struct xs_transaction_handle *th; + xs_transaction_t th; char *path; char **xsval; @@ -193,7 +193,7 @@ static PyObject *xspy_mkdir(XsHandle *self, PyObject *args) { struct xs_handle *xh; - struct xs_transaction_handle *th; + xs_transaction_t th; char *path; bool result; @@ -221,7 +221,7 @@ static PyObject *xspy_rm(XsHandle *self, PyObject *args) { struct xs_handle *xh; - struct xs_transaction_handle *th; + xs_transaction_t th; char *path; bool result; @@ -256,7 +256,7 @@ unsigned int perms_n = 0; int i; - struct xs_transaction_handle *th; + xs_transaction_t th; char *thstr; if (!xh) @@ -264,7 +264,7 @@ if (!PyArg_ParseTuple(args, arg_spec, &thstr, &path)) return NULL; - th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + th = strtoul(thstr, NULL, 16); Py_BEGIN_ALLOW_THREADS perms = xs_get_permissions(xh, th, path, &perms_n); @@ -312,7 +312,7 @@ int xsperms_n; PyObject *tuple0 = NULL; - struct xs_transaction_handle *th; + xs_transaction_t th; char *thstr; if (!xh) @@ -320,7 +320,7 @@ if (!PyArg_ParseTuple(args, "ssO", &thstr, &path, &perms)) goto exit; - th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + th = strtoul(thstr, NULL, 16); if (!PyList_Check(perms)) { PyErr_SetString(PyExc_RuntimeError, "perms must be a list"); @@ -509,7 +509,7 @@ static PyObject *xspy_transaction_start(XsHandle *self) { struct xs_handle *xh = xshandle(self); - struct xs_transaction_handle *th; + xs_transaction_t th; char thstr[MAX_STRLEN(unsigned long) + 1]; if (!xh) @@ -519,7 +519,7 @@ th = xs_transaction_start(xh); Py_END_ALLOW_THREADS - if (th == NULL) { + if (th == XBT_NULL) { PyErr_SetFromErrno(PyExc_RuntimeError); return NULL; } @@ -547,7 +547,7 @@ struct xs_handle *xh = xshandle(self); bool result; - struct xs_transaction_handle *th; + xs_transaction_t th; char *thstr; if (!xh) @@ -556,7 +556,7 @@ &thstr, &abort)) return NULL; - th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + th = strtoul(thstr, NULL, 16); Py_BEGIN_ALLOW_THREADS result = xs_transaction_end(xh, th, abort); @@ -727,7 +727,7 @@ */ static int parse_transaction_path(XsHandle *self, PyObject *args, struct xs_handle **xh, - struct xs_transaction_handle **th, + xs_transaction_t *th, char **path) { char *thstr; @@ -740,7 +740,7 @@ if (!PyArg_ParseTuple(args, "ss", &thstr, path)) return 0; - *th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + *th = strtoul(thstr, NULL, 16); return 1; } diff -r 40bb46f599d9 -r a38c292e8390 tools/vtpm/Makefile --- a/tools/vtpm/Makefile Tue Jan 10 15:21:00 2006 +++ b/tools/vtpm/Makefile Tue Jan 24 16:54:34 2006 @@ -10,6 +10,8 @@ # Emulator tarball name TPM_EMULATOR_TARFILE = tpm_emulator-0.2b.tar.gz + +GMP_HEADER = /usr/include/gmp.h all: build @@ -55,5 +57,12 @@ patch -p1 <../vtpm.patch build_sub: - $(MAKE) -C $(TPM_EMULATOR_DIR) - $(MAKE) -C $(VTPM_DIR) + if [ -e $(GMP_HEADER) ]; then \ + $(MAKE) -C $(VTPM_DIR); \ + if [ "$(BUILD_EMULATOR)" = "y" ]; then \ + $(MAKE) -C $(TPM_EMULATOR_DIR); \ + fi \ + else \ + echo "*** Unable to build VTPMs. libgmp could not be found."; \ + fi + diff -r 40bb46f599d9 -r a38c292e8390 tools/vtpm/Rules.mk --- a/tools/vtpm/Rules.mk Tue Jan 10 15:21:00 2006 +++ b/tools/vtpm/Rules.mk Tue Jan 24 16:54:34 2006 @@ -33,5 +33,7 @@ -include $(DEP_FILES) +BUILD_EMULATOR = n + # Make sure these are just rules .PHONY : all build install clean diff -r 40bb46f599d9 -r a38c292e8390 tools/vtpm_manager/Makefile --- a/tools/vtpm_manager/Makefile Tue Jan 10 15:21:00 2006 +++ b/tools/vtpm_manager/Makefile Tue Jan 24 16:54:34 2006 @@ -4,13 +4,18 @@ include $(XEN_ROOT)/tools/vtpm_manager/Rules.mk SUBDIRS = crypto tcs util manager +OPENSSL_HEADER = /usr/include/openssl/crypto.h all: build build: - @set -e; for subdir in $(SUBDIRS); do \ - $(MAKE) -C $$subdir $@; \ - done + if [ -e $(OPENSSL_HEADER) ]; then \ + @set -e; for subdir in $(SUBDIRS); do \ + $(MAKE) -C $$subdir $@; \ + done; \ + else \ + echo "*** Cannot build vtpm_manager: OpenSSL developement files missing."; \ + fi install: build @set -e; for subdir in $(SUBDIRS); do \ diff -r 40bb46f599d9 -r a38c292e8390 tools/vtpm_manager/manager/vtpm_manager.c --- a/tools/vtpm_manager/manager/vtpm_manager.c Tue Jan 10 15:21:00 2006 +++ b/tools/vtpm_manager/manager/vtpm_manager.c Tue Jan 24 16:54:34 2006 @@ -151,9 +151,6 @@ &osap) ); // Generate boot key's auth - Crypto_GetRandom( &vtpm_globals->storage_key_usage_auth, - sizeof(TPM_AUTHDATA) ); - TPM_AUTHDATA bootKeyWrapAuth; memset(&bootKeyWrapAuth, 0, sizeof(bootKeyWrapAuth)); diff -r 40bb46f599d9 -r a38c292e8390 tools/xenmon/Makefile --- a/tools/xenmon/Makefile Tue Jan 10 15:21:00 2006 +++ b/tools/xenmon/Makefile Tue Jan 24 16:54:34 2006 @@ -13,12 +13,9 @@ INSTALL = install INSTALL_PROG = $(INSTALL) -m0755 INSTALL_DIR = $(INSTALL) -d -m0755 -INSTALL_DATA = $(INSTALL) -m064 +INSTALL_DATA = $(INSTALL) -m0644 -prefix=/usr/local -mandir=$(prefix)/share/man -man1dir=$(mandir)/man1 -sbindir=$(prefix)/sbin +sbindir=/usr/sbin XEN_ROOT=../.. include $(XEN_ROOT)/tools/Rules.mk diff -r 40bb46f599d9 -r a38c292e8390 tools/xenstat/libxenstat/src/xenstat.c --- a/tools/xenstat/libxenstat/src/xenstat.c Tue Jan 10 15:21:00 2006 +++ b/tools/xenstat/libxenstat/src/xenstat.c Tue Jan 24 16:54:34 2006 @@ -705,7 +705,7 @@ snprintf(path, sizeof(path),"/local/domain/%i/name", domain_id); - name = xs_read(handle->xshandle, NULL, path, NULL); + name = xs_read(handle->xshandle, XBT_NULL, path, NULL); if (name == NULL) name = strdup(" "); diff -r 40bb46f599d9 -r a38c292e8390 tools/xenstore/Makefile --- a/tools/xenstore/Makefile Tue Jan 10 15:21:00 2006 +++ b/tools/xenstore/Makefile Tue Jan 24 16:54:34 2006 @@ -27,7 +27,7 @@ CLIENTS += xenstore-write CLIENTS_OBJS := $(patsubst xenstore-%,xenstore_%.o,$(CLIENTS)) -all: libxenstore.so xenstored $(CLIENTS) xs_tdb_dump xsls +all: libxenstore.so xenstored $(CLIENTS) xs_tdb_dump xenstore-ls testcode: xs_test xenstored_test xs_random @@ -40,7 +40,7 @@ $(CLIENTS_OBJS): xenstore_%.o: xenstore_client.c $(COMPILE.c) -DCLIENT_$(*F) -o $@ $< -xsls: xsls.o libxenstore.so +xenstore-ls: xsls.o libxenstore.so $(LINK.o) $< $(LOADLIBES) $(LDLIBS) -lxenctrl -L. -lxenstore -o $@ xenstored_test: xenstored_core_test.o xenstored_watch_test.o xenstored_domain_test.o xenstored_transaction_test.o xs_lib.o talloc_test.o fake_libxc.o utils.o tdb.o @@ -77,7 +77,7 @@ clean: testsuite-clean rm -f *.o *.opic *.so rm -f xenstored xs_random xs_stress xs_crashme - rm -f xs_test xenstored_test xs_tdb_dump xsls $(CLIENTS) + rm -f xs_test xenstored_test xs_tdb_dump xenstore-ls $(CLIENTS) $(RM) $(PROG_DEP) print-dir: @@ -129,7 +129,7 @@ tarball: clean cd .. && tar -c -j -v -h -f xenstore.tar.bz2 xenstore/ -install: libxenstore.so xenstored xsls $(CLIENTS) +install: libxenstore.so xenstored xenstore-ls $(CLIENTS) $(INSTALL_DIR) -p $(DESTDIR)/var/run/xenstored $(INSTALL_DIR) -p $(DESTDIR)/var/lib/xenstored $(INSTALL_DIR) -p $(DESTDIR)/usr/bin @@ -137,7 +137,7 @@ $(INSTALL_DIR) -p $(DESTDIR)/usr/include $(INSTALL_PROG) xenstored $(DESTDIR)/usr/sbin $(INSTALL_PROG) $(CLIENTS) $(DESTDIR)/usr/bin - $(INSTALL_PROG) xsls $(DESTDIR)/usr/bin + $(INSTALL_PROG) xenstore-ls $(DESTDIR)/usr/bin $(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR) $(INSTALL_DATA) libxenstore.so $(DESTDIR)/usr/$(LIBDIR) $(INSTALL_DATA) xs.h $(DESTDIR)/usr/include diff -r 40bb46f599d9 -r a38c292e8390 tools/xenstore/utils.c --- a/tools/xenstore/utils.c Tue Jan 10 15:21:00 2006 +++ b/tools/xenstore/utils.c Tue Jan 24 16:54:34 2006 @@ -92,23 +92,33 @@ else fd = open(filename, O_RDONLY, 0); - if (fd < 0) + if (fd == -1) return NULL; buffer = malloc(max+1); + if (!buffer) + goto error; *size = 0; while ((ret = read(fd, buffer + *size, max - *size)) > 0) { *size += ret; - if (*size == max) - buffer = realloc(buffer, max *= 2 + 1); + if (*size == max) { + void *nbuffer; + max *= 2; + nbuffer = realloc(buffer, max + 1); + if (!nbuffer) + goto error; + buffer = nbuffer; + } } - if (ret < 0) { - free(buffer); - buffer = NULL; - } else - ((char *)buffer)[*size] = '\0'; + if (ret < 0) + goto error; + ((char *)buffer)[*size] = '\0'; close(fd); return buffer; +error: + free(buffer); + close(fd); + return NULL; } void release_file(void *data, unsigned long size __attribute__((unused))) diff -r 40bb46f599d9 -r a38c292e8390 tools/xenstore/xenstore_client.c --- a/tools/xenstore/xenstore_client.c Tue Jan 10 15:21:00 2006 +++ b/tools/xenstore/xenstore_client.c Tue Jan 24 16:54:34 2006 @@ -66,7 +66,7 @@ #if defined(CLIENT_rm) static int -do_rm(char *path, struct xs_handle *xsh, struct xs_transaction_handle *xth) +do_rm(char *path, struct xs_handle *xsh, xs_transaction_t xth) { if (xs_rm(xsh, xth, path)) { return 0; @@ -81,7 +81,7 @@ static int perform(int optind, int argc, char **argv, struct xs_handle *xsh, - struct xs_transaction_handle *xth, int prefix, int tidy) + xs_transaction_t xth, int prefix, int tidy) { while (optind < argc) { #if defined(CLIENT_read) @@ -179,7 +179,7 @@ main(int argc, char **argv) { struct xs_handle *xsh; - struct xs_transaction_handle *xth; + xs_transaction_t xth; int ret = 0, socket = 0; int prefix = 0; int tidy = 0; @@ -243,7 +243,7 @@ again: xth = xs_transaction_start(xsh); - if (xth == NULL) + if (xth == XBT_NULL) errx(1, "couldn't start transaction"); ret = perform(optind, argc, argv, xsh, xth, prefix, tidy); diff -r 40bb46f599d9 -r a38c292e8390 tools/xenstore/xenstored_core.c --- a/tools/xenstore/xenstored_core.c Tue Jan 10 15:21:00 2006 +++ b/tools/xenstore/xenstored_core.c Tue Jan 24 16:54:34 2006 @@ -174,69 +174,27 @@ } } -static void trace_io(const struct connection *conn, - const char *prefix, - const struct buffered_data *data) -{ - char string[64]; - unsigned int i; - time_t now; - struct tm *tm; +void trace(const char *fmt, ...) +{ + va_list arglist; + char *str; + char sbuf[1024]; + int ret; if (tracefd < 0) return; - now = time(NULL); - tm = localtime(&now); - - write(tracefd, prefix, strlen(prefix)); - sprintf(string, " %p %02d:%02d:%02d ", conn, tm->tm_hour, tm->tm_min, - tm->tm_sec); - write(tracefd, string, strlen(string)); - write(tracefd, sockmsg_string(data->hdr.msg.type), - strlen(sockmsg_string(data->hdr.msg.type))); - write(tracefd, " (", 2); - for (i = 0; i < data->hdr.msg.len; i++) { - if (data->buffer[i] == '\0') - write(tracefd, " ", 1); - else - write(tracefd, data->buffer + i, 1); - } - write(tracefd, ")\n", 2); -} - -void trace_create(const void *data, const char *type) -{ - char string[64]; - if (tracefd < 0) + /* try to use a static buffer */ + va_start(arglist, fmt); + ret = vsnprintf(sbuf, 1024, fmt, arglist); + va_end(arglist); + + if (ret <= 1024) { + write(tracefd, sbuf, ret); return; - - write(tracefd, "CREATE ", strlen("CREATE ")); - write(tracefd, type, strlen(type)); - sprintf(string, " %p\n", data); - write(tracefd, string, strlen(string)); -} - -void trace_destroy(const void *data, const char *type) -{ - char string[64]; - if (tracefd < 0) - return; - - write(tracefd, "DESTROY ", strlen("DESTROY ")); - write(tracefd, type, strlen(type)); - sprintf(string, " %p\n", data); - write(tracefd, string, strlen(string)); -} - -void trace(const char *fmt, ...) -{ - va_list arglist; - char *str; - - if (tracefd < 0) - return; - + } + + /* fail back to dynamic allocation */ va_start(arglist, fmt); str = talloc_vasprintf(NULL, fmt, arglist); va_end(arglist); @@ -244,6 +202,38 @@ talloc_free(str); } +static void trace_io(const struct connection *conn, + const char *prefix, + const struct buffered_data *data) +{ + unsigned int i; + time_t now; + struct tm *tm; + + if (tracefd < 0) + return; + + now = time(NULL); + tm = localtime(&now); + + trace("%s %p %02d:%02d:%02d %s (", prefix, conn, + tm->tm_hour, tm->tm_min, tm->tm_sec, + sockmsg_string(data->hdr.msg.type)); + + for (i = 0; i < data->hdr.msg.len; i++) + trace("%c", (data->buffer[i] != '\0') ? data->buffer[i] : ' '); + trace(")\n"); +} + +void trace_create(const void *data, const char *type) +{ + trace("CREATE %s %p\n", type, data); +} + +void trace_destroy(const void *data, const char *type) +{ + trace("DESTROY %s %p\n", type, data); +} /** * Signal handler for SIGHUP, which requests that the trace log is reopened @@ -268,7 +258,7 @@ if (tracefd < 0) perror("Could not open tracefile"); else - write(tracefd, "\n***\n", strlen("\n***\n")); + trace("\n***\n"); } } @@ -1311,11 +1301,10 @@ { struct connection *new; - new = talloc(talloc_autofree_context(), struct connection); + new = talloc_zero(talloc_autofree_context(), struct connection); if (!new) return NULL; - memset(new, 0, sizeof(*new)); new->fd = -1; new->write = write; new->read = read; diff -r 40bb46f599d9 -r a38c292e8390 tools/xenstore/xenstored_domain.c --- a/tools/xenstore/xenstored_domain.c Tue Jan 10 15:21:00 2006 +++ b/tools/xenstore/xenstored_domain.c Tue Jan 24 16:54:34 2006 @@ -278,12 +278,12 @@ talloc_set_destructor(domain, destroy_domain); /* Tell kernel we're interested in this event. */ - bind.remote_domain = domid; - bind.remote_port = port; - rc = ioctl(eventchn_fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind); - if (rc == -1) - return NULL; - domain->port = rc; + bind.remote_domain = domid; + bind.remote_port = port; + rc = ioctl(eventchn_fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind); + if (rc == -1) + return NULL; + domain->port = rc; domain->conn = new_connection(writechn, readchn); domain->conn->domain = domain; @@ -426,10 +426,10 @@ int result; unsigned int domid; - if (!domid_str) { - send_error(conn, EINVAL); - return; - } + if (!domid_str) { + send_error(conn, EINVAL); + return; + } domid = atoi(domid_str); if (domid == DOMID_SELF) @@ -461,35 +461,45 @@ static int dom0_init(void) { - int rc, fd; + int rc, fd; evtchn_port_t port; - unsigned long mfn; - char str[20]; - struct domain *dom0; - - fd = open(XENSTORED_PROC_MFN, O_RDONLY); - - rc = read(fd, str, sizeof(str)); - str[rc] = '\0'; - mfn = strtoul(str, NULL, 0); - - close(fd); - - fd = open(XENSTORED_PROC_PORT, O_RDONLY); - - rc = read(fd, str, sizeof(str)); - str[rc] = '\0'; - port = strtoul(str, NULL, 0); - - close(fd); - - - dom0 = new_domain(NULL, 0, mfn, port); - talloc_steal(dom0->conn, dom0); - - evtchn_notify(dom0->port); - - return 0; + unsigned long mfn; + char str[20]; + struct domain *dom0; + + fd = open(XENSTORED_PROC_MFN, O_RDONLY); + if (fd == -1) + return -1; + + rc = read(fd, str, sizeof(str)); + if (rc == -1) + goto outfd; + str[rc] = '\0'; + mfn = strtoul(str, NULL, 0); + + close(fd); + + fd = open(XENSTORED_PROC_PORT, O_RDONLY); + if (fd == -1) + return -1; + + rc = read(fd, str, sizeof(str)); + if (rc == -1) + goto outfd; + str[rc] = '\0'; + port = strtoul(str, NULL, 0); + + close(fd); + + dom0 = new_domain(NULL, 0, mfn, port); + talloc_steal(dom0->conn, dom0); + + evtchn_notify(dom0->port); + + return 0; +outfd: + close(fd); + return -1; } @@ -539,9 +549,9 @@ if (eventchn_fd < 0) barf_perror("Failed to open evtchn device"); - if (dom0_init() != 0) - barf_perror("Failed to initialize dom0 state"); - + if (dom0_init() != 0) + barf_perror("Failed to initialize dom0 state"); + bind.virq = VIRQ_DOM_EXC; rc = ioctl(eventchn_fd, IOCTL_EVTCHN_BIND_VIRQ, &bind); if (rc == -1) diff -r 40bb46f599d9 -r a38c292e8390 tools/xenstore/xs.c --- a/tools/xenstore/xs.c Tue Jan 10 15:21:00 2006 +++ b/tools/xenstore/xs.c Tue Jan 24 16:54:34 2006 @@ -292,7 +292,7 @@ } /* Send message to xs, get malloc'ed reply. NULL and set errno on error. */ -static void *xs_talkv(struct xs_handle *h, struct xs_transaction_handle *t, +static void *xs_talkv(struct xs_handle *h, xs_transaction_t t, enum xsd_sockmsg_type type, const struct iovec *iovec, unsigned int num_vecs, @@ -304,7 +304,7 @@ unsigned int i; struct sigaction ignorepipe, oldact; - msg.tx_id = (uint32_t)(unsigned long)t; + msg.tx_id = t; msg.req_id = 0; msg.type = type; msg.len = 0; @@ -368,7 +368,7 @@ } /* Simplified version of xs_talkv: single message. */ -static void *xs_single(struct xs_handle *h, struct xs_transaction_handle *t, +static void *xs_single(struct xs_handle *h, xs_transaction_t t, enum xsd_sockmsg_type type, const char *string, unsigned int *len) @@ -388,7 +388,7 @@ return true; } -char **xs_directory(struct xs_handle *h, struct xs_transaction_handle *t, +char **xs_directory(struct xs_handle *h, xs_transaction_t t, const char *path, unsigned int *num) { char *strings, *p, **ret; @@ -420,7 +420,7 @@ * Returns a malloced value: call free() on it after use. * len indicates length in bytes, not including the nul. */ -void *xs_read(struct xs_handle *h, struct xs_transaction_handle *t, +void *xs_read(struct xs_handle *h, xs_transaction_t t, const char *path, unsigned int *len) { return xs_single(h, t, XS_READ, path, len); @@ -429,7 +429,7 @@ /* Write the value of a single file. * Returns false on failure. */ -bool xs_write(struct xs_handle *h, struct xs_transaction_handle *t, +bool xs_write(struct xs_handle *h, xs_transaction_t t, const char *path, const void *data, unsigned int len) { struct iovec iovec[2]; @@ -446,7 +446,7 @@ /* Create a new directory. * Returns false on failure, or success if it already exists. */ -bool xs_mkdir(struct xs_handle *h, struct xs_transaction_handle *t, +bool xs_mkdir(struct xs_handle *h, xs_transaction_t t, const char *path) { return xs_bool(xs_single(h, t, XS_MKDIR, path, NULL)); @@ -455,7 +455,7 @@ /* Destroy a file or directory (directories must be empty). * Returns false on failure, or success if it doesn't exist. */ -bool xs_rm(struct xs_handle *h, struct xs_transaction_handle *t, +bool xs_rm(struct xs_handle *h, xs_transaction_t t, const char *path) { return xs_bool(xs_single(h, t, XS_RM, path, NULL)); @@ -465,7 +465,7 @@ * Returns malloced array, or NULL: call free() after use. */ struct xs_permissions *xs_get_permissions(struct xs_handle *h, - struct xs_transaction_handle *t, + xs_transaction_t t, const char *path, unsigned int *num) { char *strings; @@ -499,7 +499,7 @@ * Returns false on failure. */ bool xs_set_permissions(struct xs_handle *h, - struct xs_transaction_handle *t, + xs_transaction_t t, const char *path, struct xs_permissions *perms, unsigned int num_perms) @@ -634,21 +634,21 @@ /* Start a transaction: changes by others will not be seen during this * transaction, and changes will not be visible to others until end. * You can only have one transaction at any time. - * Returns NULL on failure. - */ -struct xs_transaction_handle *xs_transaction_start(struct xs_handle *h) + * Returns XBT_NULL on failure. + */ +xs_transaction_t xs_transaction_start(struct xs_handle *h) { char *id_str; - unsigned long id; + xs_transaction_t id; id_str = xs_single(h, XBT_NULL, XS_TRANSACTION_START, "", NULL); if (id_str == NULL) - return NULL; + return XBT_NULL; id = strtoul(id_str, NULL, 0); free(id_str); - return (struct xs_transaction_handle *)id; + return id; } /* End a transaction. @@ -656,7 +656,7 @@ * Returns false on failure, which indicates an error: transactions will * not fail spuriously. */ -bool xs_transaction_end(struct xs_handle *h, struct xs_transaction_handle *t, +bool xs_transaction_end(struct xs_handle *h, xs_transaction_t t, bool abort) { char abortstr[2]; diff -r 40bb46f599d9 -r a38c292e8390 tools/xenstore/xs.h --- a/tools/xenstore/xs.h Tue Jan 10 15:21:00 2006 +++ b/tools/xenstore/xs.h Tue Jan 24 16:54:34 2006 @@ -22,10 +22,10 @@ #include <xs_lib.h> -#define XBT_NULL NULL +#define XBT_NULL 0 struct xs_handle; -struct xs_transaction_handle; +typedef uint32_t xs_transaction_t; /* On failure, these routines set errno. */ @@ -47,45 +47,45 @@ * Returns a malloced array: call free() on it after use. * Num indicates size. */ -char **xs_directory(struct xs_handle *h, struct xs_transaction_handle *t, +char **xs_directory(struct xs_handle *h, xs_transaction_t t, const char *path, unsigned int *num); /* Get the value of a single file, nul terminated. * Returns a malloced value: call free() on it after use. * len indicates length in bytes, not including terminator. */ -void *xs_read(struct xs_handle *h, struct xs_transaction_handle *t, +void *xs_read(struct xs_handle *h, xs_transaction_t t, const char *path, unsigned int *len); /* Write the value of a single file. * Returns false on failure. */ -bool xs_write(struct xs_handle *h, struct xs_transaction_handle *t, +bool xs_write(struct xs_handle *h, xs_transaction_t t, const char *path, const void *data, unsigned int len); /* Create a new directory. * Returns false on failure, or success if it already exists. */ -bool xs_mkdir(struct xs_handle *h, struct xs_transaction_handle *t, +bool xs_mkdir(struct xs_handle *h, xs_transaction_t t, const char *path); /* Destroy a file or directory (and children). * Returns false on failure, or if it doesn't exist. */ -bool xs_rm(struct xs_handle *h, struct xs_transaction_handle *t, +bool xs_rm(struct xs_handle *h, xs_transaction_t t, const char *path); /* Get permissions of node (first element is owner, first perms is "other"). * Returns malloced array, or NULL: call free() after use. */ struct xs_permissions *xs_get_permissions(struct xs_handle *h, - struct xs_transaction_handle *t, + xs_transaction_t t, const char *path, unsigned int *num); /* Set permissions of node (must be owner). * Returns false on failure. */ -bool xs_set_permissions(struct xs_handle *h, struct xs_transaction_handle *t, +bool xs_set_permissions(struct xs_handle *h, xs_transaction_t t, const char *path, struct xs_permissions *perms, unsigned int num_perms); @@ -115,14 +115,14 @@ * You can only have one transaction at any time. * Returns NULL on failure. */ -struct xs_transaction_handle *xs_transaction_start(struct xs_handle *h); +xs_transaction_t xs_transaction_start(struct xs_handle *h); /* End a transaction. * If abandon is true, transaction is discarded instead of committed. * Returns false on failure: if errno == EAGAIN, you have to restart * transaction. */ -bool xs_transaction_end(struct xs_handle *h, struct xs_transaction_handle *t, +bool xs_transaction_end(struct xs_handle *h, xs_transaction_t t, bool abort); /* Introduce a new domain. diff -r 40bb46f599d9 -r a38c292e8390 tools/xenstore/xs_test.c --- a/tools/xenstore/xs_test.c Tue Jan 10 15:21:00 2006 +++ b/tools/xenstore/xs_test.c Tue Jan 24 16:54:34 2006 @@ -43,7 +43,7 @@ #define XSTEST static struct xs_handle *handles[10] = { NULL }; -static struct xs_transaction_handle *txh[10] = { XBT_NULL }; +static xs_transaction_t txh[10] = { XBT_NULL }; static unsigned int timeout_ms = 500; static bool timeout_suppressed = true; @@ -535,7 +535,7 @@ *(uint16_t *)((void *)interface + 36) = atoi(eventchn); if (!xs_introduce_domain(handles[handle], atoi(domid), - atol(mfn), atoi(eventchn), path)) { + atol(mfn), atoi(eventchn))) { failed(handle); munmap(interface, getpagesize()); return; diff -r 40bb46f599d9 -r a38c292e8390 tools/xentrace/Makefile --- a/tools/xentrace/Makefile Tue Jan 10 15:21:00 2006 +++ b/tools/xentrace/Makefile Tue Jan 24 16:54:34 2006 @@ -33,14 +33,14 @@ install: build [ -d $(DESTDIR)/usr/bin ] || $(INSTALL_DIR) $(DESTDIR)/usr/bin - [ -z "$(LIBBIN)"] || [ -d $(DESTDIR)/usr/$(LIBDIR)/xen/bin ] || \ + [ -z "$(LIBBIN)" ] || [ -d $(DESTDIR)/usr/$(LIBDIR)/xen/bin ] || \ $(INSTALL_DIR) $(DESTDIR)/usr/$(LIBDIR)/xen/bin [ -d $(DESTDIR)/usr/share/man/man1 ] || \ $(INSTALL_DIR) $(DESTDIR)/usr/share/man/man1 [ -d $(DESTDIR)/usr/share/man/man8 ] || \ $(INSTALL_DIR) $(DESTDIR)/usr/share/man/man8 $(INSTALL_PROG) $(BIN) $(SCRIPTS) $(DESTDIR)/usr/bin - [ -z "$(LIBBIN)"] || $(INSTALL_PROG) $(LIBBIN) $(DESTDIR)/usr/$(LIBDIR)/xen/bin + [ -z "$(LIBBIN)" ] || $(INSTALL_PROG) $(LIBBIN) $(DESTDIR)/usr/$(LIBDIR)/xen/bin $(INSTALL_DATA) $(MAN1) $(DESTDIR)/usr/share/man/man1 $(INSTALL_DATA) $(MAN8) $(DESTDIR)/usr/share/man/man8 diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/Makefile --- a/xen/arch/ia64/Makefile Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/Makefile Tue Jan 24 16:54:34 2006 @@ -22,6 +22,10 @@ memset.o strlen.o memcpy_mck.o \ __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \ __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o + +ifeq ($(crash_debug),y) +OBJS += gdbstub.o +endif # xen stack unwinder # unwind_decoder.c is included in unwind.c diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/Rules.mk --- a/xen/arch/ia64/Rules.mk Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/Rules.mk Tue Jan 24 16:54:34 2006 @@ -23,10 +23,10 @@ -I$(BASEDIR)/include/asm-ia64/linux-xen \ -I$(BASEDIR)/include/asm-ia64/linux-null \ -I$(BASEDIR)/arch/ia64/linux -I$(BASEDIR)/arch/ia64/linux-xen -CFLAGS += -Wno-pointer-arith -Wredundant-decls +#CFLAGS += -Wno-pointer-arith -Wredundant-decls CFLAGS += -DIA64 -DXEN -DLINUX_2_6 -DV_IOSAPIC_READY CFLAGS += -ffixed-r13 -mfixed-range=f12-f15,f32-f127 -CFLAGS += -w -g +CFLAGS += -g #CFLAGS += -DVTI_DEBUG ifeq ($(VALIDATE_VT),y) CFLAGS += -DVALIDATE_VT diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/asm-offsets.c --- a/xen/arch/ia64/asm-offsets.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/asm-offsets.c Tue Jan 24 16:54:34 2006 @@ -15,7 +15,7 @@ #define task_struct vcpu #define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) + asm volatile("\n->" #sym " (%0) " #val : : "i" (val)) #define BLANK() asm volatile("\n->" : : ) diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/asm-xsi-offsets.c --- a/xen/arch/ia64/asm-xsi-offsets.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/asm-xsi-offsets.c Tue Jan 24 16:54:34 2006 @@ -38,7 +38,7 @@ #define task_struct vcpu #define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) + asm volatile("\n->" #sym " (%0) " #val : : "i" (val)) #define BLANK() asm volatile("\n->" : : ) diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/linux-xen/sal.c --- a/xen/arch/ia64/linux-xen/sal.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/linux-xen/sal.c Tue Jan 24 16:54:34 2006 @@ -16,6 +16,7 @@ #ifdef XEN #include <linux/smp.h> +#include <xen/lib.h> #endif #include <asm/page.h> #include <asm/sal.h> diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/linux-xen/smp.c --- a/xen/arch/ia64/linux-xen/smp.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/linux-xen/smp.c Tue Jan 24 16:54:34 2006 @@ -57,8 +57,21 @@ void flush_tlb_mask(cpumask_t mask) { #ifdef CONFIG_SMP - printf("flush_tlb_mask called, not implemented for SMP\n"); - dummy(); + int cpu; + + cpu = smp_processor_id(); + if (cpu_isset (cpu, mask)) { + cpu_clear(cpu, mask); + local_flush_tlb_all (); + } + + if (cpus_empty(mask)) + return; + + for (cpu = 0; cpu < NR_CPUS; ++cpu) + if (cpu_isset(cpu, mask)) + smp_call_function_single + (cpu, (void (*)(void *))local_flush_tlb_all, NULL, 1, 1); #endif } //#if CONFIG_SMP || IA64 diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/linux-xen/smpboot.c --- a/xen/arch/ia64/linux-xen/smpboot.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/linux-xen/smpboot.c Tue Jan 24 16:54:34 2006 @@ -64,6 +64,10 @@ #ifdef XEN #include <asm/hw_irq.h> int ht_per_core = 1; +#ifndef CONFIG_SMP +cpumask_t cpu_online_map = CPU_MASK_CPU0; +EXPORT_SYMBOL(cpu_online_map); +#endif #endif #ifdef CONFIG_SMP /* ifdef XEN */ @@ -482,9 +486,8 @@ struct vcpu *v; void *stack; - if ( (idle = do_createdomain(IDLE_DOMAIN_ID, cpu)) == NULL ) - panic("failed 'createdomain' for CPU %d", cpu); - v = idle->vcpu[0]; + v = idle_vcpu[cpu] = alloc_vcpu(idle_vcpu[0]->domain, cpu, cpu); + BUG_ON(v == NULL); printf ("do_boot_cpu: cpu=%d, domain=%p, vcpu=%p\n", cpu, idle, v); diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/vmx/vlsapic.c --- a/xen/arch/ia64/vmx/vlsapic.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/vmx/vlsapic.c Tue Jan 24 16:54:34 2006 @@ -119,7 +119,7 @@ itc_freq = local_cpu_data->itc_freq; vtm->cfg_max_jump=itc_freq*MAX_JUMP_STEP/1000; vtm->cfg_min_grun=itc_freq*MIN_GUEST_RUNNING_TIME/1000; - init_ac_timer(&vtm->vtm_timer, vtm_timer_fn, vcpu, 0); + init_timer(&vtm->vtm_timer, vtm_timer_fn, vcpu, 0); vtm_reset(vcpu); } @@ -163,20 +163,20 @@ local_irq_save(spsr); itv = VCPU(vcpu, itv); if ( ITV_IRQ_MASK(itv) ) - rem_ac_timer(&vtm->vtm_timer); + stop_timer(&vtm->vtm_timer); vtm_interruption_update(vcpu, vtm); local_irq_restore(spsr); } /* - * Update interrupt or hook the vtm ac_timer for fire + * Update interrupt or hook the vtm timer for fire * At this point vtm_timer should be removed if itv is masked. */ /* Interrupt must be disabled at this point */ extern u64 cycle_to_ns(u64 cyle); -#define TIMER_SLOP (50*1000) /* ns */ /* copy from ac_timer.c */ +#define TIMER_SLOP (50*1000) /* ns */ /* copy from timer.c */ void vtm_interruption_update(VCPU *vcpu, vtime_t* vtm) { uint64_t cur_itc,vitm,vitv; @@ -198,7 +198,7 @@ if ( diff_last >= 0 ) { // interrupt already fired. - rem_ac_timer(&vtm->vtm_timer); + stop_timer(&vtm->vtm_timer); } else if ( diff_now >= 0 ) { // ITV is fired. @@ -207,24 +207,24 @@ /* Both last_itc & cur_itc < itm, wait for fire condition */ else { expires = NOW() + cycle_to_ns(0-diff_now) + TIMER_SLOP; - set_ac_timer(&vtm->vtm_timer, expires); + set_timer(&vtm->vtm_timer, expires); } local_irq_restore(spsr); } /* * Action for vtm when the domain is scheduled out. - * Remove the ac_timer for vtm. + * Remove the timer for vtm. */ void vtm_domain_out(VCPU *vcpu) { if(!is_idle_domain(vcpu->domain)) - rem_ac_timer(&vcpu->arch.arch_vmx.vtm.vtm_timer); + stop_timer(&vcpu->arch.arch_vmx.vtm.vtm_timer); } /* * Action for vtm when the domain is scheduled in. - * Fire vtm IRQ or add the ac_timer for vtm. + * Fire vtm IRQ or add the timer for vtm. */ void vtm_domain_in(VCPU *vcpu) { diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/vmx/vmx_process.c --- a/xen/arch/ia64/vmx/vmx_process.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/vmx/vmx_process.c Tue Jan 24 16:54:34 2006 @@ -41,6 +41,7 @@ #include <asm/regionreg.h> #include <asm/privop.h> #include <asm/ia64_int.h> +#include <asm/debugger.h> //#include <asm/hpsim_ssc.h> #include <asm/dom_fw.h> #include <asm/vmx_vcpu.h> @@ -107,6 +108,14 @@ if (running_on_sim) do_ssc(vcpu_get_gr_nat(current,36), regs); else do_ssc(vcpu_get_gr_nat(current,36), regs); } +#endif +#ifdef CRASH_DEBUG + if ((iim == 0 || iim == CDB_BREAK_NUM) && !user_mode(regs) && + IS_VMM_ADDRESS(regs->cr_iip)) { + if (iim == 0) + show_registers(regs); + debugger_trap_fatal(0 /* don't care */, regs); + } else #endif if (iim == d->arch.breakimm) { struct ia64_pal_retval y; diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/xen/domain.c --- a/xen/arch/ia64/xen/domain.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/xen/domain.c Tue Jan 24 16:54:34 2006 @@ -65,12 +65,14 @@ unsigned long map_domain_page0(struct domain *); extern unsigned long dom_fw_setup(struct domain *, char *, int); +static void init_switch_stack(struct vcpu *v); /* this belongs in include/asm, but there doesn't seem to be a suitable place */ -void free_perdomain_pt(struct domain *d) -{ - printf("free_perdomain_pt: not implemented\n"); +void arch_domain_destroy(struct domain *d) +{ + printf("arch_domain_destroy: not implemented\n"); //free_page((unsigned long)d->mm.perdomain_pt); + free_xenheap_page(d->shared_info); } static void default_idle(void) @@ -87,7 +89,6 @@ int cpu = smp_processor_id(); for ( ; ; ) { - printf ("idle%dD\n", cpu); #ifdef IA64 // __IRQ_STAT(cpu, idle_timestamp) = jiffies #else @@ -145,16 +146,45 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) { struct vcpu *v; - - if ((v = alloc_xenheap_pages(KERNEL_STACK_SIZE_ORDER)) == NULL) + struct thread_info *ti; + + /* Still keep idle vcpu0 static allocated at compilation, due + * to some code from Linux still requires it in early phase. + */ + if (is_idle_domain(d) && !vcpu_id) + v = idle_vcpu[0]; + else { + if ((v = alloc_xenheap_pages(KERNEL_STACK_SIZE_ORDER)) == NULL) return NULL; - - memset(v, 0, sizeof(*v)); - memcpy(&v->arch, &idle0_vcpu.arch, sizeof(v->arch)); - v->arch.privregs = + memset(v, 0, sizeof(*v)); + } + + ti = alloc_thread_info(v); + /* Clear thread_info to clear some important fields, like + * preempt_count + */ + memset(ti, 0, sizeof(struct thread_info)); + init_switch_stack(v); + + if (!is_idle_domain(d)) { + v->arch.privregs = alloc_xenheap_pages(get_order(sizeof(mapped_regs_t))); - printf("arch_vcpu_info=%p\n", v->arch.privregs); - memset(v->arch.privregs, 0, PAGE_SIZE); + BUG_ON(v->arch.privregs == NULL); + memset(v->arch.privregs, 0, PAGE_SIZE); + + if (!vcpu_id) + memset(&d->shared_info->evtchn_mask[0], 0xff, + sizeof(d->shared_info->evtchn_mask)); + + v->vcpu_info = &(d->shared_info->vcpu_info[0]); + v->arch.metaphysical_rr0 = d->arch.metaphysical_rr0; + v->arch.metaphysical_rr4 = d->arch.metaphysical_rr4; + v->arch.metaphysical_saved_rr0 = d->arch.metaphysical_rr0; + v->arch.metaphysical_saved_rr4 = d->arch.metaphysical_rr4; + v->arch.starting_rid = d->arch.starting_rid; + v->arch.ending_rid = d->arch.ending_rid; + v->arch.breakimm = d->arch.breakimm; + } return v; } @@ -182,34 +212,21 @@ memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96); } -int arch_do_createdomain(struct vcpu *v) -{ - struct domain *d = v->domain; - struct thread_info *ti = alloc_thread_info(v); - - /* Clear thread_info to clear some important fields, like preempt_count */ - memset(ti, 0, sizeof(struct thread_info)); - init_switch_stack(v); - - d->shared_info = (void *)alloc_xenheap_page(); - if (!d->shared_info) { - printk("ERROR/HALTING: CAN'T ALLOC PAGE\n"); - while (1); - } +int arch_domain_create(struct domain *d) +{ + // the following will eventually need to be negotiated dynamically + d->xen_vastart = XEN_START_ADDR; + d->xen_vaend = XEN_END_ADDR; + d->shared_info_va = SHAREDINFO_ADDR; + + if (is_idle_domain(d)) + return 0; + + if ((d->shared_info = (void *)alloc_xenheap_page()) == NULL) + goto fail_nomem; memset(d->shared_info, 0, PAGE_SIZE); - if (v == d->vcpu[0]) - memset(&d->shared_info->evtchn_mask[0], 0xff, - sizeof(d->shared_info->evtchn_mask)); -#if 0 - d->vcpu[0].arch.privregs = - alloc_xenheap_pages(get_order(sizeof(mapped_regs_t))); - printf("arch_vcpu_info=%p\n", d->vcpu[0].arch.privregs); - memset(d->vcpu.arch.privregs, 0, PAGE_SIZE); -#endif - v->vcpu_info = &(d->shared_info->vcpu_info[0]); d->max_pages = (128UL*1024*1024)/PAGE_SIZE; // 128MB default // FIXME - /* We may also need emulation rid for region4, though it's unlikely * to see guest issue uncacheable access in metaphysical mode. But * keep such info here may be more sane. @@ -217,41 +234,27 @@ if (((d->arch.metaphysical_rr0 = allocate_metaphysical_rr()) == -1UL) || ((d->arch.metaphysical_rr4 = allocate_metaphysical_rr()) == -1UL)) BUG(); -// VCPU(v, metaphysical_mode) = 1; - v->arch.metaphysical_rr0 = d->arch.metaphysical_rr0; - v->arch.metaphysical_rr4 = d->arch.metaphysical_rr4; - v->arch.metaphysical_saved_rr0 = d->arch.metaphysical_rr0; - v->arch.metaphysical_saved_rr4 = d->arch.metaphysical_rr4; #define DOMAIN_RID_BITS_DEFAULT 18 if (!allocate_rid_range(d,DOMAIN_RID_BITS_DEFAULT)) // FIXME BUG(); - v->arch.starting_rid = d->arch.starting_rid; - v->arch.ending_rid = d->arch.ending_rid; - // the following will eventually need to be negotiated dynamically - d->xen_vastart = XEN_START_ADDR; - d->xen_vaend = XEN_END_ADDR; - d->shared_info_va = SHAREDINFO_ADDR; d->arch.breakimm = 0x1000; - v->arch.breakimm = d->arch.breakimm; - d->arch.sys_pgnr = 0; - if (d->domain_id != IDLE_DOMAIN_ID) { - d->arch.mm = xmalloc(struct mm_struct); - if (unlikely(!d->arch.mm)) { - printk("Can't allocate mm_struct for domain %d\n",d->domain_id); - return -ENOMEM; - } - memset(d->arch.mm, 0, sizeof(*d->arch.mm)); - d->arch.mm->pgd = pgd_alloc(d->arch.mm); - if (unlikely(!d->arch.mm->pgd)) { - printk("Can't allocate pgd for domain %d\n",d->domain_id); - return -ENOMEM; - } - } else - d->arch.mm = NULL; - printf ("arch_do_create_domain: domain=%p\n", d); - + + if ((d->arch.mm = xmalloc(struct mm_struct)) == NULL) + goto fail_nomem; + memset(d->arch.mm, 0, sizeof(*d->arch.mm)); + + if ((d->arch.mm->pgd = pgd_alloc(d->arch.mm)) == NULL) + goto fail_nomem; + + printf ("arch_domain_create: domain=%p\n", d); return 0; + +fail_nomem: + free_xenheap_page(d->shared_info); + xfree(d->arch.mm); + pgd_free(d->arch.mm->pgd); + return -ENOMEM; } void arch_getdomaininfo_ctxt(struct vcpu *v, struct vcpu_guest_context *c) diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/xen/hyperprivop.S --- a/xen/arch/ia64/xen/hyperprivop.S Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/xen/hyperprivop.S Tue Jan 24 16:54:34 2006 @@ -12,6 +12,7 @@ #include <asm/offsets.h> #include <asm/processor.h> #include <asm/system.h> +#include <asm/debugger.h> #include <public/arch-ia64.h> @@ -549,7 +550,12 @@ (p7) br.spnt.many 1f ;; cmp.eq p7,p0=r17,r0 (p7) br.spnt.few dispatch_break_fault ;; -1: +#ifdef CRASH_DEBUG + movl r21=CDB_BREAK_NUM ;; + cmp.eq p7,p0=r17,r21 +(p7) br.spnt.few dispatch_break_fault ;; +#endif +1: #if 1 /* special handling in case running on simulator */ movl r20=first_break;; ld4 r23=[r20];; diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/xen/idle0_task.c --- a/xen/arch/ia64/xen/idle0_task.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/xen/idle0_task.c Tue Jan 24 16:54:34 2006 @@ -11,29 +11,14 @@ .mmlist = LIST_HEAD_INIT(name.mmlist), \ } -#define IDLE0_EXEC_DOMAIN(_ed,_d) \ +#define IDLE_VCPU(_v) \ { \ processor: 0, \ - mm: 0, \ - thread: INIT_THREAD, \ - domain: (_d) \ -} - -#define IDLE0_DOMAIN(_t) \ -{ \ - domain_id: IDLE_DOMAIN_ID, \ - refcnt: ATOMIC_INIT(1) \ + domain: 0 \ } struct mm_struct init_mm = INIT_MM(init_mm); EXPORT_SYMBOL(init_mm); - -struct domain idle0_domain = IDLE0_DOMAIN(idle0_domain); -#if 0 -struct vcpu idle0_vcpu = IDLE0_EXEC_DOMAIN(idle0_vcpu, - &idle0_domain); -#endif - /* * Initial task structure. @@ -43,15 +28,12 @@ */ union { struct { - struct domain task; + struct vcpu task; } s; unsigned long stack[KERNEL_STACK_SIZE/sizeof (unsigned long)]; -} init_task_mem asm ("init_task") __attribute__((section(".data.init_task"))); -// = {{ - ; -//.task = IDLE0_EXEC_DOMAIN(init_task_mem.s.task,&idle0_domain), -//}; -//}; +} init_task_mem asm ("init_task") __attribute__((section(".data.init_task"))) = {{ + .task = IDLE_VCPU(init_task_mem.s.task) +}}; EXPORT_SYMBOL(init_task); diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/xen/ivt.S --- a/xen/arch/ia64/xen/ivt.S Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/xen/ivt.S Tue Jan 24 16:54:34 2006 @@ -15,6 +15,7 @@ #define sys_call_table 0 #define sys_ni_syscall 0 #include <asm/vhpt.h> +#include <asm/debugger.h> #endif /* * arch/ia64/kernel/ivt.S @@ -841,6 +842,13 @@ ;; cmp.eq p7,p0=r17,r0 (p7) br.spnt.few dispatch_break_fault ;; +#ifdef CRASH_DEBUG + // panic can occur before domain0 is created. + // in such case referencing XSI_PSR_IC causes nested_dtlb_miss + movl r18=CDB_BREAK_NUM ;; + cmp.eq p7,p0=r17,r18 ;; +(p7) br.spnt.few dispatch_break_fault ;; +#endif movl r18=XSI_PSR_IC ;; ld8 r19=[r18] diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/xen/mm_init.c --- a/xen/arch/ia64/xen/mm_init.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/xen/mm_init.c Tue Jan 24 16:54:34 2006 @@ -502,6 +502,7 @@ } #endif /* CONFIG_VIRTUAL_MEM_MAP */ +#ifndef XEN static int count_reserved_pages (u64 start, u64 end, void *arg) { @@ -514,6 +515,7 @@ *count += num_reserved; return 0; } +#endif /* * Boot command-line option "nolwsys" can be used to disable the use of any light-weight diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/xen/process.c --- a/xen/arch/ia64/xen/process.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/xen/process.c Tue Jan 24 16:54:34 2006 @@ -31,6 +31,7 @@ #include <asm/dom_fw.h> #include "hpsim_ssc.h" #include <xen/multicall.h> +#include <asm/debugger.h> extern unsigned long vcpu_get_itir_on_fault(struct vcpu *, UINT64); extern void die_if_kernel(char *str, struct pt_regs *regs, long err); @@ -652,7 +653,7 @@ ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long isr, unsigned long iim) { struct domain *d = (struct domain *) current->domain; - struct vcpu *v = (struct domain *) current; + struct vcpu *v = current; extern unsigned long running_on_sim; if (first_break) { @@ -663,7 +664,14 @@ if (iim == 0x80001 || iim == 0x80002) { //FIXME: don't hardcode constant if (running_on_sim) do_ssc(vcpu_get_gr(current,36), regs); else do_ssc(vcpu_get_gr(current,36), regs); - } + } +#ifdef CRASH_DEBUG + else if ((iim == 0 || iim == CDB_BREAK_NUM) && !user_mode(regs)) { + if (iim == 0) + show_registers(regs); + debugger_trap_fatal(0 /* don't care */, regs); + } +#endif else if (iim == d->arch.breakimm) { /* by default, do not continue */ v->arch.hypercall_continuation = 0; diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/xen/sn_console.c --- a/xen/arch/ia64/xen/sn_console.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/xen/sn_console.c Tue Jan 24 16:54:34 2006 @@ -4,6 +4,7 @@ * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved. */ +#include <xen/lib.h> #include <asm/acpi.h> #include <asm/sn/sn_sal.h> #include <xen/serial.h> diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/xen/xenmisc.c --- a/xen/arch/ia64/xen/xenmisc.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/xen/xenmisc.c Tue Jan 24 16:54:34 2006 @@ -18,6 +18,7 @@ #include <xen/softirq.h> #include <public/sched.h> #include <asm/vhpt.h> +#include <asm/debugger.h> efi_memory_desc_t ia64_efi_io_md; EXPORT_SYMBOL(ia64_efi_io_md); @@ -75,7 +76,7 @@ void raise_actimer_softirq(void) { - raise_softirq(AC_TIMER_SOFTIRQ); + raise_softirq(TIMER_SOFTIRQ); } unsigned long @@ -202,6 +203,8 @@ { printk("dump_pageframe_info not implemented\n"); } + +int nmi_count(int x) { return x; } /////////////////////////////// // called from arch/ia64/head.S @@ -354,6 +357,11 @@ va_end(args); printf(buf); if (regs) show_registers(regs); + if (regs) { + debugger_trap_fatal(0 /* don't care */, regs); + } else { + debugger_trap_immediate(); + } domain_pause_by_systemcontroller(current->domain); v->domain->shutdown_code = SHUTDOWN_crash; set_bit(_DOMF_shutdown, v->domain->domain_flags); diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/xen/xensetup.c --- a/xen/arch/ia64/xen/xensetup.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/xen/xensetup.c Tue Jan 24 16:54:34 2006 @@ -21,12 +21,13 @@ #include <asm/page.h> #include <asm/setup.h> #include <xen/string.h> +#include <asm/vmx.h> unsigned long xenheap_phys_end; char saved_command_line[COMMAND_LINE_SIZE]; -struct vcpu *idle_vcpu[NR_CPUS] = { &idle0_vcpu }; +struct vcpu *idle_vcpu[NR_CPUS]; cpumask_t cpu_present_map; @@ -156,15 +157,11 @@ unsigned long dom0_memory_start, dom0_memory_size; unsigned long dom0_initrd_start, dom0_initrd_size; unsigned long initial_images_start, initial_images_end; + struct domain *idle_domain; running_on_sim = is_platform_hp_ski(); /* Kernel may be relocated by EFI loader */ xen_pstart = ia64_tpa(KERNEL_START); - - /* Must do this early -- e.g., spinlocks rely on get_current(). */ - //set_current(&idle0_vcpu); - ia64_r13 = (void *)&idle0_vcpu; - idle0_vcpu.domain = &idle0_domain; early_setup_arch(&cmdline); @@ -281,18 +278,22 @@ (xenheap_phys_end-__pa(heap_start)) >> 20, (xenheap_phys_end-__pa(heap_start)) >> 10); +printk("About to call scheduler_init()\n"); + scheduler_init(); + idle_vcpu[0] = (struct vcpu*) ia64_r13; + idle_domain = domain_create(IDLE_DOMAIN_ID, 0); + BUG_ON(idle_domain == NULL); + late_setup_arch(&cmdline); setup_per_cpu_areas(); mem_init(); -printk("About to call scheduler_init()\n"); - scheduler_init(); local_irq_disable(); init_IRQ (); printk("About to call init_xen_time()\n"); init_xen_time(); /* initialise the time */ -printk("About to call ac_timer_init()\n"); - ac_timer_init(); +printk("About to call timer_init()\n"); + timer_init(); #ifdef CONFIG_XEN_CONSOLE_INPUT /* CONFIG_SERIAL_8250_CONSOLE=n in dom0! */ initialize_keytable(); @@ -308,13 +309,9 @@ } smp_prepare_cpus(max_cpus); - /* We aren't hotplug-capable yet. */ - //BUG_ON(!cpus_empty(cpu_present_map)); for_each_cpu ( i ) cpu_set(i, cpu_present_map); - - //BUG_ON(!local_irq_is_enabled()); /* Enable IRQ to receive IPI (needed for ITC sync). */ local_irq_enable(); @@ -342,19 +339,14 @@ /* Create initial domain 0. */ -printk("About to call do_createdomain()\n"); - dom0 = do_createdomain(0, 0); - init_task.domain = &idle0_domain; - init_task.processor = 0; -// init_task.mm = &init_mm; - init_task.domain->arch.mm = &init_mm; -// init_task.thread = INIT_THREAD; - //arch_do_createdomain(current); +printk("About to call domain_create()\n"); + dom0 = domain_create(0, 0); + #ifdef CLONE_DOMAIN0 { int i; for (i = 0; i < CLONE_DOMAIN0; i++) { - clones[i] = do_createdomain(i+1, 0); + clones[i] = domain_create(i+1, 0); if ( clones[i] == NULL ) panic("Error creating domain0 clone %d\n",i); } @@ -431,8 +423,8 @@ local_irq_enable(); - printf("About to call schedulers_start dom0=%p, idle0_dom=%p\n", - dom0, &idle0_domain); + printf("About to call schedulers_start dom0=%p, idle_dom=%p\n", + dom0, &idle_domain); schedulers_start(); domain_unpause_by_systemcontroller(dom0); @@ -445,9 +437,10 @@ { char *p=info; - *p=0; - - p+=sprintf(p,"xen_%d.%d_ia64 ",XEN_VERSION,XEN_SUBVERSION); + p += sprintf(p,"xen-%d.%d-ia64 ", XEN_VERSION, XEN_SUBVERSION); + + if (vmx_enabled) + p += sprintf(p,"hvm-%d.%d-ia64 ", XEN_VERSION, XEN_SUBVERSION); *(p-1) = 0; diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/xen/xentime.c --- a/xen/arch/ia64/xen/xentime.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/xen/xentime.c Tue Jan 24 16:54:34 2006 @@ -196,7 +196,7 @@ //#endif /* double check, in case we got hit by a (slow) PMI: */ } while (time_after_eq(ia64_get_itc(), new_itm)); - raise_softirq(AC_TIMER_SOFTIRQ); + raise_softirq(TIMER_SOFTIRQ); return IRQ_HANDLED; } @@ -235,7 +235,7 @@ return 0; } -int reprogram_ac_timer(s_time_t timeout) +int reprogram_timer(s_time_t timeout) { struct vcpu *v = current; s_time_t expire; diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/Makefile --- a/xen/arch/x86/Makefile Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/Makefile Tue Jan 24 16:54:34 2006 @@ -32,7 +32,7 @@ OBJS := $(subst $(TARGET_SUBARCH)/xen.lds.o,,$(OBJS)) ifneq ($(crash_debug),y) -OBJS := $(patsubst cdb%.o,,$(OBJS)) +OBJS := $(patsubst gdbstub%.o,,$(OBJS)) endif default: $(TARGET) diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/apic.c --- a/xen/arch/x86/apic.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/apic.c Tue Jan 24 16:54:34 2006 @@ -870,7 +870,7 @@ * returns 1 on success * returns 0 if the timeout value is too small or in the past. */ -int reprogram_ac_timer(s_time_t timeout) +int reprogram_timer(s_time_t timeout) { s_time_t now; s_time_t expire; @@ -931,7 +931,7 @@ { ack_APIC_irq(); perfc_incrc(apic_timer); - raise_softirq(AC_TIMER_SOFTIRQ); + raise_softirq(TIMER_SOFTIRQ); } /* diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/domain.c Tue Jan 24 16:54:34 2006 @@ -110,6 +110,20 @@ break; } +void __attribute__((noreturn)) __machine_halt(void *unused) +{ + for ( ; ; ) + safe_halt(); +} + +void machine_halt(void) +{ + watchdog_disable(); + console_start_sync(); + smp_call_function(__machine_halt, NULL, 1, 0); + __machine_halt(NULL); +} + void machine_restart(char * __unused) { int i; @@ -117,8 +131,7 @@ if ( opt_noreboot ) { printk("Reboot disabled on cmdline: require manual reset\n"); - for ( ; ; ) - safe_halt(); + machine_halt(); } watchdog_disable(); @@ -164,20 +177,6 @@ } -void __attribute__((noreturn)) __machine_halt(void *unused) -{ - for ( ; ; ) - safe_halt(); -} - -void machine_halt(void) -{ - watchdog_disable(); - console_start_sync(); - smp_call_function(__machine_halt, NULL, 1, 0); - __machine_halt(NULL); -} - void dump_pageframe_info(struct domain *d) { struct pfn_info *page; @@ -215,7 +214,6 @@ memset(v, 0, sizeof(*v)); - memcpy(&v->arch, &idle_vcpu[0]->arch, sizeof(v->arch)); v->arch.flags = TF_kernel_mode; if ( is_idle_domain(d) ) @@ -223,40 +221,31 @@ percpu_ctxt[vcpu_id].curr_vcpu = v; v->arch.schedule_tail = continue_idle_domain; } - - if ( (v->vcpu_id = vcpu_id) != 0 ) - { - v->arch.schedule_tail = d->vcpu[0]->arch.schedule_tail; - v->arch.perdomain_ptes = - d->arch.mm_perdomain_pt + (vcpu_id << GDT_LDT_VCPU_SHIFT); - } + else + { + v->arch.schedule_tail = continue_nonidle_domain; + } + + v->arch.perdomain_ptes = + d->arch.mm_perdomain_pt + (vcpu_id << GDT_LDT_VCPU_SHIFT); + + v->arch.guest_vtable = __linear_l2_table; + v->arch.shadow_vtable = __shadow_linear_l2_table; +#if defined(__x86_64__) + v->arch.guest_vl3table = __linear_l3_table; + v->arch.guest_vl4table = __linear_l4_table; +#endif return v; } void free_vcpu_struct(struct vcpu *v) { - BUG_ON(v->next_in_list != NULL); - if ( v->vcpu_id != 0 ) - v->domain->vcpu[v->vcpu_id - 1]->next_in_list = NULL; xfree(v); } -void free_perdomain_pt(struct domain *d) -{ - free_xenheap_pages( - d->arch.mm_perdomain_pt, - get_order_from_bytes(PDPT_L1_ENTRIES * sizeof(l1_pgentry_t))); - -#ifdef __x86_64__ - free_xenheap_page(d->arch.mm_perdomain_l2); - free_xenheap_page(d->arch.mm_perdomain_l3); -#endif -} - -int arch_do_createdomain(struct vcpu *v) -{ - struct domain *d = v->domain; +int arch_domain_create(struct domain *d) +{ l1_pgentry_t gdt_l1e; int vcpuid, pdpt_order, rc; #ifdef __x86_64__ @@ -267,9 +256,7 @@ d->arch.mm_perdomain_pt = alloc_xenheap_pages(pdpt_order); if ( d->arch.mm_perdomain_pt == NULL ) goto fail_nomem; - memset(d->arch.mm_perdomain_pt, 0, PAGE_SIZE << pdpt_order); - v->arch.perdomain_ptes = d->arch.mm_perdomain_pt; /* * Map Xen segments into every VCPU's GDT, irrespective of whether every @@ -283,19 +270,11 @@ d->arch.mm_perdomain_pt[((vcpuid << GDT_LDT_VCPU_SHIFT) + FIRST_RESERVED_GDT_PAGE)] = gdt_l1e; - v->arch.guest_vtable = __linear_l2_table; - v->arch.shadow_vtable = __shadow_linear_l2_table; - #if defined(__i386__) - d->arch.mapcache.l1tab = d->arch.mm_perdomain_pt + - (GDT_LDT_MBYTES << (20 - PAGE_SHIFT)); - spin_lock_init(&d->arch.mapcache.lock); + mapcache_init(d); #else /* __x86_64__ */ - - v->arch.guest_vl3table = __linear_l3_table; - v->arch.guest_vl4table = __linear_l4_table; d->arch.mm_perdomain_l2 = alloc_xenheap_page(); d->arch.mm_perdomain_l3 = alloc_xenheap_page(); @@ -333,10 +312,7 @@ goto fail_nomem; memset(d->shared_info, 0, PAGE_SIZE); - v->vcpu_info = &d->shared_info->vcpu_info[v->vcpu_id]; SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d); - - v->arch.schedule_tail = continue_nonidle_domain; } return 0; @@ -349,6 +325,20 @@ #endif free_xenheap_pages(d->arch.mm_perdomain_pt, pdpt_order); return -ENOMEM; +} + +void arch_domain_destroy(struct domain *d) +{ + free_xenheap_pages( + d->arch.mm_perdomain_pt, + get_order_from_bytes(PDPT_L1_ENTRIES * sizeof(l1_pgentry_t))); + +#ifdef __x86_64__ + free_xenheap_page(d->arch.mm_perdomain_l2); + free_xenheap_page(d->arch.mm_perdomain_l3); +#endif + + free_xenheap_page(d->shared_info); } /* This is called by arch_final_setup_guest and do_boot_vcpu */ @@ -481,14 +471,6 @@ #ifdef __x86_64__ - -void toggle_guest_mode(struct vcpu *v) -{ - v->arch.flags ^= TF_kernel_mode; - __asm__ __volatile__ ( "swapgs" ); - update_pagetables(v); - write_ptbase(v); -} #define loadsegment(seg,value) ({ \ int __r = 1; \ @@ -659,35 +641,6 @@ percpu_ctxt[smp_processor_id()].dirty_segment_mask = dirty_segment_mask; } -long do_switch_to_user(void) -{ - struct cpu_user_regs *regs = guest_cpu_user_regs(); - struct switch_to_user stu; - struct vcpu *v = current; - - if ( unlikely(copy_from_user(&stu, (void *)regs->rsp, sizeof(stu))) || - unlikely(pagetable_get_paddr(v->arch.guest_table_user) == 0) ) - return -EFAULT; - - toggle_guest_mode(v); - - regs->rip = stu.rip; - regs->cs = stu.cs | 3; /* force guest privilege */ - regs->rflags = (stu.rflags & ~(EF_IOPL|EF_VM)) | EF_IE; - regs->rsp = stu.rsp; - regs->ss = stu.ss | 3; /* force guest privilege */ - - if ( !(stu.flags & VGCF_IN_SYSCALL) ) - { - regs->entry_vector = 0; - regs->r11 = stu.r11; - regs->rcx = stu.rcx; - } - - /* Saved %rax gets written back to regs->rax in entry.S. */ - return stu.rax; -} - #define switch_kernel_stack(_n,_c) ((void)0) #elif defined(__i386__) @@ -785,7 +738,8 @@ if ( unlikely(!cpu_isset(cpu, dirty_mask) && !cpus_empty(dirty_mask)) ) { /* Other cpus call __sync_lazy_execstate from flush ipi handler. */ - flush_tlb_mask(dirty_mask); + if ( !cpus_empty(next->vcpu_dirty_cpumask) ) + flush_tlb_mask(next->vcpu_dirty_cpumask); } local_irq_disable(); diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/mm.c Tue Jan 24 16:54:34 2006 @@ -297,7 +297,6 @@ #if defined(__x86_64__) /* If in user mode, switch to kernel mode just to read LDT mapping. */ - extern void toggle_guest_mode(struct vcpu *); int user_mode = !(v->arch.flags & TF_kernel_mode); #define TOGGLE_MODE() if ( user_mode ) toggle_guest_mode(v) #elif defined(__i386__) @@ -2971,7 +2970,6 @@ #ifdef CONFIG_X86_64 struct vcpu *v = current; - extern void toggle_guest_mode(struct vcpu *); int user_mode = !(v->arch.flags & TF_kernel_mode); #endif @@ -3001,7 +2999,7 @@ BUG(); } PTWR_PRINTK("[%c] disconnected_l1va at %p is %"PRIpte"\n", - PTWR_PRINT_WHICH, ptep, pte.l1); + PTWR_PRINT_WHICH, ptep, l1e_get_intpte(pte)); l1e_remove_flags(pte, _PAGE_RW); /* Write-protect the p.t. page in the guest page table. */ @@ -3019,18 +3017,31 @@ /* NB. INVLPG is a serialising instruction: flushes pending updates. */ flush_tlb_one_mask(d->domain_dirty_cpumask, l1va); PTWR_PRINTK("[%c] disconnected_l1va at %p now %"PRIpte"\n", - PTWR_PRINT_WHICH, ptep, pte.l1); + PTWR_PRINT_WHICH, ptep, l1e_get_intpte(pte)); /* * STEP 2. Validate any modified PTEs. */ - pl1e = d->arch.ptwr[which].pl1e; - modified = revalidate_l1(d, pl1e, d->arch.ptwr[which].page); - unmap_domain_page(pl1e); - perfc_incr_histo(wpt_updates, modified, PT_UPDATES); - ptwr_eip_stat_update(d->arch.ptwr[which].eip, d->domain_id, modified); - d->arch.ptwr[which].prev_nr_updates = modified; + if ( likely(d == current->domain) ) + { + pl1e = map_domain_page(l1e_get_pfn(pte)); + modified = revalidate_l1(d, pl1e, d->arch.ptwr[which].page); + unmap_domain_page(pl1e); + perfc_incr_histo(wpt_updates, modified, PT_UPDATES); + ptwr_eip_stat_update(d->arch.ptwr[which].eip, d->domain_id, modified); + d->arch.ptwr[which].prev_nr_updates = modified; + } + else + { + /* + * Must make a temporary global mapping, since we are running in the + * wrong address space, so no access to our own mapcache. + */ + pl1e = map_domain_page_global(l1e_get_pfn(pte)); + modified = revalidate_l1(d, pl1e, d->arch.ptwr[which].page); + unmap_domain_page_global(pl1e); + } /* * STEP 3. Reattach the L1 p.t. page into the current address space. @@ -3208,7 +3219,7 @@ { unsigned long pfn; struct pfn_info *page; - l1_pgentry_t pte; + l1_pgentry_t *pl1e, pte; l2_pgentry_t *pl2e, l2e; int which, flags; unsigned long l2_idx; @@ -3345,11 +3356,10 @@ } /* Temporarily map the L1 page, and make a copy of it. */ - d->arch.ptwr[which].pl1e = map_domain_page(pfn); - memcpy(d->arch.ptwr[which].page, - d->arch.ptwr[which].pl1e, - L1_PAGETABLE_ENTRIES * sizeof(l1_pgentry_t)); - + pl1e = map_domain_page(pfn); + memcpy(d->arch.ptwr[which].page, pl1e, PAGE_SIZE); + unmap_domain_page(pl1e); + /* Finally, make the p.t. page writable by the guest OS. */ l1e_add_flags(pte, _PAGE_RW); if ( unlikely(__put_user(pte.l1, @@ -3358,7 +3368,6 @@ MEM_LOG("ptwr: Could not update pte at %p", (unsigned long *) &linear_pg_table[l1_linear_offset(addr)]); /* Toss the writable pagetable state and crash. */ - unmap_domain_page(d->arch.ptwr[which].pl1e); d->arch.ptwr[which].l1va = 0; domain_crash(d); return 0; diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/nmi.c --- a/xen/arch/x86/nmi.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/nmi.c Tue Jan 24 16:54:34 2006 @@ -23,18 +23,20 @@ #include <xen/sched.h> #include <xen/console.h> #include <xen/smp.h> +#include <xen/keyhandler.h> #include <asm/current.h> #include <asm/mc146818rtc.h> #include <asm/msr.h> #include <asm/mpspec.h> #include <asm/debugger.h> #include <asm/div64.h> +#include <asm/apic.h> unsigned int nmi_watchdog = NMI_NONE; static unsigned int nmi_hz = HZ; static unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ static unsigned int nmi_p4_cccr_val; -static struct ac_timer nmi_timer[NR_CPUS]; +static struct timer nmi_timer[NR_CPUS]; static unsigned int nmi_timer_ticks[NR_CPUS]; /* @@ -132,7 +134,7 @@ { int cpu = smp_processor_id(); nmi_timer_ticks[cpu]++; - set_ac_timer(&nmi_timer[cpu], NOW() + MILLISECS(1000)); + set_timer(&nmi_timer[cpu], NOW() + MILLISECS(1000)); } static void disable_lapic_nmi_watchdog(void) @@ -308,8 +310,6 @@ void __pminit setup_apic_nmi_watchdog(void) { - int cpu = smp_processor_id(); - if (!nmi_watchdog) return; @@ -344,49 +344,37 @@ lapic_nmi_owner = LAPIC_NMI_WATCHDOG; nmi_active = 1; - - init_ac_timer(&nmi_timer[cpu], nmi_timer_fn, NULL, cpu); } static unsigned int last_irq_sums [NR_CPUS], alert_counter [NR_CPUS]; -static spinlock_t watchdog_lock = SPIN_LOCK_UNLOCKED; -static unsigned int watchdog_disable_count = 1; -static unsigned int watchdog_on; +static atomic_t watchdog_disable_count = ATOMIC_INIT(1); void watchdog_disable(void) { - unsigned long flags; - - spin_lock_irqsave(&watchdog_lock, flags); - - if ( watchdog_disable_count++ == 0 ) - watchdog_on = 0; - - spin_unlock_irqrestore(&watchdog_lock, flags); + atomic_inc(&watchdog_disable_count); } void watchdog_enable(void) { - unsigned int cpu; - unsigned long flags; - - spin_lock_irqsave(&watchdog_lock, flags); - - if ( --watchdog_disable_count == 0 ) + static unsigned long heartbeat_initialised; + unsigned int cpu; + + if ( !atomic_dec_and_test(&watchdog_disable_count) || + test_and_set_bit(0, &heartbeat_initialised) ) + return; + + /* + * Activate periodic heartbeats. We cannot do this earlier during + * setup because the timer infrastructure is not available. + */ + for_each_online_cpu ( cpu ) { - watchdog_on = 1; - /* - * Ensure periodic heartbeats are active. We cannot do this earlier - * during setup because the timer infrastructure is not available. - */ - for_each_online_cpu ( cpu ) - set_ac_timer(&nmi_timer[cpu], NOW()); - } - - spin_unlock_irqrestore(&watchdog_lock, flags); + init_timer(&nmi_timer[cpu], nmi_timer_fn, NULL, cpu); + set_timer(&nmi_timer[cpu], NOW()); + } } void nmi_watchdog_tick(struct cpu_user_regs * regs) @@ -395,7 +383,7 @@ sum = nmi_timer_ticks[cpu]; - if ( (last_irq_sums[cpu] == sum) && watchdog_on ) + if ( (last_irq_sums[cpu] == sum) && !atomic_read(&watchdog_disable_count) ) { /* * Ayiee, looks like this CPU is stuck ... wait a few IRQs (5 seconds) @@ -440,3 +428,51 @@ write_watchdog_counter(NULL); } } + +/* + * For some reason the destination shorthand for self is not valid + * when used with the NMI delivery mode. This is documented in Tables + * 8-3 and 8-4 in IA32 Reference Manual Volume 3. We send the IPI to + * our own APIC ID explicitly which is valid. + */ +static void do_nmi_trigger(unsigned char key) +{ + u32 id = apic_read(APIC_ID); + + printk("Triggering NMI on APIC ID %x\n", id); + + local_irq_disable(); + apic_wait_icr_idle(); + apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id)); + apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_INT_ASSERT); + local_irq_enable(); +} + +static void do_nmi_stats(unsigned char key) +{ + int i; + struct domain *d; + struct vcpu *v; + printk("CPU\tNMI\n"); + for_each_cpu(i) + printk("%3d\t%3d\n", i, nmi_count(i)); + + if ((d = dom0) == NULL) + return; + if ((v = d->vcpu[0]) == NULL) + return; + if (v->vcpu_flags & (VCPUF_nmi_pending|VCPUF_nmi_masked)) + printk("dom0 vpu0: NMI %s%s\n", + v->vcpu_flags & VCPUF_nmi_pending ? "pending " : "", + v->vcpu_flags & VCPUF_nmi_masked ? "masked " : ""); + else + printk("dom0 vcpu0: NMI neither pending nor masked\n"); +} + +static __init int register_nmi_trigger(void) +{ + register_keyhandler('n', do_nmi_trigger, "trigger an NMI"); + register_keyhandler('N', do_nmi_stats, "NMI statistics"); + return 0; +} +__initcall(register_nmi_trigger); diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/setup.c Tue Jan 24 16:54:34 2006 @@ -385,7 +385,7 @@ scheduler_init(); - idle_domain = do_createdomain(IDLE_DOMAIN_ID, 0); + idle_domain = domain_create(IDLE_DOMAIN_ID, 0); BUG_ON(idle_domain == NULL); set_current(idle_domain->vcpu[0]); @@ -423,7 +423,7 @@ trap_init(); - ac_timer_init(); + timer_init(); early_time_init(); @@ -478,7 +478,8 @@ schedulers_start(); - watchdog_enable(); + if ( opt_watchdog ) + watchdog_enable(); shadow_mode_init(); @@ -486,7 +487,7 @@ acm_init(&initrdidx, mbi, initial_images_start); /* Create initial domain 0. */ - dom0 = do_createdomain(0, 0); + dom0 = domain_create(0, 0); if ( dom0 == NULL ) panic("Error creating domain 0\n"); diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/shadow.c --- a/xen/arch/x86/shadow.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/shadow.c Tue Jan 24 16:54:34 2006 @@ -469,6 +469,7 @@ { unsigned long smfn; l2_pgentry_t *spl2e; + int i; SH_VVLOG("shadow_l2_table(gpfn=%lx, gmfn=%lx)", gpfn, gmfn); @@ -503,9 +504,11 @@ spl2e[l2_table_offset(SH_LINEAR_PT_VIRT_START)] = l2e_from_pfn(smfn, __PAGE_HYPERVISOR); - spl2e[l2_table_offset(PERDOMAIN_VIRT_START)] = - l2e_from_paddr(__pa(page_get_owner(pfn_to_page(gmfn))->arch.mm_perdomain_pt), - __PAGE_HYPERVISOR); + for ( i = 0; i < PDPT_L2_ENTRIES; i++ ) + spl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] = + l2e_from_page(virt_to_page(page_get_owner(pfn_to_page(gmfn))-> + arch.mm_perdomain_pt) + i, + __PAGE_HYPERVISOR); if ( shadow_mode_translate(d) ) // NB: not external { @@ -2135,6 +2138,7 @@ #if CONFIG_PAGING_LEVELS == 2 unsigned long hl2mfn; #endif + int need_sync = 0; int max_mode = ( shadow_mode_external(d) ? SHM_external : shadow_mode_translate(d) ? SHM_translate @@ -2150,8 +2154,8 @@ if ( max_mode & (SHM_enable | SHM_external) ) { if ( likely(v->arch.guest_vtable != NULL) ) - unmap_domain_page(v->arch.guest_vtable); - v->arch.guest_vtable = map_domain_page(gmfn); + unmap_domain_page_global(v->arch.guest_vtable); + v->arch.guest_vtable = map_domain_page_global(gmfn); } /* @@ -2166,8 +2170,17 @@ #elif CONFIG_PAGING_LEVELS == 4 smfn = shadow_l4_table(d, gpfn, gmfn); #endif - }else - shadow_sync_all(d); + } + else + { + /* + * move sync later in order to avoid this smfn been + * unshadowed occasionally + */ + need_sync = 1; + } + + if ( !get_shadow_ref(smfn) ) BUG(); old_smfn = pagetable_get_pfn(v->arch.shadow_table); @@ -2187,8 +2200,8 @@ ) { if ( v->arch.shadow_vtable ) - unmap_domain_page(v->arch.shadow_vtable); - v->arch.shadow_vtable = map_domain_page(smfn); + unmap_domain_page_global(v->arch.shadow_vtable); + v->arch.shadow_vtable = map_domain_page_global(smfn); } #if CONFIG_PAGING_LEVELS == 2 @@ -2204,8 +2217,8 @@ if ( unlikely(!(hl2mfn = __shadow_status(d, gpfn, PGT_hl2_shadow))) ) hl2mfn = shadow_hl2_table(d, gpfn, gmfn, smfn); if ( v->arch.hl2_vtable ) - unmap_domain_page(v->arch.hl2_vtable); - v->arch.hl2_vtable = map_domain_page(hl2mfn); + unmap_domain_page_global(v->arch.hl2_vtable); + v->arch.hl2_vtable = map_domain_page_global(hl2mfn); } /* @@ -2237,6 +2250,9 @@ local_flush_tlb(); } #endif /* CONFIG_PAGING_LEVELS == 2 */ + + if(likely(need_sync)) + shadow_sync_all(d); #if CONFIG_PAGING_LEVELS == 3 /* FIXME: PAE code to be written */ diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/shadow32.c --- a/xen/arch/x86/shadow32.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/shadow32.c Tue Jan 24 16:54:34 2006 @@ -726,6 +726,7 @@ l2_pgentry_t *mpl2e; struct pfn_info *mmfn_info; struct domain *d = v->domain; + int i; ASSERT(pagetable_get_paddr(v->arch.monitor_table) == 0); @@ -733,16 +734,17 @@ ASSERT(mmfn_info != NULL); mmfn = page_to_pfn(mmfn_info); - mpl2e = (l2_pgentry_t *)map_domain_page(mmfn); + mpl2e = (l2_pgentry_t *)map_domain_page_global(mmfn); memset(mpl2e, 0, PAGE_SIZE); memcpy(&mpl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], &idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE], HYPERVISOR_ENTRIES_PER_L2_PAGETABLE * sizeof(l2_pgentry_t)); - mpl2e[l2_table_offset(PERDOMAIN_VIRT_START)] = - l2e_from_paddr(__pa(d->arch.mm_perdomain_pt), - __PAGE_HYPERVISOR); + for ( i = 0; i < PDPT_L2_ENTRIES; i++ ) + mpl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] = + l2e_from_page(virt_to_page(d->arch.mm_perdomain_pt) + i, + __PAGE_HYPERVISOR); // map the phys_to_machine map into the Read-Only MPT space for this domain mpl2e[l2_table_offset(RO_MPT_VIRT_START)] = @@ -794,7 +796,7 @@ * Then free monitor_table. */ mfn = pagetable_get_pfn(v->arch.monitor_table); - unmap_domain_page(v->arch.monitor_vtable); + unmap_domain_page_global(v->arch.monitor_vtable); free_domheap_page(pfn_to_page(mfn)); v->arch.monitor_table = mk_pagetable(0); @@ -929,7 +931,7 @@ if ( v->arch.guest_vtable && (v->arch.guest_vtable != __linear_l2_table) ) { - unmap_domain_page(v->arch.guest_vtable); + unmap_domain_page_global(v->arch.guest_vtable); } if ( (mode & (SHM_translate | SHM_external)) == SHM_translate ) v->arch.guest_vtable = __linear_l2_table; @@ -942,7 +944,7 @@ if ( v->arch.shadow_vtable && (v->arch.shadow_vtable != __shadow_linear_l2_table) ) { - unmap_domain_page(v->arch.shadow_vtable); + unmap_domain_page_global(v->arch.shadow_vtable); } if ( !(mode & SHM_external) ) v->arch.shadow_vtable = __shadow_linear_l2_table; @@ -955,7 +957,7 @@ if ( v->arch.hl2_vtable && (v->arch.hl2_vtable != __linear_hl2_table) ) { - unmap_domain_page(v->arch.hl2_vtable); + unmap_domain_page_global(v->arch.hl2_vtable); } if ( (mode & (SHM_translate | SHM_external)) == SHM_translate ) v->arch.hl2_vtable = __linear_hl2_table; @@ -1508,6 +1510,7 @@ { unsigned long smfn; l2_pgentry_t *spl2e; + int i; SH_VVLOG("shadow_l2_table(gpfn=%lx, gmfn=%lx)", gpfn, gmfn); @@ -1542,9 +1545,11 @@ spl2e[l2_table_offset(SH_LINEAR_PT_VIRT_START)] = l2e_from_pfn(smfn, __PAGE_HYPERVISOR); - spl2e[l2_table_offset(PERDOMAIN_VIRT_START)] = - l2e_from_paddr(__pa(page_get_owner(pfn_to_page(gmfn))->arch.mm_perdomain_pt), - __PAGE_HYPERVISOR); + for ( i = 0; i < PDPT_L2_ENTRIES; i++ ) + spl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] = + l2e_from_page(virt_to_page(page_get_owner(pfn_to_page(gmfn))-> + arch.mm_perdomain_pt) + i, + __PAGE_HYPERVISOR); if ( shadow_mode_translate(d) ) // NB: not external { @@ -2891,6 +2896,7 @@ unsigned long gmfn = pagetable_get_pfn(v->arch.guest_table); unsigned long gpfn = __mfn_to_gpfn(d, gmfn); unsigned long smfn, hl2mfn, old_smfn; + int need_sync = 0; int max_mode = ( shadow_mode_external(d) ? SHM_external : shadow_mode_translate(d) ? SHM_translate @@ -2906,8 +2912,8 @@ if ( max_mode & (SHM_enable | SHM_external) ) { if ( likely(v->arch.guest_vtable != NULL) ) - unmap_domain_page(v->arch.guest_vtable); - v->arch.guest_vtable = map_domain_page(gmfn); + unmap_domain_page_global(v->arch.guest_vtable); + v->arch.guest_vtable = map_domain_page_global(gmfn); } /* @@ -2916,7 +2922,13 @@ if ( unlikely(!(smfn = __shadow_status(d, gpfn, PGT_base_page_table))) ) smfn = shadow_l2_table(d, gpfn, gmfn); else - shadow_sync_all(d); + { + /* + * move sync later in order to avoid this smfn been + * unshadowed occasionally + */ + need_sync = 1; + } if ( !get_shadow_ref(smfn) ) BUG(); old_smfn = pagetable_get_pfn(v->arch.shadow_table); @@ -2932,8 +2944,8 @@ if ( max_mode == SHM_external ) { if ( v->arch.shadow_vtable ) - unmap_domain_page(v->arch.shadow_vtable); - v->arch.shadow_vtable = map_domain_page(smfn); + unmap_domain_page_global(v->arch.shadow_vtable); + v->arch.shadow_vtable = map_domain_page_global(smfn); } /* @@ -2948,8 +2960,8 @@ if ( unlikely(!(hl2mfn = __shadow_status(d, gpfn, PGT_hl2_shadow))) ) hl2mfn = shadow_hl2_table(d, gpfn, gmfn, smfn); if ( v->arch.hl2_vtable ) - unmap_domain_page(v->arch.hl2_vtable); - v->arch.hl2_vtable = map_domain_page(hl2mfn); + unmap_domain_page_global(v->arch.hl2_vtable); + v->arch.hl2_vtable = map_domain_page_global(hl2mfn); } /* @@ -2980,6 +2992,9 @@ // XXX - maybe this can be optimized somewhat?? local_flush_tlb(); } + + if(likely(need_sync)) + shadow_sync_all(d); } void clear_all_shadow_status(struct domain *d) diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/shadow_public.c --- a/xen/arch/x86/shadow_public.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/shadow_public.c Tue Jan 24 16:54:34 2006 @@ -151,6 +151,8 @@ for (i = 0; i < L1_PAGETABLE_ENTRIES; i++) put_page_from_l1e(pl1e[i], d); + + unmap_domain_page(pl1e); } /* @@ -254,6 +256,7 @@ pae_l3 = map_domain_page(pagetable_get_pfn(d->arch.phys_table)); for (i = 0; i < PDP_ENTRIES; i++) l3[i] = l3e_from_pfn(l3e_get_pfn(pae_l3[i]), __PAGE_HYPERVISOR); + unmap_domain_page(pae_l3); unmap_domain_page(l4); unmap_domain_page(l3); @@ -275,7 +278,7 @@ ASSERT( mmfn_info ); mmfn = page_to_pfn(mmfn_info); - mpl4e = (l4_pgentry_t *) map_domain_page(mmfn); + mpl4e = (l4_pgentry_t *) map_domain_page_global(mmfn); memcpy(mpl4e, &idle_pg_table[0], PAGE_SIZE); mpl4e[l4_table_offset(PERDOMAIN_VIRT_START)] = l4e_from_paddr(__pa(d->arch.mm_perdomain_l3), __PAGE_HYPERVISOR); @@ -298,7 +301,7 @@ * free monitor_table. */ mfn = pagetable_get_pfn(v->arch.monitor_table); - unmap_domain_page(v->arch.monitor_vtable); + unmap_domain_page_global(v->arch.monitor_vtable); free_domheap_page(pfn_to_page(mfn)); v->arch.monitor_table = mk_pagetable(0); @@ -325,6 +328,7 @@ l2_pgentry_t *mpl2e; struct pfn_info *mmfn_info; struct domain *d = v->domain; + int i; ASSERT(pagetable_get_paddr(v->arch.monitor_table) == 0); @@ -332,16 +336,17 @@ ASSERT(mmfn_info != NULL); mmfn = page_to_pfn(mmfn_info); - mpl2e = (l2_pgentry_t *)map_domain_page(mmfn); + mpl2e = (l2_pgentry_t *)map_domain_page_global(mmfn); memset(mpl2e, 0, PAGE_SIZE); memcpy(&mpl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], &idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE], HYPERVISOR_ENTRIES_PER_L2_PAGETABLE * sizeof(l2_pgentry_t)); - mpl2e[l2_table_offset(PERDOMAIN_VIRT_START)] = - l2e_from_paddr(__pa(d->arch.mm_perdomain_pt), - __PAGE_HYPERVISOR); + for ( i = 0; i < PDPT_L2_ENTRIES; i++ ) + mpl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] = + l2e_from_page(virt_to_page(d->arch.mm_perdomain_pt) + i, + __PAGE_HYPERVISOR); // map the phys_to_machine map into the Read-Only MPT space for this domain mpl2e[l2_table_offset(RO_MPT_VIRT_START)] = @@ -393,7 +398,7 @@ * Then free monitor_table. */ mfn = pagetable_get_pfn(v->arch.monitor_table); - unmap_domain_page(v->arch.monitor_vtable); + unmap_domain_page_global(v->arch.monitor_vtable); free_domheap_page(pfn_to_page(mfn)); v->arch.monitor_table = mk_pagetable(0); @@ -977,7 +982,7 @@ if ( v->arch.guest_vtable && (v->arch.guest_vtable != __linear_l2_table) ) { - unmap_domain_page(v->arch.guest_vtable); + unmap_domain_page_global(v->arch.guest_vtable); } if ( (mode & (SHM_translate | SHM_external)) == SHM_translate ) v->arch.guest_vtable = __linear_l2_table; @@ -990,7 +995,7 @@ if ( v->arch.shadow_vtable && (v->arch.shadow_vtable != __shadow_linear_l2_table) ) { - unmap_domain_page(v->arch.shadow_vtable); + unmap_domain_page_global(v->arch.shadow_vtable); } if ( !(mode & SHM_external) && d->arch.ops->guest_paging_levels == 2) v->arch.shadow_vtable = __shadow_linear_l2_table; @@ -1004,7 +1009,7 @@ if ( v->arch.hl2_vtable && (v->arch.hl2_vtable != __linear_hl2_table) ) { - unmap_domain_page(v->arch.hl2_vtable); + unmap_domain_page_global(v->arch.hl2_vtable); } if ( (mode & (SHM_translate | SHM_external)) == SHM_translate ) v->arch.hl2_vtable = __linear_hl2_table; diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/time.c --- a/xen/arch/x86/time.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/time.c Tue Jan 24 16:54:34 2006 @@ -17,7 +17,7 @@ #include <xen/config.h> #include <xen/init.h> #include <xen/time.h> -#include <xen/ac_timer.h> +#include <xen/timer.h> #include <xen/smp.h> #include <xen/irq.h> #include <xen/softirq.h> @@ -56,7 +56,7 @@ s_time_t stime_local_stamp; s_time_t stime_master_stamp; struct time_scale tsc_scale; - struct ac_timer calibration_timer; + struct timer calibration_timer; } __cacheline_aligned; static struct cpu_time cpu_time[NR_CPUS]; @@ -163,7 +163,7 @@ /* Rough hack to allow accurate timers to sort-of-work with no APIC. */ if ( !cpu_has_apic ) - raise_softirq(AC_TIMER_SOFTIRQ); + raise_softirq(TIMER_SOFTIRQ); if ( using_pit ) pit_overflow(); @@ -342,7 +342,7 @@ /* Protected by platform_timer_lock. */ static u64 hpet_counter64, hpet_overflow_period; static u32 hpet_stamp; -static struct ac_timer hpet_overflow_timer; +static struct timer hpet_overflow_timer; static void hpet_overflow(void *unused) { @@ -354,7 +354,7 @@ hpet_stamp = counter; spin_unlock_irq(&platform_timer_lock); - set_ac_timer(&hpet_overflow_timer, NOW() + hpet_overflow_period); + set_timer(&hpet_overflow_timer, NOW() + hpet_overflow_period); } static u64 read_hpet_count(void) @@ -430,7 +430,7 @@ (void)do_div(hpet_overflow_period, (u32)hpet_rate); } - init_ac_timer(&hpet_overflow_timer, hpet_overflow, NULL, 0); + init_timer(&hpet_overflow_timer, hpet_overflow, NULL, 0); hpet_overflow(NULL); platform_timer_stamp = hpet_counter64; @@ -459,7 +459,7 @@ /* Protected by platform_timer_lock. */ static u64 cyclone_counter64; static u32 cyclone_stamp; -static struct ac_timer cyclone_overflow_timer; +static struct timer cyclone_overflow_timer; static volatile u32 *cyclone_timer; /* Cyclone MPMC0 register */ static void cyclone_overflow(void *unused) @@ -472,7 +472,7 @@ cyclone_stamp = counter; spin_unlock_irq(&platform_timer_lock); - set_ac_timer(&cyclone_overflow_timer, NOW() + MILLISECS(20000)); + set_timer(&cyclone_overflow_timer, NOW() + MILLISECS(20000)); } static u64 read_cyclone_count(void) @@ -510,7 +510,7 @@ read_platform_count = read_cyclone_count; - init_ac_timer(&cyclone_overflow_timer, cyclone_overflow, NULL, 0); + init_timer(&cyclone_overflow_timer, cyclone_overflow, NULL, 0); cyclone_overflow(NULL); platform_timer_stamp = cyclone_counter64; set_time_scale(&platform_timer_scale, CYCLONE_TIMER_FREQ); @@ -876,7 +876,7 @@ cpu_time[cpu].stime_master_stamp = curr_master_stime; out: - set_ac_timer(&cpu_time[cpu].calibration_timer, NOW() + EPOCH); + set_timer(&cpu_time[cpu].calibration_timer, NOW() + EPOCH); if ( cpu == 0 ) platform_time_calibration(); @@ -896,9 +896,9 @@ cpu_time[cpu].stime_master_stamp = now; cpu_time[cpu].stime_local_stamp = now; - init_ac_timer(&cpu_time[cpu].calibration_timer, + init_timer(&cpu_time[cpu].calibration_timer, local_time_calibration, NULL, cpu); - set_ac_timer(&cpu_time[cpu].calibration_timer, NOW() + EPOCH); + set_timer(&cpu_time[cpu].calibration_timer, NOW() + EPOCH); } /* Late init function (after all CPUs are booted). */ diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/traps.c Tue Jan 24 16:54:34 2006 @@ -130,9 +130,19 @@ static void show_guest_stack(struct cpu_user_regs *regs) { int i; - unsigned long *stack = (unsigned long *)regs->esp, addr; - - printk("Guest stack trace from "__OP"sp=%p:\n ", stack); + unsigned long *stack, addr; + + if ( VM86_MODE(regs) ) + { + stack = (unsigned long *)((regs->ss << 4) + (regs->esp & 0xffff)); + printk("Guest stack trace from ss:sp = %04x:%04x (VM86)\n ", + regs->ss, (uint16_t)(regs->esp & 0xffff)); + } + else + { + stack = (unsigned long *)regs->esp; + printk("Guest stack trace from "__OP"sp=%p:\n ", stack); + } for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ ) { @@ -596,7 +606,6 @@ u16 x; #if defined(__x86_64__) /* If in user mode, switch to kernel mode just to read I/O bitmap. */ - extern void toggle_guest_mode(struct vcpu *); int user_mode = !(v->arch.flags & TF_kernel_mode); #define TOGGLE_MODE() if ( user_mode ) toggle_guest_mode(v) #elif defined(__i386__) @@ -964,16 +973,26 @@ case 0x30: /* WRMSR */ /* Ignore the instruction if unprivileged. */ if ( !IS_PRIV(v->domain) ) - DPRINTK("Non-priv domain attempted WRMSR(%p,%08lx,%08lx).\n", - _p(regs->ecx), (long)regs->eax, (long)regs->edx); + { + u32 l, h; + if ( (rdmsr_user(regs->ecx, l, h) != 0) || + (regs->ecx != MSR_EFER) || + (regs->eax != l) || (regs->edx != h) ) + DPRINTK("Non-priv domain attempted WRMSR %p from " + "%08x:%08x to %08lx:%08lx.\n", + _p(regs->ecx), h, l, (long)regs->edx, (long)regs->eax); + } else if ( wrmsr_user(regs->ecx, regs->eax, regs->edx) ) goto fail; break; case 0x32: /* RDMSR */ if ( !IS_PRIV(v->domain) ) - DPRINTK("Non-priv domain attempted RDMSR(%p,%08lx,%08lx).\n", - _p(regs->ecx), (long)regs->eax, (long)regs->edx); + { + if ( regs->ecx != MSR_EFER ) + DPRINTK("Non-priv domain attempted RDMSR %p.\n", + _p(regs->ecx)); + } /* Everyone can read the MSR space. */ if ( rdmsr_user(regs->ecx, regs->eax, regs->edx) ) goto fail; @@ -1080,26 +1099,23 @@ return 0; } - -/* Defer dom0 notification to softirq context (unsafe in NMI context). */ -static unsigned long nmi_dom0_softirq_reason; -#define NMI_DOM0_PARITY_ERR 0 -#define NMI_DOM0_IO_ERR 1 -#define NMI_DOM0_UNKNOWN 2 - -static void nmi_dom0_softirq(void) -{ - if ( dom0 == NULL ) +static void nmi_softirq(void) +{ + /* Only used to defer wakeup of dom0,vcpu0 to a safe (non-NMI) context. */ + evtchn_notify(dom0->vcpu[0]); +} + +static void nmi_dom0_report(unsigned int reason_idx) +{ + struct domain *d; + + if ( (d = dom0) == NULL ) return; - if ( test_and_clear_bit(NMI_DOM0_PARITY_ERR, &nmi_dom0_softirq_reason) ) - send_guest_virq(dom0->vcpu[0], VIRQ_PARITY_ERR); - - if ( test_and_clear_bit(NMI_DOM0_IO_ERR, &nmi_dom0_softirq_reason) ) - send_guest_virq(dom0->vcpu[0], VIRQ_IO_ERR); - - if ( test_and_clear_bit(NMI_DOM0_UNKNOWN, &nmi_dom0_softirq_reason) ) - send_guest_virq(dom0->vcpu[0], VIRQ_NMI); + set_bit(reason_idx, &d->shared_info->arch.nmi_reason); + + if ( test_and_set_bit(_VCPUF_nmi_pending, &d->vcpu[0]->vcpu_flags) ) + raise_softirq(NMI_SOFTIRQ); /* not safe to wake up a vcpu here */ } asmlinkage void mem_parity_error(struct cpu_user_regs *regs) @@ -1107,8 +1123,7 @@ switch ( opt_nmi[0] ) { case 'd': /* 'dom0' */ - set_bit(NMI_DOM0_PARITY_ERR, &nmi_dom0_softirq_reason); - raise_softirq(NMI_DOM0_SOFTIRQ); + nmi_dom0_report(_XEN_NMIREASON_parity_error); case 'i': /* 'ignore' */ break; default: /* 'fatal' */ @@ -1127,8 +1142,7 @@ switch ( opt_nmi[0] ) { case 'd': /* 'dom0' */ - set_bit(NMI_DOM0_IO_ERR, &nmi_dom0_softirq_reason); - raise_softirq(NMI_DOM0_SOFTIRQ); + nmi_dom0_report(_XEN_NMIREASON_io_error); case 'i': /* 'ignore' */ break; default: /* 'fatal' */ @@ -1147,8 +1161,7 @@ switch ( opt_nmi[0] ) { case 'd': /* 'dom0' */ - set_bit(NMI_DOM0_UNKNOWN, &nmi_dom0_softirq_reason); - raise_softirq(NMI_DOM0_SOFTIRQ); + nmi_dom0_report(_XEN_NMIREASON_unknown); case 'i': /* 'ignore' */ break; default: /* 'fatal' */ @@ -1347,7 +1360,7 @@ cpu_init(); - open_softirq(NMI_DOM0_SOFTIRQ, nmi_dom0_softirq); + open_softirq(NMI_SOFTIRQ, nmi_softirq); } diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/vmx.c --- a/xen/arch/x86/vmx.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/vmx.c Tue Jan 24 16:54:34 2006 @@ -98,19 +98,18 @@ /* unmap IO shared page */ struct domain *d = v->domain; if ( d->arch.vmx_platform.shared_page_va ) - unmap_domain_page((void *)d->arch.vmx_platform.shared_page_va); + unmap_domain_page_global( + (void *)d->arch.vmx_platform.shared_page_va); } destroy_vmcs(&v->arch.arch_vmx); free_monitor_pagetable(v); vpit = &v->domain->arch.vmx_platform.vmx_pit; - if ( active_ac_timer(&(vpit->pit_timer)) ) - rem_ac_timer(&vpit->pit_timer); - if ( active_ac_timer(&v->arch.arch_vmx.hlt_timer) ) - rem_ac_timer(&v->arch.arch_vmx.hlt_timer); + kill_timer(&vpit->pit_timer); + kill_timer(&v->arch.arch_vmx.hlt_timer); if ( vmx_apic_support(v->domain) && (VLAPIC(v) != NULL) ) { - rem_ac_timer(&VLAPIC(v)->vlapic_timer); + kill_timer(&VLAPIC(v)->vlapic_timer); xfree(VLAPIC(v)); } } @@ -1599,7 +1598,7 @@ next_wakeup = next_pit; } if ( next_wakeup != - 1 ) - set_ac_timer(¤t->arch.arch_vmx.hlt_timer, next_wakeup); + set_timer(¤t->arch.arch_vmx.hlt_timer, next_wakeup); do_block(); } diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/vmx_intercept.c --- a/xen/arch/x86/vmx_intercept.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/vmx_intercept.c Tue Jan 24 16:54:34 2006 @@ -356,19 +356,19 @@ vpit->pending_intr_nr++; if ( test_bit(_VCPUF_running, &v->vcpu_flags) ) { vpit->scheduled += vpit->period; - set_ac_timer(&vpit->pit_timer, vpit->scheduled); + set_timer(&vpit->pit_timer, vpit->scheduled); } } void pickup_deactive_ticks(struct vmx_virpit *vpit) { - if ( !active_ac_timer(&(vpit->pit_timer)) ) { + if ( !active_timer(&(vpit->pit_timer)) ) { /* pick up missed timer tick */ missed_ticks(vpit); vpit->scheduled += vpit->period; - set_ac_timer(&vpit->pit_timer, vpit->scheduled); + set_timer(&vpit->pit_timer, vpit->scheduled); } } @@ -385,14 +385,14 @@ /* load init count*/ if (p->state == STATE_IORESP_HOOK) { /* set up actimer, handle re-init */ - if ( active_ac_timer(&(vpit->pit_timer)) ) { + if ( active_timer(&(vpit->pit_timer)) ) { VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT: guest reset PIT with channel %lx!\n", (unsigned long) ((p->u.data >> 24) & 0x3) ); - rem_ac_timer(&(vpit->pit_timer)); + stop_timer(&(vpit->pit_timer)); reinit = 1; } else { - init_ac_timer(&vpit->pit_timer, pit_timer_fn, v, v->processor); + init_timer(&vpit->pit_timer, pit_timer_fn, v, v->processor); } /* init count for this channel */ @@ -431,7 +431,7 @@ } vpit->scheduled = NOW() + vpit->period; - set_ac_timer(&vpit->pit_timer, vpit->scheduled); + set_timer(&vpit->pit_timer, vpit->scheduled); /*restore the state*/ p->state = STATE_IORESP_READY; diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/vmx_io.c --- a/xen/arch/x86/vmx_io.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/vmx_io.c Tue Jan 24 16:54:34 2006 @@ -819,7 +819,7 @@ if ( !vpit->first_injected ) { vpit->pending_intr_nr = 0; vpit->scheduled = NOW() + vpit->period; - set_ac_timer(&vpit->pit_timer, vpit->scheduled); + set_timer(&vpit->pit_timer, vpit->scheduled); vpit->first_injected = 1; } else { vpit->pending_intr_nr--; diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/vmx_vlapic.c --- a/xen/arch/x86/vmx_vlapic.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/vmx_vlapic.c Tue Jan 24 16:54:34 2006 @@ -391,7 +391,7 @@ (262144 / get_apic_bus_scale()) * vlapic->timer_divide_counter; vlapic->vlapic_timer.expires = cur + offset; - set_ac_timer(&(vlapic->vlapic_timer), vlapic->vlapic_timer.expires ); + set_timer(&(vlapic->vlapic_timer), vlapic->vlapic_timer.expires ); VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_begin_timer: " "bus_scale %x now %08x%08x expire %08x%08x " @@ -739,7 +739,7 @@ case APIC_TMICT: if (vlapic_timer_active(vlapic)) - rem_ac_timer(&(vlapic->vlapic_timer)); + stop_timer(&(vlapic->vlapic_timer)); vlapic->timer_initial = val; vlapic->timer_current = val; @@ -846,7 +846,7 @@ vlapic->timer_current = vlapic->timer_initial; offset = vlapic->timer_current * (262144/get_apic_bus_scale()) * vlapic->timer_divide_counter; vlapic->vlapic_timer.expires = NOW() + offset; - set_ac_timer(&(vlapic->vlapic_timer), vlapic->vlapic_timer.expires); + set_timer(&(vlapic->vlapic_timer), vlapic->vlapic_timer.expires); }else { vlapic->timer_current = 0; } @@ -986,7 +986,7 @@ vmx_vioapic_add_lapic(vlapic, v); - init_ac_timer(&vlapic->vlapic_timer, + init_timer(&vlapic->vlapic_timer, vlapic_timer_fn, vlapic, v->processor); #ifdef VLAPIC_NO_BIOS diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/vmx_vmcs.c --- a/xen/arch/x86/vmx_vmcs.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/vmx_vmcs.c Tue Jan 24 16:54:34 2006 @@ -193,7 +193,7 @@ domain_crash_synchronous(); } - p = map_domain_page(mpfn); + p = map_domain_page_global(mpfn); if (p == NULL) { printk("Can not map io request shared page for VMX domain.\n"); domain_crash_synchronous(); @@ -341,7 +341,7 @@ vlapic_init(v); vmx_set_host_env(v); - init_ac_timer(&v->arch.arch_vmx.hlt_timer, hlt_timer_fn, v, v->processor); + init_timer(&v->arch.arch_vmx.hlt_timer, hlt_timer_fn, v, v->processor); error |= __vmwrite(GUEST_LDTR_SELECTOR, 0); error |= __vmwrite(GUEST_LDTR_BASE, 0); diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/x86_32/asm-offsets.c --- a/xen/arch/x86/x86_32/asm-offsets.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/x86_32/asm-offsets.c Tue Jan 24 16:54:34 2006 @@ -65,6 +65,10 @@ arch.guest_context.kernel_ss); OFFSET(VCPU_kernel_sp, struct vcpu, arch.guest_context.kernel_sp); + OFFSET(VCPU_flags, struct vcpu, vcpu_flags); + OFFSET(VCPU_nmi_addr, struct vcpu, nmi_addr); + DEFINE(_VCPUF_nmi_pending, _VCPUF_nmi_pending); + DEFINE(_VCPUF_nmi_masked, _VCPUF_nmi_masked); BLANK(); OFFSET(VCPUINFO_upcall_pending, vcpu_info_t, evtchn_upcall_pending); diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/x86_32/domain_page.c --- a/xen/arch/x86/x86_32/domain_page.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/x86_32/domain_page.c Tue Jan 24 16:54:34 2006 @@ -1,14 +1,9 @@ /****************************************************************************** * domain_page.h * - * Allow temporary mapping of domain pages. Based on ideas from the - * Linux PKMAP code -- the copyrights and credits are retained below. - */ - -/* - * (C) 1999 Andrea Arcangeli, SuSE GmbH, andrea@xxxxxxx - * Gerhard Wichert, Siemens AG, Gerhard.Wichert@xxxxxxxxxxxxxx * - * Copyright (C) 1999 Ingo Molnar <mingo@xxxxxxxxxx> + * Allow temporary mapping of domain pages. + * + * Copyright (c) 2003-2006, Keir Fraser <keir@xxxxxxxxxxxxx> */ #include <xen/config.h> @@ -20,84 +15,203 @@ #include <asm/flushtlb.h> #include <asm/hardirq.h> -#define MAPCACHE_ORDER 10 -#define MAPCACHE_ENTRIES (1 << MAPCACHE_ORDER) - -/* Use a spare PTE bit to mark entries ready for recycling. */ -#define READY_FOR_TLB_FLUSH (1<<10) - -static void flush_all_ready_maps(void) -{ - struct mapcache *cache = ¤t->domain->arch.mapcache; - unsigned int i; - - for ( i = 0; i < MAPCACHE_ENTRIES; i++ ) - if ( (l1e_get_flags(cache->l1tab[i]) & READY_FOR_TLB_FLUSH) ) - cache->l1tab[i] = l1e_empty(); -} - -void *map_domain_pages(unsigned long pfn, unsigned int order) +void *map_domain_page(unsigned long pfn) { unsigned long va; - unsigned int idx, i, flags, vcpu = current->vcpu_id; - struct mapcache *cache = ¤t->domain->arch.mapcache; -#ifndef NDEBUG - unsigned int flush_count = 0; -#endif + unsigned int idx, i, vcpu = current->vcpu_id; + struct domain *d; + struct mapcache *cache; + struct vcpu_maphash_entry *hashent; ASSERT(!in_irq()); + perfc_incrc(map_domain_page_count); /* If we are the idle domain, ensure that we run on our own page tables. */ - if ( unlikely(is_idle_vcpu(current)) ) + d = current->domain; + if ( unlikely(is_idle_domain(d)) ) __sync_lazy_execstate(); + cache = &d->arch.mapcache; + + hashent = &cache->vcpu_maphash[vcpu].hash[MAPHASH_HASHFN(pfn)]; + if ( hashent->pfn == pfn ) + { + idx = hashent->idx; + hashent->refcnt++; + ASSERT(hashent->refcnt != 0); + ASSERT(l1e_get_pfn(cache->l1tab[idx]) == pfn); + goto out; + } + spin_lock(&cache->lock); /* Has some other CPU caused a wrap? We must flush if so. */ - if ( cache->epoch != cache->shadow_epoch[vcpu] ) - { + if ( unlikely(cache->epoch != cache->shadow_epoch[vcpu]) ) + { + cache->shadow_epoch[vcpu] = cache->epoch; + if ( NEED_FLUSH(tlbflush_time[smp_processor_id()], + cache->tlbflush_timestamp) ) + { + perfc_incrc(domain_page_tlb_flush); + local_flush_tlb(); + } + } + + idx = find_next_zero_bit(cache->inuse, MAPCACHE_ENTRIES, cache->cursor); + if ( unlikely(idx >= MAPCACHE_ENTRIES) ) + { + /* /First/, clean the garbage map and update the inuse list. */ + for ( i = 0; i < ARRAY_SIZE(cache->garbage); i++ ) + { + unsigned long x = xchg(&cache->garbage[i], 0); + cache->inuse[i] &= ~x; + } + + /* /Second/, flush TLBs. */ perfc_incrc(domain_page_tlb_flush); local_flush_tlb(); - cache->shadow_epoch[vcpu] = cache->epoch; - } - - do { - idx = cache->cursor = (cache->cursor + 1) & (MAPCACHE_ENTRIES - 1); - if ( unlikely(idx == 0) ) - { - ASSERT(flush_count++ == 0); - flush_all_ready_maps(); - perfc_incrc(domain_page_tlb_flush); - local_flush_tlb(); - cache->shadow_epoch[vcpu] = ++cache->epoch; - } - - flags = 0; - for ( i = 0; i < (1U << order); i++ ) - flags |= l1e_get_flags(cache->l1tab[idx+i]); - } - while ( flags & _PAGE_PRESENT ); - - for ( i = 0; i < (1U << order); i++ ) - cache->l1tab[idx+i] = l1e_from_pfn(pfn+i, __PAGE_HYPERVISOR); + cache->shadow_epoch[vcpu] = ++cache->epoch; + cache->tlbflush_timestamp = tlbflush_current_time(); + + idx = find_first_zero_bit(cache->inuse, MAPCACHE_ENTRIES); + ASSERT(idx < MAPCACHE_ENTRIES); + } + + set_bit(idx, cache->inuse); + cache->cursor = idx + 1; spin_unlock(&cache->lock); + cache->l1tab[idx] = l1e_from_pfn(pfn, __PAGE_HYPERVISOR); + + out: va = MAPCACHE_VIRT_START + (idx << PAGE_SHIFT); return (void *)va; } -void unmap_domain_pages(void *va, unsigned int order) -{ - unsigned int idx, i; +void unmap_domain_page(void *va) +{ + unsigned int idx; struct mapcache *cache = ¤t->domain->arch.mapcache; + unsigned long pfn; + struct vcpu_maphash_entry *hashent; + + ASSERT(!in_irq()); ASSERT((void *)MAPCACHE_VIRT_START <= va); ASSERT(va < (void *)MAPCACHE_VIRT_END); idx = ((unsigned long)va - MAPCACHE_VIRT_START) >> PAGE_SHIFT; - - for ( i = 0; i < (1U << order); i++ ) - l1e_add_flags(cache->l1tab[idx+i], READY_FOR_TLB_FLUSH); -} + pfn = l1e_get_pfn(cache->l1tab[idx]); + hashent = &cache->vcpu_maphash[current->vcpu_id].hash[MAPHASH_HASHFN(pfn)]; + + if ( hashent->idx == idx ) + { + ASSERT(hashent->pfn == pfn); + ASSERT(hashent->refcnt != 0); + hashent->refcnt--; + } + else if ( hashent->refcnt == 0 ) + { + if ( hashent->idx != MAPHASHENT_NOTINUSE ) + { + /* /First/, zap the PTE. */ + ASSERT(l1e_get_pfn(cache->l1tab[hashent->idx]) == hashent->pfn); + cache->l1tab[hashent->idx] = l1e_empty(); + /* /Second/, mark as garbage. */ + set_bit(hashent->idx, cache->garbage); + } + + /* Add newly-freed mapping to the maphash. */ + hashent->pfn = pfn; + hashent->idx = idx; + } + else + { + /* /First/, zap the PTE. */ + cache->l1tab[idx] = l1e_empty(); + /* /Second/, mark as garbage. */ + set_bit(idx, cache->garbage); + } +} + +void mapcache_init(struct domain *d) +{ + unsigned int i, j; + + d->arch.mapcache.l1tab = d->arch.mm_perdomain_pt + + (GDT_LDT_MBYTES << (20 - PAGE_SHIFT)); + spin_lock_init(&d->arch.mapcache.lock); + + /* Mark all maphash entries as not in use. */ + for ( i = 0; i < MAX_VIRT_CPUS; i++ ) + for ( j = 0; j < MAPHASH_ENTRIES; j++ ) + d->arch.mapcache.vcpu_maphash[i].hash[j].idx = + MAPHASHENT_NOTINUSE; +} + +#define GLOBALMAP_BITS (IOREMAP_MBYTES << (20 - PAGE_SHIFT)) +static unsigned long inuse[BITS_TO_LONGS(GLOBALMAP_BITS)]; +static unsigned long garbage[BITS_TO_LONGS(GLOBALMAP_BITS)]; +static unsigned int inuse_cursor; +static spinlock_t globalmap_lock = SPIN_LOCK_UNLOCKED; + +void *map_domain_page_global(unsigned long pfn) +{ + l2_pgentry_t *pl2e; + l1_pgentry_t *pl1e; + unsigned int idx, i; + unsigned long va; + + ASSERT(!in_irq() && local_irq_is_enabled()); + + spin_lock(&globalmap_lock); + + idx = find_next_zero_bit(inuse, GLOBALMAP_BITS, inuse_cursor); + va = IOREMAP_VIRT_START + (idx << PAGE_SHIFT); + if ( unlikely(va >= FIXADDR_START) ) + { + /* /First/, clean the garbage map and update the inuse list. */ + for ( i = 0; i < ARRAY_SIZE(garbage); i++ ) + { + unsigned long x = xchg(&garbage[i], 0); + inuse[i] &= ~x; + } + + /* /Second/, flush all TLBs to get rid of stale garbage mappings. */ + flush_tlb_all(); + + idx = find_first_zero_bit(inuse, GLOBALMAP_BITS); + va = IOREMAP_VIRT_START + (idx << PAGE_SHIFT); + ASSERT(va < FIXADDR_START); + } + + set_bit(idx, inuse); + inuse_cursor = idx + 1; + + spin_unlock(&globalmap_lock); + + pl2e = virt_to_xen_l2e(va); + pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(va); + *pl1e = l1e_from_pfn(pfn, __PAGE_HYPERVISOR); + + return (void *)va; +} + +void unmap_domain_page_global(void *va) +{ + unsigned long __va = (unsigned long)va; + l2_pgentry_t *pl2e; + l1_pgentry_t *pl1e; + unsigned int idx; + + /* /First/, we zap the PTE. */ + pl2e = virt_to_xen_l2e(__va); + pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(__va); + *pl1e = l1e_empty(); + + /* /Second/, we add to the garbage map. */ + idx = (__va - IOREMAP_VIRT_START) >> PAGE_SHIFT; + set_bit(idx, garbage); +} diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/x86_32/entry.S --- a/xen/arch/x86/x86_32/entry.S Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/x86_32/entry.S Tue Jan 24 16:54:34 2006 @@ -326,7 +326,9 @@ shl $IRQSTAT_shift,%eax test %ecx,irq_stat(%eax,1) jnz process_softirqs -/*test_guest_events:*/ + btr $_VCPUF_nmi_pending,VCPU_flags(%ebx) + jc process_nmi +test_guest_events: movl VCPU_vcpu_info(%ebx),%eax testb $0xFF,VCPUINFO_upcall_mask(%eax) jnz restore_all_guest @@ -348,7 +350,24 @@ sti call do_softirq jmp test_all_events - + + ALIGN +process_nmi: + movl VCPU_nmi_addr(%ebx),%eax + test %eax,%eax + jz test_all_events + bts $_VCPUF_nmi_masked,VCPU_flags(%ebx) + jc 1f + sti + leal VCPU_trap_bounce(%ebx),%edx + movl %eax,TRAPBOUNCE_eip(%edx) + movw $FLAT_KERNEL_CS,TRAPBOUNCE_cs(%edx) + movw $TBF_INTERRUPT,TRAPBOUNCE_flags(%edx) + call create_bounce_frame + jmp test_all_events +1: bts $_VCPUF_nmi_pending,VCPU_flags(%ebx) + jmp test_guest_events + /* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK: */ /* {EIP, CS, EFLAGS, [ESP, SS]} */ /* %edx == trap_bounce, %ebx == struct vcpu */ @@ -620,9 +639,7 @@ jne defer_nmi continue_nmi: - movl $(__HYPERVISOR_DS),%edx - movl %edx,%ds - movl %edx,%es + SET_XEN_SEGMENTS(d) movl %esp,%edx pushl %edx call do_nmi @@ -659,42 +676,6 @@ GET_GUEST_REGS(%ecx) movl %eax,UREGS_eax(%ecx) jmp do_sched_op - -do_switch_vm86: - # Reset the stack pointer - GET_GUEST_REGS(%ecx) - movl %ecx,%esp - - # GS:ESI == Ring-1 stack activation - movl UREGS_esp(%esp),%esi -VFLT1: mov UREGS_ss(%esp),%gs - - # ES:EDI == Ring-0 stack activation - leal UREGS_eip(%esp),%edi - - # Restore the hypercall-number-clobbered EAX on our stack frame -VFLT2: movl %gs:(%esi),%eax - movl %eax,UREGS_eax(%esp) - addl $4,%esi - - # Copy the VM86 activation from the ring-1 stack to the ring-0 stack - movl $(UREGS_user_sizeof-UREGS_eip)/4,%ecx -VFLT3: movl %gs:(%esi),%eax - stosl - addl $4,%esi - loop VFLT3 - - # Fix up EFLAGS: IOPL=0, IF=1, VM=1 - andl $~X86_EFLAGS_IOPL,UREGS_eflags(%esp) - orl $X86_EFLAGS_IF|X86_EFLAGS_VM,UREGS_eflags(%esp) - - jmp test_all_events - -.section __ex_table,"a" - .long VFLT1,domain_crash_synchronous - .long VFLT2,domain_crash_synchronous - .long VFLT3,domain_crash_synchronous -.previous .data @@ -744,11 +725,12 @@ .long do_grant_table_op /* 20 */ .long do_vm_assist .long do_update_va_mapping_otherdomain - .long do_switch_vm86 + .long do_iret .long do_vcpu_op .long do_ni_hypercall /* 25 */ .long do_mmuext_op - .long do_acm_op /* 27 */ + .long do_acm_op + .long do_nmi_op .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr @@ -777,11 +759,12 @@ .byte 3 /* do_grant_table_op */ /* 20 */ .byte 2 /* do_vm_assist */ .byte 5 /* do_update_va_mapping_otherdomain */ - .byte 0 /* do_switch_vm86 */ + .byte 0 /* do_iret */ .byte 3 /* do_vcpu_op */ .byte 0 /* do_ni_hypercall */ /* 25 */ .byte 4 /* do_mmuext_op */ .byte 1 /* do_acm_op */ + .byte 2 /* do_nmi_op */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/x86_32/traps.c --- a/xen/arch/x86/x86_32/traps.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/x86_32/traps.c Tue Jan 24 16:54:34 2006 @@ -157,6 +157,64 @@ __asm__ __volatile__ ( "hlt" ); } +asmlinkage unsigned long do_iret(void) +{ + struct cpu_user_regs *regs = guest_cpu_user_regs(); + u32 eflags; + + /* Check worst-case stack frame for overlap with Xen protected area. */ + if ( unlikely(!access_ok(regs->esp, 40)) ) + domain_crash_synchronous(); + + /* Pop and restore EAX (clobbered by hypercall). */ + if ( unlikely(__copy_from_user(®s->eax, (void __user *)regs->esp, 4)) ) + domain_crash_synchronous(); + regs->esp += 4; + + /* Pop and restore CS and EIP. */ + if ( unlikely(__copy_from_user(®s->eip, (void __user *)regs->esp, 8)) ) + domain_crash_synchronous(); + regs->esp += 8; + + /* + * Pop, fix up and restore EFLAGS. We fix up in a local staging area + * to avoid firing the BUG_ON(IOPL) check in arch_getdomaininfo_ctxt. + */ + if ( unlikely(__copy_from_user(&eflags, (void __user *)regs->esp, 4)) ) + domain_crash_synchronous(); + regs->esp += 4; + regs->eflags = (eflags & ~X86_EFLAGS_IOPL) | X86_EFLAGS_IF; + + if ( VM86_MODE(regs) ) + { + /* Return to VM86 mode: pop and restore ESP,SS,ES,DS,FS and GS. */ + if ( __copy_from_user(®s->esp, (void __user *)regs->esp, 24) ) + domain_crash_synchronous(); + } + else if ( unlikely(RING_0(regs)) ) + { + domain_crash_synchronous(); + } + else if ( !RING_1(regs) ) + { + /* Return to ring 2/3: pop and restore ESP and SS. */ + if ( __copy_from_user(®s->esp, (void __user *)regs->esp, 8) ) + domain_crash_synchronous(); + } + + /* No longer in NMI context. */ + clear_bit(_VCPUF_nmi_masked, ¤t->vcpu_flags); + + /* Restore upcall mask from saved value. */ + current->vcpu_info->evtchn_upcall_mask = regs->saved_upcall_mask; + + /* + * The hypercall exit path will overwrite EAX with this return + * value. + */ + return regs->eax; +} + BUILD_SMP_INTERRUPT(deferred_nmi, TRAP_deferred_nmi) asmlinkage void smp_deferred_nmi(struct cpu_user_regs regs) { diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/x86_64/asm-offsets.c --- a/xen/arch/x86/x86_64/asm-offsets.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/x86_64/asm-offsets.c Tue Jan 24 16:54:34 2006 @@ -65,6 +65,10 @@ arch.guest_context.syscall_callback_eip); OFFSET(VCPU_kernel_sp, struct vcpu, arch.guest_context.kernel_sp); + OFFSET(VCPU_flags, struct vcpu, vcpu_flags); + OFFSET(VCPU_nmi_addr, struct vcpu, nmi_addr); + DEFINE(_VCPUF_nmi_pending, _VCPUF_nmi_pending); + DEFINE(_VCPUF_nmi_masked, _VCPUF_nmi_masked); BLANK(); OFFSET(VCPUINFO_upcall_pending, vcpu_info_t, evtchn_upcall_pending); diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/x86_64/entry.S --- a/xen/arch/x86/x86_64/entry.S Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/x86_64/entry.S Tue Jan 24 16:54:34 2006 @@ -171,7 +171,9 @@ leaq irq_stat(%rip),%rcx testl $~0,(%rcx,%rax,1) jnz process_softirqs -/*test_guest_events:*/ + btr $_VCPUF_nmi_pending,VCPU_flags(%rbx) + jc process_nmi +test_guest_events: movq VCPU_vcpu_info(%rbx),%rax testb $0xFF,VCPUINFO_upcall_mask(%rax) jnz restore_all_guest @@ -322,6 +324,23 @@ call do_softirq jmp test_all_events + ALIGN +/* %rbx: struct vcpu */ +process_nmi: + movq VCPU_nmi_addr(%rbx),%rax + test %rax,%rax + jz test_all_events + bts $_VCPUF_nmi_masked,VCPU_flags(%rbx) + jc 1f + sti + leaq VCPU_trap_bounce(%rbx),%rdx + movq %rax,TRAPBOUNCE_eip(%rdx) + movw $(TBF_INTERRUPT|TBF_SLOW_IRET),TRAPBOUNCE_flags(%rdx) + call create_bounce_frame + jmp test_all_events +1: bts $_VCPUF_nmi_pending,VCPU_flags(%rbx) + jmp test_guest_events + /* CREATE A BASIC EXCEPTION FRAME ON GUEST OS STACK: */ /* { RCX, R11, [DS-GS,] [CR2,] [ERRCODE,] RIP, CS, RFLAGS, RSP, SS } */ /* %rdx: trap_bounce, %rbx: struct vcpu */ @@ -339,6 +358,9 @@ 1: /* In kernel context already: push new frame at existing %rsp. */ movq UREGS_rsp+8(%rsp),%rsi andb $0xfc,UREGS_cs+8(%rsp) # Indicate kernel context to guest. + testw $(TBF_SLOW_IRET),TRAPBOUNCE_flags(%rdx) + jz 2f + orb $0x01,UREGS_cs+8(%rsp) 2: andq $~0xf,%rsi # Stack frames are 16-byte aligned. movq $HYPERVISOR_VIRT_START,%rax cmpq %rax,%rsi @@ -569,7 +591,7 @@ SAVE_ALL movq %rsp,%rdi call do_nmi - jmp restore_all_xen + jmp ret_from_intr do_arch_sched_op: # Ensure we return success even if we return via schedule_tail() @@ -626,11 +648,12 @@ .quad do_grant_table_op /* 20 */ .quad do_vm_assist .quad do_update_va_mapping_otherdomain - .quad do_switch_to_user + .quad do_iret .quad do_vcpu_op .quad do_set_segment_base /* 25 */ .quad do_mmuext_op .quad do_acm_op + .quad do_nmi_op .rept NR_hypercalls-((.-hypercall_table)/4) .quad do_ni_hypercall .endr @@ -659,11 +682,12 @@ .byte 3 /* do_grant_table_op */ /* 20 */ .byte 2 /* do_vm_assist */ .byte 4 /* do_update_va_mapping_otherdomain */ - .byte 0 /* do_switch_to_user */ + .byte 0 /* do_iret */ .byte 3 /* do_vcpu_op */ .byte 2 /* do_set_segment_base */ /* 25 */ .byte 4 /* do_mmuext_op */ .byte 1 /* do_acm_op */ + .byte 2 /* do_nmi_op */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/x86_64/traps.c --- a/xen/arch/x86/x86_64/traps.c Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/x86_64/traps.c Tue Jan 24 16:54:34 2006 @@ -12,6 +12,7 @@ #include <asm/current.h> #include <asm/flushtlb.h> #include <asm/msr.h> +#include <asm/shadow.h> #include <asm/vmx.h> void show_registers(struct cpu_user_regs *regs) @@ -113,6 +114,52 @@ __asm__ __volatile__ ( "hlt" ); } +void toggle_guest_mode(struct vcpu *v) +{ + v->arch.flags ^= TF_kernel_mode; + __asm__ __volatile__ ( "swapgs" ); + update_pagetables(v); + write_ptbase(v); +} + +long do_iret(void) +{ + struct cpu_user_regs *regs = guest_cpu_user_regs(); + struct iret_context iret_saved; + struct vcpu *v = current; + + if ( unlikely(copy_from_user(&iret_saved, (void *)regs->rsp, + sizeof(iret_saved))) ) + domain_crash_synchronous(); + + /* Returning to user mode? */ + if ( (iret_saved.cs & 3) == 3 ) + { + if ( unlikely(pagetable_get_paddr(v->arch.guest_table_user) == 0) ) + return -EFAULT; + toggle_guest_mode(v); + } + + regs->rip = iret_saved.rip; + regs->cs = iret_saved.cs | 3; /* force guest privilege */ + regs->rflags = (iret_saved.rflags & ~(EF_IOPL|EF_VM)) | EF_IE; + regs->rsp = iret_saved.rsp; + regs->ss = iret_saved.ss | 3; /* force guest privilege */ + + if ( !(iret_saved.flags & VGCF_IN_SYSCALL) ) + { + regs->entry_vector = 0; + regs->r11 = iret_saved.r11; + regs->rcx = iret_saved.rcx; + } + + /* No longer in NMI context. */ + clear_bit(_VCPUF_nmi_masked, ¤t->vcpu_flags); + + /* Saved %rax gets written back to regs->rax in entry.S. */ + return iret_saved.rax; +} + asmlinkage void syscall_enter(void); void __init percpu_traps_init(void) { diff -r 40bb46f599d9 -r a38c292e8390 xen/common/Makefile --- a/xen/common/Makefile Tue Jan 10 15:21:00 2006 +++ b/xen/common/Makefile Tue Jan 24 16:54:34 2006 @@ -3,6 +3,9 @@ ifneq ($(perfc),y) OBJS := $(subst perfc.o,,$(OBJS)) +endif +ifneq ($(crash_debug),y) +OBJS := $(patsubst gdbstub.o,,$(OBJS)) endif default: common.o diff -r 40bb46f599d9 -r a38c292e8390 xen/common/dom0_ops.c --- a/xen/common/dom0_ops.c Tue Jan 10 15:21:00 2006 +++ b/xen/common/dom0_ops.c Tue Jan 24 16:54:34 2006 @@ -208,7 +208,7 @@ pro = i; ret = -ENOMEM; - if ( (d = do_createdomain(dom, pro)) == NULL ) + if ( (d = domain_create(dom, pro)) == NULL ) break; memcpy(d->handle, op->u.createdomain.handle, @@ -323,7 +323,7 @@ new_affinity = v->cpu_affinity; memcpy(cpus_addr(new_affinity), &op->u.setvcpuaffinity.cpumap, - min((int)BITS_TO_LONGS(NR_CPUS), + min((int)(BITS_TO_LONGS(NR_CPUS) * sizeof(long)), (int)sizeof(op->u.setvcpuaffinity.cpumap))); ret = vcpu_set_affinity(v, &new_affinity); @@ -450,6 +450,10 @@ if ( (v = d->vcpu[op->u.getvcpucontext.vcpu]) == NULL ) goto getvcpucontext_out; + ret = -ENODATA; + if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) ) + goto getvcpucontext_out; + ret = -ENOMEM; if ( (c = xmalloc(struct vcpu_guest_context)) == NULL ) goto getvcpucontext_out; @@ -501,7 +505,7 @@ op->u.getvcpuinfo.cpumap = 0; memcpy(&op->u.getvcpuinfo.cpumap, cpus_addr(v->cpu_affinity), - min((int)BITS_TO_LONGS(NR_CPUS), + min((int)(BITS_TO_LONGS(NR_CPUS) * sizeof(long)), (int)sizeof(op->u.getvcpuinfo.cpumap))); ret = 0; diff -r 40bb46f599d9 -r a38c292e8390 xen/common/domain.c --- a/xen/common/domain.c Tue Jan 10 15:21:00 2006 +++ b/xen/common/domain.c Tue Jan 24 16:54:34 2006 @@ -29,7 +29,7 @@ struct domain *dom0; -struct domain *do_createdomain(domid_t dom_id, unsigned int cpu) +struct domain *domain_create(domid_t dom_id, unsigned int cpu) { struct domain *d, **pd; struct vcpu *v; @@ -46,25 +46,27 @@ INIT_LIST_HEAD(&d->page_list); INIT_LIST_HEAD(&d->xenpage_list); + rangeset_domain_initialise(d); + if ( !is_idle_domain(d) ) + { set_bit(_DOMF_ctrl_pause, &d->domain_flags); - - if ( !is_idle_domain(d) && - ((evtchn_init(d) != 0) || (grant_table_create(d) != 0)) ) - goto fail1; - + if ( evtchn_init(d) != 0 ) + goto fail1; + if ( grant_table_create(d) != 0 ) + goto fail2; + } + + if ( arch_domain_create(d) != 0 ) + goto fail3; + if ( (v = alloc_vcpu(d, 0, cpu)) == NULL ) - goto fail2; - - rangeset_domain_initialise(d); + goto fail4; d->iomem_caps = rangeset_new(d, "I/O Memory", RANGESETF_prettyprint_hex); d->irq_caps = rangeset_new(d, "Interrupts", 0); - - if ( (d->iomem_caps == NULL) || - (d->irq_caps == NULL) || - (arch_do_createdomain(v) != 0) ) - goto fail3; + if ( (d->iomem_caps == NULL) || (d->irq_caps == NULL) ) + goto fail4; /* NB. alloc_vcpu() is undone in free_domain() */ if ( !is_idle_domain(d) ) { @@ -82,12 +84,16 @@ return d; + fail4: + arch_domain_destroy(d); fail3: + if ( !is_idle_domain(d) ) + grant_table_destroy(d); + fail2: + if ( !is_idle_domain(d) ) + evtchn_destroy(d); + fail1: rangeset_domain_destroy(d); - fail2: - grant_table_destroy(d); - fail1: - evtchn_destroy(d); free_domain(d); return NULL; } @@ -256,16 +262,16 @@ /* Release resources belonging to task @p. */ -void domain_destruct(struct domain *d) +void domain_destroy(struct domain *d) { struct domain **pd; atomic_t old, new; BUG_ON(!test_bit(_DOMF_dying, &d->domain_flags)); - /* May be already destructed, or get_domain() can race us. */ + /* May be already destroyed, or get_domain() can race us. */ _atomic_set(old, 0); - _atomic_set(new, DOMAIN_DESTRUCTED); + _atomic_set(new, DOMAIN_DESTROYED); old = atomic_compareandswap(old, new, &d->refcnt); if ( _atomic_read(old) != 0 ) return; @@ -287,8 +293,7 @@ evtchn_destroy(d); grant_table_destroy(d); - free_perdomain_pt(d); - free_xenheap_page(d->shared_info); + arch_domain_destroy(d); free_domain(d); @@ -369,15 +374,16 @@ if ( (vcpu >= MAX_VIRT_CPUS) || ((v = d->vcpu[vcpu]) == NULL) ) return -EINVAL; - if ( !test_bit(_DOMF_ctrl_pause, &d->domain_flags) ) - return -EINVAL; - if ( (c = xmalloc(struct vcpu_guest_context)) == NULL ) return -ENOMEM; + + domain_pause(d); rc = -EFAULT; if ( copy_from_user(c, setvcpucontext->ctxt, sizeof(*c)) == 0 ) rc = arch_set_info_guest(v, c); + + domain_unpause(d); xfree(c); return rc; diff -r 40bb46f599d9 -r a38c292e8390 xen/common/kernel.c --- a/xen/common/kernel.c Tue Jan 10 15:21:00 2006 +++ b/xen/common/kernel.c Tue Jan 24 16:54:34 2006 @@ -11,6 +11,7 @@ #include <xen/compile.h> #include <xen/sched.h> #include <asm/current.h> +#include <public/nmi.h> #include <public/version.h> void cmdline_parse(char *cmdline) @@ -146,6 +147,43 @@ } return -ENOSYS; +} + +long do_nmi_op(unsigned int cmd, void *arg) +{ + struct vcpu *v = current; + struct domain *d = current->domain; + long rc = 0; + + switch ( cmd ) + { + case XENNMI_register_callback: + if ( (d->domain_id != 0) || (v->vcpu_id != 0) ) + { + rc = -EINVAL; + } + else + { + v->nmi_addr = (unsigned long)arg; +#ifdef CONFIG_X86 + /* + * If no handler was registered we can 'lose the NMI edge'. + * Re-assert it now. + */ + if ( d->shared_info->arch.nmi_reason != 0 ) + set_bit(_VCPUF_nmi_pending, &v->vcpu_flags); +#endif + } + break; + case XENNMI_unregister_callback: + v->nmi_addr = 0; + break; + default: + rc = -ENOSYS; + break; + } + + return rc; } long do_vm_assist(unsigned int cmd, unsigned int type) diff -r 40bb46f599d9 -r a38c292e8390 xen/common/memory.c --- a/xen/common/memory.c Tue Jan 10 15:21:00 2006 +++ b/xen/common/memory.c Tue Jan 24 16:54:34 2006 @@ -38,10 +38,7 @@ if ( (extent_order != 0) && !multipage_allocation_permitted(current->domain) ) - { - DPRINTK("Only I/O-capable domains may allocate multi-page extents.\n"); return 0; - } for ( i = 0; i < nr_extents; i++ ) { diff -r 40bb46f599d9 -r a38c292e8390 xen/common/sched_bvt.c --- a/xen/common/sched_bvt.c Tue Jan 10 15:21:00 2006 +++ b/xen/common/sched_bvt.c Tue Jan 24 16:54:34 2006 @@ -20,7 +20,7 @@ #include <xen/delay.h> #include <xen/event.h> #include <xen/time.h> -#include <xen/ac_timer.h> +#include <xen/timer.h> #include <xen/perfc.h> #include <xen/sched-if.h> #include <xen/softirq.h> @@ -45,9 +45,9 @@ limits*/ s32 warp_value; /* virtual time warp */ s_time_t warpl; /* warp limit */ - struct ac_timer warp_timer; /* deals with warpl */ + struct timer warp_timer; /* deals with warpl */ s_time_t warpu; /* unwarp time requirement */ - struct ac_timer unwarp_timer; /* deals with warpu */ + struct timer unwarp_timer; /* deals with warpu */ struct bvt_vcpu_info vcpu_inf[MAX_VIRT_CPUS]; }; @@ -98,9 +98,9 @@ static void warp_timer_fn(void *data) { struct bvt_dom_info *inf = data; - unsigned int cpu = inf->domain->vcpu[0]->processor; - - spin_lock_irq(&schedule_data[cpu].schedule_lock); + struct vcpu *v = inf->domain->vcpu[0]; + + vcpu_schedule_lock_irq(v); inf->warp = 0; @@ -108,28 +108,28 @@ if ( inf->warpu == 0 ) { inf->warpback = 0; - cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ); - } - - set_ac_timer(&inf->unwarp_timer, NOW() + inf->warpu); - - spin_unlock_irq(&schedule_data[cpu].schedule_lock); + cpu_raise_softirq(v->processor, SCHEDULE_SOFTIRQ); + } + + set_timer(&inf->unwarp_timer, NOW() + inf->warpu); + + vcpu_schedule_unlock_irq(v); } static void unwarp_timer_fn(void *data) { struct bvt_dom_info *inf = data; - unsigned int cpu = inf->domain->vcpu[0]->processor; - - spin_lock_irq(&schedule_data[cpu].schedule_lock); + struct vcpu *v = inf->domain->vcpu[0]; + + vcpu_schedule_lock_irq(v); if ( inf->warpback ) { inf->warp = 1; - cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ); + cpu_raise_softirq(v->processor, SCHEDULE_SOFTIRQ); } - spin_unlock_irq(&schedule_data[cpu].schedule_lock); + vcpu_schedule_unlock_irq(v); } static inline u32 calc_avt(struct vcpu *d, s_time_t now) @@ -168,6 +168,7 @@ static int bvt_alloc_task(struct vcpu *v) { struct domain *d = v->domain; + struct bvt_dom_info *inf; if ( (d->sched_priv == NULL) ) { @@ -176,32 +177,12 @@ memset(d->sched_priv, 0, sizeof(struct bvt_dom_info)); } - v->sched_priv = &BVT_INFO(d)->vcpu_inf[v->vcpu_id]; - - BVT_INFO(d)->vcpu_inf[v->vcpu_id].inf = BVT_INFO(d); - BVT_INFO(d)->vcpu_inf[v->vcpu_id].vcpu = v; - - return 0; -} - -/* - * Add and remove a domain - */ -static void bvt_add_task(struct vcpu *v) -{ - struct bvt_dom_info *inf = BVT_INFO(v->domain); - struct bvt_vcpu_info *einf = EBVT_INFO(v); - ASSERT(inf != NULL); - ASSERT(v != NULL); - - /* Allocate per-CPU context if this is the first domain to be added. */ - if ( CPU_INFO(v->processor) == NULL ) - { - schedule_data[v->processor].sched_priv = xmalloc(struct bvt_cpu_info); - BUG_ON(CPU_INFO(v->processor) == NULL); - INIT_LIST_HEAD(RUNQUEUE(v->processor)); - CPU_SVT(v->processor) = 0; - } + inf = BVT_INFO(d); + + v->sched_priv = &inf->vcpu_inf[v->vcpu_id]; + + inf->vcpu_inf[v->vcpu_id].inf = BVT_INFO(d); + inf->vcpu_inf[v->vcpu_id].vcpu = v; if ( v->vcpu_id == 0 ) { @@ -214,11 +195,28 @@ inf->warpl = MILLISECS(2000); inf->warpu = MILLISECS(1000); /* Initialise the warp timers. */ - init_ac_timer(&inf->warp_timer, warp_timer_fn, inf, v->processor); - init_ac_timer(&inf->unwarp_timer, unwarp_timer_fn, inf, v->processor); - } - - einf->vcpu = v; + init_timer(&inf->warp_timer, warp_timer_fn, inf, v->processor); + init_timer(&inf->unwarp_timer, unwarp_timer_fn, inf, v->processor); + } + + return 0; +} + +/* + * Add and remove a domain + */ +static void bvt_add_task(struct vcpu *v) +{ + struct bvt_vcpu_info *einf = EBVT_INFO(v); + + /* Allocate per-CPU context if this is the first domain to be added. */ + if ( CPU_INFO(v->processor) == NULL ) + { + schedule_data[v->processor].sched_priv = xmalloc(struct bvt_cpu_info); + BUG_ON(CPU_INFO(v->processor) == NULL); + INIT_LIST_HEAD(RUNQUEUE(v->processor)); + CPU_SVT(v->processor) = 0; + } if ( is_idle_vcpu(v) ) { @@ -271,7 +269,7 @@ if ( is_idle_vcpu(curr) || (einf->evt <= curr_evt) ) cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ); else if ( schedule_data[cpu].s_timer.expires > r_time ) - set_ac_timer(&schedule_data[cpu].s_timer, r_time); + set_timer(&schedule_data[cpu].s_timer, r_time); } @@ -305,8 +303,14 @@ */ static void bvt_free_task(struct domain *d) { - ASSERT(d->sched_priv != NULL); - xfree(d->sched_priv); + struct bvt_dom_info *inf = BVT_INFO(d); + + ASSERT(inf != NULL); + + kill_timer(&inf->warp_timer); + kill_timer(&inf->unwarp_timer); + + xfree(inf); } /* Control the scheduler. */ @@ -355,10 +359,10 @@ inf->warpu = MILLISECS(warpu); /* If the unwarp timer set up it needs to be removed */ - rem_ac_timer(&inf->unwarp_timer); + stop_timer(&inf->unwarp_timer); /* If we stop warping the warp timer needs to be removed */ if ( !warpback ) - rem_ac_timer(&inf->warp_timer); + stop_timer(&inf->warp_timer); } else if ( cmd->direction == SCHED_INFO_GET ) { @@ -405,7 +409,7 @@ prev_einf->evt = calc_evt(prev, prev_einf->avt); if(prev_inf->warpback && prev_inf->warpl > 0) - rem_ac_timer(&prev_inf->warp_timer); + stop_timer(&prev_inf->warp_timer); __del_from_runqueue(prev); @@ -455,7 +459,7 @@ } if ( next_einf->inf->warp && next_einf->inf->warpl > 0 ) - set_ac_timer(&next_einf->inf->warp_timer, now + next_einf->inf->warpl); + set_timer(&next_einf->inf->warp_timer, now + next_einf->inf->warpl); /* Extract the domain pointers from the dom infos */ next = next_einf->vcpu; diff -r 40bb46f599d9 -r a38c292e8390 xen/common/sched_sedf.c --- a/xen/common/sched_sedf.c Tue Jan 10 15:21:00 2006 +++ b/xen/common/sched_sedf.c Tue Jan 24 16:54:34 2006 @@ -9,7 +9,7 @@ #include <xen/sched.h> #include <xen/sched-if.h> #include <public/sched_ctl.h> -#include <xen/ac_timer.h> +#include <xen/timer.h> #include <xen/softirq.h> #include <xen/time.h> diff -r 40bb46f599d9 -r a38c292e8390 xen/common/schedule.c --- a/xen/common/schedule.c Tue Jan 10 15:21:00 2006 +++ b/xen/common/schedule.c Tue Jan 24 16:54:34 2006 @@ -21,7 +21,7 @@ #include <xen/delay.h> #include <xen/event.h> #include <xen/time.h> -#include <xen/ac_timer.h> +#include <xen/timer.h> #include <xen/perfc.h> #include <xen/sched-if.h> #include <xen/softirq.h> @@ -71,17 +71,31 @@ : (typeof(ops.fn(__VA_ARGS__)))0 ) /* Per-CPU periodic timer sends an event to the currently-executing domain. */ -static struct ac_timer t_timer[NR_CPUS]; +static struct timer t_timer[NR_CPUS]; + +struct domain *alloc_domain(void) +{ + struct domain *d; + + if ( (d = xmalloc(struct domain)) != NULL ) + memset(d, 0, sizeof(*d)); + + return d; +} void free_domain(struct domain *d) { + struct vcpu *v; int i; + for_each_vcpu ( d, v ) + sched_rem_domain(v); + SCHED_OP(free_task, d); for ( i = MAX_VIRT_CPUS-1; i >= 0; i-- ) - if ( d->vcpu[i] != NULL ) - free_vcpu_struct(d->vcpu[i]); + if ( (v = d->vcpu[i]) != NULL ) + free_vcpu_struct(v); xfree(d); } @@ -100,48 +114,33 @@ v->vcpu_id = vcpu_id; v->processor = cpu_id; atomic_set(&v->pausecnt, 0); + v->vcpu_info = &d->shared_info->vcpu_info[vcpu_id]; v->cpu_affinity = is_idle_domain(d) ? cpumask_of_cpu(cpu_id) : CPU_MASK_ALL; - d->vcpu[vcpu_id] = v; + if ( (vcpu_id != 0) && !is_idle_domain(d) ) + set_bit(_VCPUF_down, &v->vcpu_flags); if ( SCHED_OP(alloc_task, v) < 0 ) { - d->vcpu[vcpu_id] = NULL; free_vcpu_struct(v); return NULL; } + d->vcpu[vcpu_id] = v; + if ( vcpu_id != 0 ) + d->vcpu[v->vcpu_id-1]->next_in_list = v; + sched_add_domain(v); - if ( vcpu_id != 0 ) - { - v->vcpu_info = &d->shared_info->vcpu_info[vcpu_id]; - d->vcpu[v->vcpu_id-1]->next_in_list = v; - set_bit(_VCPUF_down, &v->vcpu_flags); - } - return v; } -struct domain *alloc_domain(void) -{ - struct domain *d; - - if ( (d = xmalloc(struct domain)) != NULL ) - memset(d, 0, sizeof(*d)); - - return d; -} - -/* - * Add and remove a domain - */ void sched_add_domain(struct vcpu *v) { /* Initialise the per-domain timer. */ - init_ac_timer(&v->timer, dom_timer_fn, v, v->processor); + init_timer(&v->timer, dom_timer_fn, v, v->processor); if ( is_idle_vcpu(v) ) { @@ -156,7 +155,7 @@ void sched_rem_domain(struct vcpu *v) { - rem_ac_timer(&v->timer); + kill_timer(&v->timer); SCHED_OP(rem_task, v); TRACE_2D(TRC_SCHED_DOM_REM, v->domain->domain_id, v->vcpu_id); } @@ -165,26 +164,19 @@ { unsigned long flags; - spin_lock_irqsave(&schedule_data[v->processor].schedule_lock, flags); + vcpu_schedule_lock_irqsave(v, flags); if ( likely(!vcpu_runnable(v)) ) SCHED_OP(sleep, v); - spin_unlock_irqrestore(&schedule_data[v->processor].schedule_lock, flags); + vcpu_schedule_unlock_irqrestore(v, flags); TRACE_2D(TRC_SCHED_SLEEP, v->domain->domain_id, v->vcpu_id); -} +} void vcpu_sleep_sync(struct vcpu *v) { vcpu_sleep_nosync(v); - /* - * We can be sure that the VCPU is finally descheduled after the running - * flag is cleared and the scheduler lock is released. We also check that - * the domain continues to be unrunnable, in case someone else wakes it. - */ - while ( !vcpu_runnable(v) && - (test_bit(_VCPUF_running, &v->vcpu_flags) || - spin_is_locked(&schedule_data[v->processor].schedule_lock)) ) + while ( !vcpu_runnable(v) && test_bit(_VCPUF_running, &v->vcpu_flags) ) cpu_relax(); sync_vcpu_execstate(v); @@ -194,20 +186,23 @@ { unsigned long flags; - spin_lock_irqsave(&schedule_data[v->processor].schedule_lock, flags); + vcpu_schedule_lock_irqsave(v, flags); if ( likely(vcpu_runnable(v)) ) { SCHED_OP(wake, v); v->wokenup = NOW(); } - spin_unlock_irqrestore(&schedule_data[v->processor].schedule_lock, flags); + vcpu_schedule_unlock_irqrestore(v, flags); TRACE_2D(TRC_SCHED_WAKE, v->domain->domain_id, v->vcpu_id); } int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity) { - if ( cpus_empty(*affinity) ) + cpumask_t online_affinity; + + cpus_and(online_affinity, *affinity, cpu_online_map); + if ( cpus_empty(online_affinity) ) return -EINVAL; return SCHED_OP(set_affinity, v, affinity); @@ -282,9 +277,9 @@ struct vcpu *v = current; if ( timeout == 0 ) - rem_ac_timer(&v->timer); + stop_timer(&v->timer); else - set_ac_timer(&v->timer, timeout); + set_timer(&v->timer, timeout); return 0; } @@ -311,68 +306,42 @@ { struct domain *d; struct vcpu *v; - int cpu; -#if NR_CPUS <=32 - unsigned long have_lock; - #else - unsigned long long have_lock; -#endif - int succ; - - #define __set_cpu_bit(cpu, data) data |= ((typeof(data))1)<<cpu - #define __get_cpu_bit(cpu, data) (data & ((typeof(data))1)<<cpu) - #define __clear_cpu_bits(data) data = ((typeof(data))0) - if ( cmd->sched_id != ops.sched_id ) - return -EINVAL; - - if ( cmd->direction != SCHED_INFO_PUT && cmd->direction != SCHED_INFO_GET ) + if ( (cmd->sched_id != ops.sched_id) || + ((cmd->direction != SCHED_INFO_PUT) && + (cmd->direction != SCHED_INFO_GET)) ) return -EINVAL; d = find_domain_by_id(cmd->domain); if ( d == NULL ) return -ESRCH; - /* acquire locks on all CPUs on which vcpus of this domain run */ - do { - succ = 0; - __clear_cpu_bits(have_lock); - for_each_vcpu ( d, v ) - { - cpu = v->processor; - if ( !__get_cpu_bit(cpu, have_lock) ) - { - /* if we don't have a lock on this CPU: acquire it*/ - if ( spin_trylock(&schedule_data[cpu].schedule_lock) ) - { - /*we have this lock!*/ - __set_cpu_bit(cpu, have_lock); - succ = 1; - } - else - { - /*we didn,t get this lock -> free all other locks too!*/ - for ( cpu = 0; cpu < NR_CPUS; cpu++ ) - if ( __get_cpu_bit(cpu, have_lock) ) - spin_unlock(&schedule_data[cpu].schedule_lock); - /* and start from the beginning! */ - succ = 0; - /* leave the "for_each_domain_loop" */ - break; - } - } - } - } while ( !succ ); + /* + * Most VCPUs we can simply pause. If we are adjusting this VCPU then + * we acquire the local schedule_lock to guard against concurrent updates. + */ + for_each_vcpu ( d, v ) + { + if ( v == current ) + vcpu_schedule_lock_irq(v); + else + vcpu_pause(v); + } SCHED_OP(adjdom, d, cmd); - for ( cpu = 0; cpu < NR_CPUS; cpu++ ) - if ( __get_cpu_bit(cpu, have_lock) ) - spin_unlock(&schedule_data[cpu].schedule_lock); - __clear_cpu_bits(have_lock); - TRACE_1D(TRC_SCHED_ADJDOM, d->domain_id); + + for_each_vcpu ( d, v ) + { + if ( v == current ) + vcpu_schedule_unlock_irq(v); + else + vcpu_unpause(v); + } + put_domain(d); + return 0; } @@ -395,7 +364,7 @@ spin_lock_irq(&schedule_data[cpu].schedule_lock); - rem_ac_timer(&schedule_data[cpu].s_timer); + stop_timer(&schedule_data[cpu].s_timer); prev->cpu_time += now - prev->lastschd; @@ -409,7 +378,7 @@ next->lastschd = now; - set_ac_timer(&schedule_data[cpu].s_timer, now + r_time); + set_timer(&schedule_data[cpu].s_timer, now + r_time); if ( unlikely(prev == next) ) { @@ -451,6 +420,7 @@ } #endif + ASSERT(!test_bit(_VCPUF_running, &next->vcpu_flags)); set_bit(_VCPUF_running, &next->vcpu_flags); spin_unlock_irq(&schedule_data[cpu].schedule_lock); @@ -492,7 +462,7 @@ /* Periodic tick timer: send timer event to current domain */ static void t_timer_fn(void *unused) { - struct vcpu *v = current; + struct vcpu *v = current; unsigned int cpu = smp_processor_id(); schedule_data[cpu].tick++; @@ -505,7 +475,7 @@ page_scrub_schedule_work(); - set_ac_timer(&t_timer[cpu], NOW() + MILLISECS(10)); + set_timer(&t_timer[cpu], NOW() + MILLISECS(10)); } /* Domain timer function, sends a virtual timer interrupt to domain */ @@ -527,8 +497,8 @@ for ( i = 0; i < NR_CPUS; i++ ) { spin_lock_init(&schedule_data[i].schedule_lock); - init_ac_timer(&schedule_data[i].s_timer, s_timer_fn, NULL, i); - init_ac_timer(&t_timer[i], t_timer_fn, NULL, i); + init_timer(&schedule_data[i].s_timer, s_timer_fn, NULL, i); + init_timer(&t_timer[i], t_timer_fn, NULL, i); } for ( i = 0; schedulers[i] != NULL; i++ ) diff -r 40bb46f599d9 -r a38c292e8390 xen/common/xmalloc.c --- a/xen/common/xmalloc.c Tue Jan 10 15:21:00 2006 +++ b/xen/common/xmalloc.c Tue Jan 24 16:54:34 2006 @@ -30,7 +30,7 @@ #include <xen/config.h> #include <xen/mm.h> #include <xen/spinlock.h> -#include <xen/ac_timer.h> +#include <xen/timer.h> #include <xen/cache.h> #include <xen/prefetch.h> diff -r 40bb46f599d9 -r a38c292e8390 xen/drivers/char/ns16550.c --- a/xen/drivers/char/ns16550.c Tue Jan 10 15:21:00 2006 +++ b/xen/drivers/char/ns16550.c Tue Jan 24 16:54:34 2006 @@ -33,7 +33,7 @@ /* UART with IRQ line: interrupt-driven I/O. */ struct irqaction irqaction; /* UART with no IRQ line: periodically-polled I/O. */ - struct ac_timer timer; + struct timer timer; unsigned int timeout_ms; } ns16550_com[2] = { { 0 } }; @@ -138,7 +138,7 @@ if ( ns_read_reg(uart, LSR) & LSR_THRE ) serial_tx_interrupt(port, regs); - set_ac_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms)); + set_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms)); } static int ns16550_tx_empty(struct serial_port *port) @@ -214,8 +214,8 @@ bits = uart->data_bits + uart->stop_bits + !!uart->parity; uart->timeout_ms = max_t( unsigned int, 1, (bits * port->tx_fifo_size * 1000) / uart->baud); - init_ac_timer(&uart->timer, ns16550_poll, port, 0); - set_ac_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms)); + init_timer(&uart->timer, ns16550_poll, port, 0); + set_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms)); } else { diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-ia64/config.h --- a/xen/include/asm-ia64/config.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-ia64/config.h Tue Jan 24 16:54:34 2006 @@ -92,7 +92,7 @@ //#define __acquire(x) (void)0 //#define __release(x) (void)0 //#define __cond_lock(x) (x) -#define __must_check +//#define __must_check #define __deprecated #ifndef RELOC_HIDE # define RELOC_HIDE(ptr, off) \ @@ -121,7 +121,7 @@ // from include/asm-ia64/smp.h #ifdef CONFIG_SMP -#warning "Lots of things to fix to enable CONFIG_SMP!" +//#warning "Lots of things to fix to enable CONFIG_SMP!" #endif #define get_cpu() smp_processor_id() #define put_cpu() do {} while(0) @@ -140,10 +140,6 @@ #undef free_task_struct #undef alloc_task_struct #define get_thread_info(v) alloc_thread_info(v) - -// initial task has a different name in Xen -//#define idle0_task init_task -#define idle0_vcpu init_task // avoid redefining task_t in asm/thread_info.h #define task_t struct domain @@ -160,7 +156,7 @@ #define platform_outl __ia64_outl // FIXME: This just overrides a use in a typedef (not allowed in ia64, -// or maybe just in older gcc's?) used in ac_timer.c but should be OK +// or maybe just in older gcc's?) used in timer.c but should be OK // (and indeed is probably required!) elsewhere #undef __cacheline_aligned #undef ____cacheline_aligned @@ -187,7 +183,9 @@ struct exception_table_entry *finish); void sort_main_extable(void); +#if 0 /* Already defined in xen/lib.h */ #define printk printf +#endif #undef __ARCH_IRQ_STAT @@ -205,7 +203,6 @@ #define OPT_CONSOLE_STR "com2" #endif -#define __attribute_used__ __attribute__ ((unused)) #define __nocast // see include/asm-x86/atomic.h (different from standard linux) @@ -255,9 +252,6 @@ #define seq_printf(a,b...) printf(b) #define CONFIG_BLK_DEV_INITRD // needed to reserve memory for domain0 -// needed for newer ACPI code -#define asmlinkage - #define FORCE_CRASH() asm("break 0;;"); void dummy_called(char *function); @@ -306,13 +300,8 @@ #endif -// FOLLOWING ADDED FOR XEN POST-NGIO and/or LINUX 2.6.7 - -// following derived from linux/include/linux/compiler-gcc3.h -// problem because xen (over?)simplifies include/xen/compiler.h -#if __GNUC_MAJOR < 3 || __GNUC_MINOR__ >= 3 -# define __attribute_used__ __attribute__((__used__)) -#else -# define __attribute_used__ __attribute__((__unused__)) -#endif +#ifndef __ASSEMBLY__ +#include <linux/linkage.h> +#endif + #endif /* _IA64_CONFIG_H_ */ diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-ia64/debugger.h --- a/xen/include/asm-ia64/debugger.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-ia64/debugger.h Tue Jan 24 16:54:34 2006 @@ -24,6 +24,54 @@ #include <xen/softirq.h> +// this number is an arbitary number which is not used for any other purpose +// __builtin_trap(), FORCE_CRASH() 0x0 +// ski 0x80001, 0x80002 +// kdb 0x80100, 0x80101 +// kprobe 0x80200, jprobe 0x80300 +// kgdb 0x6665 +// gdb 0x99998 (#define IA64_BREAKPOINT 0x00003333300LL) + +// cdb should handle 0 and CDB_BREAK_NUM. +#define CDB_BREAK_NUM 0x80800 + + +#ifndef __ASSEMBLY__ + +#include <xen/gdbstub.h> + +// NOTE: on xen struct pt_regs = struct cpu_user_regs +// see include/asm-ia64/linux-xen/asm/ptrace.h +#ifdef CRASH_DEBUG +// crash_debug=y + +/* The main trap handlers use these helper macros which include early bail. */ +static inline int debugger_trap_entry( + unsigned int vector, struct cpu_user_regs *regs) +{ + return 0; +} + +extern int __trap_to_cdb(struct cpu_user_regs *r); +static inline int debugger_trap_fatal( + unsigned int vector, struct cpu_user_regs *regs) +{ + (void)__trap_to_gdb(regs, vector); + return 0; +} + +#define ____debugger_trap_immediate(b) __asm__ __volatile__ ("break.m "#b"\n") +#define __debugger_trap_immediate(b) ____debugger_trap_immediate(b) +#define debugger_trap_immediate() __debugger_trap_immediate(CDB_BREAK_NUM) + +//XXX temporal work around +#ifndef CONFIG_SMP +#define smp_send_stop() /* nothing */ +#endif + +#elif defined DOMU_DEBUG +// domu_debug=y +#warning "domu_debug is not implemented yet." /* The main trap handlers use these helper macros which include early bail. */ static inline int debugger_trap_entry( unsigned int vector, struct cpu_user_regs *regs) @@ -37,6 +85,23 @@ return 0; } -#define debugger_trap_immediate() do {} while(0) +#define debugger_trap_immediate() ((void)0) +#else +/* The main trap handlers use these helper macros which include early bail. */ +static inline int debugger_trap_entry( + unsigned int vector, struct cpu_user_regs *regs) +{ + return 0; +} + +static inline int debugger_trap_fatal( + unsigned int vector, struct cpu_user_regs *regs) +{ + return 0; +} + +#define debugger_trap_immediate() ((void)0) +#endif +#endif // __ASSEMBLLY__ #endif /* __ASM_DEBUGGER_H__ */ diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-ia64/domain.h --- a/xen/include/asm-ia64/domain.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-ia64/domain.h Tue Jan 24 16:54:34 2006 @@ -9,8 +9,6 @@ #include <public/arch-ia64.h> #include <asm/vmx_platform.h> #include <xen/list.h> - -extern int arch_do_createdomain(struct vcpu *); extern void domain_relinquish_resources(struct domain *); diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-ia64/linux-xen/asm/ptrace.h --- a/xen/include/asm-ia64/linux-xen/asm/ptrace.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-ia64/linux-xen/asm/ptrace.h Tue Jan 24 16:54:34 2006 @@ -110,6 +110,7 @@ return (struct cpu_user_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1; } +struct pt_regs *guest_cpu_user_regs(void); #else struct pt_regs { diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-ia64/linux-xen/linux/interrupt.h --- a/xen/include/asm-ia64/linux-xen/linux/interrupt.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-ia64/linux-xen/linux/interrupt.h Tue Jan 24 16:54:34 2006 @@ -104,6 +104,7 @@ al. should be converted to tasklets, not to softirqs. */ +#ifndef XEN enum { HI_SOFTIRQ=0, @@ -113,6 +114,7 @@ SCSI_SOFTIRQ, TASKLET_SOFTIRQ }; +#endif /* softirq mask and active fields moved to irq_cpustat_t in * asm/hardirq.h to get better cache usage. KAO diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-ia64/mm.h --- a/xen/include/asm-ia64/mm.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-ia64/mm.h Tue Jan 24 16:54:34 2006 @@ -67,10 +67,12 @@ } free; } u; +#if 0 // following added for Linux compiling page_flags_t flags; atomic_t _count; struct list_head lru; // is this the same as above "list"? +#endif }; #define set_page_count(p,v) atomic_set(&(p)->_count, v - 1) diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-ia64/vmmu.h --- a/xen/include/asm-ia64/vmmu.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-ia64/vmmu.h Tue Jan 24 16:54:34 2006 @@ -151,8 +151,8 @@ typedef u64 *(THASH_FN)(PTA pta, u64 va); typedef u64 *(TTAG_FN)(PTA pta, u64 va); typedef u64 *(GET_MFN_FN)(domid_t d, u64 gpfn, u64 pages); -typedef void *(REM_NOTIFIER_FN)(struct hash_cb *hcb, thash_data_t *entry); -typedef void (RECYCLE_FN)(struct hash_cb *hc, u64 para); +typedef void *(REM_NOTIFIER_FN)(struct thash_cb *hcb, thash_data_t *entry); +typedef void (RECYCLE_FN)(struct thash_cb *hc, u64 para); typedef ia64_rr (GET_RR_FN)(struct vcpu *vcpu, u64 reg); typedef thash_data_t *(FIND_OVERLAP_FN)(struct thash_cb *hcb, u64 va, u64 ps, int rid, char cl, search_section_t s_sect); diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-ia64/vtm.h --- a/xen/include/asm-ia64/vtm.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-ia64/vtm.h Tue Jan 24 16:54:34 2006 @@ -23,7 +23,7 @@ #ifndef _VTM_H_ #define _VTM_H_ -#include <xen/ac_timer.h> +#include <xen/timer.h> #include <xen/types.h> #define MAX_JUMP_STEP (5000) /* 500ms, max jump step */ @@ -46,7 +46,7 @@ uint64_t cfg_max_jump; // max jump within one time suspendsion uint64_t cfg_min_grun; // min guest running time since last jump // uint64_t latest_read_itc; // latest guest read ITC - struct ac_timer vtm_timer; + struct timer vtm_timer; // int triggered; diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-x86/debugger.h --- a/xen/include/asm-x86/debugger.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-x86/debugger.h Tue Jan 24 16:54:34 2006 @@ -42,19 +42,19 @@ #if defined(CRASH_DEBUG) -extern int __trap_to_cdb(struct cpu_user_regs *r); +#include <xen/gdbstub.h> #define __debugger_trap_entry(_v, _r) (0) static inline int __debugger_trap_fatal( unsigned int vector, struct cpu_user_regs *regs) { - (void)__trap_to_cdb(regs); + (void)__trap_to_gdb(regs, vector); return (vector == TRAP_int3); /* int3 is harmless */ } /* Int3 is a trivial way to gather cpu_user_regs context. */ -#define __debugger_trap_immediate() __asm__ __volatile__ ( "int3" ); +#define debugger_trap_immediate() __asm__ __volatile__ ( "int3" ); #elif 0 @@ -73,7 +73,7 @@ } /* Int3 is a trivial way to gather cpu_user_regs context. */ -#define __debugger_trap_immediate() __asm__ __volatile__ ( "int3" ) +#define debugger_trap_immediate() __asm__ __volatile__ ( "int3" ) #else @@ -100,6 +100,8 @@ } #define debugger_trap_fatal(v, r) (__debugger_trap_fatal(v, r)) +#ifndef debugger_trap_immediate #define debugger_trap_immediate() (__debugger_trap_immediate()) +#endif #endif /* __X86_DEBUGGER_H__ */ diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-x86/domain.h Tue Jan 24 16:54:34 2006 @@ -13,12 +13,43 @@ unsigned long eip; }; +#define MAPHASH_ENTRIES 8 +#define MAPHASH_HASHFN(pfn) ((pfn) & (MAPHASH_ENTRIES-1)) +#define MAPHASHENT_NOTINUSE ((u16)~0U) +struct vcpu_maphash { + struct vcpu_maphash_entry { + unsigned long pfn; + uint16_t idx; + uint16_t refcnt; + } hash[MAPHASH_ENTRIES]; +} __cacheline_aligned; + +#define MAPCACHE_ORDER 10 +#define MAPCACHE_ENTRIES (1 << MAPCACHE_ORDER) struct mapcache { + /* The PTEs that provide the mappings, and a cursor into the array. */ l1_pgentry_t *l1tab; unsigned int cursor; + + /* Protects map_domain_page(). */ + spinlock_t lock; + + /* Garbage mappings are flushed from TLBs in batches called 'epochs'. */ unsigned int epoch, shadow_epoch[MAX_VIRT_CPUS]; - spinlock_t lock; + u32 tlbflush_timestamp; + + /* Which mappings are in use, and which are garbage to reap next epoch? */ + unsigned long inuse[BITS_TO_LONGS(MAPCACHE_ENTRIES)]; + unsigned long garbage[BITS_TO_LONGS(MAPCACHE_ENTRIES)]; + + /* Lock-free per-VCPU hash of recently-used mappings. */ + struct vcpu_maphash vcpu_maphash[MAX_VIRT_CPUS]; }; + +extern void mapcache_init(struct domain *); + +/* x86/64: toggle guest between kernel and user modes. */ +extern void toggle_guest_mode(struct vcpu *); struct arch_domain { diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-x86/mm.h --- a/xen/include/asm-x86/mm.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-x86/mm.h Tue Jan 24 16:54:34 2006 @@ -309,16 +309,13 @@ unsigned long l1va; /* Copy of the p.t. page, taken before guest is given write access. */ l1_pgentry_t *page; - /* A temporary Xen mapping of the actual p.t. page. */ - l1_pgentry_t *pl1e; /* Index in L2 page table where this L1 p.t. is always hooked. */ unsigned int l2_idx; /* NB. Only used for PTWR_PT_ACTIVE. */ /* Info about last ptwr update batch. */ unsigned int prev_nr_updates; - /* Exec domain which created writable mapping. */ + /* VCPU which created writable mapping. */ struct vcpu *vcpu; - /* EIP of the address which took the original write fault - used for stats collection only */ + /* EIP of the original write fault (stats collection only). */ unsigned long eip; }; diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-x86/nmi.h --- a/xen/include/asm-x86/nmi.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-x86/nmi.h Tue Jan 24 16:54:34 2006 @@ -1,6 +1,8 @@ #ifndef ASM_NMI_H #define ASM_NMI_H + +#include <public/nmi.h> struct cpu_user_regs; diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-x86/processor.h --- a/xen/include/asm-x86/processor.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-x86/processor.h Tue Jan 24 16:54:34 2006 @@ -123,6 +123,7 @@ #define TBF_EXCEPTION_ERRCODE 2 #define TBF_INTERRUPT 8 #define TBF_FAILSAFE 16 +#define TBF_SLOW_IRET 32 /* 'arch_vcpu' flags values */ #define _TF_kernel_mode 0 diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-x86/vmx_vlapic.h --- a/xen/include/asm-x86/vmx_vlapic.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-x86/vmx_vlapic.h Tue Jan 24 16:54:34 2006 @@ -187,7 +187,7 @@ uint32_t timer_current; uint32_t timer_divconf; uint32_t timer_divide_counter; - struct ac_timer vlapic_timer; + struct timer vlapic_timer; int intr_pending_count[MAX_VECTOR]; s_time_t timer_current_update; uint32_t icr_high; @@ -216,7 +216,7 @@ static inline int vlapic_timer_active(struct vlapic *vlapic) { - return active_ac_timer(&(vlapic->vlapic_timer)); + return active_timer(&(vlapic->vlapic_timer)); } int vlapic_find_highest_irr(struct vlapic *vlapic); diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-x86/vmx_vmcs.h --- a/xen/include/asm-x86/vmx_vmcs.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-x86/vmx_vmcs.h Tue Jan 24 16:54:34 2006 @@ -100,7 +100,7 @@ void *io_bitmap_a, *io_bitmap_b; struct vlapic *vlapic; u64 tsc_offset; - struct ac_timer hlt_timer; /* hlt ins emulation wakeup timer */ + struct timer hlt_timer; /* hlt ins emulation wakeup timer */ }; #define vmx_schedule_tail(next) \ diff -r 40bb46f599d9 -r a38c292e8390 xen/include/asm-x86/vmx_vpit.h --- a/xen/include/asm-x86/vmx_vpit.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/asm-x86/vmx_vpit.h Tue Jan 24 16:54:34 2006 @@ -6,7 +6,7 @@ #include <xen/lib.h> #include <xen/time.h> #include <xen/errno.h> -#include <xen/ac_timer.h> +#include <xen/timer.h> #include <asm/vmx_vmcs.h> #include <asm/vmx_vpic.h> @@ -23,7 +23,7 @@ u64 inject_point; /* the time inject virt intr */ u64 shift; /* save the value of offset - drift */ s_time_t scheduled; /* scheduled timer interrupt */ - struct ac_timer pit_timer; /* periodic timer for mode 2*/ + struct timer pit_timer; /* periodic timer for mode 2*/ unsigned int channel; /* the pit channel, counter 0~2 */ unsigned int pending_intr_nr; /* the couner for pending timer interrupts */ u32 period; /* pit frequency in ns */ diff -r 40bb46f599d9 -r a38c292e8390 xen/include/public/arch-ia64.h --- a/xen/include/public/arch-ia64.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/public/arch-ia64.h Tue Jan 24 16:54:34 2006 @@ -9,7 +9,7 @@ /* Maximum number of virtual CPUs in multi-processor guests. */ /* WARNING: before changing this, check that shared_info fits on a page */ -#define MAX_VIRT_CPUS 1 +#define MAX_VIRT_CPUS 4 #ifndef __ASSEMBLY__ diff -r 40bb46f599d9 -r a38c292e8390 xen/include/public/arch-x86_32.h --- a/xen/include/public/arch-x86_32.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/public/arch-x86_32.h Tue Jan 24 16:54:34 2006 @@ -135,6 +135,7 @@ unsigned long max_pfn; /* max pfn that appears in table */ /* Frame containing list of mfns containing list of mfns containing p2m. */ unsigned long pfn_to_mfn_frame_list_list; + unsigned long nmi_reason; } arch_shared_info_t; typedef struct { diff -r 40bb46f599d9 -r a38c292e8390 xen/include/public/arch-x86_64.h --- a/xen/include/public/arch-x86_64.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/public/arch-x86_64.h Tue Jan 24 16:54:34 2006 @@ -88,11 +88,20 @@ #define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */ /* - * int HYPERVISOR_switch_to_user(void) + * int HYPERVISOR_iret(void) * All arguments are on the kernel stack, in the following format. * Never returns if successful. Current kernel context is lost. + * The saved CS is mapped as follows: + * RING0 -> RING3 kernel mode. + * RING1 -> RING3 kernel mode. + * RING2 -> RING3 kernel mode. + * RING3 -> RING3 user mode. + * However RING0 indicates that the guest kernel should return to iteself + * directly with + * orb $3,1*8(%rsp) + * iretq * If flags contains VGCF_IN_SYSCALL: - * Restore RAX, RIP, RFLAGS, RSP. + * Restore RAX, RIP, RFLAGS, RSP. * Discard R11, RCX, CS, SS. * Otherwise: * Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP. @@ -100,10 +109,19 @@ */ /* Guest exited in SYSCALL context? Return to guest with SYSRET? */ #define VGCF_IN_SYSCALL (1<<8) +struct iret_context { + /* Top of stack (%rsp at point of hypercall). */ + uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss; + /* Bottom of iret stack frame. */ +}; +/* + * For compatibility with HYPERVISOR_switch_to_user which is the old + * name for HYPERVISOR_iret. + */ struct switch_to_user { /* Top of stack (%rsp at point of hypercall). */ uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss; - /* Bottom of switch_to_user stack frame. */ + /* Bottom of iret stack frame. */ }; /* @@ -202,6 +220,7 @@ unsigned long max_pfn; /* max pfn that appears in table */ /* Frame containing list of mfns containing list of mfns containing p2m. */ unsigned long pfn_to_mfn_frame_list_list; + unsigned long nmi_reason; } arch_shared_info_t; typedef struct { diff -r 40bb46f599d9 -r a38c292e8390 xen/include/public/xen.h --- a/xen/include/public/xen.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/public/xen.h Tue Jan 24 16:54:34 2006 @@ -53,12 +53,14 @@ #define __HYPERVISOR_grant_table_op 20 #define __HYPERVISOR_vm_assist 21 #define __HYPERVISOR_update_va_mapping_otherdomain 22 -#define __HYPERVISOR_switch_vm86 23 /* x86/32 only */ -#define __HYPERVISOR_switch_to_user 23 /* x86/64 only */ +#define __HYPERVISOR_iret 23 /* x86 only */ +#define __HYPERVISOR_switch_vm86 23 /* x86/32 only (obsolete name) */ +#define __HYPERVISOR_switch_to_user 23 /* x86/64 only (obsolete name) */ #define __HYPERVISOR_vcpu_op 24 #define __HYPERVISOR_set_segment_base 25 /* x86/64 only */ #define __HYPERVISOR_mmuext_op 26 #define __HYPERVISOR_acm_op 27 +#define __HYPERVISOR_nmi_op 28 /* * VIRTUAL INTERRUPTS @@ -69,10 +71,7 @@ #define VIRQ_DEBUG 1 /* Request guest to dump debug info. */ #define VIRQ_CONSOLE 2 /* (DOM0) Bytes received on emergency console. */ #define VIRQ_DOM_EXC 3 /* (DOM0) Exceptional event for some domain. */ -#define VIRQ_PARITY_ERR 4 /* (DOM0) NMI parity error (port 0x61, bit 7). */ -#define VIRQ_IO_ERR 5 /* (DOM0) NMI I/O error (port 0x61, bit 6). */ #define VIRQ_DEBUGGER 6 /* (DOM0) A domain has paused for debugging. */ -#define VIRQ_NMI 7 /* (DOM0) Unknown NMI (not from ISA port 0x61).*/ #define NR_VIRQS 8 /* diff -r 40bb46f599d9 -r a38c292e8390 xen/include/xen/domain.h --- a/xen/include/xen/domain.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/xen/domain.h Tue Jan 24 16:54:34 2006 @@ -13,12 +13,12 @@ extern void free_vcpu_struct(struct vcpu *v); -extern int arch_do_createdomain(struct vcpu *v); +extern int arch_domain_create(struct domain *d); + +extern void arch_domain_destroy(struct domain *d); extern int arch_set_info_guest( struct vcpu *v, struct vcpu_guest_context *c); - -extern void free_perdomain_pt(struct domain *d); extern void domain_relinquish_resources(struct domain *d); diff -r 40bb46f599d9 -r a38c292e8390 xen/include/xen/domain_page.h --- a/xen/include/xen/domain_page.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/xen/domain_page.h Tue Jan 24 16:54:34 2006 @@ -2,6 +2,8 @@ * domain_page.h * * Allow temporary mapping of domain page frames into Xen space. + * + * Copyright (c) 2003-2006, Keir Fraser <keir@xxxxxxxxxxxxx> */ #ifndef __XEN_DOMAIN_PAGE_H__ @@ -10,22 +12,27 @@ #include <xen/config.h> #include <xen/mm.h> -#define map_domain_page(pfn) map_domain_pages(pfn,0) -#define unmap_domain_page(va) unmap_domain_pages(va,0) - #ifdef CONFIG_DOMAIN_PAGE /* - * Maps a given range of page frames, returning the mapped virtual address. The - * pages are now accessible until a corresponding call to unmap_domain_page(). + * Map a given page frame, returning the mapped virtual address. The page is + * then accessible within the current VCPU until a corresponding unmap call. */ -extern void *map_domain_pages(unsigned long pfn, unsigned int order); +extern void *map_domain_page(unsigned long pfn); /* - * Pass a VA within the first page of a range previously mapped with - * map_omain_pages(). Those pages will then be removed from the mapping lists. + * Pass a VA within a page previously mapped in the context of the + * currently-executing VCPU via a call to map_domain_pages(). */ -extern void unmap_domain_pages(void *va, unsigned int order); +extern void unmap_domain_page(void *va); + +/* + * Similar to the above calls, except the mapping is accessible in all + * address spaces (not just within the VCPU that created the mapping). Global + * mappings can also be unmapped from any context. + */ +extern void *map_domain_page_global(unsigned long pfn); +extern void unmap_domain_page_global(void *va); #define DMCACHE_ENTRY_VALID 1U #define DMCACHE_ENTRY_HELD 2U @@ -87,8 +94,11 @@ #else /* !CONFIG_DOMAIN_PAGE */ -#define map_domain_pages(pfn,order) phys_to_virt((pfn)<<PAGE_SHIFT) -#define unmap_domain_pages(va,order) ((void)((void)(va),(void)(order))) +#define map_domain_page(pfn) phys_to_virt((pfn)<<PAGE_SHIFT) +#define unmap_domain_page(va) ((void)(va)) + +#define map_domain_page_global(pfn) phys_to_virt((pfn)<<PAGE_SHIFT) +#define unmap_domain_page_global(va) ((void)(va)) struct domain_mmap_cache { }; diff -r 40bb46f599d9 -r a38c292e8390 xen/include/xen/perfc_defn.h --- a/xen/include/xen/perfc_defn.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/xen/perfc_defn.h Tue Jan 24 16:54:34 2006 @@ -32,7 +32,7 @@ PERFCOUNTER_CPU(irq_time, "cycles spent in irq handler") PERFCOUNTER_CPU(apic_timer, "apic timer interrupts") -PERFCOUNTER_CPU(ac_timer_max, "ac_timer max error (ns)") +PERFCOUNTER_CPU(timer_max, "timer max error (ns)") PERFCOUNTER_CPU(sched_irq, "sched: timer") PERFCOUNTER_CPU(sched_run, "sched: runs through scheduler") PERFCOUNTER_CPU(sched_ctx, "sched: context switches") diff -r 40bb46f599d9 -r a38c292e8390 xen/include/xen/sched-if.h --- a/xen/include/xen/sched-if.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/xen/sched-if.h Tue Jan 24 16:54:34 2006 @@ -16,16 +16,47 @@ struct vcpu *curr; /* current task */ struct vcpu *idle; /* idle task for this cpu */ void *sched_priv; - struct ac_timer s_timer; /* scheduling timer */ + struct timer s_timer; /* scheduling timer */ unsigned long tick; /* current periodic 'tick' */ #ifdef BUCKETS u32 hist[BUCKETS]; /* for scheduler latency histogram */ #endif } __cacheline_aligned; +extern struct schedule_data schedule_data[]; + +static inline void vcpu_schedule_lock(struct vcpu *v) +{ + unsigned int cpu; + + for ( ; ; ) + { + cpu = v->processor; + spin_lock(&schedule_data[cpu].schedule_lock); + if ( likely(v->processor == cpu) ) + break; + spin_unlock(&schedule_data[cpu].schedule_lock); + } +} + +#define vcpu_schedule_lock_irq(v) \ + do { local_irq_disable(); vcpu_schedule_lock(v); } while ( 0 ) +#define vcpu_schedule_lock_irqsave(v, flags) \ + do { local_irq_save(flags); vcpu_schedule_lock(v); } while ( 0 ) + +static inline void vcpu_schedule_unlock(struct vcpu *v) +{ + spin_unlock(&schedule_data[v->processor].schedule_lock); +} + +#define vcpu_schedule_unlock_irq(v) \ + do { vcpu_schedule_unlock(v); local_irq_enable(); } while ( 0 ) +#define vcpu_schedule_unlock_irqrestore(v, flags) \ + do { vcpu_schedule_unlock(v); local_irq_restore(flags); } while ( 0 ) + struct task_slice { struct vcpu *task; - s_time_t time; + s_time_t time; }; struct scheduler { @@ -48,6 +79,4 @@ void (*dump_cpu_state) (int); }; -extern struct schedule_data schedule_data[]; - #endif /* __XEN_SCHED_IF_H__ */ diff -r 40bb46f599d9 -r a38c292e8390 xen/include/xen/sched.h --- a/xen/include/xen/sched.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/xen/sched.h Tue Jan 24 16:54:34 2006 @@ -9,7 +9,7 @@ #include <public/xen.h> #include <public/dom0_ops.h> #include <xen/time.h> -#include <xen/ac_timer.h> +#include <xen/timer.h> #include <xen/grant_table.h> #include <xen/rangeset.h> #include <asm/domain.h> @@ -63,7 +63,7 @@ struct vcpu *next_in_list; - struct ac_timer timer; /* one-shot timer for timeout values */ + struct timer timer; /* one-shot timer for timeout values */ unsigned long sleep_tick; /* tick at which this vcpu started sleep */ s_time_t lastschd; /* time this domain was last scheduled */ @@ -80,6 +80,8 @@ /* Bitmask of CPUs on which this VCPU may run. */ cpumask_t cpu_affinity; + + unsigned long nmi_addr; /* NMI callback address. */ /* Bitmask of CPUs which are holding onto this VCPU's state. */ cpumask_t vcpu_dirty_cpumask; @@ -183,13 +185,13 @@ struct domain *alloc_domain(void); void free_domain(struct domain *d); -#define DOMAIN_DESTRUCTED (1<<31) /* assumes atomic_t is >= 32 bits */ +#define DOMAIN_DESTROYED (1<<31) /* assumes atomic_t is >= 32 bits */ #define put_domain(_d) \ - if ( atomic_dec_and_test(&(_d)->refcnt) ) domain_destruct(_d) + if ( atomic_dec_and_test(&(_d)->refcnt) ) domain_destroy(_d) /* * Use this when you don't have an existing reference to @d. It returns - * FALSE if @d is being destructed. + * FALSE if @d is being destroyed. */ static always_inline int get_domain(struct domain *d) { @@ -197,7 +199,7 @@ do { old = seen; - if ( unlikely(_atomic_read(old) & DOMAIN_DESTRUCTED) ) + if ( unlikely(_atomic_read(old) & DOMAIN_DESTROYED) ) return 0; _atomic_set(new, _atomic_read(old) + 1); seen = atomic_compareandswap(old, new, &d->refcnt); @@ -208,15 +210,15 @@ /* * Use this when you already have, or are borrowing, a reference to @d. - * In this case we know that @d cannot be destructed under our feet. + * In this case we know that @d cannot be destroyed under our feet. */ static inline void get_knownalive_domain(struct domain *d) { atomic_inc(&d->refcnt); - ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTRUCTED)); + ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTROYED)); } -extern struct domain *do_createdomain( +extern struct domain *domain_create( domid_t dom_id, unsigned int cpu); extern int construct_dom0( struct domain *d, @@ -226,7 +228,7 @@ extern int set_info_guest(struct domain *d, dom0_setvcpucontext_t *); struct domain *find_domain_by_id(domid_t dom); -extern void domain_destruct(struct domain *d); +extern void domain_destroy(struct domain *d); extern void domain_kill(struct domain *d); extern void domain_shutdown(struct domain *d, u8 reason); extern void domain_pause_for_debugger(void); @@ -361,6 +363,12 @@ /* VCPU is not-runnable */ #define _VCPUF_down 5 #define VCPUF_down (1UL<<_VCPUF_down) + /* NMI callback pending for this VCPU? */ +#define _VCPUF_nmi_pending 8 +#define VCPUF_nmi_pending (1UL<<_VCPUF_nmi_pending) + /* Avoid NMI reentry by allowing NMIs to be masked for short periods. */ +#define _VCPUF_nmi_masked 9 +#define VCPUF_nmi_masked (1UL<<_VCPUF_nmi_masked) /* * Per-domain flags (domain_flags). diff -r 40bb46f599d9 -r a38c292e8390 xen/include/xen/softirq.h --- a/xen/include/xen/softirq.h Tue Jan 10 15:21:00 2006 +++ b/xen/include/xen/softirq.h Tue Jan 24 16:54:34 2006 @@ -2,11 +2,11 @@ #define __XEN_SOFTIRQ_H__ /* Common softirqs come first in the following list. */ -#define AC_TIMER_SOFTIRQ 0 +#define TIMER_SOFTIRQ 0 #define SCHEDULE_SOFTIRQ 1 #define NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ 2 #define KEYPRESS_SOFTIRQ 3 -#define NMI_DOM0_SOFTIRQ 4 +#define NMI_SOFTIRQ 4 #define PAGE_SCRUB_SOFTIRQ 5 #define DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ 6 #define NR_SOFTIRQS 7 diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/mach_traps.h --- /dev/null Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/mach_traps.h Tue Jan 24 16:54:34 2006 @@ -0,0 +1,33 @@ +/* + * include/asm-xen/asm-i386/mach-xen/mach_traps.h + * + * Machine specific NMI handling for Xen + */ +#ifndef _MACH_TRAPS_H +#define _MACH_TRAPS_H + +#include <linux/bitops.h> +#include <asm-xen/xen-public/nmi.h> + +static inline void clear_mem_error(unsigned char reason) {} +static inline void clear_io_check_error(unsigned char reason) {} + +static inline unsigned char get_nmi_reason(void) +{ + shared_info_t *s = HYPERVISOR_shared_info; + unsigned char reason = 0; + + /* construct a value which looks like it came from + * port 0x61. + */ + if (test_bit(_XEN_NMIREASON_io_error, &s->arch.nmi_reason)) + reason |= 0x40; + if (test_bit(_XEN_NMIREASON_parity_error, &s->arch.nmi_reason)) + reason |= 0x80; + + return reason; +} + +static inline void reassert_nmi(void) {} + +#endif /* !_MACH_TRAPS_H */ diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/nmi.h --- /dev/null Tue Jan 10 15:21:00 2006 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/nmi.h Tue Jan 24 16:54:34 2006 @@ -0,0 +1,75 @@ +/* + * linux/include/asm-i386/nmi.h + */ +#ifndef ASM_NMI_H +#define ASM_NMI_H + +#include <linux/pm.h> + +#include <asm-xen/xen-public/nmi.h> + +struct pt_regs; + +typedef int (*nmi_callback_t)(struct pt_regs * regs, int cpu); + +/** + * set_nmi_callback + * + * Set a handler for an NMI. Only one handler may be + * set. Return 1 if the NMI was handled. + */ +void set_nmi_callback(nmi_callback_t callback); + +/** + * unset_nmi_callback + * + * Remove the handler previously set. + */ +void unset_nmi_callback(void); + +#ifdef CONFIG_PM + +/** Replace the PM callback routine for NMI. */ +struct pm_dev * set_nmi_pm_callback(pm_callback callback); + +/** Unset the PM callback routine back to the default. */ +void unset_nmi_pm_callback(struct pm_dev * dev); + +#else + +static inline struct pm_dev * set_nmi_pm_callback(pm_callback callback) +{ + return 0; +} + +static inline void unset_nmi_pm_callback(struct pm_dev * dev) +{ +} + +#endif /* CONFIG_PM */ + +extern void default_do_nmi(struct pt_regs *); +extern void die_nmi(char *str, struct pt_regs *regs); + +static inline unsigned char get_nmi_reason(void) +{ + shared_info_t *s = HYPERVISOR_shared_info; + unsigned char reason = 0; + + /* construct a value which looks like it came from + * port 0x61. + */ + if (test_bit(_XEN_NMIREASON_io_error, &s->arch.nmi_reason)) + reason |= 0x40; + if (test_bit(_XEN_NMIREASON_parity_error, &s->arch.nmi_reason)) + reason |= 0x80; + + return reason; +} + +extern int panic_on_timeout; +extern int unknown_nmi_panic; + +extern int check_nmi_watchdog(void); + +#endif /* ASM_NMI_H */ diff -r 40bb46f599d9 -r a38c292e8390 patches/linux-2.6.12/i386-mach-io-check-nmi.patch --- /dev/null Tue Jan 10 15:21:00 2006 +++ b/patches/linux-2.6.12/i386-mach-io-check-nmi.patch Tue Jan 24 16:54:34 2006 @@ -0,0 +1,43 @@ +--- ref-linux-2.6.12/arch/i386/kernel/traps.c 2005-12-19 09:23:44.000000000 +0000 ++++ linux-2.6.12-xen0/arch/i386/kernel/traps.c 2006-01-05 15:51:52.000000000 +0000 +@@ -521,18 +521,11 @@ + + static void io_check_error(unsigned char reason, struct pt_regs * regs) + { +- unsigned long i; +- + printk("NMI: IOCK error (debug interrupt?)\n"); + show_registers(regs); + + /* Re-enable the IOCK line, wait for a few seconds */ +- reason = (reason & 0xf) | 8; +- outb(reason, 0x61); +- i = 2000; +- while (--i) udelay(1000); +- reason &= ~8; +- outb(reason, 0x61); ++ clear_io_check_error(reason); + } + + static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) +--- ref-linux-2.6.12/include/asm-i386/mach-default/mach_traps.h 2005-06-17 20:48:29.000000000 +0100 ++++ linux-2.6.12-xen0/include/asm-i386/mach-default/mach_traps.h 2006-01-05 15:52:33.000000000 +0000 +@@ -15,6 +15,18 @@ + outb(reason, 0x61); + } + ++static inline void clear_io_check_error(unsigned char reason) ++{ ++ unsigned long i; ++ ++ reason = (reason & 0xf) | 8; ++ outb(reason, 0x61); ++ i = 2000; ++ while (--i) udelay(1000); ++ reason &= ~8; ++ outb(reason, 0x61); ++} ++ + static inline unsigned char get_nmi_reason(void) + { + return inb(0x61); diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/ia64/xen/gdbstub.c --- /dev/null Tue Jan 10 15:21:00 2006 +++ b/xen/arch/ia64/xen/gdbstub.c Tue Jan 24 16:54:34 2006 @@ -0,0 +1,811 @@ +/* + * ia64-specific cdb routines + * cdb xen/ia64 by Isaku Yamahta <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * some routines are stolen from kgdb/ia64. + */ +/* + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + +/* + * Copyright (C) 2000-2001 VERITAS Software Corporation. + */ +/* + * Contributor: Lake Stevens Instrument Division$ + * Written by: Glenn Engel $ + * Updated by: Amit Kale<akale@xxxxxxxxxxx> + * Modified for 386 by Jim Kingdon, Cygnus Support. + * Origianl kgdb, compatibility with 2.1.xx kernel by David Grothe <dave@xxxxxxxx> + * + */ + + +#include <xen/lib.h> +#include <asm/byteorder.h> +#include <asm/debugger.h> +#include <asm/uaccess.h> + +#define USE_UNWIND + +#ifdef USE_UNWIND +#include <asm/unwind.h> +#endif + +/* Printk isn't particularly safe just after we've trapped to the + debugger. so avoid it. */ +#define dbg_printk(...) +//#define dbg_printk(...) printk(__VA_ARGS__) + +u16 +gdb_arch_signal_num(struct cpu_user_regs *regs, unsigned long cookie) +{ + /* XXX */ + return 1; +} + +void +gdb_arch_read_reg_array(struct cpu_user_regs *regs, struct gdb_context *ctx) +{ + gdb_send_reply("", ctx); +} + +void +gdb_arch_write_reg_array(struct cpu_user_regs *regs, const char* buf, + struct gdb_context *ctx) +{ + /* XXX TODO */ + gdb_send_reply("E02", ctx); +} + +/* Like copy_from_user, but safe to call with interrupts disabled. + Trust me, and don't look behind the curtain. */ +unsigned +gdb_arch_copy_from_user(void *dest, const void *src, unsigned len) +{ + int val; + __asm__ __volatile__( + "cmp4.eq p6, p0 = r0, %1\n" + "(p6) br.cond.dptk 2f\n" + "[1:]\n" + ".xdata4 \"__ex_table\", 99f-., 2f-.;\n" + "[99:] ld1 %0 = [%3], 1\n" + ";;\n" + ".xdata4 \"__ex_table\", 99f-., 2f-.;\n" + "[99:] st1 [%2] = %0, 1\n" + "adds %1 = -1, %1\n" + ";;\n" + "cmp4.eq p0, p6 = r0, %1\n" + "(p6) br.cond.dptk 1b\n" + "[2:]\n" + : "=r"(val), "=r"(len), "=r"(dest), "=r"(src) + : "1"(len), "2"(dest), "3"(src) + : "memory", "p6"); + return len; +} + +unsigned int +gdb_arch_copy_to_user(void *dest, const void *src, unsigned len) +{ + /* XXX */ + return len; +} + +#define NUM_REGS 590 +#define REGISTER_BYTES (NUM_REGS*8+128*8) +#define REGISTER_BYTE(N) (((N) * 8) \ + + ((N) <= IA64_FR0_REGNUM ? \ + 0 : 8 * (((N) > IA64_FR127_REGNUM) ? 128 : (N) - IA64_FR0_REGNUM))) +#define REGISTER_SIZE(N) \ + (((N) >= IA64_FR0_REGNUM && (N) <= IA64_FR127_REGNUM) ? 16 : 8) +#define IA64_GR0_REGNUM 0 +#define IA64_FR0_REGNUM 128 +#define IA64_FR127_REGNUM (IA64_FR0_REGNUM+127) +#define IA64_PR0_REGNUM 256 +#define IA64_BR0_REGNUM 320 +#define IA64_VFP_REGNUM 328 +#define IA64_PR_REGNUM 330 +#define IA64_IP_REGNUM 331 +#define IA64_PSR_REGNUM 332 +#define IA64_CFM_REGNUM 333 +#define IA64_AR0_REGNUM 334 +#define IA64_NAT0_REGNUM 462 +#define IA64_NAT31_REGNUM (IA64_NAT0_REGNUM+31) +#define IA64_NAT32_REGNUM (IA64_NAT0_REGNUM+32) +#define IA64_RSC_REGNUM (IA64_AR0_REGNUM+16) +#define IA64_BSP_REGNUM (IA64_AR0_REGNUM+17) +#define IA64_BSPSTORE_REGNUM (IA64_AR0_REGNUM+18) +#define IA64_RNAT_REGNUM (IA64_AR0_REGNUM+19) +#define IA64_FCR_REGNUM (IA64_AR0_REGNUM+21) +#define IA64_EFLAG_REGNUM (IA64_AR0_REGNUM+24) +#define IA64_CSD_REGNUM (IA64_AR0_REGNUM+25) +#define IA64_SSD_REGNUM (IA64_AR0_REGNUM+26) +#define IA64_CFLG_REGNUM (IA64_AR0_REGNUM+27) +#define IA64_FSR_REGNUM (IA64_AR0_REGNUM+28) +#define IA64_FIR_REGNUM (IA64_AR0_REGNUM+29) +#define IA64_FDR_REGNUM (IA64_AR0_REGNUM+30) +#define IA64_CCV_REGNUM (IA64_AR0_REGNUM+32) +#define IA64_UNAT_REGNUM (IA64_AR0_REGNUM+36) +#define IA64_FPSR_REGNUM (IA64_AR0_REGNUM+40) +#define IA64_ITC_REGNUM (IA64_AR0_REGNUM+44) +#define IA64_PFS_REGNUM (IA64_AR0_REGNUM+64) +#define IA64_LC_REGNUM (IA64_AR0_REGNUM+65) +#define IA64_EC_REGNUM (IA64_AR0_REGNUM+66) + +#ifndef USE_UNWIND +struct regs_to_cpu_user_resgs_index { + unsigned int reg; + unsigned int ptregoff; +}; + +#define ptoff(V) ((unsigned int)&((struct cpu_user_regs*)0x0)->V) + +// gr +static const struct regs_to_cpu_user_resgs_index +gr_reg_to_cpu_user_regs_index[] = { + {IA64_GR0_REGNUM + 8, ptoff(r8)}, + {IA64_GR0_REGNUM + 9, ptoff(r9)}, + {IA64_GR0_REGNUM + 10, ptoff(r10)}, + {IA64_GR0_REGNUM + 11, ptoff(r11)}, + {IA64_GR0_REGNUM + 1, ptoff(r1)}, + {IA64_GR0_REGNUM + 12, ptoff(r12)}, + {IA64_GR0_REGNUM + 13, ptoff(r13)}, + {IA64_GR0_REGNUM + 15, ptoff(r15)}, + + {IA64_GR0_REGNUM + 14, ptoff(r14)}, + {IA64_GR0_REGNUM + 2, ptoff(r2)}, + {IA64_GR0_REGNUM + 3, ptoff(r3)}, + {IA64_GR0_REGNUM + 16, ptoff(r16)}, + {IA64_GR0_REGNUM + 17, ptoff(r17)}, + {IA64_GR0_REGNUM + 18, ptoff(r18)}, + {IA64_GR0_REGNUM + 19, ptoff(r19)}, + {IA64_GR0_REGNUM + 20, ptoff(r20)}, + {IA64_GR0_REGNUM + 21, ptoff(r21)}, + {IA64_GR0_REGNUM + 22, ptoff(r22)}, + {IA64_GR0_REGNUM + 23, ptoff(r23)}, + {IA64_GR0_REGNUM + 24, ptoff(r24)}, + {IA64_GR0_REGNUM + 25, ptoff(r25)}, + {IA64_GR0_REGNUM + 26, ptoff(r26)}, + {IA64_GR0_REGNUM + 27, ptoff(r27)}, + {IA64_GR0_REGNUM + 28, ptoff(r28)}, + {IA64_GR0_REGNUM + 29, ptoff(r29)}, + {IA64_GR0_REGNUM + 30, ptoff(r30)}, + {IA64_GR0_REGNUM + 31, ptoff(r31)}, + + {IA64_GR0_REGNUM + 4, ptoff(r4)}, + {IA64_GR0_REGNUM + 5, ptoff(r5)}, + {IA64_GR0_REGNUM + 6, ptoff(r6)}, + {IA64_GR0_REGNUM + 7, ptoff(r7)}, +}; +static const int gr_reg_to_cpu_user_regs_index_max = + sizeof(gr_reg_to_cpu_user_regs_index) / + sizeof(gr_reg_to_cpu_user_regs_index[0]); + +// br +static const struct regs_to_cpu_user_resgs_index +br_reg_to_cpu_user_regs_index[] = { + {IA64_BR0_REGNUM + 0, ptoff(b0)}, + {IA64_BR0_REGNUM + 6, ptoff(b6)}, + {IA64_BR0_REGNUM + 7, ptoff(b7)}, +}; +static const int br_reg_to_cpu_user_regs_index_max = + sizeof(br_reg_to_cpu_user_regs_index) / + sizeof(br_reg_to_cpu_user_regs_index[0]); + +// f +static const struct regs_to_cpu_user_resgs_index +fr_reg_to_cpu_user_regs_index[] = { + {IA64_FR0_REGNUM + 6, ptoff(f6)}, + {IA64_FR0_REGNUM + 7, ptoff(f7)}, + {IA64_FR0_REGNUM + 8, ptoff(f8)}, + {IA64_FR0_REGNUM + 9, ptoff(f9)}, + {IA64_FR0_REGNUM + 10, ptoff(f10)}, + {IA64_FR0_REGNUM + 11, ptoff(f11)}, +}; +static const int fr_reg_to_cpu_user_regs_index_max = + sizeof(fr_reg_to_cpu_user_regs_index) / + sizeof(fr_reg_to_cpu_user_regs_index[0]); + + +void +gdb_arch_read_reg(unsigned long regnum, struct cpu_user_regs *regs, + struct gdb_context *ctx) +{ + unsigned long reg = IA64_IP_REGNUM; + char buf[9]; + int i; + + dbg_printk("Register read regnum = 0x%lx\n", regnum); + if (IA64_GR0_REGNUM <= regnum && regnum <= IA64_GR0_REGNUM + 31) { + for (i = 0; i < gr_reg_to_cpu_user_regs_index_max; i++) { + if (gr_reg_to_cpu_user_regs_index[i].reg == regnum) { + reg = *(unsigned long*)(((char*)regs) + gr_reg_to_cpu_user_regs_index[i].ptregoff); + break; + } + } + if (i == gr_reg_to_cpu_user_regs_index_max) { + goto out_err; + } + } else if (IA64_BR0_REGNUM <= regnum && regnum <= IA64_BR0_REGNUM + 7) { + for (i = 0; i < br_reg_to_cpu_user_regs_index_max; i++) { + if (br_reg_to_cpu_user_regs_index[i].reg == regnum) { + reg = *(unsigned long*)(((char*)regs) + br_reg_to_cpu_user_regs_index[i].ptregoff); + break; + } + } + if (i == br_reg_to_cpu_user_regs_index_max) { + goto out_err; + } + } else if (IA64_FR0_REGNUM + 6 <= regnum && regnum <= IA64_FR0_REGNUM + 11) { + for (i = 0; i < fr_reg_to_cpu_user_regs_index_max; i++) { + if (fr_reg_to_cpu_user_regs_index[i].reg == regnum) { + reg = *(unsigned long*)(((char*)regs) + fr_reg_to_cpu_user_regs_index[i].ptregoff); + break; + } + } + if (i == fr_reg_to_cpu_user_regs_index_max) { + goto out_err; + } + } else if (regnum == IA64_CSD_REGNUM) { + reg = regs->ar_csd; + } else if (regnum == IA64_SSD_REGNUM) { + reg = regs->ar_ssd; + } else if (regnum == IA64_PSR_REGNUM) { + reg = regs->cr_ipsr; + } else if (regnum == IA64_IP_REGNUM) { + reg = regs->cr_iip; + } else if (regnum == IA64_CFM_REGNUM) { + reg = regs->cr_ifs; + } else if (regnum == IA64_UNAT_REGNUM) { + reg = regs->ar_unat; + } else if (regnum == IA64_PFS_REGNUM) { + reg = regs->ar_pfs; + } else if (regnum == IA64_RSC_REGNUM) { + reg = regs->ar_rsc; + } else if (regnum == IA64_RNAT_REGNUM) { + reg = regs->ar_rnat; + } else if (regnum == IA64_BSPSTORE_REGNUM) { + reg = regs->ar_bspstore; + } else if (regnum == IA64_PR_REGNUM) { + reg = regs->pr; + } else if (regnum == IA64_FPSR_REGNUM) { + reg = regs->ar_fpsr; + } else if (regnum == IA64_CCV_REGNUM) { + reg = regs->ar_ccv; + } else { + // emul_unat, rfi_pfs + goto out_err; + } + + dbg_printk("Register read regnum = 0x%lx, val = 0x%lx\n", regnum, reg); + sprintf(buf, "%.08lx", swab64(reg)); +out: + return gdb_send_reply(buf, ctx); + +out_err: + dbg_printk("Register read unsupported regnum = 0x%lx\n", regnum); + sprintf(buf, "%s", "x"); + goto out; +} +#else + +#define ptoff(V) ((unsigned int) &((struct pt_regs *)0x0)->V) +struct reg_to_ptreg_index { + unsigned int reg; + unsigned int ptregoff; +}; + +static struct reg_to_ptreg_index gr_reg_to_ptreg_index[] = { + {IA64_GR0_REGNUM + 1, ptoff(r1)}, + {IA64_GR0_REGNUM + 2, ptoff(r2)}, + {IA64_GR0_REGNUM + 3, ptoff(r3)}, + {IA64_GR0_REGNUM + 8, ptoff(r8)}, + {IA64_GR0_REGNUM + 9, ptoff(r9)}, + {IA64_GR0_REGNUM + 10, ptoff(r10)}, + {IA64_GR0_REGNUM + 11, ptoff(r11)}, + {IA64_GR0_REGNUM + 12, ptoff(r12)}, + {IA64_GR0_REGNUM + 13, ptoff(r13)}, + {IA64_GR0_REGNUM + 14, ptoff(r14)}, + {IA64_GR0_REGNUM + 15, ptoff(r15)}, + {IA64_GR0_REGNUM + 16, ptoff(r16)}, + {IA64_GR0_REGNUM + 17, ptoff(r17)}, + {IA64_GR0_REGNUM + 18, ptoff(r18)}, + {IA64_GR0_REGNUM + 19, ptoff(r19)}, + {IA64_GR0_REGNUM + 20, ptoff(r20)}, + {IA64_GR0_REGNUM + 21, ptoff(r21)}, + {IA64_GR0_REGNUM + 22, ptoff(r22)}, + {IA64_GR0_REGNUM + 23, ptoff(r23)}, + {IA64_GR0_REGNUM + 24, ptoff(r24)}, + {IA64_GR0_REGNUM + 25, ptoff(r25)}, + {IA64_GR0_REGNUM + 26, ptoff(r26)}, + {IA64_GR0_REGNUM + 27, ptoff(r27)}, + {IA64_GR0_REGNUM + 28, ptoff(r28)}, + {IA64_GR0_REGNUM + 29, ptoff(r29)}, + {IA64_GR0_REGNUM + 30, ptoff(r30)}, + {IA64_GR0_REGNUM + 31, ptoff(r31)}, +}; + +static struct reg_to_ptreg_index br_reg_to_ptreg_index[] = { + {IA64_BR0_REGNUM, ptoff(b0)}, + {IA64_BR0_REGNUM + 6, ptoff(b6)}, + {IA64_BR0_REGNUM + 7, ptoff(b7)}, +}; + +static struct reg_to_ptreg_index ar_reg_to_ptreg_index[] = { + {IA64_PFS_REGNUM, ptoff(ar_pfs)}, + {IA64_UNAT_REGNUM, ptoff(ar_unat)}, + {IA64_RNAT_REGNUM, ptoff(ar_rnat)}, + {IA64_BSPSTORE_REGNUM, ptoff(ar_bspstore)}, + {IA64_RSC_REGNUM, ptoff(ar_rsc)}, + {IA64_CSD_REGNUM, ptoff(ar_csd)}, + {IA64_SSD_REGNUM, ptoff(ar_ssd)}, + {IA64_FPSR_REGNUM, ptoff(ar_fpsr)}, + {IA64_CCV_REGNUM, ptoff(ar_ccv)}, +}; + +#ifndef XEN +extern atomic_t cpu_doing_single_step; +#endif + +static int kgdb_gr_reg(int regnum, struct unw_frame_info *info, + unsigned long *reg, int rw) +{ + char nat; + + if ((regnum >= IA64_GR0_REGNUM && regnum <= (IA64_GR0_REGNUM + 1)) || + (regnum >= (IA64_GR0_REGNUM + 4) && + regnum <= (IA64_GR0_REGNUM + 7))) + return !unw_access_gr(info, regnum - IA64_GR0_REGNUM, + reg, &nat, rw); + else + return 0; +} +static int kgdb_gr_ptreg(int regnum, struct pt_regs * ptregs, + struct unw_frame_info *info, unsigned long *reg, int rw) +{ + int i, result = 1; + char nat; + + if (!((regnum >= (IA64_GR0_REGNUM + 2) && + regnum <= (IA64_GR0_REGNUM + 3)) || + (regnum >= (IA64_GR0_REGNUM + 8) && + regnum <= (IA64_GR0_REGNUM + 15)) || + (regnum >= (IA64_GR0_REGNUM + 16) && + regnum <= (IA64_GR0_REGNUM + 31)))) + return 0; + else if (rw && ptregs) { + for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++) + if (gr_reg_to_ptreg_index[i].reg == regnum) { + *((unsigned long *)(((void *)ptregs) + + gr_reg_to_ptreg_index[i].ptregoff)) = *reg; + break; + } + } else if (!rw && ptregs) { + for (i = 0; i < ARRAY_SIZE(gr_reg_to_ptreg_index); i++) + if (gr_reg_to_ptreg_index[i].reg == regnum) { + *reg = *((unsigned long *) + (((void *)ptregs) + + gr_reg_to_ptreg_index[i].ptregoff)); + break; + } + } else + result = !unw_access_gr(info, regnum - IA64_GR0_REGNUM, + reg, &nat, rw); + return result; +} + +static int kgdb_br_reg(int regnum, struct pt_regs * ptregs, + struct unw_frame_info *info, unsigned long *reg, int rw) +{ + int i, result = 1; + + if (!(regnum >= IA64_BR0_REGNUM && regnum <= (IA64_BR0_REGNUM + 7))) + return 0; + + switch (regnum) { + case IA64_BR0_REGNUM: + case IA64_BR0_REGNUM + 6: + case IA64_BR0_REGNUM + 7: + if (rw) { + for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++) + if (br_reg_to_ptreg_index[i].reg == regnum) { + *((unsigned long *) + (((void *)ptregs) + + br_reg_to_ptreg_index[i].ptregoff)) = + *reg; + break; + } + } else + for (i = 0; i < ARRAY_SIZE(br_reg_to_ptreg_index); i++) + if (br_reg_to_ptreg_index[i].reg == regnum) { + *reg = *((unsigned long *) + (((void *)ptregs) + + br_reg_to_ptreg_index[i]. + ptregoff)); + break; + } + break; + case IA64_BR0_REGNUM + 1: + case IA64_BR0_REGNUM + 2: + case IA64_BR0_REGNUM + 3: + case IA64_BR0_REGNUM + 4: + case IA64_BR0_REGNUM + 5: + result = !unw_access_br(info, regnum - IA64_BR0_REGNUM, + reg, rw); + break; + } + + return result; +} + +static int kgdb_fr_reg(int regnum, char *inbuffer, struct pt_regs * ptregs, + struct unw_frame_info *info, unsigned long *reg, + struct ia64_fpreg *freg, int rw) +{ + int result = 1; + + if (!(regnum >= IA64_FR0_REGNUM && regnum <= (IA64_FR0_REGNUM + 127))) + return 0; + + switch (regnum) { + case IA64_FR0_REGNUM + 6: + case IA64_FR0_REGNUM + 7: + case IA64_FR0_REGNUM + 8: + case IA64_FR0_REGNUM + 9: + case IA64_FR0_REGNUM + 10: + case IA64_FR0_REGNUM + 11: + case IA64_FR0_REGNUM + 12: + if (rw) { +#ifndef XEN + char *ptr = inbuffer; + + freg->u.bits[0] = *reg; + kgdb_hex2long(&ptr, &freg->u.bits[1]); + *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))) = + *freg; +#else + printk("%s: %d: writing to fpreg is not supported.\n", + __func__, __LINE__); +#endif + break; + } else if (!ptregs) + result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM, + freg, rw); + else +#ifndef XEN + *freg = + *(&ptregs->f6 + (regnum - (IA64_FR0_REGNUM + 6))); +#else + //XXX struct ia64_fpreg and struct pt_fpreg are same. + *freg = *((struct ia64_fpreg*)(&ptregs->f6 + + (regnum - (IA64_FR0_REGNUM + 6)))); +#endif + break; + default: + if (!rw) + result = !unw_access_fr(info, regnum - IA64_FR0_REGNUM, + freg, rw); + else + result = 0; + break; + } + + return result; +} + +static int kgdb_ar_reg(int regnum, struct pt_regs * ptregs, + struct unw_frame_info *info, unsigned long *reg, int rw) +{ + int result = 0, i; + + if (!(regnum >= IA64_AR0_REGNUM && regnum <= IA64_EC_REGNUM)) + return 0; + + if (rw && ptregs) { + for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++) + if (ar_reg_to_ptreg_index[i].reg == regnum) { + *((unsigned long *) (((void *)ptregs) + + ar_reg_to_ptreg_index[i].ptregoff)) = + *reg; + result = 1; + break; + } + } else if (ptregs) { + for (i = 0; i < ARRAY_SIZE(ar_reg_to_ptreg_index); i++) + if (ar_reg_to_ptreg_index[i].reg == regnum) { + *reg = *((unsigned long *) (((void *)ptregs) + + ar_reg_to_ptreg_index[i].ptregoff)); + result = 1; + break; + } + } + + if (result) + return result; + + result = 1; + + switch (regnum) { + case IA64_CSD_REGNUM: + result = !unw_access_ar(info, UNW_AR_CSD, reg, rw); + break; + case IA64_SSD_REGNUM: + result = !unw_access_ar(info, UNW_AR_SSD, reg, rw); + break; + case IA64_UNAT_REGNUM: + result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); + break; + case IA64_RNAT_REGNUM: + result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); + break; + case IA64_BSPSTORE_REGNUM: + result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); + break; + case IA64_PFS_REGNUM: + result = !unw_access_ar(info, UNW_AR_RNAT, reg, rw); + break; + case IA64_LC_REGNUM: + result = !unw_access_ar(info, UNW_AR_LC, reg, rw); + break; + case IA64_EC_REGNUM: + result = !unw_access_ar(info, UNW_AR_EC, reg, rw); + break; + case IA64_FPSR_REGNUM: + result = !unw_access_ar(info, UNW_AR_FPSR, reg, rw); + break; + case IA64_RSC_REGNUM: + result = !unw_access_ar(info, UNW_AR_RSC, reg, rw); + break; + case IA64_CCV_REGNUM: + result = !unw_access_ar(info, UNW_AR_CCV, reg, rw); + break; + default: + result = 0; + } + + return result; +} + +#ifndef XEN +void kgdb_get_reg(char *outbuffer, int regnum, struct unw_frame_info *info, + struct pt_regs *ptregs) +#else +static int +kgdb_get_reg(int regnum, struct unw_frame_info *info, + struct cpu_user_regs* ptregs, + unsigned long* __reg, struct ia64_fpreg* __freg) +#endif +{ + unsigned long reg, size = 0, *mem = ® + struct ia64_fpreg freg; + + if (kgdb_gr_reg(regnum, info, ®, 0) || + kgdb_gr_ptreg(regnum, ptregs, info, ®, 0) || + kgdb_br_reg(regnum, ptregs, info, ®, 0) || + kgdb_ar_reg(regnum, ptregs, info, ®, 0)) + size = sizeof(reg); + else if (kgdb_fr_reg(regnum, NULL, ptregs, info, ®, &freg, 0)) { + size = sizeof(freg); + mem = (unsigned long *)&freg; + } else if (regnum == IA64_IP_REGNUM) { + if (!ptregs) { + unw_get_ip(info, ®); + size = sizeof(reg); + } else { + reg = ptregs->cr_iip; + size = sizeof(reg); + } + } else if (regnum == IA64_CFM_REGNUM) { + if (!ptregs) + unw_get_cfm(info, ®); + else + reg = ptregs->cr_ifs; + size = sizeof(reg); + } else if (regnum == IA64_PSR_REGNUM) { +#ifndef XEN + if (!ptregs && kgdb_usethread) + ptregs = (struct pt_regs *) + ((unsigned long)kgdb_usethread + + IA64_STK_OFFSET) - 1; +#endif + if (ptregs) + reg = ptregs->cr_ipsr; + size = sizeof(reg); + } else if (regnum == IA64_PR_REGNUM) { + if (ptregs) + reg = ptregs->pr; + else + unw_access_pr(info, ®, 0); + size = sizeof(reg); + } else if (regnum == IA64_BSP_REGNUM) { + unw_get_bsp(info, ®); + size = sizeof(reg); + } + +#ifndef XEN + if (size) { + kgdb_mem2hex((char *) mem, outbuffer, size); + outbuffer[size*2] = 0; + } + else + strcpy(outbuffer, "E0"); + + return; +#else + if (size) { + if (size == sizeof(reg)) { + *__reg = reg; + } else { + BUG_ON(size != sizeof(freg)); + *__freg = freg; + } + return 0; + } + + return -1; +#endif +} + +#ifndef XEN +static int inline kgdb_get_blocked_state(struct task_struct *p, + struct unw_frame_info *unw) +#else +static int +kgdb_get_blocked_state(struct vcpu *p, + struct cpu_user_regs *regs, + struct unw_frame_info *unw) +#endif +{ + unsigned long ip; + int count = 0; + +#ifndef XEN + unw_init_from_blocked_task(unw, p); +#endif + ip = 0UL; + do { + if (unw_unwind(unw) < 0) + return -1; + unw_get_ip(unw, &ip); +#ifndef XEN + if (!in_sched_functions(ip)) + break; +#else + dbg_printk("ip 0x%lx cr_iip 0x%lx\n", ip, regs->cr_iip); + if (ip == regs->cr_iip) + break; +#endif + } while (count++ < 16); + + if (!ip) + return -1; + else + return 0; +} + +struct gdb_callback_arg +{ + struct cpu_user_regs* regs; + unsigned long regnum; + unsigned long* reg; + struct pt_fpreg* freg; + + int error; + // 1: not supported + // 0: success + // -1: failure +}; + +static void +gdb_get_reg_callback(struct unw_frame_info* info, void* __arg) +{ + struct gdb_callback_arg* arg = (struct gdb_callback_arg*)__arg; + + if (kgdb_get_blocked_state(current, arg->regs, info) < 0) { + dbg_printk("%s: kgdb_get_blocked_state failed\n", __func__); + arg->error = -1; + return; + } + //XXX struct ia64_fpreg and struct pt_fpreg are same. + if (kgdb_get_reg(arg->regnum, info, arg->regs, arg->reg, + (struct ia64_fpreg*)arg->freg) < 0) { + dbg_printk("%s: kgdb_get_reg failed\n", __func__); + arg->error = 1; + return; + } + arg->error = 0; + return; +} + +void +gdb_arch_read_reg(unsigned long regnum, struct cpu_user_regs *regs, + struct gdb_context *ctx) +{ + struct gdb_callback_arg arg; + unsigned long reg; + struct pt_fpreg freg; + char buf[16 * 2 + 1]; + + if (regnum >= NUM_REGS) { + dbg_printk("%s: regnum %ld\n", __func__, regnum); + goto out_err; + } + + arg.regs = regs; + arg.regnum = regnum; + arg.reg = ® + arg.freg = &freg; + arg.error = 0; + unw_init_running(&gdb_get_reg_callback, (void*)&arg); + if (arg.error < 0) { + dbg_printk("%s: gdb_get_reg_callback failed\n", __func__); + goto out_err; + } + + if (arg.error > 0) { + // notify gdb that this register is not supported. + // see fetch_register_using_p() in gdb/remote.c. + sprintf(buf, "%s", "x"); + } else if (IA64_FR0_REGNUM <= regnum && regnum <= IA64_FR0_REGNUM + 127) { + sprintf(buf, "%.016lx", swab64(freg.u.bits[0])); + sprintf(buf + 16, "%.016lx", swab64(freg.u.bits[1])); + } else { + sprintf(buf, "%.016lx", swab64(reg)); + } +out: + return gdb_send_reply(buf, ctx); + +out_err: + dbg_printk("Register read unsupported regnum = 0x%lx\n", regnum); + sprintf(buf, "%s", "E0"); + goto out; +} +#endif + +void +gdb_arch_resume(struct cpu_user_regs *regs, + unsigned long addr, unsigned long type, + struct gdb_context *ctx) +{ + /* XXX */ + if (type == GDB_STEP) { + gdb_send_reply("S01", ctx); + } +} + +void +gdb_arch_print_state(struct cpu_user_regs *regs) +{ + /* XXX */ +} + +void +gdb_arch_enter(struct cpu_user_regs *regs) +{ + /* nothing */ +} + +void +gdb_arch_exit(struct cpu_user_regs *regs) +{ + /* nothing */ +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/gdbstub.c --- /dev/null Tue Jan 10 15:21:00 2006 +++ b/xen/arch/x86/gdbstub.c Tue Jan 24 16:54:34 2006 @@ -0,0 +1,146 @@ +/* + * x86-specific gdb stub routines + * based on x86 cdb(xen/arch/x86/cdb.c), but Extensively modified. + * + * Copyright (C) 2006 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan. K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <asm/debugger.h> + +u16 +gdb_arch_signal_num(struct cpu_user_regs *regs, unsigned long cookie) +{ + /* XXX */ + return 1; +} + +void +gdb_arch_read_reg_array(struct cpu_user_regs *regs, struct gdb_context *ctx) +{ +#define GDB_REG(r) gdb_write_to_packet_hex(r, sizeof(r), ctx); + GDB_REG(regs->eax); + GDB_REG(regs->ecx); + GDB_REG(regs->edx); + GDB_REG(regs->ebx); + GDB_REG(regs->esp); + GDB_REG(regs->ebp); + GDB_REG(regs->esi); + GDB_REG(regs->edi); + GDB_REG(regs->eip); + GDB_REG(regs->eflags); +#undef GDB_REG +#define GDB_SEG_REG(s) gdb_write_to_packet_hex(s, sizeof(u32), ctx); + /* sizeof(segment) = 16bit */ + /* but gdb requires its return value as 32bit value */ + GDB_SEG_REG(regs->cs); + GDB_SEG_REG(regs->ss); + GDB_SEG_REG(regs->ds); + GDB_SEG_REG(regs->es); + GDB_SEG_REG(regs->fs); + GDB_SEG_REG(regs->gs); +#undef GDB_SEG_REG + gdb_send_packet(ctx); +} + +void +gdb_arch_write_reg_array(struct cpu_user_regs *regs, const char* buf, + struct gdb_context *ctx) +{ + /* XXX TODO */ + gdb_send_reply("E02", ctx); +} + +void +gdb_arch_read_reg(unsigned long regnum, struct cpu_user_regs *regs, + struct gdb_context *ctx) +{ + gdb_send_reply("", ctx); +} + +/* Like copy_from_user, but safe to call with interrupts disabled. + Trust me, and don't look behind the curtain. */ +unsigned +gdb_arch_copy_from_user(void *dest, const void *src, unsigned len) +{ + int __d0, __d1, __d2; + ASSERT(!local_irq_is_enabled()); + __asm__ __volatile__( + "1: rep; movsb\n" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: addl $4, %%esp\n" + " jmp 2b\n" + ".previous\n" + ".section __pre_ex_table,\"a\"\n" + " "__FIXUP_ALIGN"\n" + " "__FIXUP_WORD" 1b,3b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " "__FIXUP_ALIGN"\n" + " "__FIXUP_WORD" 1b,2b\n" + ".previous\n" + : "=c"(__d2), "=D" (__d0), "=S" (__d1) + : "0"(len), "1"(dest), "2"(src) + : "memory"); + ASSERT(!local_irq_is_enabled()); + return __d2; +} + +unsigned int +gdb_arch_copy_to_user(void *dest, const void *src, unsigned len) +{ + /* XXX */ + return len; +} + +void +gdb_arch_resume(struct cpu_user_regs *regs, + unsigned long addr, unsigned long type, + struct gdb_context *ctx) +{ + /* XXX */ + if (type == GDB_STEP) { + gdb_send_reply("S01", ctx); + } +} + +void +gdb_arch_print_state(struct cpu_user_regs *regs) +{ + /* XXX */ +} + +void +gdb_arch_enter(struct cpu_user_regs *regs) +{ + /* nothing */ +} + +void +gdb_arch_exit(struct cpu_user_regs *regs) +{ + /* nothing */ +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff -r 40bb46f599d9 -r a38c292e8390 xen/common/gdbstub.c --- /dev/null Tue Jan 10 15:21:00 2006 +++ b/xen/common/gdbstub.c Tue Jan 24 16:54:34 2006 @@ -0,0 +1,593 @@ +/* + * Copyright (C) 2005 Jimi Xenidis <jimix@xxxxxxxxxxxxxx>, IBM Corporation + * Copyright (C) 2006 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan. K.K. + * + * gdbstub arch neutral part + * Based on x86 cdb (xen/arch/x86/cdb.c) and ppc gdbstub(xen/common/gdbstub.c) + * But extensively modified. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * gdbstub: implements the architecture independant parts of the + * gdb remote protocol. + */ + +/* We try to avoid assuming much about what the rest of the system is + doing. In particular, dynamic memory allocation is out of the + question. */ + +/* Resuming after we've stopped used to work, but more through luck + than any actual intention. It doesn't at the moment. */ + +#include <xen/lib.h> +#include <asm/uaccess.h> +#include <xen/spinlock.h> +#include <xen/serial.h> +#include <xen/irq.h> +#include <asm/debugger.h> +#include <xen/init.h> +#include <xen/smp.h> +#include <xen/console.h> + +/* Printk isn't particularly safe just after we've trapped to the + debugger. so avoid it. */ +#define dbg_printk(...) +/*#define dbg_printk(...) printk(__VA_ARGS__)*/ + +#define GDB_RETRY_MAX 10 + +static char opt_gdb[30] = "none"; +string_param("gdb", opt_gdb); + +/* value <-> char (de)serialzers */ +char +hex2char(unsigned long x) +{ + const char array[] = "0123456789abcdef"; + + return array[x & 15]; +} + +int +char2hex(unsigned char c) +{ + if ( (c >= '0') && (c <= '9') ) + return c - '0'; + else if ( (c >= 'a') && (c <= 'f') ) + return c - 'a' + 10; + else if ( (c >= 'A') && (c <= 'F') ) + return c - 'A' + 10; + else + BUG(); + return -1; +} + +char +str2hex(const char *str) +{ + return (char2hex(str[0]) << 4) | char2hex(str[1]); +} + +unsigned long +str2ulong(const char *str, unsigned long bytes) +{ + unsigned long x = 0; + unsigned long i = 0; + + while ( *str && (i < (bytes * 2)) ) + { + x <<= 4; + x += char2hex(*str); + ++str; + ++i; + } + + return x; +} + +/* gdb io wrappers */ +static signed long +gdb_io_write(const char *buf, unsigned long len, struct gdb_context *ctx) +{ + int i; + for ( i = 0; i < len; i++ ) + serial_putc(ctx->serhnd, buf[i]); + return i; +} + +static int +gdb_io_write_char(u8 data, struct gdb_context *ctx) +{ + return gdb_io_write((char*)&data, 1, ctx); +} + +static unsigned char +gdb_io_read(struct gdb_context *ctx) +{ + return serial_getc(ctx->serhnd); +} + +/* Receive a command. Returns -1 on csum error, 0 otherwise. */ +/* Does not acknowledge. */ +static int +attempt_receive_packet(struct gdb_context *ctx) +{ + u8 csum; + u8 received_csum; + u8 ch; + + /* Skip over everything up to the first '$' */ + while ( (ch = gdb_io_read(ctx)) != '$' ) + continue; + + csum = 0; + for ( ctx->in_bytes = 0; + ctx->in_bytes < sizeof(ctx->in_buf); + ctx->in_bytes++ ) + { + ch = gdb_io_read(ctx); + if ( ch == '#' ) + break; + ctx->in_buf[ctx->in_bytes] = ch; + csum += ch; + } + + if ( ctx->in_bytes == sizeof(ctx->in_buf) ) + { + dbg_printk("WARNING: GDB sent a stupidly big packet.\n"); + return -1; + } + + ctx->in_buf[ctx->in_bytes] = '\0'; + received_csum = char2hex(gdb_io_read(ctx)) * 16 + + char2hex(gdb_io_read(ctx)); + + return (received_csum == csum) ? 0 : -1; +} + +/* Receive a command, discarding up to ten packets with csum + * errors. Acknowledges all received packets. */ +static int +receive_command(struct gdb_context *ctx) +{ + int r, count = 0; + + count = 0; + do { + r = attempt_receive_packet(ctx); + gdb_io_write_char((r < 0) ? '-' : '+', ctx); + count++; + } while ( (r < 0) && (count < GDB_RETRY_MAX) ); + + return r; +} + +/* routines to send reply packets */ + +static void +gdb_start_packet(struct gdb_context *ctx) +{ + ctx->out_buf[0] = '$'; + ctx->out_offset = 1; + ctx->out_csum = 0; +} + +static void +gdb_write_to_packet_char(u8 data, struct gdb_context *ctx) +{ + ctx->out_csum += data; + ctx->out_buf[ctx->out_offset] = data; + ctx->out_offset++; +} + +void +gdb_write_to_packet(const char *buf, int count, struct gdb_context *ctx) +{ + int x; + for ( x = 0; x < count; x++ ) + gdb_write_to_packet_char(buf[x], ctx); +} + +void +gdb_write_to_packet_str(const char *buf, struct gdb_context *ctx) +{ + gdb_write_to_packet(buf, strlen(buf), ctx); +} + +void +gdb_write_to_packet_hex(unsigned long x, int int_size, struct gdb_context *ctx) +{ + char buf[sizeof(unsigned long) * 2 + 1]; + int i = sizeof(unsigned long) * 2; + int width = int_size * 2; + + buf[sizeof(unsigned long) * 2] = 0; + + switch ( int_size ) + { + case sizeof(u8): + case sizeof(u16): + case sizeof(u32): + case sizeof(u64): + break; + default: + dbg_printk("WARNING: %s x: 0x%lx int_size: %d\n", + __func__, x, int_size); + break; + } + + do { + buf[--i] = hex2char(x & 15); + x >>= 4; + } while ( x ); + + while ( (i + width) > (sizeof(unsigned long) * 2) ) + buf[--i] = '0'; + + gdb_write_to_packet(&buf[i], width, ctx); +} + +static int +gdb_check_ack(struct gdb_context *ctx) +{ + u8 c = gdb_io_read(ctx); + + switch ( c ) + { + case '+': + return 1; + case '-': + return 0; + default: + printk("Bad ack: %c\n", c); + return 0; + } +} + +/* Return 0 if the reply was successfully received, !0 otherwise. */ +void +gdb_send_packet(struct gdb_context *ctx) +{ + char buf[3]; + int count; + + sprintf(buf, "%.02x\n", ctx->out_csum); + + gdb_write_to_packet_char('#', ctx); + gdb_write_to_packet(buf, 2, ctx); + + count = 0; + do { + gdb_io_write(ctx->out_buf, ctx->out_offset, ctx); + } while ( !gdb_check_ack(ctx) && (count++ < GDB_RETRY_MAX) ); + + if ( count == GDB_RETRY_MAX ) + dbg_printk("WARNING: %s reached max retry %d\n", + __func__, GDB_RETRY_MAX); +} + +void +gdb_send_reply(const char *buf, struct gdb_context *ctx) +{ + gdb_start_packet(ctx); + gdb_write_to_packet_str(buf, ctx); + gdb_send_packet(ctx); +} + +/* arch neutral command handlers */ + +static void +gdb_cmd_signum(struct gdb_context *ctx) +{ + gdb_write_to_packet_char('S', ctx); + gdb_write_to_packet_hex(ctx->signum, sizeof(ctx->signum), ctx); + gdb_send_packet(ctx); +} + +static void +gdb_cmd_read_mem(unsigned long addr, unsigned long length, + struct gdb_context *ctx) +{ + int x, r; + unsigned char val; + + dbg_printk("Memory read starting at %lx, length %lx.\n", addr, + length); + + for ( x = 0; x < length; x++ ) + { + r = gdb_arch_copy_from_user(&val, (void *)(addr + x), 1); + if ( r != 0 ) + { + dbg_printk("Error reading from %lx.\n", addr + x); + break; + } + gdb_write_to_packet_hex(val, sizeof(val), ctx); + } + + if ( x == 0 ) + gdb_write_to_packet_str("E05", ctx); + + dbg_printk("Read done.\n"); + + gdb_send_packet(ctx); +} + +static void +gdb_cmd_write_mem(unsigned long addr, unsigned long length, + const char *buf, struct gdb_context *ctx) +{ + int x, r; + unsigned char val; + + dbg_printk("Memory write starting at %lx, length %lx.\n", addr, length); + + for ( x = 0; x < length; x++, addr++, buf += 2 ) + { + val = str2ulong(buf, sizeof(val)); + r = gdb_arch_copy_to_user((void*)addr, (void*)&val, 1); + if ( r != 0 ) + { + dbg_printk("Error writing to %lx.\n", addr); + break; + } + } + + gdb_write_to_packet_str((x != length) ? "OK" : "E11", ctx); + + dbg_printk("Write done.\n"); + + gdb_send_packet(ctx); +} + +/* command dispatcher */ +static int +process_command(struct cpu_user_regs *regs, struct gdb_context *ctx) +{ + char *ptr; + unsigned long addr, length; + int resume = 0; + + /* XXX check ctx->in_bytes >= 2 or similar. */ + + gdb_start_packet(ctx); + switch ( ctx->in_buf[0] ) + { + case '?': /* query signal number */ + gdb_cmd_signum(ctx); + break; + case 'H': /* thread operations */ + gdb_send_reply("OK", ctx); + break; + case 'g': /* Read registers */ + gdb_arch_read_reg_array(regs, ctx); + ASSERT(!local_irq_is_enabled()); + break; + case 'G': /* Write registers */ + gdb_arch_write_reg_array(regs, ctx->in_buf + 1, ctx); + break; + case 'm': /* Read memory */ + addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16); + if ( (ptr == (ctx->in_buf + 1)) || (ptr[0] != ',') ) + { + gdb_send_reply("E03", ctx); + return 0; + } + length = simple_strtoul(ptr + 1, &ptr, 16); + if ( ptr[0] != 0 ) + { + gdb_send_reply("E04", ctx); + return 0; + } + gdb_cmd_read_mem(addr, length, ctx); + ASSERT(!local_irq_is_enabled()); + break; + case 'M': /* Write memory */ + addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16); + if ( (ptr == (ctx->in_buf + 1)) || (ptr[0] != ':') ) + { + gdb_send_reply("E03", ctx); + return 0; + } + length = simple_strtoul(ptr + 1, &ptr, 16); + gdb_cmd_write_mem(addr, length, ptr, ctx); + break; + case 'p': /* read register */ + addr = simple_strtoul(ctx->in_buf + 1, &ptr, 16); + if ( ptr == (ctx->in_buf + 1) ) + { + gdb_send_reply("E03", ctx); + return 0; + } + if ( ptr[0] != 0 ) + { + gdb_send_reply("E04", ctx); + return 0; + } + gdb_arch_read_reg(addr, regs, ctx); + break; + case 'Z': /* We need to claim to support these or gdb + won't let you continue the process. */ + case 'z': + gdb_send_reply("OK", ctx); + break; + + case 'D': + ctx->currently_attached = 0; + gdb_send_reply("OK", ctx); + /* fall through */ + case 'k': + ctx->connected = 0; + /* fall through */ + case 's': /* Single step */ + case 'c': /* Resume at current address */ + { + unsigned long addr = ~((unsigned long)0); + unsigned long type = GDB_CONTINUE; + if ( ctx->in_buf[0] == 's' ) + type = GDB_STEP; + if ( ((ctx->in_buf[0] == 's') || (ctx->in_buf[0] == 'c')) && + ctx->in_buf[1] ) + addr = str2ulong(&ctx->in_buf[1], sizeof(unsigned long)); + if ( ctx->in_buf[0] != 'D' ) + ctx->currently_attached = 1; + resume = 1; + gdb_arch_resume(regs, addr, type, ctx); + break; + } + + default: + gdb_send_reply("", ctx); + break; + } + return resume; +} + +static struct gdb_context +__gdb_ctx = { + .serhnd = -1, + .currently_attached = 0, + .running = ATOMIC_INIT(1), + .connected = 0, + .signum = 1, + .in_bytes = 0, + .out_offset = 0, + .out_csum = 0, +}; +static struct gdb_context *gdb_ctx = &__gdb_ctx; + +/* trap handler: main entry point */ +int +__trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie) +{ + int resume = 0; + int r; + unsigned flags; + + if ( gdb_ctx->serhnd < 0 ) + { + dbg_printk("Debugger not ready yet.\n"); + return 0; + } + + /* We rely on our caller to ensure we're only on one processor + * at a time... We should probably panic here, but given that + * we're a debugger we should probably be a little tolerant of + * things going wrong. */ + /* We don't want to use a spin lock here, because we're doing + two distinct things: + + 1 -- we don't want to run on more than one processor at a time, + and + 2 -- we want to do something sensible if we re-enter ourselves. + + Spin locks are good for 1, but useless for 2. */ + if ( !atomic_dec_and_test(&gdb_ctx->running) ) + { + printk("WARNING WARNING WARNING: Avoiding recursive gdb.\n"); + atomic_inc(&gdb_ctx->running); + return 0; + } + + if ( !gdb_ctx->connected ) + { + printk("GDB connection activated\n"); + gdb_arch_print_state(regs); + gdb_ctx->connected = 1; + } + + smp_send_stop(); + + /* Try to make things a little more stable by disabling + interrupts while we're here. */ + local_irq_save(flags); + + watchdog_disable(); + console_start_sync(); + + /* Shouldn't really do this, but otherwise we stop for no + obvious reason, which is Bad */ + printk("Waiting for GDB to attach to Gdb\n"); + + gdb_arch_enter(regs); + gdb_ctx->signum = gdb_arch_signal_num(regs, cookie); + /* If gdb is already attached, tell it we've stopped again. */ + if ( gdb_ctx->currently_attached ) + { + gdb_start_packet(gdb_ctx); + gdb_cmd_signum(gdb_ctx); + } + + while ( resume == 0 ) + { + ASSERT(!local_irq_is_enabled()); + r = receive_command(gdb_ctx); + ASSERT(!local_irq_is_enabled()); + if ( r < 0 ) + { + dbg_printk("GDB disappeared, trying to resume Xen...\n"); + resume = 1; + } + else + { + ASSERT(!local_irq_is_enabled()); + resume = process_command(regs, gdb_ctx); + ASSERT(!local_irq_is_enabled()); + } + } + + gdb_arch_exit(regs); + console_end_sync(); + watchdog_enable(); + atomic_inc(&gdb_ctx->running); + + local_irq_restore(flags); + + return 0; +} + +/* + * initialization + * XXX TODO + * This should be an explicit call from architecture code. + * initcall is far too late for some early debugging, and only the + * architecture code knows when this call can be made. + */ +static int +initialize_gdb(void) +{ + if ( !strcmp(opt_gdb, "none") ) + return 0; + gdb_ctx->serhnd = serial_parse_handle(opt_gdb); + if ( gdb_ctx->serhnd == -1 ) + panic("Can't parse %s as GDB serial info.\n", opt_gdb); + + printk("Gdb initialised.\n"); + return 0; +} + +__initcall(initialize_gdb); + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff -r 40bb46f599d9 -r a38c292e8390 xen/common/timer.c --- /dev/null Tue Jan 10 15:21:00 2006 +++ b/xen/common/timer.c Tue Jan 24 16:54:34 2006 @@ -0,0 +1,308 @@ +/****************************************************************************** + * timer.c + * + * Copyright (c) 2002-2003 Rolf Neugebauer + * Copyright (c) 2002-2005 K A Fraser + */ + +#include <xen/config.h> +#include <xen/init.h> +#include <xen/types.h> +#include <xen/errno.h> +#include <xen/sched.h> +#include <xen/lib.h> +#include <xen/smp.h> +#include <xen/perfc.h> +#include <xen/time.h> +#include <xen/softirq.h> +#include <xen/timer.h> +#include <xen/keyhandler.h> +#include <asm/system.h> +#include <asm/desc.h> + +/* + * We pull handlers off the timer list this far in future, + * rather than reprogramming the time hardware. + */ +#define TIMER_SLOP (50*1000) /* ns */ + +struct timers { + spinlock_t lock; + struct timer **heap; + struct timer *running; +} __cacheline_aligned; + +struct timers timers[NR_CPUS]; + +extern int reprogram_timer(s_time_t timeout); + +/**************************************************************************** + * HEAP OPERATIONS. + */ + +#define GET_HEAP_SIZE(_h) ((int)(((u16 *)(_h))[0])) +#define SET_HEAP_SIZE(_h,_v) (((u16 *)(_h))[0] = (u16)(_v)) + +#define GET_HEAP_LIMIT(_h) ((int)(((u16 *)(_h))[1])) +#define SET_HEAP_LIMIT(_h,_v) (((u16 *)(_h))[1] = (u16)(_v)) + +/* Sink down element @pos of @heap. */ +static void down_heap(struct timer **heap, int pos) +{ + int sz = GET_HEAP_SIZE(heap), nxt; + struct timer *t = heap[pos]; + + while ( (nxt = (pos << 1)) <= sz ) + { + if ( ((nxt+1) <= sz) && (heap[nxt+1]->expires < heap[nxt]->expires) ) + nxt++; + if ( heap[nxt]->expires > t->expires ) + break; + heap[pos] = heap[nxt]; + heap[pos]->heap_offset = pos; + pos = nxt; + } + + heap[pos] = t; + t->heap_offset = pos; +} + +/* Float element @pos up @heap. */ +static void up_heap(struct timer **heap, int pos) +{ + struct timer *t = heap[pos]; + + while ( (pos > 1) && (t->expires < heap[pos>>1]->expires) ) + { + heap[pos] = heap[pos>>1]; + heap[pos]->heap_offset = pos; + pos >>= 1; + } + + heap[pos] = t; + t->heap_offset = pos; +} + + +/* Delete @t from @heap. Return TRUE if new top of heap. */ +static int remove_entry(struct timer **heap, struct timer *t) +{ + int sz = GET_HEAP_SIZE(heap); + int pos = t->heap_offset; + + t->heap_offset = 0; + + if ( unlikely(pos == sz) ) + { + SET_HEAP_SIZE(heap, sz-1); + goto out; + } + + heap[pos] = heap[sz]; + heap[pos]->heap_offset = pos; + + SET_HEAP_SIZE(heap, --sz); + + if ( (pos > 1) && (heap[pos]->expires < heap[pos>>1]->expires) ) + up_heap(heap, pos); + else + down_heap(heap, pos); + + out: + return (pos == 1); +} + + +/* Add new entry @t to @heap. Return TRUE if new top of heap. */ +static int add_entry(struct timer ***pheap, struct timer *t) +{ + struct timer **heap = *pheap; + int sz = GET_HEAP_SIZE(heap); + + /* Copy the heap if it is full. */ + if ( unlikely(sz == GET_HEAP_LIMIT(heap)) ) + { + /* old_limit == (2^n)-1; new_limit == (2^(n+4))-1 */ + int old_limit = GET_HEAP_LIMIT(heap); + int new_limit = ((old_limit + 1) << 4) - 1; + heap = xmalloc_array(struct timer *, new_limit + 1); + BUG_ON(heap == NULL); + memcpy(heap, *pheap, (old_limit + 1) * sizeof(*heap)); + SET_HEAP_LIMIT(heap, new_limit); + if ( old_limit != 0 ) + xfree(*pheap); + *pheap = heap; + } + + SET_HEAP_SIZE(heap, ++sz); + heap[sz] = t; + t->heap_offset = sz; + up_heap(heap, sz); + return (t->heap_offset == 1); +} + + +/**************************************************************************** + * TIMER OPERATIONS. + */ + +static inline void __add_timer(struct timer *timer) +{ + int cpu = timer->cpu; + if ( add_entry(&timers[cpu].heap, timer) ) + cpu_raise_softirq(cpu, TIMER_SOFTIRQ); +} + + +static inline void __stop_timer(struct timer *timer) +{ + int cpu = timer->cpu; + if ( remove_entry(timers[cpu].heap, timer) ) + cpu_raise_softirq(cpu, TIMER_SOFTIRQ); +} + + +void set_timer(struct timer *timer, s_time_t expires) +{ + int cpu = timer->cpu; + unsigned long flags; + + spin_lock_irqsave(&timers[cpu].lock, flags); + if ( active_timer(timer) ) + __stop_timer(timer); + timer->expires = expires; + if ( likely(!timer->killed) ) + __add_timer(timer); + spin_unlock_irqrestore(&timers[cpu].lock, flags); +} + + +void stop_timer(struct timer *timer) +{ + int cpu = timer->cpu; + unsigned long flags; + + spin_lock_irqsave(&timers[cpu].lock, flags); + if ( active_timer(timer) ) + __stop_timer(timer); + spin_unlock_irqrestore(&timers[cpu].lock, flags); +} + + +void kill_timer(struct timer *timer) +{ + int cpu = timer->cpu; + unsigned long flags; + + BUG_ON(timers[cpu].running == timer); + + spin_lock_irqsave(&timers[cpu].lock, flags); + if ( active_timer(timer) ) + __stop_timer(timer); + timer->killed = 1; + spin_unlock_irqrestore(&timers[cpu].lock, flags); + + for_each_online_cpu ( cpu ) + while ( timers[cpu].running == timer ) + cpu_relax(); +} + + +static void timer_softirq_action(void) +{ + int cpu = smp_processor_id(); + struct timer *t, **heap; + s_time_t now; + void (*fn)(void *); + void *data; + + spin_lock_irq(&timers[cpu].lock); + + do { + heap = timers[cpu].heap; + now = NOW(); + + while ( (GET_HEAP_SIZE(heap) != 0) && + ((t = heap[1])->expires < (now + TIMER_SLOP)) ) + { + remove_entry(heap, t); + + timers[cpu].running = t; + + fn = t->function; + data = t->data; + + spin_unlock_irq(&timers[cpu].lock); + (*fn)(data); + spin_lock_irq(&timers[cpu].lock); + + /* Heap may have grown while the lock was released. */ + heap = timers[cpu].heap; + } + + timers[cpu].running = NULL; + } + while ( !reprogram_timer(GET_HEAP_SIZE(heap) ? heap[1]->expires : 0) ); + + spin_unlock_irq(&timers[cpu].lock); +} + + +static void dump_timerq(unsigned char key) +{ + struct timer *t; + unsigned long flags; + s_time_t now = NOW(); + int i, j; + + printk("Dumping timer queues: NOW=0x%08X%08X\n", + (u32)(now>>32), (u32)now); + + for_each_online_cpu( i ) + { + printk("CPU[%02d] ", i); + spin_lock_irqsave(&timers[i].lock, flags); + for ( j = 1; j <= GET_HEAP_SIZE(timers[i].heap); j++ ) + { + t = timers[i].heap[j]; + printk (" %d : %p ex=0x%08X%08X %p\n", + j, t, (u32)(t->expires>>32), (u32)t->expires, t->data); + } + spin_unlock_irqrestore(&timers[i].lock, flags); + printk("\n"); + } +} + + +void __init timer_init(void) +{ + static struct timer *dummy_heap; + int i; + + open_softirq(TIMER_SOFTIRQ, timer_softirq_action); + + /* + * All CPUs initially share an empty dummy heap. Only those CPUs that + * are brought online will be dynamically allocated their own heap. + */ + SET_HEAP_SIZE(&dummy_heap, 0); + SET_HEAP_LIMIT(&dummy_heap, 0); + + for ( i = 0; i < NR_CPUS; i++ ) + { + spin_lock_init(&timers[i].lock); + timers[i].heap = &dummy_heap; + } + + register_keyhandler('a', dump_timerq, "dump timer queues"); +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 40bb46f599d9 -r a38c292e8390 xen/include/public/nmi.h --- /dev/null Tue Jan 10 15:21:00 2006 +++ b/xen/include/public/nmi.h Tue Jan 24 16:54:34 2006 @@ -0,0 +1,54 @@ +/****************************************************************************** + * nmi.h + * + * NMI callback registration and reason codes. + * + * Copyright (c) 2005, Keir Fraser <keir@xxxxxxxxxxxxx> + */ + +#ifndef __XEN_PUBLIC_NMI_H__ +#define __XEN_PUBLIC_NMI_H__ + +/* + * NMI reason codes: + * Currently these are x86-specific, stored in arch_shared_info.nmi_reason. + */ + /* I/O-check error reported via ISA port 0x61, bit 6. */ +#define _XEN_NMIREASON_io_error 0 +#define XEN_NMIREASON_io_error (1UL << _XEN_NMIREASON_io_error) + /* Parity error reported via ISA port 0x61, bit 7. */ +#define _XEN_NMIREASON_parity_error 1 +#define XEN_NMIREASON_parity_error (1UL << _XEN_NMIREASON_parity_error) + /* Unknown hardware-generated NMI. */ +#define _XEN_NMIREASON_unknown 2 +#define XEN_NMIREASON_unknown (1UL << _XEN_NMIREASON_unknown) + +/* + * long nmi_op(unsigned int cmd, void *arg) + * NB. All ops return zero on success, else a negative error code. + */ + +/* + * Register NMI callback for this (calling) VCPU. Currently this only makes + * sense for domain 0, vcpu 0. All other callers will be returned EINVAL. + * arg == address of callback function. + */ +#define XENNMI_register_callback 0 + +/* + * Deregister NMI callback for this (calling) VCPU. + * arg == NULL. + */ +#define XENNMI_unregister_callback 1 + +#endif /* __XEN_PUBLIC_NMI_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 40bb46f599d9 -r a38c292e8390 xen/include/xen/gdbstub.h --- /dev/null Tue Jan 10 15:21:00 2006 +++ b/xen/include/xen/gdbstub.h Tue Jan 24 16:54:34 2006 @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2005 Hollis Blanchard <hollisb@xxxxxxxxxx>, IBM Corporation + * Copyright (C) 2006 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan. K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __XEN_GDBSTUB_H__ +#define __XEN_GDBSTUB_H__ + +/* value <-> char (de)serialzers for arch specific gdb backends */ +char hex2char(unsigned long x); +int char2hex(unsigned char c); +char str2hex(const char *str); +unsigned long str2ulong(const char *str, unsigned long bytes); + +struct gdb_context { + int serhnd; + int currently_attached:1; + atomic_t running; + unsigned long connected; + u8 signum; + + char in_buf[PAGE_SIZE]; + unsigned long in_bytes; + + char out_buf[PAGE_SIZE]; + unsigned long out_offset; + u8 out_csum; +}; + +/* interface to arch specific routines */ +void gdb_write_to_packet( + const char *buf, int count, struct gdb_context *ctx); +void gdb_write_to_packet_hex( + unsigned long x, int int_size, struct gdb_context *ctx); +void gdb_send_packet(struct gdb_context *ctx); +void gdb_send_reply(const char *buf, struct gdb_context *ctx); + +/* gdb stub trap handler: entry point */ +int __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie); + +/* arch specific routines */ +u16 gdb_arch_signal_num( + struct cpu_user_regs *regs, unsigned long cookie); +void gdb_arch_read_reg_array( + struct cpu_user_regs *regs, struct gdb_context *ctx); +void gdb_arch_write_reg_array( + struct cpu_user_regs *regs, const char* buf, struct gdb_context *ctx); +void gdb_arch_read_reg( + unsigned long regnum, struct cpu_user_regs *regs, struct gdb_context *ctx); +unsigned int gdb_arch_copy_from_user( + void *dest, const void *src, unsigned len); +unsigned int gdb_arch_copy_to_user( + void *dest, const void *src, unsigned len); +void gdb_arch_resume( + struct cpu_user_regs *regs, unsigned long addr, + unsigned long type, struct gdb_context *ctx); +void gdb_arch_print_state(struct cpu_user_regs *regs); +void gdb_arch_enter(struct cpu_user_regs *regs); +void gdb_arch_exit(struct cpu_user_regs *regs); + +#define GDB_CONTINUE 0 +#define GDB_STEP 1 + +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGBUS 7 +#define SIGFPE 8 +#define SIGSEGV 11 +#define SIGALRM 14 +#define SIGTERM 15 + +#endif /* __XEN_GDBSTUB_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff -r 40bb46f599d9 -r a38c292e8390 xen/include/xen/timer.h --- /dev/null Tue Jan 10 15:21:00 2006 +++ b/xen/include/xen/timer.h Tue Jan 24 16:54:34 2006 @@ -0,0 +1,90 @@ +/****************************************************************************** + * timer.h + * + * Copyright (c) 2002-2003 Rolf Neugebauer + * Copyright (c) 2002-2005 K A Fraser + */ + +#ifndef _TIMER_H_ +#define _TIMER_H_ + +#include <xen/spinlock.h> +#include <xen/time.h> +#include <xen/string.h> + +struct timer { + /* System time expiry value (nanoseconds since boot). */ + s_time_t expires; + /* CPU on which this timer will be installed and executed. */ + unsigned int cpu; + /* On expiry, '(*function)(data)' will be executed in softirq context. */ + void (*function)(void *); + void *data; + /* Timer-heap offset. */ + unsigned int heap_offset; + /* Has this timer been killed (cannot be activated)? */ + int killed; +}; + +/* + * All functions below can be called for any CPU from any CPU in any context. + */ + +/* Returns TRUE if the given timer is on a timer list. */ +static __inline__ int active_timer(struct timer *timer) +{ + return (timer->heap_offset != 0); +} + +/* + * It initialises the static fields of the timer structure. + * It can be called multiple times to reinitialise a single (inactive) timer. + */ +static __inline__ void init_timer( + struct timer *timer, + void (*function)(void *), + void *data, + unsigned int cpu) +{ + memset(timer, 0, sizeof(*timer)); + timer->function = function; + timer->data = data; + timer->cpu = cpu; +} + +/* + * Set the expiry time and activate a timer (which must previously have been + * initialised by init_timer). + */ +extern void set_timer(struct timer *timer, s_time_t expires); + +/* + * Deactivate a timer (which must previously have been initialised by + * init_timer). This function has no effect if the timer is not currently + * active. + */ +extern void stop_timer(struct timer *timer); + +/* + * Deactivate a timer and prevent it from being re-set (future calls to + * set_timer will silently fail). When this function returns it is guaranteed + * that the timer callback handler is not running on any CPU. + */ +extern void kill_timer(struct timer *timer); + +/* + * Initialisation. Must be called before any other timer function. + */ +extern void timer_init(void); + +#endif /* _TIMER_H_ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/blkfront/Kconfig --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/Kconfig Tue Jan 10 15:21:00 2006 +++ /dev/null Tue Jan 24 16:54:34 2006 @@ -1,6 +0,0 @@ - -config XENBLOCK - tristate "Block device driver" - depends on ARCH_XEN - help - Block device driver for Xen diff -r 40bb46f599d9 -r a38c292e8390 linux-2.6-xen-sparse/drivers/xen/netfront/Kconfig --- a/linux-2.6-xen-sparse/drivers/xen/netfront/Kconfig Tue Jan 10 15:21:00 2006 +++ /dev/null Tue Jan 24 16:54:34 2006 @@ -1,6 +0,0 @@ - -config XENNET - tristate "Xen network driver" - depends on NETDEVICES && ARCH_XEN - help - Network driver for Xen diff -r 40bb46f599d9 -r a38c292e8390 xen/arch/x86/cdb.c --- a/xen/arch/x86/cdb.c Tue Jan 10 15:21:00 2006 +++ /dev/null Tue Jan 24 16:54:34 2006 @@ -1,414 +0,0 @@ -/* Simple hacked-up version of pdb for use in post-mortem debugging of - Xen and domain 0. This should be a little cleaner, hopefully. Note - that we can't share a serial line with PDB. */ -/* We try to avoid assuming much about what the rest of the system is - doing. In particular, dynamic memory allocation is out of the - question. */ -/* Resuming after we've stopped used to work, but more through luck - than any actual intention. It doesn't at the moment. */ -#include <xen/lib.h> -#include <asm/uaccess.h> -#include <xen/spinlock.h> -#include <xen/serial.h> -#include <xen/irq.h> -#include <asm/debugger.h> -#include <xen/init.h> -#include <xen/smp.h> -#include <xen/console.h> -#include <asm/apic.h> - -/* Printk isn't particularly safe just after we've trapped to the - debugger. so avoid it. */ -#define dbg_printk(...) - -static char opt_cdb[30] = "none"; -string_param("cdb", opt_cdb); - -struct xendbg_context { - int serhnd; - u8 reply_csum; - int currently_attached:1; -}; - -/* Like copy_from_user, but safe to call with interrupts disabled. - - Trust me, and don't look behind the curtain. */ -static unsigned -dbg_copy_from_user(void *dest, const void *src, unsigned len) -{ - int __d0, __d1, __d2; - ASSERT(!local_irq_is_enabled()); - __asm__ __volatile__( - "1: rep; movsb\n" - "2:\n" - ".section .fixup,\"ax\"\n" - "3: addl $4, %%esp\n" - " jmp 2b\n" - ".previous\n" - ".section __pre_ex_table,\"a\"\n" - " .align 4\n" - " .long 1b,3b\n" - ".previous\n" - ".section __ex_table,\"a\"\n" - " .align 4\n" - " .long 1b,2b\n" - ".previous\n" - : "=c"(__d2), "=D" (__d0), "=S" (__d1) - : "0"(len), "1"(dest), "2"(src) - : "memory"); - ASSERT(!local_irq_is_enabled()); - return __d2; -} - -static void -xendbg_put_char(u8 data, struct xendbg_context *ctx) -{ - ctx->reply_csum += data; - serial_putc(ctx->serhnd, data); -} - -static int -hex_char_val(unsigned char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - else if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - else - BUG(); - return -1; -} - -/* Receive a command. Returns -1 on csum error, 0 otherwise. */ -/* Does not acknowledge. */ -static int -attempt_receive_packet(char *recv_buf, struct xendbg_context *ctx) -{ - int count; - u8 csum; - u8 received_csum; - u8 ch; - - /* Skip over everything up to the first '$' */ - while ((ch = serial_getc(ctx->serhnd)) != '$') - ; - csum = 0; - for (count = 0; count < 4096; count++) { - ch = serial_getc(ctx->serhnd); - if (ch == '#') - break; - recv_buf[count] = ch; - csum += ch; - } - if (count == 4096) { - dbg_printk("WARNING: GDB sent a stupidly big packet.\n"); - return -1; - } - recv_buf[count] = 0; - received_csum = hex_char_val(serial_getc(ctx->serhnd)) * 16 + - hex_char_val(serial_getc(ctx->serhnd)); - if (received_csum == csum) { - return 0; - } else { - return -1; - } -} - -/* Send a string of bytes to the debugger. */ -static void -xendbg_send(const char *buf, int count, struct xendbg_context *ctx) -{ - int x; - for (x = 0; x < count; x++) - xendbg_put_char(buf[x], ctx); -} - -/* Receive a command, discarding up to ten packets with csum - * errors. Acknowledges all received packets. */ -static int -receive_command(char *recv_buf, struct xendbg_context *ctx) -{ - int r; - int count; - - count = 0; - do { - r = attempt_receive_packet(recv_buf, ctx); - if (r < 0) - xendbg_put_char('-', ctx); - else - xendbg_put_char('+', ctx); - count++; - } while (r < 0 && count < 10); - return r; -} - -static void -xendbg_start_reply(struct xendbg_context *ctx) -{ - xendbg_put_char('$', ctx); - ctx->reply_csum = 0; -} - -/* Return 0 if the reply was successfully received, !0 otherwise. */ -static int -xendbg_finish_reply(struct xendbg_context *ctx) -{ - char ch; - char buf[3]; - - sprintf(buf, "%.02x\n", ctx->reply_csum); - - xendbg_put_char('#', ctx); - xendbg_send(buf, 2, ctx); - - ch = serial_getc(ctx->serhnd); - if (ch == '+') - return 0; - else - return 1; -} - -/* Swap the order of the bytes in a work. */ -static inline unsigned -bswab32(unsigned val) -{ - return (((val >> 0) & 0xff) << 24) | - (((val >> 8) & 0xff) << 16) | - (((val >> 16) & 0xff) << 8) | - (((val >> 24) & 0xff) << 0); -} - -static int -handle_memory_read_command(unsigned long addr, unsigned long length, - struct xendbg_context *ctx) -{ - int x; - unsigned char val; - int r; - char buf[2]; - - dbg_printk("Memory read starting at %lx, length %lx.\n", addr, - length); - xendbg_start_reply(ctx); - for (x = 0; x < length; x++) { - r = dbg_copy_from_user(&val, (void *)(addr + x), 1); - if (r != 0) { - dbg_printk("Error reading from %lx.\n", addr + x); - break; - } - sprintf(buf, "%.02x", val); - xendbg_send(buf, 2, ctx); - } - if (x == 0) - xendbg_send("E05", 3, ctx); - dbg_printk("Read done.\n"); - return xendbg_finish_reply(ctx); -} - -static int -xendbg_send_reply(const char *buf, struct xendbg_context *ctx) -{ - xendbg_start_reply(ctx); - xendbg_send(buf, strlen(buf), ctx); - return xendbg_finish_reply(ctx); -} - -static int -handle_register_read_command(struct cpu_user_regs *regs, struct xendbg_context *ctx) -{ - char buf[121]; - - sprintf(buf, - "%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x%.08x", - bswab32(regs->eax), - bswab32(regs->ecx), - bswab32(regs->edx), - bswab32(regs->ebx), - bswab32(regs->esp), - bswab32(regs->ebp), - bswab32(regs->esi), - bswab32(regs->edi), - bswab32(regs->eip), - bswab32(regs->eflags), - bswab32(regs->cs), - bswab32(regs->ss), - bswab32(regs->ds), - bswab32(regs->es), - bswab32(regs->fs), - bswab32(regs->gs)); - return xendbg_send_reply(buf, ctx); -} - -static int -process_command(char *received_packet, struct cpu_user_regs *regs, - struct xendbg_context *ctx) -{ - char *ptr; - unsigned long addr, length; - int retry; - int counter; - int resume = 0; - - /* Repeat until gdb acks the reply */ - counter = 0; - do { - switch (received_packet[0]) { - case 'g': /* Read registers */ - retry = handle_register_read_command(regs, ctx); - ASSERT(!local_irq_is_enabled()); - break; - case 'm': /* Read memory */ - addr = simple_strtoul(received_packet + 1, &ptr, 16); - if (ptr == received_packet + 1 || - ptr[0] != ',') { - xendbg_send_reply("E03", ctx); - return 0; - } - length = simple_strtoul(ptr + 1, &ptr, 16); - if (ptr[0] != 0) { - xendbg_send_reply("E04", ctx); - return 0; - } - retry = - handle_memory_read_command(addr, - length, - ctx); - ASSERT(!local_irq_is_enabled()); - break; - case 'G': /* Write registers */ - case 'M': /* Write memory */ - retry = xendbg_send_reply("E02", ctx); - break; - case 'D': - resume = 1; - ctx->currently_attached = 0; - retry = xendbg_send_reply("", ctx); - break; - case 'c': /* Resume at current address */ - ctx->currently_attached = 1; - resume = 1; - retry = 0; - break; - case 'Z': /* We need to claim to support these or gdb - won't let you continue the process. */ - case 'z': - retry = xendbg_send_reply("OK", ctx); - break; - - case 's': /* Single step */ - case '?': - retry = xendbg_send_reply("S01", ctx); - break; - default: - retry = xendbg_send_reply("", ctx); - break; - } - counter++; - } while (retry == 1 && counter < 10); - if (retry) { - dbg_printk("WARNING: gdb disappeared when we were trying to send it a reply.\n"); - return 1; - } - return resume; -} - -static struct xendbg_context -xdb_ctx = { - serhnd : -1 -}; - -int -__trap_to_cdb(struct cpu_user_regs *regs) -{ - int resume = 0; - int r; - static atomic_t xendbg_running = ATOMIC_INIT(1); - static char recv_buf[4096]; - unsigned flags; - - if (xdb_ctx.serhnd < 0) { - dbg_printk("Debugger not ready yet.\n"); - return 0; - } - - /* We rely on our caller to ensure we're only on one processor - * at a time... We should probably panic here, but given that - * we're a debugger we should probably be a little tolerant of - * things going wrong. */ - /* We don't want to use a spin lock here, because we're doing - two distinct things: - - 1 -- we don't want to run on more than one processor at a time, - and - 2 -- we want to do something sensible if we re-enter ourselves. - - Spin locks are good for 1, but useless for 2. */ - if (!atomic_dec_and_test(&xendbg_running)) { - printk("WARNING WARNING WARNING: Avoiding recursive xendbg.\n"); - atomic_inc(&xendbg_running); - return 0; - } - - smp_send_stop(); - - /* Try to make things a little more stable by disabling - interrupts while we're here. */ - local_irq_save(flags); - - watchdog_disable(); - console_start_sync(); - - /* Shouldn't really do this, but otherwise we stop for no - obvious reason, which is Bad */ - printk("Waiting for GDB to attach to XenDBG\n"); - - /* If gdb is already attached, tell it we've stopped again. */ - if (xdb_ctx.currently_attached) { - do { - r = xendbg_send_reply("S01", &xdb_ctx); - } while (r != 0); - } - - while (resume == 0) { - ASSERT(!local_irq_is_enabled()); - r = receive_command(recv_buf, &xdb_ctx); - ASSERT(!local_irq_is_enabled()); - if (r < 0) { - dbg_printk("GDB disappeared, trying to resume Xen...\n"); - resume = 1; - } else { - ASSERT(!local_irq_is_enabled()); - resume = process_command(recv_buf, regs, &xdb_ctx); - ASSERT(!local_irq_is_enabled()); - } - } - - console_end_sync(); - watchdog_enable(); - atomic_inc(&xendbg_running); - - local_irq_restore(flags); - - return 0; -} - -static int -initialize_xendbg(void) -{ - if (!strcmp(opt_cdb, "none")) - return 0; - xdb_ctx.serhnd = serial_parse_handle(opt_cdb); - if (xdb_ctx.serhnd == -1) - panic("Can't parse %s as CDB serial info.\n", opt_cdb); - - /* Acknowledge any spurious GDB packets. */ - xendbg_put_char('+', &xdb_ctx); - - printk("Xendbg initialised.\n"); - return 0; -} - -__initcall(initialize_xendbg); diff -r 40bb46f599d9 -r a38c292e8390 xen/common/ac_timer.c --- a/xen/common/ac_timer.c Tue Jan 10 15:21:00 2006 +++ /dev/null Tue Jan 24 16:54:34 2006 @@ -1,286 +0,0 @@ -/****************************************************************************** - * ac_timer.c - * - * Copyright (c) 2002-2003 Rolf Neugebauer - * Copyright (c) 2002-2005 K A Fraser - */ - -#include <xen/config.h> -#include <xen/init.h> -#include <xen/types.h> -#include <xen/errno.h> -#include <xen/sched.h> -#include <xen/lib.h> -#include <xen/smp.h> -#include <xen/perfc.h> -#include <xen/time.h> -#include <xen/softirq.h> -#include <xen/ac_timer.h> -#include <xen/keyhandler.h> -#include <asm/system.h> -#include <asm/desc.h> - -/* - * We pull handlers off the timer list this far in future, - * rather than reprogramming the time hardware. - */ -#define TIMER_SLOP (50*1000) /* ns */ - -struct ac_timers { - spinlock_t lock; - struct ac_timer **heap; - unsigned int softirqs; -} __cacheline_aligned; - -struct ac_timers ac_timers[NR_CPUS]; - -extern int reprogram_ac_timer(s_time_t timeout); - -/**************************************************************************** - * HEAP OPERATIONS. - */ - -#define GET_HEAP_SIZE(_h) ((int)(((u16 *)(_h))[0])) -#define SET_HEAP_SIZE(_h,_v) (((u16 *)(_h))[0] = (u16)(_v)) - -#define GET_HEAP_LIMIT(_h) ((int)(((u16 *)(_h))[1])) -#define SET_HEAP_LIMIT(_h,_v) (((u16 *)(_h))[1] = (u16)(_v)) - -/* Sink down element @pos of @heap. */ -static void down_heap(struct ac_timer **heap, int pos) -{ - int sz = GET_HEAP_SIZE(heap), nxt; - struct ac_timer *t = heap[pos]; - - while ( (nxt = (pos << 1)) <= sz ) - { - if ( ((nxt+1) <= sz) && (heap[nxt+1]->expires < heap[nxt]->expires) ) - nxt++; - if ( heap[nxt]->expires > t->expires ) - break; - heap[pos] = heap[nxt]; - heap[pos]->heap_offset = pos; - pos = nxt; - } - - heap[pos] = t; - t->heap_offset = pos; -} - -/* Float element @pos up @heap. */ -static void up_heap(struct ac_timer **heap, int pos) -{ - struct ac_timer *t = heap[pos]; - - while ( (pos > 1) && (t->expires < heap[pos>>1]->expires) ) - { - heap[pos] = heap[pos>>1]; - heap[pos]->heap_offset = pos; - pos >>= 1; - } - - heap[pos] = t; - t->heap_offset = pos; -} - - -/* Delete @t from @heap. Return TRUE if new top of heap. */ -static int remove_entry(struct ac_timer **heap, struct ac_timer *t) -{ - int sz = GET_HEAP_SIZE(heap); - int pos = t->heap_offset; - - t->heap_offset = 0; - - if ( unlikely(pos == sz) ) - { - SET_HEAP_SIZE(heap, sz-1); - goto out; - } - - heap[pos] = heap[sz]; - heap[pos]->heap_offset = pos; - - SET_HEAP_SIZE(heap, --sz); - - if ( (pos > 1) && (heap[pos]->expires < heap[pos>>1]->expires) ) - up_heap(heap, pos); - else - down_heap(heap, pos); - - out: - return (pos == 1); -} - - -/* Add new entry @t to @heap. Return TRUE if new top of heap. */ -static int add_entry(struct ac_timer ***pheap, struct ac_timer *t) -{ - struct ac_timer **heap = *pheap; - int sz = GET_HEAP_SIZE(heap); - - /* Copy the heap if it is full. */ - if ( unlikely(sz == GET_HEAP_LIMIT(heap)) ) - { - /* old_limit == (2^n)-1; new_limit == (2^(n+4))-1 */ - int old_limit = GET_HEAP_LIMIT(heap); - int new_limit = ((old_limit + 1) << 4) - 1; - heap = xmalloc_array(struct ac_timer *, new_limit + 1); - BUG_ON(heap == NULL); - memcpy(heap, *pheap, (old_limit + 1) * sizeof(*heap)); - SET_HEAP_LIMIT(heap, new_limit); - if ( old_limit != 0 ) - xfree(*pheap); - *pheap = heap; - } - - SET_HEAP_SIZE(heap, ++sz); - heap[sz] = t; - t->heap_offset = sz; - up_heap(heap, sz); - return (t->heap_offset == 1); -} - - -/**************************************************************************** - * TIMER OPERATIONS. - */ - -static inline void __add_ac_timer(struct ac_timer *timer) -{ - int cpu = timer->cpu; - if ( add_entry(&ac_timers[cpu].heap, timer) ) - cpu_raise_softirq(cpu, AC_TIMER_SOFTIRQ); -} - - -static inline void __rem_ac_timer(struct ac_timer *timer) -{ - int cpu = timer->cpu; - if ( remove_entry(ac_timers[cpu].heap, timer) ) - cpu_raise_softirq(cpu, AC_TIMER_SOFTIRQ); -} - - -void set_ac_timer(struct ac_timer *timer, s_time_t expires) -{ - int cpu = timer->cpu; - unsigned long flags; - - spin_lock_irqsave(&ac_timers[cpu].lock, flags); - ASSERT(timer != NULL); - if ( active_ac_timer(timer) ) - __rem_ac_timer(timer); - timer->expires = expires; - __add_ac_timer(timer); - spin_unlock_irqrestore(&ac_timers[cpu].lock, flags); -} - - -void rem_ac_timer(struct ac_timer *timer) -{ - int cpu = timer->cpu; - unsigned long flags; - - spin_lock_irqsave(&ac_timers[cpu].lock, flags); - ASSERT(timer != NULL); - if ( active_ac_timer(timer) ) - __rem_ac_timer(timer); - spin_unlock_irqrestore(&ac_timers[cpu].lock, flags); -} - - -static void ac_timer_softirq_action(void) -{ - int cpu = smp_processor_id(); - struct ac_timer *t, **heap; - s_time_t now; - void (*fn)(void *); - - spin_lock_irq(&ac_timers[cpu].lock); - - do { - heap = ac_timers[cpu].heap; - now = NOW(); - - while ( (GET_HEAP_SIZE(heap) != 0) && - ((t = heap[1])->expires < (now + TIMER_SLOP)) ) - { - remove_entry(heap, t); - - if ( (fn = t->function) != NULL ) - { - void *data = t->data; - spin_unlock_irq(&ac_timers[cpu].lock); - (*fn)(data); - spin_lock_irq(&ac_timers[cpu].lock); - } - - /* Heap may have grown while the lock was released. */ - heap = ac_timers[cpu].heap; - } - } - while ( !reprogram_ac_timer(GET_HEAP_SIZE(heap) ? heap[1]->expires : 0) ); - - spin_unlock_irq(&ac_timers[cpu].lock); -} - - -static void dump_timerq(unsigned char key) -{ - struct ac_timer *t; - unsigned long flags; - s_time_t now = NOW(); - int i, j; - - printk("Dumping ac_timer queues: NOW=0x%08X%08X\n", - (u32)(now>>32), (u32)now); - - for_each_online_cpu( i ) - { - printk("CPU[%02d] ", i); - spin_lock_irqsave(&ac_timers[i].lock, flags); - for ( j = 1; j <= GET_HEAP_SIZE(ac_timers[i].heap); j++ ) - { - t = ac_timers[i].heap[j]; - printk (" %d : %p ex=0x%08X%08X %p\n", - j, t, (u32)(t->expires>>32), (u32)t->expires, t->data); - } - spin_unlock_irqrestore(&ac_timers[i].lock, flags); - printk("\n"); - } -} - - -void __init ac_timer_init(void) -{ - static struct ac_timer *dummy_heap; - int i; - - open_softirq(AC_TIMER_SOFTIRQ, ac_timer_softirq_action); - - /* - * All CPUs initially share an empty dummy heap. Only those CPUs that - * are brought online will be dynamically allocated their own heap. - */ - SET_HEAP_SIZE(&dummy_heap, 0); - SET_HEAP_LIMIT(&dummy_heap, 0); - - for ( i = 0; i < NR_CPUS; i++ ) - { - spin_lock_init(&ac_timers[i].lock); - ac_timers[i].heap = &dummy_heap; - } - - register_keyhandler('a', dump_timerq, "dump ac_timer queues"); -} - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff -r 40bb46f599d9 -r a38c292e8390 xen/include/xen/ac_timer.h --- a/xen/include/xen/ac_timer.h Tue Jan 10 15:21:00 2006 +++ /dev/null Tue Jan 24 16:54:34 2006 @@ -1,81 +0,0 @@ -/****************************************************************************** - * ac_timer.h - * - * Copyright (c) 2002-2003 Rolf Neugebauer - * Copyright (c) 2002-2005 K A Fraser - */ - -#ifndef _AC_TIMER_H_ -#define _AC_TIMER_H_ - -#include <xen/spinlock.h> -#include <xen/time.h> -#include <xen/string.h> - -struct ac_timer { - /* System time expiry value (nanoseconds since boot). */ - s_time_t expires; - /* CPU on which this timer will be installed and executed. */ - unsigned int cpu; - /* On expiry, '(*function)(data)' will be executed in softirq context. */ - void (*function)(void *); - void *data; - /* Timer-heap offset. */ - unsigned int heap_offset; -}; - -/* - * All functions below can be called for any CPU from any CPU in any context. - */ - -/* Returns TRUE if the given timer is on a timer list. */ -static __inline__ int active_ac_timer(struct ac_timer *timer) -{ - return (timer->heap_offset != 0); -} - -/* - * It initialises the static fields of the ac_timer structure. - * It can be called multiple times to reinitialise a single (inactive) timer. - */ -static __inline__ void init_ac_timer( - struct ac_timer *timer, - void (*function)(void *), - void *data, - unsigned int cpu) -{ - memset(timer, 0, sizeof(*timer)); - timer->function = function; - timer->data = data; - timer->cpu = cpu; -} - -/* - * Set the expiry time and activate a timer (which must previously have been - * initialised by init_ac_timer). - */ -extern void set_ac_timer(struct ac_timer *timer, s_time_t expires); - -/* - * Deactivate a timer (which must previously have been initialised by - * init_ac_timer). This function has no effect if the timer is not currently - * active. - */ -extern void rem_ac_timer(struct ac_timer *timer); - -/* - * Initialisation. Must be called before any other ac_timer function. - */ -extern void ac_timer_init(void); - -#endif /* _AC_TIMER_H_ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |