diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-11-29 18:51:18 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-11-29 18:51:18 +0000 |
commit | 9e34879530f2d1dad18dcbd62ed56a673e6947e3 (patch) | |
tree | d7001d72f86a39df19660b758b649cddd61ec198 | |
parent | 6098b15ac3f7c9435021a2c10fe611b2520b30c0 (diff) | |
parent | cfb60f4ea0474627c26647f300fef046b162ef76 (diff) | |
download | xen-9e34879530f2d1dad18dcbd62ed56a673e6947e3.tar.gz xen-9e34879530f2d1dad18dcbd62ed56a673e6947e3.tar.bz2 xen-9e34879530f2d1dad18dcbd62ed56a673e6947e3.zip |
bitkeeper revision 1.1159.187.39 (41ab6fa6Y09a8uLTIgCHmRV5IVqoRA)
Merge scramble.cl.cam.ac.uk:/auto/groups/xeno/BK/xen-2.0-testing.bk
into scramble.cl.cam.ac.uk:/local/scratch/kaf24/xen-2.0-testing.bk
-rw-r--r-- | .rootkeys | 1 | ||||
-rw-r--r-- | linux-2.6.9-xen-sparse/arch/xen/i386/mm/ioremap.c | 351 | ||||
-rw-r--r-- | linux-2.6.9-xen-sparse/arch/xen/kernel/Makefile | 2 | ||||
-rw-r--r-- | linux-2.6.9-xen-sparse/arch/xen/kernel/devmem.c | 158 | ||||
-rw-r--r-- | linux-2.6.9-xen-sparse/drivers/char/mem.c | 25 | ||||
-rw-r--r-- | linux-2.6.9-xen-sparse/include/asm-xen/asm-i386/io.h | 3 |
6 files changed, 316 insertions, 224 deletions
@@ -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 <asm/cacheflush.h> #include <asm/tlbflush.h> #include <asm/pgtable.h> +#include <asm/pgalloc.h> #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; - - 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)); + unsigned long end; + + 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)); } -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; - - 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; + unsigned long end; + + 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; - - 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++; - - } while (address && (address < end)); - spin_unlock(&mm->page_table_lock); - flush_tlb_all(); - return 0; + pgd_t * dir; + unsigned long end = address + size; + + 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); + 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; - - 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; - - 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; + 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]; + + 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); - - machine_addr += PAGE_SIZE; - address += PAGE_SIZE; - v++; - } - - 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; + 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; + } + + flush_tlb_all(); + + 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 <cananian@alumni.princeton.edu> + * Shared /dev/zero mmaping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com> + */ + +#include <linux/config.h> +#include <linux/mm.h> +#include <linux/miscdevice.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <linux/mman.h> +#include <linux/random.h> +#include <linux/init.h> +#include <linux/raw.h> +#include <linux/tty.h> +#include <linux/capability.h> +#include <linux/smp_lock.h> +#include <linux/devfs_fs_kernel.h> +#include <linux/ptrace.h> +#include <linux/device.h> +#include <asm/pgalloc.h> +#include <asm/uaccess.h> +#include <asm/io.h> + +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 <asm/uaccess.h> #include <asm/io.h> -#include <asm/pgalloc.h> #ifdef CONFIG_IA64 # include <linux/efi.h> @@ -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 |