|
kusano |
2b45e8 |
/*********************************************************************/
|
|
kusano |
2b45e8 |
/* Copyright 2009, 2010 The University of Texas at Austin. */
|
|
kusano |
2b45e8 |
/* All rights reserved. */
|
|
kusano |
2b45e8 |
/* */
|
|
kusano |
2b45e8 |
/* Redistribution and use in source and binary forms, with or */
|
|
kusano |
2b45e8 |
/* without modification, are permitted provided that the following */
|
|
kusano |
2b45e8 |
/* conditions are met: */
|
|
kusano |
2b45e8 |
/* */
|
|
kusano |
2b45e8 |
/* 1. Redistributions of source code must retain the above */
|
|
kusano |
2b45e8 |
/* copyright notice, this list of conditions and the following */
|
|
kusano |
2b45e8 |
/* disclaimer. */
|
|
kusano |
2b45e8 |
/* */
|
|
kusano |
2b45e8 |
/* 2. Redistributions in binary form must reproduce the above */
|
|
kusano |
2b45e8 |
/* copyright notice, this list of conditions and the following */
|
|
kusano |
2b45e8 |
/* disclaimer in the documentation and/or other materials */
|
|
kusano |
2b45e8 |
/* provided with the distribution. */
|
|
kusano |
2b45e8 |
/* */
|
|
kusano |
2b45e8 |
/* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF TEXAS AT */
|
|
kusano |
2b45e8 |
/* AUSTIN ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, */
|
|
kusano |
2b45e8 |
/* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
|
|
kusano |
2b45e8 |
/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
|
|
kusano |
2b45e8 |
/* DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT */
|
|
kusano |
2b45e8 |
/* AUSTIN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */
|
|
kusano |
2b45e8 |
/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
|
|
kusano |
2b45e8 |
/* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE */
|
|
kusano |
2b45e8 |
/* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR */
|
|
kusano |
2b45e8 |
/* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */
|
|
kusano |
2b45e8 |
/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
|
|
kusano |
2b45e8 |
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT */
|
|
kusano |
2b45e8 |
/* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
|
|
kusano |
2b45e8 |
/* POSSIBILITY OF SUCH DAMAGE. */
|
|
kusano |
2b45e8 |
/* */
|
|
kusano |
2b45e8 |
/* The views and conclusions contained in the software and */
|
|
kusano |
2b45e8 |
/* documentation are those of the authors and should not be */
|
|
kusano |
2b45e8 |
/* interpreted as representing official policies, either expressed */
|
|
kusano |
2b45e8 |
/* or implied, of The University of Texas at Austin. */
|
|
kusano |
2b45e8 |
/*********************************************************************/
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
#include <linux version.h=""></linux>
|
|
kusano |
2b45e8 |
#include <linux module.h=""></linux>
|
|
kusano |
2b45e8 |
#include <linux sched.h=""></linux>
|
|
kusano |
2b45e8 |
#include <asm pgtable.h=""></asm>
|
|
kusano |
2b45e8 |
#include <linux init.h=""></linux>
|
|
kusano |
2b45e8 |
#include <linux fs.h=""></linux>
|
|
kusano |
2b45e8 |
#include <linux cdev.h=""></linux>
|
|
kusano |
2b45e8 |
#include <linux spinlock.h=""></linux>
|
|
kusano |
2b45e8 |
#include <linux mm.h=""></linux>
|
|
kusano |
2b45e8 |
#ifdef CONFIG_BIGPHYS_AREA
|
|
kusano |
2b45e8 |
#include <linux bigphysarea.h=""></linux>
|
|
kusano |
2b45e8 |
#endif
|
|
kusano |
2b45e8 |
#include <asm current.h=""></asm>
|
|
kusano |
2b45e8 |
#ifdef MODVERSIONS
|
|
kusano |
2b45e8 |
#include <linux modversions.h=""></linux>
|
|
kusano |
2b45e8 |
#endif
|
|
kusano |
2b45e8 |
#include <asm io.h=""></asm>
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
typedef struct {
|
|
kusano |
2b45e8 |
pid_t pid;
|
|
kusano |
2b45e8 |
#ifndef CONFIG_BIGPHYS_AREA
|
|
kusano |
2b45e8 |
long size;
|
|
kusano |
2b45e8 |
#endif
|
|
kusano |
2b45e8 |
caddr_t address;
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
} buffer_t;
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
#define MAX_BUFF_SIZE 1024
|
|
kusano |
2b45e8 |
#define MAX_LENGTH (4UL << 20)
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
static spinlock_t lock __attribute__((aligned(64)));
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
static buffer_t buffer[MAX_BUFF_SIZE];
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
static dev_t mapper_dev;
|
|
kusano |
2b45e8 |
static struct cdev mapper_cdev;
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
static int mapper_open (struct inode *inode, struct file *fp){ return 0;}
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
static int mapper_release(struct inode *inode, struct file *fp){
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
int pos;
|
|
kusano |
2b45e8 |
#ifndef CONFIG_BIGPHYS_AREA
|
|
kusano |
2b45e8 |
caddr_t addr;
|
|
kusano |
2b45e8 |
#endif
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
// printk("Releasing memory... %d\n", current -> tgid);
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
spin_lock(&lock);
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
for (pos = 0; pos < MAX_BUFF_SIZE; pos ++) {
|
|
kusano |
2b45e8 |
if (buffer[pos].pid == (pid_t) current -> tgid) {
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
#ifdef CONFIG_BIGPHYS_AREA
|
|
kusano |
2b45e8 |
bigphysarea_free_pages(buffer[pos].address);
|
|
kusano |
2b45e8 |
#else
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
for (addr = buffer[pos].address; addr < buffer[pos].address + buffer[pos].size; addr += PAGE_SIZE) {
|
|
kusano |
2b45e8 |
ClearPageReserved(virt_to_page(addr));
|
|
kusano |
2b45e8 |
}
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
kfree(buffer[pos].address);
|
|
kusano |
2b45e8 |
buffer[pos].size = 0;
|
|
kusano |
2b45e8 |
#endif
|
|
kusano |
2b45e8 |
buffer[pos].pid = 0;
|
|
kusano |
2b45e8 |
buffer[pos].address = 0;
|
|
kusano |
2b45e8 |
}
|
|
kusano |
2b45e8 |
}
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
spin_unlock(&lock);
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
return 0;
|
|
kusano |
2b45e8 |
}
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
int mapper_mapper(struct file *fp, struct vm_area_struct *vma){
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
int ret, pos;
|
|
kusano |
2b45e8 |
caddr_t alloc_addr;
|
|
kusano |
2b45e8 |
#ifndef CONFIG_BIGPHYS_AREA
|
|
kusano |
2b45e8 |
caddr_t addr;
|
|
kusano |
2b45e8 |
#endif
|
|
kusano |
2b45e8 |
long all_length, length, current_addr;
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
all_length = vma->vm_end - vma->vm_start;
|
|
kusano |
2b45e8 |
current_addr = vma -> vm_start;
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
spin_lock(&lock);
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
while (all_length > 0) {
|
|
kusano |
2b45e8 |
length = all_length;
|
|
kusano |
2b45e8 |
if (length > MAX_LENGTH) length = MAX_LENGTH;
|
|
kusano |
2b45e8 |
all_length -= MAX_LENGTH;
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
// printk("Allocating memory... %d\n", length);
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
pos = 0;
|
|
kusano |
2b45e8 |
while ((pos < MAX_BUFF_SIZE) && (buffer[pos].address != 0)) pos ++;
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
if (pos >= MAX_BUFF_SIZE) {
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
printk("Memory Allocator : too much memory allocation requested.\n");
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
spin_unlock(&lock);
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
return -EIO;
|
|
kusano |
2b45e8 |
}
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
#ifdef CONFIG_BIGPHYS_AREA
|
|
kusano |
2b45e8 |
alloc_addr = (caddr_t)bigphysarea_alloc_pages(length >> PAGE_SHIFT, 1, GFP_KERNEL);
|
|
kusano |
2b45e8 |
#else
|
|
kusano |
2b45e8 |
alloc_addr = (caddr_t)kmalloc(length, GFP_KERNEL);
|
|
kusano |
2b45e8 |
#endif
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
if (alloc_addr == (caddr_t)NULL) {
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
spin_unlock(&lock);
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
return -EIO;
|
|
kusano |
2b45e8 |
}
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
#ifndef CONFIG_BIGPHYS_AREA
|
|
kusano |
2b45e8 |
for (addr = alloc_addr; addr < alloc_addr + length; addr += PAGE_SIZE) {
|
|
kusano |
2b45e8 |
clear_page(addr);
|
|
kusano |
2b45e8 |
SetPageReserved(virt_to_page(addr));
|
|
kusano |
2b45e8 |
}
|
|
kusano |
2b45e8 |
#endif
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
if ((ret = remap_pfn_range(vma,
|
|
kusano |
2b45e8 |
current_addr,
|
|
kusano |
2b45e8 |
virt_to_phys((void *)alloc_addr) >> PAGE_SHIFT,
|
|
kusano |
2b45e8 |
length,
|
|
kusano |
2b45e8 |
PAGE_SHARED)) < 0) {
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
#ifdef CONFIG_BIGPHYS_AREA
|
|
kusano |
2b45e8 |
bigphysarea_free_pages((caddr_t)alloc_addr);
|
|
kusano |
2b45e8 |
#else
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
for (addr = alloc_addr; addr < alloc_addr + length; addr += PAGE_SIZE) ClearPageReserved(virt_to_page(addr));
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
kfree((caddr_t)alloc_addr);
|
|
kusano |
2b45e8 |
#endif
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
spin_unlock(&lock);
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
return ret;
|
|
kusano |
2b45e8 |
}
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
buffer[pos].pid = current -> tgid;
|
|
kusano |
2b45e8 |
buffer[pos].address = alloc_addr;
|
|
kusano |
2b45e8 |
#ifndef CONFIG_BIGPHYS_AREA
|
|
kusano |
2b45e8 |
buffer[pos].size = length;
|
|
kusano |
2b45e8 |
#endif
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
current_addr += length;
|
|
kusano |
2b45e8 |
}
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
spin_unlock(&lock);
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
return 0;
|
|
kusano |
2b45e8 |
}
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
static struct file_operations mapper_fops = {
|
|
kusano |
2b45e8 |
.open = mapper_open,
|
|
kusano |
2b45e8 |
.release = mapper_release,
|
|
kusano |
2b45e8 |
.mmap = mapper_mapper,
|
|
kusano |
2b45e8 |
.owner = THIS_MODULE,
|
|
kusano |
2b45e8 |
};
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
static int __init mapper_init(void){
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
int ret, i;
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
ret = alloc_chrdev_region(&mapper_dev, 0, 1, "mapper");
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
cdev_init(&mapper_cdev, &mapper_fops);
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
ret = cdev_add(&mapper_cdev, mapper_dev, 1);
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
spin_lock_init(&lock);
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
for (i = 0; i < MAX_BUFF_SIZE; i++) {
|
|
kusano |
2b45e8 |
buffer[i].pid = 0;
|
|
kusano |
2b45e8 |
#ifndef CONFIG_BIGPHYS_AREA
|
|
kusano |
2b45e8 |
buffer[i].size = 0;
|
|
kusano |
2b45e8 |
#endif
|
|
kusano |
2b45e8 |
buffer[i].address = 0;
|
|
kusano |
2b45e8 |
}
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
return ret;
|
|
kusano |
2b45e8 |
}
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
static void __exit mapper_exit(void){
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
int pos;
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
for (pos = 0; pos < MAX_BUFF_SIZE; pos ++) {
|
|
kusano |
2b45e8 |
if (buffer[pos].address != 0) {
|
|
kusano |
2b45e8 |
#ifdef CONFIG_BIGPHYS_AREA
|
|
kusano |
2b45e8 |
bigphysarea_free_pages(buffer[pos].address);
|
|
kusano |
2b45e8 |
#else
|
|
kusano |
2b45e8 |
kfree(buffer[pos].address);
|
|
kusano |
2b45e8 |
#endif
|
|
kusano |
2b45e8 |
}
|
|
kusano |
2b45e8 |
}
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
cdev_del(&mapper_cdev);
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
unregister_chrdev_region(mapper_dev, 1);
|
|
kusano |
2b45e8 |
}
|
|
kusano |
2b45e8 |
|
|
kusano |
2b45e8 |
module_init(mapper_init);
|
|
kusano |
2b45e8 |
module_exit(mapper_exit);
|
|
kusano |
2b45e8 |
MODULE_DESCRIPTION("BigPhysArea User Mapping Driver");
|
|
kusano |
2b45e8 |
MODULE_LICENSE("Unknown");
|