1 /* g/e.c
2 **
3 */
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <sys/stat.h>
7
8 #include "all.h"
9
10 #if 0
11 /* Image check.
12 */
13 struct {
14 c3_w nor_w;
15 c3_w sou_w;
16 c3_w mug_w[u3a_pages];
17 } u3K;
18
19 /* _ce_check_page(): checksum page.
20 */
21 static c3_w
22 _ce_check_page(c3_w pag_w)
23 {
24 c3_w* mem_w = u3_Loom + (pag_w << u3a_page);
25 c3_w mug_w = u3r_mug_words(mem_w, (1 << u3a_page));
26
27 return mug_w;
28 }
29
30 /* u3e_check(): compute a checksum on all memory within the watermarks.
31 */
32 void
33 u3e_check(c3_c* cap_c)
34 {
35 c3_w nor_w = 0;
36 c3_w sou_w = 0;
37
38 {
39 c3_w nwr_w, swu_w;
40
41 u3m_water(&nwr_w, &swu_w);
42
43 nor_w = (nwr_w + ((1 << u3a_page) - 1)) >> u3a_page;
44 sou_w = (swu_w + ((1 << u3a_page) - 1)) >> u3a_page;
45 }
46
47 /* Count dirty pages.
48 */
49 {
50 c3_w i_w, sum_w, mug_w;
51
52 sum_w = 0;
53 for ( i_w = 0; i_w < nor_w; i_w++ ) {
54 mug_w = _ce_check_page(i_w);
55 if ( strcmp(cap_c, "boot") ) {
56 c3_assert(mug_w == u3K.mug_w[i_w]);
57 }
58 sum_w += mug_w;
59 }
60 for ( i_w = 0; i_w < sou_w; i_w++ ) {
61 mug_w = _ce_check_page((u3a_pages - (i_w + 1)));
62 if ( strcmp(cap_c, "boot") ) {
63 c3_assert(mug_w == u3K.mug_w[(u3a_pages - (i_w + 1))]);
64 }
65 sum_w += mug_w;
66 }
67 printf("%s: sum %x (%x, %x)\r\n", cap_c, sum_w, nor_w, sou_w);
68 }
69 }
70
71 /* _ce_maplloc(): crude off-loom allocator.
72 */
73 static void*
74 _ce_maplloc(c3_w len_w)
75 {
76 void* map_v;
77
78 map_v = mmap(0,
79 len_w,
80 (PROT_READ | PROT_WRITE),
81 (MAP_ANON | MAP_PRIVATE),
82 -1, 0);
83
84 if ( -1 == (c3_ps)map_v ) {
85 c3_assert(0);
86 }
87 else {
88 c3_w* map_w = map_v;
89
90 map_w[0] = len_w;
91
92 return map_w + 1;
93 }
94 }
95
96 /* _ce_mapfree(): crude off-loom allocator.
97 */
98 static void
99 _ce_mapfree(void* map_v)
100 {
101 c3_w* map_w = map_v;
102 c3_i res_i;
103
104 map_w -= 1;
105 res_i = munmap(map_w, map_w[0]);
106
107 c3_assert(0 == res_i);
108 }
109 #endif
110
111 /* u3e_fault(): handle a memory event with libsigsegv protocol.
112 */
113 c3_i
u3e_fault(void * adr_v,c3_i ser_i)114 u3e_fault(void* adr_v, c3_i ser_i)
115 {
116 // Let the stack overflow handler run.
117 if ( 0 == ser_i ) {
118 return 0;
119 }
120
121 c3_w* adr_w = (c3_w*) adr_v;
122
123 if ( (adr_w < u3_Loom) || (adr_w >= (u3_Loom + u3a_words)) ) {
124 fprintf(stderr, "address %p out of loom!\r\n", adr_v);
125 fprintf(stderr, "loom: [%p : %p)\r\n", u3_Loom, u3_Loom + u3a_words);
126 c3_assert(0);
127 return 0;
128 }
129 else {
130 c3_w off_w = (adr_w - u3_Loom);
131 c3_w pag_w = off_w >> u3a_page;
132 c3_w blk_w = (pag_w >> 5);
133 c3_w bit_w = (pag_w & 31);
134
135 #if 0
136 if ( pag_w == 131041 ) {
137 printf("dirty page %d (at %p); unprotecting %p to %p\r\n",
138 pag_w,
139 adr_v,
140 (u3_Loom + (pag_w << u3a_page)),
141 (u3_Loom + (pag_w << u3a_page) + (1 << u3a_page)));
142 }
143 #endif
144 if ( 0 != (u3P.dit_w[blk_w] & (1 << bit_w)) ) {
145 fprintf(stderr, "strange page: %d, at %p, off %x\r\n",
146 pag_w, adr_w, off_w);
147 abort();
148 }
149
150 c3_assert(0 == (u3P.dit_w[blk_w] & (1 << bit_w)));
151 u3P.dit_w[blk_w] |= (1 << bit_w);
152
153 if ( -1 == mprotect((void *)(u3_Loom + (pag_w << u3a_page)),
154 (1 << (u3a_page + 2)),
155 (PROT_READ | PROT_WRITE)) )
156 {
157 perror("mprotect");
158 c3_assert(0);
159 return 0;
160 }
161 }
162 return 1;
163 }
164
165 /* _ce_image_open(): open or create image.
166 */
167 static c3_o
_ce_image_open(u3e_image * img_u,c3_o nuu_o)168 _ce_image_open(u3e_image* img_u, c3_o nuu_o)
169 {
170 c3_i mod_i = _(nuu_o) ? (O_RDWR | O_CREAT) : O_RDWR;
171 c3_c ful_c[8193];
172
173 snprintf(ful_c, 8192, "%s", u3P.dir_c);
174 mkdir(ful_c, 0700);
175
176 snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c);
177 mkdir(ful_c, 0700);
178
179 snprintf(ful_c, 8192, "%s/.urb/chk", u3P.dir_c);
180 mkdir(ful_c, 0700);
181
182 snprintf(ful_c, 8192, "%s/.urb/chk/%s.bin", u3P.dir_c, img_u->nam_c);
183 if ( -1 == (img_u->fid_i = open(ful_c, mod_i, 0666)) ) {
184 perror(ful_c);
185 return c3n;
186 }
187 else {
188 struct stat buf_u;
189
190 if ( -1 == fstat(img_u->fid_i, &buf_u) ) {
191 perror(ful_c);
192 c3_assert(0);
193 return c3n;
194 }
195 else {
196 c3_d siz_d = buf_u.st_size;
197 c3_d pgs_d = (siz_d + (c3_d)((1 << (u3a_page + 2)) - 1)) >>
198 (c3_d)(u3a_page + 2);
199
200 if ( c3y == nuu_o ) {
201 if ( siz_d ) {
202 c3_assert(0);
203 return c3n;
204 }
205 return c3y;
206 }
207 else {
208 if ( siz_d != (pgs_d << (c3_d)(u3a_page + 2)) ) {
209 fprintf(stderr, "%s: corrupt size %" PRIx64 "\r\n", ful_c, siz_d);
210 return c3n;
211 }
212 img_u->pgs_w = (c3_w) pgs_d;
213 c3_assert(pgs_d == (c3_d)img_u->pgs_w);
214
215 return c3y;
216 }
217 }
218 }
219 }
220
221 /* _ce_patch_write_control(): write control block file.
222 */
223 static void
_ce_patch_write_control(u3_ce_patch * pat_u)224 _ce_patch_write_control(u3_ce_patch* pat_u)
225 {
226 c3_w len_w = sizeof(u3e_control) +
227 (pat_u->con_u->pgs_w * sizeof(u3e_line));
228
229 if ( len_w != write(pat_u->ctl_i, pat_u->con_u, len_w) ) {
230 c3_assert(0);
231 }
232 }
233
234 /* _ce_patch_read_control(): read control block file.
235 */
236 static c3_o
_ce_patch_read_control(u3_ce_patch * pat_u)237 _ce_patch_read_control(u3_ce_patch* pat_u)
238 {
239 c3_w len_w;
240
241 c3_assert(0 == pat_u->con_u);
242 {
243 struct stat buf_u;
244
245 if ( -1 == fstat(pat_u->ctl_i, &buf_u) ) {
246 c3_assert(0);
247 return c3n;
248 }
249 len_w = (c3_w) buf_u.st_size;
250 }
251
252 pat_u->con_u = malloc(len_w);
253 if ( (len_w != read(pat_u->ctl_i, pat_u->con_u, len_w)) ||
254 (len_w != sizeof(u3e_control) +
255 (pat_u->con_u->pgs_w * sizeof(u3e_line))) )
256 {
257 free(pat_u->con_u);
258 pat_u->con_u = 0;
259 return c3n;
260 }
261 return c3y;
262 }
263
264 /* _ce_patch_create(): create patch files.
265 */
266 static void
_ce_patch_create(u3_ce_patch * pat_u)267 _ce_patch_create(u3_ce_patch* pat_u)
268 {
269 c3_c ful_c[8193];
270
271 snprintf(ful_c, 8192, "%s", u3P.dir_c);
272 mkdir(ful_c, 0700);
273
274 snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c);
275 mkdir(ful_c, 0700);
276
277 snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c);
278 if ( -1 == (pat_u->ctl_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0666)) ) {
279 c3_assert(0);
280 }
281
282 snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c);
283 if ( -1 == (pat_u->mem_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0666)) ) {
284 c3_assert(0);
285 }
286 }
287
288 /* _ce_patch_delete(): delete a patch.
289 */
290 static void
_ce_patch_delete(void)291 _ce_patch_delete(void)
292 {
293 c3_c ful_c[8193];
294
295 snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c);
296 unlink(ful_c);
297
298 snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c);
299 unlink(ful_c);
300 }
301
302 /* _ce_patch_verify(): check patch data mug.
303 */
304 static c3_o
_ce_patch_verify(u3_ce_patch * pat_u)305 _ce_patch_verify(u3_ce_patch* pat_u)
306 {
307 c3_w i_w;
308
309 for ( i_w = 0; i_w < pat_u->con_u->pgs_w; i_w++ ) {
310 c3_w pag_w = pat_u->con_u->mem_u[i_w].pag_w;
311 c3_w mug_w = pat_u->con_u->mem_u[i_w].mug_w;
312 c3_w mem_w[1 << u3a_page];
313
314 if ( -1 == lseek(pat_u->mem_i, (i_w << (u3a_page + 2)), SEEK_SET) ) {
315 perror("seek");
316 c3_assert(0);
317 return c3n;
318 }
319 if ( -1 == read(pat_u->mem_i, mem_w, (1 << (u3a_page + 2))) ) {
320 perror("read");
321 c3_assert(0);
322 return c3n;
323 }
324 {
325 c3_w nug_w = u3r_mug_words(mem_w, (1 << u3a_page));
326
327 if ( mug_w != nug_w ) {
328 printf("_ce_patch_verify: mug mismatch %d/%d; (%x, %x)\r\n",
329 pag_w, i_w, mug_w, nug_w);
330 c3_assert(0);
331 return c3n;
332 }
333 #if 0
334 else {
335 printf("verify: patch %d/%d, %x\r\n", pag_w, i_w, mug_w);
336 }
337 #endif
338 }
339 }
340 return c3y;
341 }
342
343 /* _ce_patch_free(): free a patch.
344 */
345 static void
_ce_patch_free(u3_ce_patch * pat_u)346 _ce_patch_free(u3_ce_patch* pat_u)
347 {
348 free(pat_u->con_u);
349 close(pat_u->ctl_i);
350 close(pat_u->mem_i);
351 free(pat_u);
352 }
353
354 /* _ce_patch_open(): open patch, if any.
355 */
356 static u3_ce_patch*
_ce_patch_open(void)357 _ce_patch_open(void)
358 {
359 u3_ce_patch* pat_u;
360 c3_c ful_c[8193];
361 c3_i ctl_i, mem_i;
362
363 snprintf(ful_c, 8192, "%s", u3P.dir_c);
364 mkdir(ful_c, 0700);
365
366 snprintf(ful_c, 8192, "%s/.urb", u3P.dir_c);
367 mkdir(ful_c, 0700);
368
369 snprintf(ful_c, 8192, "%s/.urb/chk/control.bin", u3P.dir_c);
370 if ( -1 == (ctl_i = open(ful_c, O_RDWR)) ) {
371 return 0;
372 }
373
374 snprintf(ful_c, 8192, "%s/.urb/chk/memory.bin", u3P.dir_c);
375 if ( -1 == (mem_i = open(ful_c, O_RDWR)) ) {
376 close(ctl_i);
377
378 _ce_patch_delete();
379 return 0;
380 }
381 pat_u = malloc(sizeof(u3_ce_patch));
382 pat_u->ctl_i = ctl_i;
383 pat_u->mem_i = mem_i;
384 pat_u->con_u = 0;
385
386 if ( c3n == _ce_patch_read_control(pat_u) ) {
387 close(pat_u->ctl_i);
388 close(pat_u->mem_i);
389 free(pat_u);
390
391 _ce_patch_delete();
392 return 0;
393 }
394 if ( c3n == _ce_patch_verify(pat_u) ) {
395 _ce_patch_free(pat_u);
396 _ce_patch_delete();
397 return 0;
398 }
399 return pat_u;
400 }
401
402 /* _ce_patch_write_page(): write a page of patch memory.
403 */
404 static void
_ce_patch_write_page(u3_ce_patch * pat_u,c3_w pgc_w,c3_w * mem_w)405 _ce_patch_write_page(u3_ce_patch* pat_u,
406 c3_w pgc_w,
407 c3_w* mem_w)
408 {
409 if ( -1 == lseek(pat_u->mem_i, (pgc_w << (u3a_page + 2)), SEEK_SET) ) {
410 c3_assert(0);
411 }
412 if ( (1 << (u3a_page + 2)) !=
413 write(pat_u->mem_i, mem_w, (1 << (u3a_page + 2))) )
414 {
415 c3_assert(0);
416 }
417 }
418
419 /* _ce_patch_count_page(): count a page, producing new counter.
420 */
421 static c3_w
_ce_patch_count_page(c3_w pag_w,c3_w pgc_w)422 _ce_patch_count_page(c3_w pag_w,
423 c3_w pgc_w)
424 {
425 c3_w blk_w = (pag_w >> 5);
426 c3_w bit_w = (pag_w & 31);
427
428 if ( u3P.dit_w[blk_w] & (1 << bit_w) ) {
429 pgc_w += 1;
430 }
431 return pgc_w;
432 }
433
434 /* _ce_patch_save_page(): save a page, producing new page counter.
435 */
436 static c3_w
_ce_patch_save_page(u3_ce_patch * pat_u,c3_w pag_w,c3_w pgc_w)437 _ce_patch_save_page(u3_ce_patch* pat_u,
438 c3_w pag_w,
439 c3_w pgc_w)
440 {
441 c3_w blk_w = (pag_w >> 5);
442 c3_w bit_w = (pag_w & 31);
443
444 if ( u3P.dit_w[blk_w] & (1 << bit_w) ) {
445 c3_w* mem_w = u3_Loom + (pag_w << u3a_page);
446
447 pat_u->con_u->mem_u[pgc_w].pag_w = pag_w;
448 pat_u->con_u->mem_u[pgc_w].mug_w = u3r_mug_words(mem_w,
449 (1 << u3a_page));
450
451 #if 0
452 printf("protect a: page %d\r\n", pag_w);
453 #endif
454 _ce_patch_write_page(pat_u, pgc_w, mem_w);
455
456 if ( -1 == mprotect(u3_Loom + (pag_w << u3a_page),
457 (1 << (u3a_page + 2)),
458 PROT_READ) )
459 {
460 c3_assert(0);
461 }
462
463 u3P.dit_w[blk_w] &= ~(1 << bit_w);
464 pgc_w += 1;
465 }
466 return pgc_w;
467 }
468
469 /* _ce_patch_junk_page(): mark a page as junk.
470 */
471 static void
_ce_patch_junk_page(u3_ce_patch * pat_u,c3_w pag_w)472 _ce_patch_junk_page(u3_ce_patch* pat_u,
473 c3_w pag_w)
474 {
475 c3_w blk_w = (pag_w >> 5);
476 c3_w bit_w = (pag_w & 31);
477
478 // printf("protect b: page %d\r\n", pag_w);
479 if ( -1 == mprotect(u3_Loom + (pag_w << u3a_page),
480 (1 << (u3a_page + 2)),
481 PROT_READ) )
482 {
483 c3_assert(0);
484 }
485 u3P.dit_w[blk_w] &= ~(1 << bit_w);
486 }
487
488 /* u3e_dirty(): count dirty pages.
489 */
490 c3_w
u3e_dirty(void)491 u3e_dirty(void)
492 {
493 c3_w pgs_w = 0;
494 c3_w nor_w = 0;
495 c3_w sou_w = 0;
496
497 /* Calculate number of saved pages, north and south.
498 */
499 {
500 c3_w nwr_w, swu_w;
501
502 u3m_water(&nwr_w, &swu_w);
503
504 nor_w = (nwr_w + ((1 << u3a_page) - 1)) >> u3a_page;
505 sou_w = (swu_w + ((1 << u3a_page) - 1)) >> u3a_page;
506 }
507 // u3K.nor_w = nor_w;
508 // u3K.sou_w = sou_w;
509
510 /* Count dirty pages.
511 */
512 {
513 c3_w i_w;
514
515 for ( i_w = 0; i_w < nor_w; i_w++ ) {
516 pgs_w = _ce_patch_count_page(i_w, pgs_w);
517 }
518 for ( i_w = 0; i_w < sou_w; i_w++ ) {
519 pgs_w = _ce_patch_count_page((u3a_pages - (i_w + 1)), pgs_w);
520 }
521 }
522 return pgs_w;
523 }
524
525 /* _ce_patch_compose(): make and write current patch.
526 */
527 static u3_ce_patch*
_ce_patch_compose(void)528 _ce_patch_compose(void)
529 {
530 c3_w pgs_w = 0;
531 c3_w nor_w = 0;
532 c3_w sou_w = 0;
533
534 /* Calculate number of saved pages, north and south.
535 */
536 {
537 c3_w nwr_w, swu_w;
538
539 u3m_water(&nwr_w, &swu_w);
540
541 nor_w = (nwr_w + ((1 << u3a_page) - 1)) >> u3a_page;
542 sou_w = (swu_w + ((1 << u3a_page) - 1)) >> u3a_page;
543 }
544 // u3K.nor_w = nor_w;
545 // u3K.sou_w = sou_w;
546
547 /* Count dirty pages.
548 */
549 {
550 c3_w i_w;
551
552 for ( i_w = 0; i_w < nor_w; i_w++ ) {
553 pgs_w = _ce_patch_count_page(i_w, pgs_w);
554 }
555 for ( i_w = 0; i_w < sou_w; i_w++ ) {
556 pgs_w = _ce_patch_count_page((u3a_pages - (i_w + 1)), pgs_w);
557 }
558 }
559
560 if ( !pgs_w ) {
561 return 0;
562 }
563 else {
564 u3_ce_patch* pat_u = malloc(sizeof(u3_ce_patch));
565 c3_w i_w, pgc_w;
566
567 _ce_patch_create(pat_u);
568 pat_u->con_u = malloc(sizeof(u3e_control) + (pgs_w * sizeof(u3e_line)));
569 pgc_w = 0;
570
571 for ( i_w = 0; i_w < nor_w; i_w++ ) {
572 pgc_w = _ce_patch_save_page(pat_u, i_w, pgc_w);
573 }
574 for ( i_w = 0; i_w < sou_w; i_w++ ) {
575 pgc_w = _ce_patch_save_page(pat_u, (u3a_pages - (i_w + 1)), pgc_w);
576 }
577 for ( i_w = nor_w; i_w < (u3a_pages - sou_w); i_w++ ) {
578 _ce_patch_junk_page(pat_u, i_w);
579 }
580
581 pat_u->con_u->nor_w = nor_w;
582 pat_u->con_u->sou_w = sou_w;
583 pat_u->con_u->pgs_w = pgc_w;
584
585 _ce_patch_write_control(pat_u);
586 return pat_u;
587 }
588 }
589
590 /* _ce_sync(): sync a file descriptor.
591 */
592 static void
_ce_sync(c3_i fid_i)593 _ce_sync(c3_i fid_i)
594 {
595 #if defined(U3_OS_linux)
596 fdatasync(fid_i);
597 #elif defined(U3_OS_osx)
598 fcntl(fid_i, F_FULLFSYNC);
599 #elif defined(U3_OS_bsd)
600 fsync(fid_i);
601 #else
602 # error "port: datasync"
603 #endif
604 }
605
606 /* _ce_patch_sync(): make sure patch is synced to disk.
607 */
608 static void
_ce_patch_sync(u3_ce_patch * pat_u)609 _ce_patch_sync(u3_ce_patch* pat_u)
610 {
611 _ce_sync(pat_u->ctl_i);
612 _ce_sync(pat_u->mem_i);
613 }
614
615 /* _ce_image_sync(): make sure image is synced to disk.
616 */
617 static void
_ce_image_sync(u3e_image * img_u)618 _ce_image_sync(u3e_image* img_u)
619 {
620 _ce_sync(img_u->fid_i);
621 }
622
623 /* _ce_patch_apply(): apply patch to image.
624 */
625 static void
_ce_patch_apply(u3_ce_patch * pat_u)626 _ce_patch_apply(u3_ce_patch* pat_u)
627 {
628 c3_w i_w;
629
630 //printf("image: nor_w %d, new %d\r\n", u3P.nor_u.pgs_w, pat_u->con_u->nor_w);
631 //printf("image: sou_w %d, new %d\r\n", u3P.sou_u.pgs_w, pat_u->con_u->sou_w);
632
633 if ( u3P.nor_u.pgs_w > pat_u->con_u->nor_w ) {
634 ftruncate(u3P.nor_u.fid_i, u3P.nor_u.pgs_w << (u3a_page + 2));
635 }
636 u3P.nor_u.pgs_w = pat_u->con_u->nor_w;
637
638 if ( u3P.sou_u.pgs_w > pat_u->con_u->sou_w ) {
639 ftruncate(u3P.sou_u.fid_i, u3P.sou_u.pgs_w << (u3a_page + 2));
640 }
641 u3P.sou_u.pgs_w = pat_u->con_u->sou_w;
642
643 if ( (-1 == lseek(pat_u->mem_i, 0, SEEK_SET)) ||
644 (-1 == lseek(u3P.nor_u.fid_i, 0, SEEK_SET)) ||
645 (-1 == lseek(u3P.sou_u.fid_i, 0, SEEK_SET)) )
646 {
647 perror("apply: seek");
648 c3_assert(0);
649 }
650
651 for ( i_w = 0; i_w < pat_u->con_u->pgs_w; i_w++ ) {
652 c3_w pag_w = pat_u->con_u->mem_u[i_w].pag_w;
653 c3_w mem_w[1 << u3a_page];
654 c3_i fid_i;
655 c3_w off_w;
656
657 if ( pag_w < pat_u->con_u->nor_w ) {
658 fid_i = u3P.nor_u.fid_i;
659 off_w = pag_w;
660 }
661 else {
662 fid_i = u3P.sou_u.fid_i;
663 off_w = (u3a_pages - (pag_w + 1));
664 }
665
666 if ( -1 == read(pat_u->mem_i, mem_w, (1 << (u3a_page + 2))) ) {
667 perror("apply: read");
668 c3_assert(0);
669 }
670 else {
671 if ( -1 == lseek(fid_i, (off_w << (u3a_page + 2)), SEEK_SET) ) {
672 perror("apply: lseek");
673 c3_assert(0);
674 }
675 if ( -1 == write(fid_i, mem_w, (1 << (u3a_page + 2))) ) {
676 perror("apply: write");
677 c3_assert(0);
678 }
679 }
680 #if 0
681 printf("apply: %d, %x\n", pag_w, u3r_mug_words(mem_w, (1 << u3a_page)));
682 #endif
683 }
684 }
685
686 /* _ce_image_blit(): apply image to memory.
687 */
688 static void
_ce_image_blit(u3e_image * img_u,c3_w * ptr_w,c3_ws stp_ws)689 _ce_image_blit(u3e_image* img_u,
690 c3_w* ptr_w,
691 c3_ws stp_ws)
692 {
693 c3_w i_w;
694
695 lseek(img_u->fid_i, 0, SEEK_SET);
696 for ( i_w=0; i_w < img_u->pgs_w; i_w++ ) {
697 if ( -1 == read(img_u->fid_i, ptr_w, (1 << (u3a_page + 2))) ) {
698 perror("read");
699 c3_assert(0);
700 }
701 #if 0
702 {
703 c3_w off_w = (ptr_w - u3_Loom);
704 c3_w pag_w = (off_w >> u3a_page);
705
706 printf("blit: page %d, mug %x\r\n", pag_w,
707 u3r_mug_words(ptr_w, (1 << u3a_page)));
708 }
709 #endif
710 ptr_w += stp_ws;
711 }
712 }
713
714 #if 0
715 /* _ce_image_fine(): compare image to memory.
716 */
717 static void
718 _ce_image_fine(u3e_image* img_u,
719 c3_w* ptr_w,
720 c3_ws stp_ws)
721 {
722 c3_w i_w;
723 c3_w buf_w[1 << u3a_page];
724
725 lseek(img_u->fid_i, 0, SEEK_SET);
726 for ( i_w=0; i_w < img_u->pgs_w; i_w++ ) {
727 c3_w mem_w, fil_w;
728
729 if ( -1 == read(img_u->fid_i, buf_w, (1 << (u3a_page + 2))) ) {
730 perror("read");
731 c3_assert(0);
732 }
733 mem_w = u3r_mug_words(ptr_w, (1 << u3a_page));
734 fil_w = u3r_mug_words(buf_w, (1 << u3a_page));
735
736 if ( mem_w != fil_w ) {
737 c3_w pag_w = (ptr_w - u3_Loom) >> u3a_page;
738
739 fprintf(stderr, "mismatch: page %d, mem_w %x, fil_w %x, K %x\r\n",
740 pag_w,
741 mem_w,
742 fil_w,
743 u3K.mug_w[pag_w]);
744 abort();
745 }
746 ptr_w += stp_ws;
747 }
748 }
749 #endif
750
751 /* u3e_save(): save current changes.
752 */
753 void
u3e_save(void)754 u3e_save(void)
755 {
756 u3_ce_patch* pat_u;
757
758 // In dry-run mode, we never touch this stuff.
759 //
760 if ( u3C.wag_w & u3o_dryrun ) {
761 return;
762 }
763
764 // Write all dirty pages to disk; clear protection and dirty bits.
765 //
766 // This has to block the main thread. All further processing can happen
767 // in a separate thread, though we can't save again till this completes.
768 //
769
770 if ( !(pat_u = _ce_patch_compose()) ) {
771 return;
772 }
773
774 // Sync the patch files.
775 //
776 // u3a_print_memory("sync: save", 4096 * pat_u->con_u->pgs_w);
777 _ce_patch_sync(pat_u);
778
779 // Verify the patch - because why not?
780 //
781 // printf("_ce_patch_verify\r\n");
782 _ce_patch_verify(pat_u);
783
784 // Write the patch data into the image file. Idempotent.
785 //
786 // printf("_ce_patch_apply\r\n");
787 _ce_patch_apply(pat_u);
788
789 #if 0
790 {
791 _ce_image_fine(&u3P.nor_u,
792 u3_Loom,
793 (1 << u3a_page));
794
795 _ce_image_fine(&u3P.sou_u,
796 (u3_Loom + (1 << u3a_bits) - (1 << u3a_page)),
797 -(1 << u3a_page));
798
799 c3_assert(u3P.nor_u.pgs_w == u3K.nor_w);
800 c3_assert(u3P.sou_u.pgs_w == u3K.sou_w);
801 }
802 #endif
803
804 // Sync the image file.
805 //
806 // printf("_ce_image_sync\r\n");
807 _ce_image_sync(&u3P.nor_u);
808 _ce_image_sync(&u3P.sou_u);
809
810 // Delete the patchfile and free it.
811 //
812 // printf("_ce_patch_delete\r\n");
813 _ce_patch_delete();
814 // printf("_ce_patch_free\r\n");
815 _ce_patch_free(pat_u);
816 }
817
818 /* u3e_live(): start the persistence system.
819 */
820 c3_o
u3e_live(c3_o nuu_o,c3_c * dir_c)821 u3e_live(c3_o nuu_o, c3_c* dir_c)
822 {
823 u3P.dir_c = dir_c;
824 u3P.nor_u.nam_c = "north";
825 u3P.sou_u.nam_c = "south";
826
827 #if 0
828 if ( u3C.wag_w & u3o_dryrun ) {
829 return c3y;
830 } else
831 #endif
832 {
833 /* Open and apply any patches.
834 */
835 if ( _(nuu_o) ) {
836 if ( (c3n == _ce_image_open(&u3P.nor_u, c3y)) ||
837 (c3n == _ce_image_open(&u3P.sou_u, c3y)) )
838 {
839 printf("boot: image failed\r\n");
840 exit(1);
841 }
842 }
843 else {
844 u3_ce_patch* pat_u;
845
846 /* Open image files.
847 */
848 {
849 if ( (c3n == _ce_image_open(&u3P.nor_u, c3n)) ||
850 (c3n == _ce_image_open(&u3P.sou_u, c3n)) )
851 {
852 fprintf(stderr, "boot: no image\r\n");
853 return u3e_live(c3y, dir_c);
854 }
855 }
856 /* Load any patch files; apply them to images.
857 */
858 if ( 0 != (pat_u = _ce_patch_open()) ) {
859 printf("_ce_patch_apply\r\n");
860 _ce_patch_apply(pat_u);
861
862 printf("_ce_image_sync\r\n");
863 _ce_image_sync(&u3P.nor_u);
864 _ce_image_sync(&u3P.sou_u);
865
866 printf("_ce_patch_delete\r\n");
867 _ce_patch_delete();
868 printf("_ce_patch_free\r\n");
869 _ce_patch_free(pat_u);
870 }
871
872 /* Write image files to memory; reinstate protection.
873 */
874 {
875 _ce_image_blit(&u3P.nor_u,
876 u3_Loom,
877 (1 << u3a_page));
878
879 _ce_image_blit(&u3P.sou_u,
880 (u3_Loom + (1 << u3a_bits) - (1 << u3a_page)),
881 -(1 << u3a_page));
882
883 if ( 0 != mprotect((void *)u3_Loom, u3a_bytes, PROT_READ) ) {
884 perror("protect");
885 c3_assert(0);
886 }
887 printf("protected loom\r\n");
888 }
889
890 /* If the images were empty, we are logically booting.
891 */
892 if ( (0 == u3P.nor_u.pgs_w) && (0 == u3P.sou_u.pgs_w) ) {
893 printf("live: logical boot\r\n");
894 nuu_o = c3y;
895 }
896 else {
897 u3a_print_memory("live: loaded",
898 (u3P.nor_u.pgs_w + u3P.sou_u.pgs_w) << u3a_page);
899 }
900 }
901 }
902 return nuu_o;
903 }
904
905