#Retro Rocket OS - A BASIC powered Operating System (started 2009!)

1 messages · Page 4 of 1

willow ginkgo
#

did you see this first on reddit btw?

#

or on one of the other servers

round sparrow
willow ginkgo
#

ah ok

#

i do still post there every so often

#

but nobody ever reples to any of the osdev pictures thread lol

round sparrow
#

i used to be a regular, but quit when the spam control went overboard

#

i used to try to respond to the pictures thread, but i could only really appreciate the graphical ones which people said weren't so good under the surface, so i didn't know what to say lol

willow ginkgo
#

yeah good is subjective

#

many people dont like retro rocket

#

because it doesnt do the standard memory protected rings and stuff system

#

with binary programs and preemptive intrrupt driven tasks

round sparrow
#

yeah, i'm not looking forward to dealing with those people

#

for one thing, i had a good think about cooperative multitasking and don't see too much of a problem with it.

fervent nimbus
willow ginkgo
#

glad you do! 🙂 i think pretty much everyone here in this thread does

#

omg theres a fucking riot outside my house

#

not joking, at least 6 drunk and very angry idiots having a proper barney outside on the street, cop cars pulled up blues and twos blaring

#

the joys of living in town centre

round sparrow
#

oof!

#

yeah

willow ginkgo
#

its silly because we live literally across the street from the town police station and council office

#

omg i think its a mugging

#

"get off your fucking bike"

#

brb

round sparrow
#

my road's nice in cold weather, but when it gets warm enough for drunks to walk home, there's sometimes a bit of trouble

willow ginkgo
#

i think they arrested someone

#

the cops were yelling at someone to get off their bike, had him pinned down and he was shouting abuse calling them pigs etc

#

probably was up to no good in the cop shop car park

#

like 6 cops strode out the back door torches on to come deal with him

#

if drunks are drunk enough, its always warm enough to walk home

#

ok back to improving randomness in retro rocket!

#

csprng for tcp isns here we come!

willow ginkgo
#

new isn generator 😄

#
uint32_t get_isn(uint32_t local_addr, uint32_t remote_addr, uint16_t local_port, uint16_t remote_port) {
    if (!isn_init) {
        uint64_t seeds[2];

        if (!csprng_fill(seeds, sizeof(seeds))) {
            preboot_fail("Unable to initialise TCP ISN generator");
        }

        isn_hash_seed0 = seeds[0];
        isn_hash_seed1 = seeds[1];
        isn_tick_base = get_ticks();
        isn_init = 1;
    }

    uint64_t tuple[2] = {
        ((uint64_t)local_addr << 32) | (uint64_t)remote_addr,
        ((uint64_t)local_port << 48) | ((uint64_t)remote_port << 32),
    };

    uint32_t delta = (get_ticks() - isn_tick_base) * 250; /* 250k/sec */
    uint32_t base = (uint32_t)hashmap_sip(tuple, sizeof(tuple), isn_hash_seed0, isn_hash_seed1);

    return base + delta;
}
willow ginkgo
#

decided to move the isn_init part into the tcp_init function

#

a lot cleaner now

#
void tcp_init() {
    uint64_t seeds[2];
    tcb = hashmap_new(sizeof(tcp_conn_t), 0, 6, 28, tcp_conn_hash, tcp_conn_compare, NULL, NULL);
    tls_fd_table_init(FD_MAX);
    if (!csprng_fill(seeds, sizeof(seeds))) {
        preboot_fail("Unable to initialise TCP ISN generator");
    }
    isn_hash_seed0 = seeds[0];
    isn_hash_seed1 = seeds[1];
    isn_tick_base = get_ticks();
    proc_register_idle(tcp_idle, IDLE_BACKGROUND, 1);
}
uint32_t get_isn(uint32_t local_addr, uint32_t remote_addr, uint16_t local_port, uint16_t remote_port) {
    uint64_t tuple[2] = {
        ((uint64_t)local_addr << 32) | (uint64_t)remote_addr,
        ((uint64_t)local_port << 48) | ((uint64_t)remote_port << 32),
    };

    uint32_t delta = (get_ticks() - isn_tick_base) * 250; /* 250k/sec */
    uint32_t base = (uint32_t)hashmap_sip(tuple, sizeof(tuple), isn_hash_seed0, isn_hash_seed1);

    return base + delta;
}
narrow elbow
#

mmm... maybee you could ass a BBC BASIC mode

#

for compatibility

willow ginkgo
#

it would need a completely different expression parser, and most of the features of retro rocket wouldnt work in it, plus youd have to always have line numbers and BBC BASIC programs are stored tokenized

#

and BBC BASIC has weird numeric formats

#

40 bit 5-byte floating point?

#

plus, it would have to support BBC graphics, that is 7 graphics modes, some of which arent on a PC, and would need me to do mode switch

willow ginkgo
#

added support for TCP retransmission queues! This means the TCP implementation is much more realistic now, and doesnt just assume things get sent

#

also added proper random selection of dns request ids, and validation that dns replies come from the same ip that they were requested from

willow ginkgo
#

adding a telnet client!

willow ginkgo
willow ginkgo
#

telehack has some weird, old stuff

willow ginkgo
#

allowed for INPUT and SOCKREAD to accept an array subscript or whole-array input specification, this was left out for some reason a couple of years ago when i added arrays

#

also added the old type-in demo program MASTERMIND often seen in magzines. i used the one i found in telehack as a basis, only needed to change a couple of lines and remove GOTOs to modernise it and it ... just worked!

willow ginkgo
#

Fixed a bug that i introduced at some point where if you did A$ = @ it would get stuck in an infinite loop

willow ginkgo
#

i heard u leik teh BASIC so i did BASIC in ur BASIC cat

willow ginkgo
#

added SOUND FADE streamhandle, milliseconds, SOUND REPEAT [ON|OFF] soundhandle
also improved performance of the interpeter again by a huge margin, watch how fast it rotates 😄

fiery echo
#

hi :) coming from the details you mentioned in #showing-off (on keyword parsing), perfect hashing (perfect hashing (https://en.wikipedia.org/wiki/Perfect_hash_function) is probably a good way to go further with this

In computer science, a perfect hash function h for a set S is a hash function that maps distinct elements in S to a set of m integers, with no collisions. In mathematical terms, it is an injective function.
Perfect hash functions may be used to implement a lookup table with constant worst-case access time. A perfect hash function can, as any has...

#

you could probably get away with some mixing of first few letters and length to generate lookup index in a pretty small lookup table

willow ginkgo
# fiery echo hi :) coming from the details you mentioned in <#1437649502717874267> (on keywo...

already went further!

        GENERATE_ENUM_STRING_NAMES(TOKEN, token_names)
        GENERATE_ENUM_STRING_LENGTHS(TOKEN, token_name_lengths)
        uint16_t key = prefix16(ctx->ptr);
        int start = keyword_prefix_offsets[key];
        int end = keyword_prefix_offsets[key + 1];
        for (int kt = start; kt < end; ++kt) {
            int tok = keywords[kt];
            size_t len = token_name_lengths[tok];
            /* First two characters already matched by prefix16 bucket.
             * Compare from byte 2 onwards; <=2 length is already a full match.
             * Ordering is preserved within the bucket, so early-exit still works.
             */
            int comparison = len > 2 ? strncmp(ctx->ptr + 2, token_names[tok] + 2, len - 2) : 0;
            if (comparison == 0) {
                const char *backup = ctx->nextptr;
                ctx->nextptr = ctx->ptr + len;
                bool next_is_varlike = (*ctx->nextptr == '_' || isalnum(*ctx->nextptr));
                if (!next_is_varlike || keywords[kt] == PROC || keywords[kt] == FN || keywords[kt] == EQUALS) {
                    /* Only return the token if what follows the token is not continuation of a variable-name or keyword-name like sequence, e.g. "END -> ENDING"
                     * Special case for PROC, FN, =, as PROC and FN can be immediately followed by the name of their subroutine. e.g. PROCfoo
                     */
                    return tok;
                } else {
                    ctx->nextptr = backup;
                }
            } else if (comparison < 0) {
                /* We depend upon keyword_tokens being alphabetically sorted,
                 * so that we can bail early if we go too far down the list
                 * and still haven't found the keyword.
                 */
                break;
            }
        }
#

im using a 16 bit bucket now, and able to bail early if the token is <= 2 chars long, e.g. IF, TO, ON etc

#

and this allows me to cut the first two chars off the strncmp

#

meaning that every lookup is now constant time O(1), buckets only on average contain 1.7 keywords (mean)

#
[288]: Building keyword buckets...
[289]: Keyword bucket summary:
[290]:   keywords        : 121
[290]:   buckets used    : 69 / 65536
[291]:   empty buckets   : 65467
[292]:   avg bucket size : 1.753
[293]:   max bucket size : 7 (key=5245 'RE')
#

thanks for the docs though, definitely going to read them 😄

#

also if youre curious:

/**
 * @brief Return a 16-bit lexicographic prefix for a string.
 *
 * Encodes the first two characters as (c0 << 8) | c1 so that the numeric
 * ordering of the key matches the alphabetical ordering of the keyword table.
 *
 * Assumptions:
 * - Strings are at least one character long (second byte may be '\0')
 * - Direct byte access is safe (x86-64, no alignment restrictions of concern)
 * - Endianness is known and controlled (explicit shift/or avoids host order)
 *
 * Portability is not a goal; this is tuned specifically for x86-64.
 */
static inline __attribute__((always_inline)) uint16_t prefix16(const char *p)
{
    return ((uint16_t)(unsigned char)p[0] << 8) | (uint16_t)(unsigned char)p[1];
}
#

thats the prefix16 function, its really simple intentionally

fiery echo
#

the neat part of perfect hashing is that you don't get any collisions without having an enormous table (2^16 slots for this feels unreasonably large)

#

it takes some brute-forcing to find a good hash function for that though

#

here you could use first three letters and just take their lowest 5 bits (which uniquely identify uppercase letters) and use that to index array of size 2^15...

#

or try some random shifts/xors/adds/muls until you get some small table (for e|ample < 256 slots) without collisions

willow ginkgo
#

this is as close to perfect as I need to get rationally, before complexity and maintenance tuning of a hash function start taking all my time for something that is now incredibly quick

#

you'd need to get at least the first 6 letters for a truly perfect hash, if not more, because of a bunch of keywords that start SPRITE

#

2^16 bits for buckets is tiny tbh. it's like 128k, which is once, for the whole system. compared to each instances gc and heaps and stuff, a running basic program can go into megabytes easily, this isn't for tiny machines and 128k isn't going to break the bank.

#

bearing in mind all basic programs share that hash bucket table, it isn't a 128k table per program

willow ginkgo
#

ive moved builtin int/string/real functions into hashmaps. this will also greatly improve performance. now looking at caching common strings too

fiery echo
#

but yes, it is a bit of added complexity (not much tho), you just seemed to be interested for better techniques for this problem :)

willow ginkgo
#

now made a separate hash store for symbolic constants e.g. variable names so they don't pollute the GC. they don't need to be collected.

willow ginkgo
#

stonking along so fast the gif is a blur and there are 4 or 5 ghosted copies of the cube per 60hz refresh interval

willow ginkgo
#

I really need to make a BASIC profiler

fiery echo
# willow ginkgo yes, but "perfect" is purely academic

tried it out (it was fun :) ), and it doesn't work as well as I hoped, but probably could work ok-ish
with your keywords this seems to pretty stably (over seeds) generate 10bit/11bit lookup tables for hash function from word length + 8 lookups+shifts (doesn't seem to work with 7 :( ) in about half a second on my 3rd gen i5 with gcc and O3

willow ginkgo
#

perhaps, but I go for readability over perfection and it's fast enough.

also retro rocket always runs in -O0

#

my philosophy is, i can't hide behind the compilers optimisations if I pick bad algorithms

#

and it makes it very easy to debug, debugability and ease of understanding are very important to this OS

#

do I dare run the kernel profiler lol... that thing bogs down the system real bad

fiery echo
willow ginkgo
#

0.8fps for one of my simpler programs, and list running dog slow... thats profiler build for ya lol

#

sooo worth it though

slow glen
#

how did you do this, dump over serial?

willow ginkgo
#

the profile data is built up in linked lists and arrays then a special key combo attached to the keyboard interrupt directly dumps out the callgrind.out over serial

#

then qemu can save it

slow glen
#

I see, very nice

willow ginkgo
#

Added support for UDF optical media, and improved the github readme 😄

willow ginkgo
#

adding support for mounting and reading ADFS images as first-class data format!

willow ginkgo
#

@light ice let me know if theres anything i can do to help you with trying to diagnose the fred stuff 🙂

#

i'll likely get my own copy built some point soon, not tonight its nearly midnight here

light ice
#

I lowkey have zero clue

#

💀

#

@charred rampart is the one who made the clanker patches

#

I just know the FRED spec mostly

light ice
#

So I can try and see what the fuck is going on

willow ginkgo
#

if you run the full ./run.sh command line you get useful debug

#

to debug.log

light ice
#

qemu-fred-system-x86_64 -machine q35,accel=tcg -s -monitor stdio -cpu max,fred=on,lkgs=on -m 4G -drive id=disk,file=../../harddisk0,format=raw,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -drive file=rr.iso,media=cdrom,if=none,id=sata-cdrom -device ide-cd,drive=sata-cdrom,bus=ahci.1 -boot d -vnc 0.0.0.0:10 -debugcon file:debug.log -netdev user,id=netuser,hostfwd=tcp::2000-:2000,hostfwd=tcp::2080-:80 -object filter-dump,id=dump,netdev=netuser,file=dump.dat -device e1000,netdev=netuser

#

i added fred to it

#

and it wants a disk file that dosnt exist

#

and if i remove that stuff

#

it just opens the monitor

willow ginkgo
#

or create that drive

#

that isnt mandatory

#

also take out the -vnc 0.0.0.0:10

#

if you want it to run on standard display not vnc

#

by default it runs on vnc

light ice
willow ginkgo
#

youll have to pull nigtly again anyway

#

the way i was defining the fred vectors was wrong

light ice
#

ahh

#

did i mention that or was it somthin else

#

can you resend link?

willow ginkgo
#

sure

#

yeah this was completely wrong

#
fred_entry_page:
    /* FRED SPEC:
     * ----------
     * FRED event delivery uses two entry points, depending on the CPL at the time the event
     * occurred. This allows an event handler to identify the appropriate return instruction
     * (ERETU or ERETS).
     * Specifically, the new RIP value that FRED event delivery establishes is
     * IA32_FRED_CONFIG & ~FFFH for events that occur in ring 3 and
     * (IA32_FRED_CONFIG & ~FFFH) + 256 for events that occur in ring 0.
     */

    /* CPL3 entry (unused in this kernel) */
    .quad fred_unused_entry

    /* pad to exactly 256 bytes */
    .fill 0x100 - 8, 1, 0

    /* CPL0 entry (all kernel interrupts arrive here) */
    .quad fred_common_entry
#

i fixed it to match the spec

#

basically i filled it like a vector table before (oof)

willow ginkgo
#

yup

#

the rest of the config seemed irrelevent to me rn

light ice
#

isnt this proper?

willow ginkgo
#

same thing isnt it?

light ice
#

no?

#

this has code right there

#

FRED_CONFIG is set to fred_ring3_entry_asm_stub

willow ginkgo
#

hmmm, but the spec doesnt say jmp

light ice
#

no it executes code

#

starting from there

willow ginkgo
#

the spec says it loads rip with the addresses at those offsets

light ice
#

RIP gets set there

#

nope

willow ginkgo
#

ugh

#

why is it so vague

light ice
#

RIP is set to FRED_CONFIG

#

or + 256 for CPL0

#

which spec version did you read?

#

8.3.1.1 Determining the New RIP Value
FRED event delivery uses two entry points, depending on the CPL at the time the event occurred. This allows an
event handler to identify the appropriate return instruction (ERETU or ERETS).
Specifically, the new RIP value that FRED event delivery establishes is IA32_FRED_CONFIG & ~FFFH for events
that occur while CPL = 3 and (IA32_FRED_CONFIG & ~FFFH) + 256 for events that occur while CPL = 0.
If the new RIP value is not paging canonical, FRED event delivery causes a general-protection fault (#GP).1

willow ginkgo
#

gonna match mine to yours then

    /* CPL3 entry (unused in this kernel) */
    jmp fred_unused_entry

    /* pad to exactly 256 bytes */
    .fill 0x100 - (. - fred_entry_page), 1, 0

    /* CPL0 entry (all kernel interrupts arrive here) */
    jmp fred_common_entry
#

i hate GAS

light ice
#

Real

#

This is why I use NASM where I can trl

willow ginkgo
#

i avoid asm where i can

#

x86-64 is not a nice arch to work with in assembly

light ice
#

i actualy like its assemblt

#

😢

willow ginkgo
#

give me 6502 any day

light ice
#

Atleast with a good assembly like NASM

willow ginkgo
#

nasm is nicer yeah

#

doesnt have a % obsesion

#

ok, so if you refetch nightly, it has that fix

light ice
#

To be fair for GAS

#

It’s meant to be machine generated

willow ginkgo
#

well, we made some progress

#

what do you want to see from the cpuid etc

#

waitttttt......

#

im so dumb

light ice
#

What

willow ginkgo
#

i just wasted all our time, and i really appreciate you spending time on this

#

i'll show you the diff, and you can gladly eslap me for my dumbness

#
diff --git a/src/init.c b/src/init.c
index c2126757..4830fc93 100644
--- a/src/init.c
+++ b/src/init.c
@@ -7,7 +7,7 @@ spinlock_t debug_console_spinlock = 0;

init_func_t init_funcs[] = {
validate_limine_page_tables_and_gdt, init_heap, init_console,
-       init_acpi, init_idt, boot_aps, init_pci, init_realtime_clock,
+       init_acpi, init_interrupts, boot_aps, init_pci, init_realtime_clock,
init_devicenames, init_keyboard, init_ide, init_ahci, init_nvme,
init_virtio_block, init_filesystem, init_devfs, init_iso9660, init_udf,
init_adfs, init_fat32, init_rfs, init_modules, network_up, audio_init,
@@ -16,7 +16,7 @@ init_func_t init_funcs[] = {

char* init_funcs_names[] = {
"gdt",          "heap",         "console",      "acpi",
-       "idt",          "cpus",         "pci",          "clock",
+       "interrupts",   "cpus",         "pci",          "clock",
"devicenames",  "keyboard",     "ide",          "ahci",
"nvme",         "virtio-block", "filesystem",   "devfs",
"iso9660",      "udf",          "adfs",         "fat32",
#

it was bypassing the version that even LOOKED for fred

light ice
#

atleast we found the other bugs lmfao

#

Hopefully you did the rest of the spec proper

willow ginkgo
#

i was bypassing the init function that checks for fred lol

light ice
#

Yup XD

willow ginkgo
#

and just going right to the idt version

#

should be good to try nightly now

#

it should detect fred... and it may asplode

light ice
#

What’s your code for demuktiplexing the vector etc?

willow ginkgo
#

tbh the only other bit i could get wrong is extracting the interrupt no from the fred struct

#
.type fred_common_entry, @function
fred_common_entry:
    mov %rsp, %r8
    MPUSHA
    mov 0x28(%r8), %rsi
    mov 0x08(%r8), %rdx
    PUSH_SENTINEL
    call Interrupt
    POP_SENTINEL
    MPOPA
    ERETS
light ice
#
void fred_ring0_entry(fred_frame_t* frame) {
    uint8_t vector = (frame->cpu_frame.ss >> 32) & 0xFF;
    printf("GOT VECTOR 0x%02x VIA FRED!!!\n", vector);
    dispatch_interrupt(&frame->regs, &frame->cpu_frame, vector);
}
#

this is how i do it

#

all in C

#
typedef struct irq_saved_regs {
    uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
    uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax;
} irq_saved_regs_t;

typedef struct irq_cpu_frame {
    uint64_t error, ip, cs, flags, rsp, ss;
} irq_cpu_frame_t;

typedef struct fred_frame {
    irq_saved_regs_t regs;
    irq_cpu_frame_t cpu_frame;
    uint64_t fred_event_data;
    uint64_t fred_reserved;
} fred_frame_t;
#

Make sure you check that before I test

willow ginkgo
#

im just using offsets from %r8 which should hold the cpu frame

light ice
#

I’m about to eat lunch

willow ginkgo
#

but i could be wrong

light ice
#

The frame goes in the stack?

#

So it would be RSP

willow ginkgo
#

mov %rsp, %r8
MPUSHA
mov 0x28(%r8), %rsi
mov 0x08(%r8), %rdx

taken from the sp

light ice
#

Yeah yeah

#

So should be fine?

willow ginkgo
#

yeah i just move it into r8 before i push stuff

#

if 0x28 and 0x08 is the right offset, sure

light ice
#

You could also do mov whatever [rsp + val]

willow ginkgo
#

if they arent i'll get given the wrong interrupt numbers

#

is that syntax valid in gas?

light ice
#

Well it’s x86 assembly

#

So yes if you convert it

#

But if you push all the GPRs

#

Those offsets are wrong?

willow ginkgo
#

no i push after i move it to r8

#

so it still points to the right place

light ice
#

Ahh

willow ginkgo
#

right?

light ice
#

Is r8 being clobbered then?

willow ginkgo
#

shouldnt be

light ice
#

On interrupts?

#

If you move it to r8?

#

Before pushing?

#

r8 gets fucking nuked

willow ginkgo
#
.macro MPUSHA
    push %r15
    push %r14
    push %r13
    push %r12
    push %r11
    push %r10
    push %r9
    push %r8
    push %rdi
    push %rsi
    push %rbp
    push %rbx
    push %rdx
    push %rcx
    push %rax
.endm
#

MPUSHA just pushes stuff it doesnt touch any regs

willow ginkgo
#

oh wait yeah

light ice
willow ginkgo
#

you mean i'll break r8 for the caller

#

yeah

light ice
#

If you interrupt anything

#

R8 is donezo

#

Push then use rsp relative loads

#

And do the processing in C

#

🙏

#

It’s way cleaner

#

And the compiler can do its magic

#

The assembly should just be a stub to save and restore and set the registers right to pass the frame

willow ginkgo
#
fred_common_entry:
    MPUSHA
    lea 120(%rsp), %r8
    mov 0x28(%r8), %rsi
    mov 0x08(%r8), %rdx
    PUSH_SENTINEL
    call Interrupt
    POP_SENTINEL
    MPOPA
    ERETS
#

something like this perhaps

#

MPUSHA pushes 120 bytes

light ice
#

Do you even need the r8 here atp?

#

You can just do it right off rsp

#

What I do is have seperate C functions for fred that convert the frame etc

#

Since it’s also a different layout

#

Every so slightly

willow ginkgo
#

yeah i could

light ice
#

extern void dispatch_interrupt(irq_saved_regs_t* regs, irq_cpu_frame_t* frame, uint64_t vector);
then i have this function the IDT calls with

    mov rdi, rsp         ; irq_saved_regs_t* ; also same as lea rdi, [rsp + 0]
    lea rsi, [rsp + 128] ; irq_cpu_frame_t
    mov rdx, [rsp + 120] ; uint64_t vector

    cld
    call dispatch_interrupt
    cli
light ice
#

It’s FRED Stub - JMP > Fred ASM - CALL > Fred C - CALL > common interrupt handler

willow ginkgo
#
fred_common_entry:
    MPUSHA
    mov 0x98(%rsp), %rsi /* 120 + 0x28 = 0x98 */
    mov 0x80(%rsp), %rdx /* 120 + 0x08 = 0x80 */
    PUSH_SENTINEL
    call Interrupt
    POP_SENTINEL
    MPOPA
    ERETS
light ice
#

Which is very little overhead which dosnt matter since FRED is wayy faster than IDT etc

willow ginkgo
#

i wont notice the speed difference at all

#

im doing this because intel is pushing this hard, and i dont want to be left behind

light ice
#

Yeah lmfao. Chances are on real hardware it will be faster esp on diskIO

#

Linux saw some good benchmarks

light ice
#

I have the role for a reason

willow ginkgo
#

yours and linux switch CPL though

#

i dont

light ice
#

I was the first hobby kernel to get it

light ice
#

And it dosnt matter much for FRED

#

It’s still much faster due to how it operates on 64byte aligned stacks

#

And it pushes 64 bytes always

#

So it’s always on a cache line perfectly

#

Among other improvements

light ice
willow ginkgo
#

pushing the r8 clobber fix

#

i use the stack that limine gives, if it isnt 64 byte aligned i may have to move my stack

light ice
#

its for the RSPx values

#

which may not be used?

willow ginkgo
#

its one i explicitly request, of quite some size

#

nightly is ready for another go!

light ice
#

send link?

#

sorry was checking some FRED spec stuff to make sure i wanst mucking stuff up

#

My IDT path wasn’t properly setting interrupts so any handler couldn’t get interrupted

#

My gates are all set to clear IF for stack pushes etc and then letting it happen on C code and disabling on exit

#

And I forget to have that mmLol

#

FRED also sets RFLAGS to 0x2 so it’s cleared too along with direction flag etc

light ice
#

ty

willow ginkgo
#

yw

light ice
#

tripple fault

willow ginkgo
#

how far through?

light ice
#

it never even printed FRED enabled

#

or if it did it was too fast

willow ginkgo
#

it did

#

just wasnt there long enough

#

[0]: Interrupts enabled!

[0]: Initialisation of interrupts done!

light ice
#

ahh

willow ginkgo
#

happens between these two

#

it triple faulted at the first interrupt, i think

#

perhaps like you said, the stack isnt aligned 64 bytes

light ice
#

FWIW i use the limine stack too

#

its just the RSPx that has that requirement

#

otherwise things would be funky

willow ginkgo
#

so its not that

#

i really dont have the energy to back and forth debug this at 1am 🙁

light ice
#

Got to sleep

#

😭

#

I may be preaching the word of FRED more than a jahovas witness but I still respect sleep

willow ginkgo
#

lol

#

if you feel like poking around my code, i really really do appreciate PRs

#

retro rocket isnt hard to build, just has some odd deps

light ice
#

Il see what I can do

#

I will probably end up moving more logic into C though

#

And unifying things like my kernel

#

Because then I can control c control v a lot more of it

#

And it will be cleaner regardless

willow ginkgo
#

so long as the path for interrupts still handles the same for idt as it does for isr; it should go through the global functions Interrupt and IRQ with the same parameters

#

other levels shouldnt care about fred or idt

light ice
#

No they won’t

#

It’s just since the frames differ I need to deliver the stuff a lil differently

#

To make it easy for both

willow ginkgo
#

also, dont change the idt stuff 🙂

light ice
#

In my old kernel I had some nasty conversion logic

willow ginkgo
#

but apart from that...

#

have at it

light ice
willow ginkgo
#

i dont really want to change idt stuff, this is well tested on real hw

light ice
#

FWIW this is behavior that wouldn’t break between real hardware and emulation

#

But I understand

willow ginkgo
#

but you dont need to change Interrupt() and IRQ(), just put your stuff below it and call into the existing stuff

light ice
#

May just be way harder to make FRED work

willow ginkgo
#

i have asm stubs that call into the C

willow ginkgo
#

i dont need all that

light ice
#

its for converting a frame?

willow ginkgo
#

its irrelevant to isr handlers in retro rocket

light ice
#

what do ISR handlers take in?

willow ginkgo
#

this is all i need for isr

void Interrupt(uint64_t isrnumber, uint64_t errorcode, uint64_t rip)

#

and this for IRQ:

void IRQ(uint64_t isrnumber, uint64_t irqnum)

light ice
#

ahh then its easy enough to not touch ^^

willow ginkgo
#

i dont need complex frame stuff

light ice
#

mine needs to edit the stuff from the stack for stuff like fork() later signals reg dumps, redirecting from faults etc etc

willow ginkgo
#

the Interrupt thing can build entire stack traces just from rip (its the pre-empted rip)

#

yeah, its a very simple system

#

which is why i was able to test it quite well on real hw

light ice
#

yeah i should be able to make very clean conversion logic there :3

#

basicaly just this

willow ginkgo
#

the existing code is at the bottom of asm/loader.S and src/idt.c

#

and yeah as i said i was planning to move the fred stuff to a new fred.c

#

but that can wait till it works

#

unless you get the urge lol

light ice
willow ginkgo
#

yeah youll need the definition of the fred frame too

#

i dont have it atm

light ice
#

good thing i can copy paste it

willow ginkgo
#

would be nice if it lived in a fred.h i guess

light ice
#

i can prolly just inline it in the .c tbh

willow ginkgo
#

i like your fred flintstone btw lol

light ice
#

i stole it from online

willow ginkgo
#

i have a homer that i used to put in crash dumps

#

but it was too tall

light ice
#

ahh dang

#

i ended up having to cut down the size on mine

#

ASCII codeblocks actualy end up being a ood bit smaller for the detail ratio

#

i fit an entire ralsei properly

willow ginkgo
#

i just noticed you configure the msrs for stack addresses, i dont

#
    uint64_t star = ((uint64_t)(0x18 | 3) << 48) | ((uint64_t)0x08 << 32);
    wrmsr(STAR, star);
    wrmsr(FRED_CONFIG, (uint64_t)fred_ring3_entry_asm_stub);
    wrmsr(FRED_RSP0, (uint64_t)&fred_kernel_stack + sizeof(fred_kernel_stack));
    wrmsr(FRED_RSP2, (uint64_t)&fred_df_stack     + sizeof(fred_df_stack));
    wrmsr(FRED_RSP3, (uint64_t)&fred_nmi_stack    + sizeof(fred_nmi_stack));
    wrmsr(FRED_STKLVLS, 0);
light ice
#

thats only used for stack levles

#

which since its zero

#

its unised

#

RSP0 is from cpl3 to 0

#

the others are for stack levels

#

IIRC

#

my new kernel leaves rsp0 unset

willow ginkgo
#

i'll let you have a dig through my code 🙂 gonna go rest

#

thanks so much for looking

light ice
#

il try and do some stuff tomorrow

#

o7

#

btw @willow ginkgo where has intel been pushing this lol

willow ginkgo
#

i'll do other stuff away from the idt/fred suff

#

it was more about this

light ice
#

ahhh yeah

#

its not replacing it to be clear

willow ginkgo
#

toms hardware really do a half ass job of explaining it

light ice
#

its not being zapped

#

FRED is just a new option

willow ginkgo
#

but if its coming to zen 6, i dont have to worry about "its intel only code" any more

light ice
willow ginkgo
#

it will eventually be everywhere

light ice
#

you may like this

#

for an actual review on FRED and the legacy stuff

willow ginkgo
#

nice

willow ginkgo
#

I haven't really looked more into any FRED stuff

#

mainly been looking into acorn DFS today

light ice
#

can you give me a TLDR on the build process

#

il get looking into it in a monento

willow ginkgo
#

install deps listed at bottom of readme

#

cd retrorocket; mkdir build

#

cmake ..
make -j${NPROC}

#

expects gcc only, isn't designed to be portable

#

and yeah it's that simple, when it's done it outputs iso and usb.img

light ice
#

this is the repo yeah

willow ginkgo
#

yup

#

if you're wondering php is required for image builder scripts, I prefer it to bash

light ice
#

its reall angy

willow ginkgo
#

how are you building it

#

can you show me the whole log

#

it looks like it's ignoring the include paths

#

your xmmintrin is weird....

#

why is it not standalone @light ice

light ice
#

huh

#

this is how i buult it

willow ginkgo
#

your xmmintrin isn't standalone

#

it's trying to pull in malloc

light ice
#

does does one fix that

willow ginkgo
#

idk, works fine for me in Ubuntu

light ice
#

im on arch/cachyos

#

this is also why containers are goated

willow ginkgo
#

no idea, something isn't right about your setup

#

it builds fine in github actions too

light ice
#

I am lowkey kinda cursed tho

#

I can’t build astral either

#

Everything I do works for me tho

willow ginkgo
#

yeah something ain't right

light ice
#

And never has had strange issues

#

😭

#

I do it a bit more freestanding tho and stuff so it’s less environment dependent

#

My commit is up for you to go look at fred shit tho and compare

willow ginkgo
#

you don't need a special cross compiler for retro rocket if that's what you got

willow ginkgo
light ice
#

Nope

#

My main GCC is standard Linux GCC

willow ginkgo
#

try a docker container of Ubuntu 24.04

#

your os interrupt setup is a bit different to mine

light ice
willow ginkgo
#

or 14

#

I'm using 14 and that's fine

light ice
#

I don’t think I can downgrade safely on arch

willow ginkgo
#

can't you install side by side

#

I have like gcc 10 thru 14 all installed at once

#

then CC=gcc-14 cmake ..

light ice
#

Maybe?

#

Il install Debian 13 into a VM later to try and compile and test

willow ginkgo
#

you could try this quick hack

#

make a file called mm_malloc.h in the include dir of retro rocket

#

no contents

#

then try

#

it can't make it worse lol

#

yeah that will fix it

light ice
#

me when you dont properly provide these

willow ginkgo
#

wtf is that

#

what is your compiler adding

light ice
#

stack smashing protector

#

you need to disable it

#

or add runtime support

willow ginkgo
#

it shouldnt have one

#

turn that off

light ice
#

did you explictly disable it?

willow ginkgo
#

no nor did I enable it!

light ice
#

because alot of compilers have it on by defau;t

willow ginkgo
#

this should be my choice

#

this is not supposed to be portable code for Linux

light ice
#

well if you use the system compiler you have to be excplict

willow ginkgo
#

add the no stack protector to the cmake cflags

light ice
#

the limine template needs all of these

willow ginkgo
#

and the no stack check

#

...I don't use the limine template

light ice
#

yes

#

but the flags apply

willow ginkgo
#

my os is 15 years older than limine

#

you have it checked out from gh yes?

light ice
#

yes

willow ginkgo
#

I'm going to change the cmakelists so you can pull

light ice
#

lets get a working set of patches up

#

to be safe

willow ginkgo
#

there, pull now

light ice
#

alr

willow ginkgo
#

uh

#

thats zlib

#

which is part of the os

#

statically linked

light ice
#

no idea

willow ginkgo
#

no thats what im saying

#

its RIGHT THERE lol

#

what the hell have you done to your system

light ice
#

ungodly things

#

i recloned and

willow ginkgo
#

src/zlib in the retro rocket system

#

its right there!

#

did you pull

light ice
willow ginkgo
#

its still trying to do stack checks

light ice
willow ginkgo
#

and did you rerun cmake

light ice
#

i nuked the entire folder

#

and recloned

willow ginkgo
#

i really dont know wtf youve done

light ice
#

did you add it here?

#

to the asm flags

#

?

willow ginkgo
#

is your os putting -fstack-protector-strong in?

#

hmmmm

#

its only IN the asmflags

#

pull and redo cmake

#

hopefully we can get it down to just the zlib

light ice
#

i did mange that

willow ginkgo
#

so we only got zlib problem

light ice
#

i have these warnings too

#

and just zlib

willow ginkgo
#

where are all these warns coming from that i didnt enable

#

that more annoyingly are in third party dependencies

light ice
#

I’m able to compile most things

#

GCC compiles fine for example

willow ginkgo
#

mbedlts isnt my code...

light ice
willow ginkgo
#

its probably from -Wextra

#

as you have a newer gcc and they continually add new warnings in there

#

i'd ignore the warnings, they arent in my code

#

im not sure why it doesnt like zlib

willow ginkgo
#

change #include <zconf.h> to #include "zconf..h"

#

likely wont fix it, im cluthing at straws

#

but im wondering if your systems zconf is weird and its picking it up

#

also what do you get from:

#

env | grep -E '^(CFLAGS|CXXFLAGS|CPPFLAGS|LDFLAGS|CC|CXX)='

light ice
#

an error

willow ginkgo
#

no

light ice
#

same thing

willow ginkgo
#

just a return code of non zero

light ice
willow ginkgo
#

can you show me the whole build output pls

light ice
willow ginkgo
#

ty

willow ginkgo
# light ice

nm CMakeFiles/kernel.bin.dir/src/zlib/inflate.c.o | grep inflate

light ice
#

nm: 'CMakeFiles/kernel.bin.dir/src/zlib/inflate.c.o': No such file

#

if i do from build dir

willow ginkgo
#

what.....

light ice
#

im not familar with cmake that much

willow ginkgo
#

ok so

light ice
#

i ran from wrong foldeer

willow ginkgo
#

its not adding the z_ prefix

light ice
#

strange

willow ginkgo
#

line 12 cmakelists

#

take out Z_PREFIX=z_

#

leave Z_SOLO

willow ginkgo
#

hoooray

#

i'll commit that change

light ice
#

oh thats not good

#

with FRED

#

IDT is fine

#

time to work me magik

willow ginkgo
#

lmfao

light ice
#

how do i do incremental builds here?

willow ginkgo
#

btw what editor do you use

light ice
#

KATE

willow ginkgo
#

i have it all set up for clion if you use it, if you dont its ok

light ice
#

micro for terminal

willow ginkgo
#

as in, comes with .idea dir

#

it just gives syntax highlighting for .rrbasic and stuff

light ice
#

i get LSP and stuff dw

willow ginkgo
#

thanks soooo much for having the patience to work through this with me

light ice
#

its fineee

#

what files is your FRED stuff in?

#

new codebase to get used to and all

willow ginkgo
#

asm/loader.S and src/idt.c

#

nowhere else rn, i didnt get around to splitting it up yet

light ice
#

loader.S should be split a little

willow ginkgo
#

i was also going to add a boot flag you can specify to turn fred on and off, thats what the bool is for, but rn that does nothing

#

it shouldnt even be called loader.S kekeke

light ice
#

i can do that with QEMU

#

and disable on and off

willow ginkgo
#

it used to be a 32-64 trampoline for grub years ago

#

it used to do basic identity map paging, long mode, and idt

#

now it just does idt stubs

light ice
#

is there a helper to enable and disable the IF flag?

willow ginkgo
#

interrupts_on()

#

and interrupts_off()

#

while FRED is being set up, interrupts are off

#

they arent enabled for the first time till thats done with

light ice
#

ahh so its fine to not diddle that in the enable_fred_for_this_cpu?

willow ginkgo
#

yup

#

this is all pretty much early boot

light ice
#

im yeeting cpu_serialise because mov CRx is already considered as such

#

same for reading so itd redundant

#

and the exita bits set in FRED looked off

#

and do you set IA32_STAR?

#

im not sure if its needed unless it does CPL changes though

willow ginkgo
#

thought i did

light ice
#

but i know it can do corruption if thats not valid

willow ginkgo
#

i dont ever change CPL, everything retro rocket is ring 0

light ice
#

but it also does CPL3 things

#

so it should be fine?

#

just wanting to note this just incase

willow ginkgo
#

nothing is CPL3

light ice
#

yes ofc

#

but IA32_STAR

#

does that stuff and can HORRIBLY CORRUPT SHIT if not correct

willow ginkgo
#

if you did set up CPL3 interrupts they would never be called

#

so IA32_STAR should be set? it wouldnt be set anywhere but idt.c

light ice
#

should be fineee

willow ginkgo
#

its like just the way its handling the incoming interrupts thats bad, im sure youll figure it out real quick

light ice
#

whats the stackframe layout for RSP here?

#

besides what fred pushes

willow ginkgo
#

its 120 bytes pushed by the MPUSHA macro

#

i dont remember the order of the regs pushed, youd have to check the macro

#

its in the same file

light ice
#

the order dosnt matter for this

#

just need to do ze maths

willow ginkgo
#

15 regs is 120 bytes yes?

#

and its 15 regs

light ice
#

yes

willow ginkgo
#

oh and in retro rocket we dont have reentrant interrupts

#

so all interrupts run with interrupts off and dont re-enable them

#

it makes things much simpler

willow ginkgo
#

Interrupt and IRQ are different places, Interrupt for exceptions, and IRQ for the rest

#

see src/interrupt.c

light ice
#

ahh yeah il 100% wana put this into C then

#

after i made all the logic in ASM

#

il just make more in asm

willow ginkgo
#

yeah if that works for you, and its more readable for me

#

so long as we dont change the IDT path for now

light ice
#

i need to get better at asm anyways

#

IEQ num would be isrnumber minus 0x20 right?

willow ginkgo
#

bur yeah depending on the isr number etc it needs to be routed to either IRQ or Interrupt and IRQ takes 2 params Interrupt takes 3

light ice
#

yes i can handle this

willow ginkgo
#

irq 0 is isr 32

#

and i have 64 upwards reserved for msi

#

they still go through IRQ as normal

#

if i remember isrnumber is the raw number irqnum is the isr - 32

#

as in these macros

#

IRQ 0, 32
IRQ 1, 33
IRQ 2, 34
IRQ 3, 35
IRQ 4, 36
IRQ 5, 37
IRQ 6, 38

#

looks like it

.macro IRQ num byte
    .global irq\num
    .type   irq\num, @function
irq\num:
    MPUSHA
    mov $\byte, %rdi
    mov $\num, %rsi
    jmp irq_stub
.endm
#

been a while since i looked at that or ever used the isrnumber parameter

light ice
#

you use sysv right?

#

also im doing this in C

#

it tripple faults now

willow ginkgo
#

that the standard calling convention for 64 bit?

#

if so yes

light ice
#

yes

willow ginkgo
#

as in not the MS jank

#

yeah i do

light ice
#

i think this should have been right?

#

what is PUSH_SENTINEL btw?

willow ginkgo
#

its a sentinel value that marks when we move into an irq

#

its purely for stack traces

light ice
#

ahh

willow ginkgo
#

btw on the C side, you can use dprintf() to output to the qemu console

#

kprintf to print to the screen

#

dprintf works right from early boot

#

kprintf works as soon as flanterm is up

light ice
#

gonna add a bit like this

willow ginkgo
#

makes sense

#

at least you can diagnose from there with dprintf and stuff

light ice
#

i should be able to

willow ginkgo
#

if youre doing that may be nice to make a fred.h header

#

for the struct

light ice
#

it wont really need to be used elsewhere?

willow ginkgo
#

true, i just like to separate out structs

light ice
#

fair fair

willow ginkgo
#

because then i can add doxygen comments to them later

#

😄

#

FREDdo

light ice
#

it locks up if i have a kprintf

#

it does this without it

#

💀

willow ginkgo
#

yeah try dprintf

light ice
#

these remind me of page tables in the fb for some reason

willow ginkgo
#

kprintf is not a good idea in an interrupt

#

it spinlocks

light ice
#

fair

#

XD

willow ginkgo
#

tbh so does dprintf but only for microseconds

#

kprintf calls into flanterm

light ice
#

it does a tripple fault with that

#

and none of me logs

willow ginkgo
#

hmmm

#

not sure why

#

perhaps something too broken

#

if you need to, you should be able to attach gdb to the kernel

light ice
#

its getting somthing

willow ginkgo
#

is that the dprintf?

light ice
#

yes

willow ginkgo
#

vector 13

#

gpf isnt it?

#

smells like fred isnt configured right

light ice
#

tripple fault without the print

#

if i dont push the sentinal

#

it dosnt crash

#

but does the courrption?

willow ginkgo
#

hmmmm

#

is it trying to pull the sentinel as a return address or something

#

the sentinel is just the value -1

light ice
#

maybe?

#

im just gonna do this without the macros and use more of my OG code to be safe

#

atleast to debug

willow ginkgo
#

its important to push the regs though in MPUSHA

#

as those stop the interrupt handler trampling it

#

im sure youll figure it out

light ice
#

its just these?

#

im just inliining it

#

also i dont think you need all of these

#

with the sysv ABI

#

as it makes the C code do some saving its self

#

etc

#

maybe its the crappy patches

#

let me try SIMICS?

#

oh wait theat dosnt work

willow ginkgo
#

im sure ive seen talk of FRED stuff in normal qemu

#

in commit log

light ice
#

only if your CPU has it

willow ginkgo
#

but i dont see any official announce

light ice
#

they have it in KVM

willow ginkgo
#

the commit logs referring to FRED go back to 2023

#

hmm

light ice
#

wait is the kernel build with SSE?

willow ginkgo
#

yes

#

and the interrupt handlers save it with fxstor

#

but thats on the C side

light ice
#

it dosnt work

#

i have no idea why

#

here is what i got so far

#

wait

#

GPF?

#

its IA32_STAR

#

its expecting its ring0 sections too

#

because how its assuming segments

willow ginkgo
#

was gonna say

light ice
willow ginkgo
#

so you need to set IA32_STAR, and what, the kernel stack for ring 0 ints?

light ice
#

can you uhhh

#

set this properly?

#

with your GDT setup

willow ginkgo
#

we dont call ERETU

light ice
#

yes

willow ginkgo
#

we call ERETS

light ice
#

RETS

#

it still loads from it

#

regardless

willow ginkgo
#

hmmmm i really really dont want to go as far as changing my entire gdt

light ice
#

RED event delivery loads the CS and SS selectors with values
derived from IA32_STAR[47:32]

#

you may not

#

ifn its in a valid layout

willow ginkgo
#

its a copy of the limine one, copied to where i can control and alter it, but that has effects way outside of fred

light ice
#

uhh

willow ginkgo
#

src/gdt.c

light ice
#

so you dont know the exact layout?

willow ginkgo
#

i take a copy and validate it

#

i had no need to make any special one

light ice
#

why does gdt,c have page walk function

#

😭

willow ginkgo
#

it also does page table stuff

light ice
#

i think this one is your gob to deal with the GDTness

willow ginkgo
#

it clones the limine page table, so i can keep limine's identity map but identity map new pages as i wish for driver use

light ice
#

cursed

willow ginkgo
#

i dont want to change the GDT

light ice
#

💀

willow ginkgo
#

that effects stuff outside FRED

#

FRED should stay separate

#

dont you just need to set ISTAR to the selectors in the gdt?

light ice
#

this is the GDT limine gives

willow ginkgo
#

not change the GDT?

light ice
willow ginkgo
#

yes and thats the one i take copy of, i dont change it

light ice
#

because x86

#

BUT

#

if you only do ring0 64bit

#

i can make it work

#

maybe

#

hopefuly

willow ginkgo
#

yeah i dont have CPL3 selectors

#

which is why i dont really change GDT

light ice
#

thats not the part i worry

#

the ring0 selectors need to be in a special form too!

willow ginkgo
#

i thought this is all about interrupts and getting rid of legacy jank

#

so why is it making me change my gdt

light ice
#

because its how syscall/sysret work

willow ginkgo
#

didnt you say youre using limines stuff too?

light ice
#

and they share this MSR

#

i use limine

willow ginkgo
#

but i dont USE syscall/sysret

light ice
#

but my own GDT

willow ginkgo
#

i dont have any need for syscalls

light ice
#

let me find the docs on this

willow ginkgo
#

theres nothing special about limines default gdt

#

it shouldnt need more than that

light ice
#

CS = Bits 47:32
SS = Bits 47:32 + 8

#

so it should work

#

willow ginkgo
#

what even does this mean

light ice
#

okay so

#

the IA32_STAR msr

#

it takes thoees bits from it

#

and puts it into the segment registers

#

but it assumes an offset

#

for SS

willow ginkgo
#

dont you set IA32_STAR to 0?

#

in your OS?

light ice
#

nope

#
    uint64_t star = ((uint64_t)(0x18 | 3) << 48) | ((uint64_t)0x08 << 32);
    wrmsr(MSR_STAR, star);
willow ginkgo
#

ah

#

so its the 64 bit cs/ss

light ice
#

and it assumes an offset yeah

#

so if its not in the right layout

#

it wont work

willow ginkgo
#

ok, so in my case its what 6th and 7th entry?

light ice
#

yes

#

so it will be fine

willow ginkgo
#

only difference from what it says in the limine docs is the gdt is no longer "in bootloader reclaimable memory"

#

as i take a copy and move it

#

but that matters not

#

hmmm wait i dont move it any more ignore that

#

like i said it matters not, it doesnt get reclaimed

light ice
#

it dosnt seem to help

#
    uint64_t star = ((uint64_t)(0x28) << 48) | ((uint64_t)0x28 << 32);
    wrmsr(IA32_STAR, star);
willow ginkgo
#

it cant hurt to set it though

#

is it because we dont set up the stacks

#

yours does

light ice
#

the segmebts should be right

light ice
#

they dont get tripped

willow ginkgo
#

true, but its worth trying yeah

light ice
#

i cant finish this rn

#

i got no idea how to fix this

willow ginkgo
#

no worries

light ice
#

Only thing I know of

#

Is the patches don’t support certain edge cases

#

With the GDT

#

And will constantly flood you with GPFs

#

Like how it is now

#

If the GDT is fucked up enough to not be standard

willow ginkgo
#

how is a simple limine gdt an edge case

#

ive been working on something completely different tonight btw

#

^ it literally is a real production fs from the 80s that is pretty much like that array

#

double sided double density DFS

light ice
#

so its not that

willow ginkgo
#

i managed to get simics to work on windows

#

i applied your FRED patches

#

it still breaks if:

__attribute__((target("general-regs-only")))
void fred_ring0_entry(fred_frame_t* frame) {
    /*uint8_t vector = (frame->ss >> 32) & 0xFF;
    kprintf("eeee %x\n", vector);
    if (vector <= 0x1F) {
        Interrupt(vector, frame->error, frame->ip);
    } else {
        IRQ(vector, vector - 0x20);
    }*/
}
#

so, the crash isnt in the C side

#

just locked up here. no triple fault

willow ginkgo
#

i figured out why kprintf isnt working here i think

#

so it does run to the first int

light ice
willow ginkgo
#

it prints to a backbuffer, the backbuffer is flipped by the timer interrupt

#

without interrupts on it cant flip

#

so i temporarily put rr_flip() inside printf

light ice
#

Ah

willow ginkgo
#

i can come up with a better solution later

light ice
#

Would that cause crashes later though?

#

Why would*

willow ginkgo
#

idk yet

#

im adding a shit ton of debuggin

#

i also set IA32_STAR, and i set up all 4 stacks to eliminate that being a problem

#

btw simics is ass, what were intel thinking

light ice
#

I told you 💀

#

Everyone who has ever touched it

#

Fucking hates it

willow ginkgo
#

hmmm
no crash, continually firing the timer interrupt...

#

hmm wait no thats isr 0

#

not 32

#

wtf is that doing

light ice
#

How do you calculate the vector?

light ice
willow ginkgo
#

uhm why did you add: attribute((target("general-regs-only")))

light ice
#

To disable SSE on that function

willow ginkgo
#

ok

light ice
#

To make sure it wasn’t clobbering before it could get saved etc

willow ginkgo
#

that may break some interrupts

light ice
#

That only affects the one function?

willow ginkgo
#

yes but that calls IRQ which calls device drivers

#

e.g. sound mixer

light ice
#

The other functions would be able to use FPU after

willow ginkgo
#

i dont think it matters rn

light ice
#

It tells the compiler don’t use FPU registers for this

#

It would give a compile error

willow ginkgo
#

but something is fishy

void fred_ring0_entry(fred_frame_t* frame) {
    uint64_t vector = (frame->ss >> 32) & 0xFF;
    kprintf("fred int %lu\n", vector);
    if (vector <= 0x1F) {
        kprintf("Interrupt: %lu %lu %lx\n", vector, frame->error, frame->ip);
        Interrupt(vector, frame->error, frame->ip);
    } else {
        kprintf("IRQ: %lu %lu\n", vector, vector - 0x20);
        IRQ(vector, vector - 0x20);
    }
}
#

this is getting 0

light ice
#

Not a runtime error if it did

willow ginkgo
#

and thats from:

fred_ring0_entry_asm:
    MPUSHA
    PUSH_SENTINEL
    movq %rsp, %rdi
    call fred_ring0_entry
    POP_SENTINEL
    MPOPA
    ERETS
#

and:

light ice
#

The struct dosnt match with the sentinel?

#

Unless you changed that

willow ginkgo
#

ah it doesnt have the calculations for rdx etc

light ice
#

That’s what C does

#

You just need to put the stack pointer into rdi

#

But if the sentinel is there

#

You need to move the movq up

willow ginkgo
#

ok, so, we are back to where we started

light ice
#

Yes because it’s calculating the vector now properly

#

Because the stack isn’t misaligned

light ice
#

FRED pushes 64 bytes. Then you push 120. Then an extra 8 bytes and then you have the 8 bytes from call

willow ginkgo
#

i took the sentinel out for now

#

it isnt too important

light ice
#

Good good

willow ginkgo
#

im tracing down the stack with debug jank:

/* Both the Interrupt() and ISR() functions are dispatched from the assembly code trampoline via a pre-set IDT */

void Interrupt(uint64_t isrnumber, uint64_t errorcode, uint64_t rip) {
    __attribute__((aligned(16))) uint8_t fx[512];
    __builtin_ia32_fxsave64(&fx);

    kprintf("Interrupt %lu\n", isrnumber);

    for (shared_interrupt_t *si = shared_interrupt[0][isrnumber]; si; si = si->next) {
        /* There is no shared interrupt routing on these interrupts,
         * they are purely routed to interested handlers
         */
        if (si->interrupt_handler) {
            kprintf("Call handler\n");
            si->interrupt_handler((uint8_t) isrnumber, errorcode, rip, si->opaque);
            wait_forever();
        }
    }

    if (isrnumber < 32) {
        /* This simple error handler is replaced by a more complex debugger once the system is up */
        aprintf("CPU %d halted with exception %016lx, error code %016lx: %s at rip 0x%lx.\n", logical_cpu_id(), isrnumber, errorcode, error_table[isrnumber], rip);
        wait_forever();
    }

    entropy_irq_event();
    local_apic_clear_interrupt();
    __builtin_ia32_fxrstor64(&fx);
}
#

i expect one int call then wait_forever()

#

kprintf("Interrupt: %lu %lu %lx\n", vector, frame->error, frame->ip);
Interrupt(vector, frame->error, frame->ip);

doesnt actually seem to call that function at all

#

attepting to call Interrupt causes the exception 13

#

fxsave in the interrupt handler crashes it @light ice

light ice
#

I wonder if it’s to do with stack alignment?

willow ginkgo
#

maybe

light ice
#

What happens if you store it in the thread struct

#

Which is probably better than that

willow ginkgo
#

thread struct?

#

i dont have native threads

gritty osprey
#

#GP(0) If a memory operand is not aligned on a 16-byte boundary, regardless of segment. (See the description of the alignment check exception [#AC] below.)
on fxsave

willow ginkgo
#
__attribute__((aligned(16))) uint8_t fx[512]; __builtin_ia32_fxsave64(&fx);

looks aligned to me?

gritty osprey
#

to align you should subtract 8 bytes from the stack before calling i think

light ice
#

You could also allocate an extra 8 bytes in the struct and add 8 bytes to the pointer?

gritty osprey
#

you are breaking the ABI; the abi requires that the stack is aligned in a specific way at entry

#

there is an attribute to make the compiler align the stack

#

or at least to make clang align it

#

[[gnu::force_align_arg_pointer]]

willow ginkgo
#

hmmm taking out fxstor allows it to boot

light ice
#

If you remove the sentinel

willow ginkgo
#

there are other issues.... which are simics being simics i think, this vm isnt set up properly for rr

gritty osprey
#

idr what the exact requirement is, though

willow ginkgo
gritty osprey
#

maybe that is fine

light ice
#

It’s 16 byte alignment for the stacks

light ice
#

(64 + 120 + 8) % 16 = 0

#

Should be correct?

gritty osprey
#

after the call, the stack has to be congruent to 8 mod 16

willow ginkgo
#

everything should already be aligned to 16 bytes yes

gritty osprey
#

just use the stack aligning attribute

willow ginkgo
gritty osprey
#

ofc

willow ginkgo
#

it already is aligned

light ice
#

I guess not considering it’s blowing up

gritty osprey
#

if you get a crash

#

its not aligned lol

light ice
#

Add the attribute to the FRED C entry

#

So that can align it it’s self

gritty osprey
#

clang knows better how to do alignment tbh

willow ginkgo
#

well, it only blows up if we attempt to do fxstor, in a function 3 funcs removed from the asm

gritty osprey