]> Zhao Yanbai Git Server - minix.git/commitdiff
sef: Extensions for new RS. 98/3098/2
authorCristiano Giuffrida <giuffrida@cs.vu.nl>
Tue, 30 Sep 2014 05:15:41 +0000 (07:15 +0200)
committerDavid van Moolenbroek <david@minix3.org>
Wed, 16 Sep 2015 15:30:34 +0000 (15:30 +0000)
Change-Id: I89b6f8015b1f9c46bf98694450bdaa80b7777940

minix/include/minix/sef.h
minix/lib/libsys/Makefile
minix/lib/libsys/sef.c
minix/lib/libsys/sef_init.c
minix/lib/libsys/sef_liveupdate.c
minix/lib/libsys/sef_llvm.c [new file with mode: 0644]
minix/lib/libsys/sef_st.c [new file with mode: 0644]
minix/servers/rs/utility.c
minix/servers/vm/utility.c

index 8da2bd8a7f904cee7a8906008368a382e3a35526..28a63b903bc1c45d59995467eeaff05ae2a1e5bd 100644 (file)
@@ -11,6 +11,8 @@ int sef_receive_status(endpoint_t src, message *m_ptr, int *status_ptr);
 endpoint_t sef_self(void);
 void sef_cancel(void);
 void __dead sef_exit(int status);
+int sef_getrndseed (void);
+int sef_munmap(void *addrstart, vir_bytes len, int type);
 #define sef_receive(src, m_ptr) sef_receive_status(src, m_ptr, NULL)
 
 /* SEF global definitions. */
@@ -46,6 +48,7 @@ typedef struct {
     void* init_buff_start;
     void* init_buff_cleanup_start;
     size_t init_buff_len;
+    int copy_flags;
 } sef_init_info_t;
 
 /* Callback type definitions. */
@@ -65,6 +68,10 @@ int sef_cb_init_response_null(message *m_ptr);
 int sef_cb_init_fail(int type, sef_init_info_t *info);
 int sef_cb_init_reset(int type, sef_init_info_t *info);
 int sef_cb_init_crash(int type, sef_init_info_t *info);
+int sef_cb_init_timeout(int type, sef_init_info_t *info);
+int sef_cb_init_identity_state_transfer(int type, sef_init_info_t *info);
+int sef_cb_init_lu_identity_as_restart(int type, sef_init_info_t *info);
+int sef_cb_init_lu_generic(int type, sef_init_info_t *info);
 int sef_cb_init_response_rs_reply(message *m_ptr);
 
 /* Macros for predefined callback implementations. */
@@ -175,10 +182,12 @@ int sef_cb_lu_response_null(message *m_ptr);
 int sef_cb_lu_prepare_always_ready(int state);
 int sef_cb_lu_prepare_never_ready(int state);
 int sef_cb_lu_prepare_crash(int state);
+int sef_cb_lu_prepare_eval(int state);
 int sef_cb_lu_state_isvalid_standard(int state, int flags);
 int sef_cb_lu_state_isvalid_workfree(int state, int flags);
 int sef_cb_lu_state_isvalid_workfree_self(int state, int flags);
 int sef_cb_lu_state_isvalid_generic(int state, int flags);
+void sef_cb_lu_state_dump_eval(int state);
 int sef_cb_lu_response_rs_reply(message *m_ptr);
 
 /* Macros for predefined callback implementations. */
@@ -316,6 +325,49 @@ void sef_setcb_gcov(sef_cb_gcov_t cb);
 /* Fault injection tool support. */
 #define SEF_FI_ALLOW_EDFI               1
 
+/*===========================================================================*
+ *                          SEF State Transfer                               *
+ *===========================================================================*/
+#define SEF_LU_STATE_EVAL_MAX_LEN          512
+
+/* State transfer helpers. */
+int sef_copy_state_region_ctl(sef_init_info_t *info,
+    vir_bytes *src_address, vir_bytes *dst_address);
+int sef_copy_state_region(sef_init_info_t *info,
+    vir_bytes address, size_t size, vir_bytes dst_address);
+int sef_st_state_transfer(sef_init_info_t *info);
+
+/* Callback prototypes to be passed to the State Transfer framwork. */
+int sef_old_state_table_lookup(sef_init_info_t *info, void *addr);
+int sef_old_state_table_lookup_opaque(void *info_opaque, void *addr);
+int sef_copy_state_region_opaque(void *info_opaque, uint32_t address,
+    size_t size, uint32_t dst_address);
+
+/* Debug. */
+#define SEF_ST_DEBUG_DEFAULT           0
+
+#ifndef SEF_ST_DEBUG
+#define SEF_ST_DEBUG                    SEF_ST_DEBUG_DEFAULT
+#endif
+
+/*===========================================================================*
+ *                               SEF LLVM                                    *
+ *===========================================================================*/
+/* LLVM helpers. */
+int sef_llvm_magic_enabled(void);
+int sef_llvm_real_brk(char *newbrk);
+int sef_llvm_state_cleanup(void);
+void sef_llvm_dump_eval(char *expr);
+int sef_llvm_eval_bool(char *expr, char *result);
+void *sef_llvm_state_table_addr(void);
+size_t sef_llvm_state_table_size(void);
+void sef_llvm_stack_refs_save(char *stack_buff);
+void sef_llvm_stack_refs_restore(char *stack_buff);
+int sef_llvm_state_transfer(sef_init_info_t *info);
+
+int sef_llvm_ltckpt_enabled(void);
+int sef_llvm_get_ltckpt_offset(void);
+
 #if !defined(USE_LIVEUPDATE)
 #undef INTERCEPT_SEF_LU_REQUESTS
 #undef SEF_LU_DEBUG
index a73c58c8925c023ff19d1906496600b1f7bd5f2a..cb6874f5b3a351e434a8bdd54d33e04dc38f2bbd 100644 (file)
@@ -43,8 +43,10 @@ SRCS+=  \
        sef_fi.c \
        sef_init.c \
        sef_liveupdate.c \
+       sef_llvm.c \
        sef_ping.c \
        sef_signal.c \
+       sef_st.c \
        sqrt_approx.c \
        srv_fork.c \
        srv_kill.c \
@@ -139,5 +141,6 @@ CPPFLAGS+= -DUSE_SYSDEBUG
 .endif
 
 CPPFLAGS.sched_start.c+=       -I${NETBSDSRCDIR}/minix
+CPPFLAGS.sef_st.c+=            -I${NETBSDSRCDIR}/minix
 
 .include <bsd.lib.mk>
index d61639dd0c2ab6b21c5ba55739ae7f609eea578e..9d385f9ca8997e98eb7698a45eaad01eb7a51948 100644 (file)
@@ -1,6 +1,9 @@
 #include "syslib.h"
 #include <assert.h>
 #include <minix/sysutil.h>
+#include <minix/rs.h>
+#include <minix/timers.h>
+#include <minix/endpoint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #define SEF_SELF_NAME_MAXLEN 20
 char sef_self_name[SEF_SELF_NAME_MAXLEN];
 endpoint_t sef_self_endpoint = NONE;
+endpoint_t sef_self_proc_nr;
 int sef_self_priv_flags;
-int sef_self_first_receive_done;
+int sef_self_init_flags;
 int sef_self_receiving;
 
+/* Extern variables. */
+EXTERN int sef_lu_state;
+EXTERN int __sef_st_before_receive_enabled;
+
 /* Debug. */
 #if SEF_INIT_DEBUG || SEF_LU_DEBUG || SEF_PING_DEBUG || SEF_SIGNAL_DEBUG
-#define SEF_DEBUG_HEADER_MAXLEN 32
+#define SEF_DEBUG_HEADER_MAXLEN 50
 static int sef_debug_init = 0;
 static time_t sef_debug_boottime = 0;
 static u32_t sef_debug_system_hz = 0;
@@ -41,6 +49,9 @@ EXTERN int do_sef_lu_request(message *m_ptr);
 /* SEF Signal prototypes. */
 EXTERN int do_sef_signal_request(message *m_ptr);
 
+/* State transfer prototypes. */
+EXTERN void do_sef_st_before_receive(void);
+
 /* SEF GCOV prototypes. */
 #ifdef USE_COVERAGE
 EXTERN int do_sef_gcov_request(message *m_ptr);
@@ -67,8 +78,15 @@ void sef_startup()
   if ( r != OK) {
       panic("sef_startup: sys_whoami failed: %d\n", r);
   }
+
+  sef_self_proc_nr = _ENDPOINT_P(sef_self_endpoint);
   sef_self_priv_flags = priv_flags;
+  sef_self_init_flags = init_flags;
+  sef_lu_state = SEF_LU_STATE_NULL;
   old_endpoint = NONE;
+  if(init_flags & SEF_LU_NOMMAP) {
+      sys_upd_flags |= SF_VM_NOMMAP;
+  }
 
 #if USE_LIVEUPDATE
   /* RS may wake up with the wrong endpoint, perfom the update in that case. */
@@ -117,8 +135,9 @@ void sef_startup()
 #endif
 
   /* (Re)initialize SEF variables. */
-  sef_self_first_receive_done = FALSE;
   sef_self_priv_flags = priv_flags;
+  sef_self_init_flags = init_flags;
+  sef_lu_state = SEF_LU_STATE_NULL;
 }
 
 /*===========================================================================*
@@ -140,13 +159,19 @@ int sef_receive_status(endpoint_t src, message *m_ptr, int *status_ptr)
 
 #if INTERCEPT_SEF_LU_REQUESTS
       /* Handle SEF Live update before receive events. */
-      do_sef_lu_before_receive();
+      if(sef_lu_state != SEF_LU_STATE_NULL) {
+          do_sef_lu_before_receive();
+      }
+
+      /* Handle State transfer before receive events. */
+      if(__sef_st_before_receive_enabled) {
+          do_sef_st_before_receive();
+      }
 #endif
 
       /* Receive and return in case of error. */
       r = ipc_receive(src, m_ptr, &status);
       if(status_ptr) *status_ptr = status;
-      if(!sef_self_first_receive_done) sef_self_first_receive_done = TRUE;
       if(r != OK) {
           return r;
       }
@@ -271,6 +296,16 @@ void sef_cancel(void)
   sef_self_receiving = FALSE;
 }
 
+/*===========================================================================*
+ *                              sef_getrndseed                              *
+ *===========================================================================*/
+int sef_getrndseed(void)
+{
+    clock_t uptime;
+    sys_times(SELF, NULL, NULL, &uptime, NULL);
+    return (int) uptime;
+}
+
 /*===========================================================================*
  *                               sef_exit                                   *
  *===========================================================================*/
@@ -293,6 +328,24 @@ __weak_alias(_exit, sef_exit);
 __weak_alias(__exit, sef_exit);
 #endif
 
+/*===========================================================================*
+ *                                sef_munmap                                 *
+ *===========================================================================*/
+int sef_munmap(void *addrstart, vir_bytes len, int type)
+{
+/* System services use a special version of munmap() to control implicit
+ * munmaps as startup and allow for asynchronous mnmap for VM.
+ */
+  message m;
+  m.m_type = type;
+  m.VMUM_ADDR = addrstart;
+  m.VMUM_LEN = len;
+  if(sef_self_endpoint == VM_PROC_NR) {
+      return asynsend3(SELF, &m, AMF_NOREPLY);
+  }
+  return _syscall(VM_PROC_NR, type, &m);
+}
+
 #if SEF_INIT_DEBUG || SEF_LU_DEBUG || SEF_PING_DEBUG || SEF_SIGNAL_DEBUG
 /*===========================================================================*
  *                         sef_debug_refresh_params                         *
index 23cf5cf7d63469def9476feb6992eae859756501..876e35f45c523cea2d33dfddb5f4eaecbf2b2b19 100644 (file)
@@ -27,6 +27,11 @@ EXTERN char* sef_debug_header(void);
 /* Information about SELF. */
 EXTERN endpoint_t sef_self_endpoint;
 EXTERN endpoint_t sef_self_priv_flags;
+EXTERN endpoint_t sef_self_init_flags;
+
+#ifndef ST_STACK_REFS_BUFF_SIZE
+#define ST_STACK_REFS_BUFF_SIZE           1024
+#endif
 
 /*===========================================================================*
  *                              process_init                                *
@@ -34,33 +39,71 @@ EXTERN endpoint_t sef_self_priv_flags;
 static int process_init(int type, sef_init_info_t *info)
 {
 /* Process initialization. */
-  int r, result;
+  int r, result, debug_result_found, is_def_cb;
+  cp_grant_id_t gid;
   message m;
 
   /* Debug. */
 #if SEF_INIT_DEBUG
   sef_init_debug_begin();
-  sef_init_dprint("%s. Got a SEF Init request of type: %d. About to init.\n",
-      sef_debug_header(), type);
+  sef_init_dprint("%s. Got a SEF Init request of type %d, flags 0x%08x, rproctab_gid %d, ep %d, old ep %d, restarts %d. About to init.\n",
+      sef_debug_header(), type, info->flags, info->rproctab_gid, info->endpoint, info->old_endpoint, info->restarts);
   sef_init_debug_end();
 #endif
 
-  /* Let the callback code handle the specific initialization type. */
-  switch(type) {
-      case SEF_INIT_FRESH:
-          result = sef_init_cbs.sef_cb_init_fresh(type, info);
-      break;
-      case SEF_INIT_LU:
-          result = sef_init_cbs.sef_cb_init_lu(type, info);
-      break;
-      case SEF_INIT_RESTART:
-          result = sef_init_cbs.sef_cb_init_restart(type, info);
-      break;
+  /* Clear any IPC filter. */
+  r = sys_statectl(SYS_STATE_CLEAR_IPC_FILTERS, 0, 0);
+  assert(r == OK);
+
+  /* Create grant for state transfer. */
+  gid = cpf_grant_direct(sef_self_endpoint, 0, ULONG_MAX, CPF_READ);
+  if(!GRANT_VALID(gid)) {
+      panic("unable to create grant for state transfer");
+  }
+  if(gid != SEF_STATE_TRANSFER_GID) {
+      panic("bad state transfer gid");
+  }
+
+  /* If debug init flags are allowed, process them first. */
+  debug_result_found = 0;
+  if(SEF_INIT_ALLOW_DEBUG_INIT_FLAGS) {
+      int flags = info->flags;
+      if(flags & SEF_INIT_CRASH) {
+          result = sef_cb_init_crash(type, info);
+          debug_result_found = 1;
+      }
+      else if(flags & SEF_INIT_FAIL) {
+          result = sef_cb_init_fail(type, info);
+          debug_result_found = 1;
+      }
+      else if(flags & SEF_INIT_TIMEOUT) {
+          result = sef_cb_init_timeout(type, info);
+          debug_result_found = 1;
+      }
+  }
 
-      default:
-          /* Not a valid SEF init type. */
-          result = EINVAL;
-      break;
+  if(!debug_result_found) {
+      /* Let the callback code handle the specific initialization type. */
+      is_def_cb = info->flags & SEF_INIT_DEFCB;
+      switch(type) {
+          case SEF_INIT_FRESH:
+              result = is_def_cb ? SEF_CB_INIT_FRESH_DEFAULT(type, info)
+                                 : sef_init_cbs.sef_cb_init_fresh(type, info);
+          break;
+          case SEF_INIT_LU:
+              result = is_def_cb ? SEF_CB_INIT_LU_DEFAULT(type, info)
+                                 : sef_init_cbs.sef_cb_init_lu(type, info);
+          break;
+          case SEF_INIT_RESTART:
+              result = is_def_cb ? SEF_CB_INIT_RESTART_DEFAULT(type, info)
+                                 : sef_init_cbs.sef_cb_init_restart(type, info);
+          break;
+
+          default:
+              /* Not a valid SEF init type. */
+              result = EINVAL;
+          break;
+      }
   }
 
   memset(&m, 0, sizeof(m));
@@ -68,6 +111,31 @@ static int process_init(int type, sef_init_info_t *info)
   m.m_type = RS_INIT;
   m.m_rs_init.result = result;
   r = sef_init_cbs.sef_cb_init_response(&m);
+  if (r != OK) {
+      return r;
+  }
+
+  /* See if we need to unmap the initialization buffer. */
+  if(info->init_buff_cleanup_start) {
+      void *addrstart = info->init_buff_cleanup_start;
+      size_t len = info->init_buff_len - (size_t)((char*)info->init_buff_cleanup_start - (char*)info->init_buff_start);
+      r = sef_munmap(addrstart, len, VM_MUNMAP);
+      if(r != OK) {
+          printf("process_init: warning: munmap failed for init buffer\n");
+      }
+  }
+
+  /* Tell the kernel about the grant table. */
+  cpf_reload();
+
+  /* Tell the kernel about the senda table. */
+  r = senda_reload();
+  if(r != OK) {
+      printf("process_init: warning: senda_reload failed\n");
+  }
+
+  /* Tell the kernel about the state table. */
+  sys_statectl(SYS_STATE_SET_STATE_TABLE, sef_llvm_state_table_addr(), 0);
 
   return r;
 }
@@ -81,6 +149,7 @@ int do_sef_rs_init(endpoint_t old_endpoint)
   int r;
   int type;
   sef_init_info_t info;
+  memset(&info, 0, sizeof(info));
 
   /* Get init parameters from SEF. */
   type = SEF_INIT_FRESH;
@@ -90,9 +159,23 @@ int do_sef_rs_init(endpoint_t old_endpoint)
   else if(sef_self_priv_flags & RST_SYS_PROC) {
       type = SEF_INIT_RESTART;
   }
-  info.rproctab_gid = -1;
+  info.flags = sef_self_init_flags;
+  info.rproctab_gid = GRANT_INVALID;
   info.endpoint = sef_self_endpoint;
   info.old_endpoint = old_endpoint;
+  info.restarts = 0;
+
+  /* Get init buffer details from VM. */
+  info.init_buff_start = NULL;
+  info.init_buff_len = 0;
+  if(type != SEF_INIT_FRESH) {
+      r = vm_memctl(RS_PROC_NR, VM_RS_MEM_GET_PREALLOC_MAP,
+          &info.init_buff_start, &info.init_buff_len);
+      if(r != OK) {
+          printf("do_sef_rs_init: vm_memctl failed\n");
+      }
+  }
+  info.init_buff_cleanup_start = info.init_buff_start;
 
   /* Peform initialization. */
   r = process_init(type, &info);
@@ -109,12 +192,18 @@ int do_sef_init_request(message *m_ptr)
   int r;
   int type;
   sef_init_info_t info;
+  memset(&info, 0, sizeof(info));
 
   /* Get init parameters from message. */
   type = m_ptr->m_rs_init.type;
+  info.flags = m_ptr->m_rs_init.flags;
   info.rproctab_gid = m_ptr->m_rs_init.rproctab_gid;
   info.endpoint = sef_self_endpoint;
   info.old_endpoint = m_ptr->m_rs_init.old_endpoint;
+  info.restarts = m_ptr->m_rs_init.restarts;
+  info.init_buff_start = (void*) m_ptr->m_rs_init.buff_addr;
+  info.init_buff_cleanup_start = info.init_buff_start;
+  info.init_buff_len = m_ptr->m_rs_init.buff_len;
 
   /* Peform initialization. */
   r = process_init(type, &info);
@@ -202,6 +291,136 @@ int sef_cb_init_crash(int UNUSED(type), sef_init_info_t *UNUSED(info))
   return OK;
 }
 
+/*===========================================================================*
+ *                          sef_cb_init_timeout                             *
+ *===========================================================================*/
+int sef_cb_init_timeout(int UNUSED(type), sef_init_info_t *UNUSED(info))
+{
+  message m;
+  int status;
+
+  printf("Simulating a timeout at initialization time...\n");
+
+  ipc_receive(IDLE, &m, &status);
+
+  return EBADCALL;
+}
+
+/*===========================================================================*
+ *                    sef_cb_init_identity_state_transfer                   *
+ *===========================================================================*/
+int sef_cb_init_identity_state_transfer(int type, sef_init_info_t *info)
+{
+  extern char *_brksize;
+  extern char *_etext;
+  int r;
+  char *old_brksize, *new_brksize;
+  char stack_buff[ST_STACK_REFS_BUFF_SIZE];
+  vir_bytes data_start;
+  size_t size;
+
+  /* Identity state transfer is for crash recovery and self update only. */
+  if(type != SEF_INIT_RESTART && (type != SEF_INIT_LU || !(info->flags & SEF_LU_SELF))) {
+      printf("sef_cb_init_identity_state_transfer: state transfer failed\n");
+      return ENOSYS;
+  }
+
+  /* Save stack refs. */
+  sef_llvm_stack_refs_save(stack_buff);
+
+  old_brksize = _brksize;
+  data_start = (vir_bytes)&_etext;
+#if SEF_ST_DEBUG
+  printf("sef_cb_init_identity_state_transfer: _brksize = 0x%08x, _etext = 0x%08x, data_start = 0x%08x\n",
+      _brksize, &_etext, data_start);
+#endif
+
+  /* Transfer data. */
+  size = (size_t)(_brksize - data_start);
+  r = sef_copy_state_region(info, data_start, size, data_start);
+  if(r != OK) {
+      printf("sef_cb_init_identity_state_transfer: data transfer failed\n");
+      return r;
+  }
+
+  new_brksize = _brksize;
+
+  /* Transfer heap if necessary. */
+  if(old_brksize != new_brksize) {
+
+#if SEF_ST_DEBUG
+      printf("sef_cb_init_identity_state_transfer: brk() for new_brksize = 0x%08x\n",
+          new_brksize);
+#endif
+
+      /* Extend heap first. */
+      _brksize = old_brksize;
+      r = sef_llvm_real_brk(new_brksize);
+      if(r != OK) {
+          printf("sef_cb_init_identity_state_transfer: brk failed\n");
+          return EFAULT;
+      }
+
+      /* Transfer state on the heap. */
+      assert(_brksize == new_brksize);
+      size = (size_t)(_brksize - old_brksize);
+      r = sef_copy_state_region(info, (vir_bytes) old_brksize, size,
+          (vir_bytes) old_brksize);
+      if(r != OK) {
+          printf("sef_cb_init_identity_state_transfer: extended heap transfer failed\n");
+          return r;
+      }
+  }
+
+  /* Restore stack refs. */
+  sef_llvm_stack_refs_restore(stack_buff);
+
+  return OK;
+}
+
+/*===========================================================================*
+ *                   sef_cb_init_lu_identity_as_restart                     *
+ *===========================================================================*/
+int sef_cb_init_lu_identity_as_restart(int type, sef_init_info_t *info)
+{
+  /* Can only handle live update. */
+  if(type != SEF_INIT_LU) {
+      printf("sef_cb_init_lu_identity_as_restart: init failed\n");
+      return ENOSYS;
+  }
+
+  /* Resort to restart callback only for identity updates, ignore other cases. */
+  if(SEF_LU_IS_IDENTITY_UPDATE(info->flags)) {
+      if(info->flags & (SEF_INIT_DEFCB|SEF_INIT_SCRIPT_RESTART)) {
+          /* Use default callback when requested or when using a script.*/
+          return SEF_CB_INIT_RESTART_DEFAULT(type, info);
+      }
+      return sef_init_cbs.sef_cb_init_restart(type, info);
+  }
+
+  return ENOSYS;
+}
+
+/*===========================================================================*
+ *                          sef_cb_init_lu_generic                          *
+ *===========================================================================*/
+int sef_cb_init_lu_generic(int type, sef_init_info_t *info)
+{
+  /* Can only handle live update. */
+  if(type != SEF_INIT_LU) {
+      printf("sef_cb_init_lu_generic: init failed\n");
+      return ENOSYS;
+  }
+
+  /* Resort to restart callback for identity updates. */
+  if(SEF_LU_IS_IDENTITY_UPDATE(info->flags)) {
+      return sef_cb_init_lu_identity_as_restart(type, info); 
+  }
+
+  /* Perform state transfer updates in all the other cases. */
+  return sef_st_state_transfer(info);
+}
+
 /*===========================================================================*
  *                       sef_cb_init_response_rs_reply                      *
  *===========================================================================*/
index 537f9a98cb5f874c0bb9fa59b7fdf266795ffdf0..5becf0c2ad6cdfc5ccf4e6e4a96d39d3bc261008 100644 (file)
@@ -1,13 +1,14 @@
 #include "syslib.h"
 #include <assert.h>
 #include <minix/sysutil.h>
+#include <minix/rs.h>
 
 /* SEF Live update variables. */
-static int sef_lu_state;
+int sef_lu_state;
+int __sef_st_before_receive_enabled;
+char sef_lu_state_eval[SEF_LU_STATE_EVAL_MAX_LEN];
 static int sef_lu_flags;
 
-extern __attribute__((weak)) int st_do_state_cleanup(void);
-
 /* SEF Live update callbacks. */
 static struct sef_lu_cbs {
     sef_cb_lu_prepare_t                 sef_cb_lu_prepare;
@@ -31,6 +32,9 @@ int do_sef_lu_request(message *m_ptr);
 
 /* SEF Live update helpers. */
 static void sef_lu_ready(int result);
+static void sef_lu_state_change(int state, int flags);
+int sef_lu_handle_state_data(endpoint_t src_e, int state,
+    cp_grant_id_t state_data_gid);
 
 /* Debug. */
 EXTERN char* sef_debug_header(void);
@@ -38,7 +42,6 @@ static int sef_lu_debug_cycle = 0;
 
 /* Information about SELF. */
 EXTERN endpoint_t sef_self_endpoint;
-EXTERN int sef_self_first_receive_done;
 
 /*===========================================================================*
  *                         do_sef_lu_before_receive                         *
@@ -48,15 +51,7 @@ void do_sef_lu_before_receive(void)
 /* Handle SEF Live update before receive events. */
   int r;
 
-  /* Initialize on first receive. */
-  if(!sef_self_first_receive_done) {
-      sef_lu_state = SEF_LU_STATE_NULL;
-  }
-
-  /* Nothing to do if we are not preparing for a live update. */
-  if(sef_lu_state == SEF_LU_STATE_NULL) {
-      return;
-  }
+  assert(sef_lu_state != SEF_LU_STATE_NULL);
 
   /* Debug. */
 #if SEF_LU_DEBUG
@@ -68,15 +63,29 @@ void do_sef_lu_before_receive(void)
   sef_lu_debug_end();
 #endif
 
-  /* Let the callback code handle the event.
-   * For SEF_LU_STATE_WORK_FREE, we're always ready, tell immediately.
+  /* Check the state. For SEF_LU_STATE_WORK_FREE/SEF_LU_STATE_UNREACHABLE,
+   * we are always/never ready. For SEF_LU_STATE_EVAL, evaluate the expression.
+   * For other states, let the callback code handle the event.
    */
-  r = OK;
-  if(sef_lu_state != SEF_LU_STATE_WORK_FREE) {
-      r = sef_lu_cbs.sef_cb_lu_prepare(sef_lu_state);
+  switch(sef_lu_state) {
+      case SEF_LU_STATE_WORK_FREE:
+          r = OK;
+      break;
+      case SEF_LU_STATE_UNREACHABLE:
+          r = sef_cb_lu_prepare_never_ready(sef_lu_state);
+      break;
+      case SEF_LU_STATE_PREPARE_CRASH:
+          r = sef_cb_lu_prepare_crash(sef_lu_state);
+      break;
+      case SEF_LU_STATE_EVAL:
+          r = sef_cb_lu_prepare_eval(sef_lu_state);
+      break;
+      default:
+          r = sef_lu_cbs.sef_cb_lu_prepare(sef_lu_state);
+      break;
   }
-  if(r == OK) {
-      sef_lu_ready(OK);
+  if(r == OK || r != ENOTREADY) {
+       sef_lu_ready(r);
   }
 }
 
@@ -86,15 +95,25 @@ void do_sef_lu_before_receive(void)
 int do_sef_lu_request(message *m_ptr)
 {
 /* Handle a SEF Live update request. */
-  int state, old_state, flags, is_valid_state;
+  int r, state, flags, is_valid_state;
+  cp_grant_id_t rs_state_data_gid;
 
   sef_lu_debug_cycle = 0;
-  old_state = sef_lu_state;
   state = m_ptr->m_rs_update.state;
   flags = m_ptr->m_rs_update.flags;
+  rs_state_data_gid = m_ptr->m_rs_update.state_data_gid;
+
+  /* Deal with prepare cancel requests first, where no reply is requested. */
+  if(state == SEF_LU_STATE_NULL) {
+      sef_lu_state_change(SEF_LU_STATE_NULL, 0);
+      return OK;
+  }
 
-  /* Deal with prepare cancel requests first. */
-  is_valid_state = (state == SEF_LU_STATE_NULL);
+  /* Check if we are already busy. */
+  if(sef_lu_state != SEF_LU_STATE_NULL) {
+      sef_lu_ready(EBUSY);
+      return OK;
+  }
 
   /* Otherwise only accept live update requests with a valid state. */
   is_valid_state = SEF_LU_ALWAYS_ALLOW_DEBUG_STATES && SEF_LU_STATE_IS_DEBUG(state);
@@ -106,19 +125,20 @@ int do_sef_lu_request(message *m_ptr)
       else {
           sef_lu_ready(EINVAL);
       }
+      return OK;
   }
-  else {
-      /* Set the new live update state. */
-      sef_lu_state = state;
-
-      /* If the live update state changed, let the callback code
-       * handle the rest.
-       */
-      if(old_state != sef_lu_state) {
-          sef_lu_cbs.sef_cb_lu_state_changed(old_state, sef_lu_state);
-      }
+
+  /* Handle additional state data (if any). */
+  r = sef_lu_handle_state_data(m_ptr->m_source, state, rs_state_data_gid);
+  if(r != OK) {
+      sef_lu_ready(r);
+      return OK;
   }
 
+  /* Set the new live update state. */
+  sef_lu_state_change(state, flags);
+
+
   /* Return OK not to let anybody else intercept the request. */
   return(OK);
 }
@@ -129,7 +149,7 @@ int do_sef_lu_request(message *m_ptr)
 static void sef_lu_ready(int result)
 {
   message m;
-  int old_state, r=EINVAL;
+  int r=EINVAL;
 
 #if SEF_LU_DEBUG
   sef_lu_debug_begin();
@@ -143,10 +163,7 @@ static void sef_lu_ready(int result)
    * any state that must be carried over to the new version.
    */
   if(result == OK) {
-      /* st_do_state_cleanup is a weak symbol. It is only defined if
-       * we are linked against magic */
-      if (st_do_state_cleanup)
-          r = st_do_state_cleanup();
+      r = sef_llvm_state_cleanup();
       if(r == OK) {
           r = sef_lu_cbs.sef_cb_lu_state_save(sef_lu_state, sef_lu_flags);
       }
@@ -178,13 +195,126 @@ static void sef_lu_ready(int result)
   /* Something went wrong. Update was aborted and we didn't get updated.
    * Restore things back to normal and continue executing.
    */
+  sef_lu_state_change(SEF_LU_STATE_NULL, 0);
+}
+
+/*===========================================================================*
+ *                           sef_lu_state_change                            *
+ *===========================================================================*/
+static void sef_lu_state_change(int state, int flags)
+{
+  int r, old_state;
+
   old_state = sef_lu_state;
-  sef_lu_state = SEF_LU_STATE_NULL;
+  sef_lu_state = state;
+  sef_lu_flags = flags;
+  if(sef_lu_state == SEF_LU_STATE_NULL) {
+      r = sys_statectl(SYS_STATE_CLEAR_IPC_FILTERS, 0, 0);
+      assert(r == OK);
+  }
   if(old_state != sef_lu_state) {
       sef_lu_cbs.sef_cb_lu_state_changed(old_state, sef_lu_state);
   }
 }
 
+/*===========================================================================*
+ *                         sef_lu_handle_state_data                         *
+ *===========================================================================*/
+int sef_lu_handle_state_data(endpoint_t src_e,
+    int state, cp_grant_id_t state_data_gid)
+{
+    int r;
+    struct rs_state_data rs_state_data;
+
+    if(state_data_gid == GRANT_INVALID) {
+        /* SEF_LU_STATE_EVAL requires an eval expression. */
+        return state == SEF_LU_STATE_EVAL ? EINVAL : OK;
+    }
+
+    r = sys_safecopyfrom(src_e, state_data_gid, 0,
+        (vir_bytes) &rs_state_data, sizeof(rs_state_data));
+    if(r != OK) {
+        return r;
+    }
+    if(rs_state_data.size != sizeof(rs_state_data)) {
+        return E2BIG;
+    }
+    if(state == SEF_LU_STATE_EVAL) {
+        if(rs_state_data.eval_addr && rs_state_data.eval_len) {
+            if(rs_state_data.eval_len >= SEF_LU_STATE_EVAL_MAX_LEN) {
+                return E2BIG;
+            }
+            r = sys_safecopyfrom(src_e, rs_state_data.eval_gid, 0,
+                (vir_bytes) sef_lu_state_eval, rs_state_data.eval_len);
+            if(r != OK) {
+                return r;
+            }
+            sef_lu_state_eval[rs_state_data.eval_len] = '\0';
+            r = sef_cb_lu_prepare_eval(SEF_LU_STATE_EVAL);
+            if(r != OK && r != ENOTREADY) {
+                /* State expression could not be evaluated correctly. */
+                return EINVAL;
+            }
+        }
+        else {
+            /* SEF_LU_STATE_EVAL requires a valid eval expression. */
+            return EINVAL;
+        }
+    }
+    if(rs_state_data.ipcf_els && rs_state_data.ipcf_els_size) {
+        ipc_filter_el_t ipc_filter[IPCF_MAX_ELEMENTS];
+        size_t ipc_filter_size = sizeof(ipc_filter);
+        int num_ipc_filters = rs_state_data.ipcf_els_size / ipc_filter_size;
+        int i;
+        if(rs_state_data.ipcf_els_size % ipc_filter_size) {
+            return E2BIG;
+        }
+        r = OK;
+        for(i=0;i<num_ipc_filters;i++) {
+            int num_elements=0;
+            r = sys_safecopyfrom(src_e, rs_state_data.ipcf_els_gid, i*ipc_filter_size,
+                (vir_bytes) ipc_filter, ipc_filter_size);
+            if(r != OK) {
+                break;
+            }
+#if SEF_LU_DEBUG
+            sef_lu_debug_begin();
+            sef_lu_dprint("%s, Installing ipc filter:\n", sef_debug_header());
+#endif
+            while(num_elements < IPCF_MAX_ELEMENTS && ipc_filter[num_elements].flags) {
+#if SEF_LU_DEBUG
+                sef_lu_dprint("el[%d]=(flags=%c%c%c%c, m_source=%d, m_type=%d)",
+                  num_elements,
+                  (ipc_filter[num_elements].flags & IPCF_MATCH_M_SOURCE) ? 'S' : '-',
+                  (ipc_filter[num_elements].flags & IPCF_MATCH_M_TYPE) ? 'T' : '-',
+                  (ipc_filter[num_elements].flags & IPCF_EL_BLACKLIST) ? 'B' : '-',
+                  (ipc_filter[num_elements].flags & IPCF_EL_WHITELIST) ? 'W' : '-',
+                  ipc_filter[num_elements].m_source, ipc_filter[num_elements].m_type);
+                sef_lu_dprint("\n");
+#endif
+                num_elements++;
+            }
+#if SEF_LU_DEBUG
+            sef_lu_debug_end();
+#endif
+            if(num_elements == 0) {
+                r = EINVAL;
+                break;
+            }
+            r = sys_statectl(ipc_filter[0].flags & IPCF_EL_BLACKLIST ? SYS_STATE_ADD_IPC_BL_FILTER : SYS_STATE_ADD_IPC_WL_FILTER,
+                ipc_filter, num_elements*sizeof(ipc_filter_el_t));
+            if(r != OK) {
+                break;
+            }
+        }
+        if(r != OK) {
+            sys_statectl(SYS_STATE_CLEAR_IPC_FILTERS, 0, 0);
+            return r;
+        }
+    }
+    return OK;
+}
+
 /*===========================================================================*
  *                            sef_setcb_lu_prepare                           *
  *===========================================================================*/
@@ -320,6 +450,27 @@ int sef_cb_lu_prepare_crash(int UNUSED(state))
   return OK;
 }
 
+/*===========================================================================*
+ *                      sef_cb_lu_prepare_eval                              *
+ *===========================================================================*/
+int sef_cb_lu_prepare_eval(int UNUSED(state))
+{
+  char result = 0;
+  int ret = sef_llvm_eval_bool(sef_lu_state_eval, &result);
+
+#if SEF_LU_DEBUG
+  sef_lu_debug_begin();
+  sef_lu_dprint("%s, cycle=%d. Evaluated state expression '%s' with error code %d and result %d\n",
+      sef_debug_header(), sef_lu_debug_cycle, sef_lu_state_eval, ret, result);
+  sef_lu_debug_end();
+#endif
+
+  if(ret < 0) {
+      return ret == ENOTREADY ? EINTR : ret;
+  }
+  return result ? OK : ENOTREADY;
+}
+
 /*===========================================================================*
  *                   sef_cb_lu_state_isvalid_standard                       *
  *===========================================================================*/
@@ -352,6 +503,19 @@ int sef_cb_lu_state_isvalid_generic(int state, int flags)
   return (state == SEF_LU_STATE_EVAL) || sef_cb_lu_state_isvalid_workfree(state, flags);
 }
 
+/*===========================================================================*
+ *                       sef_cb_lu_state_dump_eval                          *
+ *===========================================================================*/
+void sef_cb_lu_state_dump_eval(int state)
+{
+  if(state == SEF_LU_STATE_EVAL) {
+      sef_llvm_dump_eval(sef_lu_state_eval);
+  }
+  else {
+      return sef_cb_lu_state_dump_null(state);
+  }
+}
+
 /*===========================================================================*
  *                       sef_cb_lu_response_rs_reply                        *
  *===========================================================================*/
diff --git a/minix/lib/libsys/sef_llvm.c b/minix/lib/libsys/sef_llvm.c
new file mode 100644 (file)
index 0000000..38cc536
--- /dev/null
@@ -0,0 +1,152 @@
+#include "syslib.h"
+#include <assert.h>
+#include <unistd.h>
+#include <minix/sysutil.h>
+
+/* Stack refs definitions. */
+extern char **environ;
+extern char **env_argv;
+extern int env_argc;
+
+#define sef_llvm_stack_refs_save_one(P, T, R) { *((T*)P) = R; P += sizeof(T); }
+#define sef_llvm_stack_refs_restore_one(P, T, R) { R = *((T*)P); P += sizeof(T); }
+
+/*===========================================================================*
+ *                           sef_llvm_magic_enabled                         *
+ *===========================================================================*/
+int sef_llvm_magic_enabled()
+{
+    extern void __attribute__((weak)) magic_init();
+    if (!magic_init)
+        return 0;
+    return 1;
+}
+
+/*===========================================================================*
+ *                             sef_llvm_real_brk                            *
+ *===========================================================================*/
+int sef_llvm_real_brk(char *newbrk)
+{
+    extern int __attribute__((weak)) _magic_real_brk(char*);
+    if (!_magic_real_brk)
+        return brk(newbrk);
+    return _magic_real_brk(newbrk);
+}
+
+/*===========================================================================*
+ *                           sef_llvm_state_cleanup                         *
+ *===========================================================================*/
+int sef_llvm_state_cleanup()
+{
+    return OK;
+}
+
+/*===========================================================================*
+ *                             sef_llvm_dump_eval                           *
+ *===========================================================================*/
+void sef_llvm_dump_eval(char *expr)
+{
+    extern void __attribute__((weak)) _magic_dump_eval_bool(char*);
+    if (!_magic_dump_eval_bool)
+        return;
+    return _magic_dump_eval_bool(expr);
+}
+
+/*===========================================================================*
+ *                            sef_llvm_eval_bool                            *
+ *===========================================================================*/
+int sef_llvm_eval_bool(char *expr, char *result)
+{
+    extern int __attribute__((weak)) magic_eval_bool(char*, char*);
+    if (!magic_eval_bool)
+        return 0;
+    return magic_eval_bool(expr, result);
+}
+
+/*===========================================================================*
+ *                         sef_llvm_state_table_addr                        *
+ *===========================================================================*/
+void *sef_llvm_state_table_addr()
+{
+    extern void* __attribute__((weak)) _magic_vars_addr(void);
+    if (!_magic_vars_addr)
+        return NULL;
+    return _magic_vars_addr();
+}
+
+/*===========================================================================*
+ *                         sef_llvm_state_table_size                        *
+ *===========================================================================*/
+size_t sef_llvm_state_table_size()
+{
+    extern size_t __attribute__((weak)) _magic_vars_size(void);
+    if (!_magic_vars_size)
+        return 0;
+    return _magic_vars_size();
+}
+
+/*===========================================================================*
+ *                         sef_llvm_stack_refs_save                         *
+ *===========================================================================*/
+void sef_llvm_stack_refs_save(char *stack_buff)
+{
+    extern void __attribute__((weak)) st_stack_refs_save_restore(char*, int);
+    char *p = stack_buff;
+
+    sef_llvm_stack_refs_save_one(p, char**, environ);
+    sef_llvm_stack_refs_save_one(p, char**, env_argv);
+    sef_llvm_stack_refs_save_one(p, int, env_argc);
+
+    if (st_stack_refs_save_restore)
+        st_stack_refs_save_restore(p, 1);
+}
+
+/*===========================================================================*
+ *                        sef_llvm_stack_refs_restore                       *
+ *===========================================================================*/
+void sef_llvm_stack_refs_restore(char *stack_buff)
+{
+    extern void __attribute__((weak)) st_stack_refs_save_restore(char*, int);
+    char *p = stack_buff;
+
+    sef_llvm_stack_refs_restore_one(p, char**, environ);
+    sef_llvm_stack_refs_restore_one(p, char**, env_argv);
+    sef_llvm_stack_refs_restore_one(p, int, env_argc);
+
+    if (st_stack_refs_save_restore)
+        st_stack_refs_save_restore(p, 0);
+}
+
+/*===========================================================================*
+ *                         sef_llvm_state_transfer                          *
+ *===========================================================================*/
+int sef_llvm_state_transfer(sef_init_info_t *info)
+{
+    extern int __attribute__((weak)) _magic_state_transfer(sef_init_info_t *info);
+    if (!_magic_state_transfer)
+        return ENOSYS;
+    return _magic_state_transfer(info);
+}
+
+/*===========================================================================*
+ *                          sef_llvm_ltckpt_enabled                         *
+ *===========================================================================*/
+int sef_llvm_ltckpt_enabled()
+{
+    extern int __attribute__((weak)) ltckpt_get_offset();
+    if (!ltckpt_get_offset)
+        return 0;
+    return 1;
+}
+
+/*===========================================================================*
+ *                         sef_llvm_ltckpt_get_offset                       *
+ *===========================================================================*/
+int sef_llvm_get_ltckpt_offset()
+{
+    extern int __attribute__((weak)) ltckpt_get_offset();
+    if (!ltckpt_get_offset)
+        return 0;
+    return ltckpt_get_offset();
+}
+
diff --git a/minix/lib/libsys/sef_st.c b/minix/lib/libsys/sef_st.c
new file mode 100644 (file)
index 0000000..3189d9a
--- /dev/null
@@ -0,0 +1,124 @@
+#include "syslib.h"
+#include <assert.h>
+#include <string.h>
+#include <machine/archtypes.h>
+#include <minix/timers.h>
+#include <minix/sysutil.h>
+
+#include "kernel/config.h"
+#include "kernel/const.h"
+#include "kernel/type.h"
+#include "kernel/proc.h"
+
+/* SEF Live update prototypes for sef_receive(). */
+void do_sef_st_before_receive(void);
+
+/*===========================================================================*
+ *                         do_sef_st_before_receive                         *
+ *===========================================================================*/
+void do_sef_st_before_receive(void)
+{
+}
+
+/*===========================================================================*
+ *                         sef_copy_state_region_ctl                        *
+ *===========================================================================*/
+int sef_copy_state_region_ctl(sef_init_info_t *info, vir_bytes *src_address, vir_bytes *dst_address) {
+    if(info->copy_flags & SEF_COPY_DEST_OFFSET) {
+        *dst_address += sef_llvm_get_ltckpt_offset();
+    }
+    if(info->copy_flags & SEF_COPY_SRC_OFFSET) {
+        *src_address += sef_llvm_get_ltckpt_offset();
+    }
+#if STATE_TRANS_DEBUG
+    printf("sef_copy_state_region_ctl. copy_flags:\nSEF_COPY_DEST_OFFSET\t%d\nSEF_COPY_SRC_OFFSET\t%d\nSEF_COPY_NEW_TO_NEW\t%d\nSEF_COPY_OLD_TO_NEW\t%d\n", info->copy_flags & SEF_COPY_DEST_OFFSET ? 1 : 0, 
+            info->copy_flags & SEF_COPY_SRC_OFFSET ? 1 : 0, info->copy_flags & SEF_COPY_NEW_TO_NEW ? 1 : 0, info->copy_flags & SEF_COPY_OLD_TO_NEW ? 1 : 0);
+#endif
+    if(info->copy_flags & SEF_COPY_NEW_TO_NEW)
+        return 1;
+    return 0;
+}
+
+/*===========================================================================*
+ *                          sef_copy_state_region                           *
+ *===========================================================================*/
+int sef_copy_state_region(sef_init_info_t *info,
+    vir_bytes address, size_t size, vir_bytes dst_address)
+{
+  int r;
+  if(sef_copy_state_region_ctl(info, &address, &dst_address)) {
+#if STATE_TRANS_DEBUG
+      printf("sef_copy_state_region: memcpy %d bytes, addr = 0x%08x -> 0x%08x...\n",
+              size, address, dst_address);
+#endif
+      /* memcpy region from current state */
+      memcpy((void*) dst_address, (void *)address, size);
+  } else {
+#if STATE_TRANS_DEBUG
+      printf("sef_copy_state_region: copying %d bytes, addr = 0x%08x -> 0x%08x, gid = %d, source = %d...\n",
+              size, address, dst_address, SEF_STATE_TRANSFER_GID, info->old_endpoint);
+#endif
+      /* Perform a safe copy of a region of the old state. */
+      if((r = sys_safecopyfrom(info->old_endpoint, SEF_STATE_TRANSFER_GID, address,
+        dst_address, size)) != OK) {
+#if STATE_TRANS_DEBUG
+          printf("sef_copy_state_region: sys_safecopyfrom failed\n");
+#endif
+          return r;
+    }
+  }
+
+  return OK;
+}
+
+/*===========================================================================*
+ *                          sef_old_state_table_lookup                       *
+ *===========================================================================*/
+ int sef_old_state_table_lookup(sef_init_info_t *info, void *addr)
+{
+  struct priv old_priv;
+  int r;
+
+  if ((r = sys_getpriv(&old_priv, info->old_endpoint)) != OK) {
+      printf("ERROR. sys_getpriv() failed.\n");
+      return r;
+  }
+
+  if (sef_copy_state_region(info, old_priv.s_state_table
+    , sef_llvm_state_table_size(), (vir_bytes) addr))
+  {
+      printf("ERROR. state table transfer failed\n");
+      return EGENERIC;
+  }
+
+  return OK;
+}
+
+/*===========================================================================*
+ *                       sef_old_state_table_lookup_opaque                   *
+ *===========================================================================*/
+int sef_old_state_table_lookup_opaque(void *info_opaque, void *addr)
+{
+  assert(info_opaque != NULL && "Invalid info_opaque pointer.");
+  return sef_old_state_table_lookup((sef_init_info_t *)(info_opaque), addr);
+}
+
+/*===========================================================================*
+ *                         sef_copy_state_region_opaque                      *
+ *===========================================================================*/
+int sef_copy_state_region_opaque(void *info_opaque, uint32_t address,
+       size_t size, uint32_t dst_address)
+{
+  assert(info_opaque != NULL && "Invalid info_opaque pointer.");
+  return sef_copy_state_region((sef_init_info_t *)(info_opaque),
+      (vir_bytes) address, size, (vir_bytes) dst_address);
+}
+
+/*===========================================================================*
+ *                            sef_st_state_transfer                          *
+ *===========================================================================*/
+int sef_st_state_transfer(sef_init_info_t *info)
+{
+    return sef_llvm_state_transfer(info);
+}
+
index 62f3dd14cf446ff640aa82451c038917319b2860..62aad62e06dd63700ef26975805662171a3267e5 100644 (file)
@@ -42,6 +42,7 @@ int type;                                     /* type of initialization */
   }
 
   /* Send initialization message. */
+  memset(&m, 0, sizeof(message));
   m.m_type = RS_INIT;
   m.m_rs_init.type = type;
   m.m_rs_init.rproctab_gid = rinit.rproctab_gid;
index 81417870c1666ff66e943e7bc91b6681cc3b5bd6..8d265d8d79d09874f7774f308786b793061072c1 100644 (file)
@@ -3,8 +3,6 @@
 
 #define _SYSTEM                1
 
-#define brk _brk       /* get rid of no previous prototype warning */
-
 #include <minix/callnr.h>
 #include <minix/com.h>
 #include <minix/config.h>
@@ -24,6 +22,7 @@
 #include <env.h>
 #include <unistd.h>
 #include <assert.h>
+#include <sys/cdefs.h>
 #include <sys/param.h>
 #include <sys/mman.h>
 #include <sys/resource.h>
@@ -305,7 +304,10 @@ int munmap(void * addr, size_t len)
        return 0;
 }
 
-int brk(void *addr)
+#ifdef __weak_alias
+__weak_alias(brk, _brk)
+#endif
+int _brk(void *addr)
 {
        /* brk is a special case function to allow vm itself to
           allocate memory in it's own (cacheable) HEAP */