diff --git a/control/auxiliary.c b/control/auxiliary.c
index 14fd016ed7a9da87227a87502f7b43c87ca91a08..b00ed6efe4e6db2664278575696bf6b8b52fe119 100644
--- a/control/auxiliary.c
+++ b/control/auxiliary.c
@@ -53,7 +53,7 @@
  *          Warning message to display.
  *
  ******************************************************************************/
-void morse_warning(const char *func_name, char* msg_text)
+void morse_warning(const char *func_name, const char *msg_text)
 {
     MORSE_context_t *morse;
 
@@ -78,7 +78,7 @@ void morse_warning(const char *func_name, char* msg_text)
  *          Warning message to display.
  *
  ******************************************************************************/
-void morse_error(const char *func_name, char* msg_text)
+void morse_error(const char *func_name, const char *msg_text)
 {
     fprintf(stderr, "MORSE ERROR: %s(): %s\n", func_name, msg_text);
 }
@@ -96,7 +96,7 @@ void morse_error(const char *func_name, char* msg_text)
  *          Warning message to display.
  *
  ******************************************************************************/
-void morse_fatal_error(const char *func_name, char* msg_text)
+void morse_fatal_error(const char *func_name, const char *msg_text)
 {
     fprintf(stderr, "MORSE FATAL ERROR: %s(): %s\n", func_name, msg_text);
     exit(0);
diff --git a/control/auxiliary.h b/control/auxiliary.h
index 653bb38a037cd8188ca450947ba6b2652421043a..147fe1694635c905accafddd9c847ff930f05914 100644
--- a/control/auxiliary.h
+++ b/control/auxiliary.h
@@ -36,9 +36,9 @@ extern "C" {
 /*******************************************************************************
  *  Internal routines
  **/
-void morse_warning      (const char *func_name, char* msg_text);
-void morse_error        (const char *func_name, char* msg_text);
-void morse_fatal_error  (const char *func_name, char* msg_text);
+void morse_warning      (const char *func_name, const char* msg_text);
+void morse_error        (const char *func_name, const char* msg_text);
+void morse_fatal_error  (const char *func_name, const char* msg_text);
 int  morse_rank         (MORSE_context_t *morse);
 int  morse_tune         (MORSE_enum func, int M, int N, int NRHS);
 
diff --git a/control/descriptor.c b/control/descriptor.c
index e5f4146b2f24538adb9ff3e11cdc18640af3cfaf..b7963cf76d9173c5e11dde119e525827fd514e73 100644
--- a/control/descriptor.c
+++ b/control/descriptor.c
@@ -38,49 +38,89 @@
 
 static int nbdesc = 0;
 
-/*******************************************************************************
- *  Internal static descriptor initializer
- **/
-MORSE_desc_t morse_desc_init(MORSE_enum dtyp, int mb, int nb, int bsiz,
-                             int lm, int ln, int i, int j,
-                             int m,  int n,  int p, int q)
-{
-  return morse_desc_init_user(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q,
-                              morse_getaddr_ccrb, morse_getblkldd_ccrb, morse_getrankof_2d);
-}
-
-/*******************************************************************************
- *  Internal static descriptor initializer for a block diagonal matrix
- **/
-MORSE_desc_t morse_desc_init_diag(MORSE_enum dtyp, int mb, int nb, int bsiz,
-                                  int lm, int ln, int i, int j,
-                                  int m,  int n,  int p, int q)
-{
-  return morse_desc_init_user(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q,
-                              morse_getaddr_ccrb, morse_getblkldd_ccrb, morse_getrankof_2d_diag);
-}
-
-/*******************************************************************************
- *  Static descriptor initializer for users
- **/
+/**
+ ******************************************************************************
+ *
+ * @ingroup Descriptor
+ *
+ * morse_desc_init_user - Internal function to create tiled matrix descriptor
+ * with generic function for data distribution and storage format.
+ *
+ ******************************************************************************
+ *
+ * @param[in] dtyp
+ *          Data type of the matrix:
+ *          @arg MorseRealFloat:     single precision real (S),
+ *          @arg MorseRealDouble:    double precision real (D),
+ *          @arg MorseComplexFloat:  single precision complex (C),
+ *          @arg MorseComplexDouble: double precision complex (Z).
+ *
+ * @param[in] mb
+ *          Number of rows in a tile.
+ *
+ * @param[in] nb
+ *          Number of columns in a tile.
+ *
+ * @param[in] bsiz
+ *          Size in bytes including padding.
+ *
+ * @param[in] lm
+ *          Number of rows of the entire matrix.
+ *
+ * @param[in] ln
+ *          Number of columns of the entire matrix.
+ *
+ * @param[in] i
+ *          Row index to the beginning of the submatrix.
+ *
+ * @param[in] j
+ *          Column indes to the beginning of the submatrix.
+ *
+ * @param[in] m
+ *          Number of rows of the submatrix.
+ *
+ * @param[in] n
+ *          Number of columns of the submatrix.
+ *
+ * @param[in] p
+ *          2D-block cyclic distribution in rows.
+ *
+ * @param[in] q
+ *          2D-block cyclic distribution in columns.
+ *
+ * @param[in] (*get_blkaddr)( const MORSE_desc_t *A, int m, int n)
+ *          A function which return the address of the data corresponding to
+ *          the tile A(m,n).
+ *
+ * @param[in] (*get_blkldd)( const MORSE_desc_t *A, int m )
+ *          A function that return the leading dimension of the tile A(m,*).
+ *
+ * @param[in] (*get_rankof)( const MORSE_desc_t *A, int m, int n)
+ *          A function that return the MPI rank of the tile A(m,n).
+ *
+ ******************************************************************************
+ *
+ * @return  The descriptor with the matrix description parameters set.
+ *
+ *****************************************************************************/
 MORSE_desc_t morse_desc_init_user(MORSE_enum dtyp, int mb, int nb, int bsiz,
                                   int lm, int ln, int i, int j,
                                   int m,  int n,  int p, int q,
                                   void* (*get_blkaddr)( const MORSE_desc_t*, int, int ),
-                                  int (*get_blkldd)( const MORSE_desc_t*, int ),
-                                  int (*get_rankof)( const MORSE_desc_t*, int, int ))
+                                  int   (*get_blkldd) ( const MORSE_desc_t*, int      ),
+                                  int   (*get_rankof) ( const MORSE_desc_t*, int, int ))
 {
     MORSE_desc_t desc;
     // If one of the function get_* is NULL, we switch back to the default, like in morse_desc_init()
     desc.get_blkaddr = get_blkaddr ? get_blkaddr : morse_getaddr_ccrb;
-    desc.get_blkldd  = get_blkldd ? get_blkldd : morse_getblkldd_ccrb;
-    desc.get_rankof  = get_rankof ? get_rankof : morse_getrankof_2d;
+    desc.get_blkldd  = get_blkldd  ? get_blkldd  : morse_getblkldd_ccrb;
+    desc.get_rankof  = get_rankof  ? get_rankof  : morse_getrankof_2d;
     // Matrix properties
     desc.dtyp = dtyp;
-    // seems useless
+    // Should be given as parameter to follow get_blkaddr (unused)
     desc.styp = MorseCCRB;
-    desc.mb = mb;
-    desc.nb = nb;
+    desc.mb   = mb;
+    desc.nb   = nb;
     desc.bsiz = bsiz;
     // Large matrix parameters
     desc.lm = lm;
@@ -99,9 +139,10 @@ MORSE_desc_t morse_desc_init_user(MORSE_enum dtyp, int mb, int nb, int bsiz,
 
     desc.id = nbdesc; nbdesc++;
     desc.occurences = 0;
-    desc.use_mat = 1;
-    desc.alloc_mat = 1;
+    desc.use_mat      = 1;
+    desc.alloc_mat    = 1;
     desc.register_mat = 1;
+    desc.ooc          = 0;
 
     RUNTIME_comm_rank( &(desc.myrank) );
 
@@ -130,12 +171,12 @@ MORSE_desc_t morse_desc_init_user(MORSE_enum dtyp, int mb, int nb, int bsiz,
         desc.llm1 = (desc.llm/mb);
         desc.lln1 = (desc.lln/nb);
     } else {
-      desc.llmt = 0;
-      desc.llnt = 0;
-      desc.llm  = 0;
-      desc.lln  = 0;
-      desc.llm1 = 0;
-      desc.lln1 = 0;
+        desc.llmt = 0;
+        desc.llnt = 0;
+        desc.llm  = 0;
+        desc.lln  = 0;
+        desc.llm1 = 0;
+        desc.lln1 = 0;
     }
 
     // Matrix address
@@ -149,10 +190,32 @@ MORSE_desc_t morse_desc_init_user(MORSE_enum dtyp, int mb, int nb, int bsiz,
     return desc;
 }
 
+/*******************************************************************************
+ *  Internal static descriptor initializer
+ **/
+MORSE_desc_t morse_desc_init(MORSE_enum dtyp, int mb, int nb, int bsiz,
+                             int lm, int ln, int i, int j,
+                             int m,  int n,  int p, int q)
+{
+    return morse_desc_init_user(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q,
+                                morse_getaddr_ccrb, morse_getblkldd_ccrb, morse_getrankof_2d);
+}
+
+/*******************************************************************************
+ *  Internal static descriptor initializer for a block diagonal matrix
+ **/
+MORSE_desc_t morse_desc_init_diag(MORSE_enum dtyp, int mb, int nb, int bsiz,
+                                  int lm, int ln, int i, int j,
+                                  int m,  int n,  int p, int q)
+{
+    return morse_desc_init_user(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q,
+                                morse_getaddr_ccrb, morse_getblkldd_ccrb, morse_getrankof_2d_diag);
+}
+
 /*******************************************************************************
  *  Internal static descriptor initializer for submatrices
  **/
-MORSE_desc_t* morse_desc_submatrix(MORSE_desc_t *descA, int i, int j, int m, int n )
+MORSE_desc_t* morse_desc_submatrix(MORSE_desc_t *descA, int i, int j, int m, int n)
 {
     MORSE_desc_t *descB = malloc(sizeof(MORSE_desc_t));
     int mb, nb;
@@ -237,7 +300,7 @@ int morse_desc_mat_alloc( MORSE_desc_t *desc )
 {
 
     size_t size = (size_t)(desc->llm) * (size_t)(desc->lln)
-      * (size_t)MORSE_Element_Size(desc->dtyp);
+        * (size_t)MORSE_Element_Size(desc->dtyp);
     if ((desc->mat = RUNTIME_mat_alloc(size)) == NULL) {
         morse_error("morse_desc_mat_alloc", "malloc() failed");
         return MORSE_ERR_OUT_OF_RESOURCES;
@@ -255,12 +318,12 @@ int morse_desc_mat_alloc( MORSE_desc_t *desc )
  **/
 int morse_desc_mat_free( MORSE_desc_t *desc )
 {
-
     RUNTIME_desc_destroy( desc );
 
-    if (desc->mat != NULL  &&
-        desc->use_mat == 1 &&
-        desc->alloc_mat == 1) {
+    if ( (desc->mat       != NULL) &&
+         (desc->use_mat   == 1   ) &&
+         (desc->alloc_mat == 1   ) )
+    {
         size_t size = (size_t)(desc->llm) * (size_t)(desc->lln)
             * (size_t)MORSE_Element_Size(desc->dtyp);
 
@@ -270,11 +333,12 @@ int morse_desc_mat_free( MORSE_desc_t *desc )
     return MORSE_SUCCESS;
 }
 
-/** ***************************************************************************
+/**
+ *****************************************************************************
  *
  * @ingroup Descriptor
  *
- *  MORSE_Desc_Create - Create matrix descriptor.
+ *  MORSE_Desc_Create - Create tiled matrix descriptor.
  *
  ******************************************************************************
  *
@@ -331,59 +395,71 @@ int morse_desc_mat_free( MORSE_desc_t *desc )
  *          \retval MORSE_SUCCESS successful exit
  *
  *****************************************************************************/
-int MORSE_Desc_Create(MORSE_desc_t **desc, void *mat, MORSE_enum dtyp, int mb, int nb, int bsiz,
+int MORSE_Desc_Create(MORSE_desc_t **descptr, void *mat, MORSE_enum dtyp, int mb, int nb, int bsiz,
                       int lm, int ln, int i, int j, int m, int n, int p, int q)
 {
     MORSE_context_t *morse;
+    MORSE_desc_t *desc;
     int status;
 
+    *descptr = NULL;
+
     morse = morse_context_self();
     if (morse == NULL) {
         morse_error("MORSE_Desc_Create", "MORSE not initialized");
         return MORSE_ERR_NOT_INITIALIZED;
     }
+
     /* Allocate memory and initialize the descriptor */
-    *desc = (MORSE_desc_t*)malloc(sizeof(MORSE_desc_t));
-    if (*desc == NULL) {
+    desc = (MORSE_desc_t*)malloc(sizeof(MORSE_desc_t));
+    if (desc == NULL) {
         morse_error("MORSE_Desc_Create", "malloc() failed");
         return MORSE_ERR_OUT_OF_RESOURCES;
     }
-    **desc = morse_desc_init(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q);
+    *desc = morse_desc_init(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q);
 
     if (mat == NULL) {
 
-        size_t size = (size_t)((*desc)->llm) * (size_t)((*desc)->lln)
-            * (size_t)MORSE_Element_Size((*desc)->dtyp);
+        size_t size = (size_t)(desc->llm) * (size_t)(desc->lln)
+            * (size_t)MORSE_Element_Size(desc->dtyp);
 
-        if (((*desc)->mat = RUNTIME_mat_alloc(size)) == NULL) {
+        if ((desc->mat = RUNTIME_mat_alloc(size)) == NULL) {
             morse_error("MORSE_Desc_Create", "malloc() failed");
             return MORSE_ERR_OUT_OF_RESOURCES;
         }
-        (*desc)->alloc_mat = 1;
+        desc->use_mat      = 1;
+        desc->alloc_mat    = 1;
+        desc->register_mat = 0;
 
     } else {
-        (*desc)->mat = mat;
-        /* memory of the matrix is handle by users */
-        (*desc)->alloc_mat = 0;
+        desc->mat = mat;
+        /* memory of the matrix is handled by users */
+        desc->alloc_mat    = 0;
+        desc->use_mat      = 1;
+        desc->register_mat = 0;
     }
 
     /* Create scheduler structure like registering data */
-    RUNTIME_desc_create( *desc );
+    RUNTIME_desc_create( desc );
 
-    status = morse_desc_check(*desc);
+    status = morse_desc_check( desc );
     if (status != MORSE_SUCCESS) {
         morse_error("MORSE_Desc_Create", "invalid descriptor");
+        MORSE_Desc_Destroy( &desc );
         return status;
     }
 
+    *descptr = desc;
     return MORSE_SUCCESS;
 }
 
-/** ***************************************************************************
+/**
+ *****************************************************************************
  *
  * @ingroup Descriptor
  *
- *  MORSE_Desc_Create_User - Create matrix descriptor for general applications.
+ *  MORSE_Desc_Create_User - Create generic tiled matrix descriptor for general
+ *  applications.
  *
  ******************************************************************************
  *
@@ -410,7 +486,7 @@ int MORSE_Desc_Create(MORSE_desc_t **desc, void *mat, MORSE_enum dtyp, int mb, i
  * @param[in] n
  *          Number of columns of the entire matrix.
  *
-  * @param[in] p
+ * @param[in] p
  *          2d-block cyclic partitioning, number of tiles in rows.
  *
  * @param[in] q
@@ -432,53 +508,205 @@ int MORSE_Desc_Create(MORSE_desc_t **desc, void *mat, MORSE_enum dtyp, int mb, i
  *          \retval MORSE_SUCCESS successful exit
  *
  *****************************************************************************/
-int MORSE_Desc_Create_User(MORSE_desc_t **desc, void *mat, MORSE_enum dtyp, int mb, int nb, int bsiz,
+int MORSE_Desc_Create_User(MORSE_desc_t **descptr, void *mat, MORSE_enum dtyp, int mb, int nb, int bsiz,
                            int lm, int ln, int i, int j, int m, int n, int p, int q,
                            void* (*get_blkaddr)( const MORSE_desc_t*, int, int ),
-                           int (*get_blkldd)( const MORSE_desc_t*, int ),
-                           int (*get_rankof)( const MORSE_desc_t*, int, int ))
+                           int   (*get_blkldd) ( const MORSE_desc_t*, int      ),
+                           int   (*get_rankof) ( const MORSE_desc_t*, int, int ))
 {
     MORSE_context_t *morse;
+    MORSE_desc_t *desc;
     int status;
 
+    *descptr = NULL;
+
     morse = morse_context_self();
     if (morse == NULL) {
-        morse_error("MORSE_Desc_Create", "MORSE not initialized");
+        morse_error("MORSE_Desc_Create_User", "MORSE not initialized");
         return MORSE_ERR_NOT_INITIALIZED;
     }
+
     /* Allocate memory and initialize the descriptor */
-    *desc = (MORSE_desc_t*)malloc(sizeof(MORSE_desc_t));
-    if (*desc == NULL) {
-        morse_error("MORSE_Desc_Create", "malloc() failed");
+    desc = (MORSE_desc_t*)malloc(sizeof(MORSE_desc_t));
+    if (desc == NULL) {
+        morse_error("MORSE_Desc_Create_User", "malloc() failed");
         return MORSE_ERR_OUT_OF_RESOURCES;
     }
-    **desc = morse_desc_init_user(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q,
-        get_blkaddr, get_blkldd, get_rankof);
+
+    *desc = morse_desc_init_user(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q,
+                                 get_blkaddr, get_blkldd, get_rankof);
 
     /* if the user gives a pointer to the overall data (tiles) we can use it */
-    (**desc).use_mat = (mat == NULL) ? 0 : 1;
+    desc->use_mat = (mat == NULL) ? 0 : 1;
 
-    /* memory of the matrix is handle by users */
-    (**desc).alloc_mat = 0;
+    /* memory of the matrix is handled by the user */
+    desc->alloc_mat = 0;
 
     /* users data can have multiple forms: let him register tiles */
-    (**desc).register_mat = 0;
+    desc->register_mat = 0;
+
+    desc->mat = mat;
+
+    /* Create runtime specific structure like registering data */
+    RUNTIME_desc_create( desc );
+
+    status = morse_desc_check( desc );
+    if (status != MORSE_SUCCESS) {
+        morse_error("MORSE_Desc_Create_User", "invalid descriptor");
+        MORSE_Desc_Destroy( &desc );
+        return status;
+    }
+
+    *descptr = desc;
+    return MORSE_SUCCESS;
+}
+
+/**
+ *****************************************************************************
+ *
+ * @ingroup Descriptor
+ *
+ *  MORSE_Desc_Create_OOC_User - Create matrix descriptor for tiled matrix which
+ *  may not fit memory.
+ *
+ ******************************************************************************
+ *
+ * @param[out] desc
+ *          On exit, descriptor of the matrix.
+ *
+ * @param[in] dtyp
+ *          Data type of the matrix:
+ *          @arg MorseRealFloat:     single precision real (S),
+ *          @arg MorseRealDouble:    double precision real (D),
+ *          @arg MorseComplexFloat:  single precision complex (C),
+ *          @arg MorseComplexDouble: double precision complex (Z).
+ *
+ * @param[in] nb
+ *          Number of rows and columns in a tile.
+ *
+ * @param[in] m
+ *          Number of rows of the entire matrix.
+ *
+ * @param[in] n
+ *          Number of columns of the entire matrix.
+ *
+ * @param[in] p
+ *          2d-block cyclic partitioning, number of tiles in rows.
+ *
+ * @param[in] q
+ *          2d-block cyclic partitioning, number of tiles in columns.
+ *
+ * @param[in] (*get_rankof)( const MORSE_desc_t *A, int m, int n)
+ *          A function that return the MPI rank of the tile A(m,n).
+ *
+ ******************************************************************************
+ *
+ * @return
+ *          \retval MORSE_SUCCESS successful exit
+ *
+ *****************************************************************************/
+int MORSE_Desc_Create_OOC_User(MORSE_desc_t **descptr, MORSE_enum dtyp, int mb, int nb, int bsiz,
+                               int lm, int ln, int i, int j, int m, int n, int p, int q,
+                               int (*get_rankof)( const MORSE_desc_t*, int, int ))
+{
+#if !defined (CHAMELEON_SCHED_STARPU)
+    morse_error("MORSE_Desc_Create_OOC_User", "Only StarPU supports on-demand tile allocation");
+    return MORSE_ERR_NOT_INITIALIZED;
+#else
+    MORSE_context_t *morse;
+    MORSE_desc_t *desc;
+    int status;
 
-    (**desc).mat = mat;
+    *descptr = NULL;
+
+    morse = morse_context_self();
+    if (morse == NULL) {
+        morse_error("MORSE_Desc_Create_OOC_User", "MORSE not initialized");
+        return MORSE_ERR_NOT_INITIALIZED;
+    }
+    /* Allocate memory and initialize the descriptor */
+    desc = (MORSE_desc_t*)malloc(sizeof(MORSE_desc_t));
+    if (desc == NULL) {
+        morse_error("MORSE_Desc_Create_OOC_User", "malloc() failed");
+        return MORSE_ERR_OUT_OF_RESOURCES;
+    }
+    *desc = morse_desc_init_user(dtyp, mb, nb, bsiz, lm, ln, i, j, m, n, p, q,
+                                 morse_getaddr_null, NULL, get_rankof);
+
+    /* memory of the matrix is completely handled by runtime */
+    desc->use_mat      = 0;
+    desc->alloc_mat    = 0;
+    desc->register_mat = 0;
+
+    desc->mat = NULL;
+    desc->ooc = 1;
 
     /* Create scheduler structure like registering data */
-    RUNTIME_desc_create( *desc );
+    RUNTIME_desc_create( desc );
 
-    status = morse_desc_check(*desc);
+    status = morse_desc_check( desc );
     if (status != MORSE_SUCCESS) {
-        morse_error("MORSE_Desc_Create", "invalid descriptor");
+        morse_error("MORSE_Desc_Create_OOC_User", "invalid descriptor");
+        MORSE_Desc_Destroy( &desc );
         return status;
     }
 
+    *descptr = desc;
     return MORSE_SUCCESS;
+#endif
 }
 
-/** ***************************************************************************
+/**
+ *****************************************************************************
+ *
+ * @ingroup Descriptor
+ *
+ *  MORSE_Desc_Create_OOC - Create matrix descriptor for tiled matrix which may
+ *  not fit memory.
+ *
+ ******************************************************************************
+ *
+ * @param[out] desc
+ *          On exit, descriptor of the matrix.
+ *
+ * @param[in] dtyp
+ *          Data type of the matrix:
+ *          @arg MorseRealFloat:     single precision real (S),
+ *          @arg MorseRealDouble:    double precision real (D),
+ *          @arg MorseComplexFloat:  single precision complex (C),
+ *          @arg MorseComplexDouble: double precision complex (Z).
+ *
+ * @param[in] nb
+ *          Number of rows and columns in a tile.
+ *
+ * @param[in] m
+ *          Number of rows of the entire matrix.
+ *
+ * @param[in] n
+ *          Number of columns of the entire matrix.
+ *
+ * @param[in] p
+ *          2d-block cyclic partitioning, number of tiles in rows.
+ *
+ * @param[in] q
+ *          2d-block cyclic partitioning, number of tiles in columns.
+ *
+ ******************************************************************************
+ *
+ * @return
+ *          \retval MORSE_SUCCESS successful exit
+ *
+ *****************************************************************************/
+int MORSE_Desc_Create_OOC(MORSE_desc_t **descptr, MORSE_enum dtyp, int mb, int nb, int bsiz,
+                          int lm, int ln, int i, int j, int m, int n, int p, int q)
+{
+    return MORSE_Desc_Create_OOC_User( descptr, dtyp, mb, nb, bsiz,
+                                       lm, ln, i, j, m, n, p, q,
+                                       morse_getrankof_2d );
+}
+
+/**
+ *****************************************************************************
  *
  * @ingroup Descriptor
  *
@@ -516,7 +744,8 @@ int MORSE_Desc_Destroy(MORSE_desc_t **desc)
     return MORSE_SUCCESS;
 }
 
-/** ***************************************************************************
+/**
+ *****************************************************************************
  *
  * @ingroup Descriptor
  *
@@ -535,10 +764,11 @@ int MORSE_Desc_Destroy(MORSE_desc_t **desc)
  *
  *****************************************************************************/
 int MORSE_Desc_Acquire (MORSE_desc_t  *desc) {
-  return RUNTIME_desc_acquire( desc );
+    return RUNTIME_desc_acquire( desc );
 }
 
-/** ***************************************************************************
+/**
+ *****************************************************************************
  *
  * @ingroup Descriptor
  *
@@ -558,10 +788,11 @@ int MORSE_Desc_Acquire (MORSE_desc_t  *desc) {
  *
  *****************************************************************************/
 int MORSE_Desc_Release (MORSE_desc_t  *desc) {
-  return RUNTIME_desc_release( desc );
+    return RUNTIME_desc_release( desc );
 }
 
-/** ***************************************************************************
+/**
+ *****************************************************************************
  *
  * @ingroup Descriptor
  *
@@ -580,17 +811,18 @@ int MORSE_Desc_Release (MORSE_desc_t  *desc) {
  *
  *****************************************************************************/
 int MORSE_Desc_Getoncpu(MORSE_desc_t  *desc) {
-  return RUNTIME_desc_getoncpu( desc );
+    return RUNTIME_desc_getoncpu( desc );
 }
 
-/** ***************************************************************************
+/**
+ *****************************************************************************
  *
  * @ingroup Descriptor
  *
  *  MORSE_user_tag_size - Set the sizes for the MPI tags
- *  Default value: tag_width=31, tag_sep=24, meaning that the MPI tag is stored in 31 bits,
- *  with 24 bits for the tile tag and 7 for the descriptor.
- *  This function must be called before any descriptor creation.
+ *  Default value: tag_width=31, tag_sep=24, meaning that the MPI tag is stored
+ *  in 31 bits, with 24 bits for the tile tag and 7 for the descriptor.  This
+ *  function must be called before any descriptor creation.
  *
  ******************************************************************************
  *
@@ -607,6 +839,6 @@ int MORSE_Desc_Getoncpu(MORSE_desc_t  *desc) {
  *
  *****************************************************************************/
 void MORSE_user_tag_size(int user_tag_width, int user_tag_sep) {
-  RUNTIME_user_tag_size(user_tag_width, user_tag_sep);
-  return;
+    RUNTIME_user_tag_size(user_tag_width, user_tag_sep);
+    return;
 }
diff --git a/control/descriptor.h b/control/descriptor.h
index 7d1cb20577e03e7c25e45a93f2253d295130f784..0d3d2173bd130d2dea2722eda16b2d4ffb56231b 100644
--- a/control/descriptor.h
+++ b/control/descriptor.h
@@ -41,6 +41,7 @@ extern "C" {
 inline static void* morse_geteltaddr(const MORSE_desc_t *A, int m, int n, int eltsize);
 inline static void* morse_getaddr_cm    (const MORSE_desc_t *A, int m, int n);
 inline static void* morse_getaddr_ccrb  (const MORSE_desc_t *A, int m, int n);
+inline static void* morse_getaddr_null  (const MORSE_desc_t *A, int m, int n);
 inline static int   morse_getblkldd_cm  (const MORSE_desc_t *A, int m);
 inline static int   morse_getblkldd_ccrb(const MORSE_desc_t *A, int m);
 
@@ -120,6 +121,15 @@ inline static void *morse_getaddr_cm(const MORSE_desc_t *A, int m, int n)
     return (void*)((intptr_t)A->mat + (offset*eltsize) );
 }
 
+/*******************************************************************************
+ *  Internal function to return address of block (m,n) with m,n = block indices
+ *  This version lets the runtime allocate on-demand.
+ **/
+inline static void *morse_getaddr_null(const MORSE_desc_t *A, int m, int n)
+{
+    return NULL;
+}
+
 /*******************************************************************************
  *  Internal function to return address of element A(m,n) with m,n = matrix indices
  **/
diff --git a/docs/texinfo/chapters/configuration.texi b/docs/texinfo/chapters/configuration.texi
index a147cf1f9cdfee0626d03a279d62a2f8daadb745..d57a476a99607ec8b487539c8af94afac8a945ae 100644
--- a/docs/texinfo/chapters/configuration.texi
+++ b/docs/texinfo/chapters/configuration.texi
@@ -344,3 +344,26 @@ Database of models is subject to change, it should be enrich in a near future.
 
 One can additionally decide to enable the magma kernels by setting the cmake
 option @option{-DCHAMELEON_SIMULATION_MAGMA=ON} .
+
+@node Use out of core support with StarPU
+@section Use out of core support with StarPU
+
+If the matrix can not fit in the main memory, StarPU can automatically evict
+tiles to the disk. The following variables need to be set:
+@itemize @bullet
+@item @env{STARPU_DISK_SWAP} environment variable to a place where to store
+evicted tiles, for example:
+  @example
+  @env{STARPU_DISK_SWAP}=/tmp
+  @end example
+@item @env{STARPU_DISK_SWAP_BACKEND} environment variable to the I/O method,
+for example:
+  @example
+  @env{STARPU_DISK_SWAP_BACKEND}=unistd_o_direct
+  @end example
+@item @env{STARPU_LIMIT_CPU_MEM} environment variable to the amount of memory
+that can be used in MBytes, for example:
+  @example
+  @env{STARPU_LIMIT_CPU_MEM}=1000
+  @end example
+@end itemize
diff --git a/docs/texinfo/chapters/using.texi b/docs/texinfo/chapters/using.texi
index 47bf96ddf5a6e25c14fc9cb4225c3a391865649f..4cfd8e6626b79a17baaf587765ffbeb527fb5cf0 100644
--- a/docs/texinfo/chapters/using.texi
+++ b/docs/texinfo/chapters/using.texi
@@ -435,6 +435,9 @@ This can be achieved from different ways.
 @item Use the existing function @code{MORSE_Desc_Create}: means the
 matrix data are considered contiguous in memory as it is considered in PLASMA
 (@ref{Tile Data Layout}).
+@item Use the existing function @code{MORSE_Desc_Create_OOC}: means the
+matrix data is allocated on-demand in memory tile by tile, and possibly pushed
+to disk if that does not fit memory.
 @item Use the existing function @code{MORSE_Desc_Create_User}: it is more
 flexible than @code{Desc_Create} because you can give your own way to access to
 tile data so that your tiles can be allocated wherever you want in memory, see
diff --git a/example/out_of_core/out_of_core.h b/example/out_of_core/out_of_core.h
index dcb9e970292bb2ec1ca5c803b69fb42bcbf8454e..95a25dcbcf149999e1ad5046a7f03ea783c97406 100644
--- a/example/out_of_core/out_of_core.h
+++ b/example/out_of_core/out_of_core.h
@@ -260,13 +260,4 @@ print_o_direct_wont_work(void) {
                     "multiples of 4096. Tip : chose 'n' and 'nb' as both multiples of 32.\n");
 }
 
-/******************************************************************************
- *  Ffunction to return address of block (m,n) -> here NULL because memory is
- *  directly handled by StarPU
- **/
-inline static void* morse_getaddr_null(const MORSE_desc_t *A, int m, int n)
-{
-    return (void*)( NULL );
-}
-
 #endif /* OOC_H */
diff --git a/include/morse.h.in b/include/morse.h.in
index 9473b6e1cb8754b10e636f725ce5a550fae62586..b0460b6950bfbf8c3f5967742c730421143cec7b 100644
--- a/include/morse.h.in
+++ b/include/morse.h.in
@@ -90,6 +90,13 @@ int MORSE_Desc_Create_User(MORSE_desc_t **desc, void *mat, MORSE_enum dtyp, int
                            void* (*get_blkaddr)( const MORSE_desc_t*, int, int ),
                            int (*get_blkldd)( const MORSE_desc_t*, int ),
                            int (*get_rankof)( const MORSE_desc_t*, int, int ));
+int MORSE_Desc_Create_OOC(MORSE_desc_t **desc, MORSE_enum dtyp,
+                          int mb, int nb, int bsiz, int lm, int ln,
+                          int i, int j, int m, int n, int p, int q);
+int MORSE_Desc_Create_OOC_User(MORSE_desc_t **desc, MORSE_enum dtyp,
+                               int mb, int nb, int bsiz, int lm, int ln,
+                               int i, int j, int m, int n, int p, int q,
+                               int (*get_rankof)( const MORSE_desc_t*, int, int ));
 int MORSE_Desc_Destroy (MORSE_desc_t **desc);
 int MORSE_Desc_Acquire (MORSE_desc_t  *desc);
 int MORSE_Desc_Release (MORSE_desc_t  *desc);
diff --git a/include/morse_struct.h b/include/morse_struct.h
index f307645d27a6b5ab39cbc36963b8dee547409cd3..2aacefcdf501d36326ba63fbc2081400fae2af65 100644
--- a/include/morse_struct.h
+++ b/include/morse_struct.h
@@ -108,6 +108,7 @@ struct morse_desc_s {
     int alloc_mat;    // 1 if we handle the allocation of mat - else 0
     int register_mat; // 1 if we have to register mat - else 0 (handled by the application)
     int myrank;       // MPI rank of the descriptor
+    int ooc;          // 1 if the matrix is not to fit in memory
     void *schedopt;   // scheduler (QUARK|StarPU) specific structure
 };
 
diff --git a/runtime/starpu/control/runtime_descriptor.c b/runtime/starpu/control/runtime_descriptor.c
index 3f6a1e28502f67435c3ce7446f175a9e3d120805..62b84a75286729194f2037807fd2405ad2ca11e6 100644
--- a/runtime/starpu/control/runtime_descriptor.c
+++ b/runtime/starpu/control/runtime_descriptor.c
@@ -22,6 +22,7 @@
  *
  **/
 #include <stdlib.h>
+#include <unistd.h>
 #include "runtime/starpu/include/morse_starpu.h"
 
 #if defined(CHAMELEON_USE_MPI)
@@ -118,6 +119,21 @@ void RUNTIME_desc_create( MORSE_desc_t *desc )
         }
     }
 #endif
+    if (desc->ooc) {
+        int lastmm = desc->lm - (desc->lmt-1) * desc->mb;
+        int lastnn = desc->ln - (desc->lnt-1) * desc->nb;
+        int64_t eltsze = MORSE_Element_Size(desc->dtyp);
+        int pagesize = getpagesize();
+
+        if ((desc->mb * desc->nb * eltsze) % pagesize != 0
+         || (lastmm   * desc->nb * eltsze) % pagesize != 0
+         || (desc->mb * lastnn   * eltsze) % pagesize != 0
+         || (lastmm   * lastnn   * eltsze) % pagesize != 0)
+        {
+            morse_error("RUNTIME_desc_create", "Matrix and tile size not suitable for out-of-core: all tiles have to be multiples of 4096. Tip : choose 'n' and 'nb' as both multiples of 32.");
+            return;
+        }
+    }
 
 #if defined(CHAMELEON_USE_MPI)
     /*
@@ -279,6 +295,10 @@ int RUNTIME_desc_getoncpu( MORSE_desc_t *desc )
     int lnt = desc->lnt;
     int m, n;
 
+    if (desc->ooc)
+        /* May not even fit */
+        return MORSE_SUCCESS;
+
     for (n = 0; n < lnt; n++)
         for (m = 0; m < lmt; m++)
         {
diff --git a/timing/timing.c b/timing/timing.c
index d271202961ae3c3200abd8aa1d7a61efdf7b8c19..d2b73d49b7963115401402b1c94957f8c5b2c5f9 100644
--- a/timing/timing.c
+++ b/timing/timing.c
@@ -475,6 +475,7 @@ main(int argc, char *argv[]) {
     iparam[IPARAM_TRACE         ] = 0;
     iparam[IPARAM_DAG           ] = 0;
     iparam[IPARAM_ASYNC         ] = 1;
+    iparam[IPARAM_OOC           ] = 0;
     iparam[IPARAM_MX            ] = -1;
     iparam[IPARAM_NX            ] = -1;
     iparam[IPARAM_RHBLK         ] = 0;
@@ -549,6 +550,10 @@ main(int argc, char *argv[]) {
             iparam[IPARAM_ASYNC] = 0;
         } else if (startswith( argv[i], "--async" )) {
             iparam[IPARAM_ASYNC] = 1;
+        } else if (startswith( argv[i], "--ooc" )) {
+            iparam[IPARAM_OOC] = 1;
+        } else if (startswith( argv[i], "--noooc" )) {
+            iparam[IPARAM_OOC] = 0;
         } else if (startswith( argv[i], "--n_range=" )) {
             get_range( strchr( argv[i], '=' ) + 1, &start, &stop, &step );
         } else if (startswith( argv[i], "--m=" )) {
diff --git a/timing/timing.h b/timing/timing.h
index 3d33748a61ec65e73fc2f4e5e5410d9e5e15a04e..1b4bacb354e3613422833eaddeb9650202bb0055 100644
--- a/timing/timing.h
+++ b/timing/timing.h
@@ -38,6 +38,7 @@ enum iparam_timing {
     IPARAM_TRACE,          /* Generate trace on the first non warmup run */
     IPARAM_DAG,            /* Do we require to output the DOT file?      */
     IPARAM_ASYNC,          /* Asynchronous calls                         */
+    IPARAM_OOC,            /* Out of Core                                */
     IPARAM_MX,             /* */
     IPARAM_NX,             /* */
     IPARAM_RHBLK,          /* Householder reduction parameter for QR/LQ  */
@@ -97,6 +98,7 @@ enum dparam_timing {
     int64_t MT    = (M%MB==0) ? (M/MB) : (M/MB+1); \
     int64_t NT    = (N%NB==0) ? (N/NB) : (N/NB+1); \
     int bigmat     = iparam[IPARAM_BIGMAT];         \
+    int ooc       = iparam[IPARAM_OOC];            \
     int check     = iparam[IPARAM_CHECK];          \
     int loud      = iparam[IPARAM_VERBOSE];        \
     (void)M;(void)N;(void)K;(void)NRHS;            \
@@ -107,15 +109,18 @@ enum dparam_timing {
 /* Paste code to allocate a matrix in desc if cond_init is true */
 #define PASTE_CODE_ALLOCATE_MATRIX_TILE(_desc_, _cond_, _type_, _type2_, _lda_, _m_, _n_) \
     MORSE_desc_t *_desc_ = NULL;                                        \
-    int status ## _desc_ ; \
+    int status ## _desc_ ;                                              \
     if( _cond_ ) {                                                      \
-       if (!bigmat) \
-           status ## _desc_ = MORSE_Desc_Create_User(&(_desc_), NULL, _type2_, MB, NB, MB*NB, _lda_, _n_, 0, 0, _m_, _n_, \
-                          P, Q, morse_getaddr_null, NULL, NULL);\
-       else \
-           status ## _desc_ = MORSE_Desc_Create(&(_desc_), NULL, _type2_, MB, NB, MB*NB, _lda_, _n_, 0, 0, _m_, _n_, \
-                    P, Q);\
-        if (status ## _desc_ != MORSE_SUCCESS) return (status ## _desc_);          \
+        if (ooc)                                                        \
+            status ## _desc_ = MORSE_Desc_Create_OOC(&(_desc_), _type2_, MB, NB, MB*NB, _lda_, _n_, 0, 0, _m_, _n_, \
+                                                     P, Q);             \
+        else if (!bigmat)                                               \
+            status ## _desc_ = MORSE_Desc_Create_User(&(_desc_), NULL, _type2_, MB, NB, MB*NB, _lda_, _n_, 0, 0, _m_, _n_, \
+                                                      P, Q, morse_getaddr_null, NULL, NULL); \
+        else                                                            \
+            status ## _desc_ = MORSE_Desc_Create(&(_desc_), NULL, _type2_, MB, NB, MB*NB, _lda_, _n_, 0, 0, _m_, _n_, \
+                                                 P, Q);                 \
+        if (status ## _desc_ != MORSE_SUCCESS) return (status ## _desc_); \
     }
 
 #define PASTE_CODE_FREE_MATRIX(_desc_)                                  \