Browse Source

Initial import

Suren A. Chilingaryan 8 years ago
commit
f6ff38753c
7 changed files with 295 additions and 0 deletions
  1. 7 0
      .bzrignore
  2. 43 0
      Makefile
  3. 19 0
      debug.h
  4. 45 0
      dev.c
  5. 15 0
      dev.h
  6. 157 0
      mod.c
  7. 9 0
      mod.h

+ 7 - 0
.bzrignore

@@ -0,0 +1,7 @@
+*.ko
+*.mod.c
+Module.symvers
+.*.cmd
+.*.d
+.tmp_versions
+modules.order

+ 43 - 0
Makefile

@@ -0,0 +1,43 @@
+obj-m := kmm.o
+kmm-objs := mod.o dev.o
+
+KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+INSTALLDIR ?= /lib/modules/$(shell uname -r)/kernel/extra
+PWD := $(shell pwd)
+
+EXTRA_CFLAGS += -I$(M)/..
+
+default:
+	@KERNEL_GCC_VERSION=`cat /proc/version | head -n1 | cut -d " " -f 7` ;\
+	GCC_VERSION=`$(CC) --version | head -n 1 | tr ' ' '\n' | grep -e "[0-9]\+\.[0-9]" | tail -n 1` ;\
+	if [ $$KERNEL_GCC_VERSION != $$GCC_VERSION ]; then \
+	    echo "Kernel is compiled with gcc $$KERNEL_GCC_VERSION, but you are now using $$GCC_VERSION" ;\
+	    GCC_MAJOR=`echo $$KERNEL_GCC_VERSION | cut -d "." -f 1-2` ;\
+	    newCC=gcc-$$GCC_MAJOR ;\
+	    CC=`which $$newCC 2>/dev/null` ;\
+	    if [ $$? -ne 0 ]; then \
+		echo "No compiler of $$GCC_MAJOR series is installed" ;\
+		exit 1 ;\
+	    fi ;\
+	    GCC_VERSION=`$$CC --version | head -n 1 | tr ' ' '\n' | grep -e "[0-9]\+\.[0-9]" | head -n 1` ;\
+	    if [ $$KERNEL_GCC_VERSION != $$GCC_VERSION ]; then \
+		echo "The $$GCC_VERSION of $$GCC_MAJOR series is installed" ;\
+		exit 1 ;\
+	    fi ;\
+	    echo "Setting CC to $$newCC" ;\
+	else \
+	    CC=$(CC) ;\
+	fi ;\
+	$(MAKE) $(CFLAGS) -C $(KERNELDIR) M=$(PWD) CC=$$CC modules
+
+install:
+	@mkdir -p $(INSTALLDIR)
+	@echo "INSTALL $(INSTALLDIR)/pciDriver.ko"
+	@install -m 755 pciDriver.ko $(INSTALLDIR)
+
+uninstall:
+	@echo "UNINSTALL $(INSTALLDIR)/pciDriver.ko"
+	@rm -f $(INSTALLDIR)/pciDriver.ko
+
+clean:
+	rm -rf *.o *.ko *.mod.c .*.o.cmd .*.o.tmp .*.ko.cmd  .*.o *.symvers modules.order .tmp_versions

+ 19 - 0
debug.h

@@ -0,0 +1,19 @@
+#ifndef _KMM_DEBUG_H
+#define _KMM_DEBUG_H
+
+#ifdef DEBUG
+ #define mod_info( args... ) \
+    do { printk( KERN_INFO "%s - %s : ", MODNAME , __FUNCTION__ );\
+    printk( args ); } while(0)
+ #define mod_info_dbg( args... ) \
+    do { printk( KERN_INFO "%s - %s : ", MODNAME , __FUNCTION__ );\
+    printk( args ); } while(0)
+#else
+ #define mod_info( args... ) \
+    do { printk( KERN_INFO "%s: ", MODNAME );\
+    printk( args ); } while(0)
+ #define mod_info_dbg( args... ) 
+#endif
+
+
+#endif /* _KMM_DEBUG_H */

+ 45 - 0
dev.c

@@ -0,0 +1,45 @@
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+
+
+#include "mod.h"
+#include "dev.h"
+#include "debug.h"
+
+int kmm_device_open(struct inode *inode, struct file *filp)
+{
+    kmm_dev_t *dev;
+
+    dev = container_of( inode->i_cdev, kmm_dev_t, cdev);
+    filp->private_data = dev;
+    
+    mod_info("open\n");
+
+    return 0;
+}
+
+int kmm_device_release(struct inode *inode, struct file *filp)
+{
+    mod_info("close\n");
+
+    return 0;
+}
+
+
+static struct file_operations kmm_fops = {
+    .owner = THIS_MODULE,
+//	.unlocked_ioctl = pcidriver_ioctl,
+//	.mmap = pcidriver_mmap,
+    .open = kmm_device_open,
+    .release = kmm_device_release,
+};
+
+const struct file_operations *kmm_get_fops(void)
+{
+    return &kmm_fops;
+}

+ 15 - 0
dev.h

@@ -0,0 +1,15 @@
+#ifndef _KMM_DEV_H
+#define _KMM_DEV_H
+
+#include <linux/fs.h>
+
+typedef struct {
+    dev_t devno;
+    struct device *dev;					/**< Class device */
+
+    struct cdev cdev;
+} kmm_dev_t;
+
+const struct file_operations *kmm_get_fops(void);
+
+#endif /* _KMM_BASE_H */

+ 157 - 0
mod.c

@@ -0,0 +1,157 @@
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+
+
+#include "mod.h"
+#include "dev.h"
+#include "debug.h"
+
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Suren A. Chilingaryan <csa@suren.me>");
+MODULE_DESCRIPTION("Kernel Memory Manager - a module to manipulate kernel memory");
+MODULE_VERSION("0.0.1");
+
+int kmm_minors = KMM_MINORS;
+
+module_param(kmm_minors, int, S_IRUGO);
+
+
+static dev_t kmm_devno;			/**< major number */
+static kmm_dev_t **kmm_devs = NULL;	/**< per-device context */
+static spinlock_t kmm_devs_lock;	/**< lock protecting creation/destruction of devices */
+static struct class *kmm_class;		/**< device class */
+
+
+static void kmm_module_cleanup(void)
+{
+    int i;
+
+    if (kmm_devs) {
+	for (i = 0; i < kmm_minors; i++) {
+	    if (kmm_devs[i]) {
+		if (kmm_devs[i]->dev)
+		    device_destroy(kmm_class, kmm_devs[i]->devno);
+		cdev_del(&kmm_devs[i]->cdev);
+		kfree(kmm_devs[i]);
+	    }
+	}
+	kfree(kmm_devs);
+    }
+
+
+    if (kmm_class)
+    	class_destroy(kmm_class);
+
+    unregister_chrdev_region(kmm_devno, kmm_minors);
+}
+
+static int kmm_module_setup_cdev(void)
+{
+    int i;
+    int err = 0;
+    dev_t devno;
+    kmm_dev_t *dev;
+
+    dev = kmalloc(sizeof(kmm_dev_t), GFP_KERNEL);
+    if (!dev) {
+	mod_info("Couldn't allocate memory. Device is not created.\n");
+	return -ENOMEM;
+    }
+
+    cdev_init(&dev->cdev, kmm_get_fops());
+    dev->cdev.owner = THIS_MODULE;
+    dev->cdev.ops = kmm_get_fops();
+
+    spin_lock(&kmm_devs_lock);
+    for (i = 0; i < kmm_minors; i++) {
+	if (!kmm_devs[i])
+	    break;
+    }
+
+    if (i == kmm_minors) {
+	mod_info("No free minor numbers left");
+	err = -EBUSY;
+	goto fail;
+    }
+
+    devno = MKDEV(MAJOR(kmm_devno), MINOR(kmm_devno) + i);
+    dev->devno = devno;
+
+    err = cdev_add(&dev->cdev, devno, 1);
+    if (err) {
+	mod_info("Error %d adding device kmm%d", err, i);
+	goto fail;
+    }
+
+    dev->dev = device_create(kmm_class, NULL, devno, dev, KMM_NODE_FMT, MINOR(kmm_devno) + i);
+    if (!dev->dev) {
+	mod_info("Error creating /dev/%s%d\n", KMM_NODE, MINOR(kmm_devno) + i);
+	goto fail;
+    }
+    dev_set_drvdata(dev->dev, dev);
+
+    kmm_devs[i] = dev;
+    spin_unlock(&kmm_devs_lock);
+
+    mod_info("Device /dev/%s%d added\n", KMM_NODE, MINOR(kmm_devno) + i);
+
+    return 0;
+
+fail:
+    spin_unlock(&kmm_devs_lock);
+    kfree(dev);
+    return err;
+}
+
+static int __init kmm_module_init(void)
+{
+    int err;
+
+    spin_lock_init(&kmm_devs_lock);
+
+    if ((err = alloc_chrdev_region(&kmm_devno, 0, kmm_minors, KMM_NODE))) {
+	mod_info("Couldn't allocate chrdev region. Module not loaded.\n");
+	goto alloc_chrdev_fail;
+    }
+
+    kmm_class = class_create(THIS_MODULE, KMM_NODE);
+    if (IS_ERR(kmm_class)) {
+	mod_info("No sysfs support. Module not loaded.\n");
+	goto fail;
+    }
+
+    kmm_devs = kmalloc(kmm_minors * sizeof(kmm_dev_t*), GFP_KERNEL);
+    if (!kmm_devs) {
+	mod_info("Couldn't allocate memory. Module not loaded.\n");
+	err = -ENOMEM;
+    }
+    memset(kmm_devs, 0, kmm_minors * sizeof(kmm_dev_t*));
+
+    mod_info("Major %d allocated to node '%s'\n", MAJOR(kmm_devno), KMM_NODE);
+
+    err = kmm_module_setup_cdev();
+    if (err) goto fail;
+
+
+    return 0;
+
+fail:
+    kmm_module_cleanup();
+alloc_chrdev_fail:
+    return err;
+}
+
+
+static void __exit kmm_module_exit(void)
+{
+    kmm_module_cleanup();
+}
+
+module_init(kmm_module_init);
+module_exit(kmm_module_exit);

+ 9 - 0
mod.h

@@ -0,0 +1,9 @@
+#ifndef _KMM_MODE_H
+#define _KMM_MODE_H
+
+#define MODNAME		"kmm"
+#define KMM_NODE	"kmm"
+#define KMM_NODE_FMT	"kmm%i"
+#define KMM_MINORS 	16
+
+#endif /* _KMM_MODE_H */