mintsuki / flanterm

Fast and reasonably complete (framebuffer) terminal emulator.
BSD 2-Clause "Simplified" License
69 stars 8 forks source link

Triple fault in flanterm_fb_init #11

Open ethindp opened 1 month ago

ethindp commented 1 month ago

When I initialize flanterm as demonstrated in the README but adapted for Zig, like so:

fb_contexts[i] = flanterm.flanterm_fb_init(null, null, @alignCast(@ptrCast(fb.address)), fb.width, fb.height, fb.pitch, fb.red_mask_size, fb.red_mask_shift, fb.green_mask_size, fb.green_mask_shift, fb.blue_mask_size, fb.blue_mask_shift, null, null, null, null, null, null, null, null, 0, 0, 1, 0, 0, 0);

A triple fault occurs, at least when built in debug mode. When built in release safe mode, the system just hangs. Qemu says this about the triggered interrupt:

check_exception old: 0xffffffff new 0x6
   792: v=06 e=0000 i=0 cpl=0 IP=0028:ffffffff80024db6 pc=ffffffff80024db6 SP=0030:ffff80007a169e00 env->regs[R_EAX]=0000000000000000
RAX=0000000000000000 RBX=0000000000000008 RCX=0000000000000001 RDX=00000000000000ff
RSI=0000000000000000 RDI=ffffffff80050401 RBP=ffff80007a16a0f0 RSP=ffff80007a169e00
R8 =0000000000000000 R9 =0000000000000000 R10=0000000000000008 R11=0000000000000008
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
RIP=ffffffff80024db6 RFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
CS =0028 0000000000000000 00000000 00209b00 DPL=0 CS64 [-RA]
SS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
DS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
FS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
GS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT=     ffff80007fe7d000 00000037
IDT=     0000000000000000 00000000
CR0=80010011 CR2=0000000000000000 CR3=000000007bb92000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000004 CCD=0000000000000000 CCO=LOGICB
EFER=0000000000000d00
check_exception old: 0xffffffff new 0xd
   793: v=0d e=0062 i=0 cpl=0 IP=0028:ffffffff80024db6 pc=ffffffff80024db6 SP=0030:ffff80007a169e00 env->regs[R_EAX]=0000000000000000
RAX=0000000000000000 RBX=0000000000000008 RCX=0000000000000001 RDX=00000000000000ff
RSI=0000000000000000 RDI=ffffffff80050401 RBP=ffff80007a16a0f0 RSP=ffff80007a169e00
R8 =0000000000000000 R9 =0000000000000000 R10=0000000000000008 R11=0000000000000008
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
RIP=ffffffff80024db6 RFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
CS =0028 0000000000000000 00000000 00209b00 DPL=0 CS64 [-RA]
SS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
DS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
FS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
GS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT=     ffff80007fe7d000 00000037
IDT=     0000000000000000 00000000
CR0=80010011 CR2=0000000000000000 CR3=000000007bb92000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000004 CCD=0000000000000000 CCO=LOGICB
EFER=0000000000000d00
check_exception old: 0xd new 0xd
   794: v=08 e=0000 i=0 cpl=0 IP=0028:ffffffff80024db6 pc=ffffffff80024db6 SP=0030:ffff80007a169e00 env->regs[R_EAX]=0000000000000000
RAX=0000000000000000 RBX=0000000000000008 RCX=0000000000000001 RDX=00000000000000ff
RSI=0000000000000000 RDI=ffffffff80050401 RBP=ffff80007a16a0f0 RSP=ffff80007a169e00
R8 =0000000000000000 R9 =0000000000000000 R10=0000000000000008 R11=0000000000000008
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
RIP=ffffffff80024db6 RFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
CS =0028 0000000000000000 00000000 00209b00 DPL=0 CS64 [-RA]
SS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
DS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
FS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
GS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT=     ffff80007fe7d000 00000037
IDT=     0000000000000000 00000000
CR0=80010011 CR2=0000000000000000 CR3=000000007bb92000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000004 CCD=0000000000000000 CCO=LOGICB
EFER=0000000000000d00
check_exception old: 0x8 new 0xd

The data that's passed to the first flanterm_fb_init call is:

(gdb) print *fb
$3 = {address = 0xffff800080000000 "", width = 1280, height = 800, pitch = 5120, bpp = 32, memory_model = rgb,
  red_mask_size = 8 '\b', red_mask_shift = 16 '\020', green_mask_size = 8 '\b', green_mask_shift = 8 '\b',
  blue_mask_size = 8 '\b', blue_mask_shift = 0 '\000', unused = "\000\000\000\000\000\000", edid_size = 0, edid = 0x0,
  mode_count = 30, modes = 0xffff80007bb96000}

(Why there are 30 video modes is beyond me.) After lots of digging into Flanterm's FB backend code, it appears that the error occurs sometime in the flanterm_fb_full_refresh function, specifically, I believe, in the plot_char call. Line 456 does:

uint32_t *canvas_line = ctx->canvas + x + (y + gy) * ctx->width;

And appears to just assume that the canvas is set, from what I can tell. But I may be wrong here; I'm not positive if I'm quite getting the right lines or not.

mintsuki commented 1 month ago

This is very likely not a Flanterm issue. Make sure your provided mem*() family of functions respects the C specification, and that your bindings work properly.

ethindp commented 1 month ago

I believe that Zig's mem*() implementation does respect the C specification, but I can check. As for the bindings part, I'm not using any bindings; I'm directly calling into the C code via Zig's @cImport facility. I know that in hosted environments Zig does turn on some extras such as the thread sanitizer and such, but I can't imagine it would do that in a freestanding environment since the relevant infrastructure isn't available.

ethindp commented 1 month ago

@mintsuki Okay, can confirm that it's something wrong with the flanterm library itself because somewhere it's invoking undefined behavior. Normally when Zig builds code it enables the UB sanitizer (which is obviously particularly important in C code). If I pass -fno-sanitize=undefined to the C compiler when building flanterm specifically, I don't get the crash. I still get a black screen (for some reason it's not writing anything to my framebuffer... Weird) but it doesn't immediately crash for me when initializing flanterm.

ethindp commented 1 month ago

Update: okay, so it's working fine for me (with UB sanitizer off) but it just doesn't work properly for me with -nographic. So probably a qemu problem, maybe.