u3: adds facade for u3e_fault(), refactors error handling

This commit is contained in:
Joe Bryan 2022-12-12 23:04:03 -05:00
parent d043a42128
commit c3821c3325
3 changed files with 94 additions and 68 deletions

View File

@ -47,6 +47,14 @@
u3e_image sou_u; // south segment u3e_image sou_u; // south segment
} u3e_pool; } u3e_pool;
/* u3e_flaw: loom fault result.
*/
typedef enum {
u3e_flaw_sham = 0, // bogus state
u3e_flaw_base = 1, // vm fail (mprotect)
u3e_flaw_meme = 2, // bail:meme
u3e_flaw_good = 3 // handled
} u3e_flaw;
/** Globals. /** Globals.
**/ **/
@ -61,10 +69,10 @@
/** Functions. /** Functions.
**/ **/
/* u3e_fault(): handle a memory event with libsigsegv protocol. /* u3e_fault(): handle a memory fault.
*/ */
c3_i u3e_flaw
u3e_fault(void* adr_v, c3_i ser_i); u3e_fault(u3_post low_p, u3_post hig_p, u3_post off_p);
/* u3e_save(): update the checkpoint. /* u3e_save(): update the checkpoint.
*/ */

View File

@ -210,107 +210,67 @@ _ce_ward_post(c3_w nop_w, c3_w sop_w)
/* _ce_ward_clip(): hit the guard page. /* _ce_ward_clip(): hit the guard page.
*/ */
static inline c3_i static inline u3e_flaw
_ce_ward_clip(void) _ce_ward_clip(c3_w nop_w, c3_w sop_w)
{ {
const c3_w old_w = u3P.gar_w; c3_w old_w = u3P.gar_w;
c3_w nop_w, sop_w;
{
u3_post low_p, hig_p;
if ( !u3R ) {
low_p = 1;
hig_p = u3C.wor_i - 1;
}
else if ( c3y == u3a_is_north(u3R) ) {
low_p = u3R->hat_p;
hig_p = u3R->cap_p;
}
else {
low_p = u3R->cap_p;
hig_p = u3R->hat_p;
}
nop_w = (low_p - 1) >> u3a_page;
sop_w = hig_p >> u3a_page;
}
if ( !u3P.gar_w || ((nop_w < u3P.gar_w) && (sop_w > u3P.gar_w)) ) { if ( !u3P.gar_w || ((nop_w < u3P.gar_w) && (sop_w > u3P.gar_w)) ) {
fprintf(stderr, "loom: ward bogus (>%u %u %u<)\r\n", fprintf(stderr, "loom: ward bogus (>%u %u %u<)\r\n",
nop_w, u3P.gar_w, sop_w); nop_w, u3P.gar_w, sop_w);
return 0; return u3e_flaw_sham;
} }
if ( sop_w <= (nop_w + 1) ) { if ( sop_w <= (nop_w + 1) ) {
u3m_signal(c3__meme); // doesn't return return u3e_flaw_meme;
return 1;
} }
if ( _ce_ward_post(nop_w, sop_w) ) { if ( _ce_ward_post(nop_w, sop_w) ) {
return 0; return u3e_flaw_base;
} }
c3_assert( old_w != u3P.gar_w ); c3_assert( old_w != u3P.gar_w );
return 1;
return u3e_flaw_good;
} }
#endif /* ifdef U3_GUARD_PAGE */ #endif /* ifdef U3_GUARD_PAGE */
/* u3e_fault(): handle a memory event with libsigsegv protocol. /* u3e_fault(): handle a memory fault.
*/ */
c3_i u3e_flaw
u3e_fault(void* adr_v, c3_i ser_i) u3e_fault(u3_post low_p, u3_post hig_p, u3_post off_p)
{ {
// Let the stack overflow handler run. c3_w pag_w = off_p >> u3a_page;
if ( 0 == ser_i ) { c3_w blk_w = pag_w >> 5;
return 0; c3_w bit_w = pag_w & 31;
}
// XX u3l_log avoid here, as it can
// cause problems when handling errors
c3_w* adr_w = (c3_w*) adr_v;
if ( (adr_w < u3_Loom) || (adr_w >= (u3_Loom + u3C.wor_i)) ) {
fprintf(stderr, "address %p out of loom!\r\n", adr_w);
fprintf(stderr, "loom: [%p : %p)\r\n", u3_Loom, u3_Loom + u3C.wor_i);
c3_assert(0);
return 0;
}
u3p(c3_w) adr_p = u3a_outa(adr_w);
c3_w pag_w = adr_p >> u3a_page;
c3_w blk_w = (pag_w >> 5);
c3_w bit_w = (pag_w & 31);
#ifdef U3_GUARD_PAGE #ifdef U3_GUARD_PAGE
if ( pag_w == u3P.gar_w ) { if ( pag_w == u3P.gar_w ) {
if ( !_ce_ward_clip() ) { u3e_flaw fal_e = _ce_ward_clip(low_p >> u3a_page, hig_p >> u3a_page);
c3_assert(0);
return 0; if ( u3e_flaw_good != fal_e ) {
return fal_e;
} }
if ( !(u3P.dit_w[blk_w] & (1 << bit_w)) ) { if ( !(u3P.dit_w[blk_w] & (1 << bit_w)) ) {
fprintf(stderr, "loom: strange guard (%d)\r\n", pag_w); fprintf(stderr, "loom: strange guard (%d)\r\n", pag_w);
c3_assert(0); return u3e_flaw_sham;
return 0;
} }
} }
else else
#endif #endif
if ( 0 != (u3P.dit_w[blk_w] & (1 << bit_w)) ) { if ( u3P.dit_w[blk_w] & (1 << bit_w) ) {
fprintf(stderr, "strange page: %d, at %p, off %x\r\n", pag_w, adr_w, adr_p); fprintf(stderr, "loom: strange page (%d): %x\r\n", pag_w, off_p);
c3_assert(0); return u3e_flaw_sham;
return 0;
} }
u3P.dit_w[blk_w] |= (1 << bit_w); u3P.dit_w[blk_w] |= (1 << bit_w);
if ( _ce_flaw_protect(pag_w) ) { if ( _ce_flaw_protect(pag_w) ) {
c3_assert(0); return u3e_flaw_base;
return 0;
} }
return 1; return u3e_flaw_good;
} }
/* _ce_image_open(): open or create image. /* _ce_image_open(): open or create image.

View File

@ -1687,12 +1687,70 @@ _cm_limits(void)
# endif # endif
} }
void
_cm_water(u3_post* low_p, u3_post* hig_p)
{
c3_w top_w, bot_w;
if ( c3y == u3a_is_north(u3R) ) {
*low_p = u3R->hat_p - 1;
*hig_p = u3R->cap_p;
}
else {
*low_p = u3R->cap_p - 1;
*hig_p = u3R->hat_p;
}
}
/* u3m_fault(): handle a memory event with libsigsegv protocol. /* u3m_fault(): handle a memory event with libsigsegv protocol.
*/ */
c3_i c3_i
u3m_fault(void* adr_v, c3_i ser_i) u3m_fault(void* adr_v, c3_i ser_i)
{ {
return u3e_fault(adr_v, ser_i); // let the stack overflow handler run.
//
if ( 0 == ser_i ) {
return 0;
}
c3_w* adr_w = (c3_w*)adr_v;
u3_post low_p, hig_p;
if ( (adr_w < u3_Loom) || (adr_w >= (u3_Loom + u3C.wor_i)) ) {
fprintf(stderr, "loom: external fault: %p (%p : %p)\r\n\r\n",
adr_w, u3_Loom, u3_Loom + u3C.wor_i);
c3_assert(0);
return 0;
}
_cm_water(&low_p, &hig_p);
switch ( u3e_fault(low_p, hig_p, u3a_outa(adr_w)) ) {
// page tracking invariants violated, fatal
//
case u3e_flaw_sham: {
c3_assert(0);
return 0;
}
// virtual memory failure (protections), possibly recoverable XX
//
case u3e_flaw_base: {
c3_assert(0);
return 0;
}
// loom limits exceeded, recoverable
//
case u3e_flaw_meme: {
u3m_signal(c3__meme); // doesn't return
return 1;
}
case u3e_flaw_good: return 1;
}
c3_assert(!"unpossible");
} }
/* u3m_save(): update the checkpoint. /* u3m_save(): update the checkpoint.