1 #include "syslib.h" 2 #include <assert.h> 3 #include <string.h> 4 #include <machine/archtypes.h> 5 #include <minix/timers.h> 6 #include <minix/sysutil.h> 7 #include <minix/vm.h> 8 9 #include "kernel/config.h" 10 #include "kernel/const.h" 11 #include "kernel/type.h" 12 #include "kernel/proc.h" 13 14 EXTERN endpoint_t sef_self_endpoint; 15 16 /* SEF Live update prototypes for sef_receive(). */ 17 void do_sef_st_before_receive(void); 18 19 /*===========================================================================* 20 * do_sef_st_before_receive * 21 *===========================================================================*/ 22 void do_sef_st_before_receive(void) 23 { 24 } 25 26 /*===========================================================================* 27 * sef_copy_state_region_ctl * 28 *===========================================================================*/ 29 int sef_copy_state_region_ctl(sef_init_info_t *info, vir_bytes *src_address, vir_bytes *dst_address) { 30 if(info->copy_flags & SEF_COPY_DEST_OFFSET) { 31 *dst_address += sef_llvm_get_ltckpt_offset(); 32 } 33 if(info->copy_flags & SEF_COPY_SRC_OFFSET) { 34 *src_address += sef_llvm_get_ltckpt_offset(); 35 } 36 #if STATE_TRANS_DEBUG 37 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, 38 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); 39 #endif 40 if(info->copy_flags & SEF_COPY_NEW_TO_NEW) 41 return 1; 42 return 0; 43 } 44 45 /*===========================================================================* 46 * sef_copy_state_region * 47 *===========================================================================*/ 48 int sef_copy_state_region(sef_init_info_t *info, 49 vir_bytes address, size_t size, vir_bytes dst_address, int may_have_holes) 50 { 51 vir_bytes base, top, target; 52 struct vm_region_info vri; 53 int r; 54 55 base = address; 56 57 if(sef_copy_state_region_ctl(info, &address, &dst_address)) { 58 #if STATE_TRANS_DEBUG 59 printf("sef_copy_state_region: memcpy %d bytes, addr = 0x%08x -> 0x%08x...\n", 60 size, address, dst_address); 61 #endif 62 /* memcpy region from current state */ 63 memcpy((void*) dst_address, (void *)address, size); 64 } else if (may_have_holes && sef_self_endpoint != VM_PROC_NR && 65 vm_info_region(info->old_endpoint, &vri, 1, &base) == 1) { 66 /* Perform a safe copy of a region of the old state. The section may 67 * contain holes, so ask VM for the actual regions within the data 68 * section and transfer each one separately. The alternative, just 69 * copying until a page fault happens, is not possible in the multi- 70 * component-with-VM live update case, where VM may not receive page 71 * faults during the live update window. For now, we use the region 72 * iteration approach for the data section only; other cases have not 73 * been tested, but may work as well. 74 */ 75 #if STATE_TRANS_DEBUG 76 printf("sef_copy_state_region: copying %d bytes, addr = 0x%08x -> " 77 "0x%08x, gid = %d, source = %d, with holes...\n", size, address, 78 dst_address, SEF_STATE_TRANSFER_GID, info->old_endpoint); 79 #endif 80 81 /* The following is somewhat of a hack: the start of the data section 82 * may in fact not be page-aligned and may be part of the last page of 83 * of the preceding (text) section. Therefore, if the first region we 84 * find starts above the known base address, blindly copy the area in 85 * between. 86 */ 87 if (vri.vri_addr > address) { 88 if ((r = sys_safecopyfrom(info->old_endpoint, SEF_STATE_TRANSFER_GID, 89 address, dst_address, vri.vri_addr - address)) != OK) { 90 #if STATE_TRANS_DEBUG 91 printf("sef_copy_state_region: sys_safecopyfrom failed\n"); 92 #endif 93 return r; 94 } 95 } 96 97 top = address + size; 98 do { 99 assert(vri.vri_addr >= address); 100 if (vri.vri_addr >= top) 101 break; 102 if (vri.vri_length > top - vri.vri_addr) 103 vri.vri_length = top - vri.vri_addr; 104 target = dst_address + (vri.vri_addr - address); 105 if ((r = sys_safecopyfrom(info->old_endpoint, 106 SEF_STATE_TRANSFER_GID, vri.vri_addr, target, 107 vri.vri_length)) != OK) { 108 #if STATE_TRANS_DEBUG 109 printf("sef_copy_state_region: sys_safecopyfrom failed\n"); 110 #endif 111 return r; 112 } 113 /* Save on a VM call if the next address is already too high. */ 114 if (base >= top) 115 break; 116 } while (vm_info_region(info->old_endpoint, &vri, 1, &base) == 1); 117 } else { 118 /* Perform a safe copy of a region of the old state, without taking into 119 * account any holes. This is the default for anything but the data 120 * section, with a few additioanl exceptions: VM can't query VM, so 121 * simply assume there are no holes; also, if we fail to get one region 122 * for the old process (and this is presumably possible if its heap is 123 * so small it fits in the last text page, see above), we also just 124 * blindly copy over the entire data section. 125 */ 126 #if STATE_TRANS_DEBUG 127 printf("sef_copy_state_region: copying %d bytes, addr = 0x%08x -> " 128 "0x%08x, gid = %d, source = %d, without holes...\n", size, address, 129 dst_address, SEF_STATE_TRANSFER_GID, info->old_endpoint); 130 #endif 131 if ((r = sys_safecopyfrom(info->old_endpoint, SEF_STATE_TRANSFER_GID, 132 address, dst_address, size)) != OK) { 133 #if STATE_TRANS_DEBUG 134 printf("sef_copy_state_region: sys_safecopyfrom failed\n"); 135 #endif 136 return r; 137 } 138 } 139 140 return OK; 141 } 142 143 /*===========================================================================* 144 * sef_old_state_table_lookup * 145 *===========================================================================*/ 146 int sef_old_state_table_lookup(sef_init_info_t *info, void *addr) 147 { 148 struct priv old_priv; 149 int r; 150 151 if ((r = sys_getpriv(&old_priv, info->old_endpoint)) != OK) { 152 printf("ERROR. sys_getpriv() failed.\n"); 153 return r; 154 } 155 156 if (sef_copy_state_region(info, old_priv.s_state_table 157 , sef_llvm_state_table_size(), (vir_bytes) addr, FALSE /*may_have_holes*/)) 158 { 159 printf("ERROR. state table transfer failed\n"); 160 return EGENERIC; 161 } 162 163 return OK; 164 } 165 166 /*===========================================================================* 167 * sef_old_state_table_lookup_opaque * 168 *===========================================================================*/ 169 int sef_old_state_table_lookup_opaque(void *info_opaque, void *addr) 170 { 171 assert(info_opaque != NULL && "Invalid info_opaque pointer."); 172 return sef_old_state_table_lookup((sef_init_info_t *)(info_opaque), addr); 173 } 174 175 /*===========================================================================* 176 * sef_copy_state_region_opaque * 177 *===========================================================================*/ 178 int sef_copy_state_region_opaque(void *info_opaque, uint32_t address, 179 size_t size, uint32_t dst_address) 180 { 181 assert(info_opaque != NULL && "Invalid info_opaque pointer."); 182 return sef_copy_state_region((sef_init_info_t *)(info_opaque), 183 (vir_bytes) address, size, (vir_bytes) dst_address, 184 FALSE /*may_have_holes*/); 185 } 186 187 /*===========================================================================* 188 * sef_st_state_transfer * 189 *===========================================================================*/ 190 int sef_st_state_transfer(sef_init_info_t *info) 191 { 192 return sef_llvm_state_transfer(info); 193 } 194 195