X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fmem.c;h=840a0afaeb1b2735e564c3a212cf45b52f6f0d49;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=477c63d6b0f3b8e98ca112f7d26be585c3ee4390;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 477c63d6b..840a0afae 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -26,15 +26,11 @@ #include #include -#include #ifdef CONFIG_IA64 # include #endif -#ifdef CONFIG_FB -extern void fbmem_init(void); -#endif #if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR) extern void tapechar_init(void); #endif @@ -62,6 +58,19 @@ static inline int uncached_access(struct file *file, unsigned long addr) test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) || test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability) ) && addr >= __pa(high_memory); +#elif defined(__x86_64__) + /* + * This is broken because it can generate memory type aliases, + * which can cause cache corruptions + * But it is only available for root and we have to be bug-to-bug + * compatible with i386. + */ + if (file->f_flags & O_SYNC) + return 1; + /* same behaviour as i386. PAT always set to cached and MTRRs control the + caching behaviour. + Hopefully a full PAT implementation will fix that soon. */ + return 0; #elif defined(CONFIG_IA64) /* * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases. @@ -74,7 +83,7 @@ static inline int uncached_access(struct file *file, unsigned long addr) * above the IO hole... Ah, and of course, XFree86 doesn't pass * O_SYNC when mapping us to tap IO space. Surprised ? */ - return !page_is_ram(addr); + return !page_is_ram(addr >> PAGE_SHIFT); #else /* * Accessing memory above the top the kernel knows about or through a file pointer @@ -103,7 +112,7 @@ static inline int valid_phys_addr_range(unsigned long addr, size_t *count) #endif static ssize_t do_write_mem(void *p, unsigned long realp, - const char * buf, size_t count, loff_t *ppos) + const char __user * buf, size_t count, loff_t *ppos) { ssize_t written; unsigned long copied; @@ -139,7 +148,7 @@ static ssize_t do_write_mem(void *p, unsigned long realp, * This funcion reads the *physical* memory. The f_pos points directly to the * memory location. */ -static ssize_t read_mem(struct file * file, char * buf, +static ssize_t read_mem(struct file * file, char __user * buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; @@ -171,7 +180,7 @@ static ssize_t read_mem(struct file * file, char * buf, return read; } -static ssize_t write_mem(struct file * file, const char * buf, +static ssize_t write_mem(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; @@ -183,26 +192,21 @@ static ssize_t write_mem(struct file * file, const char * buf, static int mmap_mem(struct file * file, struct vm_area_struct * vma) { +#ifdef pgprot_noncached unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; int uncached; uncached = uncached_access(file, offset); -#ifdef pgprot_noncached if (uncached) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); #endif - /* 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 (remap_page_range(vma, vma->vm_start, offset, vma->vm_end-vma->vm_start, - vma->vm_page_prot)) + /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ + if (remap_pfn_range(vma, + vma->vm_start, + vma->vm_pgoff, + vma->vm_end-vma->vm_start, + vma->vm_page_prot)) return -EAGAIN; return 0; } @@ -213,7 +217,7 @@ extern long vwrite(char *buf, char *addr, unsigned long count); /* * This function reads the *virtual* memory as seen by the kernel. */ -static ssize_t read_kmem(struct file *file, char *buf, +static ssize_t read_kmem(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; @@ -276,7 +280,7 @@ static ssize_t read_kmem(struct file *file, char *buf, /* * This function writes to the *virtual* memory as seen by the kernel. */ -static ssize_t write_kmem(struct file * file, const char * buf, +static ssize_t write_kmem(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; @@ -333,11 +337,11 @@ static ssize_t write_kmem(struct file * file, const char * buf, } #if defined(CONFIG_ISA) || !defined(__mc68000__) -static ssize_t read_port(struct file * file, char * buf, +static ssize_t read_port(struct file * file, char __user * buf, size_t count, loff_t *ppos) { unsigned long i = *ppos; - char *tmp = buf; + char __user *tmp = buf; if (verify_area(VERIFY_WRITE,buf,count)) return -EFAULT; @@ -351,11 +355,11 @@ static ssize_t read_port(struct file * file, char * buf, return tmp-buf; } -static ssize_t write_port(struct file * file, const char * buf, +static ssize_t write_port(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { unsigned long i = *ppos; - const char * tmp = buf; + const char __user * tmp = buf; if (verify_area(VERIFY_READ,buf,count)) return -EFAULT; @@ -372,13 +376,13 @@ static ssize_t write_port(struct file * file, const char * buf, } #endif -static ssize_t read_null(struct file * file, char * buf, +static ssize_t read_null(struct file * file, char __user * buf, size_t count, loff_t *ppos) { return 0; } -static ssize_t write_null(struct file * file, const char * buf, +static ssize_t write_null(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { return count; @@ -388,7 +392,7 @@ static ssize_t write_null(struct file * file, const char * buf, /* * For fun, we are using the MMU for this. */ -static inline size_t read_zero_pagealigned(char * buf, size_t size) +static inline size_t read_zero_pagealigned(char __user * buf, size_t size) { struct mm_struct *mm; struct vm_area_struct * vma; @@ -404,7 +408,7 @@ static inline size_t read_zero_pagealigned(char * buf, size_t size) if (vma->vm_start > addr || (vma->vm_flags & VM_WRITE) == 0) goto out_up; - if (vma->vm_flags & VM_SHARED) + if (vma->vm_flags & (VM_SHARED | VM_HUGETLB)) break; count = vma->vm_end - addr; if (count > size) @@ -438,7 +442,7 @@ out_up: return size; } -static ssize_t read_zero(struct file * file, char * buf, +static ssize_t read_zero(struct file * file, char __user * buf, size_t count, loff_t *ppos) { unsigned long left, unwritten, written = 0; @@ -510,7 +514,7 @@ static int mmap_zero(struct file * file, struct vm_area_struct * vma) } #endif /* CONFIG_MMU */ -static ssize_t write_full(struct file * file, const char * buf, +static ssize_t write_full(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { return -ENOSPC; @@ -615,7 +619,7 @@ static struct file_operations full_fops = { .write = write_full, }; -static ssize_t kmsg_write(struct file * file, const char * buf, +static ssize_t kmsg_write(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { char *tmp; @@ -718,9 +722,6 @@ static int __init chr_dev_init(void) S_IFCHR | devlist[i].mode, devlist[i].name); } -#if defined (CONFIG_FB) - fbmem_init(); -#endif return 0; }