From 79bd06c7dd8ac1e7e3cf5de24c77bb6db8ee7761 Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Thu, 5 Jan 2006 10:16:29 -0600 Subject: [PATCH 01/97] Disable virtual memmap to avoid problem on machines with big holes --- linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_ia64 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_ia64 b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_ia64 index 2e1430136d..3b50f2ee73 100644 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_ia64 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_ia64 @@ -91,8 +91,7 @@ CONFIG_IA64_PAGE_SIZE_16KB=y # 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 From 787d665d63ecc1533213cb536fd07cc1115be6c3 Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Fri, 6 Jan 2006 12:39:28 -0600 Subject: [PATCH 02/97] Add 'hvm' capability to indicate whether hardware VTI feature is on. Control panel will query this cap to decide whether legible to create VTI domain on an ia64 box. Signed-off-by Kevin Tian --- xen/arch/ia64/xen/xensetup.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index f21723e342..79d33cdc53 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -21,6 +21,7 @@ #include #include #include +#include unsigned long xenheap_phys_end; @@ -446,9 +447,10 @@ void arch_get_xen_caps(xen_capabilities_info_t info) { 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; From e2fa4bde2c9f52542e704510198c2796c8cab0c4 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Tue, 10 Jan 2006 17:27:16 +0100 Subject: [PATCH 03/97] Cleanups. Signed-off-by: Christian Limpach --- .../arch/xen/i386/kernel/io_apic.c | 2 + .../arch/xen/i386/kernel/traps.c | 10 +- linux-2.6-xen-sparse/arch/xen/i386/mm/init.c | 2 +- .../arch/xen/x86_64/kernel/e820.c | 4 +- .../arch/xen/x86_64/kernel/entry.S | 5 +- .../arch/xen/x86_64/kernel/head64.c | 11 +- .../arch/xen/x86_64/kernel/io_apic.c | 5 +- .../arch/xen/x86_64/kernel/irq.c | 15 +- .../arch/xen/x86_64/kernel/ldt.c | 2 + .../arch/xen/x86_64/kernel/setup.c | 14 +- .../arch/xen/x86_64/kernel/setup64.c | 8 +- .../arch/xen/x86_64/kernel/smp.c | 3 +- .../arch/xen/x86_64/kernel/traps.c | 1 - .../arch/xen/x86_64/mm/fault.c | 2 - .../arch/xen/x86_64/mm/init.c | 165 ++++++++---------- 15 files changed, 115 insertions(+), 134 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/io_apic.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/io_apic.c index 0b786dbfc7..9cc425faea 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/io_apic.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/io_apic.c @@ -622,9 +622,11 @@ static int balanced_irq(void *unused) 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 --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c index 5ad8d1b273..adb0986b4b 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c @@ -648,12 +648,6 @@ fastcall void do_int3(struct pt_regs *regs, long error_code) } #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. * We do not clear them on entry and exit from the kernel. Therefore @@ -686,9 +680,9 @@ fastcall void do_debug(struct pt_regs * regs, long error_code) 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 --git a/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c b/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c index 771ea5ebfd..96797b44a6 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c @@ -65,7 +65,7 @@ static pmd_t * __init one_md_table_init(pgd_t *pgd) { 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 --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c index f2a7160a0e..74596e589d 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/e820.c @@ -526,7 +526,7 @@ extern union xen_start_info_union xen_start_info_union; 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 @@ void __init parse_memopt(char *p, char **from) { 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 --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S index 877a3027ee..c8fa7871d8 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S @@ -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) @@ -418,7 +418,6 @@ ENTRY(stub_rt_sigreturn) jmp int_ret_from_sys_call CFI_ENDPROC - /* * Interrupt entry/exit. * diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head64.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head64.c index 734b9d3082..2a7f4cee42 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head64.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head64.c @@ -68,13 +68,13 @@ static void __init copy_bootdata(char *real_mode_data) 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 @@ void __init x86_64_start_kernel(char * real_mode_data) if (s != NULL) setup_early_printk(s); #endif - #ifdef CONFIG_DISCONTIGMEM s = strstr(saved_command_line, "numa="); if (s != NULL) diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/io_apic.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/io_apic.c index 4cbb1aed8f..33651e64aa 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/io_apic.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/io_apic.c @@ -255,11 +255,9 @@ static int __init enable_ioapic_setup(char *str) return 1; } - __setup("noapic", disable_ioapic_setup); __setup("apic", enable_ioapic_setup); - #include #include #include @@ -1146,6 +1144,7 @@ void __apicdebuginit print_PIC(void) v = inb(0x4d1) << 8 | inb(0x4d0); printk(KERN_DEBUG "... PIC ELCR: %04x\n", v); } + #endif /* 0 */ #else @@ -1191,6 +1190,7 @@ void disable_IO_APIC(void) * Clear the IO-APIC before rebooting: */ clear_IO_APIC(); + #ifndef CONFIG_XEN disconnect_bsp_APIC(); #endif @@ -1202,6 +1202,7 @@ void disable_IO_APIC(void) * * by Matt Domsch Tue Dec 21 12:25:05 CST 1999 */ + #ifndef CONFIG_XEN static void __init setup_ioapic_ids_from_mpc (void) { diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/irq.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/irq.c index 7a8d319d2b..ca26c1234e 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/irq.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/irq.c @@ -9,18 +9,15 @@ * x86_64-specific irq controller code. (e.g. i8259.c and * io_apic.c.) */ -#include -#include -#include -#include -#include -/* - * Interrupt statistics: - */ +#include +#include +#include +#include +#include +#include atomic_t irq_err_count; - #ifdef CONFIG_X86_IO_APIC #ifdef APIC_MISMATCH_DEBUG atomic_t irq_mis_count; diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/ldt.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/ldt.c index 72bde0ec16..fa77040acd 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/ldt.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/ldt.c @@ -62,6 +62,7 @@ static int alloc_ldt(mm_context_t *pc, unsigned mincount, int reload) 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 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode) struct user_desc ldt_info; error = -EINVAL; + if (bytecount != sizeof(ldt_info)) goto out; error = -EFAULT; diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c index 9e1a023282..f82f8aac84 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c @@ -304,7 +304,6 @@ static void __init probe_roms(void) } #endif - static __init void parse_cmdline_early (char ** cmdline_p) { char c = ' ', *to = command_line, *from = COMMAND_LINE; @@ -379,6 +378,7 @@ static __init void parse_cmdline_early (char ** cmdline_p) acpi_skip_timer_override = 1; #endif #endif + #ifndef CONFIG_XEN if (!memcmp(from, "nolapic", 7) || !memcmp(from, "disableapic", 11)) @@ -391,7 +391,8 @@ static __init void parse_cmdline_early (char ** cmdline_p) skip_ioapic_setup = 0; ioapic_force = 1; } -#endif +#endif + if (!memcmp(from, "mem=", 4)) parse_memopt(from+4, &from); @@ -588,7 +589,7 @@ void __init setup_arch(char **cmdline_p) 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 +613,7 @@ void __init setup_arch(char **cmdline_p) 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; @@ -668,7 +669,6 @@ void __init setup_arch(char **cmdline_p) reserve_ebda_region(); #endif - #ifdef CONFIG_SMP /* * But first pinch a few for the stack/trampoline stuff @@ -790,8 +790,6 @@ void __init setup_arch(char **cmdline_p) } - - if ( ! (xen_start_info->flags & SIF_INITDOMAIN)) { acpi_disabled = 1; @@ -835,7 +833,7 @@ void __init setup_arch(char **cmdline_p) * 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 --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c index 56c546fec5..71cf502718 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c @@ -33,6 +33,7 @@ #ifdef CONFIG_XEN #include #endif + char x86_boot_params[BOOT_PARAM_SIZE] __initdata = {0,}; cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE; @@ -165,7 +166,6 @@ void __init cpu_gdt_init(struct desc_ptr *gdt_descr) } #endif - void pda_init(int cpu) { struct x8664_pda *pda = &cpu_pda[cpu]; @@ -175,9 +175,10 @@ void pda_init(int cpu) #ifndef CONFIG_XEN wrmsrl(MSR_GS_BASE, cpu_pda + cpu); #else - HYPERVISOR_set_segment_base(SEGBASE_GS_KERNEL, - (unsigned long)(cpu_pda + cpu)); + 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 @@ void pda_init(int cpu) } switch_pt(); + pda->irqstackptr += IRQSTACKSIZE-64; } diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smp.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smp.c index 0e6ee3c72b..4f565ab325 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smp.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smp.c @@ -30,8 +30,9 @@ #include #ifdef CONFIG_XEN #include +#endif -#else +#ifndef CONFIG_XEN /* * Smarter SMP flushing macros. * c/o Linus Torvalds. diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c index 07a8a35dcc..227042ba63 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c @@ -890,7 +890,6 @@ asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void) 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 --git a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c index 97e6ea1895..4edb3c40c5 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c @@ -153,7 +153,6 @@ void dump_pagetable(unsigned long address) 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 @@ static int vmalloc_fault(unsigned long address) 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 --git a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c index ff58486f33..d682ee1222 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c @@ -40,16 +40,16 @@ #include #include +#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[]; DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -200,9 +200,9 @@ static void *spp_getpage(void) static inline pud_t *pud_offset_u(unsigned long address) { - pud_t *pud = level3_user_pgt; + pud_t *pud = level3_user_pgt; - return pud + pud_index(address); + return pud + pud_index(address); } static void set_pte_phys(unsigned long vaddr, @@ -215,34 +215,27 @@ static void set_pte_phys(unsigned long vaddr, 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 @@ static void set_pte_phys(unsigned long vaddr, 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 @@ static void set_pte_phys_ma(unsigned long 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; @@ -298,8 +290,8 @@ static void set_pte_phys_ma(unsigned long 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)) { @@ -311,12 +303,12 @@ static void set_pte_phys_ma(unsigned long vaddr, 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 @@ void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t prot) } } - /* * At this point it only supports vsyscall area. */ @@ -360,18 +351,18 @@ void __set_fixmap_user (enum fixed_addresses idx, unsigned long phys, pgprot_t p 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 inline int make_readonly(unsigned long paddr) 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 @@ static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned lon } 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 @@ void __init xen_init_pt(void) 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 @@ extern struct x8664_pda cpu_pda[NR_CPUS]; 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 @@ void __init paging_init(void) { { 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 @@ void __init paging_init(void) 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); + 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)); + 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 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size) 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 @@ extern char __initdata_begin[], __initdata_end[]; 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 @@ void free_initmem(void) 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 @@ int kern_addr_valid(unsigned long addr) if (pgd_none(*pgd)) return 0; - pud = pud_offset_k(addr); + pud = pud_offset_k(addr); if (pud_none(*pud)) return 0; From ec5303c071f8087397a0bfa7712d12ea75c833ca Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Tue, 10 Jan 2006 17:16:30 +0000 Subject: [PATCH 04/97] Change xenbus_transaction fake pointer into an opaque type. Signed-off-by: Vincent Hanquez --- linux-2.6-xen-sparse/arch/xen/kernel/reboot.c | 4 +-- .../drivers/xen/blkback/xenbus.c | 2 +- .../drivers/xen/blkfront/blkfront.c | 2 +- .../drivers/xen/netfront/netfront.c | 2 +- .../drivers/xen/tpmback/xenbus.c | 2 +- .../drivers/xen/tpmfront/tpmfront.c | 2 +- .../drivers/xen/xenbus/xenbus_client.c | 2 +- .../drivers/xen/xenbus/xenbus_dev.c | 4 +-- .../drivers/xen/xenbus/xenbus_xs.c | 30 ++++++++--------- linux-2.6-xen-sparse/include/asm-xen/xenbus.h | 25 ++++++++------- tools/python/xen/lowlevel/xs/xs.c | 32 +++++++++---------- tools/xenstore/xenstore_client.c | 6 ++-- tools/xenstore/xs.c | 24 +++++++------- tools/xenstore/xs.h | 19 +++++------ tools/xenstore/xs_test.c | 2 +- 15 files changed, 80 insertions(+), 78 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c index 644a2c1015..7a14d8b6cd 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c @@ -290,7 +290,7 @@ static void shutdown_handler(struct xenbus_watch *watch, const char **vec, unsigned int len) { char *str; - struct xenbus_transaction *xbt; + xenbus_transaction_t xbt; int err; if (shutting_down != SHUTDOWN_INVALID) @@ -339,7 +339,7 @@ static void sysrq_handler(struct xenbus_watch *watch, const char **vec, unsigned int len) { char sysrq_key = '\0'; - struct xenbus_transaction *xbt; + xenbus_transaction_t xbt; int err; again: diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c index 2b2f40f2e6..c5612ce48b 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -302,7 +302,7 @@ static void maybe_connect(struct backend_info *be) */ static void connect(struct backend_info *be) { - struct xenbus_transaction *xbt; + xenbus_transaction_t xbt; int err; struct xenbus_device *dev = be->dev; diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c index 5bf408a9b8..9864ef0a63 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -161,7 +161,7 @@ static int talk_to_backend(struct xenbus_device *dev, struct blkfront_info *info) { const char *message = NULL; - struct xenbus_transaction *xbt; + xenbus_transaction_t xbt; int err; /* Create shared ring, alloc event channel. */ diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index 5c3e563358..86798341f4 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -260,7 +260,7 @@ static int talk_to_backend(struct xenbus_device *dev, 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); diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c index b5039adadc..f93d1c219b 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c @@ -230,7 +230,7 @@ static void maybe_connect(struct backend_info *be) 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; diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c index 72b1971421..488a17bd69 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c @@ -271,7 +271,7 @@ static int talk_to_backend(struct xenbus_device *dev, { const char *message = NULL; int err; - struct xenbus_transaction *xbt; + xenbus_transaction_t xbt; err = setup_tpmring(dev, info); if (err) { diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c index 385419e134..303eab86c4 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c @@ -87,7 +87,7 @@ EXPORT_SYMBOL(xenbus_watch_path2); 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 --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c index b7a7d892f5..4cfd57c34f 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c @@ -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,7 +147,7 @@ static ssize_t xenbus_dev_write(struct file *filp, } if (u->u.msg.type == XS_TRANSACTION_START) { - trans->handle = (struct xenbus_transaction *) + trans->handle = (xenbus_transaction_t) simple_strtoul(reply, NULL, 0); list_add(&trans->list, &u->transactions); } else if (u->u.msg.type == XS_TRANSACTION_END) { diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c index b6435d7040..98498dcf97 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c @@ -190,7 +190,7 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) } /* 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, @@ -242,7 +242,7 @@ static void *xs_talkv(struct xenbus_transaction *t, } /* 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 @@ static char **split(char *strings, unsigned int len, unsigned int *num) 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 @@ char **xenbus_directory(struct xenbus_transaction *t, 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 @@ EXPORT_SYMBOL(xenbus_exists); * 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 @@ EXPORT_SYMBOL(xenbus_read); /* 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 @@ int xenbus_write(struct xenbus_transaction *t, 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 @@ int xenbus_mkdir(struct xenbus_transaction *t, 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,7 +424,7 @@ EXPORT_SYMBOL(xenbus_rm); /* 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) +xenbus_transaction_t xenbus_transaction_start(void) { char *id_str; unsigned long id; @@ -434,20 +434,20 @@ struct xenbus_transaction *xenbus_transaction_start(void) 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; + return (xenbus_transaction_t )id_str; } id = simple_strtoul(id_str, NULL, 0); kfree(id_str); - return (struct xenbus_transaction *)id; + return (xenbus_transaction_t) id; } 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 +466,7 @@ int xenbus_transaction_end(struct xenbus_transaction *t, int abort) 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 +489,7 @@ int xenbus_scanf(struct xenbus_transaction *t, 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 +515,7 @@ int xenbus_printf(struct xenbus_transaction *t, 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 --git a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h index c7e3ac7834..b6339dbc75 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h +++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h @@ -103,34 +103,35 @@ int xenbus_register_backend(struct xenbus_driver *drv); void xenbus_unregister_driver(struct xenbus_driver *drv); struct xenbus_transaction; +typedef struct xenbus_transaction *xenbus_transaction_t; -char **xenbus_directory(struct 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); +xenbus_transaction_t xenbus_transaction_start(void); +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 +197,7 @@ int xenbus_watch_path2(struct xenbus_device *dev, const char *path, * 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 --git a/tools/python/xen/lowlevel/xs/xs.c b/tools/python/xen/lowlevel/xs/xs.c index e473a4902b..35c3c0cf6a 100644 --- a/tools/python/xen/lowlevel/xs/xs.c +++ b/tools/python/xen/lowlevel/xs/xs.c @@ -66,7 +66,7 @@ static PyObject *none(bool result); static int parse_transaction_path(XsHandle *self, PyObject *args, struct xs_handle **xh, - struct xs_transaction_handle **th, + xs_transaction_handle *th, char **path); @@ -83,7 +83,7 @@ static int parse_transaction_path(XsHandle *self, PyObject *args, static PyObject *xspy_read(XsHandle *self, PyObject *args) { struct xs_handle *xh; - struct xs_transaction_handle *th; + xs_transaction_handle th; char *path; char *xsval; @@ -120,7 +120,7 @@ static PyObject *xspy_write(XsHandle *self, PyObject *args) { static char *arg_spec = "sss#"; struct xs_handle *xh = xshandle(self); - struct xs_transaction_handle *th; + xs_transaction_handle th; char *thstr; char *path; char *data; @@ -132,7 +132,7 @@ static PyObject *xspy_write(XsHandle *self, PyObject *args) if (!PyArg_ParseTuple(args, arg_spec, &thstr, &path, &data, &data_n)) return NULL; - th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + th = (xs_transaction_handle)strtoul(thstr, NULL, 16); Py_BEGIN_ALLOW_THREADS result = xs_write(xh, th, path, data, data_n); @@ -155,7 +155,7 @@ static PyObject *xspy_write(XsHandle *self, PyObject *args) static PyObject *xspy_ls(XsHandle *self, PyObject *args) { struct xs_handle *xh; - struct xs_transaction_handle *th; + xs_transaction_handle th; char *path; char **xsval; @@ -193,7 +193,7 @@ static PyObject *xspy_ls(XsHandle *self, PyObject *args) static PyObject *xspy_mkdir(XsHandle *self, PyObject *args) { struct xs_handle *xh; - struct xs_transaction_handle *th; + xs_transaction_handle th; char *path; bool result; @@ -221,7 +221,7 @@ static PyObject *xspy_mkdir(XsHandle *self, PyObject *args) static PyObject *xspy_rm(XsHandle *self, PyObject *args) { struct xs_handle *xh; - struct xs_transaction_handle *th; + xs_transaction_handle th; char *path; bool result; @@ -256,7 +256,7 @@ static PyObject *xspy_get_permissions(XsHandle *self, PyObject *args) unsigned int perms_n = 0; int i; - struct xs_transaction_handle *th; + xs_transaction_handle th; char *thstr; if (!xh) @@ -264,7 +264,7 @@ static PyObject *xspy_get_permissions(XsHandle *self, PyObject *args) if (!PyArg_ParseTuple(args, arg_spec, &thstr, &path)) return NULL; - th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + th = (xs_transaction_handle)strtoul(thstr, NULL, 16); Py_BEGIN_ALLOW_THREADS perms = xs_get_permissions(xh, th, path, &perms_n); @@ -312,7 +312,7 @@ static PyObject *xspy_set_permissions(XsHandle *self, PyObject *args) int xsperms_n; PyObject *tuple0 = NULL; - struct xs_transaction_handle *th; + xs_transaction_handle th; char *thstr; if (!xh) @@ -320,7 +320,7 @@ static PyObject *xspy_set_permissions(XsHandle *self, PyObject *args) if (!PyArg_ParseTuple(args, "ssO", &thstr, &path, &perms)) goto exit; - th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + th = (xs_transaction_handle)strtoul(thstr, NULL, 16); if (!PyList_Check(perms)) { PyErr_SetString(PyExc_RuntimeError, "perms must be a list"); @@ -509,7 +509,7 @@ static PyObject *xspy_unwatch(XsHandle *self, PyObject *args) static PyObject *xspy_transaction_start(XsHandle *self) { struct xs_handle *xh = xshandle(self); - struct xs_transaction_handle *th; + xs_transaction_handle th; char thstr[MAX_STRLEN(unsigned long) + 1]; if (!xh) @@ -547,7 +547,7 @@ static PyObject *xspy_transaction_end(XsHandle *self, PyObject *args, struct xs_handle *xh = xshandle(self); bool result; - struct xs_transaction_handle *th; + xs_transaction_handle th; char *thstr; if (!xh) @@ -556,7 +556,7 @@ static PyObject *xspy_transaction_end(XsHandle *self, PyObject *args, &thstr, &abort)) return NULL; - th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + th = (xs_transaction_handle)strtoul(thstr, NULL, 16); Py_BEGIN_ALLOW_THREADS result = xs_transaction_end(xh, th, abort); @@ -727,7 +727,7 @@ static void remove_watch(XsHandle *self, PyObject *token) */ static int parse_transaction_path(XsHandle *self, PyObject *args, struct xs_handle **xh, - struct xs_transaction_handle **th, + xs_transaction_handle *th, char **path) { char *thstr; @@ -740,7 +740,7 @@ static int parse_transaction_path(XsHandle *self, PyObject *args, if (!PyArg_ParseTuple(args, "ss", &thstr, path)) return 0; - *th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + *th = (xs_transaction_handle)strtoul(thstr, NULL, 16); return 1; } diff --git a/tools/xenstore/xenstore_client.c b/tools/xenstore/xenstore_client.c index f8e1f5c893..5090499af3 100644 --- a/tools/xenstore/xenstore_client.c +++ b/tools/xenstore/xenstore_client.c @@ -66,7 +66,7 @@ usage(const char *progname) #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_handle xth) { if (xs_rm(xsh, xth, path)) { return 0; @@ -81,7 +81,7 @@ do_rm(char *path, struct xs_handle *xsh, struct xs_transaction_handle *xth) static int perform(int optind, int argc, char **argv, struct xs_handle *xsh, - struct xs_transaction_handle *xth, int prefix, int tidy) + xs_transaction_handle xth, int prefix, int tidy) { while (optind < argc) { #if defined(CLIENT_read) @@ -179,7 +179,7 @@ int main(int argc, char **argv) { struct xs_handle *xsh; - struct xs_transaction_handle *xth; + xs_transaction_handle xth; int ret = 0, socket = 0; int prefix = 0; int tidy = 0; diff --git a/tools/xenstore/xs.c b/tools/xenstore/xs.c index b8d9e23e7c..3ecb462ea3 100644 --- a/tools/xenstore/xs.c +++ b/tools/xenstore/xs.c @@ -292,7 +292,7 @@ static void *read_reply( } /* 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_handle t, enum xsd_sockmsg_type type, const struct iovec *iovec, unsigned int num_vecs, @@ -368,7 +368,7 @@ static void free_no_errno(void *p) } /* 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_handle t, enum xsd_sockmsg_type type, const char *string, unsigned int *len) @@ -388,7 +388,7 @@ static bool xs_bool(char *reply) return true; } -char **xs_directory(struct xs_handle *h, struct xs_transaction_handle *t, +char **xs_directory(struct xs_handle *h, xs_transaction_handle t, const char *path, unsigned int *num) { char *strings, *p, **ret; @@ -420,7 +420,7 @@ char **xs_directory(struct xs_handle *h, struct xs_transaction_handle *t, * 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_handle t, const char *path, unsigned int *len) { return xs_single(h, t, XS_READ, path, len); @@ -429,7 +429,7 @@ void *xs_read(struct xs_handle *h, struct xs_transaction_handle *t, /* 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_handle t, const char *path, const void *data, unsigned int len) { struct iovec iovec[2]; @@ -446,7 +446,7 @@ bool xs_write(struct xs_handle *h, struct xs_transaction_handle *t, /* 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_handle t, const char *path) { return xs_bool(xs_single(h, t, XS_MKDIR, path, NULL)); @@ -455,7 +455,7 @@ bool xs_mkdir(struct xs_handle *h, struct xs_transaction_handle *t, /* 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_handle t, const char *path) { return xs_bool(xs_single(h, t, XS_RM, path, NULL)); @@ -465,7 +465,7 @@ bool xs_rm(struct xs_handle *h, struct xs_transaction_handle *t, * 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_handle t, const char *path, unsigned int *num) { char *strings; @@ -499,7 +499,7 @@ struct xs_permissions *xs_get_permissions(struct xs_handle *h, * Returns false on failure. */ bool xs_set_permissions(struct xs_handle *h, - struct xs_transaction_handle *t, + xs_transaction_handle t, const char *path, struct xs_permissions *perms, unsigned int num_perms) @@ -636,7 +636,7 @@ bool xs_unwatch(struct xs_handle *h, const char *path, const char *token) * 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_handle xs_transaction_start(struct xs_handle *h) { char *id_str; unsigned long id; @@ -648,7 +648,7 @@ struct xs_transaction_handle *xs_transaction_start(struct xs_handle *h) id = strtoul(id_str, NULL, 0); free(id_str); - return (struct xs_transaction_handle *)id; + return (xs_transaction_handle)id; } /* End a transaction. @@ -656,7 +656,7 @@ struct xs_transaction_handle *xs_transaction_start(struct xs_handle *h) * 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_handle t, bool abort) { char abortstr[2]; diff --git a/tools/xenstore/xs.h b/tools/xenstore/xs.h index 0d0a8c8dd9..173c4bc564 100644 --- a/tools/xenstore/xs.h +++ b/tools/xenstore/xs.h @@ -26,6 +26,7 @@ struct xs_handle; struct xs_transaction_handle; +typedef struct xs_transaction_handle * xs_transaction_handle; /* On failure, these routines set errno. */ @@ -47,45 +48,45 @@ void xs_daemon_close(struct xs_handle *); * 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_handle 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_handle 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_handle 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_handle 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_handle 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_handle 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_handle t, const char *path, struct xs_permissions *perms, unsigned int num_perms); @@ -115,14 +116,14 @@ bool xs_unwatch(struct xs_handle *h, const char *path, const char *token); * 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_handle 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_handle t, bool abort); /* Introduce a new domain. diff --git a/tools/xenstore/xs_test.c b/tools/xenstore/xs_test.c index 09e04a8c62..03674bd26e 100644 --- a/tools/xenstore/xs_test.c +++ b/tools/xenstore/xs_test.c @@ -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_handle txh[10] = { XBT_NULL }; static unsigned int timeout_ms = 500; static bool timeout_suppressed = true; From af58611df658bf42f7d9bb2ff8373dfba3a778ee Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 10 Jan 2006 18:25:45 +0100 Subject: [PATCH 05/97] Add new map_domain_page_global() interface to allow mappings that are accessible in all contexts and address spaces. Used by shadow code and vmx code. Signed-off-by: Keir Fraser --- xen/arch/x86/shadow.c | 12 +++--- xen/arch/x86/shadow32.c | 22 +++++----- xen/arch/x86/shadow_public.c | 17 ++++---- xen/arch/x86/vmx.c | 3 +- xen/arch/x86/vmx_vmcs.c | 2 +- xen/arch/x86/x86_32/domain_page.c | 68 +++++++++++++++++++++++++++++++ xen/include/xen/domain_page.h | 19 +++++++-- 7 files changed, 114 insertions(+), 29 deletions(-) diff --git a/xen/arch/x86/shadow.c b/xen/arch/x86/shadow.c index 0915873283..e6c59eb58d 100644 --- a/xen/arch/x86/shadow.c +++ b/xen/arch/x86/shadow.c @@ -2150,8 +2150,8 @@ static void shadow_update_pagetables(struct vcpu *v) 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); } /* @@ -2187,8 +2187,8 @@ static void shadow_update_pagetables(struct vcpu *v) ) { 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 +2204,8 @@ static void shadow_update_pagetables(struct vcpu *v) 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); } /* diff --git a/xen/arch/x86/shadow32.c b/xen/arch/x86/shadow32.c index a8d7abbf11..b70db99eb4 100644 --- a/xen/arch/x86/shadow32.c +++ b/xen/arch/x86/shadow32.c @@ -733,7 +733,7 @@ static void alloc_monitor_pagetable(struct vcpu *v) 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], @@ -794,7 +794,7 @@ void free_monitor_pagetable(struct vcpu *v) * 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 +929,7 @@ int __shadow_mode_enable(struct domain *d, unsigned int mode) 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 +942,7 @@ int __shadow_mode_enable(struct domain *d, unsigned int mode) 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 +955,7 @@ int __shadow_mode_enable(struct domain *d, unsigned int mode) 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; @@ -2906,8 +2906,8 @@ void __update_pagetables(struct vcpu *v) 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); } /* @@ -2932,8 +2932,8 @@ void __update_pagetables(struct vcpu *v) 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 +2948,8 @@ void __update_pagetables(struct vcpu *v) 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); } /* diff --git a/xen/arch/x86/shadow_public.c b/xen/arch/x86/shadow_public.c index 931a31f83f..55d0196e47 100644 --- a/xen/arch/x86/shadow_public.c +++ b/xen/arch/x86/shadow_public.c @@ -151,6 +151,8 @@ free_shadow_fl1_table(struct domain *d, unsigned long smfn) for (i = 0; i < L1_PAGETABLE_ENTRIES; i++) put_page_from_l1e(pl1e[i], d); + + unmap_domain_page(pl1e); } /* @@ -254,6 +256,7 @@ static pagetable_t page_table_convert(struct domain *d) 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 @@ static void alloc_monitor_pagetable(struct vcpu *v) 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 @@ void free_monitor_pagetable(struct vcpu *v) * 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); @@ -332,7 +335,7 @@ static void alloc_monitor_pagetable(struct vcpu *v) 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], @@ -393,7 +396,7 @@ void free_monitor_pagetable(struct vcpu *v) * 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 +980,7 @@ int __shadow_mode_enable(struct domain *d, unsigned int mode) 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 +993,7 @@ int __shadow_mode_enable(struct domain *d, unsigned int mode) 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 +1007,7 @@ int __shadow_mode_enable(struct domain *d, unsigned int mode) 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 --git a/xen/arch/x86/vmx.c b/xen/arch/x86/vmx.c index e6dfd5f13e..2dd4925947 100644 --- a/xen/arch/x86/vmx.c +++ b/xen/arch/x86/vmx.c @@ -98,7 +98,8 @@ void vmx_relinquish_resources(struct vcpu *v) /* 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); diff --git a/xen/arch/x86/vmx_vmcs.c b/xen/arch/x86/vmx_vmcs.c index 80ec8f201f..f10124f99d 100644 --- a/xen/arch/x86/vmx_vmcs.c +++ b/xen/arch/x86/vmx_vmcs.c @@ -193,7 +193,7 @@ static void vmx_map_io_shared_page(struct domain *d) 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(); diff --git a/xen/arch/x86/x86_32/domain_page.c b/xen/arch/x86/x86_32/domain_page.c index 38d822a0f5..8b28103cf8 100644 --- a/xen/arch/x86/x86_32/domain_page.c +++ b/xen/arch/x86/x86_32/domain_page.c @@ -101,3 +101,71 @@ void unmap_domain_pages(void *va, unsigned int order) for ( i = 0; i < (1U << order); i++ ) l1e_add_flags(cache->l1tab[idx+i], READY_FOR_TLB_FLUSH); } + +#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); + + for ( ; ; ) + { + idx = find_next_zero_bit(inuse, GLOBALMAP_BITS, inuse_cursor); + va = IOREMAP_VIRT_START + (idx << PAGE_SHIFT); + + /* End of round? If not then we're done in this loop. */ + if ( va < FIXADDR_START ) + break; + + /* /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(); + + inuse_cursor = 0; + } + + 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 --git a/xen/include/xen/domain_page.h b/xen/include/xen/domain_page.h index ce152aece2..8e0a524a42 100644 --- a/xen/include/xen/domain_page.h +++ b/xen/include/xen/domain_page.h @@ -17,16 +17,26 @@ /* * 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(). + * pages are now accessible within the current domain until a corresponding + * call to unmap_domain_page(). */ extern void *map_domain_pages(unsigned long pfn, unsigned int order); /* - * 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 the first page of a range previously mapped in the context + * of the currently-executing domain via a call to map_domain_pages(). Those + * pages will then be removed from the mapping lists. */ extern void unmap_domain_pages(void *va, unsigned int order); +/* + * Similar to the above calls, except the mapping is accessible in all + * address spaces (not just within the domain 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 @@ -90,6 +100,9 @@ domain_mmap_cache_destroy(struct domain_mmap_cache *cache) #define map_domain_pages(pfn,order) phys_to_virt((pfn)< Date: Tue, 10 Jan 2006 18:53:44 +0100 Subject: [PATCH 06/97] Update map_domain_page() documentation (mappings may only be be used within the mapping vcpu). Implement TLB flush filtering on the per-domain mapcache. Signed-off-by: Keir Fraser --- xen/arch/x86/x86_32/domain_page.c | 19 ++++++++++++++----- xen/include/asm-x86/domain.h | 1 + xen/include/xen/domain_page.h | 6 +++--- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/xen/arch/x86/x86_32/domain_page.c b/xen/arch/x86/x86_32/domain_page.c index 8b28103cf8..b8ca0ab47d 100644 --- a/xen/arch/x86/x86_32/domain_page.c +++ b/xen/arch/x86/x86_32/domain_page.c @@ -40,7 +40,8 @@ void *map_domain_pages(unsigned long pfn, unsigned int order) { unsigned long va; unsigned int idx, i, flags, vcpu = current->vcpu_id; - struct mapcache *cache = ¤t->domain->arch.mapcache; + struct domain *d; + struct mapcache *cache; #ifndef NDEBUG unsigned int flush_count = 0; #endif @@ -49,17 +50,24 @@ void *map_domain_pages(unsigned long pfn, unsigned int order) 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; + 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]) ) { - perfc_incrc(domain_page_tlb_flush); - local_flush_tlb(); 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(); + } } do { @@ -71,6 +79,7 @@ void *map_domain_pages(unsigned long pfn, unsigned int order) perfc_incrc(domain_page_tlb_flush); local_flush_tlb(); cache->shadow_epoch[vcpu] = ++cache->epoch; + cache->tlbflush_timestamp = tlbflush_current_time(); } flags = 0; diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 0a29f61b1c..b9955c0249 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -17,6 +17,7 @@ struct mapcache { l1_pgentry_t *l1tab; unsigned int cursor; unsigned int epoch, shadow_epoch[MAX_VIRT_CPUS]; + u32 tlbflush_timestamp; spinlock_t lock; }; diff --git a/xen/include/xen/domain_page.h b/xen/include/xen/domain_page.h index 8e0a524a42..8fbd9ffaa7 100644 --- a/xen/include/xen/domain_page.h +++ b/xen/include/xen/domain_page.h @@ -17,21 +17,21 @@ /* * Maps a given range of page frames, returning the mapped virtual address. The - * pages are now accessible within the current domain until a corresponding + * pages are now accessible within the current VCPU until a corresponding * call to unmap_domain_page(). */ extern void *map_domain_pages(unsigned long pfn, unsigned int order); /* * Pass a VA within the first page of a range previously mapped in the context - * of the currently-executing domain via a call to map_domain_pages(). Those + * of the currently-executing VCPU via a call to map_domain_pages(). Those * pages will then be removed from the mapping lists. */ extern void unmap_domain_pages(void *va, unsigned int order); /* * Similar to the above calls, except the mapping is accessible in all - * address spaces (not just within the domain that created the mapping). Global + * 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); From 824e2dc2440e97ef3e807e8ee6d4c1d678dfdd58 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 11 Jan 2006 11:09:17 +0100 Subject: [PATCH 07/97] Fixed ia64 compilation issues and also change xen/ia64 to use one single, multi-cpu, idle domain created dynamically correspondingly. Only difference is vcpu0 of idle domain is still built at compilation phase, due to some code copied from Linux requiring that. Signed-off-by Kevin Tian --- xen/arch/ia64/linux-xen/smpboot.c | 5 +-- xen/arch/ia64/xen/domain.c | 62 +++++++++++++++++-------------- xen/arch/ia64/xen/idle0_task.c | 30 +++------------ xen/arch/ia64/xen/xensetup.c | 31 ++++++---------- xen/include/asm-ia64/config.h | 4 -- xen/include/public/arch-ia64.h | 2 +- 6 files changed, 54 insertions(+), 80 deletions(-) diff --git a/xen/arch/ia64/linux-xen/smpboot.c b/xen/arch/ia64/linux-xen/smpboot.c index 705e0cefa6..c6970ffad9 100644 --- a/xen/arch/ia64/linux-xen/smpboot.c +++ b/xen/arch/ia64/linux-xen/smpboot.c @@ -482,9 +482,8 @@ do_rest: 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 --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 305eb50f0e..99b1646614 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -87,7 +87,6 @@ static void continue_cpu_idle_loop(void) int cpu = smp_processor_id(); for ( ; ; ) { - printf ("idle%dD\n", cpu); #ifdef IA64 // __IRQ_STAT(cpu, idle_timestamp) = jiffies #else @@ -146,15 +145,26 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) { struct vcpu *v; + /* 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) + return idle_vcpu[0]; + 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 = + memcpy(&v->arch, &idle_vcpu[0]->arch, sizeof(v->arch)); + + if (!is_idle_domain(d)) { + v->arch.privregs = alloc_xenheap_pages(get_order(sizeof(mapped_regs_t))); + BUG_ON(v->arch.privregs == NULL); + memset(v->arch.privregs, 0, PAGE_SIZE); + } + printf("arch_vcpu_info=%p\n", v->arch.privregs); - memset(v->arch.privregs, 0, PAGE_SIZE); return v; } @@ -191,6 +201,14 @@ int arch_do_createdomain(struct vcpu *v) memset(ti, 0, sizeof(struct thread_info)); init_switch_stack(v); + // 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_vcpu(v)) + return 0; + d->shared_info = (void *)alloc_xenheap_page(); if (!d->shared_info) { printk("ERROR/HALTING: CAN'T ALLOC PAGE\n"); @@ -200,12 +218,7 @@ int arch_do_createdomain(struct vcpu *v) 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 @@ -227,28 +240,21 @@ int arch_do_createdomain(struct vcpu *v) 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; + 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; + } printf ("arch_do_create_domain: domain=%p\n", d); return 0; diff --git a/xen/arch/ia64/xen/idle0_task.c b/xen/arch/ia64/xen/idle0_task.c index 789424a69c..bc7aeed28a 100644 --- a/xen/arch/ia64/xen/idle0_task.c +++ b/xen/arch/ia64/xen/idle0_task.c @@ -11,30 +11,15 @@ .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 @@ struct vcpu idle0_vcpu = IDLE0_EXEC_DOMAIN(idle0_vcpu, */ 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 --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index aecd96e36b..7f40a3d792 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -26,7 +26,7 @@ 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,16 +156,12 @@ void start_kernel(void) 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); /* We initialise the serial devices very early so we can get debugging. */ @@ -281,12 +277,16 @@ void start_kernel(void) (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 = do_createdomain(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"); @@ -308,14 +308,10 @@ printk("About to call ac_timer_init()\n"); } 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(); @@ -344,12 +340,7 @@ printk("About to call sort_main_extable()\n"); /* 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); + #ifdef CLONE_DOMAIN0 { int i; @@ -431,8 +422,8 @@ printk("About to call init_trace_bufs()\n"); 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); diff --git a/xen/include/asm-ia64/config.h b/xen/include/asm-ia64/config.h index 4d730b4b1a..f0fac09eb1 100644 --- a/xen/include/asm-ia64/config.h +++ b/xen/include/asm-ia64/config.h @@ -141,10 +141,6 @@ struct page; #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 diff --git a/xen/include/public/arch-ia64.h b/xen/include/public/arch-ia64.h index 7eaf856174..a1013e3112 100644 --- a/xen/include/public/arch-ia64.h +++ b/xen/include/public/arch-ia64.h @@ -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__ From f2a491843da3d9918eabf0efa5377782c1a0aa68 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 11 Jan 2006 11:34:05 +0100 Subject: [PATCH 08/97] Fix 32-bit shadow mode to handle extended perdomain mapping area now that mapcache is per domain. Signed-off-by: Keir Fraser --- xen/arch/x86/shadow.c | 9 ++++++--- xen/arch/x86/shadow32.c | 17 +++++++++++------ xen/arch/x86/shadow_public.c | 8 +++++--- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/xen/arch/x86/shadow.c b/xen/arch/x86/shadow.c index e6c59eb58d..b2fd143452 100644 --- a/xen/arch/x86/shadow.c +++ b/xen/arch/x86/shadow.c @@ -469,6 +469,7 @@ static unsigned long shadow_l2_table( { unsigned long smfn; l2_pgentry_t *spl2e; + int i; SH_VVLOG("shadow_l2_table(gpfn=%lx, gmfn=%lx)", gpfn, gmfn); @@ -503,9 +504,11 @@ static unsigned long shadow_l2_table( 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 { diff --git a/xen/arch/x86/shadow32.c b/xen/arch/x86/shadow32.c index b70db99eb4..eb09ea92c5 100644 --- a/xen/arch/x86/shadow32.c +++ b/xen/arch/x86/shadow32.c @@ -726,6 +726,7 @@ static void alloc_monitor_pagetable(struct vcpu *v) 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); @@ -740,9 +741,10 @@ static void alloc_monitor_pagetable(struct vcpu *v) &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)] = @@ -1508,6 +1510,7 @@ static unsigned long shadow_l2_table( { unsigned long smfn; l2_pgentry_t *spl2e; + int i; SH_VVLOG("shadow_l2_table(gpfn=%lx, gmfn=%lx)", gpfn, gmfn); @@ -1542,9 +1545,11 @@ static unsigned long shadow_l2_table( 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 { diff --git a/xen/arch/x86/shadow_public.c b/xen/arch/x86/shadow_public.c index 55d0196e47..bb376bb737 100644 --- a/xen/arch/x86/shadow_public.c +++ b/xen/arch/x86/shadow_public.c @@ -328,6 +328,7 @@ static void alloc_monitor_pagetable(struct vcpu *v) 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); @@ -342,9 +343,10 @@ static void alloc_monitor_pagetable(struct vcpu *v) &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)] = From 53ed6896f34e46734d1e2d681cb234440b41a94a Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Wed, 11 Jan 2006 11:46:32 +0000 Subject: [PATCH 09/97] Share the same name for xenbus transaction type between user and kernel Signed-off-by: Vincent Hanquez --- tools/python/xen/lowlevel/xs/xs.c | 32 +++++++++++++++---------------- tools/xenstore/xenstore_client.c | 6 +++--- tools/xenstore/xs.c | 24 +++++++++++------------ tools/xenstore/xs.h | 22 ++++++++++----------- tools/xenstore/xs_test.c | 2 +- 5 files changed, 43 insertions(+), 43 deletions(-) diff --git a/tools/python/xen/lowlevel/xs/xs.c b/tools/python/xen/lowlevel/xs/xs.c index 35c3c0cf6a..5f6d1850f4 100644 --- a/tools/python/xen/lowlevel/xs/xs.c +++ b/tools/python/xen/lowlevel/xs/xs.c @@ -66,7 +66,7 @@ static PyObject *none(bool result); static int parse_transaction_path(XsHandle *self, PyObject *args, struct xs_handle **xh, - xs_transaction_handle *th, + xs_transaction_t *th, char **path); @@ -83,7 +83,7 @@ static int parse_transaction_path(XsHandle *self, PyObject *args, static PyObject *xspy_read(XsHandle *self, PyObject *args) { struct xs_handle *xh; - xs_transaction_handle th; + xs_transaction_t th; char *path; char *xsval; @@ -120,7 +120,7 @@ static PyObject *xspy_write(XsHandle *self, PyObject *args) { static char *arg_spec = "sss#"; struct xs_handle *xh = xshandle(self); - xs_transaction_handle th; + xs_transaction_t th; char *thstr; char *path; char *data; @@ -132,7 +132,7 @@ static PyObject *xspy_write(XsHandle *self, PyObject *args) if (!PyArg_ParseTuple(args, arg_spec, &thstr, &path, &data, &data_n)) return NULL; - th = (xs_transaction_handle)strtoul(thstr, NULL, 16); + th = (xs_transaction_t)strtoul(thstr, NULL, 16); Py_BEGIN_ALLOW_THREADS result = xs_write(xh, th, path, data, data_n); @@ -155,7 +155,7 @@ static PyObject *xspy_write(XsHandle *self, PyObject *args) static PyObject *xspy_ls(XsHandle *self, PyObject *args) { struct xs_handle *xh; - xs_transaction_handle th; + xs_transaction_t th; char *path; char **xsval; @@ -193,7 +193,7 @@ static PyObject *xspy_ls(XsHandle *self, PyObject *args) static PyObject *xspy_mkdir(XsHandle *self, PyObject *args) { struct xs_handle *xh; - xs_transaction_handle th; + xs_transaction_t th; char *path; bool result; @@ -221,7 +221,7 @@ static PyObject *xspy_mkdir(XsHandle *self, PyObject *args) static PyObject *xspy_rm(XsHandle *self, PyObject *args) { struct xs_handle *xh; - xs_transaction_handle th; + xs_transaction_t th; char *path; bool result; @@ -256,7 +256,7 @@ static PyObject *xspy_get_permissions(XsHandle *self, PyObject *args) unsigned int perms_n = 0; int i; - xs_transaction_handle th; + xs_transaction_t th; char *thstr; if (!xh) @@ -264,7 +264,7 @@ static PyObject *xspy_get_permissions(XsHandle *self, PyObject *args) if (!PyArg_ParseTuple(args, arg_spec, &thstr, &path)) return NULL; - th = (xs_transaction_handle)strtoul(thstr, NULL, 16); + th = (xs_transaction_t)strtoul(thstr, NULL, 16); Py_BEGIN_ALLOW_THREADS perms = xs_get_permissions(xh, th, path, &perms_n); @@ -312,7 +312,7 @@ static PyObject *xspy_set_permissions(XsHandle *self, PyObject *args) int xsperms_n; PyObject *tuple0 = NULL; - xs_transaction_handle th; + xs_transaction_t th; char *thstr; if (!xh) @@ -320,7 +320,7 @@ static PyObject *xspy_set_permissions(XsHandle *self, PyObject *args) if (!PyArg_ParseTuple(args, "ssO", &thstr, &path, &perms)) goto exit; - th = (xs_transaction_handle)strtoul(thstr, NULL, 16); + th = (xs_transaction_t)strtoul(thstr, NULL, 16); if (!PyList_Check(perms)) { PyErr_SetString(PyExc_RuntimeError, "perms must be a list"); @@ -509,7 +509,7 @@ static PyObject *xspy_unwatch(XsHandle *self, PyObject *args) static PyObject *xspy_transaction_start(XsHandle *self) { struct xs_handle *xh = xshandle(self); - xs_transaction_handle th; + xs_transaction_t th; char thstr[MAX_STRLEN(unsigned long) + 1]; if (!xh) @@ -547,7 +547,7 @@ static PyObject *xspy_transaction_end(XsHandle *self, PyObject *args, struct xs_handle *xh = xshandle(self); bool result; - xs_transaction_handle th; + xs_transaction_t th; char *thstr; if (!xh) @@ -556,7 +556,7 @@ static PyObject *xspy_transaction_end(XsHandle *self, PyObject *args, &thstr, &abort)) return NULL; - th = (xs_transaction_handle)strtoul(thstr, NULL, 16); + th = (xs_transaction_t)strtoul(thstr, NULL, 16); Py_BEGIN_ALLOW_THREADS result = xs_transaction_end(xh, th, abort); @@ -727,7 +727,7 @@ static void remove_watch(XsHandle *self, PyObject *token) */ static int parse_transaction_path(XsHandle *self, PyObject *args, struct xs_handle **xh, - xs_transaction_handle *th, + xs_transaction_t *th, char **path) { char *thstr; @@ -740,7 +740,7 @@ static int parse_transaction_path(XsHandle *self, PyObject *args, if (!PyArg_ParseTuple(args, "ss", &thstr, path)) return 0; - *th = (xs_transaction_handle)strtoul(thstr, NULL, 16); + *th = (xs_transaction_t)strtoul(thstr, NULL, 16); return 1; } diff --git a/tools/xenstore/xenstore_client.c b/tools/xenstore/xenstore_client.c index 5090499af3..deb63453d3 100644 --- a/tools/xenstore/xenstore_client.c +++ b/tools/xenstore/xenstore_client.c @@ -66,7 +66,7 @@ usage(const char *progname) #if defined(CLIENT_rm) static int -do_rm(char *path, struct xs_handle *xsh, 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 @@ do_rm(char *path, struct xs_handle *xsh, xs_transaction_handle xth) static int perform(int optind, int argc, char **argv, struct xs_handle *xsh, - 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 @@ int main(int argc, char **argv) { struct xs_handle *xsh; - xs_transaction_handle xth; + xs_transaction_t xth; int ret = 0, socket = 0; int prefix = 0; int tidy = 0; diff --git a/tools/xenstore/xs.c b/tools/xenstore/xs.c index 3ecb462ea3..8332e1aad5 100644 --- a/tools/xenstore/xs.c +++ b/tools/xenstore/xs.c @@ -292,7 +292,7 @@ static void *read_reply( } /* Send message to xs, get malloc'ed reply. NULL and set errno on error. */ -static void *xs_talkv(struct xs_handle *h, 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, @@ -368,7 +368,7 @@ static void free_no_errno(void *p) } /* Simplified version of xs_talkv: single message. */ -static void *xs_single(struct xs_handle *h, 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 @@ static bool xs_bool(char *reply) return true; } -char **xs_directory(struct xs_handle *h, 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 @@ char **xs_directory(struct xs_handle *h, xs_transaction_handle t, * 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, 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 @@ void *xs_read(struct xs_handle *h, xs_transaction_handle t, /* Write the value of a single file. * Returns false on failure. */ -bool xs_write(struct xs_handle *h, 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 @@ bool xs_write(struct xs_handle *h, xs_transaction_handle t, /* Create a new directory. * Returns false on failure, or success if it already exists. */ -bool xs_mkdir(struct xs_handle *h, 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 @@ bool xs_mkdir(struct xs_handle *h, xs_transaction_handle t, /* 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, 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 @@ bool xs_rm(struct xs_handle *h, xs_transaction_handle t, * Returns malloced array, or NULL: call free() after use. */ struct xs_permissions *xs_get_permissions(struct xs_handle *h, - xs_transaction_handle t, + xs_transaction_t t, const char *path, unsigned int *num) { char *strings; @@ -499,7 +499,7 @@ struct xs_permissions *xs_get_permissions(struct xs_handle *h, * Returns false on failure. */ bool xs_set_permissions(struct xs_handle *h, - xs_transaction_handle t, + xs_transaction_t t, const char *path, struct xs_permissions *perms, unsigned int num_perms) @@ -636,7 +636,7 @@ bool xs_unwatch(struct xs_handle *h, const char *path, const char *token) * You can only have one transaction at any time. * Returns NULL on failure. */ -xs_transaction_handle xs_transaction_start(struct xs_handle *h) +xs_transaction_t xs_transaction_start(struct xs_handle *h) { char *id_str; unsigned long id; @@ -648,7 +648,7 @@ xs_transaction_handle xs_transaction_start(struct xs_handle *h) id = strtoul(id_str, NULL, 0); free(id_str); - return (xs_transaction_handle)id; + return (xs_transaction_t)id; } /* End a transaction. @@ -656,7 +656,7 @@ xs_transaction_handle xs_transaction_start(struct xs_handle *h) * Returns false on failure, which indicates an error: transactions will * not fail spuriously. */ -bool xs_transaction_end(struct xs_handle *h, xs_transaction_handle t, +bool xs_transaction_end(struct xs_handle *h, xs_transaction_t t, bool abort) { char abortstr[2]; diff --git a/tools/xenstore/xs.h b/tools/xenstore/xs.h index 173c4bc564..55bbcd157a 100644 --- a/tools/xenstore/xs.h +++ b/tools/xenstore/xs.h @@ -25,8 +25,8 @@ #define XBT_NULL NULL struct xs_handle; -struct xs_transaction_handle; -typedef struct xs_transaction_handle * xs_transaction_handle; +struct xs_transaction_t; +typedef struct xs_transaction_t * xs_transaction_t; /* On failure, these routines set errno. */ @@ -48,45 +48,45 @@ void xs_daemon_close(struct xs_handle *); * Returns a malloced array: call free() on it after use. * Num indicates size. */ -char **xs_directory(struct xs_handle *h, 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, 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, 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, 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, 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, - 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, 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); @@ -116,14 +116,14 @@ bool xs_unwatch(struct xs_handle *h, const char *path, const char *token); * You can only have one transaction at any time. * Returns NULL on failure. */ -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, xs_transaction_handle t, +bool xs_transaction_end(struct xs_handle *h, xs_transaction_t t, bool abort); /* Introduce a new domain. diff --git a/tools/xenstore/xs_test.c b/tools/xenstore/xs_test.c index 03674bd26e..5a43bc40b7 100644 --- a/tools/xenstore/xs_test.c +++ b/tools/xenstore/xs_test.c @@ -43,7 +43,7 @@ #define XSTEST static struct xs_handle *handles[10] = { NULL }; -static 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; From d9014bb4aa1120f7024119a5719bccf8b45e7179 Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Wed, 11 Jan 2006 12:01:37 +0000 Subject: [PATCH 10/97] update xs_transaction_t to be a plain u32 integer instead of a fake pointer. Signed-off-by: Vincent Hanquez --- linux-2.6-xen-sparse/arch/xen/kernel/reboot.c | 8 ++++---- linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c | 5 ++--- linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c | 4 ++-- linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 4 ++-- linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c | 5 ++--- linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c | 4 ++-- linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c | 6 ++---- linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c | 12 +++++------- linux-2.6-xen-sparse/include/asm-xen/xenbus.h | 7 +++---- tools/python/xen/lowlevel/xs/xs.c | 12 ++++++------ tools/xenstat/libxenstat/src/xenstat.c | 2 +- tools/xenstore/xenstore_client.c | 2 +- tools/xenstore/xs.c | 10 +++++----- tools/xenstore/xs.h | 5 ++--- 14 files changed, 39 insertions(+), 47 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c index 7a14d8b6cd..534c040c10 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c @@ -297,8 +297,8 @@ static void shutdown_handler(struct xenbus_watch *watch, 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. */ @@ -343,8 +343,8 @@ static void sysrq_handler(struct xenbus_watch *watch, const char **vec, 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 --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c index c5612ce48b..f3a0287935 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -310,10 +310,9 @@ static void connect(struct backend_info *be) /* Supply the information about the device the frontend needs */ again: - xbt = xenbus_transaction_start(); + err = xenbus_transaction_start(&xbt); - if (IS_ERR(xbt)) { - err = PTR_ERR(xbt); + if (err) { xenbus_dev_fatal(dev, err, "starting transaction"); return; } diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c index 9864ef0a63..3e81abe8e4 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -170,8 +170,8 @@ static int talk_to_backend(struct xenbus_device *dev, 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; } diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index 86798341f4..f80250d55a 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -275,8 +275,8 @@ static int talk_to_backend(struct xenbus_device *dev, 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 --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c index f93d1c219b..4a39527711 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c @@ -236,9 +236,8 @@ static void connect(struct backend_info *be) 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 --git a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c index 488a17bd69..bb4bbe83c0 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c @@ -280,8 +280,8 @@ static int talk_to_backend(struct xenbus_device *dev, } 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; } diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c index 4cfd57c34f..fc8b22453f 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c @@ -147,13 +147,11 @@ static ssize_t xenbus_dev_write(struct file *filp, } if (u->u.msg.type == XS_TRANSACTION_START) { - trans->handle = (xenbus_transaction_t) - 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 --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c index 98498dcf97..fa404870f1 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c @@ -201,7 +201,7 @@ static void *xs_talkv(xenbus_transaction_t t, 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; @@ -424,23 +424,21 @@ EXPORT_SYMBOL(xenbus_rm); /* Start a transaction: changes by others will not be seen during this * transaction, and changes will not be visible to others until end. */ -xenbus_transaction_t 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 (xenbus_transaction_t )id_str; + return PTR_ERR(id_str); } - id = simple_strtoul(id_str, NULL, 0); + *t = simple_strtoul(id_str, NULL, 0); kfree(id_str); - - return (xenbus_transaction_t) id; + return 0; } EXPORT_SYMBOL(xenbus_transaction_start); diff --git a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h index b6339dbc75..5534fbe99c 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h +++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h @@ -37,7 +37,7 @@ #include #include -#define XBT_NULL NULL +#define XBT_NULL 0 /* Register callback to watch this node. */ struct xenbus_watch @@ -102,8 +102,7 @@ int xenbus_register_frontend(struct xenbus_driver *drv); int xenbus_register_backend(struct xenbus_driver *drv); void xenbus_unregister_driver(struct xenbus_driver *drv); -struct xenbus_transaction; -typedef struct xenbus_transaction *xenbus_transaction_t; +typedef u32 xenbus_transaction_t; char **xenbus_directory(xenbus_transaction_t t, const char *dir, const char *node, unsigned int *num); @@ -116,7 +115,7 @@ int xenbus_mkdir(xenbus_transaction_t t, int xenbus_exists(xenbus_transaction_t t, const char *dir, const char *node); int xenbus_rm(xenbus_transaction_t t, const char *dir, const char *node); -xenbus_transaction_t xenbus_transaction_start(void); +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. */ diff --git a/tools/python/xen/lowlevel/xs/xs.c b/tools/python/xen/lowlevel/xs/xs.c index 5f6d1850f4..25dfaaf2a4 100644 --- a/tools/python/xen/lowlevel/xs/xs.c +++ b/tools/python/xen/lowlevel/xs/xs.c @@ -132,7 +132,7 @@ static PyObject *xspy_write(XsHandle *self, PyObject *args) if (!PyArg_ParseTuple(args, arg_spec, &thstr, &path, &data, &data_n)) return NULL; - th = (xs_transaction_t)strtoul(thstr, NULL, 16); + th = strtoul(thstr, NULL, 16); Py_BEGIN_ALLOW_THREADS result = xs_write(xh, th, path, data, data_n); @@ -264,7 +264,7 @@ static PyObject *xspy_get_permissions(XsHandle *self, PyObject *args) if (!PyArg_ParseTuple(args, arg_spec, &thstr, &path)) return NULL; - th = (xs_transaction_t)strtoul(thstr, NULL, 16); + th = strtoul(thstr, NULL, 16); Py_BEGIN_ALLOW_THREADS perms = xs_get_permissions(xh, th, path, &perms_n); @@ -320,7 +320,7 @@ static PyObject *xspy_set_permissions(XsHandle *self, PyObject *args) if (!PyArg_ParseTuple(args, "ssO", &thstr, &path, &perms)) goto exit; - th = (xs_transaction_t)strtoul(thstr, NULL, 16); + th = strtoul(thstr, NULL, 16); if (!PyList_Check(perms)) { PyErr_SetString(PyExc_RuntimeError, "perms must be a list"); @@ -519,7 +519,7 @@ static PyObject *xspy_transaction_start(XsHandle *self) th = xs_transaction_start(xh); Py_END_ALLOW_THREADS - if (th == NULL) { + if (th == XBT_NULL) { PyErr_SetFromErrno(PyExc_RuntimeError); return NULL; } @@ -556,7 +556,7 @@ static PyObject *xspy_transaction_end(XsHandle *self, PyObject *args, &thstr, &abort)) return NULL; - th = (xs_transaction_t)strtoul(thstr, NULL, 16); + th = strtoul(thstr, NULL, 16); Py_BEGIN_ALLOW_THREADS result = xs_transaction_end(xh, th, abort); @@ -740,7 +740,7 @@ static int parse_transaction_path(XsHandle *self, PyObject *args, if (!PyArg_ParseTuple(args, "ss", &thstr, path)) return 0; - *th = (xs_transaction_t)strtoul(thstr, NULL, 16); + *th = strtoul(thstr, NULL, 16); return 1; } diff --git a/tools/xenstat/libxenstat/src/xenstat.c b/tools/xenstat/libxenstat/src/xenstat.c index 921c7d29db..e8a6928dac 100644 --- a/tools/xenstat/libxenstat/src/xenstat.c +++ b/tools/xenstat/libxenstat/src/xenstat.c @@ -705,7 +705,7 @@ static char *xenstat_get_domain_name(xenstat_handle *handle, unsigned int domain 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 --git a/tools/xenstore/xenstore_client.c b/tools/xenstore/xenstore_client.c index deb63453d3..07809e6c83 100644 --- a/tools/xenstore/xenstore_client.c +++ b/tools/xenstore/xenstore_client.c @@ -243,7 +243,7 @@ main(int argc, char **argv) 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 --git a/tools/xenstore/xs.c b/tools/xenstore/xs.c index 8332e1aad5..f7a576119f 100644 --- a/tools/xenstore/xs.c +++ b/tools/xenstore/xs.c @@ -304,7 +304,7 @@ static void *xs_talkv(struct xs_handle *h, xs_transaction_t t, 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; @@ -634,21 +634,21 @@ bool xs_unwatch(struct xs_handle *h, const char *path, const char *token) /* 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. + * 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 (xs_transaction_t)id; + return id; } /* End a transaction. diff --git a/tools/xenstore/xs.h b/tools/xenstore/xs.h index 55bbcd157a..cabf9d0711 100644 --- a/tools/xenstore/xs.h +++ b/tools/xenstore/xs.h @@ -22,11 +22,10 @@ #include -#define XBT_NULL NULL +#define XBT_NULL 0 struct xs_handle; -struct xs_transaction_t; -typedef struct xs_transaction_t * xs_transaction_t; +typedef uint32_t xs_transaction_t; /* On failure, these routines set errno. */ From 6bc154ed1e341a48ec3e21c08dc10fda9734aedd Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Wed, 11 Jan 2006 12:02:54 +0000 Subject: [PATCH 11/97] make xs_test in xenstore compile. Signed-off-by: Vincent Hanquez --- tools/xenstore/xs_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/xenstore/xs_test.c b/tools/xenstore/xs_test.c index 5a43bc40b7..8b1a5ebf1a 100644 --- a/tools/xenstore/xs_test.c +++ b/tools/xenstore/xs_test.c @@ -535,7 +535,7 @@ static void do_introduce(unsigned int handle, *(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; From 1582d1175001a99133810c158622c53d1e3dc9ee Mon Sep 17 00:00:00 2001 From: "Ian.Campbell@xensource.com" Date: Wed, 11 Jan 2006 15:51:18 +0000 Subject: [PATCH 12/97] Factor re-enabling the IOCK line out of io_check_error() and into a machine specific function to. Signed-off-by: Ian Campbell --- .../arch/xen/i386/kernel/traps.c | 9 +--- .../linux-2.6.12/i386-mach-io-check-nmi.patch | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 patches/linux-2.6.12/i386-mach-io-check-nmi.patch diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c index adb0986b4b..f2669a71a3 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c @@ -506,18 +506,11 @@ static void mem_parity_error(unsigned char reason, struct pt_regs * regs) 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) diff --git a/patches/linux-2.6.12/i386-mach-io-check-nmi.patch b/patches/linux-2.6.12/i386-mach-io-check-nmi.patch new file mode 100644 index 0000000000..3a6048833a --- /dev/null +++ b/patches/linux-2.6.12/i386-mach-io-check-nmi.patch @@ -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); From f071016a5c42f407493ffd5172cdbc9ffa177db0 Mon Sep 17 00:00:00 2001 From: "Ian.Campbell@xensource.com" Date: Wed, 11 Jan 2006 15:51:56 +0000 Subject: [PATCH 13/97] Pass NMIs to DOM0 via a dedicated callback, core Xen support. This patch adds core and generic x86 support code to enable Xen to pass NMI's to a dedicated NMI callback in DOM0 instead of raising a VIRQ. Introduces the nmi_op hypercall to allow DOM0 to (un)register the NMI handler. Signed-off-by: Ian Campbell --- xen/arch/x86/traps.c | 40 ++++++++++------------- xen/common/kernel.c | 25 +++++++++++++++ xen/include/asm-x86/nmi.h | 2 ++ xen/include/public/arch-x86_32.h | 1 + xen/include/public/arch-x86_64.h | 1 + xen/include/public/nmi.h | 54 ++++++++++++++++++++++++++++++++ xen/include/public/xen.h | 4 +-- xen/include/xen/sched.h | 8 +++++ xen/include/xen/softirq.h | 2 +- 9 files changed, 110 insertions(+), 27 deletions(-) create mode 100644 xen/include/public/nmi.h diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index d7590d36bd..4458b70636 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -1080,26 +1080,23 @@ asmlinkage int do_general_protection(struct cpu_user_regs *regs) 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) +static void nmi_softirq(void) { - if ( dom0 == NULL ) + /* 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); + set_bit(reason_idx, &d->shared_info->arch.nmi_reason); - 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); + 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 +1104,7 @@ asmlinkage void mem_parity_error(struct cpu_user_regs *regs) 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 +1123,7 @@ asmlinkage void io_check_error(struct cpu_user_regs *regs) 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 +1142,7 @@ static void unknown_nmi_error(unsigned char reason) 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 +1341,7 @@ void __init trap_init(void) cpu_init(); - open_softirq(NMI_DOM0_SOFTIRQ, nmi_dom0_softirq); + open_softirq(NMI_SOFTIRQ, nmi_softirq); } diff --git a/xen/common/kernel.c b/xen/common/kernel.c index 9975ee639d..f2bb308652 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -11,6 +11,7 @@ #include #include #include +#include #include void cmdline_parse(char *cmdline) @@ -148,6 +149,30 @@ long do_xen_version(int cmd, void *arg) return -ENOSYS; } +long do_nmi_op(unsigned int cmd, void *arg) +{ + long rc = 0; + + switch ( cmd ) + { + case XENNMI_register_callback: + if ( (current->domain->domain_id != 0) || (current->vcpu_id != 0) ) + rc = -EINVAL; + else + current->nmi_addr = (unsigned long)arg; + printk("***** NMI handler at 0x%lx\n", current->nmi_addr); + break; + case XENNMI_unregister_callback: + current->nmi_addr = 0; + break; + default: + rc = -ENOSYS; + break; + } + + return rc; +} + long do_vm_assist(unsigned int cmd, unsigned int type) { return vm_assist(current->domain, cmd, type); diff --git a/xen/include/asm-x86/nmi.h b/xen/include/asm-x86/nmi.h index 1529bbb8c7..d79b823ee2 100644 --- a/xen/include/asm-x86/nmi.h +++ b/xen/include/asm-x86/nmi.h @@ -2,6 +2,8 @@ #ifndef ASM_NMI_H #define ASM_NMI_H +#include + struct cpu_user_regs; typedef int (*nmi_callback_t)(struct cpu_user_regs *regs, int cpu); diff --git a/xen/include/public/arch-x86_32.h b/xen/include/public/arch-x86_32.h index b4372da204..534acb6b78 100644 --- a/xen/include/public/arch-x86_32.h +++ b/xen/include/public/arch-x86_32.h @@ -135,6 +135,7 @@ typedef struct arch_shared_info { 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 --git a/xen/include/public/arch-x86_64.h b/xen/include/public/arch-x86_64.h index ea8af05c6e..03bc3ec08c 100644 --- a/xen/include/public/arch-x86_64.h +++ b/xen/include/public/arch-x86_64.h @@ -202,6 +202,7 @@ typedef struct arch_shared_info { 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 --git a/xen/include/public/nmi.h b/xen/include/public/nmi.h new file mode 100644 index 0000000000..0c0c67b920 --- /dev/null +++ b/xen/include/public/nmi.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * nmi.h + * + * NMI callback registration and reason codes. + * + * Copyright (c) 2005, Keir Fraser + */ + +#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 --git a/xen/include/public/xen.h b/xen/include/public/xen.h index ddc901bc9a..354985359c 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -59,6 +59,7 @@ #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 +70,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 --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 8492acf97a..7d9dee679b 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -81,6 +81,8 @@ struct vcpu /* 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; @@ -361,6 +363,12 @@ extern struct domain *domain_list; /* 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 --git a/xen/include/xen/softirq.h b/xen/include/xen/softirq.h index 5f1903695b..87d6c807ee 100644 --- a/xen/include/xen/softirq.h +++ b/xen/include/xen/softirq.h @@ -6,7 +6,7 @@ #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 From f483c99420cf5a98931a27dd4b03af7f413d1320 Mon Sep 17 00:00:00 2001 From: "Ian.Campbell@xensource.com" Date: Wed, 11 Jan 2006 15:52:12 +0000 Subject: [PATCH 14/97] Pass NMIs to DOM0 via a dedicated callback, Xen x86_32 support. Handle NMI interrupts and dispatch to dom0 on x86_32. Renames the switch_vm86 hypercall to iret and implements full iret semantics instead only what is required by VM86 returns. Plumb in nmi_op hypercall to generic code. Signed-off-by: Ian Campbell --- xen/arch/x86/x86_32/asm-offsets.c | 4 ++ xen/arch/x86/x86_32/entry.S | 71 ++++++++++++------------------- xen/arch/x86/x86_32/traps.c | 43 +++++++++++++++++++ xen/include/public/xen.h | 3 +- 4 files changed, 76 insertions(+), 45 deletions(-) diff --git a/xen/arch/x86/x86_32/asm-offsets.c b/xen/arch/x86/x86_32/asm-offsets.c index 3a5c3ef9f8..42bef57240 100644 --- a/xen/arch/x86/x86_32/asm-offsets.c +++ b/xen/arch/x86/x86_32/asm-offsets.c @@ -65,6 +65,10 @@ void __dummy__(void) 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 --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index b890103160..e178d7383e 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -326,7 +326,9 @@ test_all_events: 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 @@ process_softirqs: 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 @@ ENTRY(nmi) 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 @@ -660,42 +677,6 @@ do_arch_sched_op: 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 ENTRY(exception_table) @@ -744,11 +725,12 @@ ENTRY(hypercall_table) .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 @@ ENTRY(hypercall_args_table) .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 --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index cb2b7b9eaa..e70081e1bf 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -157,6 +157,49 @@ asmlinkage void do_double_fault(void) __asm__ __volatile__ ( "hlt" ); } +asmlinkage unsigned long do_iret(void) +{ + struct cpu_user_regs *regs = guest_cpu_user_regs(); + + /* Restore EAX (clobbered by hypercall) */ + if (copy_from_user(®s->eax, (void __user *)regs->esp, 4)) + domain_crash_synchronous(); + regs->esp += 4; + + /* Restore EFLAGS, CS and EIP */ + if (copy_from_user(®s->eip, (void __user *)regs->esp, 12)) + domain_crash_synchronous(); + + if (VM86_MODE(regs)) { + /* return to VM86 mode: restore ESP,SS,ES,DS,FS and GS */ + if(copy_from_user(®s->esp, (void __user *)(regs->esp+12), 24)) + domain_crash_synchronous(); + } else if (RING_0(regs)) { + domain_crash_synchronous(); + } else if (RING_1(regs)) { + /* return to ring 1: pop EFLAGS,CS and EIP */ + regs->esp += 12; + } else { + /* return to ring 2/3: restore ESP and SS */ + if(copy_from_user(®s->esp, (void __user *)(regs->esp+12), 8)) + domain_crash_synchronous(); + } + + /* Fixup EFLAGS */ + regs->eflags &= ~X86_EFLAGS_IOPL; + regs->eflags |= X86_EFLAGS_IF; + + /* 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 --git a/xen/include/public/xen.h b/xen/include/public/xen.h index 354985359c..c141dbdc66 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -53,7 +53,8 @@ #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_iret 23 /* x86/32 only */ +#define __HYPERVISOR_switch_vm86 23 /* x86/32 only (obsolete name) */ #define __HYPERVISOR_switch_to_user 23 /* x86/64 only */ #define __HYPERVISOR_vcpu_op 24 #define __HYPERVISOR_set_segment_base 25 /* x86/64 only */ From dfafd0de0cd52ed57f31a635b165ae4ca3ad498e Mon Sep 17 00:00:00 2001 From: "Ian.Campbell@xensource.com" Date: Wed, 11 Jan 2006 15:52:33 +0000 Subject: [PATCH 15/97] Pass NMIs to DOM0 via a dedicated callback, Xen x86_64 support. Handle NMI interrupts and dispatch to dom0 on x86_64. Renames the switch_to_user hypercall to iret. Extend the semantics to include returns to guest/kernel if CS indicates ring 1. Retain the old semantics of returning to guest/user if CS indicates ring3. Plumb in nmi_op hypercall to generic code. Signed-off-by: Ian Campbell --- xen/arch/x86/domain.c | 29 ------------------------ xen/arch/x86/x86_64/asm-offsets.c | 4 ++++ xen/arch/x86/x86_64/entry.S | 32 ++++++++++++++++++++++---- xen/arch/x86/x86_64/traps.c | 37 +++++++++++++++++++++++++++++++ xen/include/asm-x86/processor.h | 1 + xen/include/public/arch-x86_64.h | 22 +++++++++++++++--- xen/include/public/xen.h | 4 ++-- 7 files changed, 91 insertions(+), 38 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 53e129178c..f492dac762 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -659,35 +659,6 @@ static void save_segments(struct vcpu *v) 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__) diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c index c7a3e6025c..0aa20ccabb 100644 --- a/xen/arch/x86/x86_64/asm-offsets.c +++ b/xen/arch/x86/x86_64/asm-offsets.c @@ -65,6 +65,10 @@ void __dummy__(void) 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 --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 3c5c344a1a..88fe273bab 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -171,7 +171,9 @@ test_all_events: 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 @@ process_softirqs: 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 @@ create_bounce_frame: 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 @@ ENTRY(nmi) 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 @@ ENTRY(hypercall_table) .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 @@ ENTRY(hypercall_args_table) .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 --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index 4f7c822ef8..e14daa3e72 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -12,6 +12,7 @@ #include #include #include +#include #include void show_registers(struct cpu_user_regs *regs) @@ -113,6 +114,42 @@ asmlinkage void do_double_fault(struct cpu_user_regs *regs) __asm__ __volatile__ ( "hlt" ); } +extern void toggle_guest_mode(struct vcpu *); + +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))) || + unlikely(pagetable_get_paddr(v->arch.guest_table_user) == 0) ) + return -EFAULT; + + /* returning to user mode */ + if ((iret_saved.cs & 0x03) == 3) + 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 --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index d3bcc69904..18748e3367 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -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 --git a/xen/include/public/arch-x86_64.h b/xen/include/public/arch-x86_64.h index 03bc3ec08c..e9e69db069 100644 --- a/xen/include/public/arch-x86_64.h +++ b/xen/include/public/arch-x86_64.h @@ -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,17 @@ */ /* 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. */ }; /* diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index c141dbdc66..ca1d4d1d03 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -53,9 +53,9 @@ #define __HYPERVISOR_grant_table_op 20 #define __HYPERVISOR_vm_assist 21 #define __HYPERVISOR_update_va_mapping_otherdomain 22 -#define __HYPERVISOR_iret 23 /* x86/32 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 */ +#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 From 716d68d4c2979938d4d4c36b0fe3fa34cc676621 Mon Sep 17 00:00:00 2001 From: "Ian.Campbell@xensource.com" Date: Wed, 11 Jan 2006 15:52:54 +0000 Subject: [PATCH 16/97] Pass NMIs to DOM0 via a dedicated callback, Xen/Linux i386 support. Register our NMI handler with Xen. Use a pseudo-flag in EFLAGS in indicate that we should return from the NMI via a hypervisor iret. Signed-off-by: Ian Campbell --- .../arch/xen/i386/kernel/entry.S | 23 +++++++++---- .../include/asm-xen/asm-i386/hypercall.h | 9 +++++ .../asm-xen/asm-i386/mach-xen/mach_traps.h | 33 +++++++++++++++++++ .../asm-i386/mach-xen/setup_arch_post.h | 3 ++ 4 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/mach_traps.h diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S b/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S index 6522f7a249..9c50c32426 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S @@ -76,7 +76,9 @@ IF_MASK = 0x00000200 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 @@ restore_all: 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 @@ iret_exc: .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 @@ debug_stack_correct: 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 --git a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h index 6fc4203116..04edbd3741 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h @@ -32,6 +32,7 @@ #include #include +#include #define _hypercall0(type, name) \ ({ \ @@ -300,6 +301,14 @@ HYPERVISOR_suspend( 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 --git a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/mach_traps.h b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/mach_traps.h new file mode 100644 index 0000000000..14c607962b --- /dev/null +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/mach_traps.h @@ -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 +#include + +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 --git a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h index b30853d2cf..fa7d6191b1 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h @@ -29,6 +29,7 @@ void __init machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c) 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 @@ static void __init machine_specific_arch_setup(void) __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); } From 544a856af58d05d324b3056daa5ac7018a99d43e Mon Sep 17 00:00:00 2001 From: "Ian.Campbell@xensource.com" Date: Wed, 11 Jan 2006 15:53:59 +0000 Subject: [PATCH 17/97] Pass NMIs to DOM0 via a dedicated callback, Xen/Linux x86_64 support. Register our NMI handler with Xen. Do an iret via the hypervisor whenever the return CS is > RING0. Add include/asm-xen/asm-x86_64/nmi.h as a Xen modified copy of include/asm-x86_64/nmi.h in order that we can implement get_nmi_reason() in a manner suitable for Xen. Signed-off-by: Ian Campbell --- .../arch/xen/x86_64/kernel/entry.S | 24 ++++-- .../arch/xen/x86_64/kernel/setup.c | 1 + .../arch/xen/x86_64/kernel/traps.c | 4 + .../include/asm-xen/asm-x86_64/hypercall.h | 12 ++- .../asm-x86_64/mach-xen/setup_arch_post.h | 3 + .../include/asm-xen/asm-x86_64/nmi.h | 75 +++++++++++++++++++ 6 files changed, 110 insertions(+), 9 deletions(-) create mode 100644 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/nmi.h diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S index c8fa7871d8..9ecc36e5ca 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S @@ -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 @@ sysret_check: 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 */ @@ -478,7 +478,7 @@ kernel_mode: orb $3,1*8(%rsp) iretq user_mode: - SWITCH_TO_USER 0 + HYPERVISOR_IRET 0 /* edi: workmask, edx: work */ retint_careful: @@ -719,6 +719,16 @@ ENTRY(do_hypervisor_callback) # do_hyperviosr_callback(struct *pt_regs) call evtchn_do_upcall jmp error_exit +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 + ALIGN restore_all_enable_events: XEN_UNBLOCK_EVENTS(%rsi) # %rsi is already set up... @@ -733,7 +743,7 @@ scrit: /**** START OF CRITICAL REGION ****/ 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 --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c index f82f8aac84..ef7deb8938 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c @@ -62,6 +62,7 @@ #include #include "setup_arch_pre.h" #include +#include #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) #define PFN_PHYS(x) ((x) << PAGE_SHIFT) #define end_pfn_map end_pfn diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c index 227042ba63..6229915b11 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c @@ -559,9 +559,11 @@ static void mem_parity_error(unsigned char reason, struct pt_regs * regs) 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 @@ static void io_check_error(unsigned char reason, struct pt_regs * regs) 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) diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h index bb338772d0..521f004c00 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h @@ -287,9 +287,9 @@ HYPERVISOR_vcpu_op( } static inline int -HYPERVISOR_switch_to_user(void) +HYPERVISOR_iret(void) { - return _hypercall0(int, switch_to_user); + return _hypercall0(int, iret); } static inline int @@ -307,6 +307,14 @@ HYPERVISOR_suspend( 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 --git a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h index 7be26e8660..bad118e44c 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h @@ -35,6 +35,7 @@ void __init machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c) 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,7 @@ static void __init machine_specific_arch_setup(void) (unsigned long) failsafe_callback, (unsigned long) system_call); + HYPERVISOR_nmi_op(XENNMI_register_callback, (unsigned long)&nmi); + machine_specific_modify_cpu_capabilities(&boot_cpu_data); } diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/nmi.h b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/nmi.h new file mode 100644 index 0000000000..1c5d28dad2 --- /dev/null +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/nmi.h @@ -0,0 +1,75 @@ +/* + * linux/include/asm-i386/nmi.h + */ +#ifndef ASM_NMI_H +#define ASM_NMI_H + +#include + +#include + +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 */ From a72cda2a94ccacbefcf81f0cfedb0646af9b1ef6 Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Wed, 11 Jan 2006 16:23:16 +0000 Subject: [PATCH 18/97] Install in /usr/sbin, not /usr/local/sbin, for consistency with the rest of the Xen distribution. Closes bug #462. Signed-off-by: Ewan Mellor --- tools/xenmon/Makefile | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tools/xenmon/Makefile b/tools/xenmon/Makefile index 7fdf786445..6ff8391f9c 100644 --- a/tools/xenmon/Makefile +++ b/tools/xenmon/Makefile @@ -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 From 046536e8eee2b74e6a98b29822adf3b8a2ba57e0 Mon Sep 17 00:00:00 2001 From: "Ian.Campbell@xensource.com" Date: Wed, 11 Jan 2006 17:50:05 +0000 Subject: [PATCH 19/97] Fixup some bogus formatting and remove a stray debug printk Signed-off-by: Ian Campbell --- .../arch/xen/i386/kernel/entry.S | 2 +- xen/arch/x86/x86_32/traps.c | 42 +++++++++++-------- xen/arch/x86/x86_64/traps.c | 10 ++--- xen/common/kernel.c | 1 - xen/include/public/arch-x86_64.h | 6 ++- 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S b/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S index 9c50c32426..ef23e7ca3c 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/entry.S @@ -76,7 +76,7 @@ IF_MASK = 0x00000200 DF_MASK = 0x00000400 NT_MASK = 0x00004000 VM_MASK = 0x00020000 -/* pseudo-eflags */ +/* Pseudo-eflags. */ NMI_MASK = 0x80000000 /* Offsets into shared_info_t. */ diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index e70081e1bf..2c896bce2a 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -161,42 +161,50 @@ asmlinkage unsigned long do_iret(void) { struct cpu_user_regs *regs = guest_cpu_user_regs(); - /* Restore EAX (clobbered by hypercall) */ - if (copy_from_user(®s->eax, (void __user *)regs->esp, 4)) + /* Restore EAX (clobbered by hypercall). */ + if ( copy_from_user(®s->eax, (void __user *)regs->esp, 4) ) domain_crash_synchronous(); regs->esp += 4; - /* Restore EFLAGS, CS and EIP */ - if (copy_from_user(®s->eip, (void __user *)regs->esp, 12)) + /* Restore EFLAGS, CS and EIP. */ + if ( copy_from_user(®s->eip, (void __user *)regs->esp, 12) ) domain_crash_synchronous(); - if (VM86_MODE(regs)) { - /* return to VM86 mode: restore ESP,SS,ES,DS,FS and GS */ + if ( VM86_MODE(regs) ) + { + /* Return to VM86 mode: restore ESP,SS,ES,DS,FS and GS. */ if(copy_from_user(®s->esp, (void __user *)(regs->esp+12), 24)) domain_crash_synchronous(); - } else if (RING_0(regs)) { + } + else if ( RING_0(regs) ) + { domain_crash_synchronous(); - } else if (RING_1(regs)) { - /* return to ring 1: pop EFLAGS,CS and EIP */ + } + else if ( RING_1(regs) ) { + /* Return to ring 1: pop EFLAGS,CS and EIP. */ regs->esp += 12; - } else { - /* return to ring 2/3: restore ESP and SS */ - if(copy_from_user(®s->esp, (void __user *)(regs->esp+12), 8)) + } + else + { + /* Return to ring 2/3: restore ESP and SS. */ + if ( copy_from_user(®s->esp, (void __user *)(regs->esp+12), 8) ) domain_crash_synchronous(); } - /* Fixup EFLAGS */ + /* Fixup EFLAGS. */ regs->eflags &= ~X86_EFLAGS_IOPL; regs->eflags |= X86_EFLAGS_IF; - /* No longer in NMI context */ + /* No longer in NMI context. */ clear_bit(_VCPUF_nmi_masked, ¤t->vcpu_flags); - /* Restore upcall mask from saved value */ + /* 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 */ + /* + * The hypercall exit path will overwrite EAX with this return + * value. + */ return regs->eax; } diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index e14daa3e72..af2f55e29a 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -118,16 +118,16 @@ extern void toggle_guest_mode(struct vcpu *); long do_iret(void) { - struct cpu_user_regs *regs = guest_cpu_user_regs(); + struct cpu_user_regs *regs = guest_cpu_user_regs(); struct iret_context iret_saved; - struct vcpu *v = current; + struct vcpu *v = current; if ( unlikely(copy_from_user(&iret_saved, (void *)regs->rsp, sizeof(iret_saved))) || unlikely(pagetable_get_paddr(v->arch.guest_table_user) == 0) ) return -EFAULT; - /* returning to user mode */ - if ((iret_saved.cs & 0x03) == 3) + /* Returning to user mode. */ + if ( (iret_saved.cs & 0x03) == 3 ) toggle_guest_mode(v); regs->rip = iret_saved.rip; @@ -143,7 +143,7 @@ long do_iret(void) regs->rcx = iret_saved.rcx; } - /* No longer in NMI context */ + /* No longer in NMI context. */ clear_bit(_VCPUF_nmi_masked, ¤t->vcpu_flags); /* Saved %rax gets written back to regs->rax in entry.S. */ diff --git a/xen/common/kernel.c b/xen/common/kernel.c index f2bb308652..3908f04019 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -160,7 +160,6 @@ long do_nmi_op(unsigned int cmd, void *arg) rc = -EINVAL; else current->nmi_addr = (unsigned long)arg; - printk("***** NMI handler at 0x%lx\n", current->nmi_addr); break; case XENNMI_unregister_callback: current->nmi_addr = 0; diff --git a/xen/include/public/arch-x86_64.h b/xen/include/public/arch-x86_64.h index e9e69db069..c8c2bd2809 100644 --- a/xen/include/public/arch-x86_64.h +++ b/xen/include/public/arch-x86_64.h @@ -114,8 +114,10 @@ struct iret_context { 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 */ +/* + * 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; From d02b79422bd22608953631a2e8fe5d87411b76a6 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 11 Jan 2006 19:18:21 +0100 Subject: [PATCH 20/97] Add a per-vcpu lock-free cache of mappings to map_domain_page. Improve mapping slot search by using a free bitmap. Removed map_domain_pages (multi-page mapping functionality). Noone uses it, nor should they use it in future, Signed-off-by: Keir Fraser --- xen/arch/x86/domain.c | 4 +- xen/arch/x86/x86_32/domain_page.c | 142 +++++++++++++++++++----------- xen/include/asm-x86/domain.h | 29 +++++- xen/include/xen/domain_page.h | 21 ++--- 4 files changed, 129 insertions(+), 67 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index f492dac762..e1485ed1a0 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -288,9 +288,7 @@ int arch_do_createdomain(struct vcpu *v) #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__ */ diff --git a/xen/arch/x86/x86_32/domain_page.c b/xen/arch/x86/x86_32/domain_page.c index b8ca0ab47d..f835beee52 100644 --- a/xen/arch/x86/x86_32/domain_page.c +++ b/xen/arch/x86/x86_32/domain_page.c @@ -20,33 +20,16 @@ #include #include -#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; + unsigned int idx, i, vcpu = current->vcpu_id; struct domain *d; struct mapcache *cache; -#ifndef NDEBUG - unsigned int flush_count = 0; -#endif + 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. */ @@ -56,6 +39,16 @@ void *map_domain_pages(unsigned long pfn, unsigned int order) 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. */ @@ -70,45 +63,97 @@ void *map_domain_pages(unsigned long pfn, unsigned int order) } } - do { - idx = cache->cursor = (cache->cursor + 1) & (MAPCACHE_ENTRIES - 1); - if ( unlikely(idx == 0) ) + 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++ ) { - ASSERT(flush_count++ == 0); - flush_all_ready_maps(); - perfc_incrc(domain_page_tlb_flush); - local_flush_tlb(); - cache->shadow_epoch[vcpu] = ++cache->epoch; - cache->tlbflush_timestamp = tlbflush_current_time(); + unsigned long x = xchg(&cache->garbage[i], 0); + cache->inuse[i] &= ~x; } - flags = 0; - for ( i = 0; i < (1U << order); i++ ) - flags |= l1e_get_flags(cache->l1tab[idx+i]); - } - while ( flags & _PAGE_PRESENT ); + /* /Second/, flush TLBs. */ + perfc_incrc(domain_page_tlb_flush); + local_flush_tlb(); + cache->shadow_epoch[vcpu] = ++cache->epoch; + cache->tlbflush_timestamp = tlbflush_current_time(); - for ( i = 0; i < (1U << order); i++ ) - cache->l1tab[idx+i] = l1e_from_pfn(pfn+i, __PAGE_HYPERVISOR); + 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) +void unmap_domain_page(void *va) { - unsigned int idx, i; + 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; + pfn = l1e_get_pfn(cache->l1tab[idx]); + hashent = &cache->vcpu_maphash[current->vcpu_id].hash[MAPHASH_HASHFN(pfn)]; - for ( i = 0; i < (1U << order); i++ ) - l1e_add_flags(cache->l1tab[idx+i], READY_FOR_TLB_FLUSH); + 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)) @@ -128,15 +173,10 @@ void *map_domain_page_global(unsigned long pfn) spin_lock(&globalmap_lock); - for ( ; ; ) + idx = find_next_zero_bit(inuse, GLOBALMAP_BITS, inuse_cursor); + va = IOREMAP_VIRT_START + (idx << PAGE_SHIFT); + if ( unlikely(va >= FIXADDR_START) ) { - idx = find_next_zero_bit(inuse, GLOBALMAP_BITS, inuse_cursor); - va = IOREMAP_VIRT_START + (idx << PAGE_SHIFT); - - /* End of round? If not then we're done in this loop. */ - if ( va < FIXADDR_START ) - break; - /* /First/, clean the garbage map and update the inuse list. */ for ( i = 0; i < ARRAY_SIZE(garbage); i++ ) { @@ -147,7 +187,9 @@ void *map_domain_page_global(unsigned long pfn) /* /Second/, flush all TLBs to get rid of stale garbage mappings. */ flush_tlb_all(); - inuse_cursor = 0; + idx = find_first_zero_bit(inuse, GLOBALMAP_BITS); + va = IOREMAP_VIRT_START + (idx << PAGE_SHIFT); + ASSERT(va < FIXADDR_START); } set_bit(idx, inuse); diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index b9955c0249..a713b89886 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -13,14 +13,41 @@ struct trap_bounce { 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]; u32 tlbflush_timestamp; - spinlock_t lock; + + /* 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 *d); + struct arch_domain { l1_pgentry_t *mm_perdomain_pt; diff --git a/xen/include/xen/domain_page.h b/xen/include/xen/domain_page.h index 8fbd9ffaa7..c4729b0ea9 100644 --- a/xen/include/xen/domain_page.h +++ b/xen/include/xen/domain_page.h @@ -10,24 +10,19 @@ #include #include -#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 within the current VCPU 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 in the context - * of the currently-executing VCPU via a call to map_domain_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 @@ -97,8 +92,8 @@ domain_mmap_cache_destroy(struct domain_mmap_cache *cache) #else /* !CONFIG_DOMAIN_PAGE */ -#define map_domain_pages(pfn,order) phys_to_virt((pfn)< Date: Wed, 11 Jan 2006 19:24:43 +0100 Subject: [PATCH 21/97] Reassert nmi pending when a nmi handler is registered if we lost a previous nmi. Signed-off-by: Keir Fraser --- xen/common/kernel.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/xen/common/kernel.c b/xen/common/kernel.c index f2bb308652..f1d74c731a 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -151,19 +151,32 @@ long do_xen_version(int cmd, void *arg) 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 ( (current->domain->domain_id != 0) || (current->vcpu_id != 0) ) - rc = -EINVAL; + if ( (d->domain_id != 0) || (v->vcpu_id != 0) ) + { + rc = -EINVAL; + } else - current->nmi_addr = (unsigned long)arg; - printk("***** NMI handler at 0x%lx\n", current->nmi_addr); + { + 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: - current->nmi_addr = 0; + v->nmi_addr = 0; break; default: rc = -ENOSYS; From ab8eb5a3ef5e7968d0c0f18db4452ac0f0995ed2 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 11 Jan 2006 19:44:54 +0100 Subject: [PATCH 22/97] More code cleanups, mainly to do_iret() implementations. Signed-off-by: Keir Fraser --- xen/arch/x86/domain.c | 8 -------- xen/arch/x86/mm.c | 2 -- xen/arch/x86/traps.c | 1 - xen/arch/x86/x86_32/traps.c | 35 +++++++++++++++++------------------ xen/arch/x86/x86_64/traps.c | 22 ++++++++++++++++------ xen/include/asm-x86/domain.h | 5 ++++- 6 files changed, 37 insertions(+), 36 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index e1485ed1a0..19c29d084c 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -480,14 +480,6 @@ void new_thread(struct vcpu *d, #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; \ __asm__ __volatile__ ( \ diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index f15ebb4d9c..a9dba3ef66 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -297,7 +297,6 @@ int map_ldt_shadow_page(unsigned int off) #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 @@ void ptwr_flush(struct domain *d, const int which) #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 diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 4458b70636..9929722fab 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -596,7 +596,6 @@ static inline int guest_io_okay( 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__) diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index 2c896bce2a..6f7fb83640 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -157,38 +157,37 @@ asmlinkage void do_double_fault(void) __asm__ __volatile__ ( "hlt" ); } +static inline void pop_from_guest_stack( + void *dst, struct cpu_user_regs *regs, unsigned int bytes) +{ + if ( unlikely(copy_from_user(dst, (void __user *)regs->esp, bytes)) ) + domain_crash_synchronous(); + regs->esp += bytes; +} + asmlinkage unsigned long do_iret(void) { struct cpu_user_regs *regs = guest_cpu_user_regs(); - /* Restore EAX (clobbered by hypercall). */ - if ( copy_from_user(®s->eax, (void __user *)regs->esp, 4) ) - domain_crash_synchronous(); - regs->esp += 4; + /* Pop and restore EAX (clobbered by hypercall). */ + pop_from_guest_stack(®s->eax, regs, 4); - /* Restore EFLAGS, CS and EIP. */ - if ( copy_from_user(®s->eip, (void __user *)regs->esp, 12) ) - domain_crash_synchronous(); + /* Pop and restore EFLAGS, CS and EIP. */ + pop_from_guest_stack(®s->eip, regs, 12); if ( VM86_MODE(regs) ) { - /* Return to VM86 mode: restore ESP,SS,ES,DS,FS and GS. */ - if(copy_from_user(®s->esp, (void __user *)(regs->esp+12), 24)) - domain_crash_synchronous(); + /* Return to VM86 mode: pop and restore ESP,SS,ES,DS,FS and GS. */ + pop_from_guest_stack(®s->esp, regs, 24); } else if ( RING_0(regs) ) { domain_crash_synchronous(); } - else if ( RING_1(regs) ) { - /* Return to ring 1: pop EFLAGS,CS and EIP. */ - regs->esp += 12; - } - else + else if ( !RING_1(regs) ) { - /* Return to ring 2/3: restore ESP and SS. */ - if ( copy_from_user(®s->esp, (void __user *)(regs->esp+12), 8) ) - domain_crash_synchronous(); + /* Return to ring 2/3: pop and restore ESP and SS. */ + pop_from_guest_stack(®s->esp, regs, 8); } /* Fixup EFLAGS. */ diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index af2f55e29a..9756c54589 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -114,7 +114,13 @@ asmlinkage void do_double_fault(struct cpu_user_regs *regs) __asm__ __volatile__ ( "hlt" ); } -extern void toggle_guest_mode(struct vcpu *); +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) { @@ -122,13 +128,17 @@ long do_iret(void) struct iret_context iret_saved; struct vcpu *v = current; - if ( unlikely(copy_from_user(&iret_saved, (void *)regs->rsp, sizeof(iret_saved))) || - unlikely(pagetable_get_paddr(v->arch.guest_table_user) == 0) ) - return -EFAULT; + if ( unlikely(copy_from_user(&iret_saved, (void *)regs->rsp, + sizeof(iret_saved))) ) + domain_crash_synchronous(); - /* Returning to user mode. */ - if ( (iret_saved.cs & 0x03) == 3 ) + /* 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 */ diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index a713b89886..6438757d67 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -46,7 +46,10 @@ struct mapcache { struct vcpu_maphash vcpu_maphash[MAX_VIRT_CPUS]; }; -extern void mapcache_init(struct domain *d); +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 { From 5ccd14f4ccd029499f4775c360cf0e32ce128ec1 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 11 Jan 2006 20:03:53 +0100 Subject: [PATCH 23/97] map_domain_page per-vcpu cache still seems broken. Disable while I fix it. Signed-off-by: Keir Fraser --- xen/arch/x86/x86_32/domain_page.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/x86_32/domain_page.c b/xen/arch/x86/x86_32/domain_page.c index f835beee52..0189c737f3 100644 --- a/xen/arch/x86/x86_32/domain_page.c +++ b/xen/arch/x86/x86_32/domain_page.c @@ -40,6 +40,7 @@ void *map_domain_page(unsigned long pfn) cache = &d->arch.mapcache; hashent = &cache->vcpu_maphash[vcpu].hash[MAPHASH_HASHFN(pfn)]; +#if 0 if ( hashent->pfn == pfn ) { idx = hashent->idx; @@ -48,6 +49,7 @@ void *map_domain_page(unsigned long pfn) ASSERT(l1e_get_pfn(cache->l1tab[idx]) == pfn); goto out; } +#endif spin_lock(&cache->lock); @@ -90,7 +92,7 @@ void *map_domain_page(unsigned long pfn) cache->l1tab[idx] = l1e_from_pfn(pfn, __PAGE_HYPERVISOR); - out: +/*out:*/ va = MAPCACHE_VIRT_START + (idx << PAGE_SHIFT); return (void *)va; } From 8a790edb70aa0745d5cb25eceba8ab077a36efe4 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 11 Jan 2006 20:14:27 +0100 Subject: [PATCH 24/97] More do_iret() fixes. We need to take care in restoring EFLAGS that we do not pull in non-zero IOPL, then crash the domain, and then bug out when dom0 gets vcpu context. This could otherwise be triggered by a malicious guest. Signed-off-by: Keir Fraser --- xen/arch/x86/x86_32/traps.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index 6f7fb83640..e9c98d8aa8 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -160,7 +160,7 @@ asmlinkage void do_double_fault(void) static inline void pop_from_guest_stack( void *dst, struct cpu_user_regs *regs, unsigned int bytes) { - if ( unlikely(copy_from_user(dst, (void __user *)regs->esp, bytes)) ) + if ( unlikely(__copy_from_user(dst, (void __user *)regs->esp, bytes)) ) domain_crash_synchronous(); regs->esp += bytes; } @@ -168,19 +168,31 @@ static inline void pop_from_guest_stack( 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). */ pop_from_guest_stack(®s->eax, regs, 4); - /* Pop and restore EFLAGS, CS and EIP. */ - pop_from_guest_stack(®s->eip, regs, 12); + /* Pop and restore CS and EIP. */ + pop_from_guest_stack(®s->eip, regs, 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. + */ + pop_from_guest_stack(&eflags, regs, 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. */ pop_from_guest_stack(®s->esp, regs, 24); } - else if ( RING_0(regs) ) + else if ( unlikely(RING_0(regs)) ) { domain_crash_synchronous(); } @@ -190,10 +202,6 @@ asmlinkage unsigned long do_iret(void) pop_from_guest_stack(®s->esp, regs, 8); } - /* Fixup EFLAGS. */ - regs->eflags &= ~X86_EFLAGS_IOPL; - regs->eflags |= X86_EFLAGS_IF; - /* No longer in NMI context. */ clear_bit(_VCPUF_nmi_masked, ¤t->vcpu_flags); From 2c5ceaba047a86db25cae8768da2df30ff2ddb75 Mon Sep 17 00:00:00 2001 From: "Ian.Campbell@xensource.com" Date: Thu, 12 Jan 2006 10:37:10 +0000 Subject: [PATCH 25/97] Fix x86_64 domU build by conditionalizing NMI support on CONFIG_X86_LOCAL_APIC The NMI handler is not built unless CONFIG_X86_LOCAL_APIC is defined, and CONFIG_X86_LOCAL_APIC requires a dom0 build. Signed-off-by: Ian Campbell --- linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S | 2 ++ .../include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S index 9ecc36e5ca..2fbe90706c 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/entry.S @@ -719,6 +719,7 @@ ENTRY(do_hypervisor_callback) # do_hyperviosr_callback(struct *pt_regs) call evtchn_do_upcall jmp error_exit +#ifdef CONFIG_X86_LOCAL_APIC ENTRY(nmi) zeroentry do_nmi_callback ENTRY(do_nmi_callback) @@ -728,6 +729,7 @@ ENTRY(do_nmi_callback) XEN_BLOCK_EVENTS(%rsi) GET_THREAD_INFO(%rcx) jmp retint_restore_args +#endif ALIGN restore_all_enable_events: diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h index bad118e44c..84186bbe96 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/setup_arch_post.h @@ -44,7 +44,9 @@ static void __init machine_specific_arch_setup(void) (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); } From 8f2651280adf042727332a1369298d8c3ecb5afa Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 12 Jan 2006 12:45:49 +0100 Subject: [PATCH 26/97] Fix cpu_affinity memcpy() (bytes not longs!) add add a better affinity map sanity check to avoid blowing up Xen if no online cpu is included in the map. Signed-off-by: Keir Fraser --- xen/common/dom0_ops.c | 4 ++-- xen/common/schedule.c | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index 42b6c50035..8e7754d84a 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -323,7 +323,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) 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); @@ -501,7 +501,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) 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 --git a/xen/common/schedule.c b/xen/common/schedule.c index 1493cbddac..20da7f9623 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -207,7 +207,10 @@ void vcpu_wake(struct vcpu *v) 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); From c6aed7c358b3f1b0e3226ef021c747a8cebe4518 Mon Sep 17 00:00:00 2001 From: "emellor@leeni.uk.xensource.com" Date: Thu, 12 Jan 2006 13:13:34 +0100 Subject: [PATCH 27/97] 8604:a51fcb5de470 introduced a discrepancy between the declaration and definition of xc_linux_save(). In particular the argument for the suspend pointer to function was null in one and int in the other. On inspection, int seemed to be correct, so I went with this. I also fixed up a few other cosmetic discrepancies. Signed-Off-By: Horms --- tools/libxc/xc_ia64_stubs.c | 3 ++- tools/libxc/xenguest.h | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/libxc/xc_ia64_stubs.c b/tools/libxc/xc_ia64_stubs.c index 2936415be0..a10992be8e 100644 --- a/tools/libxc/xc_ia64_stubs.c +++ b/tools/libxc/xc_ia64_stubs.c @@ -23,7 +23,8 @@ unsigned long xc_ia64_fpsr_default(void) } 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; diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h index c0eb5bcdd3..5cad964f80 100644 --- a/tools/libxc/xenguest.h +++ b/tools/libxc/xenguest.h @@ -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)); /** From 71e8ec899aed517e21f359d6f06ab86244179479 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 12 Jan 2006 14:27:20 +0100 Subject: [PATCH 28/97] Adds a check to vtpm_manager and vtpm Makefiles to verify openssl and gmp dev files are installed. If files are missing, Makefile exits with a message indicating that these tools will not be built, rather than an error, which prevents Xen from building. Signed-off-by: Vinnie Scarlata --- tools/vtpm/Makefile | 13 +++++++++++-- tools/vtpm/Rules.mk | 2 ++ tools/vtpm_manager/Makefile | 11 ++++++++--- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/tools/vtpm/Makefile b/tools/vtpm/Makefile index a1c8aa6438..8224a9d304 100644 --- a/tools/vtpm/Makefile +++ b/tools/vtpm/Makefile @@ -11,6 +11,8 @@ VTPM_DIR = vtpm # Emulator tarball name TPM_EMULATOR_TARFILE = tpm_emulator-0.2b.tar.gz +GMP_HEADER = /usr/include/gmp.h + all: build build: $(TPM_EMULATOR_DIR) $(VTPM_DIR) build_sub @@ -55,5 +57,12 @@ $(VTPM_DIR): $(TPM_EMULATOR_TARFILE) 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 --git a/tools/vtpm/Rules.mk b/tools/vtpm/Rules.mk index e840df141f..93b84cdaa5 100644 --- a/tools/vtpm/Rules.mk +++ b/tools/vtpm/Rules.mk @@ -33,5 +33,7 @@ $(OBJS): $(SRCS) -include $(DEP_FILES) +BUILD_EMULATOR = n + # Make sure these are just rules .PHONY : all build install clean diff --git a/tools/vtpm_manager/Makefile b/tools/vtpm_manager/Makefile index dddfa5160b..16825a2279 100644 --- a/tools/vtpm_manager/Makefile +++ b/tools/vtpm_manager/Makefile @@ -4,13 +4,18 @@ XEN_ROOT = ../.. 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 \ From 6889a045da2efd0c17c8fb1270f69f408f9fb24f Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 12 Jan 2006 14:27:55 +0100 Subject: [PATCH 29/97] fixes some compiler warnings due to new types used in the xenbus. Signed-off-by: Stefan Berger --- linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c index 4a39527711..60f0c50d1c 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c @@ -89,7 +89,7 @@ static int tpmback_probe(struct xenbus_device *dev, 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 @@ static void backend_changed(struct xenbus_watch *watch, = 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; @@ -177,7 +177,7 @@ static void frontend_changed(struct xenbus_device *dev, break; case XenbusStateClosing: - xenbus_switch_state(dev, NULL, XenbusStateClosing); + xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing); break; case XenbusStateClosed: From 6f7a043a6a492700ddb3ccadd3757939adf89123 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 12 Jan 2006 15:43:22 +0100 Subject: [PATCH 30/97] Re-enable per-cpu cache on map_domain_page(). Fix the offending caller that broke the vcpu cache (writable pagetable code kept a mapping outstanding until flush, which could occur on a different vcpu). Signed-off-by: Keir Fraser --- xen/arch/x86/mm.c | 18 ++++++++---------- xen/arch/x86/x86_32/domain_page.c | 4 +--- xen/include/asm-x86/mm.h | 7 ++----- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index a9dba3ef66..ad0ce9d2e3 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2999,7 +2999,7 @@ void ptwr_flush(struct domain *d, const int which) 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. */ @@ -3017,13 +3017,13 @@ void ptwr_flush(struct domain *d, const int which) /* 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, trawl l1e_get_intpte(pte)); /* * STEP 2. Validate any modified PTEs. */ - pl1e = d->arch.ptwr[which].pl1e; + 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); @@ -3206,7 +3206,7 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr, { 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; @@ -3343,11 +3343,10 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr, } /* 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, @@ -3356,7 +3355,6 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr, 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 --git a/xen/arch/x86/x86_32/domain_page.c b/xen/arch/x86/x86_32/domain_page.c index 0189c737f3..f835beee52 100644 --- a/xen/arch/x86/x86_32/domain_page.c +++ b/xen/arch/x86/x86_32/domain_page.c @@ -40,7 +40,6 @@ void *map_domain_page(unsigned long pfn) cache = &d->arch.mapcache; hashent = &cache->vcpu_maphash[vcpu].hash[MAPHASH_HASHFN(pfn)]; -#if 0 if ( hashent->pfn == pfn ) { idx = hashent->idx; @@ -49,7 +48,6 @@ void *map_domain_page(unsigned long pfn) ASSERT(l1e_get_pfn(cache->l1tab[idx]) == pfn); goto out; } -#endif spin_lock(&cache->lock); @@ -92,7 +90,7 @@ void *map_domain_page(unsigned long pfn) cache->l1tab[idx] = l1e_from_pfn(pfn, __PAGE_HYPERVISOR); -/*out:*/ + out: va = MAPCACHE_VIRT_START + (idx << PAGE_SHIFT); return (void *)va; } diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 9ec0e16e73..2e0937ea2d 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -309,16 +309,13 @@ struct ptwr_info { 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; }; From 8a0da1c3344769e55dc12423b116c97fe4860356 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 12 Jan 2006 15:44:44 +0100 Subject: [PATCH 31/97] Quieten debug printing on memory_op hypercall. Don't warn about disallowed multipage allocation attempts. Signed-off-by: Keir Fraser --- xen/common/memory.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/xen/common/memory.c b/xen/common/memory.c index 847fcbb0cc..ddad691d29 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -38,10 +38,7 @@ increase_reservation( 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++ ) { From b1f016182201b6af23d8491f5a26e33ab4c45825 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 12 Jan 2006 15:59:45 +0100 Subject: [PATCH 32/97] More debug print cleanups. Signed-off-by: Keir Fraser --- xen/arch/x86/mm.c | 2 +- xen/arch/x86/traps.c | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index ad0ce9d2e3..1b4afa2fa2 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -3017,7 +3017,7 @@ void ptwr_flush(struct domain *d, const int which) /* 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, trawl l1e_get_intpte(pte)); + PTWR_PRINT_WHICH, ptep, l1e_get_intpte(pte)); /* * STEP 2. Validate any modified PTEs. diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 9929722fab..0213a255bc 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -963,16 +963,26 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) 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 ( (regs->ecx != MSR_EFER) || + (rdmsr_user(regs->ecx, l, h) != 0) || + (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; From 9baabcabfe6d2ea9f0c7e3a1ab0956322d120943 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 12 Jan 2006 16:10:12 +0100 Subject: [PATCH 33/97] Update copyright on domain_page implementation. It's been rewritten from scratch a couple of times now and it's safe to assert that the original Linux heritage was deleted long ago. Signed-off-by: Keir Fraser --- xen/arch/x86/x86_32/domain_page.c | 11 +++-------- xen/include/xen/domain_page.h | 2 ++ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/xen/arch/x86/x86_32/domain_page.c b/xen/arch/x86/x86_32/domain_page.c index f835beee52..222e813693 100644 --- a/xen/arch/x86/x86_32/domain_page.c +++ b/xen/arch/x86/x86_32/domain_page.c @@ -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@suse.de - * Gerhard Wichert, Siemens AG, Gerhard.Wichert@pdb.siemens.de * - * Copyright (C) 1999 Ingo Molnar + * Allow temporary mapping of domain pages. + * + * Copyright (c) 2003-2006, Keir Fraser */ #include diff --git a/xen/include/xen/domain_page.h b/xen/include/xen/domain_page.h index c4729b0ea9..b73011216b 100644 --- a/xen/include/xen/domain_page.h +++ b/xen/include/xen/domain_page.h @@ -2,6 +2,8 @@ * domain_page.h * * Allow temporary mapping of domain page frames into Xen space. + * + * Copyright (c) 2003-2006, Keir Fraser */ #ifndef __XEN_DOMAIN_PAGE_H__ From 9b7916cc5e36941477a34c822695474e36b361e7 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 12 Jan 2006 21:48:51 +0100 Subject: [PATCH 34/97] Fix compile warning about uninitialised vars. Signed-off-by: Keir Fraser --- xen/arch/x86/traps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 0213a255bc..93b11e36c1 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -965,8 +965,8 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) if ( !IS_PRIV(v->domain) ) { u32 l, h; - if ( (regs->ecx != MSR_EFER) || - (rdmsr_user(regs->ecx, l, h) != 0) || + 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", From 4207635014c977748811f86871444f10819a6b07 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 12 Jan 2006 23:25:02 +0100 Subject: [PATCH 35/97] Simplify vcpu_sleep_sync() and sched_adjdom(). Their interaction with the scheduler locks was unnecessarily complicated. Signed-off-by: Keir Fraser --- xen/common/schedule.c | 85 +++++++++++++------------------------------ 1 file changed, 26 insertions(+), 59 deletions(-) diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 20da7f9623..6f10c3d0f5 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -171,20 +171,13 @@ void vcpu_sleep_nosync(struct vcpu *v) spin_unlock_irqrestore(&schedule_data[v->processor].schedule_lock, 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); @@ -314,68 +307,42 @@ long sched_adjdom(struct sched_adjdom_cmd *cmd) { 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)<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 ) + spin_lock_irq(&schedule_data[smp_processor_id()].schedule_lock); + 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 ) + spin_unlock_irq(&schedule_data[smp_processor_id()].schedule_lock); + else + vcpu_unpause(v); + } + put_domain(d); + return 0; } From 8a3652cb7e5d0a67a6bf08bf07efcbc0f4e2c7d6 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 12 Jan 2006 23:39:14 +0100 Subject: [PATCH 36/97] Rename ac_timer_* interfaces -> timer_*. The ac_ is meaningless and unnecessary. Rename rem_timer -> stop_timer. Signed-off-by: Keir Fraser --- xen/arch/ia64/vmx/vlsapic.c | 18 +- xen/arch/ia64/xen/xenmisc.c | 2 +- xen/arch/ia64/xen/xensetup.c | 4 +- xen/arch/ia64/xen/xentime.c | 4 +- xen/arch/x86/apic.c | 4 +- xen/arch/x86/nmi.c | 8 +- xen/arch/x86/setup.c | 2 +- xen/arch/x86/time.c | 24 +-- xen/arch/x86/vmx.c | 12 +- xen/arch/x86/vmx_intercept.c | 14 +- xen/arch/x86/vmx_io.c | 2 +- xen/arch/x86/vmx_vlapic.c | 8 +- xen/arch/x86/vmx_vmcs.c | 2 +- xen/common/ac_timer.c | 286 ------------------------------- xen/common/sched_bvt.c | 22 +-- xen/common/sched_sedf.c | 2 +- xen/common/schedule.c | 22 +-- xen/common/xmalloc.c | 2 +- xen/drivers/char/ns16550.c | 8 +- xen/include/asm-ia64/config.h | 2 +- xen/include/asm-ia64/vtm.h | 4 +- xen/include/asm-x86/vmx_vlapic.h | 4 +- xen/include/asm-x86/vmx_vmcs.h | 2 +- xen/include/asm-x86/vmx_vpit.h | 4 +- xen/include/xen/ac_timer.h | 81 --------- xen/include/xen/perfc_defn.h | 2 +- xen/include/xen/sched-if.h | 2 +- xen/include/xen/sched.h | 4 +- xen/include/xen/softirq.h | 2 +- 29 files changed, 93 insertions(+), 460 deletions(-) delete mode 100644 xen/common/ac_timer.c delete mode 100644 xen/include/xen/ac_timer.h diff --git a/xen/arch/ia64/vmx/vlsapic.c b/xen/arch/ia64/vmx/vlsapic.c index bbc3c49ecc..93dabc168b 100644 --- a/xen/arch/ia64/vmx/vlsapic.c +++ b/xen/arch/ia64/vmx/vlsapic.c @@ -119,7 +119,7 @@ void vtm_init(VCPU *vcpu) 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 @@ void vtm_set_itv(VCPU *vcpu) 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 @@ void vtm_interruption_update(VCPU *vcpu, vtime_t* vtm) 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 @@ void vtm_interruption_update(VCPU *vcpu, vtime_t* vtm) /* 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 --git a/xen/arch/ia64/xen/xenmisc.c b/xen/arch/ia64/xen/xenmisc.c index 504003ca6f..eaddbee41c 100644 --- a/xen/arch/ia64/xen/xenmisc.c +++ b/xen/arch/ia64/xen/xenmisc.c @@ -75,7 +75,7 @@ struct pt_regs *guest_cpu_user_regs(void) { return vcpu_regs(current); } void raise_actimer_softirq(void) { - raise_softirq(AC_TIMER_SOFTIRQ); + raise_softirq(TIMER_SOFTIRQ); } unsigned long diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index 7f40a3d792..7738786a1b 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -291,8 +291,8 @@ printk("About to call scheduler_init()\n"); 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(); diff --git a/xen/arch/ia64/xen/xentime.c b/xen/arch/ia64/xen/xentime.c index 72248b2118..f407509f3c 100644 --- a/xen/arch/ia64/xen/xentime.c +++ b/xen/arch/ia64/xen/xentime.c @@ -196,7 +196,7 @@ xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) //#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 @@ int __init init_xen_time() 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 --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c index 1a3d5f591e..7eb6000b37 100644 --- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -870,7 +870,7 @@ void enable_APIC_timer(void) * 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 @@ void smp_apic_timer_interrupt(struct cpu_user_regs * regs) { ack_APIC_irq(); perfc_incrc(apic_timer); - raise_softirq(AC_TIMER_SOFTIRQ); + raise_softirq(TIMER_SOFTIRQ); } /* diff --git a/xen/arch/x86/nmi.c b/xen/arch/x86/nmi.c index b63036ac54..6c969701a3 100644 --- a/xen/arch/x86/nmi.c +++ b/xen/arch/x86/nmi.c @@ -34,7 +34,7 @@ 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 +132,7 @@ static void nmi_timer_fn(void *unused) { 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) @@ -345,7 +345,7 @@ void __pminit setup_apic_nmi_watchdog(void) lapic_nmi_owner = LAPIC_NMI_WATCHDOG; nmi_active = 1; - init_ac_timer(&nmi_timer[cpu], nmi_timer_fn, NULL, cpu); + init_timer(&nmi_timer[cpu], nmi_timer_fn, NULL, cpu); } static unsigned int @@ -383,7 +383,7 @@ void watchdog_enable(void) * during setup because the timer infrastructure is not available. */ for_each_online_cpu ( cpu ) - set_ac_timer(&nmi_timer[cpu], NOW()); + set_timer(&nmi_timer[cpu], NOW()); } spin_unlock_irqrestore(&watchdog_lock, flags); diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 3abeb9d992..a1e51f45ec 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -423,7 +423,7 @@ void __init __start_xen(multiboot_info_t *mbi) trap_init(); - ac_timer_init(); + timer_init(); early_time_init(); diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index 7e7c40fca1..1bd15c6702 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -56,7 +56,7 @@ struct cpu_time { 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 @@ void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs) /* 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 @@ static void init_pit(void) /* 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 @@ static void hpet_overflow(void *unused) 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 @@ static int init_hpet(void) (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 @@ int use_cyclone; /* 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 @@ static void cyclone_overflow(void *unused) 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 @@ static int init_cyclone(void) 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 @@ static void local_time_calibration(void *unused) 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 @@ void init_percpu_time(void) 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 --git a/xen/arch/x86/vmx.c b/xen/arch/x86/vmx.c index 2dd4925947..f6a4384816 100644 --- a/xen/arch/x86/vmx.c +++ b/xen/arch/x86/vmx.c @@ -105,13 +105,13 @@ void vmx_relinquish_resources(struct vcpu *v) 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); + if ( active_timer(&(vpit->pit_timer)) ) + stop_timer(&vpit->pit_timer); + if ( active_timer(&v->arch.arch_vmx.hlt_timer) ) + stop_timer(&v->arch.arch_vmx.hlt_timer); if ( vmx_apic_support(v->domain) && (VLAPIC(v) != NULL) ) { - rem_ac_timer(&VLAPIC(v)->vlapic_timer); + stop_timer(&VLAPIC(v)->vlapic_timer); xfree(VLAPIC(v)); } } @@ -1600,7 +1600,7 @@ void vmx_vmexit_do_hlt(void) 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 --git a/xen/arch/x86/vmx_intercept.c b/xen/arch/x86/vmx_intercept.c index b4633b6c35..419960842c 100644 --- a/xen/arch/x86/vmx_intercept.c +++ b/xen/arch/x86/vmx_intercept.c @@ -356,19 +356,19 @@ static void pit_timer_fn(void *data) 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 @@ void vmx_hooks_assist(struct vcpu *v) /* 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 @@ void vmx_hooks_assist(struct vcpu *v) } 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 --git a/xen/arch/x86/vmx_io.c b/xen/arch/x86/vmx_io.c index 955763f125..c979a8d741 100644 --- a/xen/arch/x86/vmx_io.c +++ b/xen/arch/x86/vmx_io.c @@ -819,7 +819,7 @@ interrupt_post_injection(struct vcpu * v, int vector, int type) 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 --git a/xen/arch/x86/vmx_vlapic.c b/xen/arch/x86/vmx_vlapic.c index 82b167b117..d487f9739e 100644 --- a/xen/arch/x86/vmx_vlapic.c +++ b/xen/arch/x86/vmx_vlapic.c @@ -391,7 +391,7 @@ static void vlapic_begin_timer(struct vlapic *vlapic) (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 @@ static void vlapic_write(struct vcpu *v, unsigned long address, 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 @@ void vlapic_timer_fn(void *data) 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 @@ static int vlapic_reset(struct vlapic *vlapic) 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 --git a/xen/arch/x86/vmx_vmcs.c b/xen/arch/x86/vmx_vmcs.c index f10124f99d..9b7c9d41d2 100644 --- a/xen/arch/x86/vmx_vmcs.c +++ b/xen/arch/x86/vmx_vmcs.c @@ -341,7 +341,7 @@ static void vmx_do_launch(struct vcpu *v) 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 --git a/xen/common/ac_timer.c b/xen/common/ac_timer.c deleted file mode 100644 index 1bf443ac46..0000000000 --- a/xen/common/ac_timer.c +++ /dev/null @@ -1,286 +0,0 @@ -/****************************************************************************** - * ac_timer.c - * - * Copyright (c) 2002-2003 Rolf Neugebauer - * Copyright (c) 2002-2005 K A Fraser - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * 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 --git a/xen/common/sched_bvt.c b/xen/common/sched_bvt.c index 721e44338b..418909837b 100644 --- a/xen/common/sched_bvt.c +++ b/xen/common/sched_bvt.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -45,9 +45,9 @@ struct bvt_dom_info 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]; }; @@ -111,7 +111,7 @@ static void warp_timer_fn(void *data) cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ); } - set_ac_timer(&inf->unwarp_timer, NOW() + inf->warpu); + set_timer(&inf->unwarp_timer, NOW() + inf->warpu); spin_unlock_irq(&schedule_data[cpu].schedule_lock); } @@ -214,8 +214,8 @@ static void bvt_add_task(struct vcpu *v) 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); + init_timer(&inf->warp_timer, warp_timer_fn, inf, v->processor); + init_timer(&inf->unwarp_timer, unwarp_timer_fn, inf, v->processor); } einf->vcpu = v; @@ -271,7 +271,7 @@ static void bvt_wake(struct vcpu *v) 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); } @@ -355,10 +355,10 @@ static int bvt_adjdom( 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 +405,7 @@ static struct task_slice bvt_do_schedule(s_time_t now) 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 +455,7 @@ static struct task_slice bvt_do_schedule(s_time_t now) } 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 --git a/xen/common/sched_sedf.c b/xen/common/sched_sedf.c index f203380643..45fdac3073 100644 --- a/xen/common/sched_sedf.c +++ b/xen/common/sched_sedf.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 6f10c3d0f5..7d80ae78c4 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -71,7 +71,7 @@ static struct scheduler ops; : (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]; void free_domain(struct domain *d) { @@ -141,7 +141,7 @@ struct domain *alloc_domain(void) 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 +156,7 @@ void sched_add_domain(struct vcpu *v) void sched_rem_domain(struct vcpu *v) { - rem_ac_timer(&v->timer); + stop_timer(&v->timer); SCHED_OP(rem_task, v); TRACE_2D(TRC_SCHED_DOM_REM, v->domain->domain_id, v->vcpu_id); } @@ -278,9 +278,9 @@ long do_set_timer_op(s_time_t timeout) 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; } @@ -365,7 +365,7 @@ static void __enter_scheduler(void) 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; @@ -379,7 +379,7 @@ static void __enter_scheduler(void) 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) ) { @@ -475,7 +475,7 @@ static void t_timer_fn(void *unused) 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 */ @@ -497,8 +497,8 @@ void __init scheduler_init(void) 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 --git a/xen/common/xmalloc.c b/xen/common/xmalloc.c index 4d74baee70..24e4b6b2fe 100644 --- a/xen/common/xmalloc.c +++ b/xen/common/xmalloc.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c index 8ef838d3db..9476f473a2 100644 --- a/xen/drivers/char/ns16550.c +++ b/xen/drivers/char/ns16550.c @@ -33,7 +33,7 @@ static struct ns16550 { /* 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 @@ static void ns16550_poll(void *data) 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 @@ static void ns16550_init_postirq(struct serial_port *port) 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 --git a/xen/include/asm-ia64/config.h b/xen/include/asm-ia64/config.h index f0fac09eb1..5b7896aa6c 100644 --- a/xen/include/asm-ia64/config.h +++ b/xen/include/asm-ia64/config.h @@ -156,7 +156,7 @@ struct page; #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 diff --git a/xen/include/asm-ia64/vtm.h b/xen/include/asm-ia64/vtm.h index 92564b9b6c..a89d9c2b21 100644 --- a/xen/include/asm-ia64/vtm.h +++ b/xen/include/asm-ia64/vtm.h @@ -23,7 +23,7 @@ #ifndef _VTM_H_ #define _VTM_H_ -#include +#include #include #define MAX_JUMP_STEP (5000) /* 500ms, max jump step */ @@ -46,7 +46,7 @@ typedef struct vtime { 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 --git a/xen/include/asm-x86/vmx_vlapic.h b/xen/include/asm-x86/vmx_vlapic.h index da280d1d0b..2527800b60 100644 --- a/xen/include/asm-x86/vmx_vlapic.h +++ b/xen/include/asm-x86/vmx_vlapic.h @@ -187,7 +187,7 @@ struct vlapic 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_set_irq(struct vlapic *t, uint8_t vec, uint8_t trig) 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 --git a/xen/include/asm-x86/vmx_vmcs.h b/xen/include/asm-x86/vmx_vmcs.h index 62a2c91748..81b9fb6009 100644 --- a/xen/include/asm-x86/vmx_vmcs.h +++ b/xen/include/asm-x86/vmx_vmcs.h @@ -100,7 +100,7 @@ struct arch_vmx_struct { 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 --git a/xen/include/asm-x86/vmx_vpit.h b/xen/include/asm-x86/vmx_vpit.h index 3fc86a5adf..b47e6d6512 100644 --- a/xen/include/asm-x86/vmx_vpit.h +++ b/xen/include/asm-x86/vmx_vpit.h @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include @@ -23,7 +23,7 @@ struct vmx_virpit { 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 --git a/xen/include/xen/ac_timer.h b/xen/include/xen/ac_timer.h deleted file mode 100644 index bd5131d6e3..0000000000 --- a/xen/include/xen/ac_timer.h +++ /dev/null @@ -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 -#include -#include - -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: - */ diff --git a/xen/include/xen/perfc_defn.h b/xen/include/xen/perfc_defn.h index 1e6820acad..60d123689a 100644 --- a/xen/include/xen/perfc_defn.h +++ b/xen/include/xen/perfc_defn.h @@ -32,7 +32,7 @@ PERFCOUNTER_CPU(ipis, "#IPIs") 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 --git a/xen/include/xen/sched-if.h b/xen/include/xen/sched-if.h index 979cec874a..7b94338391 100644 --- a/xen/include/xen/sched-if.h +++ b/xen/include/xen/sched-if.h @@ -16,7 +16,7 @@ struct schedule_data { 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 */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 7d9dee679b..df7611a70b 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -63,7 +63,7 @@ struct vcpu 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 */ diff --git a/xen/include/xen/softirq.h b/xen/include/xen/softirq.h index 87d6c807ee..9293b3168e 100644 --- a/xen/include/xen/softirq.h +++ b/xen/include/xen/softirq.h @@ -2,7 +2,7 @@ #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 From c5c75c292628864e2f22c4186f8f16da10fbe6da Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 13 Jan 2006 00:16:07 +0100 Subject: [PATCH 37/97] Add missing renamed files. Oops. Signed-off-by: Keir Fraser --- xen/common/timer.c | 288 ++++++++++++++++++++++++++++++++++++++++ xen/include/xen/timer.h | 81 +++++++++++ 2 files changed, 369 insertions(+) create mode 100644 xen/common/timer.c create mode 100644 xen/include/xen/timer.h diff --git a/xen/common/timer.c b/xen/common/timer.c new file mode 100644 index 0000000000..336b0a15d1 --- /dev/null +++ b/xen/common/timer.c @@ -0,0 +1,288 @@ +/****************************************************************************** + * timer.c + * + * Copyright (c) 2002-2003 Rolf Neugebauer + * Copyright (c) 2002-2005 K A Fraser + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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; +} __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); + ASSERT(timer != NULL); + if ( active_timer(timer) ) + __stop_timer(timer); + timer->expires = expires; + __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); + ASSERT(timer != NULL); + if ( active_timer(timer) ) + __stop_timer(timer); + spin_unlock_irqrestore(&timers[cpu].lock, flags); +} + + +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); + + fn = t->function; + data = t->data; + + if ( fn != NULL ) + { + 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; + } + } + 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 --git a/xen/include/xen/timer.h b/xen/include/xen/timer.h new file mode 100644 index 0000000000..c89e98c346 --- /dev/null +++ b/xen/include/xen/timer.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * timer.h + * + * Copyright (c) 2002-2003 Rolf Neugebauer + * Copyright (c) 2002-2005 K A Fraser + */ + +#ifndef _TIMER_H_ +#define _TIMER_H_ + +#include +#include +#include + +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; +}; + +/* + * 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); + +/* + * 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: + */ From cc00657854df4e868598b6447ea5599798604da9 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 13 Jan 2006 01:03:44 +0100 Subject: [PATCH 38/97] Add a new timer operation kill_timer(). Effectively the 'opposite' of init_timer(), it marks the end of a timer's lifetime. After this call the timer will not be pending, its callback handler will not be running, and future calls to set_timer() will silently fail. Signed-off-by: Keir Fraser --- xen/arch/x86/vmx.c | 8 ++--- xen/common/sched_bvt.c | 66 +++++++++++++++++++++++------------------ xen/common/schedule.c | 4 +-- xen/common/timer.c | 38 ++++++++++++++++++------ xen/include/xen/timer.h | 9 ++++++ 5 files changed, 80 insertions(+), 45 deletions(-) diff --git a/xen/arch/x86/vmx.c b/xen/arch/x86/vmx.c index f6a4384816..6d6fa51764 100644 --- a/xen/arch/x86/vmx.c +++ b/xen/arch/x86/vmx.c @@ -105,13 +105,11 @@ void vmx_relinquish_resources(struct vcpu *v) destroy_vmcs(&v->arch.arch_vmx); free_monitor_pagetable(v); vpit = &v->domain->arch.vmx_platform.vmx_pit; - if ( active_timer(&(vpit->pit_timer)) ) - stop_timer(&vpit->pit_timer); - if ( active_timer(&v->arch.arch_vmx.hlt_timer) ) - stop_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) ) { - stop_timer(&VLAPIC(v)->vlapic_timer); + kill_timer(&VLAPIC(v)->vlapic_timer); xfree(VLAPIC(v)); } } diff --git a/xen/common/sched_bvt.c b/xen/common/sched_bvt.c index 418909837b..0a0f30d1a3 100644 --- a/xen/common/sched_bvt.c +++ b/xen/common/sched_bvt.c @@ -45,9 +45,9 @@ struct bvt_dom_info limits*/ s32 warp_value; /* virtual time warp */ s_time_t warpl; /* warp limit */ - struct timer warp_timer; /* deals with warpl */ + struct timer warp_timer; /* deals with warpl */ s_time_t warpu; /* unwarp time requirement */ - struct timer unwarp_timer; /* deals with warpu */ + struct timer unwarp_timer; /* deals with warpu */ struct bvt_vcpu_info vcpu_inf[MAX_VIRT_CPUS]; }; @@ -168,6 +168,7 @@ static inline u32 calc_evt(struct vcpu *d, u32 avt) 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 @@ static int bvt_alloc_task(struct vcpu *v) memset(d->sched_priv, 0, sizeof(struct bvt_dom_info)); } - v->sched_priv = &BVT_INFO(d)->vcpu_inf[v->vcpu_id]; + inf = BVT_INFO(d); - BVT_INFO(d)->vcpu_inf[v->vcpu_id].inf = BVT_INFO(d); - BVT_INFO(d)->vcpu_inf[v->vcpu_id].vcpu = v; + v->sched_priv = &inf->vcpu_inf[v->vcpu_id]; - 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->vcpu_inf[v->vcpu_id].inf = BVT_INFO(d); + inf->vcpu_inf[v->vcpu_id].vcpu = v; if ( v->vcpu_id == 0 ) { @@ -218,7 +199,28 @@ static void bvt_add_task(struct vcpu *v) init_timer(&inf->unwarp_timer, unwarp_timer_fn, inf, v->processor); } - einf->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; + } if ( is_idle_vcpu(v) ) { @@ -305,8 +307,14 @@ static int bvt_set_affinity(struct vcpu *v, cpumask_t *affinity) */ 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. */ diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 7d80ae78c4..a971d8fae1 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -156,7 +156,7 @@ void sched_add_domain(struct vcpu *v) void sched_rem_domain(struct vcpu *v) { - stop_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); } @@ -462,7 +462,7 @@ static void s_timer_fn(void *unused) /* 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++; diff --git a/xen/common/timer.c b/xen/common/timer.c index 336b0a15d1..55f39bfa98 100644 --- a/xen/common/timer.c +++ b/xen/common/timer.c @@ -29,6 +29,7 @@ struct timers { spinlock_t lock; struct timer **heap; + struct timer *running; } __cacheline_aligned; struct timers timers[NR_CPUS]; @@ -167,11 +168,11 @@ void set_timer(struct timer *timer, s_time_t expires) unsigned long flags; spin_lock_irqsave(&timers[cpu].lock, flags); - ASSERT(timer != NULL); if ( active_timer(timer) ) __stop_timer(timer); timer->expires = expires; - __add_timer(timer); + if ( likely(!timer->killed) ) + __add_timer(timer); spin_unlock_irqrestore(&timers[cpu].lock, flags); } @@ -182,13 +183,31 @@ void stop_timer(struct timer *timer) unsigned long flags; spin_lock_irqsave(&timers[cpu].lock, flags); - ASSERT(timer != NULL); 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(); @@ -208,19 +227,20 @@ static void timer_softirq_action(void) { remove_entry(heap, t); + timers[cpu].running = t; + fn = t->function; data = t->data; - if ( fn != NULL ) - { - spin_unlock_irq(&timers[cpu].lock); - (*fn)(data); - spin_lock_irq(&timers[cpu].lock); - } + 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) ); diff --git a/xen/include/xen/timer.h b/xen/include/xen/timer.h index c89e98c346..f53a7ed35f 100644 --- a/xen/include/xen/timer.h +++ b/xen/include/xen/timer.h @@ -22,6 +22,8 @@ struct timer { void *data; /* Timer-heap offset. */ unsigned int heap_offset; + /* Has this timer been killed (cannot be activated)? */ + int killed; }; /* @@ -63,6 +65,13 @@ extern void set_timer(struct timer *timer, s_time_t expires); */ 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. */ From 4c1b84163ec5c7f7fdb02290aa686a456cc8ec72 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 13 Jan 2006 11:38:33 +0100 Subject: [PATCH 39/97] Fix non-debug build. Signed-off-by: Keir Fraser --- xen/common/sched_bvt.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/xen/common/sched_bvt.c b/xen/common/sched_bvt.c index 0a0f30d1a3..df329dd982 100644 --- a/xen/common/sched_bvt.c +++ b/xen/common/sched_bvt.c @@ -207,12 +207,8 @@ static int bvt_alloc_task(struct vcpu *v) */ 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 ) { From dd38458519384dff33252ae76889e08d5dbe7a18 Mon Sep 17 00:00:00 2001 From: "Ian.Campbell@xensource.com" Date: Fri, 13 Jan 2006 11:04:04 +0000 Subject: [PATCH 40/97] Fix x86/32 do_iret implementation, fixes VM86 mode. Do not clobber a freshly restored esp when performing an iret. Signed-off-by: Keir Fraser Signed-off-by: Ian Campbell --- xen/arch/x86/x86_32/traps.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index e9c98d8aa8..95b69a14bd 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -157,14 +157,6 @@ asmlinkage void do_double_fault(void) __asm__ __volatile__ ( "hlt" ); } -static inline void pop_from_guest_stack( - void *dst, struct cpu_user_regs *regs, unsigned int bytes) -{ - if ( unlikely(__copy_from_user(dst, (void __user *)regs->esp, bytes)) ) - domain_crash_synchronous(); - regs->esp += bytes; -} - asmlinkage unsigned long do_iret(void) { struct cpu_user_regs *regs = guest_cpu_user_regs(); @@ -175,22 +167,29 @@ asmlinkage unsigned long do_iret(void) domain_crash_synchronous(); /* Pop and restore EAX (clobbered by hypercall). */ - pop_from_guest_stack(®s->eax, regs, 4); + if ( unlikely(__copy_from_user(®s->eax, (void __user *)regs->esp, 4)) ) + domain_crash_synchronous(); + regs->esp += 4; /* Pop and restore CS and EIP. */ - pop_from_guest_stack(®s->eip, regs, 8); + 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. */ - pop_from_guest_stack(&eflags, regs, 4); + 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. */ - pop_from_guest_stack(®s->esp, regs, 24); + if ( __copy_from_user(®s->esp, (void __user *)regs->esp, 24) ) + domain_crash_synchronous(); } else if ( unlikely(RING_0(regs)) ) { @@ -199,7 +198,8 @@ asmlinkage unsigned long do_iret(void) else if ( !RING_1(regs) ) { /* Return to ring 2/3: pop and restore ESP and SS. */ - pop_from_guest_stack(®s->esp, regs, 8); + if ( __copy_from_user(®s->esp, (void __user *)regs->esp, 8) ) + domain_crash_synchronous(); } /* No longer in NMI context. */ From 8ffaf9c238e61a5e435cf648f86f8ece042b8db9 Mon Sep 17 00:00:00 2001 From: "Ian.Campbell@xensource.com" Date: Fri, 13 Jan 2006 14:09:39 +0000 Subject: [PATCH 41/97] Ensure watchdog remains disabled unless enabled on the command line. Bail out of setup_apic_nmi_watchdog() early if watchdog is not enabled. Is the watchdog is disabled then increment watchdog_disable_count to prevent it ever becoming enabled. Unconditionally call setup_apic_nmi_watchdog() from setup_local_APIC() so that the above is guaranteed to have occurred before the first call of watchdog_enable(). Signed-off-by: Ian Campbell --- xen/arch/x86/apic.c | 3 +-- xen/arch/x86/nmi.c | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c index 7eb6000b37..f1a5f0b96d 100644 --- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -451,8 +451,7 @@ void __init setup_local_APIC (void) printk("No ESR for 82489DX.\n"); } - if (nmi_watchdog == NMI_LOCAL_APIC) - setup_apic_nmi_watchdog(); + setup_apic_nmi_watchdog(); } /* diff --git a/xen/arch/x86/nmi.c b/xen/arch/x86/nmi.c index 6c969701a3..d2ccd4e7e4 100644 --- a/xen/arch/x86/nmi.c +++ b/xen/arch/x86/nmi.c @@ -31,6 +31,10 @@ #include unsigned int nmi_watchdog = NMI_NONE; +static spinlock_t watchdog_lock = SPIN_LOCK_UNLOCKED; +static unsigned int watchdog_disable_count = 1; +static unsigned int watchdog_on; + 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; @@ -310,8 +314,16 @@ void __pminit setup_apic_nmi_watchdog(void) { int cpu = smp_processor_id(); - if (!nmi_watchdog) - return; + if ( nmi_active < 0 ) + return; + + if ( !nmi_watchdog ) + { + /* Force the watchdog to always be disabled. */ + watchdog_disable_count++; + nmi_active = -1; + return; + } switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: @@ -352,10 +364,6 @@ 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; - void watchdog_disable(void) { unsigned long flags; From 723bbd528ff0bcfb7c8dda05486aa69fbf0080f3 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 13 Jan 2006 15:22:36 +0100 Subject: [PATCH 42/97] Fix xenbus_cleanup_devices() to cleanup proper subdirectories of the deleted path, not merely paths mwith matching prefixes. Signed-off-by: Keir Fraser --- .../drivers/xen/xenbus/xenbus_probe.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c index 7b267836da..6fbe1e3649 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c @@ -470,12 +470,17 @@ static int cleanup_dev(struct device *dev, void *data) 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) From a3b63a0ab6effb3bae896659d6142a31ecb5c473 Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Fri, 13 Jan 2006 08:52:05 -0600 Subject: [PATCH 43/97] Enable warnings and fix a few one (those which occur in almost every file). The next step is to fix warnings one by one. Signed-off-by: Tristan Gingold # User tristan.gingold@bull.net --- xen/arch/ia64/Rules.mk | 4 ++-- xen/arch/ia64/linux-xen/sal.c | 1 + xen/arch/ia64/xen/sn_console.c | 1 + xen/include/asm-ia64/config.h | 19 ++++++------------- xen/include/asm-ia64/vmmu.h | 4 ++-- 5 files changed, 12 insertions(+), 17 deletions(-) diff --git a/xen/arch/ia64/Rules.mk b/xen/arch/ia64/Rules.mk index 9d02b6ef16..2a879dd2d1 100644 --- a/xen/arch/ia64/Rules.mk +++ b/xen/arch/ia64/Rules.mk @@ -23,10 +23,10 @@ CFLAGS += -I$(BASEDIR)/include/asm-ia64 -I$(BASEDIR)/include/asm-ia64/linux \ -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 --git a/xen/arch/ia64/linux-xen/sal.c b/xen/arch/ia64/linux-xen/sal.c index a818818206..475435d374 100644 --- a/xen/arch/ia64/linux-xen/sal.c +++ b/xen/arch/ia64/linux-xen/sal.c @@ -16,6 +16,7 @@ #ifdef XEN #include +#include #endif #include #include diff --git a/xen/arch/ia64/xen/sn_console.c b/xen/arch/ia64/xen/sn_console.c index d29a82935c..14d1a95bab 100644 --- a/xen/arch/ia64/xen/sn_console.c +++ b/xen/arch/ia64/xen/sn_console.c @@ -4,6 +4,7 @@ * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved. */ +#include #include #include #include diff --git a/xen/include/asm-ia64/config.h b/xen/include/asm-ia64/config.h index 4d730b4b1a..ed89d2996a 100644 --- a/xen/include/asm-ia64/config.h +++ b/xen/include/asm-ia64/config.h @@ -92,7 +92,7 @@ extern char _end[]; /* standard ELF symbol */ //#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) \ @@ -187,7 +187,9 @@ void sort_extable(struct exception_table_entry *start, 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 +207,6 @@ void sort_main_extable(void); #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 +256,6 @@ struct screen_info { }; #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 +304,8 @@ extern int ht_per_core; #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__)) +#ifndef __ASSEMBLY__ +#include #endif + #endif /* _IA64_CONFIG_H_ */ diff --git a/xen/include/asm-ia64/vmmu.h b/xen/include/asm-ia64/vmmu.h index 429c79b4dc..03d5f3644d 100644 --- a/xen/include/asm-ia64/vmmu.h +++ b/xen/include/asm-ia64/vmmu.h @@ -151,8 +151,8 @@ typedef union thash_cch_mem { 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); From 82f5d7e034952c4c035682c4ba8ed74158234e14 Mon Sep 17 00:00:00 2001 From: "Ian.Campbell@xensource.com" Date: Fri, 13 Jan 2006 14:59:40 +0000 Subject: [PATCH 44/97] Debug keyhandlers for triggering an NMI and examine current NMI state. Add 'N' keyhandler to dump the current per CPU NMI counts and the current NMI mask/pending status. Add 'n' keyhandler to trigger an NMI by sending an IPI. For some reason the destination shorthand for self is not valid when used with the NMI delivery mode so we send the IPI to our own APIC ID explicitly. Signed-off-by: Ian Campbell --- xen/arch/x86/nmi.c | 25 +++++++++++++++++++++++++ xen/common/keyhandler.c | 22 ++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/xen/arch/x86/nmi.c b/xen/arch/x86/nmi.c index d2ccd4e7e4..f8c34a1c27 100644 --- a/xen/arch/x86/nmi.c +++ b/xen/arch/x86/nmi.c @@ -23,12 +23,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include unsigned int nmi_watchdog = NMI_NONE; static spinlock_t watchdog_lock = SPIN_LOCK_UNLOCKED; @@ -448,3 +450,26 @@ void nmi_watchdog_tick(struct cpu_user_regs * regs) 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); + + 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); +} + +static __init int register_nmi_trigger(void) +{ + register_keyhandler('n', do_nmi_trigger, "trigger an NMI"); + return 0; +} +__initcall(register_nmi_trigger); diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c index b239391462..5fc1e6b04c 100644 --- a/xen/common/keyhandler.c +++ b/xen/common/keyhandler.c @@ -185,6 +185,27 @@ void do_debug_key(unsigned char key, struct cpu_user_regs *regs) bit. */ } +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"); +} + #ifndef NDEBUG void debugtrace_key(unsigned char key) { @@ -213,6 +234,7 @@ void initialize_keytable(void) 'r', dump_runq, "dump run queues"); register_irq_keyhandler( 'R', halt_machine, "reboot machine"); + register_keyhandler('N', do_nmi_stats, "NMI statistics"); #ifndef NDEBUG register_keyhandler( From f9a0cd1238e845d00000d1dd899917cdb7145e63 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 13 Jan 2006 16:09:45 +0100 Subject: [PATCH 45/97] Fix up the way we initialise and set the NMI heartbeat timers. Also, compund updates to APIC ICR and ICR2 registers must be done with interrupts disabled to ensure local atomicity. Signed-off-by: Keir Fraser --- xen/arch/x86/apic.c | 3 +- xen/arch/x86/nmi.c | 65 ++++++++++++++++---------------------------- xen/arch/x86/setup.c | 3 +- 3 files changed, 27 insertions(+), 44 deletions(-) diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c index f1a5f0b96d..7eb6000b37 100644 --- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -451,7 +451,8 @@ void __init setup_local_APIC (void) printk("No ESR for 82489DX.\n"); } - setup_apic_nmi_watchdog(); + if (nmi_watchdog == NMI_LOCAL_APIC) + setup_apic_nmi_watchdog(); } /* diff --git a/xen/arch/x86/nmi.c b/xen/arch/x86/nmi.c index f8c34a1c27..96c55572cd 100644 --- a/xen/arch/x86/nmi.c +++ b/xen/arch/x86/nmi.c @@ -33,10 +33,6 @@ #include unsigned int nmi_watchdog = NMI_NONE; -static spinlock_t watchdog_lock = SPIN_LOCK_UNLOCKED; -static unsigned int watchdog_disable_count = 1; -static unsigned int watchdog_on; - 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; @@ -314,18 +310,8 @@ static int __pminit setup_p4_watchdog(void) void __pminit setup_apic_nmi_watchdog(void) { - int cpu = smp_processor_id(); - - if ( nmi_active < 0 ) - return; - - if ( !nmi_watchdog ) - { - /* Force the watchdog to always be disabled. */ - watchdog_disable_count++; - nmi_active = -1; - return; - } + if (!nmi_watchdog) + return; switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: @@ -358,45 +344,37 @@ void __pminit setup_apic_nmi_watchdog(void) lapic_nmi_owner = LAPIC_NMI_WATCHDOG; nmi_active = 1; - - init_timer(&nmi_timer[cpu], nmi_timer_fn, NULL, cpu); } static unsigned int last_irq_sums [NR_CPUS], alert_counter [NR_CPUS]; +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; + static unsigned long heartbeat_initialised; + unsigned int cpu; - spin_lock_irqsave(&watchdog_lock, flags); + if ( !atomic_dec_and_test(&watchdog_disable_count) || + test_and_set_bit(0, &heartbeat_initialised) ) + return; - if ( --watchdog_disable_count == 0 ) + /* + * 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_timer(&nmi_timer[cpu], NOW()); + init_timer(&nmi_timer[cpu], nmi_timer_fn, NULL, cpu); + set_timer(&nmi_timer[cpu], NOW()); } - - spin_unlock_irqrestore(&watchdog_lock, flags); } void nmi_watchdog_tick(struct cpu_user_regs * regs) @@ -405,7 +383,7 @@ void nmi_watchdog_tick(struct cpu_user_regs * regs) 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) @@ -457,14 +435,17 @@ void nmi_watchdog_tick(struct cpu_user_regs * regs) * 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) { +static void do_nmi_trigger(unsigned char key) +{ u32 id = apic_read(APIC_ID); - printk("triggering NMI on APIC ID %x\n", 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 __init int register_nmi_trigger(void) diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index a1e51f45ec..39bf4a523d 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -478,7 +478,8 @@ void __init __start_xen(multiboot_info_t *mbi) schedulers_start(); - watchdog_enable(); + if ( opt_watchdog ) + watchdog_enable(); shadow_mode_init(); From c62fffdcdc3490cf5c671eb428f8ca0036b7722a Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 13 Jan 2006 16:27:45 +0100 Subject: [PATCH 46/97] Fix writable pagetables when a flush happens in a different domain, which is temporarily made to run on the wrong pagetables. Signed-off-by: Keir Fraser --- xen/arch/x86/mm.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 1b4afa2fa2..79da37d3ea 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -3023,12 +3023,25 @@ void ptwr_flush(struct domain *d, const int which) * STEP 2. Validate any modified PTEs. */ - 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; + 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. From fc5423d8cdf92d98f5eda9edc771cb546184ea93 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 13 Jan 2006 16:44:04 +0100 Subject: [PATCH 47/97] Introduce a locking protocol for acquiring the 'scheduler lock' on a particular VCPU. Since this requires acquiring the approrpiate per-CPU lock, we must re-check the VCPU's current CPU binding after the lock is acquired. Signed-off-by: Keir Fraser --- xen/common/sched_bvt.c | 18 +++++++++--------- xen/common/schedule.c | 12 ++++++------ xen/include/xen/sched-if.h | 37 +++++++++++++++++++++++++++++++++---- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/xen/common/sched_bvt.c b/xen/common/sched_bvt.c index df329dd982..9996e8bfac 100644 --- a/xen/common/sched_bvt.c +++ b/xen/common/sched_bvt.c @@ -98,9 +98,9 @@ static inline int __task_on_runqueue(struct vcpu *d) 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 @@ static void warp_timer_fn(void *data) if ( inf->warpu == 0 ) { inf->warpback = 0; - cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ); + cpu_raise_softirq(v->processor, SCHEDULE_SOFTIRQ); } set_timer(&inf->unwarp_timer, NOW() + inf->warpu); - spin_unlock_irq(&schedule_data[cpu].schedule_lock); + 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; + struct vcpu *v = inf->domain->vcpu[0]; - spin_lock_irq(&schedule_data[cpu].schedule_lock); + 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) diff --git a/xen/common/schedule.c b/xen/common/schedule.c index a971d8fae1..f6668d3593 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -165,10 +165,10 @@ void vcpu_sleep_nosync(struct vcpu *v) { 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); } @@ -187,13 +187,13 @@ void vcpu_wake(struct vcpu *v) { 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); } @@ -324,7 +324,7 @@ long sched_adjdom(struct sched_adjdom_cmd *cmd) for_each_vcpu ( d, v ) { if ( v == current ) - spin_lock_irq(&schedule_data[smp_processor_id()].schedule_lock); + vcpu_schedule_lock_irq(v); else vcpu_pause(v); } @@ -336,7 +336,7 @@ long sched_adjdom(struct sched_adjdom_cmd *cmd) for_each_vcpu ( d, v ) { if ( v == current ) - spin_unlock_irq(&schedule_data[smp_processor_id()].schedule_lock); + vcpu_schedule_unlock_irq(v); else vcpu_unpause(v); } diff --git a/xen/include/xen/sched-if.h b/xen/include/xen/sched-if.h index 7b94338391..d61d5c70d3 100644 --- a/xen/include/xen/sched-if.h +++ b/xen/include/xen/sched-if.h @@ -16,16 +16,47 @@ struct schedule_data { struct vcpu *curr; /* current task */ struct vcpu *idle; /* idle task for this cpu */ void *sched_priv; - struct 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 @@ struct scheduler { void (*dump_cpu_state) (int); }; -extern struct schedule_data schedule_data[]; - #endif /* __XEN_SCHED_IF_H__ */ From 7f762c3f385595d60bf00ec59e58a815df7155e8 Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Fri, 13 Jan 2006 10:23:01 -0600 Subject: [PATCH 48/97] add prototype of guest_cpu_user_regs() which is used by ns16550_poll(). Signed-off-by: Isaku Yamahata --- xen/include/asm-ia64/linux-xen/asm/ptrace.h | 1 + 1 file changed, 1 insertion(+) diff --git a/xen/include/asm-ia64/linux-xen/asm/ptrace.h b/xen/include/asm-ia64/linux-xen/asm/ptrace.h index a07b305961..c8372158b0 100644 --- a/xen/include/asm-ia64/linux-xen/asm/ptrace.h +++ b/xen/include/asm-ia64/linux-xen/asm/ptrace.h @@ -110,6 +110,7 @@ vcpu_regs (struct vcpu *v) return (struct cpu_user_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1; } +struct pt_regs *guest_cpu_user_regs(void); #else struct pt_regs { From a6be6177a3cdd38e46c4a9c8ef6fbaea0c9065f0 Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Fri, 13 Jan 2006 10:24:19 -0600 Subject: [PATCH 49/97] Unused page struct fields commented out. Signed-off-by: Tristan Gingold --- xen/arch/ia64/xen/mm_init.c | 2 ++ xen/include/asm-ia64/mm.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/xen/arch/ia64/xen/mm_init.c b/xen/arch/ia64/xen/mm_init.c index 8b4947f8f6..a6f5196884 100644 --- a/xen/arch/ia64/xen/mm_init.c +++ b/xen/arch/ia64/xen/mm_init.c @@ -502,6 +502,7 @@ find_largest_hole (u64 start, u64 end, void *arg) } #endif /* CONFIG_VIRTUAL_MEM_MAP */ +#ifndef XEN static int count_reserved_pages (u64 start, u64 end, void *arg) { @@ -514,6 +515,7 @@ count_reserved_pages (u64 start, u64 end, void *arg) *count += num_reserved; return 0; } +#endif /* * Boot command-line option "nolwsys" can be used to disable the use of any light-weight diff --git a/xen/include/asm-ia64/mm.h b/xen/include/asm-ia64/mm.h index e38ba4f149..d24ad0702a 100644 --- a/xen/include/asm-ia64/mm.h +++ b/xen/include/asm-ia64/mm.h @@ -67,10 +67,12 @@ struct page } 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) From 64d8a3587165a1e384611090ccfb07c80414872e Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Fri, 13 Jan 2006 10:25:10 -0600 Subject: [PATCH 50/97] Make xmexaple.vti support network option too and other small modifications for convenient use. Signed-off-by Zhang xiantao --- tools/examples/xmexample.vti | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/examples/xmexample.vti b/tools/examples/xmexample.vti index 2daa58ca39..5e47ba56db 100644 --- a/tools/examples/xmexample.vti +++ b/tools/examples/xmexample.vti @@ -21,7 +21,7 @@ builder='vmx' 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 @@ name = "ExampleVMXDomain" # 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 @@ disk = [ 'file:/var/images/xenia64.img,ioemu:hda,w' ] #============================================================================ # 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' From cafde138a1bc6bb3c6b1e329069204d19d40a3bc Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Fri, 13 Jan 2006 10:36:47 -0600 Subject: [PATCH 51/97] correct implementation of flush_tlb_mask needed to reenable CONFIG_SMP Signed-off-by: Tristan Gingold --- xen/arch/ia64/linux-xen/smp.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/xen/arch/ia64/linux-xen/smp.c b/xen/arch/ia64/linux-xen/smp.c index 97f66a045c..d667a428b4 100644 --- a/xen/arch/ia64/linux-xen/smp.c +++ b/xen/arch/ia64/linux-xen/smp.c @@ -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 From 542362015edbf76293862c5320692fa5dbe55ba0 Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Fri, 13 Jan 2006 10:38:44 -0600 Subject: [PATCH 52/97] Allow asm-offsets to work with vanilla binutils Necessary because SHARED_ARCHINFO_ADDR is negative Signed-off-by: Isaku Yamahata --- xen/arch/ia64/asm-offsets.c | 2 +- xen/arch/ia64/asm-xsi-offsets.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/arch/ia64/asm-offsets.c b/xen/arch/ia64/asm-offsets.c index 4e23302327..88f49e7745 100644 --- a/xen/arch/ia64/asm-offsets.c +++ b/xen/arch/ia64/asm-offsets.c @@ -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 --git a/xen/arch/ia64/asm-xsi-offsets.c b/xen/arch/ia64/asm-xsi-offsets.c index 6a2c6dfa40..aef06d7702 100755 --- a/xen/arch/ia64/asm-xsi-offsets.c +++ b/xen/arch/ia64/asm-xsi-offsets.c @@ -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->" : : ) From 0828aa84f798e1553348322962f73a843ecdfb8c Mon Sep 17 00:00:00 2001 From: "Ian.Campbell@xensource.com" Date: Fri, 13 Jan 2006 16:56:09 +0000 Subject: [PATCH 53/97] Correctly handle dumping a VM86 guest's stack. If the guest context is VM86 then we need to treat ss:sp as 16 bit segment:offset rather than 32 bit selector:offset. Signed-off-by: Ian Campbell --- xen/arch/x86/traps.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 93b11e36c1..0a7280fb70 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -130,9 +130,19 @@ unsigned long kernel_text_end(void) static void show_guest_stack(struct cpu_user_regs *regs) { int i; - unsigned long *stack = (unsigned long *)regs->esp, addr; + unsigned long *stack, addr; - printk("Guest stack trace from "__OP"sp=%p:\n ", stack); + 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++ ) { From cff39e47ebd161c2eaef471aea3f1906e4946a2e Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Fri, 13 Jan 2006 14:16:44 -0600 Subject: [PATCH 54/97] Fix for !CONFIG_SMP compile Signed-off-by: Dan Magenheimer --- xen/arch/ia64/linux-xen/smpboot.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xen/arch/ia64/linux-xen/smpboot.c b/xen/arch/ia64/linux-xen/smpboot.c index c6970ffad9..a7e5e780c5 100644 --- a/xen/arch/ia64/linux-xen/smpboot.c +++ b/xen/arch/ia64/linux-xen/smpboot.c @@ -64,6 +64,10 @@ #ifdef XEN #include 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 */ From 3773da38628d5c8d12a3a5c53cf1932115242c7e Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Fri, 13 Jan 2006 14:19:30 -0600 Subject: [PATCH 55/97] Remove annoying #warning when compiling with CONFIG_XEN_SMP --- xen/include/asm-ia64/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/include/asm-ia64/config.h b/xen/include/asm-ia64/config.h index 74ee48ac0f..3ffeb9bd6c 100644 --- a/xen/include/asm-ia64/config.h +++ b/xen/include/asm-ia64/config.h @@ -121,7 +121,7 @@ extern char _end[]; /* standard ELF symbol */ // 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) From 4b79423778b91b3a8d30ae010e0dfc220864ce3e Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Fri, 13 Jan 2006 14:31:00 -0600 Subject: [PATCH 56/97] Leave *_SOFTIRQ definitions to Xen common code Signed-off-by: Dan Magenheimer --- xen/include/asm-ia64/linux-xen/linux/interrupt.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xen/include/asm-ia64/linux-xen/linux/interrupt.h b/xen/include/asm-ia64/linux-xen/linux/interrupt.h index 1061b5e081..210cea512a 100644 --- a/xen/include/asm-ia64/linux-xen/linux/interrupt.h +++ b/xen/include/asm-ia64/linux-xen/linux/interrupt.h @@ -104,6 +104,7 @@ extern void local_bh_enable(void); al. should be converted to tasklets, not to softirqs. */ +#ifndef XEN enum { HI_SOFTIRQ=0, @@ -113,6 +114,7 @@ enum 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 From 180a69c1e2f4c2c47dfcbab32bfdc33eacbe92f4 Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Fri, 13 Jan 2006 14:58:41 -0600 Subject: [PATCH 57/97] Work around new nmi code in keyhandler Signed-off-by: Dan Magenheimer --- xen/arch/ia64/xen/xenmisc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xen/arch/ia64/xen/xenmisc.c b/xen/arch/ia64/xen/xenmisc.c index eaddbee41c..85b140dd42 100644 --- a/xen/arch/ia64/xen/xenmisc.c +++ b/xen/arch/ia64/xen/xenmisc.c @@ -203,6 +203,8 @@ void dump_pageframe_info(struct domain *d) printk("dump_pageframe_info not implemented\n"); } +int nmi_count(int x) { return x; } + /////////////////////////////// // called from arch/ia64/head.S /////////////////////////////// From c9a14b06a442b2030969d766e67cdbd5d1b9dd62 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 13 Jan 2006 23:41:28 +0100 Subject: [PATCH 58/97] Make all nmi debugkey tracing arch specific. Signed-off-by: Keir Fraser --- xen/arch/x86/nmi.c | 22 ++++++++++++++++++++++ xen/common/keyhandler.c | 22 ---------------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/xen/arch/x86/nmi.c b/xen/arch/x86/nmi.c index 96c55572cd..e2a053fe93 100644 --- a/xen/arch/x86/nmi.c +++ b/xen/arch/x86/nmi.c @@ -448,9 +448,31 @@ static void do_nmi_trigger(unsigned char key) 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 --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c index 5fc1e6b04c..b239391462 100644 --- a/xen/common/keyhandler.c +++ b/xen/common/keyhandler.c @@ -185,27 +185,6 @@ void do_debug_key(unsigned char key, struct cpu_user_regs *regs) bit. */ } -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"); -} - #ifndef NDEBUG void debugtrace_key(unsigned char key) { @@ -234,7 +213,6 @@ void initialize_keytable(void) 'r', dump_runq, "dump run queues"); register_irq_keyhandler( 'R', halt_machine, "reboot machine"); - register_keyhandler('N', do_nmi_stats, "NMI statistics"); #ifndef NDEBUG register_keyhandler( From b395f5ac6dc412c103599a4da3b74cf8ea4bdb0c Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 14 Jan 2006 10:35:39 +0100 Subject: [PATCH 59/97] Fix the issue of system crash in vmx stress test. There is a path that shadow L2 table is assigned after it is unshadowed in stress test. Signed-off-by: Xiaofeng Ling --- xen/arch/x86/shadow.c | 17 +++++++++++++++-- xen/arch/x86/shadow32.c | 12 +++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/shadow.c b/xen/arch/x86/shadow.c index b2fd143452..6ae54e208a 100644 --- a/xen/arch/x86/shadow.c +++ b/xen/arch/x86/shadow.c @@ -2138,6 +2138,7 @@ static void shadow_update_pagetables(struct vcpu *v) #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 @@ -2169,8 +2170,17 @@ static void shadow_update_pagetables(struct vcpu *v) #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); @@ -2241,6 +2251,9 @@ static void shadow_update_pagetables(struct vcpu *v) } #endif /* CONFIG_PAGING_LEVELS == 2 */ + if(likely(need_sync)) + shadow_sync_all(d); + #if CONFIG_PAGING_LEVELS == 3 /* FIXME: PAE code to be written */ #endif diff --git a/xen/arch/x86/shadow32.c b/xen/arch/x86/shadow32.c index eb09ea92c5..a36238b3d8 100644 --- a/xen/arch/x86/shadow32.c +++ b/xen/arch/x86/shadow32.c @@ -2896,6 +2896,7 @@ void __update_pagetables(struct vcpu *v) 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 @@ -2921,7 +2922,13 @@ void __update_pagetables(struct vcpu *v) 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); @@ -2985,6 +2992,9 @@ void __update_pagetables(struct vcpu *v) // 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) From 360a1871b545a65aed9fb2e346ecf13e7b2040d2 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 14 Jan 2006 16:58:54 +0100 Subject: [PATCH 60/97] Rename cdb to gdbstub and split it into arch dependent/neutral part. Signed-off-by: Isaku Yamahata Signed-off-by: Hollis Blanchard --- xen/arch/x86/Makefile | 2 +- xen/arch/x86/cdb.c | 414 ----------------------- xen/arch/x86/gdbstub.c | 146 ++++++++ xen/common/Makefile | 3 + xen/common/gdbstub.c | 593 +++++++++++++++++++++++++++++++++ xen/include/asm-x86/debugger.h | 10 +- xen/include/xen/gdbstub.h | 96 ++++++ 7 files changed, 845 insertions(+), 419 deletions(-) delete mode 100644 xen/arch/x86/cdb.c create mode 100644 xen/arch/x86/gdbstub.c create mode 100644 xen/common/gdbstub.c create mode 100644 xen/include/xen/gdbstub.h diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index 9cdbc5798c..3779672aa3 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -32,7 +32,7 @@ OBJS := $(subst $(TARGET_SUBARCH)/asm-offsets.o,,$(OBJS)) 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 --git a/xen/arch/x86/cdb.c b/xen/arch/x86/cdb.c deleted file mode 100644 index c9309b289e..0000000000 --- a/xen/arch/x86/cdb.c +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* 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 --git a/xen/arch/x86/gdbstub.c b/xen/arch/x86/gdbstub.c new file mode 100644 index 0000000000..0c34e07fd4 --- /dev/null +++ b/xen/arch/x86/gdbstub.c @@ -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 + * 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 + +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" + " .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; +} + +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 --git a/xen/common/Makefile b/xen/common/Makefile index 39688391c8..516adbc8f4 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -4,6 +4,9 @@ include $(BASEDIR)/Rules.mk ifneq ($(perfc),y) OBJS := $(subst perfc.o,,$(OBJS)) endif +ifneq ($(crash_debug),y) +OBJS := $(patsubst gdbstub.o,,$(OBJS)) +endif default: common.o common.o: $(OBJS) diff --git a/xen/common/gdbstub.c b/xen/common/gdbstub.c new file mode 100644 index 0000000000..48c1b0a41f --- /dev/null +++ b/xen/common/gdbstub.c @@ -0,0 +1,593 @@ +/* + * Copyright (C) 2005 Jimi Xenidis , IBM Corporation + * Copyright (C) 2006 Isaku Yamahata + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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 --git a/xen/include/asm-x86/debugger.h b/xen/include/asm-x86/debugger.h index 241c12d1f8..d11cc85366 100644 --- a/xen/include/asm-x86/debugger.h +++ b/xen/include/asm-x86/debugger.h @@ -42,19 +42,19 @@ #if defined(CRASH_DEBUG) -extern int __trap_to_cdb(struct cpu_user_regs *r); +#include #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 @@ static inline int __debugger_trap_fatal( } /* 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 @@ static inline int debugger_trap_entry( } #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 --git a/xen/include/xen/gdbstub.h b/xen/include/xen/gdbstub.h new file mode 100644 index 0000000000..9d2e323aed --- /dev/null +++ b/xen/include/xen/gdbstub.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2005 Hollis Blanchard , IBM Corporation + * Copyright (C) 2006 Isaku Yamahata + * 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: + */ From 7770ed988a5edf4276d092045df109391d37904b Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 14 Jan 2006 17:05:31 +0100 Subject: [PATCH 61/97] Fix 64-bit build with crash_debug enabled. Signed-off-by: Keir Fraser --- xen/arch/x86/gdbstub.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xen/arch/x86/gdbstub.c b/xen/arch/x86/gdbstub.c index 0c34e07fd4..8ed5e20298 100644 --- a/xen/arch/x86/gdbstub.c +++ b/xen/arch/x86/gdbstub.c @@ -86,12 +86,12 @@ gdb_arch_copy_from_user(void *dest, const void *src, unsigned len) " jmp 2b\n" ".previous\n" ".section __pre_ex_table,\"a\"\n" - " .align 4\n" - " .long 1b,3b\n" + " "__FIXUP_ALIGN"\n" + " "__FIXUP_WORD" 1b,3b\n" ".previous\n" ".section __ex_table,\"a\"\n" - " .align 4\n" - " .long 1b,2b\n" + " "__FIXUP_ALIGN"\n" + " "__FIXUP_WORD" 1b,2b\n" ".previous\n" : "=c"(__d2), "=D" (__d0), "=S" (__d1) : "0"(len), "1"(dest), "2"(src) From 6294397fbafa4fefe6e0671afe62d3f35e9e7b12 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 14 Jan 2006 21:26:40 +0100 Subject: [PATCH 62/97] Arch-specific per-vcpu info should be initialised to zero when allocating a new vcpu structure, not copied from CPU0's idle VCPU. Especially now that the idle VCPU itself is dynamically allocated. This should fix assertions people have been seeing in getdomain_info_ctxt() relation to IOPL in eflags. Signed-off-by: Keir Fraser --- xen/arch/x86/domain.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 19c29d084c..db764760b1 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -215,14 +215,10 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) 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) ) - { percpu_ctxt[vcpu_id].curr_vcpu = v; - v->arch.schedule_tail = continue_idle_domain; - } if ( (v->vcpu_id = vcpu_id) != 0 ) { @@ -333,10 +329,11 @@ int arch_do_createdomain(struct vcpu *v) 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; } + v->arch.schedule_tail = is_idle_domain(d) ? + continue_idle_domain : continue_nonidle_domain; + return 0; fail_nomem: From f59958dd8242e3bafdc7c03623b48222eae5f9de Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 14 Jan 2006 22:17:33 +0100 Subject: [PATCH 63/97] xc_vcpu_getcontext() can no longer be called before a VCPU's context has been explicitly initialised. Fix all the domain builders to no longer attempt this. They really don't need to anyhow. Signed-off-by: Keir Fraser --- tools/libxc/xc_ia64_stubs.c | 10 +--------- tools/libxc/xc_linux_build.c | 16 +++------------- tools/libxc/xc_vmx_build.c | 13 +------------ xen/common/dom0_ops.c | 4 ++++ xen/common/domain.c | 7 ++++--- 5 files changed, 13 insertions(+), 37 deletions(-) diff --git a/tools/libxc/xc_ia64_stubs.c b/tools/libxc/xc_ia64_stubs.c index a10992be8e..e742df3ba0 100644 --- a/tools/libxc/xc_ia64_stubs.c +++ b/tools/libxc/xc_ia64_stubs.c @@ -665,15 +665,7 @@ int xc_vmx_build(int xc_handle, 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 --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 5312b42bba..23fc456554 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -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 @@ int xc_linux_build(int xc_handle, 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 @@ int xc_linux_build(int xc_handle, 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 --git a/tools/libxc/xc_vmx_build.c b/tools/libxc/xc_vmx_build.c index ee18a4f8a2..222ec17207 100644 --- a/tools/libxc/xc_vmx_build.c +++ b/tools/libxc/xc_vmx_build.c @@ -651,18 +651,7 @@ int xc_vmx_build(int xc_handle, 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 --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index 8e7754d84a..5b92dc75d3 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -450,6 +450,10 @@ long do_dom0_op(dom0_op_t *u_dom0_op) 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; diff --git a/xen/common/domain.c b/xen/common/domain.c index 34f2ed8678..b0af3ebaf2 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -369,16 +369,17 @@ int set_info_guest(struct domain *d, dom0_setvcpucontext_t *setvcpucontext) 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; } From 0ed0e371937cadb524abb1aa5d85789565cec7d6 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 14 Jan 2006 23:16:43 +0100 Subject: [PATCH 64/97] Some refactoring of domain creation/destruction. Interface name changes: 1. do_createdomain -> domain_create 2. domain_destruct -> domain_destroy Arch-specific changes: 1. arch_do_createdomain -> arch_domain_create This function now takes a domain pointer, not a VCPU pointer! Initialisation of VCPU0 must happen in alloc_vcpu_struct(). 2. free_perdomain_pt -> arch_domain_destroy This function must undo the work of arch_domain_create TODO: arch_domain_create() refactoring is not completed for ia64. Signed-off-by: Keir Fraser --- xen/arch/ia64/xen/domain.c | 10 +++--- xen/arch/ia64/xen/xensetup.c | 8 ++--- xen/arch/x86/domain.c | 66 ++++++++++++++++------------------- xen/arch/x86/setup.c | 4 +-- xen/common/dom0_ops.c | 2 +- xen/common/domain.c | 55 ++++++++++++++++------------- xen/common/schedule.c | 11 ++++-- xen/include/asm-ia64/domain.h | 2 -- xen/include/xen/domain.h | 6 ++-- xen/include/xen/sched.h | 17 ++++----- 10 files changed, 95 insertions(+), 86 deletions(-) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 99b1646614..f8e7a0ffaf 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -67,10 +67,11 @@ unsigned long map_domain_page0(struct domain *); extern unsigned long dom_fw_setup(struct domain *, char *, int); /* this belongs in include/asm, but there doesn't seem to be a suitable place */ -void free_perdomain_pt(struct domain *d) +void arch_domain_destroy(struct domain *d) { - printf("free_perdomain_pt: not implemented\n"); + 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) @@ -192,9 +193,8 @@ static void init_switch_stack(struct vcpu *v) memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96); } -int arch_do_createdomain(struct vcpu *v) +int arch_domain_create(struct domain *d) { - struct domain *d = v->domain; struct thread_info *ti = alloc_thread_info(v); /* Clear thread_info to clear some important fields, like preempt_count */ @@ -255,7 +255,7 @@ int arch_do_createdomain(struct vcpu *v) printk("Can't allocate pgd for domain %d\n",d->domain_id); return -ENOMEM; } - printf ("arch_do_create_domain: domain=%p\n", d); + printf ("arch_domain_create: domain=%p\n", d); return 0; } diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index 1b9dc72b75..12a9fd4820 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -281,7 +281,7 @@ void start_kernel(void) printk("About to call scheduler_init()\n"); scheduler_init(); idle_vcpu[0] = (struct vcpu*) ia64_r13; - idle_domain = do_createdomain(IDLE_DOMAIN_ID, 0); + idle_domain = domain_create(IDLE_DOMAIN_ID, 0); BUG_ON(idle_domain == NULL); late_setup_arch(&cmdline); @@ -339,14 +339,14 @@ printk("About to call sort_main_extable()\n"); /* Create initial domain 0. */ -printk("About to call do_createdomain()\n"); - dom0 = do_createdomain(0, 0); +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); } diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index db764760b1..b38147211a 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -218,41 +218,35 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) v->arch.flags = TF_kernel_mode; if ( is_idle_domain(d) ) - percpu_ctxt[vcpu_id].curr_vcpu = v; - - 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); + percpu_ctxt[vcpu_id].curr_vcpu = v; + v->arch.schedule_tail = continue_idle_domain; } + 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) +int arch_domain_create(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; l1_pgentry_t gdt_l1e; int vcpuid, pdpt_order, rc; #ifdef __x86_64__ @@ -263,9 +257,7 @@ int arch_do_createdomain(struct vcpu *v) 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 @@ -279,18 +271,12 @@ int arch_do_createdomain(struct vcpu *v) 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__) 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(); if ( (d->arch.mm_perdomain_l2 == NULL) || @@ -327,13 +313,9 @@ int arch_do_createdomain(struct vcpu *v) 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 = is_idle_domain(d) ? - continue_idle_domain : continue_nonidle_domain; - return 0; fail_nomem: @@ -346,6 +328,20 @@ int arch_do_createdomain(struct vcpu *v) 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 */ int arch_set_info_guest( struct vcpu *v, struct vcpu_guest_context *c) diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 39bf4a523d..fc92f39bfa 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -385,7 +385,7 @@ void __init __start_xen(multiboot_info_t *mbi) 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]); @@ -487,7 +487,7 @@ void __init __start_xen(multiboot_info_t *mbi) 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 --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index 5b92dc75d3..3a33965201 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -208,7 +208,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) 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, diff --git a/xen/common/domain.c b/xen/common/domain.c index b0af3ebaf2..de4f6c3f79 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -29,7 +29,7 @@ struct domain *domain_list; 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 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu) INIT_LIST_HEAD(&d->page_list); INIT_LIST_HEAD(&d->xenpage_list); - 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 ( (v = alloc_vcpu(d, 0, cpu)) == NULL ) - goto fail2; - rangeset_domain_initialise(d); + if ( !is_idle_domain(d) ) + { + set_bit(_DOMF_ctrl_pause, &d->domain_flags); + 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 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 fail5; if ( !is_idle_domain(d) ) { @@ -82,12 +84,18 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu) return d; + fail5: + free_vcpu(v); + fail4: + arch_domain_destroy(d); fail3: - rangeset_domain_destroy(d); + if ( !is_idle_domain(d) ) + grant_table_destroy(d); fail2: - grant_table_destroy(d); + if ( !is_idle_domain(d) ) + evtchn_destroy(d); fail1: - evtchn_destroy(d); + rangeset_domain_destroy(d); free_domain(d); return NULL; } @@ -256,16 +264,16 @@ void domain_pause_for_debugger(void) /* 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 +295,7 @@ void domain_destruct(struct domain *d) evtchn_destroy(d); grant_table_destroy(d); - free_perdomain_pt(d); - free_xenheap_page(d->shared_info); + arch_domain_destroy(d); free_domain(d); diff --git a/xen/common/schedule.c b/xen/common/schedule.c index f6668d3593..f2815d7d9f 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -100,6 +100,7 @@ struct vcpu *alloc_vcpu( 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; @@ -117,14 +118,20 @@ struct vcpu *alloc_vcpu( 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); + if ( !is_idle_domain(d) ) + set_bit(_VCPUF_down, &v->vcpu_flags); } return v; } +void free_vcpu(struct vcpu *v) +{ + /* NB. Rest of destruction is done in free_domain(). */ + sched_rem_domain(v); +} + struct domain *alloc_domain(void) { struct domain *d; diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h index 863def1ff5..3aac190963 100644 --- a/xen/include/asm-ia64/domain.h +++ b/xen/include/asm-ia64/domain.h @@ -10,8 +10,6 @@ #include #include -extern int arch_do_createdomain(struct vcpu *); - extern void domain_relinquish_resources(struct domain *); struct arch_domain { diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h index 4ebf0ca286..4fee8e74cb 100644 --- a/xen/include/xen/domain.h +++ b/xen/include/xen/domain.h @@ -13,13 +13,13 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id); 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); extern void dump_pageframe_info(struct domain *d); diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index df7611a70b..e6b63ac324 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -181,17 +181,18 @@ extern struct vcpu *idle_vcpu[NR_CPUS]; struct vcpu *alloc_vcpu( struct domain *d, unsigned int vcpu_id, unsigned int cpu_id); +void free_vcpu(struct vcpu *v); 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) { @@ -199,7 +200,7 @@ static always_inline int get_domain(struct domain *d) 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); @@ -210,15 +211,15 @@ static always_inline int get_domain(struct domain *d) /* * 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, @@ -228,7 +229,7 @@ extern int construct_dom0( 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); From cbafa2c56bce99c8b5adf495aa33929439152fb3 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 14 Jan 2006 23:40:09 +0100 Subject: [PATCH 65/97] Remove the free_vcpu() interface I added in the preceding changeset. It makes no sense, since an allocated VCPU cannot be freed at any arbitrary point because individual VCPUs are not refcounted. Instead extend free_domain() slightly so it really does do the reverse of alloc_vcpu() for every allocated VCPU. Signed-off-by: Keir Fraser --- xen/common/domain.c | 4 +--- xen/common/schedule.c | 50 +++++++++++++++++------------------------ xen/include/xen/sched.h | 1 - 3 files changed, 22 insertions(+), 33 deletions(-) diff --git a/xen/common/domain.c b/xen/common/domain.c index de4f6c3f79..bc6eebe41c 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -66,7 +66,7 @@ struct domain *domain_create(domid_t dom_id, unsigned int cpu) 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) ) - goto fail5; + goto fail4; /* NB. alloc_vcpu() is undone in free_domain() */ if ( !is_idle_domain(d) ) { @@ -84,8 +84,6 @@ struct domain *domain_create(domid_t dom_id, unsigned int cpu) return d; - fail5: - free_vcpu(v); fail4: arch_domain_destroy(d); fail3: diff --git a/xen/common/schedule.c b/xen/common/schedule.c index f2815d7d9f..94b40559da 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -73,15 +73,29 @@ static struct scheduler ops; /* Per-CPU periodic timer sends an event to the currently-executing domain. */ 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); } @@ -105,46 +119,24 @@ struct vcpu *alloc_vcpu( 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; } - sched_add_domain(v); - + d->vcpu[vcpu_id] = v; if ( vcpu_id != 0 ) - { d->vcpu[v->vcpu_id-1]->next_in_list = v; - if ( !is_idle_domain(d) ) - set_bit(_VCPUF_down, &v->vcpu_flags); - } + + sched_add_domain(v); return v; } -void free_vcpu(struct vcpu *v) -{ - /* NB. Rest of destruction is done in free_domain(). */ - sched_rem_domain(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. */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index e6b63ac324..7005177f4c 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -181,7 +181,6 @@ extern struct vcpu *idle_vcpu[NR_CPUS]; struct vcpu *alloc_vcpu( struct domain *d, unsigned int vcpu_id, unsigned int cpu_id); -void free_vcpu(struct vcpu *v); struct domain *alloc_domain(void); void free_domain(struct domain *d); From 4e25f64449112b44c3a36f6f718c1ce433155564 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 16 Jan 2006 14:47:31 +0100 Subject: [PATCH 66/97] Complete arch_domain_create refactoring for ia64. Signed-off-by: Kevin Tian --- xen/arch/ia64/xen/domain.c | 89 ++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 46 deletions(-) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index f8e7a0ffaf..a331141976 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -65,6 +65,7 @@ extern int readelfimage_base_and_size(char *, unsigned long, 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 arch_domain_destroy(struct domain *d) @@ -145,27 +146,45 @@ void startup_cpu_idle_loop(void) struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) { struct vcpu *v; + 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) - return idle_vcpu[0]; - - if ((v = alloc_xenheap_pages(KERNEL_STACK_SIZE_ORDER)) == NULL) + v = idle_vcpu[0]; + else { + if ((v = alloc_xenheap_pages(KERNEL_STACK_SIZE_ORDER)) == NULL) return NULL; + memset(v, 0, sizeof(*v)); + } - memset(v, 0, sizeof(*v)); - memcpy(&v->arch, &idle_vcpu[0]->arch, sizeof(v->arch)); + 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))); BUG_ON(v->arch.privregs == NULL); memset(v->arch.privregs, 0, PAGE_SIZE); - } - printf("arch_vcpu_info=%p\n", v->arch.privregs); + 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; } @@ -195,34 +214,19 @@ static void init_switch_stack(struct vcpu *v) int arch_domain_create(struct domain *d) { - 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); - // 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_vcpu(v)) + if (is_idle_domain(d)) return 0; - d->shared_info = (void *)alloc_xenheap_page(); - if (!d->shared_info) { - printk("ERROR/HALTING: CAN'T ALLOC PAGE\n"); - while (1); - } + 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)); - - 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. @@ -230,34 +234,27 @@ int arch_domain_create(struct domain *d) 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; d->arch.breakimm = 0x1000; - v->arch.breakimm = d->arch.breakimm; - d->arch.sys_pgnr = 0; - 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; - } - printf ("arch_domain_create: 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) From bc7c6426621aeef647ecebfa476b95b7e738478f Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Mon, 16 Jan 2006 21:13:29 +0000 Subject: [PATCH 67/97] remove unnecessary macro bdev_put which is an alias to blkdev_put. Signed-off-by: Vincent Hanquez --- linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c b/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c index 6204ca1cbe..bbd33f7d54 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c @@ -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 @@ int vbd_create(blkif_t *blkif, blkif_vdev_t handle, unsigned major, void vbd_free(struct vbd *vbd) { if (vbd->bdev) - bdev_put(vbd->bdev); + blkdev_put(vbd->bdev); vbd->bdev = NULL; } From 23a6ea12768c317a0442394d03b13d4ec480ed60 Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Mon, 16 Jan 2006 21:29:10 +0000 Subject: [PATCH 68/97] remove ASSERT macro that is not used anymore in blkback. Signed-off-by: Vincent Hanquez --- linux-2.6-xen-sparse/drivers/xen/blkback/common.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h index df0a1553bf..406e6d9470 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h @@ -20,13 +20,9 @@ #include #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 From 1765b01024575ea0c72d3aec314334fbaa4c83ea Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Mon, 16 Jan 2006 21:43:17 +0000 Subject: [PATCH 69/97] use standard pr_debug macro for DPRINTK. Signed-off-by: Vincent Hanquez --- linux-2.6-xen-sparse/drivers/xen/blkback/common.h | 8 ++------ linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c | 5 +---- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h index 406e6d9470..2576664e7c 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h @@ -19,12 +19,8 @@ #include #include -#if 0 -#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \ - __FILE__ , __LINE__ , ## _a ) -#else -#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 --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c index f3a0287935..486dcf9883 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -24,12 +24,9 @@ #include #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 From ffd9d0c69ed61e0c69b3de96785c06f22de13579 Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Mon, 16 Jan 2006 21:48:24 +0000 Subject: [PATCH 70/97] fix xenbus_scanf called with NULL instead of XBT_NULL. Signed-off-by: Vincent Hanquez --- linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c index bb4bbe83c0..df72cedd01 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c @@ -364,7 +364,7 @@ static int tpmfront_probe(struct xenbus_device *dev, 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; From c4975c1cf00d98274ef9b2aec3221393ac4ded2b Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Mon, 16 Jan 2006 21:58:44 +0000 Subject: [PATCH 71/97] define all DPRINTK as pr_debug Signed-off-by: Vincent Hanquez --- linux-2.6-xen-sparse/drivers/xen/blkfront/block.h | 6 +----- linux-2.6-xen-sparse/drivers/xen/blktap/common.h | 6 +++--- linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 9 ++------- linux-2.6-xen-sparse/drivers/xen/tpmback/common.h | 6 +++--- linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c | 6 +----- linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c | 7 +------ linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c | 6 +----- 7 files changed, 12 insertions(+), 34 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h index 3809f9067b..1fde02dea1 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h @@ -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 --git a/linux-2.6-xen-sparse/drivers/xen/blktap/common.h b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h index 9571b057e1..c458c5c634 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h @@ -23,13 +23,13 @@ #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) struct vbd { diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index f80250d55a..72d50c8e04 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -154,13 +154,8 @@ static char *be_state_name[] = { }; #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...) \ diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h index cb7a1edffa..a994406f4f 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h @@ -21,13 +21,13 @@ #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; /* Unique identifier for this interface. */ diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c index df72cedd01..f22a2a290d 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c @@ -80,12 +80,8 @@ static int tpm_xmit(struct tpm_private *tp, 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...) \ diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c index 303eab86c4..28724abfe0 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c @@ -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, diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c index 6fbe1e3649..ce4f863538 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c @@ -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 #include From ff45641f7d6553d5ea83155eead4b8d173a697c3 Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Mon, 16 Jan 2006 22:04:42 +0000 Subject: [PATCH 72/97] replace ASSERT by BUG_ON. Signed-off-by: Vincent Hanquez --- linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c | 2 +- linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c index 3e81abe8e4..253c796c10 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -551,7 +551,7 @@ static int blkif_queue_request(struct request *req) 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 --git a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c index b8ed4fdfab..0124209b51 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c @@ -120,7 +120,7 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev) { 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 || From 562b48cc4f52c819d0651f9f4b6d6a4086e1f020 Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Mon, 16 Jan 2006 22:07:29 +0000 Subject: [PATCH 73/97] remove ASSERT macro. Signed-off-by: Vincent Hanquez --- linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c | 8 -------- linux-2.6-xen-sparse/drivers/xen/blktap/common.h | 8 -------- linux-2.6-xen-sparse/drivers/xen/netback/common.h | 12 ++---------- linux-2.6-xen-sparse/drivers/xen/tpmback/common.h | 8 -------- linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c | 8 -------- 5 files changed, 2 insertions(+), 42 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c index 253c796c10..e7eacc3d58 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -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 #include "block.h" #include diff --git a/linux-2.6-xen-sparse/drivers/xen/blktap/common.h b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h index c458c5c634..635dd467b5 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h @@ -19,14 +19,6 @@ #include #include -#if 0 -#define ASSERT(_p) \ - if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \ - __LINE__, __FILE__); *(int*)0=0; } -#else -#define ASSERT(_p) ((void)0) -#endif - #define DPRINTK(_f, _a...) pr_debug("(file=%s, line=%d) " _f, \ __FILE__ , __LINE__ , ## _a ) diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/common.h b/linux-2.6-xen-sparse/drivers/xen/netback/common.h index 6fa0d226bb..ce781d80a5 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h @@ -22,16 +22,8 @@ #include #include -#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 --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h index a994406f4f..dce6ebb151 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h @@ -17,14 +17,6 @@ #include #include -#if 0 -#define ASSERT(_p) \ - if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \ - __LINE__, __FILE__); *(int*)0=0; } -#else -#define ASSERT(_p) ((void)0) -#endif - #define DPRINTK(_f, _a...) pr_debug("(file=%s, line=%d) " _f, \ __FILE__ , __LINE__ , ## _a ) diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c index f22a2a290d..a85ab7e617 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c @@ -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; From 403ce4ff82d4df58b9346c0f52b52c34bb53db7a Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Mon, 16 Jan 2006 22:11:43 +0000 Subject: [PATCH 74/97] bool type doesn't exist in C, don't try to emulate one. Signed-off-by: Vincent Hanquez --- .../drivers/xen/tpmback/common.h | 5 ----- .../drivers/xen/tpmback/xenbus.c | 8 ++++---- .../drivers/xen/tpmfront/tpmfront.c | 18 +++++++++--------- .../drivers/xen/tpmfront/tpmfront.h | 5 ----- 4 files changed, 13 insertions(+), 23 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h index dce6ebb151..cd001d58ef 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h @@ -76,11 +76,6 @@ extern int num_frontends; #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 --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c index 60f0c50d1c..7b62227b41 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c @@ -78,7 +78,7 @@ static int tpmback_probe(struct xenbus_device *dev, memset(be, 0, sizeof(*be)); - be->is_instance_set = FALSE; + be->is_instance_set = 0; be->dev = dev; dev->data = be; @@ -120,7 +120,7 @@ static void backend_changed(struct xenbus_watch *watch, 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 @@ static void backend_changed(struct xenbus_watch *watch, 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 @@ static void backend_changed(struct xenbus_watch *watch, return; } be->instance = instance; - be->is_instance_set = TRUE; + be->is_instance_set = 1; /* * There's an unfortunate problem: diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c index a85ab7e617..a51831fe8c 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c @@ -241,7 +241,7 @@ fail: static void destroy_tpmring(struct tpmfront_info *info, struct tpm_private *tp) { - tpmif_set_connected_state(tp, FALSE); + tpmif_set_connected_state(tp, 0); if ( tp->tx != NULL ) { gnttab_end_foreign_access(info->ring_ref, 0, (unsigned long)tp->tx); @@ -329,15 +329,15 @@ static void backend_changed(struct xenbus_device *dev, 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; @@ -401,7 +401,7 @@ tpmfront_suspend(struct xenbus_device *dev) /* lock, so no app can send */ down(&suspend_lock); - tp->is_suspended = TRUE; + tp->is_suspended = 1; while (atomic_read(&tp->tx_busy) && ctr <= 25) { if ((ctr % 10) == 0) @@ -571,7 +571,7 @@ tpm_xmit(struct tpm_private *tp, return -EBUSY; } - if (tp->is_connected != TRUE) { + if (tp->is_connected != 1) { spin_unlock_irq(&tp->tx_lock); return -EIO; } @@ -660,7 +660,7 @@ static void tpmif_set_connected_state(struct tpm_private *tp, u8 is_connected) * 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; } @@ -669,8 +669,8 @@ static void tpmif_set_connected_state(struct tpm_private *tp, u8 is_connected) * 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 --git a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h index 0eb5bf0d3e..fdc0b151c8 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h @@ -1,11 +1,6 @@ #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; unsigned int evtchn; From 4ca0e16c74e57fc76cff36cd2681f87831f291c5 Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Mon, 16 Jan 2006 23:43:58 +0000 Subject: [PATCH 75/97] sanitize tpmfront. missing spin_unlock'ing in error paths and fix coding style. Signed-off-by: Vincent Hanquez --- .../drivers/xen/tpmfront/tpmfront.c | 51 +++++++------------ 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c index a51831fe8c..e4bb32328e 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c @@ -90,11 +90,8 @@ tx_buffer_copy(struct tx_buffer *txb, const u8 * src, int len, 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); } @@ -184,15 +181,12 @@ EXPORT_SYMBOL(tpm_fe_unregister_receiver); 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; @@ -242,7 +236,7 @@ fail: static void destroy_tpmring(struct tpmfront_info *info, struct tpm_private *tp) { tpmif_set_connected_state(tp, 0); - if ( tp->tx != NULL ) { + if (tp->tx != NULL) { gnttab_end_foreign_access(info->ring_ref, 0, (unsigned long)tp->tx); tp->tx = NULL; @@ -397,20 +391,19 @@ static int 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 = 1; - while (atomic_read(&tp->tx_busy) && ctr <= 25) { + 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)) { @@ -428,16 +421,13 @@ static int 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; @@ -481,12 +471,8 @@ tpm_allocate_buffers(struct tpm_private *tp) { 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; } @@ -509,9 +495,7 @@ tpmif_rx_action(unsigned long unused) 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; @@ -527,7 +511,6 @@ tpmif_rx_action(unsigned long unused) gnttab_release_grant_reference(&gref_head, tx->ref); offset += tocopy; - i++; } tpm_fe_send_upperlayer(buffer, received, tp->tx_remember); @@ -576,14 +559,13 @@ tpm_xmit(struct tpm_private *tp, 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; } @@ -591,6 +573,7 @@ tpm_xmit(struct tpm_private *tp, isuserbuffer); if (copied < 0) { /* An error occurred */ + spin_unlock_irq(&tp->tx_lock); return copied; } count -= copied; @@ -606,9 +589,10 @@ tpm_xmit(struct tpm_private *tp, 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 ); + tx->ref = gnttab_claim_grant_reference(&gref_head); - if(-ENOSPC == tx->ref ) { + 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; } @@ -616,7 +600,6 @@ tpm_xmit(struct tpm_private *tp, tp->backend_id, (tx->addr >> PAGE_SHIFT), 0 /*RW*/); - i++; wmb(); } From 99720cafe67729fc26295b7dc21989860a4007e2 Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Mon, 16 Jan 2006 23:54:24 +0000 Subject: [PATCH 76/97] return -ENOMEM value instead of -1 when running out of memory. Signed-off-by: Vincent Hanquez --- linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c index 34d3399a8e..a3586df439 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c @@ -544,7 +544,7 @@ static int __init blkif_init(void) kfree(pending_grant_handles); kfree(pending_vaddrs); printk("%s: out of memory\n", __FUNCTION__); - return -1; + return -ENOMEM; } blkif_interface_init(); From d7d7c642c2bd5bdb936303d686e701e10b434f75 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 17 Jan 2006 13:25:30 +0100 Subject: [PATCH 77/97] Sync against scheduler tail on other CPUs when context switching to a new VCPU. Otherwise we cannot pull the VCPU's state off the other CPU. Signed-off-by: Keir Fraser --- xen/arch/x86/domain.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index b38147211a..25746ab4f1 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -738,8 +738,12 @@ void context_switch(struct vcpu *prev, struct vcpu *next) ASSERT(cpus_weight(dirty_mask) <= 1); if ( unlikely(!cpu_isset(cpu, dirty_mask) && !cpus_empty(dirty_mask)) ) { + /* Make sure the next VCPU is not in a scheduling tail. */ + while ( test_bit(_VCPUF_running, &next->vcpu_flags) ) + cpu_relax(); /* 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(); From af8becc6b9cf5c23eba11be6d675d58e5c1ecfcb Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 17 Jan 2006 14:24:42 +0100 Subject: [PATCH 78/97] Remove the spin on VCPUF_running from context_switch(). It doesn't work because we already set VCPUF_running locally, and the scheduler should not pick another CPU's VCPUF_running VCPU anyway, since it mustn't modify the processor field. Instead just add a simple assertion to the scheduler to ensure the scheduling algorithm is not picking an inappropriate VCPU. Signed-off-by: Keir Fraser --- xen/arch/x86/domain.c | 3 --- xen/common/schedule.c | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 25746ab4f1..759bbadb21 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -738,9 +738,6 @@ void context_switch(struct vcpu *prev, struct vcpu *next) ASSERT(cpus_weight(dirty_mask) <= 1); if ( unlikely(!cpu_isset(cpu, dirty_mask) && !cpus_empty(dirty_mask)) ) { - /* Make sure the next VCPU is not in a scheduling tail. */ - while ( test_bit(_VCPUF_running, &next->vcpu_flags) ) - cpu_relax(); /* Other cpus call __sync_lazy_execstate from flush ipi handler. */ if ( !cpus_empty(next->vcpu_dirty_cpumask) ) flush_tlb_mask(next->vcpu_dirty_cpumask); diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 94b40559da..0ffa53a8fa 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -420,6 +420,7 @@ static void __enter_scheduler(void) } #endif + ASSERT(!test_bit(_VCPUF_running, &next->vcpu_flags)); set_bit(_VCPUF_running, &next->vcpu_flags); spin_unlock_irq(&schedule_data[cpu].schedule_lock); From 232f69bfdd2286cda346fbb96de7daa863a3d56b Mon Sep 17 00:00:00 2001 From: "maf46@burn.cl.cam.ac.uk" Date: Tue, 17 Jan 2006 16:06:03 +0100 Subject: [PATCH 79/97] Minor documentation fix --- docs/man/xm.pod.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/man/xm.pod.1 b/docs/man/xm.pod.1 index 495f7c7ce0..109535b558 100644 --- a/docs/man/xm.pod.1 +++ b/docs/man/xm.pod.1 @@ -374,7 +374,7 @@ Attempting to set-vcpus to a number larger than the initially configured VCPU count is an error. Trying to set-vcpus to < 1 will be quietly ignored. -=item B I<[domain-id]> +=item B I<[domain-id]> Lists VCPU information for a specific domain. If no domain is specified, VCPU information for all domains will be provided. From 426f6b2e81a95a8b395027c5a2c23426cdf7e838 Mon Sep 17 00:00:00 2001 From: "smh22@firebug.cl.cam.ac.uk" Date: Tue, 17 Jan 2006 16:09:03 +0100 Subject: [PATCH 80/97] No longer call xc_vcpu_getcontext() on restore (required after cset 8610). Signed-off-by: Steven Hand --- tools/libxc/xc_linux_restore.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index c91efce4b7..7d8ebda0c7 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -170,13 +170,6 @@ int xc_linux_restore(int xc_handle, int io_fd, } - /* 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"); From 67a3f812a2abb2ac5dbdb749fb43e599c54fcfe8 Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Wed, 18 Jan 2006 12:58:11 +0000 Subject: [PATCH 81/97] Delete 2 unused Kconfig files. Signed-off-by: Vincent Hanquez --- linux-2.6-xen-sparse/drivers/xen/blkfront/Kconfig | 6 ------ linux-2.6-xen-sparse/drivers/xen/netfront/Kconfig | 6 ------ 2 files changed, 12 deletions(-) delete mode 100644 linux-2.6-xen-sparse/drivers/xen/blkfront/Kconfig delete mode 100644 linux-2.6-xen-sparse/drivers/xen/netfront/Kconfig diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/Kconfig b/linux-2.6-xen-sparse/drivers/xen/blkfront/Kconfig deleted file mode 100644 index edde837fad..0000000000 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/Kconfig +++ /dev/null @@ -1,6 +0,0 @@ - -config XENBLOCK - tristate "Block device driver" - depends on ARCH_XEN - help - Block device driver for Xen diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/Kconfig b/linux-2.6-xen-sparse/drivers/xen/netfront/Kconfig deleted file mode 100644 index 334e6c3863..0000000000 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/Kconfig +++ /dev/null @@ -1,6 +0,0 @@ - -config XENNET - tristate "Xen network driver" - depends on NETDEVICES && ARCH_XEN - help - Network driver for Xen From 981d16a1283767c9b6ace56ec5814b8238c7a381 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 19 Jan 2006 09:12:40 +0100 Subject: [PATCH 82/97] Cleanup dirty code avoiding warning messages when compiling ioemu. Signed-off-by: Haifeng Xue --- tools/firmware/vmxassist/acpi_madt.c | 1 - tools/ioemu/audio/noaudio.c | 2 -- tools/ioemu/cpu.h | 3 +++ tools/ioemu/hw/pc.c | 2 -- tools/ioemu/vl.c | 2 +- tools/ioemu/vl.h | 3 +++ 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/firmware/vmxassist/acpi_madt.c b/tools/firmware/vmxassist/acpi_madt.c index 8e86646067..59e47b71c7 100644 --- a/tools/firmware/vmxassist/acpi_madt.c +++ b/tools/firmware/vmxassist/acpi_madt.c @@ -55,7 +55,6 @@ static struct hvm_info_table * get_hvm_info_table(void) { struct hvm_info_table *t; - int i; if (table != NULL) return table; diff --git a/tools/ioemu/audio/noaudio.c b/tools/ioemu/audio/noaudio.c index 819de1e538..a192885a72 100644 --- a/tools/ioemu/audio/noaudio.c +++ b/tools/ioemu/audio/noaudio.c @@ -41,7 +41,6 @@ static void no_hw_run (HWVoice *hw) { 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_write (SWVoice *sw, void *buf, int len) 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 --git a/tools/ioemu/cpu.h b/tools/ioemu/cpu.h index a3e24f2ea9..080362eaa1 100644 --- a/tools/ioemu/cpu.h +++ b/tools/ioemu/cpu.h @@ -63,6 +63,9 @@ int cpu_get_pic_interrupt(CPUX86State *s); /* 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 --git a/tools/ioemu/hw/pc.c b/tools/ioemu/hw/pc.c index 055ab885a5..c786132d14 100644 --- a/tools/ioemu/hw/pc.c +++ b/tools/ioemu/hw/pc.c @@ -382,8 +382,6 @@ void pc_init(uint64_t ram_size, int vga_ram_size, int boot_device, { 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 --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index f38f90b0c6..736a762d19 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -1204,7 +1204,7 @@ int store_console_dev(int domid, char *pts) 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 --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h index fa03595a65..2b30dc8f26 100644 --- a/tools/ioemu/vl.h +++ b/tools/ioemu/vl.h @@ -354,6 +354,9 @@ int register_savevm(const char *idstr, 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; From 1d2c4dd17193c2cc9543ce07c614fd0d6d32aa12 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 19 Jan 2006 09:16:01 +0100 Subject: [PATCH 83/97] Having /usr/bin/xsls conflicts with xsls as distributed in scalapack (http://www.netlib.org/scalapack/). It should probably be xenstore-ls a) for namespacing and b) to match up with the other xenstore commands better. Signed-off-by: Jeremy Katz --- .hgignore | 2 +- tools/xenstore/Makefile | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.hgignore b/.hgignore index 9a52e9ce12..f867e970e1 100644 --- a/.hgignore +++ b/.hgignore @@ -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 --git a/tools/xenstore/Makefile b/tools/xenstore/Makefile index 7b56ad497b..a6ba3ee2dc 100644 --- a/tools/xenstore/Makefile +++ b/tools/xenstore/Makefile @@ -27,7 +27,7 @@ CLIENTS := xenstore-exists xenstore-list xenstore-read xenstore-rm 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): xenstore-%: xenstore_%.o libxenstore.so $(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 @@ libxenstore.so: xs.opic xs_lib.opic 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 @@ TAGS: 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: libxenstore.so xenstored xsls $(CLIENTS) $(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 From 55d921d433ae0c47af53247dad9af0f536de9ff7 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 19 Jan 2006 20:04:53 +0100 Subject: [PATCH 84/97] Fix a bug that causes storage key auth to be generated twice. Signed-off-by: Vinnie Scarlata --- tools/vtpm_manager/manager/vtpm_manager.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/vtpm_manager/manager/vtpm_manager.c b/tools/vtpm_manager/manager/vtpm_manager.c index c9eda0440c..ab391a6ccc 100644 --- a/tools/vtpm_manager/manager/vtpm_manager.c +++ b/tools/vtpm_manager/manager/vtpm_manager.c @@ -151,9 +151,6 @@ TPM_RESULT VTPM_Create_Service(){ &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)); From 31415c26f92b9b3c4b70032a7f768e7c19dfb0db Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 19 Jan 2006 20:11:09 +0100 Subject: [PATCH 85/97] Allow disabling the tx checksums on the xen loopback interface, which is used for the virtual interfaces of dom0 instead of netfront/netback. I need to issue ethtool -K eth0 tx off to work around a bad checksum problem, which has been reported for domUs a few months ago. I'm bridging dom0's eth0 to a domU where I do NAT to a different virtual interface. Without this change, I get lots of packets with bad checksums. Signed-off-by: Jan Niehusmann --- linux-2.6-xen-sparse/drivers/xen/netback/loopback.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c index 31f7978af8..58a717e36f 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c @@ -27,6 +27,7 @@ #include #include #include +#include #include static int nloopbacks = 8; @@ -122,6 +123,12 @@ static void loopback_construct(struct net_device *dev, struct net_device *lo) /*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; @@ -141,6 +148,8 @@ static int __init make_loopback(int i) 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 * choose the numerically largest non-broadcast address to prevent the From 55fe40b0d137fbcc78dc95353daf1dca76c7a5ab Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 20 Jan 2006 20:31:09 +0100 Subject: [PATCH 86/97] The arguments to memset are ordered incorrectly in the pcm_hw_clear function of audio.c. Signed-off-by: Charles Coffing --- tools/ioemu/audio/audio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ioemu/audio/audio.c b/tools/ioemu/audio/audio.c index 661771e82e..c3782d58a2 100644 --- a/tools/ioemu/audio/audio.c +++ b/tools/ioemu/audio/audio.c @@ -257,11 +257,11 @@ void pcm_hw_clear (HWVoice *hw, void *buf, int len) 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: From 5a132f767473c79cf9bf749a46aa7c54fffbfec9 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 23 Jan 2006 15:17:14 +0100 Subject: [PATCH 87/97] Emergency system halt should halt all processors, not just the crashing processor. Signed-off-by: Jan Beulich --- xen/arch/x86/domain.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 759bbadb21..4fd39ad903 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -110,6 +110,20 @@ static inline void kb_wait(void) 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 @@ void machine_restart(char * __unused) if ( opt_noreboot ) { printk("Reboot disabled on cmdline: require manual reset\n"); - for ( ; ; ) - safe_halt(); + machine_halt(); } watchdog_disable(); @@ -164,20 +177,6 @@ void machine_restart(char * __unused) } -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; From e3f67392ec0dbc97ca73d548208aaebaaaac32d7 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 23 Jan 2006 15:47:00 +0100 Subject: [PATCH 88/97] ia64 specific part of gdbstub. Signed-off-by: Isaku Yamahtata --- xen/arch/ia64/Makefile | 4 + xen/arch/ia64/vmx/vmx_process.c | 9 + xen/arch/ia64/xen/gdbstub.c | 811 ++++++++++++++++++++++++++++++++ xen/arch/ia64/xen/hyperprivop.S | 8 +- xen/arch/ia64/xen/ivt.S | 8 + xen/arch/ia64/xen/process.c | 12 +- xen/arch/ia64/xen/xenmisc.c | 6 + xen/include/asm-ia64/debugger.h | 67 ++- 8 files changed, 921 insertions(+), 4 deletions(-) create mode 100644 xen/arch/ia64/xen/gdbstub.c diff --git a/xen/arch/ia64/Makefile b/xen/arch/ia64/Makefile index 62f9da9cf3..ed134a2fb0 100644 --- a/xen/arch/ia64/Makefile +++ b/xen/arch/ia64/Makefile @@ -23,6 +23,10 @@ OBJS += bitop.o clear_page.o flush.o copy_page_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 OBJS += unwind.o diff --git a/xen/arch/ia64/vmx/vmx_process.c b/xen/arch/ia64/vmx/vmx_process.c index 99e4770091..28b6074dac 100644 --- a/xen/arch/ia64/vmx/vmx_process.c +++ b/xen/arch/ia64/vmx/vmx_process.c @@ -41,6 +41,7 @@ #include #include #include +#include //#include #include #include @@ -107,6 +108,14 @@ vmx_ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long is 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 --git a/xen/arch/ia64/xen/gdbstub.c b/xen/arch/ia64/xen/gdbstub.c new file mode 100644 index 0000000000..e846a09db9 --- /dev/null +++ b/xen/arch/ia64/xen/gdbstub.c @@ -0,0 +1,811 @@ +/* + * ia64-specific cdb routines + * cdb xen/ia64 by Isaku Yamahta + * 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 + * Modified for 386 by Jim Kingdon, Cygnus Support. + * Origianl kgdb, compatibility with 2.1.xx kernel by David Grothe + * + */ + + +#include +#include +#include +#include + +#define USE_UNWIND + +#ifdef USE_UNWIND +#include +#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 --git a/xen/arch/ia64/xen/hyperprivop.S b/xen/arch/ia64/xen/hyperprivop.S index c3d7b9dbcb..0f6c37b433 100644 --- a/xen/arch/ia64/xen/hyperprivop.S +++ b/xen/arch/ia64/xen/hyperprivop.S @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -549,7 +550,12 @@ GLOBAL_ENTRY(fast_break_reflect) (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 --git a/xen/arch/ia64/xen/ivt.S b/xen/arch/ia64/xen/ivt.S index c72084ea50..26e6b3dbf3 100644 --- a/xen/arch/ia64/xen/ivt.S +++ b/xen/arch/ia64/xen/ivt.S @@ -15,6 +15,7 @@ #define sys_call_table 0 #define sys_ni_syscall 0 #include +#include #endif /* * arch/ia64/kernel/ivt.S @@ -841,6 +842,13 @@ ENTRY(break_fault) ;; 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 --git a/xen/arch/ia64/xen/process.c b/xen/arch/ia64/xen/process.c index e1da875cdb..249b5e93b6 100644 --- a/xen/arch/ia64/xen/process.c +++ b/xen/arch/ia64/xen/process.c @@ -31,6 +31,7 @@ #include #include "hpsim_ssc.h" #include +#include 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 @@ void 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 @@ ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long isr, u 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 --git a/xen/arch/ia64/xen/xenmisc.c b/xen/arch/ia64/xen/xenmisc.c index 85b140dd42..f2d5b708f4 100644 --- a/xen/arch/ia64/xen/xenmisc.c +++ b/xen/arch/ia64/xen/xenmisc.c @@ -18,6 +18,7 @@ #include #include #include +#include efi_memory_desc_t ia64_efi_io_md; EXPORT_SYMBOL(ia64_efi_io_md); @@ -356,6 +357,11 @@ loop: 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 --git a/xen/include/asm-ia64/debugger.h b/xen/include/asm-ia64/debugger.h index e933b11487..50e6475200 100644 --- a/xen/include/asm-ia64/debugger.h +++ b/xen/include/asm-ia64/debugger.h @@ -24,6 +24,54 @@ #include +// 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 + +// 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 @@ static inline int debugger_trap_fatal( 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__ */ From 05e845bdedb8c22bda0ad097b39eb5a3b6f5b078 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 23 Jan 2006 16:27:00 +0100 Subject: [PATCH 89/97] The present pud_offset_k implementation runs the value read through the m2p translation process twice. With that removed, it can then also be simplified. Signed-off-by: Jan Beulich --- linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h index 0e00baf30e..010044c623 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h @@ -417,12 +417,7 @@ static inline pud_t *__pud_offset_k(pud_t *pud, unsigned long address) 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 */ From 6ab3d2a42109645b5b3fccc8838afa0fcf9ff4dd Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Tue, 24 Jan 2006 10:37:44 +0000 Subject: [PATCH 90/97] dup and open error value is -1, not < 0 Signed-off-by: Vincent Hanquez --- tools/xenstore/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/xenstore/utils.c b/tools/xenstore/utils.c index 2bc40e009b..1bf8606b40 100644 --- a/tools/xenstore/utils.c +++ b/tools/xenstore/utils.c @@ -92,7 +92,7 @@ void *grab_file(const char *filename, unsigned long *size) else fd = open(filename, O_RDONLY, 0); - if (fd < 0) + if (fd == -1) return NULL; buffer = malloc(max+1); From 69f3c56296800ab0283a35a599c0bdd0e00443b4 Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Tue, 24 Jan 2006 10:52:52 +0000 Subject: [PATCH 91/97] fixup reallocation to "twice the size + 1", instead of "3 times the size". max *= 2 + 1 <==> max *= 3 Signed-off-by: Vincent Hanquez --- tools/xenstore/utils.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/xenstore/utils.c b/tools/xenstore/utils.c index 1bf8606b40..f8bf989c22 100644 --- a/tools/xenstore/utils.c +++ b/tools/xenstore/utils.c @@ -99,8 +99,10 @@ void *grab_file(const char *filename, unsigned long *size) *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) { + max *= 2; + buffer = realloc(buffer, max + 1); + } } if (ret < 0) { free(buffer); From caeab9b2e04d046e86a003c8ed387fe6d63be641 Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Tue, 24 Jan 2006 10:55:45 +0000 Subject: [PATCH 92/97] fixup memory leak and return value, if malloc or realloc fail. Signed-off-by: Vincent Hanquez --- tools/xenstore/utils.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/tools/xenstore/utils.c b/tools/xenstore/utils.c index f8bf989c22..6655777bcd 100644 --- a/tools/xenstore/utils.c +++ b/tools/xenstore/utils.c @@ -96,21 +96,29 @@ void *grab_file(const char *filename, unsigned long *size) 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) { + void *nbuffer; max *= 2; - buffer = realloc(buffer, max + 1); + 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))) From 620d876900639056de7274cd7a5b3e96bf9d1586 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 24 Jan 2006 12:26:38 +0100 Subject: [PATCH 93/97] Two shell commands weren't properly spaced in a makefile. Signed-off-by: Jan Beulich --- tools/xentrace/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/xentrace/Makefile b/tools/xentrace/Makefile index cf91113105..e814d0f2e8 100644 --- a/tools/xentrace/Makefile +++ b/tools/xentrace/Makefile @@ -33,14 +33,14 @@ build: $(BIN) $(LIBBIN) 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 From 79157a6885b99b18a3638467602299011f34ffd9 Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Tue, 24 Jan 2006 11:50:38 +0000 Subject: [PATCH 94/97] use format printf style to write to tracefd instead of using write syscall. add a static buffer to trace() instead of always allocating from the heap. Signed-off-by: Vincent Hanquez --- tools/xenstore/xenstored_core.c | 86 +++++++++++++++------------------ 1 file changed, 38 insertions(+), 48 deletions(-) diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c index 6afde0ae80..b55731fe16 100644 --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -174,11 +174,38 @@ static char *sockmsg_string(enum xsd_sockmsg_type type) } } +void trace(const char *fmt, ...) +{ + va_list arglist; + char *str; + char sbuf[1024]; + int ret; + + if (tracefd < 0) + return; + + /* 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; + } + + /* fail back to dynamic allocation */ + va_start(arglist, fmt); + str = talloc_vasprintf(NULL, fmt, arglist); + va_end(arglist); + write(tracefd, str, strlen(str)); + talloc_free(str); +} + 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; @@ -189,62 +216,25 @@ static void trace_io(const struct connection *conn, 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); + 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) { - char string[64]; - if (tracefd < 0) - return; - - write(tracefd, "CREATE ", strlen("CREATE ")); - write(tracefd, type, strlen(type)); - sprintf(string, " %p\n", data); - write(tracefd, string, strlen(string)); + trace("CREATE %s %p\n", type, data); } 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)); + trace("DESTROY %s %p\n", type, data); } -void trace(const char *fmt, ...) -{ - va_list arglist; - char *str; - - if (tracefd < 0) - return; - - va_start(arglist, fmt); - str = talloc_vasprintf(NULL, fmt, arglist); - va_end(arglist); - write(tracefd, str, strlen(str)); - talloc_free(str); -} - - /** * Signal handler for SIGHUP, which requests that the trace log is reopened * (in the main loop). A single byte is written to reopen_log_pipe, to awaken @@ -268,7 +258,7 @@ static void reopen_log() if (tracefd < 0) perror("Could not open tracefile"); else - write(tracefd, "\n***\n", strlen("\n***\n")); + trace("\n***\n"); } } From 78f406938d90fec6b2014e6d3a423d37e51b42da Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Tue, 24 Jan 2006 12:03:06 +0000 Subject: [PATCH 95/97] use talloc_zero instead of talloc + memset Signed-off-by: Vincent Hanquez --- tools/xenstore/xenstored_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c index b55731fe16..82080ee70e 100644 --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -1301,11 +1301,10 @@ struct connection *new_connection(connwritefn_t *write, connreadfn_t *read) { 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; From 9ebf278d68a912b6cd6eed3c215c4e1e19ac295c Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Tue, 24 Jan 2006 13:14:42 +0000 Subject: [PATCH 96/97] add some checking of opening and read in dom0_init and return -1 if error. instead of crashing, it now prints a more meaningful error message. Signed-off-by: Vincent Hanquez --- tools/xenstore/xenstored_domain.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c index 353ef9b7ac..cf862e4b8b 100644 --- a/tools/xenstore/xenstored_domain.c +++ b/tools/xenstore/xenstored_domain.c @@ -468,28 +468,38 @@ static int dom0_init(void) 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; } From ba032ccb43f3d21e5a79d9d0756aa5cc7aa67c08 Mon Sep 17 00:00:00 2001 From: "vhanquez@kneesa.uk.xensource.com" Date: Tue, 24 Jan 2006 13:21:11 +0000 Subject: [PATCH 97/97] reindent few lines that were using softtab instead of hardtab. Signed-off-by: Vincent Hanquez --- tools/xenstore/xenstored_domain.c | 76 +++++++++++++++---------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c index cf862e4b8b..fb73771787 100644 --- a/tools/xenstore/xenstored_domain.c +++ b/tools/xenstore/xenstored_domain.c @@ -278,12 +278,12 @@ static struct domain *new_domain(void *context, unsigned int domid, 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 @@ void do_is_domain_introduced(struct connection *conn, const char *domid_str) 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,42 +461,42 @@ void restore_existing_connections(void) 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); + 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)); + + 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); + 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)); + + 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); + str[rc] = '\0'; + port = strtoul(str, NULL, 0); - evtchn_notify(dom0->port); + close(fd); - return 0; + dom0 = new_domain(NULL, 0, mfn, port); + talloc_steal(dom0->conn, dom0); + + evtchn_notify(dom0->port); + + return 0; outfd: close(fd); return -1; @@ -549,9 +549,9 @@ int domain_init(void) 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)