diff --git a/.rootkeys b/.rootkeys index adfd56a286..7b0e0c9a5b 100644 --- a/.rootkeys +++ b/.rootkeys @@ -155,6 +155,7 @@ 40f56238wi6AdNQjm0RT57bSkwb6hg linux-2.6.7-xen-sparse/arch/xen/i386/kernel/vsyscall.lds 40f56238a3w6-byOzexIlMgni76Lcg linux-2.6.7-xen-sparse/arch/xen/i386/mm/Makefile 40f56238ILx8xlbywNbzTdv5Zr4xXQ linux-2.6.7-xen-sparse/arch/xen/i386/mm/fault.c +4118cc35CbY8rfGVspF5O-7EkXBEAA linux-2.6.7-xen-sparse/arch/xen/i386/mm/highmem.c 40f562383SKvDStdtrvzr5fyCbW4rw linux-2.6.7-xen-sparse/arch/xen/i386/mm/hypervisor.c 40f56239xcNylAxuGsQHwi1AyMLV8w linux-2.6.7-xen-sparse/arch/xen/i386/mm/init.c 41062ab7CjxC1UBaFhOMWWdhHkIUyg linux-2.6.7-xen-sparse/arch/xen/i386/mm/ioremap.c @@ -202,6 +203,7 @@ 4107adf1E5O4ztGHNGMzCCNhcvqNow linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/dma-mapping.h 40f5623anSzpuEHgiNmQ56fIRfCoaQ linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/e820.h 40f5623akIoBsQ3KxSB2kufkbgONXQ linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/fixmap.h +4118b6a418gnL6AZsTdglC92YGqYTg linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/highmem.h 40f5623aJVXQwpJMOLE99XgvGsfQ8Q linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/io.h 40f5623am9BzluYFuV6EQfTd-so3dA linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/mach-xen/do_timer.h 40f5623adZQ1IZGPxbDXONjyZGYuTA linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/mach-xen/io_ports.h diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/main.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/main.c index 015d62c624..0d5fd96968 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/main.c +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/main.c @@ -805,4 +805,16 @@ void blkdev_suspend(void) void blkdev_resume(void) { + ctrl_msg_t cmsg; + blkif_fe_driver_status_changed_t st; + + + /* Send a driver-UP notification to the domain controller. */ + cmsg.type = CMSG_BLKIF_FE; + cmsg.subtype = CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED; + cmsg.length = sizeof(blkif_fe_driver_status_changed_t); + st.status = BLKIF_DRIVER_STATUS_UP; + memcpy(cmsg.msg, &st, sizeof(st)); + ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); } + diff --git a/linux-2.4.26-xen-sparse/arch/xen/kernel/i386_ksyms.c b/linux-2.4.26-xen-sparse/arch/xen/kernel/i386_ksyms.c index 8b72e44f12..0938a64f65 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/kernel/i386_ksyms.c +++ b/linux-2.4.26-xen-sparse/arch/xen/kernel/i386_ksyms.c @@ -176,4 +176,5 @@ EXPORT_SYMBOL(create_xen_proc_entry); EXPORT_SYMBOL(remove_xen_proc_entry); EXPORT_SYMBOL(evtchn_do_upcall); +EXPORT_SYMBOL(force_evtchn_callback); EXPORT_SYMBOL(HYPERVISOR_shared_info); diff --git a/linux-2.4.26-xen-sparse/arch/xen/kernel/setup.c b/linux-2.4.26-xen-sparse/arch/xen/kernel/setup.c index c218d199d1..6acd49bc06 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/kernel/setup.c +++ b/linux-2.4.26-xen-sparse/arch/xen/kernel/setup.c @@ -1200,6 +1200,7 @@ static void __do_suspend(void) /* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */ extern void blkdev_suspend(void); extern void blkdev_resume(void); + extern void netif_resume(void); extern void time_suspend(void); extern void time_resume(void); @@ -1248,8 +1249,8 @@ static void __do_suspend(void) __sti(); - //blkdev_resume(); - //netdev_resume(); + blkdev_resume(); + netif_resume(); out: if ( suspend_record != NULL ) diff --git a/linux-2.6.7-xen-sparse/arch/xen/i386/Kconfig b/linux-2.6.7-xen-sparse/arch/xen/i386/Kconfig index 0cfb2d40a6..1a051d436d 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/i386/Kconfig +++ b/linux-2.6.7-xen-sparse/arch/xen/i386/Kconfig @@ -555,14 +555,14 @@ config HAVE_ARCH_BOOTMEM_NODE depends on NUMA default y -config HIGHPTE - bool "Allocate 3rd-level pagetables from highmem" - depends on HIGHMEM4G || HIGHMEM64G - help - The VM uses one page table entry for each page of physical memory. - For systems with a lot of RAM, this can be wasteful of precious - low memory. Setting this option will put user-space page table - entries in high memory. +#config HIGHPTE +# bool "Allocate 3rd-level pagetables from highmem" +# depends on HIGHMEM4G || HIGHMEM64G +# help +# The VM uses one page table entry for each page of physical memory. +# For systems with a lot of RAM, this can be wasteful of precious +# low memory. Setting this option will put user-space page table +# entries in high memory. #config MTRR # bool "MTRR (Memory Type Range Register) support" diff --git a/linux-2.6.7-xen-sparse/arch/xen/i386/mm/Makefile b/linux-2.6.7-xen-sparse/arch/xen/i386/mm/Makefile index a0f3470825..55063591f0 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/i386/mm/Makefile +++ b/linux-2.6.7-xen-sparse/arch/xen/i386/mm/Makefile @@ -11,7 +11,7 @@ c-obj-y := extable.o pageattr.o c-obj-$(CONFIG_DISCONTIGMEM) += discontig.o c-obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o -c-obj-$(CONFIG_HIGHMEM) += highmem.o +obj-$(CONFIG_HIGHMEM) += highmem.o c-obj-$(CONFIG_BOOT_IOREMAP) += boot_ioremap.o c-link := diff --git a/linux-2.6.7-xen-sparse/arch/xen/i386/mm/fault.c b/linux-2.6.7-xen-sparse/arch/xen/i386/mm/fault.c index d850d279d5..f508ccd8c3 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/i386/mm/fault.c +++ b/linux-2.6.7-xen-sparse/arch/xen/i386/mm/fault.c @@ -248,7 +248,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code, * (error_code & 4) == 0, and that the fault was not a * protection error (error_code & 1) == 0. */ - if (unlikely(address >= TASK_SIZE)) { + if (unlikely(address >= TASK_SIZE) || + unlikely(address < (FIRST_USER_PGD_NR< + +void *kmap(struct page *page) +{ + might_sleep(); + if (page < highmem_start_page) + return page_address(page); + return kmap_high(page); +} + +void kunmap(struct page *page) +{ + if (in_interrupt()) + BUG(); + if (page < highmem_start_page) + return; + kunmap_high(page); +} + +/* + * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because + * no global lock is needed and because the kmap code must perform a global TLB + * invalidation when the kmap pool wraps. + * + * However when holding an atomic kmap is is not legal to sleep, so atomic + * kmaps are appropriate for short, tight code paths only. + */ +void *kmap_atomic(struct page *page, enum km_type type) +{ + enum fixed_addresses idx; + unsigned long vaddr; + + /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ + inc_preempt_count(); + if (page < highmem_start_page) + return page_address(page); + + idx = type + KM_TYPE_NR*smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); +#ifdef CONFIG_DEBUG_HIGHMEM + if (!pte_none(*(kmap_pte-idx))) + BUG(); +#endif + set_pte(kmap_pte-idx, mk_pte(page, kmap_prot)); + __flush_tlb_one(vaddr); + + return (void*) vaddr; +} + +/* Same as kmap_atomic but with PAGE_KERNEL_RO page protection */ +void *kmap_atomic_pte(struct page *page, enum km_type type) +{ + enum fixed_addresses idx; + unsigned long vaddr; + + /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ + inc_preempt_count(); + if (page < highmem_start_page) + return page_address(page); + + idx = type + KM_TYPE_NR*smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); +#ifdef CONFIG_DEBUG_HIGHMEM + if (!pte_none(*(kmap_pte-idx))) + BUG(); +#endif + set_pte(kmap_pte-idx, mk_pte(page, PAGE_KERNEL_RO)); + __flush_tlb_one(vaddr); + + return (void*) vaddr; +} + +void kunmap_atomic(void *kvaddr, enum km_type type) +{ +#ifdef CONFIG_DEBUG_HIGHMEM + unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; + enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); + + if (vaddr < FIXADDR_START) { // FIXME + dec_preempt_count(); + preempt_check_resched(); + return; + } + + if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx)) + BUG(); + + /* + * force other mappings to Oops if they'll try to access + * this pte without first remap it + */ + pte_clear(kmap_pte-idx); + __flush_tlb_one(vaddr); +#endif + + dec_preempt_count(); + preempt_check_resched(); +} + +void kunmap_atomic_force(void *kvaddr, enum km_type type) +{ + unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; + enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); + + if (vaddr < FIXADDR_START) { // FIXME + dec_preempt_count(); + preempt_check_resched(); + return; + } + + if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx)) + BUG(); + + /* + * force other mappings to Oops if they'll try to access + * this pte without first remap it + */ + pte_clear(kmap_pte-idx); + __flush_tlb_one(vaddr); + + dec_preempt_count(); + preempt_check_resched(); +} + +struct page *kmap_atomic_to_page(void *ptr) +{ + unsigned long idx, vaddr = (unsigned long)ptr; + pte_t *pte; + + if (vaddr < FIXADDR_START) + return virt_to_page(ptr); + + idx = virt_to_fix(vaddr); + pte = kmap_pte - (idx - FIX_KMAP_BEGIN); + return pte_page(*pte); +} + diff --git a/linux-2.6.7-xen-sparse/arch/xen/i386/mm/pgtable.c b/linux-2.6.7-xen-sparse/arch/xen/i386/mm/pgtable.c index cbab491f2e..31c2fb0e5f 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/i386/mm/pgtable.c +++ b/linux-2.6.7-xen-sparse/arch/xen/i386/mm/pgtable.c @@ -194,9 +194,17 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0); #endif if (pte) { +#ifdef CONFIG_HIGHPTE + void *kaddr = kmap_atomic(pte, KM_USER0); + clear_page(kaddr); + kunmap_atomic_force(kaddr, KM_USER0); +#else clear_highpage(pte); +#endif +#ifdef CONFIG_HIGHPTE + if (pte < highmem_start_page) +#endif __make_page_readonly(phys_to_virt(page_to_pseudophys(pte))); - /* XXXcl highmem */ } return pte; } @@ -250,16 +258,21 @@ void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused) if (PTRS_PER_PMD == 1) spin_lock_irqsave(&pgd_lock, flags); - memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD, - swapper_pg_dir + USER_PTRS_PER_PGD, - (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); + memcpy((pgd_t *)pgd, + swapper_pg_dir, + FIRST_USER_PGD_NR * sizeof(pgd_t)); + memcpy((pgd_t *)pgd + FIRST_USER_PGD_NR + USER_PTRS_PER_PGD, + swapper_pg_dir + FIRST_USER_PGD_NR + USER_PTRS_PER_PGD, + (PTRS_PER_PGD - USER_PTRS_PER_PGD - + FIRST_USER_PGD_NR) * sizeof(pgd_t)); if (PTRS_PER_PMD > 1) goto out; pgd_list_add(pgd); spin_unlock_irqrestore(&pgd_lock, flags); - memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t)); + memset((pgd_t *)pgd + FIRST_USER_PGD_NR, + 0, USER_PTRS_PER_PGD*sizeof(pgd_t)); out: __make_page_readonly(pgd); queue_pgd_pin(__pa(pgd)); diff --git a/linux-2.6.7-xen-sparse/arch/xen/kernel/ctrl_if.c b/linux-2.6.7-xen-sparse/arch/xen/kernel/ctrl_if.c index c5d12db779..c4ace2b6f9 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/kernel/ctrl_if.c +++ b/linux-2.6.7-xen-sparse/arch/xen/kernel/ctrl_if.c @@ -383,21 +383,10 @@ void ctrl_if_suspend(void) unbind_evtchn_from_irq(ctrl_if_evtchn); } -/** Reset the control interface progress pointers. - * Marks the queues empty if 'clear' non-zero. - */ -void ctrl_if_reset(int clear){ - control_if_t *ctrl_if = get_ctrl_if(); - - if(clear){ - *ctrl_if = (control_if_t){}; - } - ctrl_if_tx_resp_cons = ctrl_if->tx_resp_prod; - ctrl_if_rx_req_cons = ctrl_if->rx_resp_prod; -} - void ctrl_if_resume(void) { + control_if_t *ctrl_if = get_ctrl_if(); + if ( start_info.flags & SIF_INITDOMAIN ) { /* @@ -415,7 +404,9 @@ void ctrl_if_resume(void) initdom_ctrlif_domcontroller_port = op.u.bind_interdomain.port2; } - ctrl_if_reset(0); + /* Sync up with shared indexes. */ + ctrl_if_tx_resp_cons = ctrl_if->tx_resp_prod; + ctrl_if_rx_req_cons = ctrl_if->rx_resp_prod; ctrl_if_evtchn = start_info.domain_controller_evtchn; ctrl_if_irq = bind_evtchn_to_irq(ctrl_if_evtchn); @@ -444,7 +435,6 @@ void __init ctrl_if_init(void) spin_lock_init(&ctrl_if_lock); - ctrl_if_reset(1); ctrl_if_resume(); } @@ -455,8 +445,8 @@ static int __init ctrl_if_late_setup(void) safe_to_schedule_task = 1; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ctrl_if_tx_wq = create_workqueue("ctrl_if_tx"); - if (ctrl_if_tx_wq == NULL) - return 1; /* XXX */ + if ( ctrl_if_tx_wq == NULL ) + return 1; #endif return 0; } diff --git a/linux-2.6.7-xen-sparse/arch/xen/kernel/evtchn.c b/linux-2.6.7-xen-sparse/arch/xen/kernel/evtchn.c index 06d6ae948e..87eda48725 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/kernel/evtchn.c +++ b/linux-2.6.7-xen-sparse/arch/xen/kernel/evtchn.c @@ -22,6 +22,11 @@ #include #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +EXPORT_SYMBOL(force_evtchn_callback); +EXPORT_SYMBOL(evtchn_do_upcall); +#endif + /* * This lock protects updates to the following mapping and reference-count * arrays. The lock does not need to be acquired to read the mapping tables. @@ -93,9 +98,6 @@ void evtchn_do_upcall(struct pt_regs *regs) local_irq_restore(flags); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -EXPORT_SYMBOL(evtchn_do_upcall); -#endif static int find_unbound_irq(void) { diff --git a/linux-2.6.7-xen-sparse/arch/xen/kernel/fixup.c b/linux-2.6.7-xen-sparse/arch/xen/kernel/fixup.c index 61c5497f40..f35b491876 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/kernel/fixup.c +++ b/linux-2.6.7-xen-sparse/arch/xen/kernel/fixup.c @@ -27,11 +27,12 @@ #include #include #include +#include #include #include #include -#if 0 +#if 1 #define ASSERT(_p) \ if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \ __LINE__, __FILE__); *(int*)0=0; } @@ -43,35 +44,57 @@ #define DPRINTK(_f, _a...) ((void)0) #endif +static char *fixup_buf; +#define FIXUP_BUF_USER PAGE_SIZE +#define FIXUP_BUF_ORDER 1 +#define FIXUP_BUF_SIZE (PAGE_SIZE<eip - insn_len; struct fixup_entry *fe; pte_t *pte; @@ -198,28 +224,50 @@ asmlinkage void do_fixup_4gb_segment(struct pt_regs *regs, long error_code) if ( unlikely(eip >= (PAGE_OFFSET-32)) ) { - if ( (eip < fixup_buf_user) || (eip >= (fixup_buf_user+PAGE_SIZE-32)) ) - { - DPRINTK("User executing out of kernel space?!"); - return; - } - /* We know it's safe to directly copy teh bytes into our buffer. */ - memcpy(b, (void *)eip, sizeof(b)); - } - else if ( unlikely(copy_from_user(b, (void *)eip, sizeof(b)) != 0) ) - { - DPRINTK("Could not read instruction bytes from user space."); + DPRINTK("User executing out of kernel space?!"); return; } - - if ( unlikely(((eip ^ (eip+5)) & PAGE_MASK) != 0) ) + + if ( unlikely(((eip ^ (eip+PATCH_LEN)) & PAGE_MASK) != 0) ) { DPRINTK("Patch instruction would straddle a page boundary."); return; } + /* + * Check that the page to be patched is part of a read-only VMA. This + * means that our patch will never erroneously get flushed to disc. + */ + if ( eip > (FIXUP_BUF_USER + FIXUP_BUF_SIZE) ) /* don't check fixup area */ + { + /* [SMP] Need to the mmap_sem semaphore. */ + struct vm_area_struct *vma = find_vma(current->mm, eip); + if ( (vma == NULL) || (vma->vm_flags & VM_MAYSHARE) ) + { + DPRINTK("Cannot patch a shareable VMA."); + return; + } + } + + if ( unlikely(copy_from_user(b, (void *)eip, sizeof(b)) != 0) ) + { + DPRINTK("Could not read instruction bytes from user space."); + return; + } + + /* Already created a fixup for this address and code sequence? */ + hash = FIXUP_HASH(b); + for ( fe = fixup_hash[hash]; + fe != NULL; fe = fe->next ) + { + if ( eip != fe->patch_addr ) + continue; /* XXX */ + if ( memcmp(fe->patched_code, b, fe->patched_code_len) == 0 ) + goto do_the_patch; + } + /* Guaranteed enough room to patch? */ - if ( unlikely(fixup_idx > (PAGE_SIZE-32)) ) + if ( unlikely((fi = fixup_idx) > (FIXUP_BUF_SIZE-32)) ) { static int printed = 0; if ( !printed ) @@ -268,40 +316,105 @@ asmlinkage void do_fixup_4gb_segment(struct pt_regs *regs, long error_code) return; } - while ( insn_len < 5 ) + /* Indirect jump pointer. */ + *(u32 *)&fixup_buf[fi] = FIXUP_BUF_USER + fi + 4; + fi += 4; + + /* push */ + if ( save_indirect_reg ) + fixup_buf[fi++] = 0x50 + rm; + + /* add %gs:0, */ + fixup_buf[fi++] = 0x65; + fixup_buf[fi++] = 0x03; + fixup_buf[fi++] = 0x05 | (rm << 3); + *(unsigned long *)&fixup_buf[fi] = 0; + fi += 4; + + /* Relocate the faulting instruction, minus the GS override. */ + memcpy(&fixup_buf[fi], &b[1], error_code - 1); + fi += error_code - 1; + + /* pop */ + if ( save_indirect_reg ) + fixup_buf[fi++] = 0x58 + rm; + + for ( ; ; ) { + if ( insn_len >= PATCH_LEN ) + { + /* ret */ + fixup_buf[fi++] = 0xc3; + break; + } + /* Bail if can't decode the following instruction. */ if ( unlikely((new_insn_len = - get_insn_len(&b[insn_len], &opcode)) == 0) ) + get_insn_len(&b[insn_len], &opcode, &decode)) == 0) ) { DPRINTK("Could not decode following instruction."); return; } - /* We track one 8-bit relative offset for patching later. */ - if ( ((opcode >= 0x70) && (opcode <= 0x7f)) || (opcode == 0xeb) ) + if ( (decode & CODE_MASK) == JMP ) { - if ( relbyte_idx != -1 ) - { - DPRINTK("Multiple relative offsets in patch seq!"); - return; - } - relbyte_idx = insn_len; - while ( b[relbyte_idx] != opcode ) - relbyte_idx++; - relbyte_idx++; + return; + + memcpy(&fixup_buf[fi], &b[insn_len], new_insn_len - 1); + fi += new_insn_len - 1; + + /* Patch the 8-bit relative offset. */ + fixup_buf[fi++] = 1; + + insn_len += new_insn_len; + ASSERT(insn_len >= PATCH_LEN); + + /* ret */ + fixup_buf[fi++] = 0xc3; + + /* jmp */ + fixup_buf[fi++] = 0xe9; + fi += 4; + *(unsigned long *)&fixup_buf[fi-4] = + (eip + insn_len + (long)(char)b[insn_len-1]) - + (FIXUP_BUF_USER + fi); + + break; } else if ( opcode == 0xe9 ) { - if ( relword_idx != -1 ) - { - DPRINTK("Multiple relative offsets in patch seq!"); - return; - } - relword_idx = insn_len; - while ( b[relword_idx] != opcode ) - relword_idx++; - relword_idx++; + return; + + memcpy(&fixup_buf[fi], &b[insn_len], new_insn_len - 4); + fi += new_insn_len - 4; + + insn_len += new_insn_len; + ASSERT(insn_len >= PATCH_LEN); + + /* Patch the 32-bit relative offset. */ + fi += 4; + *(unsigned long *)&fixup_buf[fi-4] = + (eip + insn_len + *(long *)&b[insn_len-4]) - + (FIXUP_BUF_USER + fi); + + /* ret */ + fixup_buf[fi++] = 0xc3; + + break; + } + else if ( (decode & CODE_MASK) == PUSH ) + { + return; + } + else if ( (decode & CODE_MASK) == POP ) + { + return; + } + else + { + /* Relocate the instruction verbatim. */ + memcpy(&fixup_buf[fi], &b[insn_len], new_insn_len); + fi += new_insn_len; } if ( (insn_len += new_insn_len) > 20 ) @@ -310,132 +423,84 @@ asmlinkage void do_fixup_4gb_segment(struct pt_regs *regs, long error_code) return; } - /* The instructions together must be no smaller than 'jmp '. */ - if ( insn_len >= 5 ) - break; - /* Can't have a RET in the middle of a patch sequence. */ - if ( opcode == 0xc4 ) + if ( (opcode == 0xc4) && (insn_len < PATCH_LEN) ) { DPRINTK("RET in middle of patch seq!\n"); return; } } - /* Already created a fixup for this address and code sequence? */ - for ( fe = fixup_hash[FIXUP_HASH(eip)]; - fe != NULL; fe = fe->next ) - { - if ( (fe->patch_addr == eip) && - (fe->patched_code_len == insn_len) && - (memcmp(fe->patched_code, b, insn_len) == 0) ) - goto do_the_patch; - } - - /* No existing patch -- create an entry for one. */ + /* Create an entry for a new fixup patch. */ fe = kmalloc(sizeof(struct fixup_entry), GFP_KERNEL); if ( unlikely(fe == NULL) ) { DPRINTK("Not enough memory to allocate a fixup_entry."); return; } - fe->patch_addr = eip; + fe->patch_addr = eip; /* XXX */ fe->patched_code_len = insn_len; memcpy(fe->patched_code, b, insn_len); fe->fixup_idx = fixup_idx; - fe->next = fixup_hash[FIXUP_HASH(eip)]; - fixup_hash[FIXUP_HASH(eip)] = fe; - - /* push */ - if ( save_indirect_reg ) - fixup_buf[fixup_idx++] = 0x50 + rm; + fe->return_idx = + fixup_idx + error_code + 6 + 4/**/ + (save_indirect_reg ? 2 : 0); + fe->next = fixup_hash[hash]; + fixup_hash[hash] = fe; - /* add %gs:0, */ - fixup_buf[fixup_idx++] = 0x65; - fixup_buf[fixup_idx++] = 0x03; - fixup_buf[fixup_idx++] = 0x05 | (rm << 3); - *(unsigned long *)&fixup_buf[fixup_idx] = 0; - fixup_idx += 4; - - /* First relocated instruction, minus the GS override. */ - memcpy(&fixup_buf[fixup_idx], &b[1], error_code - 1); - fixup_idx += error_code - 1; - - /* pop */ - if ( save_indirect_reg ) - fixup_buf[fixup_idx++] = 0x58 + rm; - - if ( insn_len != error_code ) - { - /* Relocated instructions. */ - memcpy(&fixup_buf[fixup_idx], &b[error_code], insn_len - error_code); - fixup_idx += insn_len - error_code; - } - - /* jmp */ - fixup_buf[fixup_idx++] = 0xe9; - fixup_idx += 4; - *(unsigned long *)&fixup_buf[fixup_idx-4] = - (eip + insn_len) - (fixup_buf_user + fixup_idx); - - if ( relbyte_idx != -1 ) - { - /* Patch the 8-bit relative offset. */ - int idx = fe->fixup_idx + relbyte_idx + 6; - if ( save_indirect_reg ) - idx += 2; - fixup_buf[idx] = fixup_idx - (idx + 1); - - /* jmp */ - fixup_buf[fixup_idx++] = 0xe9; - fixup_idx += 4; - *(unsigned long *)&fixup_buf[fixup_idx-4] = - (eip + relbyte_idx + 1 + (long)(char)b[relbyte_idx]) - - (fixup_buf_user + fixup_idx); - } - else if ( relword_idx != -1 ) - { - /* Patch the 32-bit relative offset by subtracting the code disp. */ - int idx = fe->fixup_idx + relword_idx + 6; - if ( save_indirect_reg ) - idx += 2; - *(unsigned long *)&fixup_buf[idx] += - (eip + relword_idx) - (fixup_buf_user + idx); - } + /* Commit the patch. */ + fixup_idx = fi; do_the_patch: +#if 1 /* Create the patching instruction in a temporary buffer. */ - patch[0] = 0xe9; - *(unsigned long *)&patch[1] = - (fixup_buf_user + fe->fixup_idx) - (eip + 5); + patch[0] = 0x67; + patch[1] = 0xff; + patch[2] = 0x16; /* call */ + *(u16 *)&patch[3] = FIXUP_BUF_USER + fe->fixup_idx; +#else + patch[0] = 0x9a; + *(u32 *)&patch[1] = FIXUP_BUF_USER + fe->fixup_idx + 4; + *(u16 *)&patch[5] = __USER_CS; +#endif - /* - * Check that the page to be patched is part of a read-only VMA. This - * means that our patch will never erroneously get flushed to disc. - */ - if ( eip < PAGE_OFFSET ) /* don't need to check the fixmap area */ +#if 1 { - /* [SMP] Need to the mmap_sem semaphore. */ - struct vm_area_struct *vma = find_vma(current->mm, eip); - if ( (vma == NULL) || (vma->vm_flags & VM_MAYSHARE) ) - { - DPRINTK("Cannot patch a shareable VMA."); - return; - } + int iii; + printk(KERN_ALERT "EIP == %08lx; USER_EIP == %08lx\n", + eip, FIXUP_BUF_USER + fe->fixup_idx); + printk(KERN_ALERT " .byte "); + for ( iii = 0; iii < insn_len; iii++ ) + printk("0x%02x,", b[iii]); + printk("!!\n"); + printk(KERN_ALERT " .byte "); + for ( iii = fe->fixup_idx; iii < fi; iii++ ) + printk("0x%02x,", (unsigned char)fixup_buf[iii]); + printk("!!\n"); + printk(KERN_ALERT " .byte "); + for ( iii = 0; iii < 7; iii++ ) + printk("0x%02x,", (unsigned char)patch[iii]); + printk("!!\n"); } +#endif + + if ( put_user(eip + insn_len, (unsigned long *)regs->esp - 1) != 0 ) + { + DPRINTK("Failed to place return address on user stack."); + return; + } + + /* Success! Return to user land to execute 2nd insn of the pair. */ + regs->esp -= 4; + regs->eip = FIXUP_BUF_USER + fe->return_idx; /* [SMP] Need to pause other threads while patching. */ pgd = pgd_offset(current->mm, eip); pmd = pmd_offset(pgd, eip); pte = pte_offset_kernel(pmd, eip); veip = kmap(pte_page(*pte)); - memcpy((char *)veip + (eip & ~PAGE_MASK), patch, 5); + memcpy((char *)veip + (eip & ~PAGE_MASK), patch, PATCH_LEN); kunmap(pte_page(*pte)); - /* Success! Return to user land to execute 2nd insn of the pair. */ - regs->eip = fixup_buf_user + fe->fixup_idx + error_code + 6; - if ( save_indirect_reg ) - regs->eip += 2; return; } @@ -443,17 +508,24 @@ static int nosegfixup = 0; static int __init fixup_init(void) { - unsigned long page; + struct vm_struct vma; + struct page *_pages[1< + */ + +#ifndef _ASM_HIGHMEM_H +#define _ASM_HIGHMEM_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include + +/* declarations for highmem.c */ +extern unsigned long highstart_pfn, highend_pfn; + +extern pte_t *kmap_pte; +extern pgprot_t kmap_prot; +extern pte_t *pkmap_page_table; + +extern void kmap_init(void); + +/* + * Right now we initialize only a single pte table. It can be extended + * easily, subsequent pte tables have to be allocated in one physical + * chunk of RAM. + */ +#if NR_CPUS <= 32 +#define PKMAP_BASE (HYPERVISOR_VIRT_START - (1<<23)) +#else +#define PKMAP_BASE (HYPERVISOR_VIRT_START - (1<<23) - 0x200000UL) +#endif +#ifdef CONFIG_X86_PAE +#define LAST_PKMAP 512 +#else +#define LAST_PKMAP 1024 +#endif +#define LAST_PKMAP_MASK (LAST_PKMAP-1) +#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT) +#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) + +extern void * FASTCALL(kmap_high(struct page *page)); +extern void FASTCALL(kunmap_high(struct page *page)); + +void *kmap(struct page *page); +void kunmap(struct page *page); +void *kmap_atomic(struct page *page, enum km_type type); +void *kmap_atomic_pte(struct page *page, enum km_type type); +void kunmap_atomic(void *kvaddr, enum km_type type); +void kunmap_atomic_force(void *kvaddr, enum km_type type); +struct page *kmap_atomic_to_page(void *ptr); + +#define flush_cache_kmaps() do { } while (0) + +#endif /* __KERNEL__ */ + +#endif /* _ASM_HIGHMEM_H */ diff --git a/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable.h b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable.h index be31d10f30..9026d62642 100644 --- a/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable.h +++ b/linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/pgtable.h @@ -64,16 +64,17 @@ void paging_init(void); #define PGDIR_SIZE (1UL << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE-1)) -#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE) -#define FIRST_USER_PGD_NR 0 +#define FIRST_USER_PGD_NR 1 +#define USER_PTRS_PER_PGD ((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR) +#if 0 /* XEN */ #define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT) #define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS) #define TWOLEVEL_PGDIR_SHIFT 22 #define BOOT_USER_PGD_PTRS (__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT) #define BOOT_KERNEL_PGD_PTRS (1024-BOOT_USER_PGD_PTRS) - +#endif #ifndef __ASSEMBLY__ /* Just any arbitrary offset to the start of the vmalloc VM area: the @@ -333,9 +334,11 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #if defined(CONFIG_HIGHPTE) #define pte_offset_map(dir, address) \ - ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address)) + ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE0) + \ + pte_index(address)) #define pte_offset_map_nested(dir, address) \ - ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + pte_index(address)) + ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE1) + \ + pte_index(address)) #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1) #else diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index 304413b485..62050c83eb 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -224,8 +224,7 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) /* XXX create domain on CPU=-1 so that in future it auto load ballances by default */ if ( xc_domain_create( xc_handle, nr_pfns * (PAGE_SIZE / 1024), - name, - -1, &dom ) ) + name, -1, &dom ) ) { xcio_error(ioctxt, "Could not create domain. pfns=%d, %dKB", nr_pfns,nr_pfns * (PAGE_SIZE / 1024)); diff --git a/xen/arch/x86/Rules.mk b/xen/arch/x86/Rules.mk index 2ecca1fffe..e419bba514 100644 --- a/xen/arch/x86/Rules.mk +++ b/xen/arch/x86/Rules.mk @@ -8,6 +8,9 @@ CFLAGS := -nostdinc -fno-builtin -fno-common -fno-strict-aliasing -O3 CFLAGS += -iwithprefix include -Wall -Werror -fomit-frame-pointer -pipe CFLAGS += -I$(BASEDIR)/include -Wno-pointer-arith -Wredundant-decls +# Prevent floating-point variables from creeping into Xen. +CFLAGS += -msoft-float + ifeq ($(TARGET_SUBARCH),x86_32) CFLAGS += -m32 -march=i686 LDFLAGS := --oformat elf32-i386 diff --git a/xen/common/sched_fair_bvt.c b/xen/common/sched_fair_bvt.c index 165c128753..ac37c582eb 100644 --- a/xen/common/sched_fair_bvt.c +++ b/xen/common/sched_fair_bvt.c @@ -252,7 +252,7 @@ static void fbvt_wake(struct domain *d) * values, the virtual time can be determined as: * SVT - const * TIME_SLEPT */ - io_warp = (int)(0.5 * inf->time_slept); + io_warp = inf->time_slept/2; if ( io_warp > 1000 ) io_warp = 1000; @@ -551,7 +551,7 @@ static task_slice_t fbvt_do_schedule(s_time_t now) * domains earlier in virtual time). Together this should give quite * good control both for CPU and IO-bound domains. */ - LAST_VTB(cpu) = (int)(0.2 * next_inf->time_slept); + LAST_VTB(cpu) = next_inf->time_slept/5; if(LAST_VTB(cpu) / next_inf->mcu_advance > max_vtb / MCU) LAST_VTB(cpu) = max_vtb * next_inf->mcu_advance / MCU;