IRC channel logs

2022-10-02.log

back to list of logs

<oriansj>and I had a good laugh today, showed someone: https://www.teamten.com/lawrence/writings/coding-machines/ and they said "The only unbelievable part of this short story is that they wrote a compiler in assembly"
<muurkha>hahaha
<muurkha>how quickly people forget
<oriansj>indeed, I've stopped telling people that I wrote one as they keep assuming I used GCC -S to generated the assembly as "No one programs in assembly"
<lanodan>I wonder how those do when they see assembly in kernels, bootloaders, compilers, standard libraries, cryptographic and multimedia libraries, …
<oriansj>lanodan: how many programmers these days read other people's code that isn't posted on stack exchange?
<lanodan>99% of programmers don't I guess
<stikonas>there isn't that much assembly in compilers though
<stikonas>probably about 1% in M2-Planet
<stikonas>and it supports quite a few ISAs
<stikonas>fossy: ready to merge that PR?
<fossy>stikonas: yep :)
<fossy>"completely crash UEFI and cause a reboot..." oh. that's quite impressively poor from uefi..
<stikonas>well, I didn't have time to debug what happened. But I guess if you overwrite incorrect memory region or something like that it could happen
<fossy>yeah, possible
<fossy>given uefi is quite low level as well
<oriansj>more high level than DOS
<stikonas>hmm, another issue I hit is that I can't print anything using stderr... Which is strange but oh well... I'll just use stdout for errors
<oriansj>stikonas: write errors to an openned file?
<stikonas>oriansj: well, I'm writing to stdout as we don't print anything to stdout anyway
<oriansj>valid point
<stikonas>normal cc_amd64 output goes to .M1 file
<stikonas>which is fine I guess...
<oriansj>well if one specifies an output file, otherwise the default was stdout
<stikonas>that's in POSIX
<stikonas>none of my earlier applications did that
<stikonas>they all could only print to file
<stikonas>partially because printing to stdout requires a bit more code
<oriansj>and always required a second argument
<stikonas>now with cc_* I have higher level language than hex
<stikonas>so I did implement a better fgetc
<stikonas>whcih can convert chars to wchars
<stikonas>\n to \n\r, etc...
<stikonas> (https://paste.debian.net/1255662/)
<stikonas>in posix it's a bit simpler, just use file descriptor 2...
<oriansj>indeed, doing the posix port probably was good practice so you had the core down before dealing with UEFI's brokenness
<stikonas>yeah, that's why I first got relocatable stuff
<stikonas>because it's hard to debug both at the same time
<stikonas>which I was doing for earlier programs...
<stikonas>but in hindsight that's not the best way
<stikonas>now I still need to figure out what causes the crash when building M2-0.c
<stikonas>but that's probably for tomorrow
<stikonas>and I'm not yet sure how to debug it anyway
<stikonas>probably will start with debug_list function and hope that it gives some clue
<oriansj>stikonas: well the easiest path forward would be first verify cc_* on posix can run the M2-0.c correctly and dump its debug at a couple points into separate files and then try to do the same on uefi and that should narrow things down quickly
<stikonas>yes, it runs fine on posix...
<oriansj>so the question is where the difference shows up
<stikonas>oriansj: oh I wonder if it's stack overflow
<stikonas>stack might be smaller there
<stikonas[m]>I think it is 128 KiB
<oriansj>unlikely as the default stack on linux is 64KiB
<stikonas[m]>Isn't it a few MiBs
<oriansj>ulimit -a
<za3k>i was thinking of trying to reduce the number of micro-stages in stage0's C bootstrapping
<za3k>is there an argument for this being a bad idea (aside from amount of work, of course)
<za3k>i can't find the docs with the zillion micro-stages any more. maybe i am confused, disregard for now
<sam_>ok
<oriansj>za3k: you are probably thinking of the steps between M2-Planet and GCC as there are a good few needed to get TCC to the state needed to build GCC.
<sam_>they left very quickly sadly
<sam_>that's why i was a bit stunned
<stikonas>oriansj: so on my stack ulimit -s is 8192 (KiB) and cc_amd64 still crashes if it's smaller than 2 MiB (you can go a bit smaller but 1950 already cause crashes)
<stikonas>so I think it's looking likely that this is the problem on UEFI too
<oriansj>so we need to allocate a new memory block and use that as a stack instead
<stikonas>yes, that's what I was thinking too
<stikonas>so I found a bit of reference in UEFI specs
<stikonas>it says you get 128 KiB or more of stack space
<stikonas>and 4 KiB+ after calling ExitBootServices (so just before kernel is started)
<oriansj>and if I remember correctly, don't arguments get passed on the stack to UEFI; would it have an issue with us using our own stack?
<stikonas>oriansj: it would but we don't have to fully use out own stack
<stikonas>we can keep two stacks and just offload heavy stuff to our own stack
<stikonas>I've freed up a register now to track our own stack
<stikonas>though that means heavy modifications to cc_amd64.S...
<stikonas>all those push rax, pop rax will have to be changed
<stikonas>and M2-Planet will also suffer from this problem...
<stikonas>probably even more
<oriansj>actually don't
<oriansj>consider this instead
<oriansj>make a global for UEFI stack
<oriansj>and a global for USER_STACK
<oriansj>on start we write the stack to UEFI_STACK
<oriansj>and allocate our new stack
<oriansj>switch RSP to point to the end of the new stack
<stikonas>oh yes, that might work
<oriansj>then inside of our syscalls we do the following: write the stack to USER_STACK
<stikonas>yeah, there we restore global stack
<stikonas>that will indeed hide most of the complexity behind a single function
<oriansj>thus minimal changes
<oriansj>and you can do it in two simple functions
<oriansj>enter and exit
<oriansj>ENTER_UEFI_STACK and EXIT_UEFI_STACK
<stikonas>yeah, those will move rsp to the required stack and save state of the other stack
<oriansj>indeed and we can steal that trick in M2-Planet as well
<stikonas>well, we need it in 3 places
<stikonas>cc_amd.M1 (codegen part of cc_amd64) and I guess in M2-Planet/M2libc
<oriansj>but that is much better than the althernate
<stikonas>indeed
<stikonas>I'll first get it into cc_amd.M1
<stikonas>which should let me compile M2-0.c but won't let M2-Planet to compile complex programs (ignoring for the moment that M2 is not ported to UEFI yet)
<stikonas>I guess 8 MiB should be fine for user stack
<stikonas>as we haven't encountered any problems in stage0-posix
<stikonas>and I guess reboot was happening because stack overflow was overwriting some critical parts of UEFI
<oriansj>well technicallly M2-Planet isn't ported to Operating systems, only hardware platforms. It is M2libc that needs to be ported to UEFI and M2-Planet will happily use the new arbitrary rules humans put ontop of the hardware.
<stikonas>well, yes, but cc_amd64 thing has two parts in it
<stikonas>one is adding it directlyu
<stikonas>well, maybe the second one goes to m2libc too...
<stikonas>to make sure that bootstrap M2 binary also has ENTER_UEFI_STACK and EXIT_UEFI_STACK
<oriansj>So the output of M2-Planet will always work on the hardware but it is the C code in M2libc is what breaks on different Operating systems (as they have different syscall methods and ways of passing arguments and different values to pass to the operating system)
<oriansj>so the changes would be entirely in M2libc and with a bit of special work in the libc-core.M1 and libc-full.M1
<oriansj>so we might end up having to make libc-uefi.M1
<stikonas>yeah, this doesn't sound too bad
<stikonas>libc-uefi.M1 was always going to be the case
<stikonas>we need to deal with command line arguments, etc...
<oriansj>well we can do that entirely in C code
<stikonas>well, in principle yes
<stikonas>maybe it's simpler that way
<oriansj>just have libc-uefi.M1 call FUNCTION__init_arguments which builds an array and returns it
<stikonas>cause it will have to me more sophisticated than what I have in early prototypes
<stikonas>(I think right now arguments are split on space, so double space means an empty argument which we might not want in M2libc)
<stikonas>anyway, let's first get cc_amd64.S working
<oriansj>indeed
<oriansj>soon it will all be downhill
<stikonas>well, at the very least soon it will be C code + some light assembly
<oriansj>with the added bonus of being able to use normal C code directly on UEFI rather than having to do the weird song and dance you need to do for UEFI right now
<stikonas>but don't we need a patch to M2-Planet to support UEFI/Windows calling convention?
<stikonas>we don't have access to call stack in C
<stikonas>actually if I remember correctly, M2-Planet passes all arguments on stack
<stikonas>so that might be fine, but we also need to populate rcx, rdx, r8 and r9
<oriansj>stikonas: no because M2-Planet doesn't even deal with POSIX's calling convention
<stikonas>oh, so where does that happen?
<oriansj>the only dealing with the calling convention is in M2libc in ASM blocks
<stikonas>oh yes...
<stikonas>well, so we might still need to insert small asm blocks in uefi wrappers then...
<oriansj>well we would be making a clone of the Linux subfolder
<stikonas>or how else would you get required arguments into rcx...r9 ?
<stikonas>yes, that is true
<stikonas>and then replace all those fgetc, etc with uefi equivalents
<oriansj>with nothing but the UEFI specific crap
<oriansj>but we can make them behave the same but be UEFI compatible
<stikonas>yes, in cc_amd64 I already tried to make fputc slightly more compatible (so it special cases file descriptor 2 and then uses different uefi function)
<stikonas>hmm, though I wonder whether real UEFI file can have file descriptor 2...
<stikonas>(though this shouldn't affect cc_amd64 as I was careful and used another variable/register for that stderr flag)
<oriansj>well we can flush that out with a good deal of experiments in M2libc
<stikonas>well, it's a pointer in UEFI
<stikonas>so unlikely to have value 2
<oriansj>stikonas: it is a pointer in M2libc as well
<oriansj>if you look in M2libc/stdio.c it shows up real quick
<oriansj>stdin, stdout and stderr are full structs
<oriansj>with buffers
<oriansj>so whatever arbitrary things UEFI needs, shouldn't be a problem
<oriansj>only in Mes.c does one have the hardcoded value of 0,1,2 for stdin, stdout and stderr
<stikonas>oriansj: so things are even simpler than what you planned for
<stikonas>we don't need to restore uefi stack before each uefi call
<stikonas>fputc/fgetc are happy with user stack
<stikonas>so I just need to call enter/exit_uefi_stack at the beginning and end of program
<stikonas>and M2-0.c compiles to at least good size
<stikonas>(same as on POSIX)
<stikonas>and in total I had to allocate 32 MiB of heap space
<stikonas>out of which 8 went to stack
<stikonas>though maybe I can try to reduce it a bit...
<stikonas>ok, 16 MiB (out of which 4 goes to stack) seems enough to build M2
<stikonas>oriansj: so basically https://git.stikonas.eu/andrius/stage0-uefi/commit/d6d8b2b7070f92ac43835990b64a7f0ab657b826
<stikonas>wait, that looks wrong... Not sure why it works
<stikonas>oh I know...
<stikonas>exit_uefi_stack is b0rked but mov rsp, rbp # restore stack just before termination saves us
<stikonas>anyway, fixed pushed
<stikonas>and I can start working on GAS->M1 conversion
***ay is now known as Andrew
<Hagfish>"soon it will be C code + some light assembly"
<Hagfish>that's great to hear
<Hagfish>i was thinking that october would be another great month for bootstrapping, and it seems to be off to a great start already :)