From cfb60f4ea0474627c26647f300fef046b162ef76 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Mon, 29 Nov 2004 18:51:13 +0000 Subject: [PATCH 01/18] bitkeeper revision 1.1159.201.1 (41ab6fa1bs5vtddKGV1tNJawdZEZdw) New /dev/mem patch moves the Xen specifics out to an arch-specific file. Read/writes of /dev/mem now access I/O space rather than kernel space. Fixed ioremap.c a whole lot to now use the rather more robust direct_remap_area_pages(). 'dmidecode' now works in DOM0. :-) --- .rootkeys | 1 + .../arch/xen/i386/mm/ioremap.c | 331 +++++++----------- .../arch/xen/kernel/Makefile | 2 +- .../arch/xen/kernel/devmem.c | 158 +++++++++ linux-2.6.9-xen-sparse/drivers/char/mem.c | 25 +- .../include/asm-xen/asm-i386/io.h | 3 + 6 files changed, 306 insertions(+), 214 deletions(-) create mode 100644 linux-2.6.9-xen-sparse/arch/xen/kernel/devmem.c diff --git a/.rootkeys b/.rootkeys index 8bda240f8f..1691f867c4 100644 --- a/.rootkeys +++ b/.rootkeys @@ -171,6 +171,7 @@ 4107adf1s5u6249DNPUViX1YNagbUQ linux-2.6.9-xen-sparse/arch/xen/i386/pci/irq.c 40f56239zOksGg_H4XD4ye6iZNtoZA linux-2.6.9-xen-sparse/arch/xen/kernel/Makefile 40f56239bvOjuuuViZ0XMlNiREFC0A linux-2.6.9-xen-sparse/arch/xen/kernel/ctrl_if.c +41ab6fa06JdF7jxUsuDcjN3UhuIAxg linux-2.6.9-xen-sparse/arch/xen/kernel/devmem.c 40f56238xFQe9T7M_U_FItM-bZIpLw linux-2.6.9-xen-sparse/arch/xen/kernel/evtchn.c 4110f478aeQWllIN7J4kouAHiAqrPw linux-2.6.9-xen-sparse/arch/xen/kernel/fixup.c 412dfae9eA3_6e6bCGUtg1mj8b56fQ linux-2.6.9-xen-sparse/arch/xen/kernel/gnttab.c diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/mm/ioremap.c b/linux-2.6.9-xen-sparse/arch/xen/i386/mm/ioremap.c index f97d3f6b4d..d28a636c77 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/mm/ioremap.c +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/mm/ioremap.c @@ -16,23 +16,33 @@ #include #include #include +#include #ifndef CONFIG_XEN_PHYSDEV_ACCESS -void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) -{ return NULL; } +void * __ioremap(unsigned long phys_addr, unsigned long size, + unsigned long flags) +{ + return NULL; +} void *ioremap_nocache (unsigned long phys_addr, unsigned long size) -{ return NULL; } +{ + return NULL; +} void iounmap(volatile void __iomem *addr) -{ } +{ +} void __init *bt_ioremap(unsigned long phys_addr, unsigned long size) -{ return NULL; } +{ + return NULL; +} void __init bt_iounmap(void *addr, unsigned long size) -{ } +{ +} #else @@ -50,86 +60,6 @@ static inline int is_local_lowmem(unsigned long address) return ((pfn < max_low_pfn) && (pfn_to_mfn(pfn) == mfn)); } -static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - unsigned long pfn; - - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - if (address >= end) - BUG(); - pfn = phys_addr >> PAGE_SHIFT; - do { - if (!pte_none(*pte)) { - printk("remap_area_pte: page already exists\n"); - BUG(); - } - set_pte(pte, pfn_pte_ma(pfn, __pgprot(_PAGE_PRESENT | _PAGE_RW | - _PAGE_DIRTY | _PAGE_ACCESSED | flags))); - address += PAGE_SIZE; - pfn++; - pte++; - } while (address && (address < end)); -} - -static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - phys_addr -= address; - if (address >= end) - BUG(); - do { - pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address); - if (!pte) - return -ENOMEM; - remap_area_pte(pte, address, end - address, address + phys_addr, flags); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); - return 0; -} - -static int remap_area_pages(unsigned long address, unsigned long phys_addr, - unsigned long size, unsigned long flags) -{ - int error; - pgd_t * dir; - unsigned long end = address + size; - - phys_addr -= address; - dir = pgd_offset(&init_mm, address); - flush_cache_all(); - if (address >= end) - BUG(); - spin_lock(&init_mm.page_table_lock); - do { - pmd_t *pmd; - pmd = pmd_alloc(&init_mm, dir, address); - error = -ENOMEM; - if (!pmd) - break; - if (remap_area_pmd(pmd, address, end - address, - phys_addr + address, flags)) - break; - error = 0; - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); - spin_unlock(&init_mm.page_table_lock); - flush_tlb_all(); - return error; -} - /* * Generic mapping function (not visible outside): */ @@ -192,7 +122,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l return NULL; area->phys_addr = phys_addr; addr = (void __iomem *) area->addr; - if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { + if (direct_remap_area_pages(&init_mm, (unsigned long) addr, phys_addr, size, __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | flags), DOMID_IO)) { vunmap((void __force *) addr); return NULL; } @@ -360,138 +290,145 @@ void __init bt_iounmap(void *addr, unsigned long size) #define direct_mk_pte_phys(physpage, pgprot) \ __direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot) -static inline void direct_remap_area_pte(pte_t *pte, - unsigned long address, - unsigned long size, - mmu_update_t **v) +static inline void direct_remap_area_pte( + pte_t *pte, + unsigned long address, + unsigned long size, + mmu_update_t **v) { - unsigned long end; + unsigned long end; - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - if (address >= end) - BUG(); + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + if (address >= end) + BUG(); - do { - (*v)->ptr = virt_to_machine(pte); - (*v)++; - address += PAGE_SIZE; - pte++; - } while (address && (address < end)); + do { + (*v)->ptr = virt_to_machine(pte); + (*v)++; + address += PAGE_SIZE; + pte++; + } while (address && (address < end)); } -static inline int direct_remap_area_pmd(struct mm_struct *mm, - pmd_t *pmd, - unsigned long address, - unsigned long size, - mmu_update_t **v) +static inline int direct_remap_area_pmd( + struct mm_struct *mm, + pmd_t *pmd, + unsigned long address, + unsigned long size, + mmu_update_t **v) { - unsigned long end; + unsigned long end; - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - if (address >= end) - BUG(); - do { - pte_t *pte = pte_alloc_map(mm, pmd, address); - if (!pte) - return -ENOMEM; - direct_remap_area_pte(pte, address, end - address, v); - pte_unmap(pte); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); - return 0; + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + if (address >= end) + BUG(); + do { + pte_t *pte = (mm == &init_mm) ? + pte_alloc_kernel(mm, pmd, address) : + pte_alloc_map(mm, pmd, address); + if (!pte) + return -ENOMEM; + direct_remap_area_pte(pte, address, end - address, v); + pte_unmap(pte); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address && (address < end)); + return 0; } -int __direct_remap_area_pages(struct mm_struct *mm, - unsigned long address, - unsigned long size, - mmu_update_t *v) +int __direct_remap_area_pages( + struct mm_struct *mm, + unsigned long address, + unsigned long size, + mmu_update_t *v) { - pgd_t * dir; - unsigned long end = address + size; + pgd_t * dir; + unsigned long end = address + size; - dir = pgd_offset(mm, address); - flush_cache_all(); - if (address >= end) - BUG(); - spin_lock(&mm->page_table_lock); - do { - pmd_t *pmd = pmd_alloc(mm, dir, address); - if (!pmd) - return -ENOMEM; - direct_remap_area_pmd(mm, pmd, address, end - address, &v); - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; + dir = pgd_offset(mm, address); + if (address >= end) + BUG(); + spin_lock(&mm->page_table_lock); + do { + pmd_t *pmd = pmd_alloc(mm, dir, address); + if (!pmd) + return -ENOMEM; + direct_remap_area_pmd(mm, pmd, address, end - address, &v); + address = (address + PGDIR_SIZE) & PGDIR_MASK; + dir++; - } while (address && (address < end)); - spin_unlock(&mm->page_table_lock); - flush_tlb_all(); - return 0; + } while (address && (address < end)); + spin_unlock(&mm->page_table_lock); + return 0; } -int direct_remap_area_pages(struct mm_struct *mm, - unsigned long address, - unsigned long machine_addr, - unsigned long size, - pgprot_t prot, - domid_t domid) +int direct_remap_area_pages( + struct mm_struct *mm, + unsigned long address, + unsigned long machine_addr, + unsigned long size, + pgprot_t prot, + domid_t domid) { - int i; - unsigned long start_address; + int i; + unsigned long start_address; #define MAX_DIRECTMAP_MMU_QUEUE 130 - mmu_update_t u[MAX_DIRECTMAP_MMU_QUEUE], *w, *v; + mmu_update_t u[MAX_DIRECTMAP_MMU_QUEUE], *w, *v; - u[0].ptr = MMU_EXTENDED_COMMAND; - u[0].val = MMUEXT_SET_FOREIGNDOM; - u[0].val |= (unsigned long)domid << 16; - v = w = &u[1]; + u[0].ptr = MMU_EXTENDED_COMMAND; + u[0].val = MMUEXT_SET_FOREIGNDOM; + u[0].val |= (unsigned long)domid << 16; + v = w = &u[1]; - start_address = address; + start_address = address; - for( i = 0; i < size; i += PAGE_SIZE ) - { - if ( (v - u) == MAX_DIRECTMAP_MMU_QUEUE ) - { - /* Fill in the PTE pointers. */ - __direct_remap_area_pages( mm, - start_address, - address-start_address, - w); - - if ( HYPERVISOR_mmu_update(u, v - u, NULL) < 0 ) - return -EFAULT; - v = w; - start_address = address; + flush_cache_all(); + + for (i = 0; i < size; i += PAGE_SIZE) { + if ((v - u) == MAX_DIRECTMAP_MMU_QUEUE) { + /* Fill in the PTE pointers. */ + __direct_remap_area_pages( + mm, + start_address, + address-start_address, + w); + + if (HYPERVISOR_mmu_update(u, v - u, NULL) < 0) + return -EFAULT; + v = w; + start_address = address; + } + + /* + * Fill in the machine address: PTE ptr is done later by + * __direct_remap_area_pages(). + */ + v->val = (machine_addr & PAGE_MASK) | pgprot_val(prot); + + machine_addr += PAGE_SIZE; + address += PAGE_SIZE; + v++; } - /* - * Fill in the machine address: PTE ptr is done later by - * __direct_remap_area_pages(). - */ - v->val = (machine_addr & PAGE_MASK) | pgprot_val(prot); + if (v != w) { + /* get the ptep's filled in */ + __direct_remap_area_pages( + mm, + start_address, + address-start_address, + w); + if (unlikely(HYPERVISOR_mmu_update(u, v - u, NULL) < 0)) + return -EFAULT; + } - machine_addr += PAGE_SIZE; - address += PAGE_SIZE; - v++; - } + flush_tlb_all(); - if ( v != w ) - { - /* get the ptep's filled in */ - __direct_remap_area_pages(mm, - start_address, - address-start_address, - w); - if ( unlikely(HYPERVISOR_mmu_update(u, v - u, NULL) < 0) ) - return -EFAULT; - } - - return 0; + return 0; } diff --git a/linux-2.6.9-xen-sparse/arch/xen/kernel/Makefile b/linux-2.6.9-xen-sparse/arch/xen/kernel/Makefile index 3e987bee23..26731eff31 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/kernel/Makefile +++ b/linux-2.6.9-xen-sparse/arch/xen/kernel/Makefile @@ -9,4 +9,4 @@ $(obj)/vmlinux.lds: extra-y += vmlinux.lds -obj-y := ctrl_if.o evtchn.o fixup.o reboot.o xen_proc.o gnttab.o skbuff.o +obj-y := ctrl_if.o evtchn.o fixup.o reboot.o xen_proc.o gnttab.o skbuff.o devmem.o diff --git a/linux-2.6.9-xen-sparse/arch/xen/kernel/devmem.c b/linux-2.6.9-xen-sparse/arch/xen/kernel/devmem.c new file mode 100644 index 0000000000..ffda098851 --- /dev/null +++ b/linux-2.6.9-xen-sparse/arch/xen/kernel/devmem.c @@ -0,0 +1,158 @@ +/* + * Originally from linux/drivers/char/mem.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * Added devfs support. + * Jan-11-1998, C. Scott Ananian + * Shared /dev/zero mmaping support, Feb 2000, Kanoj Sarcar + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline int uncached_access(struct file *file, unsigned long addr) +{ + if (file->f_flags & O_SYNC) + return 1; + /* Xen sets correct MTRR type on non-RAM for us. */ + return 0; +} + +/* + * This funcion reads the *physical* memory. The f_pos points directly to the + * memory location. + */ +static ssize_t read_mem(struct file * file, char __user * buf, + size_t count, loff_t *ppos) +{ + unsigned long i, p = *ppos; + ssize_t read = 0; + void *v; + + if ((v = ioremap(p, count)) == NULL) { + /* + * Some programs (e.g., dmidecode) groove off into weird RAM + * areas where no table scan possibly exist (because Xen will + * have stomped on them!). These programs get rather upset if + * we let them know that Xen failed their access, so we fake + * out a read of all zeroes. :-) + */ + for (i = 0; i < count; i++) + if (put_user(0, buf+i)) + return -EFAULT; + return count; + } + if (copy_to_user(buf, v, count)) + return -EFAULT; + iounmap(v); + + read += count; + *ppos += read; + + return read; +} + +static ssize_t write_mem(struct file * file, const char __user * buf, + size_t count, loff_t *ppos) +{ + unsigned long p = *ppos; + ssize_t written = 0; + void *v; + + if ((v = ioremap(p, count)) == NULL) + return -EFAULT; + if (copy_to_user(v, buf, count)) + return -EFAULT; + iounmap(v); + + written += count; + *ppos += written; + + return written; +} + +static int mmap_mem(struct file * file, struct vm_area_struct * vma) +{ + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + int uncached; + + uncached = uncached_access(file, offset); + if (uncached) + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + /* Don't try to swap out physical pages.. */ + vma->vm_flags |= VM_RESERVED; + + /* + * Don't dump addresses that are not real memory to a core file. + */ + if (uncached) + vma->vm_flags |= VM_IO; + + if (io_remap_page_range(vma, vma->vm_start, offset, + vma->vm_end-vma->vm_start, vma->vm_page_prot)) + return -EAGAIN; + + return 0; +} + +/* + * The memory devices use the full 32/64 bits of the offset, and so we cannot + * check against negative addresses: they are ok. The return value is weird, + * though, in that case (0). + * + * also note that seeking relative to the "end of file" isn't supported: + * it has no meaning, so it returns -EINVAL. + */ +static loff_t memory_lseek(struct file * file, loff_t offset, int orig) +{ + loff_t ret; + + down(&file->f_dentry->d_inode->i_sem); + switch (orig) { + case 0: + file->f_pos = offset; + ret = file->f_pos; + force_successful_syscall_return(); + break; + case 1: + file->f_pos += offset; + ret = file->f_pos; + force_successful_syscall_return(); + break; + default: + ret = -EINVAL; + } + up(&file->f_dentry->d_inode->i_sem); + return ret; +} + +static int open_mem(struct inode * inode, struct file * filp) +{ + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; +} + +struct file_operations mem_fops = { + .llseek = memory_lseek, + .read = read_mem, + .write = write_mem, + .mmap = mmap_mem, + .open = open_mem, +}; diff --git a/linux-2.6.9-xen-sparse/drivers/char/mem.c b/linux-2.6.9-xen-sparse/drivers/char/mem.c index 072c5ca761..c805a2ca48 100644 --- a/linux-2.6.9-xen-sparse/drivers/char/mem.c +++ b/linux-2.6.9-xen-sparse/drivers/char/mem.c @@ -26,7 +26,6 @@ #include #include -#include #ifdef CONFIG_IA64 # include @@ -43,12 +42,7 @@ extern void tapechar_init(void); */ static inline int uncached_access(struct file *file, unsigned long addr) { -#ifdef CONFIG_XEN - if (file->f_flags & O_SYNC) - return 1; - /* Xen sets correct MTRR type on non-RAM for us. */ - return 0; -#elif defined(__i386__) +#if defined(__i386__) /* * On the PPro and successors, the MTRRs are used to set * memory types for physical addresses outside main memory, @@ -149,7 +143,7 @@ static ssize_t do_write_mem(void *p, unsigned long realp, return written; } - +#ifndef ARCH_HAS_DEV_MEM /* * This funcion reads the *physical* memory. The f_pos points directly to the * memory location. @@ -195,8 +189,9 @@ static ssize_t write_mem(struct file * file, const char __user * buf, return -EFAULT; return do_write_mem(__va(p), p, buf, count, ppos); } +#endif -static int mmap_mem(struct file * file, struct vm_area_struct * vma) +static int mmap_kmem(struct file * file, struct vm_area_struct * vma) { unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; int uncached; @@ -216,15 +211,9 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) if (uncached) vma->vm_flags |= VM_IO; -#if defined(CONFIG_XEN) - if (io_remap_page_range(vma, vma->vm_start, offset, - vma->vm_end-vma->vm_start, vma->vm_page_prot)) - return -EAGAIN; -#else if (remap_page_range(vma, vma->vm_start, offset, vma->vm_end-vma->vm_start, vma->vm_page_prot)) return -EAGAIN; -#endif return 0; } @@ -584,7 +573,7 @@ static int open_port(struct inode * inode, struct file * filp) return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; } -#define mmap_kmem mmap_mem +#define mmap_mem mmap_kmem #define zero_lseek null_lseek #define full_lseek null_lseek #define write_zero write_null @@ -592,6 +581,7 @@ static int open_port(struct inode * inode, struct file * filp) #define open_mem open_port #define open_kmem open_mem +#ifndef ARCH_HAS_DEV_MEM static struct file_operations mem_fops = { .llseek = memory_lseek, .read = read_mem, @@ -599,6 +589,9 @@ static struct file_operations mem_fops = { .mmap = mmap_mem, .open = open_mem, }; +#else +extern struct file_operations mem_fops; +#endif static struct file_operations kmem_fops = { .llseek = memory_lseek, diff --git a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/io.h b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/io.h index 0837c81cfa..08667ae0f6 100644 --- a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/io.h +++ b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/io.h @@ -444,4 +444,7 @@ BUILDIO(b,b,char) BUILDIO(w,w,short) BUILDIO(l,,int) +/* We will be supplying our own /dev/mem implementation */ +#define ARCH_HAS_DEV_MEM + #endif From eaaafa8ef56f5d7b5e4a1f6ddbfc972863bfa755 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Tue, 30 Nov 2004 09:00:21 +0000 Subject: [PATCH 02/18] bitkeeper revision 1.1159.187.40 (41ac36a5yZurzjumuK6eZfIthngj5Q) Fix ptep_set_access_flags() macro. --- .../include/asm-xen/asm-i386/pgtable.h | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable.h b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable.h index 4f4706ddbb..1962c630f3 100644 --- a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable.h +++ b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable.h @@ -421,31 +421,19 @@ extern pte_t *lookup_address(unsigned long address); #define update_mmu_cache(vma,address,pte) do { } while (0) #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS -#if 0 #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \ do { \ if (__dirty) { \ - queue_l1_entry_update((__ptep), (__entry).pte_low); \ - flush_tlb_page(__vma, __address); \ - xen_flush_page_update_queue(); \ - } \ - } while (0) -#else -#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \ - do { \ - if (__dirty) { \ - if ( likely(vma->vm_mm == current->mm) ) { \ + if ( likely((__vma)->vm_mm == current->mm) ) { \ xen_flush_page_update_queue(); \ - HYPERVISOR_update_va_mapping(address>>PAGE_SHIFT, entry, UVMF_INVLPG); \ + HYPERVISOR_update_va_mapping((__address)>>PAGE_SHIFT, (__entry), UVMF_INVLPG); \ } else { \ xen_l1_entry_update((__ptep), (__entry).pte_low); \ - flush_tlb_page(__vma, __address); \ + flush_tlb_page((__vma), (__address)); \ } \ } \ } while (0) -#endif - #define __HAVE_ARCH_PTEP_ESTABLISH #define ptep_establish(__vma, __address, __ptep, __entry) \ do { \ From 18bbf10459e256dc78df99306b6faa820b636936 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Tue, 30 Nov 2004 15:03:06 +0000 Subject: [PATCH 03/18] bitkeeper revision 1.1159.187.41 (41ac8baanJQsmqG9w2jw_lNTjLGswA) Fix Xen crash. --- xen/arch/x86/x86_32/entry.S | 1 + 1 file changed, 1 insertion(+) diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index 1befb2828d..c85d84c649 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -341,6 +341,7 @@ process_guest_exception_and_events: leal DOMAIN_trap_bounce(%ebx),%edx testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%edx) jz test_all_events + cli # create_bounce_frame needs CLI for pre-exceptions to work call create_bounce_frame jmp test_all_events From f5f1e2a8d2bd951dbd4ee813f1a2744632b65332 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Tue, 30 Nov 2004 17:17:07 +0000 Subject: [PATCH 04/18] bitkeeper revision 1.1159.187.42 (41acab13co1dnyoD3jJfv5m4ox_FFg) Major balloon driver cleanups. This has required some moderately large changes to start-of-day code in Linux 2.4 and 2.6. --- .../arch/xen/kernel/setup.c | 20 +- linux-2.4.28-xen-sparse/arch/xen/mm/init.c | 49 +-- .../arch/xen/i386/kernel/setup.c | 34 +- .../arch/xen/i386/mm/init.c | 84 ++--- .../drivers/xen/balloon/balloon.c | 350 ++++-------------- .../include/asm-xen/hypervisor.h | 1 - 6 files changed, 170 insertions(+), 368 deletions(-) diff --git a/linux-2.4.28-xen-sparse/arch/xen/kernel/setup.c b/linux-2.4.28-xen-sparse/arch/xen/kernel/setup.c index 72454469d0..3b27174ba6 100644 --- a/linux-2.4.28-xen-sparse/arch/xen/kernel/setup.c +++ b/linux-2.4.28-xen-sparse/arch/xen/kernel/setup.c @@ -275,7 +275,8 @@ void __init setup_arch(char **cmdline_p) * arch/xen/drivers/balloon/balloon.c */ mem_param = parse_mem_cmdline(cmdline_p); - if (!mem_param) mem_param = xen_start_info.nr_pages; + if (mem_param < xen_start_info.nr_pages) + mem_param = xen_start_info.nr_pages; #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) @@ -303,6 +304,7 @@ void __init setup_arch(char **cmdline_p) printk(KERN_WARNING "Use a PAE enabled kernel.\n"); else printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n"); + max_pfn = lmax_low_pfn; #else /* !CONFIG_HIGHMEM */ #ifndef CONFIG_X86_PAE if (max_pfn > MAX_NONPAE_PFN) { @@ -350,8 +352,6 @@ void __init setup_arch(char **cmdline_p) */ max_low_pfn = lmax_low_pfn; - - #ifdef CONFIG_BLK_DEV_INITRD if ( xen_start_info.mod_start != 0 ) { @@ -375,6 +375,20 @@ void __init setup_arch(char **cmdline_p) paging_init(); + /* Make sure we have a large enough P->M table. */ + if ( max_pfn > xen_start_info.nr_pages ) + { + phys_to_machine_mapping = alloc_bootmem_low_pages( + max_pfn * sizeof(unsigned long)); + memset(phys_to_machine_mapping, ~0, max_pfn * sizeof(unsigned long)); + memcpy(phys_to_machine_mapping, + (unsigned long *)xen_start_info.mfn_list, + xen_start_info.nr_pages * sizeof(unsigned long)); + free_bootmem(__pa(xen_start_info.mfn_list), + PFN_PHYS(PFN_UP(xen_start_info.nr_pages * + sizeof(unsigned long)))); + } + pfn_to_mfn_frame_list = alloc_bootmem_low_pages(PAGE_SIZE); for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ ) { diff --git a/linux-2.4.28-xen-sparse/arch/xen/mm/init.c b/linux-2.4.28-xen-sparse/arch/xen/mm/init.c index 6a694022bf..dd622aebda 100644 --- a/linux-2.4.28-xen-sparse/arch/xen/mm/init.c +++ b/linux-2.4.28-xen-sparse/arch/xen/mm/init.c @@ -213,23 +213,16 @@ static void __init fixrange_init (unsigned long start, static void __init pagetable_init (void) { - unsigned long vaddr, end; + unsigned long vaddr, end, ram_end; pgd_t *kpgd, *pgd, *pgd_base; int i, j, k; pmd_t *kpmd, *pmd; pte_t *kpte, *pte, *pte_base; - /* create tables only for boot_pfn frames. max_low_pfn may be sized for - * pages yet to be allocated from the hypervisor, or it may be set - * to override the xen_start_info amount of memory - */ - int boot_pfn = min(xen_start_info.nr_pages,max_low_pfn); - - /* - * This can be zero as well - no problem, in that case we exit - * the loops anyway due to the PTRS_PER_* conditions. - */ - end = (unsigned long)__va(boot_pfn *PAGE_SIZE); + end = (unsigned long)__va(max_low_pfn * PAGE_SIZE); + ram_end = (unsigned long)__va(xen_start_info.nr_pages * PAGE_SIZE); + if ( ram_end > end ) + ram_end = end; pgd_base = init_mm.pgd; i = __pgd_offset(PAGE_OFFSET); @@ -237,12 +230,12 @@ static void __init pagetable_init (void) for (; i < PTRS_PER_PGD; pgd++, i++) { vaddr = i*PGDIR_SIZE; - if (end && (vaddr >= end)) + if (vaddr >= end) break; pmd = (pmd_t *)pgd; for (j = 0; j < PTRS_PER_PMD; pmd++, j++) { vaddr = i*PGDIR_SIZE + j*PMD_SIZE; - if (end && (vaddr >= end)) + if (vaddr >= end) break; /* Filled in for us already? */ @@ -250,10 +243,11 @@ static void __init pagetable_init (void) continue; pte_base = pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); + clear_page(pte_base); for (k = 0; k < PTRS_PER_PTE; pte++, k++) { vaddr = i*PGDIR_SIZE + j*PMD_SIZE + k*PAGE_SIZE; - if (end && (vaddr >= end)) + if (vaddr >= ram_end) break; *pte = mk_pte_phys(__pa(vaddr), PAGE_KERNEL); } @@ -329,28 +323,14 @@ static inline int page_is_ram (unsigned long pagenr) return 1; } -static inline int page_kills_ppro(unsigned long pagenr) -{ - return 0; -} - #ifdef CONFIG_HIGHMEM -void __init one_highpage_init(struct page *page, int pfn, int bad_ppro) +void __init one_highpage_init(struct page *page, int free_page) { - if (!page_is_ram(pfn)) { - SetPageReserved(page); - return; - } - - if (bad_ppro && page_kills_ppro(pfn)) { - SetPageReserved(page); - return; - } - ClearPageReserved(page); set_bit(PG_highmem, &page->flags); atomic_set(&page->count, 1); - __free_page(page); + if ( free_page ) + __free_page(page); totalhigh_pages++; } #endif /* CONFIG_HIGHMEM */ @@ -392,8 +372,9 @@ static int __init free_pages_init(void) reservedpages++; } #ifdef CONFIG_HIGHMEM - for (pfn = xen_start_info.nr_pages-1; pfn >= highstart_pfn; pfn--) - one_highpage_init((struct page *) (mem_map + pfn), pfn, bad_ppro); + for (pfn = highend_pfn-1; pfn >= highstart_pfn; pfn--) + one_highpage_init((struct page *) (mem_map + pfn), pfn, + (pfn < xen_start_info.nr_pages)); totalram_pages += totalhigh_pages; #endif return reservedpages; diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/setup.c b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/setup.c index 8eb0add9d6..049e4aa0f6 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/setup.c +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/setup.c @@ -52,6 +52,9 @@ #include "setup_arch_pre.h" #include +/* Allows setting of maximum possible memory size */ +static unsigned long xen_override_max_pfn; + int disable_pse __initdata = 0; /* @@ -718,8 +721,13 @@ static void __init parse_cmdline_early (char ** cmdline_p) unsigned long long mem_size; mem_size = memparse(from+4, &from); +#if 0 limit_regions(mem_size); userdef=1; +#else + xen_override_max_pfn = + (unsigned long)(mem_size>>PAGE_SHIFT); +#endif } } @@ -857,6 +865,7 @@ static void __init parse_cmdline_early (char ** cmdline_p) } } +#if 0 /* !XEN */ /* * Callback for efi_memory_walk. */ @@ -873,7 +882,6 @@ efi_find_max_pfn(unsigned long start, unsigned long end, void *arg) return 0; } - /* * Find the highest page frame number we have available */ @@ -900,6 +908,15 @@ void __init find_max_pfn(void) max_pfn = end; } } +#else +/* We don't use the fake e820 because we need to respond to user override. */ +void __init find_max_pfn(void) +{ + if ( xen_override_max_pfn < xen_start_info.nr_pages ) + xen_override_max_pfn = xen_start_info.nr_pages; + max_pfn = xen_override_max_pfn; +} +#endif /* XEN */ /* * Determine low and high memory ranges: @@ -1414,6 +1431,21 @@ void __init setup_arch(char **cmdline_p) #endif paging_init(); + /* Make sure we have a large enough P->M table. */ + if (max_pfn > xen_start_info.nr_pages) { + phys_to_machine_mapping = alloc_bootmem_low_pages( + max_pfn * sizeof(unsigned long)); + memset(phys_to_machine_mapping, ~0, + max_pfn * sizeof(unsigned long)); + memcpy(phys_to_machine_mapping, + (unsigned long *)xen_start_info.mfn_list, + xen_start_info.nr_pages * sizeof(unsigned long)); + free_bootmem( + __pa(xen_start_info.mfn_list), + PFN_PHYS(PFN_UP(xen_start_info.nr_pages * + sizeof(unsigned long)))); + } + pfn_to_mfn_frame_list = alloc_bootmem_low_pages(PAGE_SIZE); for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ ) { diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/mm/init.c b/linux-2.6.9-xen-sparse/arch/xen/i386/mm/init.c index fbf48798d3..e2408ea3f7 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/mm/init.c +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/mm/init.c @@ -77,6 +77,12 @@ static pte_t * __init one_page_table_init(pmd_t *pmd) { if (pmd_none(*pmd)) { pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); + /* XEN: Make the new p.t. read-only. */ + pgd_t *kpgd = pgd_offset_k((unsigned long)page_table); + pmd_t *kpmd = pmd_offset(kpgd, (unsigned long)page_table); + pte_t *kpte = pte_offset_kernel(kpmd, (unsigned long)page_table); + xen_l1_entry_update( + kpte, (*(unsigned long *)kpte)&~_PAGE_RW); set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE)); if (page_table != pte_offset_kernel(pmd, 0)) BUG(); @@ -141,25 +147,6 @@ void __init protect_page(pgd_t *pgd, void *page, int mode) pte_val_ma(*pte) | _PAGE_RW); } -void __init protect_pagetable(pgd_t *dpgd, pgd_t *spgd, int mode) -{ - pmd_t *pmd; - pte_t *pte; - int pgd_idx, pmd_idx; - - protect_page(dpgd, spgd, mode); - - for (pgd_idx = 0; pgd_idx < PTRS_PER_PGD_NO_HV; spgd++, pgd_idx++) { - pmd = pmd_offset(spgd, 0); - if (pmd_none(*pmd)) - continue; - for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD; pmd++, pmd_idx++) { - pte = pte_offset_kernel(pmd, 0); - protect_page(dpgd, pte, mode); - } - } -} - static inline int is_kernel_text(unsigned long addr) { if (addr >= (unsigned long)_stext && addr <= (unsigned long)__init_end) @@ -180,6 +167,10 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base) pte_t *pte; int pgd_idx, pmd_idx, pte_ofs; + unsigned long max_ram_pfn = xen_start_info.nr_pages; + if (max_ram_pfn > max_low_pfn) + max_ram_pfn = max_low_pfn; + pgd_idx = pgd_index(PAGE_OFFSET); pgd = pgd_base + pgd_idx; pfn = 0; @@ -207,7 +198,10 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base) pte = one_page_table_init(pmd); pte += pte_ofs; - for (; pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; pte++, pfn++, pte_ofs++) { + /* XEN: Only map initial RAM allocation. */ + for (; pte_ofs < PTRS_PER_PTE && pfn < max_ram_pfn; pte++, pfn++, pte_ofs++) { + if (pte_present(*pte)) + continue; if (is_kernel_text(address)) set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC)); else @@ -311,7 +305,8 @@ void __init one_highpage_init(struct page *page, int pfn, int bad_ppro) ClearPageReserved(page); set_bit(PG_highmem, &page->flags); set_page_count(page, 1); - __free_page(page); + if (pfn < xen_start_info.nr_pages) + __free_page(page); totalhigh_pages++; } else SetPageReserved(page); @@ -347,7 +342,8 @@ extern void __init remap_numa_kva(void); static void __init pagetable_init (void) { unsigned long vaddr; - pgd_t *pgd_base = swapper_pg_dir; + pgd_t *old_pgd = (pgd_t *)xen_start_info.pt_base; + pgd_t *new_pgd = swapper_pg_dir; #ifdef CONFIG_X86_PAE int i; @@ -368,7 +364,22 @@ static void __init pagetable_init (void) __PAGE_KERNEL_EXEC |= _PAGE_GLOBAL; } - kernel_physical_mapping_init(pgd_base); + /* + * Switch to proper mm_init page directory. Initialise from the current + * page directory, write-protect the new page directory, then switch to + * it. We clean up by write-enabling and then freeing the old page dir. + */ + memcpy(new_pgd, old_pgd, PTRS_PER_PGD_NO_HV*sizeof(pgd_t)); + protect_page(new_pgd, new_pgd, PROT_ON); + queue_pgd_pin(__pa(new_pgd)); + load_cr3(new_pgd); + queue_pgd_unpin(__pa(old_pgd)); + __flush_tlb_all(); /* implicit flush */ + protect_page(new_pgd, old_pgd, PROT_OFF); + flush_page_update_queue(); + free_bootmem(__pa(old_pgd), PAGE_SIZE); + + kernel_physical_mapping_init(new_pgd); remap_numa_kva(); /* @@ -376,9 +387,9 @@ static void __init pagetable_init (void) * created - mappings will be set by set_fixmap(): */ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; - page_table_range_init(vaddr, 0, pgd_base); + page_table_range_init(vaddr, 0, new_pgd); - permanent_kmaps_init(pgd_base); + permanent_kmaps_init(new_pgd); #ifdef CONFIG_X86_PAE /* @@ -388,7 +399,7 @@ static void __init pagetable_init (void) * All user-space mappings are explicitly cleared after * SMP startup. */ - pgd_base[0] = pgd_base[USER_PTRS_PER_PGD]; + new_pgd[0] = new_pgd[USER_PTRS_PER_PGD]; #endif } @@ -545,8 +556,6 @@ out: */ void __init paging_init(void) { - pgd_t *old_pgd = (pgd_t *)xen_start_info.pt_base; - pgd_t *new_pgd = swapper_pg_dir; #ifdef CONFIG_XEN_PHYSDEV_ACCESS int i; #endif @@ -559,25 +568,6 @@ void __init paging_init(void) pagetable_init(); - /* - * Write-protect both page tables within both page tables. - * That's three ops, as the old p.t. is already protected - * within the old p.t. Then pin the new table, switch tables, - * and unprotect the old table. - */ - protect_pagetable(new_pgd, old_pgd, PROT_ON); - protect_pagetable(new_pgd, new_pgd, PROT_ON); - protect_pagetable(old_pgd, new_pgd, PROT_ON); - queue_pgd_pin(__pa(new_pgd)); - load_cr3(new_pgd); - queue_pgd_unpin(__pa(old_pgd)); - __flush_tlb_all(); /* implicit flush */ - protect_pagetable(new_pgd, old_pgd, PROT_OFF); - flush_page_update_queue(); - - /* Completely detached from old tables, so free them. */ - free_bootmem(__pa(old_pgd), xen_start_info.nr_pt_frames << PAGE_SHIFT); - #ifdef CONFIG_X86_PAE /* * We will bail out later - printk doesn't work right now so diff --git a/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c b/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c index 566a9578dd..94658f1e54 100644 --- a/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c +++ b/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c @@ -4,6 +4,7 @@ * Xen balloon driver - enables returning/claiming memory to/from Xen. * * Copyright (c) 2003, B Dragovic + * Copyright (c) 2003-2004, M Williamson, K Fraser * * This file may be distributed separately from the Linux kernel, or * incorporated into other software packages, subject to the following license: @@ -48,19 +49,10 @@ #include #include -/* USER DEFINES -- THESE SHOULD BE COPIED TO USER-SPACE TOOLS */ -#define USER_INFLATE_BALLOON 1 /* return mem to hypervisor */ -#define USER_DEFLATE_BALLOON 2 /* claim mem from hypervisor */ -typedef struct user_balloon_op { - unsigned int op; - unsigned long size; -} user_balloon_op_t; -/* END OF USER DEFINE */ - static struct proc_dir_entry *balloon_pde; unsigned long credit; -static unsigned long current_pages, most_seen_pages; +static unsigned long current_pages; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) /* Use the private and mapping fields of struct page as a list. */ @@ -78,71 +70,66 @@ static unsigned long current_pages, most_seen_pages; #define pte_offset_kernel pte_offset #endif +#define IPRINTK(fmt, args...) \ + printk(KERN_INFO "xen_mem: " fmt, ##args) +#define WPRINTK(fmt, args...) \ + printk(KERN_WARNING "xen_mem: " fmt, ##args) + /* List of ballooned pages, threaded through the mem_map array. */ LIST_HEAD(ballooned_pages); -/** add_ballooned_page - remember we've ballooned a pfn */ -void add_ballooned_page(unsigned long pfn) +/* balloon_append: add the given page to the balloon. */ +void balloon_append(struct page *page) { - struct page *p = mem_map + pfn; - - list_add(PAGE_TO_LIST(p), &ballooned_pages); + list_add(PAGE_TO_LIST(page), &ballooned_pages); } -/* rem_ballooned_page - recall a ballooned page and remove from list. */ -struct page *rem_ballooned_page(void) +/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ +struct page *balloon_retrieve(void) { - if(!list_empty(&ballooned_pages)) - { - struct page *ret; + struct page *page; - ret = LIST_TO_PAGE(ballooned_pages.next); - UNLIST_PAGE(ret); - - return ret; - } - else + if ( list_empty(&ballooned_pages) ) return NULL; + + page = LIST_TO_PAGE(ballooned_pages.next); + UNLIST_PAGE(page); + return page; } static inline pte_t *get_ptep(unsigned long addr) { - pgd_t *pgd; pmd_t *pmd; pte_t *ptep; - pgd = pgd_offset_k(addr); + pgd_t *pgd; + pmd_t *pmd; + pgd = pgd_offset_k(addr); if ( pgd_none(*pgd) || pgd_bad(*pgd) ) BUG(); pmd = pmd_offset(pgd, addr); if ( pmd_none(*pmd) || pmd_bad(*pmd) ) BUG(); - ptep = pte_offset_kernel(pmd, addr); - - return ptep; + return pte_offset_kernel(pmd, addr); } /* Main function for relinquishing memory. */ static unsigned long inflate_balloon(unsigned long num_pages) - { - unsigned long *parray; - unsigned long *currp; - unsigned long curraddr; - unsigned long ret = 0; - unsigned long i, j; + unsigned long *parray, *currp, curraddr, ret = 0, i, j, mfn, pfn; + struct page *page; parray = (unsigned long *)vmalloc(num_pages * sizeof(unsigned long)); if ( parray == NULL ) { - printk(KERN_ERR "inflate_balloon: Unable to vmalloc parray\n"); - return -EFAULT; + WPRINTK("inflate_balloon: Unable to vmalloc parray\n"); + return -ENOMEM; } currp = parray; for ( i = 0; i < num_pages; i++, currp++ ) { - struct page *page = alloc_page(GFP_HIGHUSER); - unsigned long pfn = page - mem_map; + page = alloc_page(GFP_HIGHUSER); + pfn = page - mem_map; /* If allocation fails then free all reserved pages. */ if ( page == NULL ) @@ -160,10 +147,9 @@ static unsigned long inflate_balloon(unsigned long num_pages) *currp = pfn; } - for ( i = 0, currp = parray; i < num_pages; i++, currp++ ) { - unsigned long mfn = phys_to_machine_mapping[*currp]; + mfn = phys_to_machine_mapping[*currp]; curraddr = (unsigned long)page_address(mem_map + *currp); /* Blow away page contents for security, and also p.t. ref if any. */ if ( curraddr != 0 ) @@ -180,7 +166,7 @@ static unsigned long inflate_balloon(unsigned long num_pages) } #endif - add_ballooned_page(*currp); + balloon_append(&mem_map[*currp]); phys_to_machine_mapping[*currp] = INVALID_P2M_ENTRY; *currp = mfn; @@ -206,62 +192,45 @@ static unsigned long inflate_balloon(unsigned long num_pages) return ret; } -/* - * Install new mem pages obtained by deflate_balloon. function walks - * phys->machine mapping table looking for DEAD entries and populates - * them. - */ -static unsigned long process_returned_pages(unsigned long * parray, - unsigned long num) +/* Install a set of new pages (@mfn_list, @nr_mfns) into the memory map. */ +static unsigned long process_returned_pages( + unsigned long *mfn_list, unsigned long nr_mfns) { - /* currently, this function is rather simplistic as - * it is assumed that domain reclaims only number of - * pages previously released. this is to change soon - * and the code to extend page tables etc. will be - * incorporated here. - */ - - unsigned long * curr = parray; - unsigned long num_installed; - + unsigned long pfn, i; struct page *page; - num_installed = 0; - while ( (page = rem_ballooned_page()) != NULL ) + for ( i = 0; i < nr_mfns; i++ ) { - unsigned long pfn; - - if ( num_installed == num ) + if ( (page = balloon_retrieve()) != NULL ) break; pfn = page - mem_map; - - if(phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY) - { - printk("BUG: Tried to unballoon existing page!"); + if ( phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY ) BUG(); - } - phys_to_machine_mapping[pfn] = *curr; - queue_machphys_update(*curr, pfn); - if (pfnM and M->P tables. */ + phys_to_machine_mapping[pfn] = mfn_list[i]; + queue_machphys_update(mfn_list[i], pfn); + + /* Link back into the page tables if it's not a highmem page. */ + if ( pfn < max_low_pfn ) queue_l1_entry_update( get_ptep((unsigned long)__va(pfn << PAGE_SHIFT)), - ((*curr) << PAGE_SHIFT) | pgprot_val(PAGE_KERNEL)); - - __free_page(mem_map + pfn); + (mfn_list[i] << PAGE_SHIFT) | pgprot_val(PAGE_KERNEL)); - curr++; - num_installed++; + /* Finally, relinquish the memory back to the system allocator. */ + ClearPageReserved(page); + set_page_count(page, 1); + __free_page(page); } - return num_installed; + return i; } unsigned long deflate_balloon(unsigned long num_pages) { unsigned long ret; - unsigned long * parray; + unsigned long *parray; if ( num_pages > credit ) { @@ -305,205 +274,25 @@ unsigned long deflate_balloon(unsigned long num_pages) #define PAGE_TO_MB_SHIFT 8 -/* - * pagetable_extend() mimics pagetable_init() from arch/xen/mm/init.c - * The loops do go through all of low memory (ZONE_NORMAL). The - * old pages have _PAGE_PRESENT set and so get skipped. - * If low memory is not full, the new pages are used to fill it, going - * from cur_low_pfn to low_pfn. high memory is not direct mapped so - * no extension is needed for new high memory. - */ - -static void pagetable_extend (int cur_low_pfn, int newpages) -{ - unsigned long vaddr, end; - pgd_t *kpgd, *pgd, *pgd_base; - int i, j, k; - pmd_t *kpmd, *pmd; - pte_t *kpte, *pte, *pte_base; - int low_pfn = min(cur_low_pfn+newpages,(int)max_low_pfn); - - /* - * This can be zero as well - no problem, in that case we exit - * the loops anyway due to the PTRS_PER_* conditions. - */ - end = (unsigned long)__va(low_pfn*PAGE_SIZE); - - pgd_base = init_mm.pgd; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - i = pgd_index(PAGE_OFFSET); -#else - i = __pgd_offset(PAGE_OFFSET); -#endif - pgd = pgd_base + i; - - for (; i < PTRS_PER_PGD; pgd++, i++) { - vaddr = i*PGDIR_SIZE; - if (end && (vaddr >= end)) - break; - pmd = (pmd_t *)pgd; - for (j = 0; j < PTRS_PER_PMD; pmd++, j++) { - vaddr = i*PGDIR_SIZE + j*PMD_SIZE; - if (end && (vaddr >= end)) - break; - - /* Filled in for us already? */ - if ( pmd_val(*pmd) & _PAGE_PRESENT ) - continue; - - pte_base = pte = (pte_t *) __get_free_page(GFP_KERNEL); - - for (k = 0; k < PTRS_PER_PTE; pte++, k++) { - vaddr = i*PGDIR_SIZE + j*PMD_SIZE + k*PAGE_SIZE; - if (end && (vaddr >= end)) - break; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - *pte = mk_pte(virt_to_page(vaddr), PAGE_KERNEL); -#else - *pte = mk_pte_phys(__pa(vaddr), PAGE_KERNEL); -#endif - } - kpgd = pgd_offset_k((unsigned long)pte_base); - kpmd = pmd_offset(kpgd, (unsigned long)pte_base); - kpte = pte_offset_kernel(kpmd, (unsigned long)pte_base); - queue_l1_entry_update(kpte, - (*(unsigned long *)kpte)&~_PAGE_RW); - set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte_base))); - XEN_flush_page_update_queue(); - } - } -} - -/* - * claim_new_pages() asks xen to increase this domain's memory reservation - * and return a list of the new pages of memory. This new pages are - * added to the free list of the memory manager. - * - * Available RAM does not normally change while Linux runs. To make this work, - * the linux mem= boottime command line param must say how big memory could - * possibly grow. Then setup_arch() in arch/xen/kernel/setup.c - * sets max_pfn, max_low_pfn and the zones according to - * this max memory size. The page tables themselves can only be - * extended after xen has assigned new pages to this domain. - */ - -static unsigned long -claim_new_pages(unsigned long num_pages) -{ - unsigned long new_page_cnt, pfn; - unsigned long * parray, *curr; - - if (most_seen_pages+num_pages> max_pfn) - num_pages = max_pfn-most_seen_pages; - if (num_pages==0) return -EINVAL; - - parray = (unsigned long *)vmalloc(num_pages * sizeof(unsigned long)); - if ( parray == NULL ) - { - printk(KERN_ERR "claim_new_pages: Unable to vmalloc parray\n"); - return 0; - } - - new_page_cnt = HYPERVISOR_dom_mem_op(MEMOP_increase_reservation, - parray, num_pages, 0); - if ( new_page_cnt != num_pages ) - { - printk(KERN_WARNING - "claim_new_pages: xen granted only %lu of %lu requested pages\n", - new_page_cnt, num_pages); - - /* - * Avoid xen lockup when user forgot to setdomainmaxmem. Xen - * usually can dribble out a few pages and then hangs. - */ - if ( new_page_cnt < 1000 ) - { - printk(KERN_WARNING "Remember to use setdomainmaxmem\n"); - HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, - parray, new_page_cnt, 0); - return -EFAULT; - } - } - memcpy(phys_to_machine_mapping+most_seen_pages, parray, - new_page_cnt * sizeof(unsigned long)); - - pagetable_extend(most_seen_pages,new_page_cnt); - - for ( pfn = most_seen_pages, curr = parray; - pfn < most_seen_pages+new_page_cnt; - pfn++, curr++ ) - { - struct page *page = mem_map + pfn; - -#ifndef CONFIG_HIGHMEM - if ( pfn>=max_low_pfn ) - { - printk(KERN_WARNING "Warning only %ldMB will be used.\n", - pfn>>PAGE_TO_MB_SHIFT); - printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n"); - break; - } -#endif - queue_machphys_update(*curr, pfn); - if ( pfn < max_low_pfn ) - queue_l1_entry_update( - get_ptep((unsigned long)__va(pfn << PAGE_SHIFT)), - ((*curr) << PAGE_SHIFT) | pgprot_val(PAGE_KERNEL)); - - XEN_flush_page_update_queue(); - - /* this next bit mimics arch/xen/mm/init.c:one_highpage_init() */ - ClearPageReserved(page); - if ( pfn >= max_low_pfn ) - set_bit(PG_highmem, &page->flags); - set_page_count(page, 1); - __free_page(page); - } - - vfree(parray); - - return new_page_cnt; -} - - static int balloon_try_target(int target) { int change, reclaim; if ( target < current_pages ) { - int change = inflate_balloon(current_pages-target); - if ( change <= 0 ) + if ( (change = inflate_balloon(current_pages-target)) <= 0 ) return change; - current_pages -= change; printk(KERN_INFO "Relinquish %dMB to xen. Domain now has %luMB\n", change>>PAGE_TO_MB_SHIFT, current_pages>>PAGE_TO_MB_SHIFT); } - else if ( target > current_pages ) + else if ( (reclaim = target - current_pages) > 0 ) { - reclaim = min((unsigned long)target,most_seen_pages) - current_pages; - - if ( reclaim ) - { - change = deflate_balloon( reclaim ); - if ( change <= 0 ) - return change; - current_pages += change; - printk(KERN_INFO "Reclaim %dMB from xen. Domain now has %luMB\n", - change>>PAGE_TO_MB_SHIFT, current_pages>>PAGE_TO_MB_SHIFT); - } - - if ( most_seen_pages < target ) - { - int growth = claim_new_pages(target-most_seen_pages); - if ( growth <= 0 ) - return growth; - most_seen_pages += growth; - current_pages += growth; - printk(KERN_INFO "Granted %dMB new mem. Dom now has %luMB\n", - growth>>PAGE_TO_MB_SHIFT, current_pages>>PAGE_TO_MB_SHIFT); - } + if ( (change = deflate_balloon(reclaim)) <= 0 ) + return change; + current_pages += change; + printk(KERN_INFO "Reclaim %dMB from xen. Domain now has %luMB\n", + change>>PAGE_TO_MB_SHIFT, current_pages>>PAGE_TO_MB_SHIFT); } return 1; @@ -640,12 +429,15 @@ static int balloon_read(char *page, char **start, off_t off, static int __init balloon_init(void) { - printk(KERN_ALERT "Starting Xen Balloon driver\n"); + unsigned long pfn; + struct page *page; - most_seen_pages = current_pages = min(xen_start_info.nr_pages,max_pfn); + IPRINTK("Initialising balloon driver.\n"); + + current_pages = min(xen_start_info.nr_pages, max_pfn); if ( (balloon_pde = create_xen_proc_entry("memory_target", 0644)) == NULL ) { - printk(KERN_ALERT "Unable to create balloon driver proc entry!"); + WPRINTK("Unable to create balloon driver proc entry!"); return -1; } @@ -661,18 +453,12 @@ static int __init balloon_init(void) (void)ctrl_if_register_receiver(CMSG_MEM_REQUEST, balloon_ctrlif_rx, CALLBACK_IN_BLOCKING_CONTEXT); - /* - * make_module a new phys map if mem= says xen can give us memory to grow - */ - if ( max_pfn > xen_start_info.nr_pages ) + /* Initialise the balloon with excess memory space. */ + for ( pfn = xen_start_info.nr_pages; pfn < max_pfn; pfn++ ) { - extern unsigned long *phys_to_machine_mapping; - unsigned long *newmap; - newmap = (unsigned long *)vmalloc(max_pfn * sizeof(unsigned long)); - memset(newmap, ~0, max_pfn * sizeof(unsigned long)); - memcpy(newmap, phys_to_machine_mapping, - xen_start_info.nr_pages * sizeof(unsigned long)); - phys_to_machine_mapping = newmap; + page = &mem_map[pfn]; + if ( !PageReserved(page) ) + balloon_append(page); } return 0; diff --git a/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h b/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h index 235c4fc5a6..85f0f1162c 100644 --- a/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h +++ b/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h @@ -59,7 +59,6 @@ void do_hypervisor_callback(struct pt_regs *regs); #define PROT_ON 1 #define PROT_OFF 0 void /* __init */ protect_page(pgd_t *dpgd, void *page, int mode); -void /* __init */ protect_pagetable(pgd_t *dpgd, pgd_t *spgd, int mode); /* arch/xen/i386/kernel/head.S */ void lgdt_finish(void); From 637e5764e5380377a0bf64fa4bad1f701ee8deb3 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Tue, 30 Nov 2004 18:17:06 +0000 Subject: [PATCH 05/18] bitkeeper revision 1.1159.187.43 (41acb922MGgCQ71HoZ-M1-vpezLXKQ) More simplifications to p.t. management. --- .../arch/xen/i386/kernel/cpu/common.c | 2 +- .../arch/xen/i386/mm/init.c | 27 +++---------------- .../include/asm-xen/hypervisor.h | 6 ----- 3 files changed, 4 insertions(+), 31 deletions(-) diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/common.c b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/common.c index a59d760eb7..a29a7f4e97 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/common.c +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/cpu/common.c @@ -513,7 +513,7 @@ void __init cpu_gdt_init(struct Xgt_desc_struct *gdt_descr) va < gdt_descr->address + gdt_descr->size; va += PAGE_SIZE, f++) { frames[f] = virt_to_machine(va) >> PAGE_SHIFT; - protect_page(swapper_pg_dir, (void *)va, PROT_ON); + make_page_readonly((void *)va); } flush_page_update_queue(); if (HYPERVISOR_set_gdt(frames, gdt_descr->size / 8)) diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/mm/init.c b/linux-2.6.9-xen-sparse/arch/xen/i386/mm/init.c index e2408ea3f7..3a0a0eb674 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/mm/init.c +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/mm/init.c @@ -77,12 +77,7 @@ static pte_t * __init one_page_table_init(pmd_t *pmd) { if (pmd_none(*pmd)) { pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); - /* XEN: Make the new p.t. read-only. */ - pgd_t *kpgd = pgd_offset_k((unsigned long)page_table); - pmd_t *kpmd = pmd_offset(kpgd, (unsigned long)page_table); - pte_t *kpte = pte_offset_kernel(kpmd, (unsigned long)page_table); - xen_l1_entry_update( - kpte, (*(unsigned long *)kpte)&~_PAGE_RW); + make_page_readonly(page_table); set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE)); if (page_table != pte_offset_kernel(pmd, 0)) BUG(); @@ -131,22 +126,6 @@ static void __init page_table_range_init (unsigned long start, unsigned long end } } -void __init protect_page(pgd_t *pgd, void *page, int mode) -{ - pmd_t *pmd; - pte_t *pte; - unsigned long addr; - - addr = (unsigned long)page; - pgd += pgd_index(addr); - pmd = pmd_offset(pgd, addr); - pte = pte_offset_kernel(pmd, addr); - if (!pte_present(*pte)) - return; - queue_l1_entry_update(pte, mode ? pte_val_ma(*pte) & ~_PAGE_RW : - pte_val_ma(*pte) | _PAGE_RW); -} - static inline int is_kernel_text(unsigned long addr) { if (addr >= (unsigned long)_stext && addr <= (unsigned long)__init_end) @@ -370,12 +349,12 @@ static void __init pagetable_init (void) * it. We clean up by write-enabling and then freeing the old page dir. */ memcpy(new_pgd, old_pgd, PTRS_PER_PGD_NO_HV*sizeof(pgd_t)); - protect_page(new_pgd, new_pgd, PROT_ON); + make_page_readonly(new_pgd); queue_pgd_pin(__pa(new_pgd)); load_cr3(new_pgd); queue_pgd_unpin(__pa(old_pgd)); __flush_tlb_all(); /* implicit flush */ - protect_page(new_pgd, old_pgd, PROT_OFF); + make_page_writable(old_pgd); flush_page_update_queue(); free_bootmem(__pa(old_pgd), PAGE_SIZE); diff --git a/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h b/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h index 85f0f1162c..c82469bc00 100644 --- a/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h +++ b/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h @@ -54,12 +54,6 @@ void xen_cpu_idle (void); /* arch/xen/i386/kernel/hypervisor.c */ void do_hypervisor_callback(struct pt_regs *regs); -/* arch/xen/i386/mm/init.c */ -/* NOTE: caller must call flush_page_update_queue() */ -#define PROT_ON 1 -#define PROT_OFF 0 -void /* __init */ protect_page(pgd_t *dpgd, void *page, int mode); - /* arch/xen/i386/kernel/head.S */ void lgdt_finish(void); From 3f6541107dbf7d9aca9cfc481165c5420463c027 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Tue, 30 Nov 2004 18:20:38 +0000 Subject: [PATCH 06/18] bitkeeper revision 1.1159.187.44 (41acb9f65Nu4_LCJgeyWLgtrvxeqoA) Version bumb on control libraries. --- tools/libxc/Makefile | 2 +- tools/libxutil/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index 78ba7f3bf3..9065bb1bd6 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -1,5 +1,5 @@ -MAJOR = 1.3 +MAJOR = 2.0 MINOR = 0 SONAME = libxc.so.$(MAJOR) diff --git a/tools/libxutil/Makefile b/tools/libxutil/Makefile index 85acd2063c..b9034b5b8f 100644 --- a/tools/libxutil/Makefile +++ b/tools/libxutil/Makefile @@ -30,7 +30,7 @@ CFLAGS += -fno-strict-aliasing CFLAGS += -Wp,-MD,.$(@F).d DEPS = .*.d -MAJOR := 1.3 +MAJOR := 2.0 MINOR := 0 LIB_NAME := libxutil LIB := $(LIB_NAME).so From e44d6d5992257a6d22b19ea8ee76203962e8fe48 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Wed, 1 Dec 2004 09:39:42 +0000 Subject: [PATCH 07/18] bitkeeper revision 1.1159.187.45 (41ad915efwXemCBvpJ9zlx5AhK28qw) Header and EXPORT_SYMBOL() fixes so that more stuff builds. --- .../arch/xen/i386/mm/ioremap.c | 3 +++ .../include/asm-xen/asm-i386/pgalloc.h | 11 -------- .../include/asm-xen/asm-i386/pgtable.h | 27 +++++++++++++------ xen/include/public/xen.h | 2 ++ 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/mm/ioremap.c b/linux-2.6.9-xen-sparse/arch/xen/i386/mm/ioremap.c index d28a636c77..e055352612 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/mm/ioremap.c +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/mm/ioremap.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -432,3 +433,5 @@ int direct_remap_area_pages( return 0; } + +EXPORT_SYMBOL(direct_remap_area_pages); diff --git a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgalloc.h b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgalloc.h index c98a6d2933..752a069e8d 100644 --- a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgalloc.h +++ b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgalloc.h @@ -53,15 +53,4 @@ extern void pte_free(struct page *pte); #define check_pgt_cache() do { } while (0) -int direct_remap_area_pages(struct mm_struct *mm, - unsigned long address, - unsigned long machine_addr, - unsigned long size, - pgprot_t prot, - domid_t domid); -int __direct_remap_area_pages(struct mm_struct *mm, - unsigned long address, - unsigned long size, - mmu_update_t *v); - #endif /* _I386_PGALLOC_H */ diff --git a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable.h b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable.h index 1962c630f3..8d2316a4bb 100644 --- a/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable.h +++ b/linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/pgtable.h @@ -460,14 +460,14 @@ void make_page_writable(void *va); void make_pages_readonly(void *va, unsigned int nr); void make_pages_writable(void *va, unsigned int nr); -static inline unsigned long arbitrary_virt_to_machine(void *va) -{ - pgd_t *pgd = pgd_offset_k((unsigned long)va); - pmd_t *pmd = pmd_offset(pgd, (unsigned long)va); - pte_t *pte = pte_offset_kernel(pmd, (unsigned long)va); - unsigned long pa = (*(unsigned long *)pte) & PAGE_MASK; - return pa | ((unsigned long)va & (PAGE_SIZE-1)); -} +#define arbitrary_virt_to_machine(__va) \ +({ \ + pgd_t *__pgd = pgd_offset_k((unsigned long)(__va)); \ + pmd_t *__pmd = pmd_offset(__pgd, (unsigned long)(__va)); \ + pte_t *__pte = pte_offset_kernel(__pmd, (unsigned long)(__va)); \ + unsigned long __pa = (*(unsigned long *)__pte) & PAGE_MASK; \ + __pa | ((unsigned long)(__va) & (PAGE_SIZE-1)); \ +}) #endif /* !__ASSEMBLY__ */ @@ -475,6 +475,17 @@ static inline unsigned long arbitrary_virt_to_machine(void *va) #define kern_addr_valid(addr) (1) #endif /* !CONFIG_DISCONTIGMEM */ +int direct_remap_area_pages(struct mm_struct *mm, + unsigned long address, + unsigned long machine_addr, + unsigned long size, + pgprot_t prot, + domid_t domid); +int __direct_remap_area_pages(struct mm_struct *mm, + unsigned long address, + unsigned long size, + mmu_update_t *v); + #define io_remap_page_range(vma,from,phys,size,prot) \ direct_remap_area_pages(vma->vm_mm,from,phys,size,prot,DOMID_IO) diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index 905bd4c011..3f00fe2e06 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -9,8 +9,10 @@ #ifndef __XEN_PUBLIC_XEN_H__ #define __XEN_PUBLIC_XEN_H__ +#ifndef PACKED /* GCC-specific way to pack structure definitions (no implicit padding). */ #define PACKED __attribute__ ((packed)) +#endif #if defined(__i386__) #include "arch-x86_32.h" From 40adb357570be352428993abeb7479aaa988e397 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Wed, 1 Dec 2004 11:23:24 +0000 Subject: [PATCH 08/18] bitkeeper revision 1.1159.187.46 (41ada9acdxj1sndHML6zY6jvbR0CFg) Fix netback driver to correctly free the net device struct. --- .../drivers/xen/netback/interface.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/linux-2.6.9-xen-sparse/drivers/xen/netback/interface.c b/linux-2.6.9-xen-sparse/drivers/xen/netback/interface.c index 406d253fda..baa50ace22 100644 --- a/linux-2.6.9-xen-sparse/drivers/xen/netback/interface.c +++ b/linux-2.6.9-xen-sparse/drivers/xen/netback/interface.c @@ -35,8 +35,8 @@ static void __netif_disconnect_complete(void *arg) /* * These can't be done in netif_disconnect() because at that point there - * may be outstanding requests at the disc whose asynchronous responses - * must still be notified to the remote driver. + * may be outstanding requests in the network stack whose asynchronous + * responses must still be notified to the remote driver. */ unbind_evtchn_from_irq(netif->evtchn); vfree(netif->tx); /* Frees netif->rx as well. */ @@ -84,7 +84,7 @@ void netif_create(netif_be_create_t *create) unsigned int handle = create->netif_handle; struct net_device *dev; netif_t **pnetif, *netif; - char name[IFNAMSIZ] = {}; + char name[IFNAMSIZ]; snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle); dev = alloc_netdev(sizeof(netif_t), name, ether_setup); @@ -116,7 +116,7 @@ void netif_create(netif_be_create_t *create) { DPRINTK("Could not create netif: already exists\n"); create->status = NETIF_BE_STATUS_INTERFACE_EXISTS; - kfree(dev); + free_netdev(dev); return; } pnetif = &(*pnetif)->hash_next; @@ -137,7 +137,7 @@ void netif_create(netif_be_create_t *create) DPRINTK("Could not register new net device %s: err=%d\n", dev->name, err); create->status = NETIF_BE_STATUS_OUT_OF_MEMORY; - kfree(dev); + free_netdev(dev); return; } @@ -176,7 +176,7 @@ void netif_destroy(netif_be_destroy_t *destroy) destroy: *pnetif = netif->hash_next; unregister_netdev(netif->dev); - kfree(netif->dev); + free_netdev(netif->dev); destroy->status = NETIF_BE_STATUS_OKAY; } From 3752c7fe16d51e7065d8078acbd91bd3f6fe6196 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Wed, 1 Dec 2004 11:24:11 +0000 Subject: [PATCH 09/18] bitkeeper revision 1.1159.187.47 (41ada9dbh_spg2MhqENrhyi6SP00Kg) Enable some more kernel debugging. Remember to turn off before pushing to the stable repository! --- .../arch/xen/configs/xen0_defconfig | 6 +++--- .../arch/xen/configs/xenU_defconfig | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig b/linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig index 7d7cd9b99b..ab0aedf8c1 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig +++ b/linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.9-xen0 -# Sun Nov 14 16:55:05 2004 +# Wed Dec 1 09:22:49 2004 # CONFIG_XEN=y CONFIG_ARCH_XEN=y @@ -151,10 +151,10 @@ CONFIG_DEBUG_KERNEL=y CONFIG_EARLY_PRINTK=y # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_SLAB=y CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_DEBUG_PAGEALLOC=y # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_FRAME_POINTER is not set diff --git a/linux-2.6.9-xen-sparse/arch/xen/configs/xenU_defconfig b/linux-2.6.9-xen-sparse/arch/xen/configs/xenU_defconfig index d7b98c3b9d..2ff55781d0 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/configs/xenU_defconfig +++ b/linux-2.6.9-xen-sparse/arch/xen/configs/xenU_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.9-xen0 -# Sun Oct 31 21:32:23 2004 +# Linux kernel version: 2.6.9-xenU +# Wed Dec 1 09:22:09 2004 # CONFIG_XEN=y CONFIG_ARCH_XEN=y @@ -45,6 +45,7 @@ CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -114,8 +115,15 @@ CONFIG_HAVE_DEC_LOCK=y # # Kernel hacking # -# CONFIG_DEBUG_KERNEL is not set +CONFIG_DEBUG_KERNEL=y CONFIG_EARLY_PRINTK=y +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_SLAB=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_PAGEALLOC=y +# CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_FRAME_POINTER is not set # CONFIG_4KSTACKS is not set @@ -140,6 +148,7 @@ CONFIG_BINFMT_ELF=y CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set # # Block devices From ae51438ac62eb5db9d1815b52bbe3e2aef551199 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Wed, 1 Dec 2004 13:25:22 +0000 Subject: [PATCH 10/18] bitkeeper revision 1.1159.187.48 (41adc6420WlNaaoUkvfgNxl44rpYYg) Export Xen s/w perfctrs to DOM0 via new 'xenperf' utility. --- .rootkeys | 1 + BitKeeper/etc/ignore | 2 +- tools/libxc/xc.h | 9 ++- tools/libxc/xc_misc.c | 18 +++++- tools/misc/Makefile | 16 ++--- tools/misc/xenperf.c | 104 +++++++++++++++++++++++++++++++ xen/arch/x86/memory.c | 6 +- xen/common/dom0_ops.c | 10 +++ xen/common/perfc.c | 111 +++++++++++++++++++++++++++++++++- xen/include/public/dom0_ops.h | 20 ++++++ 10 files changed, 278 insertions(+), 19 deletions(-) create mode 100644 tools/misc/xenperf.c diff --git a/.rootkeys b/.rootkeys index 1691f867c4..31497b58ac 100644 --- a/.rootkeys +++ b/.rootkeys @@ -380,6 +380,7 @@ 3f5ef5a2dTZP0nnsFoeq2jRf3mWDDg tools/misc/xen-clone.README 405eedf6_nnNhFQ1I85lhCkLK6jFGA tools/misc/xencons 40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/misc/xend +41adc641dV-0cDLSyzMs5BT8nL7v3Q tools/misc/xenperf.c 4107986eMWVdBoz4tXYoOscpN_BCYg tools/misc/xensv 4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops 40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm diff --git a/BitKeeper/etc/ignore b/BitKeeper/etc/ignore index ec7c4e8ee6..6767868bd3 100644 --- a/BitKeeper/etc/ignore +++ b/BitKeeper/etc/ignore @@ -58,7 +58,7 @@ tools/balloon/balloon tools/check/.* tools/libxc/xen/* tools/misc/miniterm/miniterm -tools/misc/xen_cpuperf +tools/misc/xenperf tools/vnet/gc tools/vnet/gc*/* tools/vnet/vnet-module/.tmp_versions/* diff --git a/tools/libxc/xc.h b/tools/libxc/xc.h index 7778b71673..18665e9178 100644 --- a/tools/libxc/xc.h +++ b/tools/libxc/xc.h @@ -178,14 +178,19 @@ int xc_domain_setinitialmem(int xc_handle, unsigned int initial_memkb); int xc_domain_setmaxmem(int xc_handle, - u32 domid, - unsigned int max_memkb); + u32 domid, + unsigned int max_memkb); int xc_domain_setvmassist(int xc_handle, u32 domid, unsigned int cmd, unsigned int type); +typedef dom0_perfc_desc_t xc_perfc_desc_t; +/* IMPORTANT: The caller is responsible for mlock()'ing the @desc array. */ +int xc_perfc_control(int xc_handle, + u32 op, + xc_perfc_desc_t *desc); void *xc_map_foreign_range(int xc_handle, u32 dom, int size, int prot, diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c index e8ea18c5ff..0efd1f1972 100644 --- a/tools/libxc/xc_misc.c +++ b/tools/libxc/xc_misc.c @@ -74,10 +74,26 @@ int xc_sched_id(int xc_handle, op.cmd = DOM0_SCHED_ID; op.interface_version = DOM0_INTERFACE_VERSION; - if((ret = do_dom0_op(xc_handle, &op))) return ret; + if ( (ret = do_dom0_op(xc_handle, &op)) != 0 ) + return ret; *sched_id = op.u.sched_id.sched_id; return 0; } +int xc_perfc_control(int xc_handle, + u32 op, + xc_perfc_desc_t *desc) +{ + int rc; + dom0_op_t dop; + + dop.cmd = DOM0_PERFCCONTROL; + dop.u.perfccontrol.op = op; + dop.u.perfccontrol.desc = desc; + + rc = do_dom0_op(xc_handle, &dop); + + return (rc == 0) ? dop.u.perfccontrol.nr_counters : rc; +} diff --git a/tools/misc/Makefile b/tools/misc/Makefile index 760348b0b4..7c20e8d1b0 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -3,22 +3,18 @@ XEN_ROOT=../.. include $(XEN_ROOT)/tools/Make.defs CC = gcc -CFLAGS = -Wall -O3 +CFLAGS = -Wall -Werror -O3 INCLUDES += -I $(XEN_XC) INCLUDES += -I $(XEN_LIBXC) -INCLUDES += -I $(XEN_LIBXUTIL) - -CFLAGS += $(INCLUDES) +CFLAGS += $(INCLUDES) HDRS = $(wildcard *.h) -SRCS = $(wildcard *.c) -OBJS = $(patsubst %.c,%.o,$(SRCS)) -TARGETS = +TARGETS = xenperf INSTALL_BIN = $(TARGETS) xencons -INSTALL_SBIN = netfix xm xend xensv +INSTALL_SBIN = netfix xm xend xensv xenperf all: $(TARGETS) $(MAKE) -C miniterm @@ -32,7 +28,7 @@ install: all clean: $(RM) *.o $(TARGETS) *~ - $(MAKE) -C miniterm clean + $(MAKE) -C miniterm clean %: %.c $(HDRS) Makefile - $(CC) $(CFLAGS) -o $@ $< + $(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxc -L$(XEN_LIBXUTIL) -lxutil diff --git a/tools/misc/xenperf.c b/tools/misc/xenperf.c new file mode 100644 index 0000000000..d2846224b1 --- /dev/null +++ b/tools/misc/xenperf.c @@ -0,0 +1,104 @@ +/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- + **************************************************************************** + * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge + **************************************************************************** + * + * File: xenperf.c + * Author: Rolf Neugebauer (rolf.neugebauer@intel.com) + * Date: Nov 2004 + * + * Description: + */ + + +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + int i, j, xc_handle; + xc_perfc_desc_t *pcd; + unsigned int num, sum, reset = 0; + + if ( argc > 1 ) + { + char *p = argv[1]; + if ( (*p++ == '-') && (*p == 'r') ) + reset = 1; + else + { + printf("%s: [-r]\n", argv[0]); + printf("no args: print xen performance counters\n"); + printf(" -r : reset xen performance counters\n"); + return 0; + } + } + + if ( (xc_handle = xc_interface_open()) == -1 ) + { + fprintf(stderr, "Error opening xc interface: %d (%s)\n", + errno, strerror(errno)); + return 1; + } + + if ( reset ) + { + if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_RESET, + NULL) < 0 ) + { + fprintf(stderr, "Error reseting performance counters: %d (%s)\n", + errno, strerror(errno)); + return 1; + } + + return 0; + } + + + if ( (num = xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY, + NULL)) < 0 ) + { + fprintf(stderr, "Error getting number of perf counters: %d (%s)\n", + errno, strerror(errno)); + return 1; + } + + pcd = malloc(sizeof(*pcd) * num); + + if ( mlock(pcd, sizeof(*pcd) * num) != 0 ) + { + fprintf(stderr, "Could not mlock descriptor buffer: %d (%s)\n", + errno, strerror(errno)); + exit(-1); + } + + if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY, pcd) <= 0 ) + { + fprintf(stderr, "Error getting perf counter description: %d (%s)\n", + errno, strerror(errno)); + return 1; + } + + munlock(pcd, sizeof(*pcd) * num); + + for ( i = 0; i < num; i++ ) + { + printf ("%-35s ", pcd[i].name); + + sum = 0; + for ( j = 0; j < pcd[i].nr_vals; j++ ) + sum += pcd[i].vals[j]; + printf ("T=%10u ", (unsigned int)sum); + + for ( j = 0; j < pcd[i].nr_vals; j++ ) + printf(" %10u", (unsigned int)pcd[i].vals[j]); + + printf("\n"); + } + + return 0; +} diff --git a/xen/arch/x86/memory.c b/xen/arch/x86/memory.c index 5734f45ba9..7cab825a4d 100644 --- a/xen/arch/x86/memory.c +++ b/xen/arch/x86/memory.c @@ -1299,9 +1299,6 @@ int do_mmu_update( u32 type_info; domid_t domid; - perfc_incrc(calls_to_mmu_update); - perfc_addc(num_page_updates, count); - cleanup_writable_pagetable(d, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE); /* @@ -1331,6 +1328,9 @@ int do_mmu_update( } } + perfc_incrc(calls_to_mmu_update); + perfc_addc(num_page_updates, count); + if ( unlikely(!array_access_ok(VERIFY_READ, ureqs, count, sizeof(req))) ) { rc = -EFAULT; diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index 812814068b..5622ae174e 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -651,6 +651,16 @@ long do_dom0_op(dom0_op_t *u_dom0_op) } break; +#ifdef PERF_COUNTERS + case DOM0_PERFCCONTROL: + { + extern int perfc_control(dom0_perfccontrol_t *); + ret = perfc_control(&op->u.perfccontrol); + copy_to_user(u_dom0_op, op, sizeof(*op)); + } + break; +#endif + default: ret = arch_do_dom0_op(op,u_dom0_op); diff --git a/xen/common/perfc.c b/xen/common/perfc.c index 3a05c2e071..d5384c4af5 100644 --- a/xen/common/perfc.c +++ b/xen/common/perfc.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #undef PERFCOUNTER #undef PERFCOUNTER_CPU @@ -79,8 +81,9 @@ void perfc_reset(unsigned char key) s_time_t now = NOW(); atomic_t *counters = (atomic_t *)&perfcounters; - printk("Xen performance counters RESET (now = 0x%08X:%08X)\n", - (u32)(now>>32), (u32)now); + if ( key != '\0' ) + printk("Xen performance counters RESET (now = 0x%08X:%08X)\n", + (u32)(now>>32), (u32)now); /* leave STATUS counters alone -- don't reset */ @@ -109,3 +112,107 @@ void perfc_reset(unsigned char key) } } +static dom0_perfc_desc_t perfc_d[NR_PERFCTRS]; +static int perfc_init = 0; +static int perfc_copy_info(dom0_perfc_desc_t *desc) +{ + unsigned int i, j; + atomic_t *counters = (atomic_t *)&perfcounters; + + if ( desc == NULL ) + return 0; + + /* We only copy the name and array-size information once. */ + if ( !perfc_init ) + { + for ( i = 0; i < NR_PERFCTRS; i++ ) + { + strncpy(perfc_d[i].name, perfc_info[i].name, + sizeof(perfc_d[i].name)); + perfc_d[i].name[sizeof(perfc_d[i].name)-1] = '\0'; + + switch ( perfc_info[i].type ) + { + case TYPE_SINGLE: + case TYPE_S_SINGLE: + perfc_d[i].nr_vals = 1; + break; + case TYPE_CPU: + case TYPE_S_CPU: + perfc_d[i].nr_vals = smp_num_cpus; + break; + case TYPE_ARRAY: + case TYPE_S_ARRAY: + perfc_d[i].nr_vals = perfc_info[i].nr_elements; + break; + } + + if ( perfc_d[i].nr_vals > ARRAY_SIZE(perfc_d[i].vals) ) + perfc_d[i].nr_vals = ARRAY_SIZE(perfc_d[i].vals); + } + + perfc_init = 1; + } + + /* We gather the counts together every time. */ + for ( i = 0; i < NR_PERFCTRS; i++ ) + { + switch ( perfc_info[i].type ) + { + case TYPE_SINGLE: + case TYPE_S_SINGLE: + perfc_d[i].vals[0] = atomic_read(&counters[0]); + counters += 1; + break; + case TYPE_CPU: + case TYPE_S_CPU: + for ( j = 0; j < perfc_d[i].nr_vals; j++ ) + perfc_d[i].vals[j] = atomic_read(&counters[j]); + counters += NR_CPUS; + break; + case TYPE_ARRAY: + case TYPE_S_ARRAY: + for ( j = 0; j < perfc_d[i].nr_vals; j++ ) + perfc_d[i].vals[j] = atomic_read(&counters[j]); + counters += perfc_info[i].nr_elements; + break; + } + } + + return (copy_to_user(desc, perfc_d, NR_PERFCTRS * sizeof(*desc)) ? + -EFAULT : 0); +} + +/* Dom0 control of perf counters */ +int perfc_control(dom0_perfccontrol_t *pc) +{ + static spinlock_t lock = SPIN_LOCK_UNLOCKED; + u32 op = pc->op; + int rc; + + pc->nr_counters = NR_PERFCTRS; + + spin_lock(&lock); + + switch ( op ) + { + case DOM0_PERFCCONTROL_OP_RESET: + perfc_copy_info(pc->desc); + perfc_reset(0); + rc = 0; + break; + + case DOM0_PERFCCONTROL_OP_QUERY: + perfc_copy_info(pc->desc); + rc = 0; + break; + + default: + rc = -EINVAL; + break; + } + + spin_unlock(&lock); + + return rc; +} diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h index f8c7bab6d3..9673c88678 100644 --- a/xen/include/public/dom0_ops.h +++ b/xen/include/public/dom0_ops.h @@ -386,6 +386,25 @@ typedef struct { u32 __pad1; } PACKED dom0_read_memtype_t; /* 32 bytes */ +/* Interface for controlling Xen software performance counters. */ +#define DOM0_PERFCCONTROL 34 +/* Sub-operations: */ +#define DOM0_PERFCCONTROL_OP_RESET 1 /* Reset all counters to zero. */ +#define DOM0_PERFCCONTROL_OP_QUERY 2 /* Get perfctr information. */ +typedef struct { + u8 name[80]; /* 0: name of perf counter */ + u32 nr_vals; /* 80: number of values for this counter */ + u32 vals[64]; /* 84: array of values */ +} PACKED dom0_perfc_desc_t; /* 340 bytes */ +typedef struct { + /* IN variables. */ + u32 op; /* 0: DOM0_PERFCCONTROL_OP_??? */ + /* OUT variables. */ + u32 nr_counters; /* 4: number of counters */ + dom0_perfc_desc_t *desc; /* 8: counter information (or NULL) */ + MEMORY_PADDING; +} PACKED dom0_perfccontrol_t; /* 16 bytes */ + typedef struct { u32 cmd; /* 0 */ u32 interface_version; /* 4 */ /* DOM0_INTERFACE_VERSION */ @@ -419,6 +438,7 @@ typedef struct { dom0_add_memtype_t add_memtype; dom0_del_memtype_t del_memtype; dom0_read_memtype_t read_memtype; + dom0_perfccontrol_t perfccontrol; } PACKED u; } PACKED dom0_op_t; /* 80 bytes */ From 2639d4fd5c43a0e2e913c13df4103b7f279bb629 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Thu, 2 Dec 2004 09:21:05 +0000 Subject: [PATCH 11/18] bitkeeper revision 1.1159.187.49 (41aede81IBQOThmH0W0AYSHb2Gt7sA) Split out install targets in root Makefile. --- Makefile | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 83a844202e..13f5c5cb97 100644 --- a/Makefile +++ b/Makefile @@ -19,10 +19,30 @@ export INSTALL_DIR include buildconfigs/Rules.mk .PHONY: all dist install xen tools kernels docs world clean mkpatches mrproper -.PHONY: kbuild kdelete kclean +.PHONY: kbuild kdelete kclean install_tools install_xen install_docs +.PHONY: install_kernel all: dist +# install everything into the standard system directories +# NB: install explicitly does not check that everything is up to date! +install: install_tools install_xen install_kernels install_docs + +install_xen: + $(MAKE) -C xen install + +install_tools: + $(MAKE) -C tools install + +install_kernels: + $(shell cp -a $(INSTALL_DIR)/boot/* /boot/) + $(shell cp -a $(INSTALL_DIR)/lib/modules/* /lib/modules/) + $(shell cp -dR $(INSTALL_DIR)/boot/*$(LINUX_VER)* $(prefix)/boot/) + $(shell cp -dR $(INSTALL_DIR)/lib/modules/* $(prefix)/lib/modules/) + +install_docs: + sh ./docs/check_pkgs && $(MAKE) -C docs install || true + # build and install everything into local dist directory dist: xen tools kernels docs install -m0644 ./COPYING $(DIST_DIR) @@ -31,17 +51,6 @@ dist: xen tools kernels docs mkdir -p $(DIST_DIR)/check install -m0755 tools/check/chk tools/check/check_* $(DIST_DIR)/check -# install everything into the standard system directories -# NB: install explicitly does not check that everything is up to date! -install: - $(MAKE) -C xen install - $(MAKE) -C tools install - $(shell cp -a $(INSTALL_DIR)/boot/* /boot/) - $(shell cp -a $(INSTALL_DIR)/lib/modules/* /lib/modules/) - sh ./docs/check_pkgs && $(MAKE) -C docs install || true - $(shell cp -dR $(INSTALL_DIR)/boot/*$(LINUX_VER)* $(prefix)/boot/) - $(shell cp -dR $(INSTALL_DIR)/lib/modules/* $(prefix)/lib/modules/) - xen: $(MAKE) prefix=$(INSTALL_DIR) dist=yes -C xen install From 89c6d52aafcd9111e8e30bf48f88eaa1f85d2ca3 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Thu, 2 Dec 2004 09:21:31 +0000 Subject: [PATCH 12/18] bitkeeper revision 1.1159.187.50 (41aede9butKaW-WoEitdCDyiPTD0mg) Export ctrl_if API to modules. --- linux-2.4.28-xen-sparse/arch/xen/kernel/Makefile | 2 +- linux-2.6.9-xen-sparse/arch/xen/kernel/ctrl_if.c | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/linux-2.4.28-xen-sparse/arch/xen/kernel/Makefile b/linux-2.4.28-xen-sparse/arch/xen/kernel/Makefile index 30488e666b..3eb0701958 100644 --- a/linux-2.4.28-xen-sparse/arch/xen/kernel/Makefile +++ b/linux-2.4.28-xen-sparse/arch/xen/kernel/Makefile @@ -6,7 +6,7 @@ all: kernel.o head.o init_task.o O_TARGET := kernel.o -export-objs := i386_ksyms.o gnttab.o skbuff.o +export-objs := i386_ksyms.o gnttab.o skbuff.o ctrl_if.o obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o \ diff --git a/linux-2.6.9-xen-sparse/arch/xen/kernel/ctrl_if.c b/linux-2.6.9-xen-sparse/arch/xen/kernel/ctrl_if.c index 78195fa1ab..c5ab59b826 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/kernel/ctrl_if.c +++ b/linux-2.6.9-xen-sparse/arch/xen/kernel/ctrl_if.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -541,3 +542,10 @@ void ctrl_if_discard_responses(void) ctrl_if_tx_resp_cons = get_ctrl_if()->tx_resp_prod; } +EXPORT_SYMBOL(ctrl_if_send_message_noblock); +EXPORT_SYMBOL(ctrl_if_send_message_block); +EXPORT_SYMBOL(ctrl_if_send_message_and_get_response); +EXPORT_SYMBOL(ctrl_if_enqueue_space_callback); +EXPORT_SYMBOL(ctrl_if_send_response); +EXPORT_SYMBOL(ctrl_if_register_receiver); +EXPORT_SYMBOL(ctrl_if_unregister_receiver); From 37f78e88600942ea5263e3d04ffd423d08a70895 Mon Sep 17 00:00:00 2001 From: "cl349@arcadians.cl.cam.ac.uk" Date: Thu, 2 Dec 2004 10:24:43 +0000 Subject: [PATCH 13/18] bitkeeper revision 1.1159.187.51 (41aeed6bzN1zaGFaAP8KEzkGD9sW_A) Makefile: Rename install_* targets to install-* -- matching the targets we had already. --- Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 13f5c5cb97..7d4d23f7ef 100644 --- a/Makefile +++ b/Makefile @@ -19,28 +19,28 @@ export INSTALL_DIR include buildconfigs/Rules.mk .PHONY: all dist install xen tools kernels docs world clean mkpatches mrproper -.PHONY: kbuild kdelete kclean install_tools install_xen install_docs -.PHONY: install_kernel +.PHONY: kbuild kdelete kclean install-tools install-xen install-docs +.PHONY: install-kernels all: dist # install everything into the standard system directories # NB: install explicitly does not check that everything is up to date! -install: install_tools install_xen install_kernels install_docs +install: install-tools install-xen install-kernels install-docs -install_xen: +install-xen: $(MAKE) -C xen install -install_tools: +install-tools: $(MAKE) -C tools install -install_kernels: +install-kernels: $(shell cp -a $(INSTALL_DIR)/boot/* /boot/) $(shell cp -a $(INSTALL_DIR)/lib/modules/* /lib/modules/) $(shell cp -dR $(INSTALL_DIR)/boot/*$(LINUX_VER)* $(prefix)/boot/) $(shell cp -dR $(INSTALL_DIR)/lib/modules/* $(prefix)/lib/modules/) -install_docs: +install-docs: sh ./docs/check_pkgs && $(MAKE) -C docs install || true # build and install everything into local dist directory From c71e2fce22f279ae95bd17a032174170d6c732fe Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Thu, 2 Dec 2004 16:17:28 +0000 Subject: [PATCH 14/18] bitkeeper revision 1.1159.203.1 (41af4018fV44p80Jw5YxFLlk5sh8jg) Cleaned balloon driver internals. Better integration with device drivers that also inc/dec memory reservation. Should be more informative (cat /proc/xen/balloon) and more stable. Needs testing with Linux 2.4... --- .rootkeys | 1 + linux-2.4.28-xen-sparse/mkbuildtree | 1 + .../arch/xen/i386/kernel/pci-dma.c | 8 +- .../arch/xen/i386/mm/hypervisor.c | 50 +- linux-2.6.9-xen-sparse/drivers/xen/Makefile | 4 +- .../drivers/xen/balloon/balloon.c | 512 +++++++++--------- .../drivers/xen/netback/netback.c | 54 +- .../drivers/xen/netfront/netfront.c | 12 +- .../drivers/xen/privcmd/privcmd.c | 19 +- .../include/asm-xen/balloon.h | 51 ++ .../include/asm-xen/hypervisor.h | 2 - 11 files changed, 364 insertions(+), 350 deletions(-) create mode 100644 linux-2.6.9-xen-sparse/include/asm-xen/balloon.h diff --git a/.rootkeys b/.rootkeys index 31497b58ac..44aaa3ca19 100644 --- a/.rootkeys +++ b/.rootkeys @@ -237,6 +237,7 @@ 40f5623bc8LKPRO09wY5dGDnY_YCpw linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/tlbflush.h 41062ab7uFxnCq-KtPeAm-aV8CicgA linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/vga.h 40f5623bxUbeGjkRrjDguCy_Gm8RLw linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/xor.h +41af4017PDMuSmMWtSRU5UC9Vylw5g linux-2.6.9-xen-sparse/include/asm-xen/balloon.h 40f5623bYNP7tHE2zX6YQxp9Zq2utQ linux-2.6.9-xen-sparse/include/asm-xen/ctrl_if.h 40f5623b3Eqs8pAc5WpPX8_jTzV2qw linux-2.6.9-xen-sparse/include/asm-xen/evtchn.h 419b4e9367PjTEvdjwavWN12BeBBXg linux-2.6.9-xen-sparse/include/asm-xen/foreign_page.h diff --git a/linux-2.4.28-xen-sparse/mkbuildtree b/linux-2.4.28-xen-sparse/mkbuildtree index 382d90588b..a0e52c2c5c 100755 --- a/linux-2.4.28-xen-sparse/mkbuildtree +++ b/linux-2.4.28-xen-sparse/mkbuildtree @@ -204,6 +204,7 @@ ln -sf ../asm-i386/unaligned.h ln -sf ../asm-i386/unistd.h ln -sf ../asm-i386/user.h ln -sf ../asm-i386/vm86.h +ln -sf ../../${LINUX_26}/include/asm-xen/balloon.h ln -sf ../../${LINUX_26}/include/asm-xen/ctrl_if.h ln -sf ../../${LINUX_26}/include/asm-xen/evtchn.h ln -sf ../../${LINUX_26}/include/asm-xen/gnttab.h diff --git a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/pci-dma.c b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/pci-dma.c index b7939cff41..c346281405 100644 --- a/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/pci-dma.c +++ b/linux-2.6.9-xen-sparse/arch/xen/i386/kernel/pci-dma.c @@ -13,6 +13,7 @@ #include #include #include +#include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) #define pte_offset_kernel pte_offset @@ -37,9 +38,12 @@ xen_contig_memory(unsigned long vstart, unsigned int order) pgd_t *pgd; pmd_t *pmd; pte_t *pte; - unsigned long pfn, i; + unsigned long pfn, i, flags; scrub_pages(vstart, 1 << order); + + balloon_lock(flags); + /* 1. Zap current PTEs, giving away the underlying pages. */ for (i = 0; i < (1< #include #include +#include /* * This suffices to protect us if we ever move to SMP domains. @@ -352,7 +353,6 @@ unsigned long allocate_empty_lowmem_region(unsigned long pages) unsigned long *pfn_array; unsigned long vstart; unsigned long i; - int ret; unsigned int order = get_order(pages*PAGE_SIZE); vstart = __get_free_pages(GFP_KERNEL, order); @@ -378,57 +378,11 @@ unsigned long allocate_empty_lowmem_region(unsigned long pages) /* Flush updates through and flush the TLB. */ xen_tlb_flush(); - ret = HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, - pfn_array, 1<>PAGE_SHIFT); - phys_to_machine_mapping[__pa(vstart)>>PAGE_SHIFT] = pfn_array[i]; - } - - flush_page_update_queue(); - - vfree(pfn_array); - - free_pages(vstart, order); -} - #endif /* CONFIG_XEN_PHYSDEV_ACCESS */ diff --git a/linux-2.6.9-xen-sparse/drivers/xen/Makefile b/linux-2.6.9-xen-sparse/drivers/xen/Makefile index e181171a61..0bfb5a50c3 100644 --- a/linux-2.6.9-xen-sparse/drivers/xen/Makefile +++ b/linux-2.6.9-xen-sparse/drivers/xen/Makefile @@ -2,9 +2,9 @@ obj-y += console/ obj-y += evtchn/ -obj-y += privcmd/ -obj-y += balloon/ +obj-y += balloon/ +obj-$(CONFIG_XEN_PRIVILEGED_GUEST) += privcmd/ obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkback/ obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/ obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += blkfront/ diff --git a/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c b/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c index 94658f1e54..772d52b1ec 100644 --- a/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c +++ b/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c @@ -29,8 +29,8 @@ */ #include -#include #include +#include #include #include #include @@ -43,16 +43,41 @@ #include #include #include +#include #include #include #include #include #include +#define MIN_TARGET ((16 << 20) >> PAGE_SHIFT) /* 16MB */ + static struct proc_dir_entry *balloon_pde; -unsigned long credit; +static DECLARE_MUTEX(balloon_mutex); +spinlock_t balloon_lock = SPIN_LOCK_UNLOCKED; + +/* We aim for 'current allocation' == 'target allocation'. */ static unsigned long current_pages; +static unsigned long target_pages; + +/* We may hit the hard limit in Xen. If we do then we remember it. */ +static unsigned long hard_limit; + +/* + * Drivers may alter the memory reservation independently, but they must + * inform the balloon driver so that we can avoid hitting the hard limit. + */ +static unsigned long driver_pages; + +/* List of ballooned pages, threaded through the mem_map array. */ +static LIST_HEAD(ballooned_pages); +static unsigned long balloon_low, balloon_high; + +/* Main work function, always executed in process context. */ +static void balloon_process(void *unused); +static DECLARE_WORK(balloon_worker, balloon_process, NULL); +static struct timer_list balloon_timer; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) /* Use the private and mapping fields of struct page as a list. */ @@ -75,17 +100,24 @@ static unsigned long current_pages; #define WPRINTK(fmt, args...) \ printk(KERN_WARNING "xen_mem: " fmt, ##args) -/* List of ballooned pages, threaded through the mem_map array. */ -LIST_HEAD(ballooned_pages); - /* balloon_append: add the given page to the balloon. */ -void balloon_append(struct page *page) +static void balloon_append(struct page *page) { - list_add(PAGE_TO_LIST(page), &ballooned_pages); + /* Low memory is re-populated first, so highmem pages go at list tail. */ + if ( PageHighMem(page) ) + { + list_add_tail(PAGE_TO_LIST(page), &ballooned_pages); + balloon_high++; + } + else + { + list_add(PAGE_TO_LIST(page), &ballooned_pages); + balloon_low++; + } } /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ -struct page *balloon_retrieve(void) +static struct page *balloon_retrieve(void) { struct page *page; @@ -94,6 +126,12 @@ struct page *balloon_retrieve(void) page = LIST_TO_PAGE(ballooned_pages.next); UNLIST_PAGE(page); + + if ( PageHighMem(page) ) + balloon_high--; + else + balloon_low--; + return page; } @@ -111,194 +149,148 @@ static inline pte_t *get_ptep(unsigned long addr) return pte_offset_kernel(pmd, addr); } -/* Main function for relinquishing memory. */ -static unsigned long inflate_balloon(unsigned long num_pages) +static void balloon_alarm(unsigned long unused) { - unsigned long *parray, *currp, curraddr, ret = 0, i, j, mfn, pfn; - struct page *page; - - parray = (unsigned long *)vmalloc(num_pages * sizeof(unsigned long)); - if ( parray == NULL ) - { - WPRINTK("inflate_balloon: Unable to vmalloc parray\n"); - return -ENOMEM; - } - - currp = parray; - - for ( i = 0; i < num_pages; i++, currp++ ) - { - page = alloc_page(GFP_HIGHUSER); - pfn = page - mem_map; - - /* If allocation fails then free all reserved pages. */ - if ( page == NULL ) - { - printk(KERN_ERR "Unable to inflate balloon by %ld, only" - " %ld pages free.", num_pages, i); - currp = parray; - for ( j = 0; j < i; j++, currp++ ) - __free_page((struct page *) (mem_map + *currp)); - - ret = -EFAULT; - goto cleanup; - } - - *currp = pfn; - } - - for ( i = 0, currp = parray; i < num_pages; i++, currp++ ) - { - mfn = phys_to_machine_mapping[*currp]; - curraddr = (unsigned long)page_address(mem_map + *currp); - /* Blow away page contents for security, and also p.t. ref if any. */ - if ( curraddr != 0 ) - { - scrub_pages(curraddr, 1); - queue_l1_entry_update(get_ptep(curraddr), 0); - } -#ifdef CONFIG_XEN_SCRUB_PAGES - else - { - void *p = kmap(&mem_map[*currp]); - scrub_pages(p, 1); - kunmap(&mem_map[*currp]); - } -#endif - - balloon_append(&mem_map[*currp]); - - phys_to_machine_mapping[*currp] = INVALID_P2M_ENTRY; - *currp = mfn; - } - - /* Flush updates through and flush the TLB. */ - xen_tlb_flush(); - - ret = HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, - parray, num_pages, 0); - if ( unlikely(ret != num_pages) ) - { - printk(KERN_ERR "Unable to inflate balloon, error %lx\n", ret); - goto cleanup; - } - - credit += num_pages; - ret = num_pages; - - cleanup: - vfree(parray); - - return ret; + schedule_work(&balloon_worker); } -/* Install a set of new pages (@mfn_list, @nr_mfns) into the memory map. */ -static unsigned long process_returned_pages( - unsigned long *mfn_list, unsigned long nr_mfns) +static unsigned long current_target(void) { - unsigned long pfn, i; - struct page *page; + unsigned long target = min(target_pages, hard_limit); + if ( target > (current_pages + balloon_low + balloon_high) ) + target = current_pages + balloon_low + balloon_high; + if ( target < MIN_TARGET ) + target = MIN_TARGET; + return target; +} - for ( i = 0; i < nr_mfns; i++ ) +static void balloon_process(void *unused) +{ + unsigned long *mfn_list, pfn, i, flags; + struct page *page; + long credit, debt, rc; + void *v; + + down(&balloon_mutex); + + retry: + mfn_list = NULL; + + if ( (credit = current_target() - current_pages) > 0 ) { - if ( (page = balloon_retrieve()) != NULL ) - break; + mfn_list = (unsigned long *)vmalloc(credit * sizeof(*mfn_list)); + if ( mfn_list == NULL ) + goto out; - pfn = page - mem_map; - if ( phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY ) + balloon_lock(flags); + rc = HYPERVISOR_dom_mem_op( + MEMOP_increase_reservation, mfn_list, credit, 0); + balloon_unlock(flags); + if ( rc < credit ) + { + /* We hit the Xen hard limit: reprobe. */ + if ( HYPERVISOR_dom_mem_op( + MEMOP_decrease_reservation, mfn_list, rc, 0) != rc ) + BUG(); + hard_limit = current_pages + rc - driver_pages; + vfree(mfn_list); + goto retry; + } + + for ( i = 0; i < credit; i++ ) + { + if ( (page = balloon_retrieve()) == NULL ) + BUG(); + + pfn = page - mem_map; + if ( phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY ) + BUG(); + + /* Update P->M and M->P tables. */ + phys_to_machine_mapping[pfn] = mfn_list[i]; + queue_machphys_update(mfn_list[i], pfn); + + /* Link back into the page tables if it's not a highmem page. */ + if ( pfn < max_low_pfn ) + queue_l1_entry_update( + get_ptep((unsigned long)__va(pfn << PAGE_SHIFT)), + (mfn_list[i] << PAGE_SHIFT) | pgprot_val(PAGE_KERNEL)); + + /* Finally, relinquish the memory back to the system allocator. */ + ClearPageReserved(page); + set_page_count(page, 1); + __free_page(page); + } + + current_pages += credit; + } + else if ( credit < 0 ) + { + debt = -credit; + + mfn_list = (unsigned long *)vmalloc(debt * sizeof(*mfn_list)); + if ( mfn_list == NULL ) + goto out; + + for ( i = 0; i < debt; i++ ) + { + if ( (page = alloc_page(GFP_HIGHUSER)) == NULL ) + { + debt = i; + break; + } + + pfn = page - mem_map; + mfn_list[i] = phys_to_machine_mapping[pfn]; + phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY; + + if ( !PageHighMem(page) ) + { + v = phys_to_virt((page - mem_map) << PAGE_SHIFT); + scrub_pages(v, 1); + queue_l1_entry_update(get_ptep((unsigned long)v), 0); + } +#ifdef CONFIG_XEN_SCRUB_PAGES + else + { + v = kmap(page); + scrub_pages(v, 1); + kunmap(page); + } +#endif + + balloon_append(page); + } + + /* Flush updates through and flush the TLB. */ + xen_tlb_flush(); + + if ( HYPERVISOR_dom_mem_op( + MEMOP_decrease_reservation, mfn_list, debt, 0) != debt ) BUG(); - /* Update P->M and M->P tables. */ - phys_to_machine_mapping[pfn] = mfn_list[i]; - queue_machphys_update(mfn_list[i], pfn); - - /* Link back into the page tables if it's not a highmem page. */ - if ( pfn < max_low_pfn ) - queue_l1_entry_update( - get_ptep((unsigned long)__va(pfn << PAGE_SHIFT)), - (mfn_list[i] << PAGE_SHIFT) | pgprot_val(PAGE_KERNEL)); - - /* Finally, relinquish the memory back to the system allocator. */ - ClearPageReserved(page); - set_page_count(page, 1); - __free_page(page); + current_pages -= debt; } - return i; + out: + if ( mfn_list != NULL ) + vfree(mfn_list); + + /* Schedule more work if there is some still to be done. */ + if ( current_target() != current_pages ) + mod_timer(&balloon_timer, jiffies + HZ); + + up(&balloon_mutex); } -unsigned long deflate_balloon(unsigned long num_pages) +/* Resets the Xen limit, sets new target, and kicks off processing. */ +static void set_new_target(unsigned long target) { - unsigned long ret; - unsigned long *parray; - - if ( num_pages > credit ) - { - printk(KERN_ERR "deflate_balloon: %lu pages > %lu credit.\n", - num_pages, credit); - return -EAGAIN; - } - - parray = (unsigned long *)vmalloc(num_pages * sizeof(unsigned long)); - if ( parray == NULL ) - { - printk(KERN_ERR "deflate_balloon: Unable to vmalloc parray\n"); - return 0; - } - - ret = HYPERVISOR_dom_mem_op(MEMOP_increase_reservation, - parray, num_pages, 0); - if ( unlikely(ret != num_pages) ) - { - printk(KERN_ERR "deflate_balloon: xen increase_reservation err %lx\n", - ret); - goto cleanup; - } - - if ( (ret = process_returned_pages(parray, num_pages)) < num_pages ) - { - printk(KERN_WARNING - "deflate_balloon: restored only %lx of %lx pages.\n", - ret, num_pages); - goto cleanup; - } - - ret = num_pages; - credit -= num_pages; - - cleanup: - vfree(parray); - - return ret; + hard_limit = ~0UL; + target_pages = target; + balloon_process(NULL); } -#define PAGE_TO_MB_SHIFT 8 - -static int balloon_try_target(int target) -{ - int change, reclaim; - - if ( target < current_pages ) - { - if ( (change = inflate_balloon(current_pages-target)) <= 0 ) - return change; - current_pages -= change; - printk(KERN_INFO "Relinquish %dMB to xen. Domain now has %luMB\n", - change>>PAGE_TO_MB_SHIFT, current_pages>>PAGE_TO_MB_SHIFT); - } - else if ( (reclaim = target - current_pages) > 0 ) - { - if ( (change = deflate_balloon(reclaim)) <= 0 ) - return change; - current_pages += change; - printk(KERN_INFO "Reclaim %dMB from xen. Domain now has %luMB\n", - change>>PAGE_TO_MB_SHIFT, current_pages>>PAGE_TO_MB_SHIFT); - } - - return 1; -} - - static void balloon_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) { switch ( msg->subtype ) @@ -308,7 +300,8 @@ static void balloon_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) goto parse_error; { mem_request_t *req = (mem_request_t *)&msg->msg[0]; - req->status = balloon_try_target(req->target); + set_new_target(req->target); + req->status = 0; } break; default: @@ -323,20 +316,13 @@ static void balloon_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) ctrl_if_send_response(msg); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -typedef size_t count_t; -#else -typedef u_long count_t; -#endif - -static int do_balloon_write(const char *buffer, count_t count) +static int balloon_write(struct file *file, const char *buffer, + size_t count, loff_t *offp) { char memstring[64], *endchar; int len, i; - unsigned long target; - unsigned long long targetbytes; + unsigned long long target_bytes; - /* Only admin can play with the balloon :) */ if ( !capable(CAP_SYS_ADMIN) ) return -EPERM; @@ -344,8 +330,10 @@ static int do_balloon_write(const char *buffer, count_t count) return -EFBIG; len = strnlen_user(buffer, count); - if ( len == 0 ) return -EBADMSG; - if ( len == 1 ) return 1; /* input starts with a NUL char */ + if ( len == 0 ) + return -EBADMSG; + if ( len == 1 ) + goto out; /* input starts with a NUL char */ if ( strncpy_from_user(memstring, buffer, len) < 0 ) return -EFAULT; @@ -356,24 +344,10 @@ static int do_balloon_write(const char *buffer, count_t count) if ( i == 0 ) return -EBADMSG; - targetbytes = memparse(memstring,&endchar); - target = targetbytes >> PAGE_SHIFT; - - i = balloon_try_target(target); - - if ( i <= 0 ) return i; - - return len; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static int balloon_write(struct file *file, const char *buffer, - size_t count, loff_t *offp) -{ - int len = do_balloon_write(buffer, count); - - if ( len <= 0 ) return len; + target_bytes = memparse(memstring,&endchar); + set_new_target(target_bytes >> PAGE_SHIFT); + out: *offp += len; return len; } @@ -381,18 +355,44 @@ static int balloon_write(struct file *file, const char *buffer, static int balloon_read(struct file *filp, char *buffer, size_t count, loff_t *offp) { - static char priv_buf[32]; - char *priv_bufp = priv_buf; + char *priv_buf; int len; - len = sprintf(priv_buf,"%lu\n",current_pages<count) len = count; - if (len<0) len = 0; + if ( len > count) + len = count; + if ( len < 0 ) + len = 0; - if ( copy_to_user(buffer, priv_bufp, len) != 0 ) - return -EFAULT; + if ( len != 0 ) + (void)copy_to_user(buffer, &priv_buf[*offp], len); + + free_page((unsigned long)priv_buf); *offp += len; return len; @@ -403,30 +403,6 @@ static struct file_operations balloon_fops = { .write = balloon_write }; -#else - -static int balloon_write(struct file *file, const char *buffer, - u_long count, void *data) -{ - return do_balloon_write(buffer, count); -} - -static int balloon_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len; - len = sprintf(page,"%lu\n",current_pages<count) len = count; - if (len<0) len = 0; - return len; -} - -#endif - static int __init balloon_init(void) { unsigned long pfn; @@ -435,20 +411,23 @@ static int __init balloon_init(void) IPRINTK("Initialising balloon driver.\n"); current_pages = min(xen_start_info.nr_pages, max_pfn); - if ( (balloon_pde = create_xen_proc_entry("memory_target", 0644)) == NULL ) + target_pages = current_pages; + balloon_low = 0; + balloon_high = 0; + driver_pages = 0UL; + hard_limit = ~0UL; + + init_timer(&balloon_timer); + balloon_timer.data = 0; + balloon_timer.function = balloon_alarm; + + if ( (balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL ) { - WPRINTK("Unable to create balloon driver proc entry!"); + WPRINTK("Unable to create /proc/xen/balloon.\n"); return -1; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - balloon_pde->owner = THIS_MODULE; - balloon_pde->nlink = 1; balloon_pde->proc_fops = &balloon_fops; -#else - balloon_pde->write_proc = balloon_write; - balloon_pde->read_proc = balloon_read; -#endif (void)ctrl_if_register_receiver(CMSG_MEM_REQUEST, balloon_ctrlif_rx, CALLBACK_IN_BLOCKING_CONTEXT); @@ -464,14 +443,29 @@ static int __init balloon_init(void) return 0; } -static void __exit balloon_cleanup(void) +__initcall(balloon_init); + +void balloon_update_driver_allowance(long delta) { - if ( balloon_pde != NULL ) - { - remove_xen_proc_entry("memory_target"); - balloon_pde = NULL; - } + unsigned long flags; + balloon_lock(flags); + driver_pages += delta; + balloon_unlock(flags); } -module_init(balloon_init); -module_exit(balloon_cleanup); +void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns) +{ + unsigned long flags; + + balloon_lock(flags); + if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, + mfn_list, nr_mfns, 0) != nr_mfns ) + BUG(); + current_pages -= nr_mfns; + balloon_unlock(flags); + + schedule_work(&balloon_worker); +} + +EXPORT_SYMBOL(balloon_update_driver_allowance); +EXPORT_SYMBOL(balloon_put_pages); diff --git a/linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c index 1e114bd556..41d947bacf 100644 --- a/linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6.9-xen-sparse/drivers/xen/netback/netback.c @@ -11,6 +11,7 @@ */ #include "common.h" +#include static void netif_page_release(struct page *page); static void netif_skb_release(struct sk_buff *skb); @@ -29,6 +30,8 @@ static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0); static void net_rx_action(unsigned long unused); static DECLARE_TASKLET(net_rx_tasklet, net_rx_action, 0); +static struct timer_list net_timer; + static struct sk_buff_head rx_queue; static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE*2]; static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE*3]; @@ -69,27 +72,20 @@ static unsigned long mfn_list[MAX_MFN_ALLOC]; static unsigned int alloc_index = 0; static spinlock_t mfn_lock = SPIN_LOCK_UNLOCKED; -static void __refresh_mfn_list(void) +static unsigned long alloc_mfn(void) { - int ret = HYPERVISOR_dom_mem_op(MEMOP_increase_reservation, - mfn_list, MAX_MFN_ALLOC, 0); - if ( unlikely(ret != MAX_MFN_ALLOC) ) - BUG(); - alloc_index = MAX_MFN_ALLOC; -} - -static unsigned long get_new_mfn(void) -{ - unsigned long mfn, flags; + unsigned long mfn = 0, flags; spin_lock_irqsave(&mfn_lock, flags); - if ( alloc_index == 0 ) - __refresh_mfn_list(); - mfn = mfn_list[--alloc_index]; + if ( unlikely(alloc_index == 0) ) + alloc_index = HYPERVISOR_dom_mem_op( + MEMOP_increase_reservation, mfn_list, MAX_MFN_ALLOC, 0); + if ( alloc_index != 0 ) + mfn = mfn_list[--alloc_index]; spin_unlock_irqrestore(&mfn_lock, flags); return mfn; } -static void dealloc_mfn(unsigned long mfn) +static void free_mfn(unsigned long mfn) { unsigned long flags; spin_lock_irqsave(&mfn_lock, flags); @@ -210,8 +206,16 @@ static void net_rx_action(unsigned long unused) netif = (netif_t *)skb->dev->priv; vdata = (unsigned long)skb->data; mdata = virt_to_machine(vdata); - new_mfn = get_new_mfn(); - + + /* Memory squeeze? Back off for an arbitrary while. */ + if ( (new_mfn = alloc_mfn()) == 0 ) + { + if ( net_ratelimit() ) + printk(KERN_WARNING "Memory squeeze in netback driver.\n"); + mod_timer(&net_timer, jiffies + HZ); + break; + } + /* * Set the new P2M table entry before reassigning the old data page. * Heed the comment in pgtable-2level.h:pte_page(). :-) @@ -280,7 +284,7 @@ static void net_rx_action(unsigned long unused) if ( unlikely(mcl[1].args[5] != 0) ) { DPRINTK("Failed MMU update transferring to DOM%u\n", netif->domid); - dealloc_mfn(mdata >> PAGE_SHIFT); + free_mfn(mdata >> PAGE_SHIFT); status = NETIF_RSP_ERROR; } @@ -307,7 +311,7 @@ static void net_rx_action(unsigned long unused) } /* More work to do? */ - if ( !skb_queue_empty(&rx_queue) ) + if ( !skb_queue_empty(&rx_queue) && !timer_pending(&net_timer) ) tasklet_schedule(&net_rx_tasklet); #if 0 else @@ -315,6 +319,11 @@ static void net_rx_action(unsigned long unused) #endif } +static void net_alarm(unsigned long unused) +{ + tasklet_schedule(&net_rx_tasklet); +} + struct net_device_stats *netif_be_get_stats(struct net_device *dev) { netif_t *netif = dev->priv; @@ -781,9 +790,16 @@ static int __init netback_init(void) printk("Initialising Xen netif backend\n"); + /* We can increase reservation by this much in net_rx_action(). */ + balloon_update_driver_allowance(NETIF_RX_RING_SIZE); + skb_queue_head_init(&rx_queue); skb_queue_head_init(&tx_queue); + init_timer(&net_timer); + net_timer.data = 0; + net_timer.function = net_alarm; + netif_interface_init(); if ( (mmap_vstart = allocate_empty_lowmem_region(MAX_PENDING_REQS)) == 0 ) diff --git a/linux-2.6.9-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6.9-xen-sparse/drivers/xen/netfront/netfront.c index dd1b2492ff..d2b96cbe0f 100644 --- a/linux-2.6.9-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6.9-xen-sparse/drivers/xen/netfront/netfront.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -409,6 +410,9 @@ static void network_alloc_rx_buffers(struct net_device *dev) rx_mcl[i].args[3] = 0; rx_mcl[i].args[4] = DOMID_SELF; + /* Tell the ballon driver what is going on. */ + balloon_update_driver_allowance(i); + /* Zap PTEs and give away pages in one big multicall. */ (void)HYPERVISOR_multicall(rx_mcl, i+1); @@ -557,14 +561,15 @@ static int netif_poll(struct net_device *dev, int *pbudget) /* * An error here is very odd. Usually indicates a backend bug, * low-memory condition, or that we didn't have reservation headroom. - * Whatever - print an error and queue the id again straight away. */ if ( unlikely(rx->status <= 0) ) { - printk(KERN_ALERT "bad buffer on RX ring!(%d)\n", rx->status); + if ( net_ratelimit() ) + printk(KERN_WARNING "Bad rx buffer (memory squeeze?).\n"); np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].req.id = rx->id; wmb(); np->rx->req_prod++; + work_done--; continue; } @@ -595,6 +600,9 @@ static int netif_poll(struct net_device *dev, int *pbudget) __skb_queue_tail(&rxq, skb); } + /* Some pages are no longer absent... */ + balloon_update_driver_allowance(-work_done); + /* Do all the remapping work, and M->P updates, in one big hypercall. */ if ( likely((mcl - rx_mcl) != 0) ) { diff --git a/linux-2.6.9-xen-sparse/drivers/xen/privcmd/privcmd.c b/linux-2.6.9-xen-sparse/drivers/xen/privcmd/privcmd.c index 4316d8e2f9..98e7e92ff4 100644 --- a/linux-2.6.9-xen-sparse/drivers/xen/privcmd/privcmd.c +++ b/linux-2.6.9-xen-sparse/drivers/xen/privcmd/privcmd.c @@ -7,7 +7,6 @@ */ #include -#include #include #include #include @@ -213,23 +212,9 @@ static int __init privcmd_init(void) privcmd_intf = create_xen_proc_entry("privcmd", 0400); if ( privcmd_intf != NULL ) - { - privcmd_intf->owner = THIS_MODULE; - privcmd_intf->nlink = 1; - privcmd_intf->proc_fops = &privcmd_file_ops; - } + privcmd_intf->proc_fops = &privcmd_file_ops; return 0; } - -static void __exit privcmd_cleanup(void) -{ - if ( privcmd_intf == NULL ) return; - remove_xen_proc_entry("privcmd"); - privcmd_intf = NULL; -} - - -module_init(privcmd_init); -module_exit(privcmd_cleanup); +__initcall(privcmd_init); diff --git a/linux-2.6.9-xen-sparse/include/asm-xen/balloon.h b/linux-2.6.9-xen-sparse/include/asm-xen/balloon.h new file mode 100644 index 0000000000..80ef4acefc --- /dev/null +++ b/linux-2.6.9-xen-sparse/include/asm-xen/balloon.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * balloon.h + * + * Xen balloon driver - enables returning/claiming memory to/from Xen. + * + * Copyright (c) 2003, B Dragovic + * Copyright (c) 2003-2004, M Williamson, K Fraser + * + * This file may be distributed separately from the Linux kernel, or + * incorporated into other software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef __ASM_BALLOON_H__ +#define __ASM_BALLOON_H__ + +/* + * Inform the balloon driver that it should allow some slop for device-driver + * memory activities. + */ +extern void balloon_update_driver_allowance(long delta); + +/* Give up unmapped pages to the balloon driver. */ +extern void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns); + +/* + * Prevent the balloon driver from changing the memory reservation during + * a driver critical region. + */ +extern spinlock_t balloon_lock; +#define balloon_lock(__flags) spin_lock_irqsave(&balloon_lock, __flags) +#define balloon_unlock(__flags) spin_unlock_irqrestore(&balloon_lock, __flags) + +#endif /* __ASM_BALLOON_H__ */ diff --git a/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h b/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h index c82469bc00..ef755a4e7d 100644 --- a/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h +++ b/linux-2.6.9-xen-sparse/include/asm-xen/hypervisor.h @@ -102,8 +102,6 @@ void MULTICALL_flush_page_update_queue(void); #ifdef CONFIG_XEN_PHYSDEV_ACCESS /* Allocate a contiguous empty region of low memory. Return virtual start. */ unsigned long allocate_empty_lowmem_region(unsigned long pages); -/* Deallocate a contiguous region of low memory. Return it to the allocator. */ -void deallocate_lowmem_region(unsigned long vstart, unsigned long pages); #endif /* From b75183d3368f528e118cd983e96f45bfd3dcf776 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Thu, 2 Dec 2004 16:40:33 +0000 Subject: [PATCH 15/18] bitkeeper revision 1.1159.187.53 (41af4581GTHH1sJIbO5TqzuAB2ifOg) Fix 2.4 build. Minor mods to the balloon driver. --- linux-2.4.28-xen-sparse/arch/xen/drivers/balloon/Makefile | 1 + linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c | 7 ++----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/linux-2.4.28-xen-sparse/arch/xen/drivers/balloon/Makefile b/linux-2.4.28-xen-sparse/arch/xen/drivers/balloon/Makefile index 9fb2227978..c97a95a522 100644 --- a/linux-2.4.28-xen-sparse/arch/xen/drivers/balloon/Makefile +++ b/linux-2.4.28-xen-sparse/arch/xen/drivers/balloon/Makefile @@ -1,3 +1,4 @@ O_TARGET := drv.o +export-objs := balloon.o obj-y := balloon.o include $(TOPDIR)/Rules.make diff --git a/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c b/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c index 772d52b1ec..f90d8728fd 100644 --- a/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c +++ b/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c @@ -50,8 +50,6 @@ #include #include -#define MIN_TARGET ((16 << 20) >> PAGE_SHIFT) /* 16MB */ - static struct proc_dir_entry *balloon_pde; static DECLARE_MUTEX(balloon_mutex); @@ -93,6 +91,7 @@ static struct timer_list balloon_timer; #define LIST_TO_PAGE(l) ( list_entry(l, struct page, list) ) #define UNLIST_PAGE(p) ( list_del(&p->list) ) #define pte_offset_kernel pte_offset +#define subsys_initcall(_fn) __initcall(fn) #endif #define IPRINTK(fmt, args...) \ @@ -159,8 +158,6 @@ static unsigned long current_target(void) unsigned long target = min(target_pages, hard_limit); if ( target > (current_pages + balloon_low + balloon_high) ) target = current_pages + balloon_low + balloon_high; - if ( target < MIN_TARGET ) - target = MIN_TARGET; return target; } @@ -443,7 +440,7 @@ static int __init balloon_init(void) return 0; } -__initcall(balloon_init); +subsys_initcall(balloon_init); void balloon_update_driver_allowance(long delta) { From 0e5be44a108cd4563ebf6856bea60483e2668951 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Thu, 2 Dec 2004 17:03:09 +0000 Subject: [PATCH 16/18] bitkeeper revision 1.1159.187.54 (41af4acdZ4YHAyUW9HeJOhMYWMiB1g) More ballon driver changes/fixes. --- .../drivers/xen/balloon/balloon.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c b/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c index f90d8728fd..443a0240d6 100644 --- a/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c +++ b/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c @@ -161,6 +161,12 @@ static unsigned long current_target(void) return target; } +/* + * We avoid multiple worker processes conflicting via the balloon mutex. + * We may of course race updates of the target counts (which are protected + * by the balloon lock), or with changes to the Xen hard limit, but we will + * recover from these in time. + */ static void balloon_process(void *unused) { unsigned long *mfn_list, pfn, i, flags; @@ -283,9 +289,10 @@ static void balloon_process(void *unused) /* Resets the Xen limit, sets new target, and kicks off processing. */ static void set_new_target(unsigned long target) { + /* No need for lock. Not read-modify-write updates. */ hard_limit = ~0UL; target_pages = target; - balloon_process(NULL); + schedule_work(&balloon_worker); } static void balloon_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) @@ -426,8 +433,7 @@ static int __init balloon_init(void) balloon_pde->proc_fops = &balloon_fops; - (void)ctrl_if_register_receiver(CMSG_MEM_REQUEST, balloon_ctrlif_rx, - CALLBACK_IN_BLOCKING_CONTEXT); + (void)ctrl_if_register_receiver(CMSG_MEM_REQUEST, balloon_ctrlif_rx, 0); /* Initialise the balloon with excess memory space. */ for ( pfn = xen_start_info.nr_pages; pfn < max_pfn; pfn++ ) @@ -446,7 +452,7 @@ void balloon_update_driver_allowance(long delta) { unsigned long flags; balloon_lock(flags); - driver_pages += delta; + driver_pages += delta; /* non-atomic update */ balloon_unlock(flags); } @@ -458,7 +464,7 @@ void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns) if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, mfn_list, nr_mfns, 0) != nr_mfns ) BUG(); - current_pages -= nr_mfns; + current_pages -= nr_mfns; /* non-atomic update */ balloon_unlock(flags); schedule_work(&balloon_worker); From dbff0b77ad0ea0d7694d8119618b0c4f1404eb61 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Thu, 2 Dec 2004 20:56:17 +0000 Subject: [PATCH 17/18] bitkeeper revision 1.1159.187.55 (41af81710ePtgtFPsGTTUHYqD1qviA) Simpler balloon proc entry. --- .../drivers/xen/balloon/balloon.c | 66 +++++-------------- 1 file changed, 17 insertions(+), 49 deletions(-) diff --git a/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c b/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c index 443a0240d6..f914998bfe 100644 --- a/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c +++ b/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c @@ -320,55 +320,38 @@ static void balloon_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) ctrl_if_send_response(msg); } -static int balloon_write(struct file *file, const char *buffer, - size_t count, loff_t *offp) +static int balloon_write(struct file *file, const char __user *buffer, + unsigned long count, void *data) { char memstring[64], *endchar; - int len, i; unsigned long long target_bytes; if ( !capable(CAP_SYS_ADMIN) ) return -EPERM; + if ( count <= 1 ) + return -EBADMSG; /* runt */ if ( count > sizeof(memstring) ) - return -EFBIG; + return -EFBIG; /* too long */ - len = strnlen_user(buffer, count); - if ( len == 0 ) - return -EBADMSG; - if ( len == 1 ) - goto out; /* input starts with a NUL char */ - if ( strncpy_from_user(memstring, buffer, len) < 0 ) + if ( copy_from_user(memstring, buffer, count) ) return -EFAULT; + memstring[sizeof(memstring)-1] = '\0'; - endchar = memstring; - for ( i = 0; i < len; ++i, ++endchar ) - if ( (memstring[i] < '0') || (memstring[i] > '9') ) - break; - if ( i == 0 ) - return -EBADMSG; - - target_bytes = memparse(memstring,&endchar); + target_bytes = memparse(memstring, &endchar); set_new_target(target_bytes >> PAGE_SHIFT); - out: - *offp += len; - return len; + return count; } -static int balloon_read(struct file *filp, char *buffer, - size_t count, loff_t *offp) +static int balloon_read(char *page, char **start, off_t off, + int count, int *eof, void *data) { - char *priv_buf; int len; - priv_buf = (char *)__get_free_page(GFP_KERNEL); - if ( priv_buf == NULL ) - return -ENOMEM; - #define K(_p) ((_p)<<(PAGE_SHIFT-10)) len = sprintf( - priv_buf, + page, "Current allocation: %8lu kB\n" "Target allocation: %8lu kB / %8lu kB (actual / requested)\n" "Unused heap space: %8lu kB / %8lu kB (low-mem / high-mem)\n" @@ -379,34 +362,18 @@ static int balloon_read(struct file *filp, char *buffer, if ( hard_limit != ~0UL ) len += sprintf( - priv_buf + len, + page + len, "%8lu kB (inc. %8lu kB driver headroom)\n", K(hard_limit), K(driver_pages)); else len += sprintf( - priv_buf + len, + page + len, " ??? kB\n"); - len -= *offp; - if ( len > count) - len = count; - if ( len < 0 ) - len = 0; - - if ( len != 0 ) - (void)copy_to_user(buffer, &priv_buf[*offp], len); - - free_page((unsigned long)priv_buf); - - *offp += len; + *eof = 1; return len; } -static struct file_operations balloon_fops = { - .read = balloon_read, - .write = balloon_write -}; - static int __init balloon_init(void) { unsigned long pfn; @@ -431,7 +398,8 @@ static int __init balloon_init(void) return -1; } - balloon_pde->proc_fops = &balloon_fops; + balloon_pde->read_proc = balloon_read; + balloon_pde->write_proc = balloon_write; (void)ctrl_if_register_receiver(CMSG_MEM_REQUEST, balloon_ctrlif_rx, 0); From fdea3f84ab2ad172334572350a016acca72039a7 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Thu, 2 Dec 2004 21:14:02 +0000 Subject: [PATCH 18/18] bitkeeper revision 1.1159.187.56 (41af859alAU2_flUOUDG6VyGkjJ8Kg) More balloon fixes. --- .../drivers/xen/balloon/balloon.c | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c b/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c index f914998bfe..ad951fa984 100644 --- a/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c +++ b/linux-2.6.9-xen-sparse/drivers/xen/balloon/balloon.c @@ -91,7 +91,7 @@ static struct timer_list balloon_timer; #define LIST_TO_PAGE(l) ( list_entry(l, struct page, list) ) #define UNLIST_PAGE(p) ( list_del(&p->list) ) #define pte_offset_kernel pte_offset -#define subsys_initcall(_fn) __initcall(fn) +#define subsys_initcall(_fn) __initcall(_fn) #endif #define IPRINTK(fmt, args...) \ @@ -300,14 +300,14 @@ static void balloon_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) switch ( msg->subtype ) { case CMSG_MEM_REQUEST_SET: + { + mem_request_t *req = (mem_request_t *)&msg->msg[0]; if ( msg->length != sizeof(mem_request_t) ) goto parse_error; - { - mem_request_t *req = (mem_request_t *)&msg->msg[0]; - set_new_target(req->target); - req->status = 0; - } - break; + set_new_target(req->target); + req->status = 0; + } + break; default: goto parse_error; } @@ -353,12 +353,11 @@ static int balloon_read(char *page, char **start, off_t off, len = sprintf( page, "Current allocation: %8lu kB\n" - "Target allocation: %8lu kB / %8lu kB (actual / requested)\n" - "Unused heap space: %8lu kB / %8lu kB (low-mem / high-mem)\n" + "Requested target: %8lu kB\n" + "Low-mem balloon: %8lu kB\n" + "High-mem balloon: %8lu kB\n" "Xen hard limit: ", - K(current_pages), - K(current_target()), K(target_pages), - K(balloon_low), K(balloon_high)); + K(current_pages), K(target_pages), K(balloon_low), K(balloon_high)); if ( hard_limit != ~0UL ) len += sprintf(