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