diff --git a/swap_disk/.swap_file b/swap_disk/.swap_file
new file mode 100644
index 0000000000000000000000000000000000000000..be5f1ace884f209d3c4bb43ef627b7489e4365d0
Binary files /dev/null and b/swap_disk/.swap_file differ
diff --git a/swap_disk/Makefile b/swap_disk/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..9ed04b7622012da3255fd00d99d2e6f2ed827118
--- /dev/null
+++ b/swap_disk/Makefile
@@ -0,0 +1,47 @@
+# $Id: Makefile 102 2009-11-03 13:14:39Z simon_duquennoy $
+##############################################################################
+ROOTDIR = ../x86-64/
+LIBNAME = hardware
+
+CC	= gcc
+CFLAGS	= -Wall -ansi -pedantic
+LIBDIR  = $(ROOTDIR)
+INCDIR  = -I$(ROOTDIR)/include
+LIBS    = -L$(ROOTDIR)/lib -l$(LIBNAME)
+
+###------------------------------
+### Main targets
+###------------------------------------------------------------
+BINARIES= mmu_manager oracle
+
+all: $(BINARIES)
+
+###------------------------------
+### Main rules
+###------------------------------------------------------------
+
+%.o: %.c
+	$(CC) $(CFLAGS) -c $< $(INCDIR)
+
+%: %.o
+	$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
+
+Makefile.depends:
+	$(CC) -MM *.c $(INCDIR) > Makefile.depends
+
+include Makefile.depends
+
+
+
+mmu_manager: mmu_manager.o user_process.o matrix.o swap.o
+oracle: oracle.o matrix.o
+
+
+###------------------------------
+### Misc.
+###------------------------------------------------------------
+.PHONY: clean realclean depend
+clean:
+	$(RM) *.o $(BINARIES) Makefile.depends
+realclean: clean
+	$(RM) vdiskA.bin vdiskB.bin
diff --git a/swap_disk/hardware.h b/swap_disk/hardware.h
new file mode 100644
index 0000000000000000000000000000000000000000..14a3726125b5f212d814ee21fc76f1ee2a994784
--- /dev/null
+++ b/swap_disk/hardware.h
@@ -0,0 +1,127 @@
+/* ------------------------------
+   $Id: hardware.h 114 2009-12-01 13:06:43Z simon_duquennoy $
+   ------------------------------------------------------------
+
+   hardware.h
+
+   Interface de la biblioth�que de simulation du mat�riel. 
+
+*/
+
+#ifndef _HARDWARE_H_
+#define _HARDWARE_H_
+
+/**
+ * CMD_
+ * commandes ATA-2
+ */
+#define CMD_SEEK        0x02
+#define CMD_READ        0x04
+#define CMD_WRITE       0x06
+#define CMD_FORMAT      0x08
+#define CMD_STATUS      0x12
+#define CMD_DMASET      0x14
+#define CMD_DSKINFO     0x16
+#define CMD_MANUF       0xA2
+#define CMD_DIAG        0xA4
+
+/**
+ * Commandes de la MMU (registre MMU_CMD)
+ */
+#define MMU_PROCESS	0xCC	/* Commande d'activation/d�sactivation de la MMU */
+#define MMU_RESET	0xD5	/* Commande de r�initialisation de la MMU */
+
+/**
+ * Physical and virtual memory for MMU
+ */
+extern void *physical_memory;
+extern void *virtual_memory;
+
+/**
+ * prototype des fonctions-interruptions.
+ * une interruption ne recoit aucun param�tre "d'appel", 
+ * une interruption ne retourne aucun resultat, mais
+ * sa terminaison restaure le contexte d'ex�cution du programme interrompu. 
+ */
+typedef void (*func_irq)(void);
+
+/**
+ *      int init_hardware(const char *fileconfig);
+ *          initialisation du mat�riel. Pas de "reinitialisation" possible.
+ *          l'initialisation d�finit le mat�riel conform�ment aux sp�cifications
+ *          fournies par le fichier dont le nom est "fileconfig".
+ *          retourne 0 en cas de probl�me lors de l'initialisation.
+ */ 
+extern int init_hardware(const char *fileconfig);
+
+/**
+ *      IRQVECTOR 
+ *          donne la base d'un tableau de pointeur de fonction du type
+ *          func_irq. la fonction IRQVECTOR[n]() est appel�e lorsque 
+ *          l'interuption de niveau n est d�clanch�e par le mat�riel.
+ */
+#define IRQ_VECOTR_SIZE 256
+extern func_irq *irq_vector;	/* n'utilisez pas cette variable    */
+#define IRQVECTOR irq_vector	/* pr�f�rez ce #define IRQVECTOR    */
+
+extern int SYSTICKDURATION;	/* microseconde entre les SYSTICK   */
+
+/**
+ * MASTERBUFFER et SLAVEBUFFER
+ *     Adresses des buffers de donnees des disques maitre et esclave
+ */
+/* n'utilisez pas ces variables*/
+extern unsigned char ** HDA_masterbufferaddress, **HDB_masterbufferaddress;
+/* pr�f�rez ces #define MASTERBUFFER et SLAVEBUFFER */
+#define MASTERBUFFER (*HDA_masterbufferaddress) 
+#define SLAVEBUFFER  (*HDB_masterbufferaddress) 
+
+/**
+ *      BASEADDRESS_RAM
+ *          variable associ�e � adresse de base de la m�moire globale
+ *          de la machine. Cette m�moire est commune � tout les programmes 
+ *          qui utilisent la librairie sur la m�me machine.  
+ *          
+ */
+extern  unsigned char *baseGlobalMem;       /* n'utilisez pas cette variable */
+#define BASEADDRESS_RAM baseGlobalMem /* pr�f�rez ce #define BASEADDRESS_RAM */
+
+/**
+ *      int _in(int port);
+ *          lecture du contenu du registre mat�riel n� "port".
+ *          retourne la valeur lue.
+ */ 
+int     _in(int port);
+
+/**
+ *      void _out(int port, int value);
+ *          ecriture de la valeur "value" dans le registre mat�riel n� "port".
+ */
+void    _out(int port, int value);
+
+/**
+ *      void _sleep(int irq_level);
+ *          Stoppe l'activit� du microprocesseur jusqu'� l'occurence
+ *          une interruption de niveau au moins �gale � "irqLevel".
+ */
+void    _sleep(int irq_level);
+
+/**
+ *      void _mask(int irqLevel);
+ *          - cache au microprocesseur l'occurence d'interruptions 
+ *          de niveau inf�rieure � irqLevel.
+ * 			- 16�me bit � 0 : passage en mode prot�g�
+ * 			- 16�me bit � 1 : passage en mode user
+ *
+ */
+void     _mask(int irq_level);
+
+/**
+ *      void _int(int irqLevel);
+ *          - lance une interruption logicielle de niveau irqLevel
+ *
+ */
+void     _int(int irqLevel);
+
+#endif
+
diff --git a/swap_disk/hardware.ini b/swap_disk/hardware.ini
new file mode 100644
index 0000000000000000000000000000000000000000..5e85a850a8ea9004696dfe73ae0226197e8b8121
--- /dev/null
+++ b/swap_disk/hardware.ini
@@ -0,0 +1,135 @@
+# $Id: hardware.ini 114 2009-12-01 13:06:43Z simon_duquennoy $
+#------------------------------------------------------------
+
+#
+# Hardware.cfg
+#  Fichier de configuration du simulateur de mat�riel
+#
+
+#
+# Trace de Debug
+#
+# define DEBUG_SETUP   0x0001 /* trace hardware setup */
+# define DEBUG_IT      0x0010 /* trace interruptions generation */
+# define DEBUG_REG     0x0100 /* trace hardware register access */
+# define DEBUG_WARNING 0x1000 /* trace hardware warning messages */
+DEBUG          = 0x0000
+
+#
+# Configuration des param�tres de base du simulateur  
+#
+SYSTICK        = 1000          # delais entre deux ticks du simulateur (en micro-seconde) 
+
+#
+# Configuration des mat�riels r�seau
+#
+# configuration des ports COM (port serie de type RS232)
+# > Port Serie n�1
+SL1_ENABLE      = 0            # SL1_ENABLE = 0 => simulation lien serie d�sactiv�e
+SL1             = "chimay.lifl.fr"     # Machine connect� � la sortie du lien     serie n�1
+SL1_COM         = 1            # destinataire 1 = lien serie "com1", 2 = lien serie "com2" 
+SL1_NOISE       = 500          # bruit de la ligne 0-999 (exprim� en /1000 d'erreur)
+SL1_IRQ         = 4            # niveau d'interruption de l'UART          serie n�1
+SL1_UARTSR      = 0x3F8        # registre de status de l'UART             serie n�1    
+SL1_UARTDATA    = 0x3FA        # registre d'entr�e sortie de l'UART       serie n�1
+SL1_UDPPORT     = 1500         # port UDP "r�el" utiliser pour simulation serie n�1
+# > Port Serie n�2
+SL2_ENABLE      = 0            # SL2_ENABLE = 0 => simulation lien serie d�sactiv�e
+SL2             = "ldx2"       # Machine connect� � la sortie du lien     serie n�2
+SL2_COM         = 2            # destinataire 1 = lien serie "com1", 2 = lien serie "com2" 
+SL2_NOISE       = 0            # bruit de la ligne 0-999 (exprim� en /1000 d'erreur)
+SL2_IRQ         = 5            # niveau d'interruption de l'UART          serie n�2
+SL2_UARTSR      = 0x3FC        # registre de status de l'UART             serie n�2    
+SL2_UARTDATA    = 0x3FE        # registre d'entr�e sortie de l'UART       serie n�2
+SL2_UDPPORT     = 1501         # port UDP "r�el" utiliser pour simulation serie n�2
+# > Configuration de la carte Ethernet
+ENABLE_ETHERNET = 0            # ENABLE_ETHERNET = 0 => simulation ethernet d�sactiv�e
+Eth0_Link       = 1            # num de cable de connexion de la carte Eth0 
+Eth0_DMASR      = 0xE800       # registre de status de la carte Ethernet
+Eth0_DMABASE    = 0xE804       # adresse de base pour le vidage d'un paquet 
+Eth0_DMASIZE    = 0xE808       # adresse limite pour le vidage d'un paquet
+Eth0_IRQ        = 9            # niveau d'interruption de la carte.  
+Eth0_MCADR      = "225.0.0.1"  # adresse multicast utilis�e pour la simulation ethernet
+Eth0_UDPPORT    = 1502         # port UDP utilis� pour la simulation ethernet
+
+#
+# Configuration des disques durs
+#
+
+# > Disque dur IDE Maitre
+ENABLE_HDA      = 1            # ENABLE_HD = 0 => simulation du disque d�sactiv�e
+HDA_FILENAME    = "vdiskA.bin" # nom du fichier de stockage du disque simul�
+HDA_CMDREG      = 0x3F6        # registre de commande du disque maitre
+HDA_DATAREGS    = 0x110        # base des registres de donn�es (r,r+1,r+2,...r+7)
+HDA_IRQ         = 14           # Interruption du disque
+HDA_MAXCYLINDER = 16           # Nombre de pistes du disque ma�tre 
+HDA_MAXSECTOR   = 16           # Nombre de secteurs du disque ma�tre
+HDA_SECTORSIZE  = 32           # Taille (en octet) d'un secteur du disque ma�tre
+HDA_STPS        = 2            # nombre de SYSTICK pour changer de secteur
+HDA_STPC        = 1            # nombre de SYSTICK pour changer de piste 
+HDA_PON_DELAY   = 30           # nombre de SYSTICK avant amorce du disque
+HDA_POFF_DELAY  = 30           # nombre de SYSTICK avant arret du disque
+
+# > Disque dur IDE Esclave
+ENABLE_HDB      = 1            # ENABLE_HD = 0 => simulation du disque d�sactiv�e
+HDB_FILENAME    = "vdiskB.bin" # nom du fichier de stockage du disque simul�
+HDB_CMDREG      = 0x376        # registre de commande du disque esclave
+HDB_DATAREGS    = 0x170        # base des registres de donn�es (r,r+1,r+2,...r+7)
+HDB_IRQ         = 15           # Niveau d'interruption du disque
+HDB_MAXCYLINDER = 16           # Nombre de pistes du disque esclave 
+HDB_MAXSECTOR   = 16           # Nombre de secteurs du disque esclave
+HDB_SECTORSIZE  = 512          # Taille (en octet) d'un secteur du disque esclave
+HDB_STPS        = 2            # nombre de SYSTICK pour changer de secteur
+HDB_STPC        = 3            # nombre de SYSTICK pour changer de piste 
+HDB_PON_DELAY   = 30           # nombre de SYSTICK avant amorce du disque
+HDB_POFF_DELAY  = 30           # nombre de SYSTICK avant arret du disque
+
+#
+# Configuration de l'horologe interne
+#
+TIMER_CLOCK     = 0xF0         # registre de lecture de la date courante (en ms)
+TIMER_PARAM     = 0xF4         # registre de configuration du TIMER
+                               # bit 7 : RESET general (=1)
+                               # bit 6 : Alarm ON = 1, Alarm OFF = 0 
+                               # bit 5 : Declanche la division Hz du Timer (=1)
+                               # bit 4 \ Si le division Hz du timer est demand� : 
+                               # bit 3 / 00: 1 top d'alarme pour 1 tops d'horloge ,
+                               #         01: 1 top d'alarme pour 8 tops d'horloge ,
+                               #         10: 1 top d'alarme pour 64 tops d'horloge ,
+                               #         11: 1 top d'alarme pour 512 tops d'horloge. 
+                               # bit 2 - R.F.U. -
+                               # bit 1 \ Lecture d'un �tat interne de l'alarme 
+                               # bit 0 / 00: Alarme Courante,
+                               #         01: Division Hz,
+                               #         10: Ticks/Sec
+                               #         11: niveau d'interruption de l'horloge
+TIMER_ALARM     = 0xF8         # registre de generation d'interruption
+TIMER_IRQ       = 2            # Niveau d'interruption de l'horologe
+TIMER_TICKS     = 1            # Nombre de SYSTICKS par tick d'horloge
+
+#
+# Configuration de la MMU
+#
+MMU_ENABLE 	= 1				# MMU_ENABLE = 0 => simulation de la MMU d�sactiv�e
+MMU_IRQ		= 13				# Niveau d'interruption de la MMU
+MMU_CMD		= 0x66				# Registre de commande de la MMU
+MMU_FAULT_ADDR_LO	= 0xCC		# Registre contenant l'adresse m�moire ayant provoqu� une faute (32 bits de poids faible)
+MMU_FAULT_ADDR_HI	= 0xCD		# Registre contenant l'adresse m�moire ayant provoqu� une faute (32 bits de poids fort)
+TLB_ADD_ENTRY	= 0xCE			# Registre de commande d'ajout d'entr�e dans la TLB
+								# attend une valeur de la forme :
+								# struct tlb_entry_s {
+								#	unsigned unused: 8;
+								#	unsigned virt_page: 12;
+								#	unsigned phys_page: 8;
+								#	unsigned access_type: 3;
+								#	unsigned is_active: 1;
+								#};
+								# le nouveau mapping est ajout� dans la TLB,
+								# provoquant �ventuellement l'�crasement d'une ancienne entr�e
+TLB_DEL_ENTRY	= 0xDE			# Registre de commande de suppression d'entr�e dans la TLB
+								# seul phys_page est lu, et toutes les entr�e
+								# correspondant � cette page physicique sont supprim�es de la TLB
+TLB_SIZE		= 32			# Number of entries in the TLB
+TLB_ENTRIES		= 0x800			# Registre contenant les entr�es de la TLB (32 bits par entr�e)
+								# Accessible en lecture comme en �criture avec le m�me format que
+								# celui utilis� par TLB_ADD_ENTRY
diff --git a/swap_disk/hw_config.h b/swap_disk/hw_config.h
new file mode 100644
index 0000000000000000000000000000000000000000..930a2df501e0fcfedc470a4df84b0feda6cfd313
--- /dev/null
+++ b/swap_disk/hw_config.h
@@ -0,0 +1,34 @@
+/* ------------------------------
+   $Id: hw_config.h 105 2009-11-24 15:22:50Z simon_duquennoy $
+   ------------------------------------------------------------
+
+   Fichier de configuration des acces au materiel
+
+   Philippe Marquet, march 2007
+
+   Code au niveau applicatif la description du materiel qui est fournie
+   par hardware.ini
+   
+*/
+
+#ifndef _HW_CONFIG_H_
+#define _HW_CONFIG_H_
+
+#define HARDWARE_INI	"hardware.ini"
+
+#define MMU_IRQ		13
+#define MMU_CMD		0x66
+#define MMU_FAULT_ADDR 	0xCD
+#define TLB_ADD_ENTRY	0xCE
+#define TLB_DEL_ENTRY	0xDE
+#define TLB_SIZE	32
+#define TLB_ENTRIES	0x800
+
+#define PM_PAGES (1 << 8)
+#define VM_PAGES (1 << 12)
+#define PAGE_SIZE 4096
+#define PM_SIZE (4096 * PM_PAGES)
+#define VM_SIZE (4096 * VM_PAGES)
+
+#endif
+
diff --git a/swap_disk/matrix.c b/swap_disk/matrix.c
new file mode 100644
index 0000000000000000000000000000000000000000..df1eab2221cd0c87569c7625b99b7304d393efa4
--- /dev/null
+++ b/swap_disk/matrix.c
@@ -0,0 +1,59 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "matrix.h"
+
+static void log_state(int i, int n) {
+	if(n && i % n == n - 1) {
+		printf(".");
+		fflush(stdout);
+	}
+}
+
+void matrix_init(matrix *m) {
+	int i,j;
+	for(i = 0; i<MATRIX_SIZE; i++) {
+		for(j = 0; j<MATRIX_SIZE; j++) {
+			(*m)[i][j] = rand();
+		}
+	}
+}
+
+void matrix_add(matrix *dest, matrix *m1, matrix *m2) {
+	int i, j;
+	for(i = 0; i<MATRIX_SIZE; i++) {
+		log_state(i, MATRIX_SIZE / 20);
+		for(j = 0; j<MATRIX_SIZE; j++) {
+			(*dest)[i][j] = (*m1)[i][j] + (*m2)[i][j];
+		}
+	}
+	printf(" done\n");
+}
+
+void matrix_mult(matrix *dest, matrix *m1, matrix *m2) {
+	int i, j, k;
+	for(i = 0; i<MATRIX_SIZE; i++) {
+		log_state(i, MATRIX_SIZE / 20);
+		for(j = 0; j<MATRIX_SIZE; j++) {
+			int curr_val = 0;
+			for(k = 0; k<MATRIX_SIZE; k++) {
+				curr_val += (*m1)[i][k] * (*m2)[k][j];
+			}
+			(*dest)[i][j] = curr_val;
+		}
+	}
+	printf(" done\n");
+}
+
+unsigned matrix_checksum(matrix *m) {
+	int i, j;
+	unsigned int checksum = 0;
+	for(i = 0; i<MATRIX_SIZE; i++) {
+		for(j = 0; j<MATRIX_SIZE; j++) {
+			checksum += (*m)[i][j];
+			checksum += checksum >> 16;
+			checksum &= 0x0000ffff;
+		}
+	}
+	return checksum;
+}
+
diff --git a/swap_disk/matrix.h b/swap_disk/matrix.h
new file mode 100644
index 0000000000000000000000000000000000000000..2e0c8bcb8b1d45e22e43998abc13e1e9937c3c01
--- /dev/null
+++ b/swap_disk/matrix.h
@@ -0,0 +1,16 @@
+#ifndef _MATRIX_H_
+#define _MATRIX_H_
+
+#define MATRIX_SIZE 400
+#define MATRIX_ADD 0
+#define MATRIX_MUL 1
+
+typedef unsigned int matrix[MATRIX_SIZE][MATRIX_SIZE];
+
+extern void matrix_init(matrix *m);
+extern void matrix_add(matrix *dest, matrix *m1, matrix *m2);
+extern void matrix_mult(matrix *dest, matrix *m1, matrix *m2);
+extern unsigned matrix_checksum(matrix *m);
+
+#endif
+
diff --git a/swap_disk/mmu_manager.c b/swap_disk/mmu_manager.c
new file mode 100644
index 0000000000000000000000000000000000000000..208ae972ada6d27e893555b702582b47c1d8fcc0
--- /dev/null
+++ b/swap_disk/mmu_manager.c
@@ -0,0 +1,116 @@
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include "hardware.h"
+#include "hw_config.h"
+#include "mmu_manager.h"
+#include "swap.h"
+
+#define PAGE_SWAPPED -2
+#define EMPTY_VM_PAGE -1
+#define EMPTY_PM_PAGE 0
+
+int VM_MAPPING[VM_PAGES] = {EMPTY_PM_PAGE};
+int PM_MAPPING[PM_PAGES] = {EMPTY_VM_PAGE};
+int first_pm_free = 1;
+
+extern void user_process();
+
+void simple_swap_mmu_handler()
+{
+  tlb_entry_t tlb;
+  int ppage = 1;
+  long int vaddr = ((long int)_in(MMU_FAULT_ADDR_HI) << 32) | (_in(MMU_FAULT_ADDR_LO) & 0xFFFFFFFF);
+  long int vpage = (vaddr >> 12) & 0xFFF;
+
+  if (vaddr < ((long int)virtual_memory) || vaddr > ((long int)virtual_memory) + VM_SIZE)
+  {
+    fprintf(stderr, "Adresse virtuelle incorrecte");
+    exit(EXIT_FAILURE);
+  }
+
+  /* Sauvegarder la vpage dans le fichier swap */
+  store_to_swap(vpage, ppage);
+
+  /* Rajouter l'entree dans la tlb */
+  tlb.s.tlb_vpage = vpage;
+  tlb.s.tlb_ppage = ppage;
+  tlb.s.tlb_rwx = 7;
+  tlb.s.tlb_used = 1;
+
+  /* Vider la MMU */
+  _out(MMU_CMD, MMU_RESET);
+  _out(TLB_ADD_ENTRY, tlb.i);
+}
+
+void swap_mmu_handler()
+{
+  tlb_entry_t tlb;
+  long int vaddr = (((long int)_in(MMU_FAULT_ADDR_HI)) << 32) | (((long int)_in(MMU_FAULT_ADDR_LO)) & 0xFFFFFFFF);
+  int vpage = (vaddr >> 12) & 0xFFF;
+
+  if (vaddr < (long int)virtual_memory || vaddr > (long int)virtual_memory + VM_SIZE - 1)
+  {
+    fprintf(stderr, "Adresse virtuelle incorrecten \n");
+    exit(EXIT_FAILURE);
+  }
+
+  int ppage = VM_MAPPING[vpage];
+
+  /*
+   * Si la vpage n'a jamais eu de correspondance ou elle existe dans notre fichier de swap
+   * sinon, on recupere directement sa ppage coorespondante dans nos mapping.
+   */
+  if (ppage == EMPTY_PM_PAGE || ppage == PAGE_SWAPPED)
+  {
+    /* round robin algorithm*/
+    if (!(++first_pm_free % PM_PAGES))
+      first_pm_free = 1;
+    ppage = first_pm_free;
+
+    /* old_vpage: la vpage qui pointait vers la ppage courante */
+    /* S'il n'y a aucune vpage qui pointait vers la ppage courante
+     * nous avons donc affaire à la première correspondance.
+     */
+    int old_vpage = PM_MAPPING[ppage];
+    if (old_vpage != EMPTY_VM_PAGE)
+    {
+      store_to_swap(old_vpage, ppage);
+      VM_MAPPING[old_vpage] = PAGE_SWAPPED; /* On signifie qu'on l'a rajouté dans le swap*/
+    }
+
+    /* Si la vpage courant existe dans notre fichier swap,
+     * On le restore dans ce cas.
+     * */
+    if (VM_MAPPING[vpage] == PAGE_SWAPPED)
+      fetch_from_swap(vpage, ppage);
+
+    VM_MAPPING[vpage] = ppage;
+    PM_MAPPING[ppage] = vpage;
+  }
+
+  tlb.s.tlb_vpage = vpage;
+  tlb.s.tlb_ppage = ppage;
+  tlb.s.tlb_rwx = 7;
+  tlb.s.tlb_used = 1;
+
+  _out(TLB_DEL_ENTRY, tlb.i);
+  _out(TLB_ADD_ENTRY, tlb.i);
+}
+
+void master_process()
+{
+  if (init_hardware(HARDWARE_INI) == 0)
+    fprintf(stderr, "Error in hardware initialization\n");
+  IRQVECTOR[MMU_IRQ] = swap_mmu_handler;
+}
+
+int main(int argc, char **argv)
+{
+  master_process();
+  _mask(0x1001);
+  user_process();
+
+  return 0;
+}
diff --git a/swap_disk/mmu_manager.h b/swap_disk/mmu_manager.h
new file mode 100644
index 0000000000000000000000000000000000000000..2b44faf2d94e63ebde5b5539abf30412bb3e04a6
--- /dev/null
+++ b/swap_disk/mmu_manager.h
@@ -0,0 +1,34 @@
+#if !defined(MI_KERNEL)
+
+#define MI_KERNEL
+
+#define MMU_ENABLE 1
+#define MMU_IRQ 13
+#define MMU_FAULT_ADDR_LO 0xCC
+#define MMU_FAULT_ADDR_HI 0xCD
+#define TLB_ADD_ENTRY 0xCE
+#define MMU_CMD 0x66
+#define HARDWARE_INI "hardware.ini"
+
+struct tlb_entry_s
+{
+    unsigned tlb_RFU : 8;
+    unsigned tlb_vpage : 12;
+    unsigned tlb_ppage : 8;
+    unsigned tlb_rwx : 3;
+    unsigned tlb_used : 1;
+};
+
+union tlb_entry_u
+{
+    int i;
+    struct tlb_entry_s s;
+};
+
+typedef union tlb_entry_u tlb_entry_t;
+
+void simple_swap_mmu_handler();
+void swap_mmu_handler();
+void init_master();
+
+#endif
diff --git a/swap_disk/oracle.c b/swap_disk/oracle.c
new file mode 100644
index 0000000000000000000000000000000000000000..c792098047f6161e77d878f9e113c410ee7fe29b
--- /dev/null
+++ b/swap_disk/oracle.c
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "hw_config.h"
+#include "matrix.h"
+
+int main() {
+	int operation;
+	unsigned timestamp;
+	unsigned prev_checksum;
+	unsigned new_checksum;
+	matrix matrix1;
+	matrix matrix2;
+	matrix matrix3;
+	char line[1024];
+
+	while(!feof(stdin)) {
+		fgets(line, sizeof(line), stdin);
+	}
+	
+	if(sscanf(line, "timestamp: 0x%x, operation: %d, checksum: 0x%x", &timestamp, &operation, &prev_checksum) == 0) {
+		fprintf(stderr, "[oracle] Invalid input\n");
+		exit(1);
+	}
+		
+	srand(timestamp);
+	
+	printf("[Starting oracle]\n");
+
+	printf("timestamp: 0x%04x, ", timestamp);
+	printf("operation: %d, ", operation);
+	printf("checksum: 0x%04x\n", prev_checksum);
+	/* init matrices */
+	printf("initializing matrices\n");
+	matrix_init(&matrix1);
+	matrix_init(&matrix2);
+	switch(operation) {
+		case 0: /* add matrices */
+			printf("adding VM matrices ");fflush(stdout);
+			matrix_add(&matrix3, &matrix1, &matrix2);
+			break;
+		case 1: /* multiply matrices */
+			printf("multiplying matrices ");fflush(stdout);
+			matrix_mult(&matrix3, &matrix1, &matrix2);
+			break;
+		default:
+			break;
+	}
+	new_checksum = matrix_checksum(&matrix3);
+	printf("new checksum: 0x%04x [%s]\n", new_checksum, new_checksum == prev_checksum ? "ok" : "ko");
+	
+	return 0;
+}
+
diff --git a/swap_disk/swap.c b/swap_disk/swap.c
new file mode 100644
index 0000000000000000000000000000000000000000..bfe9065043535d7dfc7d5b5dd727b276ec9da5ef
--- /dev/null
+++ b/swap_disk/swap.c
@@ -0,0 +1,44 @@
+/* functions return non null value on error */
+
+#include <stdio.h>
+#include <stdint.h>
+
+#include "hardware.h"
+#include "hw_config.h"
+
+static FILE *swap_file = NULL;
+
+static int
+init_swap(void) 
+{
+    swap_file = fopen(".swap_file", "w+"); /* w+: create, read, write*/
+    return swap_file == NULL;
+}
+
+int
+store_to_swap(int vpage, int ppage) 
+{
+    if (swap_file == NULL)
+        if (init_swap()) 
+            return -2;
+    if (fseek(swap_file, vpage << 12, SEEK_SET) == -1) 
+        return -1;
+    if (fwrite((void*)((ppage << 12) | (uintptr_t)physical_memory), 
+               1, PAGE_SIZE, swap_file) == 0)
+        return -1;
+  return 0;
+}
+
+int 
+fetch_from_swap(int vpage, int ppage) 
+{
+    if (swap_file == NULL)
+        if (init_swap()) 
+            return -2;
+    if (fseek(swap_file, vpage << 12, SEEK_SET) == -1) 
+        return -1;
+    if (fread((void*)((ppage << 12) | (uintptr_t)physical_memory), 
+	      1, PAGE_SIZE, swap_file) == 0)
+        return -1;
+    return 0;
+}
diff --git a/swap_disk/swap.h b/swap_disk/swap.h
new file mode 100644
index 0000000000000000000000000000000000000000..75d5ad5f88b34a6fa191533484f3314e80ab9f16
--- /dev/null
+++ b/swap_disk/swap.h
@@ -0,0 +1,7 @@
+#if !defined(SWAP)
+#define SWAP
+
+int store_to_swap(int, int);
+int fetch_from_swap(int, int);
+
+#endif // SWAP
diff --git a/swap_disk/user_process.c b/swap_disk/user_process.c
new file mode 100644
index 0000000000000000000000000000000000000000..e269ce86a178875f0b6192c2c2070804db91a667
--- /dev/null
+++ b/swap_disk/user_process.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include "hw_config.h"
+#include "matrix.h"
+
+extern void *virtual_memory;
+
+#define MATRIX_OP MATRIX_ADD
+/*#define MATRIX_OP MATRIX_MUL*/
+
+void user_process() {
+	unsigned short timestamp = (unsigned)time(NULL);
+	matrix *matrix1 = (matrix*)virtual_memory;
+	matrix *matrix2 = ((matrix*)virtual_memory) + 1;
+	matrix *matrix3 = ((matrix*)virtual_memory) + 2;
+	
+	srand(timestamp);
+
+	printf("[Starting user process]\n");
+
+	/* print some informations */
+	printf("matrices size: %dx%d\n", MATRIX_SIZE, MATRIX_SIZE);
+	printf("vm used: %5d pages\n", 3 * sizeof(matrix) / PAGE_SIZE);
+	printf("pm space: %5d pages\n", 1 << 8);
+	printf("vm space: %5d pages\n", 1 << 12);
+	/* init matrices */
+	printf("initializing matrices\n");
+	matrix_init(matrix1);
+	matrix_init(matrix2);
+#if MATRIX_OP == MATRIX_ADD
+	/* add matrices */
+	printf("adding VM matrices ");fflush(stdout);
+	matrix_add(matrix3, matrix1, matrix2);
+#elif MATRIX_OP == MATRIX_MUL
+	/* multiply matrices */
+	printf("multiplying matrices ");fflush(stdout);
+	matrix_mult(matrix3, matrix1, matrix2);
+#endif
+	printf("timestamp: 0x%04x, ", timestamp);
+	printf("operation: %d, ", MATRIX_OP);
+	printf("checksum: 0x%04x\n", matrix_checksum(matrix3));
+}
+
+void show(){
+	
+}
\ No newline at end of file