diff --git a/work/tp2/Makefile b/work/tp2/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..21007509478e580d274df46a65949efd70803fcc
--- /dev/null
+++ b/work/tp2/Makefile
@@ -0,0 +1,9 @@
+KDIR=../../build/kvm/
+
+obj-m += pipebis.o
+PWD := $(CURDIR) 
+
+all: 
+	make -C $(KDIR) M=$(PWD) modules 
+clean: 
+	make -C $(KDIR) M=$(PWD) clean
diff --git a/work/tp2/modules.order b/work/tp2/modules.order
new file mode 100644
index 0000000000000000000000000000000000000000..fd9a996b3556a2bd158216de1636cfb0b0e20c1b
--- /dev/null
+++ b/work/tp2/modules.order
@@ -0,0 +1 @@
+/root/Desktop/asee/work/tp2/pipebis.o
diff --git a/work/tp2/pipebis.c b/work/tp2/pipebis.c
new file mode 100644
index 0000000000000000000000000000000000000000..43e97c4b49f356faa1ef3d0c9b5fa2e8d33ff438
--- /dev/null
+++ b/work/tp2/pipebis.c
@@ -0,0 +1,241 @@
+/* 
+ * pipebis.c: Creates a read-only char device that says how many times 
+ * you have read from the dev file 
+ */ 
+ 
+#include <linux/atomic.h> 
+#include <linux/cdev.h> 
+#include <linux/delay.h> 
+#include <linux/device.h> 
+#include <linux/fs.h> 
+#include <linux/init.h> 
+#include <linux/kernel.h> /* for sprintf() */ 
+#include <linux/module.h> 
+#include <linux/printk.h> 
+#include <linux/types.h> 
+#include <linux/uaccess.h> /* for get_user and put_user */ 
+#include <linux/version.h> 
+ 
+#include <asm/errno.h> 
+ 
+/*  Prototypes - this would normally go in a .h file */ 
+static int device_open(struct inode *, struct file *); 
+static int device_release(struct inode *, struct file *); 
+static ssize_t device_read(struct file *, char __user *, size_t, loff_t *); 
+static ssize_t device_write(struct file *, const char __user *, size_t, 
+                            loff_t *); 
+ 
+#define SUCCESS 0 
+#define DEVICE_NAME "asee_mod" /* Dev name as it appears in /proc/devices   */ 
+#define BUF_LEN 16 /* Max length of the message from the device */ 
+ 
+/* Global variables are declared as static, so are global within the file. */ 
+
+static char *msg; /* The msg the device will give when asked */ 
+
+static struct kobject *pipebis_module;
+
+static int asee_buf_count = 0;
+
+static int asee_buf_size = BUF_LEN;
+
+static ssize_t asee_buf_size_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+    return sprintf(buf, "%d\n", asee_buf_size);
+}
+
+static ssize_t asee_buf_size_store(struct kobject *kobj, struct kobj_attribute *attr, char *buf, size_t count)
+{
+    int old_size = asee_buf_size;
+    sscanf(buf, "%du", &asee_buf_size);
+    if (asee_buf_size <= asee_buf_count) {
+        asee_buf_size = old_size;
+        pr_err("New size for buffer should be less than current content in it");
+        return count;
+    }
+
+    char * second_message = kcalloc(asee_buf_size, sizeof(char), GFP_KERNEL);
+    for(int cpt = 0; cpt < old_size; cpt++) {
+        second_message[cpt] = msg[cpt];
+    }
+    kfree(msg);
+    msg = second_message;
+    // TODO: incresae buffer size
+    return count;
+}
+
+static struct kobj_attribute asee_buf_size_attribute = __ATTR(asee_buf_size, 0660, asee_buf_size_show, (void *)asee_buf_size_store);
+
+
+static ssize_t asee_buf_count_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+    return sprintf(buf, "%d\n", asee_buf_count);
+}
+
+static ssize_t asee_buf_count_store(struct kobject *kobj, struct kobj_attribute *attr, char *buf, size_t count)
+{
+    return count;
+}
+ 
+static struct kobj_attribute asee_buf_count_attribute = __ATTR(asee_buf_count, 0660, asee_buf_count_show, (void *)asee_buf_count_store);
+
+static int major; /* major number assigned to our device driver */ 
+ 
+enum { 
+    CDEV_NOT_USED = 0, 
+    CDEV_EXCLUSIVE_OPEN = 1, 
+}; 
+ 
+/* Is device open? Used to prevent multiple access to device */ 
+static atomic_t already_open = ATOMIC_INIT(CDEV_NOT_USED); 
+ 
+static struct class *cls; 
+ 
+static struct file_operations pipebis_fops = { 
+    .read = device_read, 
+    .write = device_write, 
+    .open = device_open, 
+    .release = device_release, 
+}; 
+ 
+static int __init pipebis_init(void) 
+{ 
+    major = register_chrdev(0, DEVICE_NAME, &pipebis_fops); 
+ 
+    if (major < 0) { 
+        pr_alert("Registering char device failed with %d\n", major); 
+        return major; 
+    } 
+ 
+    pr_info("I was assigned major number %d.\n", major); 
+
+    msg = kcalloc(asee_buf_size, sizeof(char), GFP_KERNEL);
+ 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) 
+    cls = class_create(DEVICE_NAME); 
+#else 
+    cls = class_create(THIS_MODULE, DEVICE_NAME); 
+#endif 
+    device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME); 
+ 
+    pr_info("Device created on /dev/%s\n", DEVICE_NAME); 
+    
+    pipebis_module = kobject_create_and_add("asee_mod", kernel_kobj);
+    if (!pipebis_module) return -ENOMEM;
+
+    int error = 0;
+    error = sysfs_create_file(pipebis_module, &asee_buf_size_attribute.attr);
+    error += sysfs_create_file(pipebis_module, &asee_buf_count_attribute.attr);
+    if (error) {
+        pr_info("failed to create a asee variable in /sys/kernel/asee_mod\n");
+        return error;
+    }
+
+    return SUCCESS; 
+} 
+ 
+static void __exit pipebis_exit(void) 
+{ 
+    device_destroy(cls, MKDEV(major, 0)); 
+    class_destroy(cls); 
+ 
+    /* Unregister the device */ 
+    unregister_chrdev(major, DEVICE_NAME); 
+    kobject_put(pipebis_module);
+} 
+ 
+/* Methods */ 
+
+/* Called when a process tries to open the device file, like 
+ * "sudo cat /dev/pipebis" 
+ */ 
+static int device_open(struct inode *inode, struct file *file) 
+{  
+    if (atomic_cmpxchg(&already_open, CDEV_NOT_USED, CDEV_EXCLUSIVE_OPEN)) 
+        return -EBUSY; 
+
+    try_module_get(THIS_MODULE); 
+ 
+    return SUCCESS; 
+} 
+ 
+/* Called when a process closes the device file. */ 
+static int device_release(struct inode *inode, struct file *file) 
+{ 
+    /* We're now ready for our next caller */ 
+    atomic_set(&already_open, CDEV_NOT_USED); 
+ 
+    /* Decrement the usage count, or else once you opened the file, you will 
+     * never get rid of the module. 
+     */ 
+    module_put(THIS_MODULE); 
+ 
+    return SUCCESS; 
+} 
+ 
+/* Called when a process, which already opened the dev file, attempts to 
+ * read from it. 
+ */ 
+static int last_writen_bytes;
+static ssize_t device_read(struct file *filp, /* see include/linux/fs.h   */ 
+                           char __user *buffer, /* buffer to fill with data */ 
+                           size_t length, /* length of the buffer     */ 
+                           loff_t *offset) 
+{ 
+    /* Number of bytes actually written to the buffer */ 
+    int bytes_read = 0; 
+    char *msg_ptr = msg; 
+ 
+    /* Actually put the data into the buffer */ 
+    while (asee_buf_count > 0) { 
+        if (last_writen_bytes >= asee_buf_size) {
+            last_writen_bytes = 0;
+        }
+        /* The buffer is in the user data segment, not the kernel 
+         * segment so "*" assignment won't work.  We have to use 
+         * put_user which copies data from the kernel data segment to 
+         * the user data segment. 
+         */ 
+        
+        put_user(*(msg_ptr + last_writen_bytes), buffer++);
+        // Try to clear the read
+        *(msg_ptr + last_writen_bytes) = '\0';
+        last_writen_bytes++;
+        asee_buf_count--;
+        bytes_read++;
+    } 
+ 
+    *offset = last_writen_bytes; 
+ 
+    /* Most read functions return the number of bytes put into the buffer. */ 
+    return bytes_read; 
+} 
+ 
+/* Called when a process writes to dev file: echo "hi" > /dev/hello */ 
+static ssize_t device_write(struct file *filp, const char __user *buff, 
+                            size_t len, loff_t *off) 
+{ 
+    int bytes_writen = 0;
+
+    int current_bytes = last_writen_bytes;
+
+    for (int cpt = 0; cpt < len; cpt++) {
+        if (current_bytes >= asee_buf_size) {
+            current_bytes = 0;
+        }
+        get_user(*(msg + current_bytes), buff + cpt);
+        current_bytes++;
+        bytes_writen++;
+        asee_buf_count++;
+    }
+
+    last_writen_bytes = current_bytes;
+    *off = last_writen_bytes; 
+
+    return bytes_writen; 
+} 
+ 
+module_init(pipebis_init); 
+module_exit(pipebis_exit); 
+ 
+MODULE_LICENSE("GPL");
\ No newline at end of file
diff --git a/work/tp2/pipebis.mod.c b/work/tp2/pipebis.mod.c
new file mode 100644
index 0000000000000000000000000000000000000000..b9e4454e83f21cc3d453c396c90caf765fec9035
--- /dev/null
+++ b/work/tp2/pipebis.mod.c
@@ -0,0 +1,65 @@
+#include <linux/module.h>
+#define INCLUDE_VERMAGIC
+#include <linux/build-salt.h>
+#include <linux/elfnote-lto.h>
+#include <linux/export-internal.h>
+#include <linux/vermagic.h>
+#include <linux/compiler.h>
+
+#ifdef CONFIG_UNWINDER_ORC
+#include <asm/orc_header.h>
+ORC_HEADER;
+#endif
+
+BUILD_SALT;
+BUILD_LTO_INFO;
+
+MODULE_INFO(vermagic, VERMAGIC_STRING);
+MODULE_INFO(name, KBUILD_MODNAME);
+
+__visible struct module __this_module
+__section(".gnu.linkonce.this_module") = {
+	.name = KBUILD_MODNAME,
+	.init = init_module,
+#ifdef CONFIG_MODULE_UNLOAD
+	.exit = cleanup_module,
+#endif
+	.arch = MODULE_ARCH_INIT,
+};
+
+#ifdef CONFIG_RETPOLINE
+MODULE_INFO(retpoline, "Y");
+#endif
+
+
+
+static const struct modversion_info ____versions[]
+__used __section("__versions") = {
+	{ 0x6bc3fbc0, "__unregister_chrdev" },
+	{ 0xecc78457, "kobject_put" },
+	{ 0x73895700, "__register_chrdev" },
+	{ 0x122c3a7e, "_printk" },
+	{ 0xeb233a45, "__kmalloc" },
+	{ 0xfb890f0b, "class_create" },
+	{ 0x41b15bc9, "device_create" },
+	{ 0xa6ef1646, "kernel_kobj" },
+	{ 0x10bd90f2, "kobject_create_and_add" },
+	{ 0xa3efd5d1, "sysfs_create_file_ns" },
+	{ 0xbcab6ee6, "sscanf" },
+	{ 0x37a0cba, "kfree" },
+	{ 0xbdfb6dbb, "__fentry__" },
+	{ 0x5b8239ca, "__x86_return_thunk" },
+	{ 0xc3aaf0a9, "__put_user_1" },
+	{ 0x167e7f9d, "__get_user_1" },
+	{ 0x3c3ff9fd, "sprintf" },
+	{ 0xab632ed, "module_put" },
+	{ 0x47143bb3, "try_module_get" },
+	{ 0xf23bcaeb, "device_destroy" },
+	{ 0xfdfe3852, "class_destroy" },
+	{ 0x76800044, "module_layout" },
+};
+
+MODULE_INFO(depends, "");
+
+
+MODULE_INFO(srcversion, "0407622983A4737B8D0E5C8");