mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
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. :-)
This commit is contained in:
1 parent
e0596851e8
commit
cfb60f4ea0
6 files changed
+306
-214
No files matched your search
@@ -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
|
||||
|
||||
@@ -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;
|
||||
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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||