#Nyaux
1 messages · Page 6 of 1
OKAY NOW
Wait acpi_entry_header is a thing?
in uacpi? yes, acpi_entry_hdr
Oh right lol
lmaoo
so 1 lapic, 1 ioapic, bunch of interrupt service overrides and a local apic nmi
Thats correct
me trying to read acpi spec trying to understand what iso's are 
yeah SRAT seems to reference that as well
Now add more CPUs
what is SRAT anyway?
NUMA affinity table
What memory belongs to what domain etc
By default irqs are identity mapped to ioapic, overrides allow the platform to redirect them
For example, if your machine has the ISA Programmable Interrupt Timer (PIT) connected to ISA IRQ 0, but in APIC mode, it is connected to I/O APIC interrupt input 2, then you would need an Interrupt Source Override where the source entry is ‘0’ and the Global System Interrupt is ‘2.’
yea im seeing 
Yup
and thats what global system interrupts are? interrupts that came from the ioapic i suppose?
is that correct?
Yeah
will come in handy for nyaux os
do i need to parse something or what
parse is a little extreme, it's mostly casting pointers
these overrides tell you what a traditional IRQ's corresponding GSI is
yes but im so confused like what i need to do next, to like configure the apics or whatevs
okay then ill just read them i suppose and print them out
Lol
which bus the IRQ is said to be from
ah okay
Bro
i shouldn't worry about the bus, i don't even remember that being a field
hm?
i saw some structure definitions were added, i will transition to them eventually
acpi_madt_x
I think I added everything that your average hobby osdever might need, but I will add more eventually
i look forward to using the SRAT and SLIT definitions in the future
obscene sounding things but what can you do
I wanna support those from the get go in my os
wow i love uacpi
Will be interesting to design allocators with those in mind
okay so 5 isos coming from the legacy isa bus
lets read that irq number and gsi number!
No need to do case 2, uACPI has enums for those
wow
i love uacpi even more
whats the enum called
i would be using them already but i decided to not be too radical as i've only just, i think, acquired a complete enough understanding of working set model based vmm design to implement a not overly impressive one - but proper NUMA support with per-domain VM management is something i want to do
Above the madt definition
Yeah that's definitely interesting
legacy irq 0 goes to 2
Looks correct
It overrides polarity and or triggering

😭
polarity says whether the irq line has to be high or low for the irq to happen
triggering says whether the irq is triggered by a transition from low to high (or high to low), or whether it's triggered by the line just being in the high (or low) state
you'll need them when you want to establish redirections with the I/O APIC
that will become relevant when you want to handle traditional IRQs
ah okay
oooo what is this
👀
global system interrupt base? is this like a table that describes which gsi's go to which vectors?
or smthin
every ioapic serves gsis [gsi base, gsi base + ioapic pin count)
oh so its memory mapped to the actual gsi pins
okay
what do i do with that lmao
can i like trigger a gsi if i write to gsi base or smthin

you can use this information to route interrupts to LAPICs
interrupts are triggered externally
you cannot trigger them yourself
oh
that's the sole purpose of the IOAPIC
i just put the lapic id into one of the gsis?
and its routed?
no, you write to the IOAPIC's redirection table
Read the ioapic spec
bruh
okay wait
Yes
oh okay
3.1
okay so its a register
i need to select a register in the REGISTER SELECT REGISTER
and then i can write or read from a register with the
WINDOW REGISTER
okay
to access these registers im guessing its ioapic address + FEC0 for the select register
correct?
i think thats correct
can there be multiple io apics?
or is there like only one
?
Indeed 
Yes
I have tested on 16 and 24 core cpus and they’ve only had one i think
I can’t comfortably approve you that
But my guess would be that especially high core server cpus are more likely to have multiple
im not writing a kernel for server cpus
☠️
maybe if i was linux sure but im not linux
im mr nyaux kernel for poo poo hobbyist os
so the moment i find an ioapic im gonna store the ioapic address as a global variable
and just assume theres only 1
That works too ig
btw @ionic jetty this is correct yes?
Yeah, and often there's two
for now im just gonna assume theres only one (FOR NOW)
That sounds high tbh
I remeber the ioapic having less regs
is what intel says
I get the ioapic base from acpi
yep
And then IOREGSEL has offset 0
Maybe the base address for the first apic
idk 🤷♂️
Base address of the first ioapic is usually there
Not always
So like first ioapic is at FEC0 0000
So read it
The next one at this + 0x1000
And so on
Thats the xy
And then the 00 at the end is what i said
Offset 0
but intel says next register is base + 10h?
no
huh?
yes
Nice
how am i supposed to put it then
Yes remove the h
Its intels way of saying this number is hex

okay i made my cool functions for writing to and reading from the ioapic registers
okay uhhhhhh
Now lapic
Lapic is the per cpu controller
yes i know
and get SMP
And a high precision low overhead per core timer
You write functions to do what we just listed
the lapic also has these kind of registers?
lapic spec sheet where?
Read spec
Sdm
Thats a rare achievement
okay i see a bunch of registers
Yup
im guessing its different to ioapic where you can just directly read and write the registers?
Wdym
as in instead of selecting your register in like a register
and writing to a rw register
like the io apic
No select here
Yes
Theres an msr for it too
And the address is most likely to be fixed if i remember correctly
okay made some functions that can read and write to a lapic register
okay
uhhhh
whats exactly next?
Start other cores
no gsi base is the number of the first gsi that is handled by that ioapic
Or do something else
also re multiple ioapics ```
qookie@selenium ~ λ dmesg | grep -i ioapic
[ 0.035325] IOAPIC[0]: apic_id 7, version 33, address 0xfec00000, GSI 0-23
[ 0.035330] IOAPIC[1]: apic_id 8, version 33, address 0xfec01000, GSI 24-55
[ 0.970713] ACPI: Using IOAPIC for interrupt routing
on my laptop
oh get u
only got one
😎
from gsis 0-119
How many cpus
1 cpu, 6 cores (and 6 threads)
2 ioapics with 6 cores? Okay
like what, if i have a apic_init function what do i do next after i set the ioapic global variable address and stuff
how do i start getting things like irqs or smthin
i'm pretty sure most amd platforms have 2 ioapics
Yup
Dont forget to route spurious ints too
Init lapic by setting the spurious vector
route spurious ints?
kk
or mask them i forgot
okay so lapic_base + 0xf0
ima write to it
okay i need to set bit 8 to 1
to enable it?
okay im writing 0x80 to it
which should just be the 8-eith bit that is on
try again
wdym?
you got it wrong
oh wait
wrong bit
thats the 7th bit
sec
0x100
no idea whats gonna happen but we will see?
you probably want a different vector than 0
what
the spurious vector?
oh i gotta select a vector
uhhhh
0x33 yea!
page faults
bruh
this should be right?
why is bro page faulting
☠️
why cast the address to a volatile uint32
you're ignoring lapic_base and adding ioapic->address?
OH
lmao
😭
please turn on -Wall -Wextra -Werror
whoopsie
-Wpedantic if you're not using gnu extensions
what's cr2?
huh ??? 
hm the first 4GB should be mapped unconditionally
huh
okay sec
Ive seen that multiple times now
Why is that
I mean yes most devices are there
But like why not map them whenever u need them
idk i wasn't there in the room when the limine spec was being written
unless you're using revision 1
Oh you meant its a limine thing
info tlb causes qemu to crash lol
then the first 4 gib isn't mapped
the first 4GB is not identity mapped then, it's still mapped into the hhdm
im using revision 1
im so confused
why isnt the hhdm working 
i mapped like pretty much everything
Limine broke, ask for replacement
😠
wheres limine 2 mintsuki
i need it now

already existed
when???
we're at Limine 7.x
no we need limine uhhh
20.x
uhhh does this look like the end of the hhdm mappings to yall
FFFF8000D0788000 is calculated as the limit of the hhdm
sounds broken
or well
your recreated hhdm doesn't match limine's hhdm if you don't map the first 4GB unconditionally
i walk through the memmap
and calculate the hhdm limit through every entry
yea
but he's using base rev 1
yes and on top of all memory map entries, limine also maps the first 4GB unconditionally into the hhdm
the hhdm mapping still exists?
what
yes
Why doesn't it map the first 4g?
it does
rev 1 gets rid of the identity mapping
Oh
not the first 4GB in the hhdm
Ultra just has a higher-half-exclusive mode in the proto
i am so confused
idk how else to word it
limine unconditionally maps [0, 0x100000000) into the hhdm, and on top of that whatever the memory map says
so i gotta map 0 to 0x100000000
correct?
if you want to end up with the same hhdm as limine gave you
okay
Thats because on x86 mmio is usually 3-4GiB phys, so it would be very inconvenient to not have it mapped
but wait
alternatively you could just allocate some vm space and map the lapic in yourself, without relying on the hhdm
does the like
the memmap represents physical memory yes?
and like wait
what if a memmap entry represents like
something in that range
0 to 0x100000000
what am i supposed to do in that case
cause currently how i calculate the hhdm limit is like
add 0x1000 to hhdm_limit as i map, looping through each page
why do you need the hhdm limit
cause i need to represent the hhdm as an allocated virtual address region
limine basically does max(what you did, 0x1_0000_0000)
what
always mapping at least 4gb for this exact reason, mmio devices that aren't "real" memory with "real" memmap entries, which live around 4gb on pcs
So what's the problem exactly
okay so i need to calculate the END of the hhdm
Why dont u have that memory mapped on the higher half
no, map [hhdm, hhdm + 4G) and then map any memory map entries that are >4G
btw do you know that cases can fall through to other cases
you don't need to repeat the body a million times
okay i know what to do
it may be stupid but
🤷♂️
i think itll work
easy
😎
and then i can just unconditionally map the lower 4gib
easily and add the hhdm pages
as normal
yea i think this'll work
THIS SHOULD WORK LETS SEE CHAT 😎
oh
okay
um
this did NOT work!
uhhhh
oh wait
lOL ITS ZERO?
WHAT??
😭
wait nvm
okay i think im doing this wrong
i dont know what to do
how tf am i gonna calculate the hhdm limit and map all of this ughhhh
.
thats what i tried to do
it's that simple
like u saw this loop and this loop causes an oom error cause its probs going on forever
Im detecting big presence of a skill issue
😠
ok
perchance..
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
please invent a printf ```c
serial_print_color("Region Information!: Base: ", 0);
serial_print(itoah(buffer, cur_node->base));
serial_print(", Length: ");
serial_print(itoah(buffer, cur_node->length));
serial_print("\n");
Lmaoo
He literally has one
Since uACPI uses it
@tawdry mirage i think this is a valid hhdm limit similar to limines??
cause it didnt page fault and now it works?
you are winrar
winrar?
i am winrar??
wowie !!!!
im winrar guys
😎
okay so it enabled the lapic!
i wrote to the spurcious vector register thingy
and it worked
tho nothing interesting happened
what do i do next now that i've enabled the lapic 😎
uhhh
is there anything else i need to configure or?
you want to configure lints as the madt lapic nmi entries say
nmi?
lints?
you literally mention it here
ok lemme read acpi spec again
This structure describes the Local APIC interrupt input (LINTn) that NMI is connected to for each of the processors in the system where such a connection exists. This information is needed by OSPM to enable the appropriate local APIC entry.
okay
nmi is non maskable interrupt right?
yes
okay so each lapic has 2 lint pins
lint0 and lint 1
so a nmi can be connected to multiple processors as well and stuff
okay
okay so im confused
lol what
oh wait
wrong struct
oh wow
an nmi connected to lint 1
!!
whatever will i do with this information
LOCAL APIC LINT THIS NMI IS CONNECTED TO: 1 FOR PROCESSER ID: FF
this is an nmi for all processors
according to acpi spec
okay
i dont get what im supposed to do with this information? 😭
yes a non maskable interrupt is connected to lapic pin 1 for all processors okay? 😭
i dont get what i have to configure
like huh?
generally it's more useful to start assuming you don't need to care until you do; there's a lot of highly specific information in these tables that won't matter to you at this stage. I'm sure it's possible to generate an NMI in qemu, but I would argue it's almost completely irrelevant to you
what
nmi in the monitor iirc
tl;dr: "what do I have to configure?" -> nothing
okay?
so what do i do now ig
i've enabled the lapic
parsed the heckin madt entries ig
set surprious interrupts to vector 33
whats next?
to do?
what was the original goal of this excursion?
okay im reading the sdm
says i need to access lapic base + 0x320 register to setup a timer?
okay so i need to set bits 0-7 to my isr handler for a timer ig?
seemingly
okay
now to configure the timer
and try it out
and see if we get an irq
and it handles it
and prints out "tick"
what should i set inital count to?
nothing happened 😔
i think cause its masked?
i dont know how to unmask it tho
sdm doesnt say which bit to set
ok bit 16 is the mask bit
WHY ISNT IT DOING ANYTHING

COME ON DO SOMETHIN
TRIGGER ME INTERRUPT

this should BE riight
😭
Worst DRY violation ive ever seen
Why isn’t the lapic timer doing anything like at all
Try sending a self ipi to test it via the ICR
Registers
You get to choose the vector
If that doesn't work your LAPIC is initialized incorrectly (maybe check the msr?)
Okay wait
But from how it looks Omar am I at least configuring the lapic correctly? I set the divide register to divide by 1, set initial count to 1 and set the vector to 34
You misconfigured
Line 71
Where you write to offset 0x320
That isn't how bit logic works
The bit isn't set though
Whatever bit is the value you were noting isn't set in 0x34
oh right
Yeah
And you're setting the value
So it doesn't matter
Ths initial count should be set last btw
That's what starts the timer
Yeah then it errored out because vector was likely zero initialized
and it's illegal to send an IRQ to vectors < 32
And it's probably also giving an error when you set all those bits (a lot reserved) in the timer vector register
no im setting it to 34
Before when you orred those bits
Did rearranging the code and not setting the bits fix anything
?
nope
Try setting the initial count to 1000
1 is quite fast especially considering you're using an emulator
ok

If they are, check if cr8 is zero (should be if you never touch it)
no thats not how x86 works
😠
why am i not allowed to put the value of rflags into i
because thats not how x86 works
what am I not allowed to access non general purpose registers or something
your not telling me why
not in this way no
and also thats not how at&t syntax works
and if you are using -Mintel.. just no
Then am I supposed to read the rflags register
push rflags, pop rax, get rax into a variable via =m in the output
I thought that for some reason he was trying to read rflags, not really read the entirr convo
I probably read this wrong
I’m did
And nothing happens still
Sorry I was at school
Executing sti does nothing
before setting up apic
and cr8 is 0xe
All of it?
okay im back
from school
yea uhhh
BRO CR8 IS ZERO WTF
😭
WORK U DAMN STUPID TIMER
GRRR
the lapic timer is a meanie
wtf
what do you expect to be in cr8?
also you are moving to cr8
of course it's gonna be 0
what significance does cr8 have here??
type info lapic into qemu monitor
see if it's configured correctly
cr8 was 0xe
which masks out irq 34
so i have to set it to zero
weird
okay
tf
WHY IS THE TIMER MASKED AND WHY IS IT SET PERIODIC AND WHY IS IT VECTOR 5😠
hm?
i clearly setup the surpious vector register
IRR is not set
irr?
after i enable the lapic i set the timer to divide by 1
then i set the vector of the lvt timer to vector 34
show the values
okay
you write to the lapic registers
write_lapic_register(madt->local_interrupt_controller_address, 0xf0, 0x100 | 33);
serial_print("enabled lapic?\n");
// enable lapic timer?
// divide by 1
write_lapic_register(madt->local_interrupt_controller_address, 0x3e0, 7);
// set vector to 34
write_lapic_register(madt->local_interrupt_controller_address, 0x320, 34);
// set inital count?
lapic_addr = madt->local_interrupt_controller_address;
write_lapic_register(madt->local_interrupt_controller_address, 0x380, 1);
no no it was part of my previous message
what im confused
show the values...
...you write to the lapic registers
thats the values ^
you are configuring lapic timer to be one-shot btw
yea ik
and it's going very slow
okay but
what is that????
oh right, i totally forgot about that
i have no idea if it's significant or not
but for me it's set to what i believe is my timer interrupt vector
¯_(ツ)_/¯
i have no idea but that value is put there if i write to the LVT timer register
weird
writeRegister(.LvtDivide, 3);
writeRegister(.LvtTimer, @as(u32, timer_vector.?));
writeRegister(.LvtInitialCount, 0x5000);```
i write those values
LvtDivide being 0x3e0, LvtTimer being 0x320 and LvtInitialCount being 0x380
can you show your write_lapic_register?
writing those values did nothing
sure
volatile void write_lapic_register(uint32_t lapic_base, uint8_t reg_offset, uint32_t data)
{
*(volatile uint32_t*)(lapic_base + reg_offset + hhdm_request.response->offset) = data;
}
why?
idk, ask someone who knows more than i do
all i know is that you should use the msr, but it should be the same
okay
well that's good at least
can you add -trace apic_mem_write* to your qemu command line
apic_mem_writel 0xf0 = 0x000001ff
apic_mem_writel 0x3e0 = 0x00000003
apic_mem_writel 0x320 = 0x00000020
apic_mem_writel 0x380 = 0x00005000```
i get this when configuring my lapic + lapic timer
apic_mem_writel 0xf0 = 0x00000121
enabled lapic?
apic_mem_writel 0xe0 = 0x00000003
apic_mem_writel 0x20 = 0x00000022
apic_mem_writel 0x80 = 0x00005000
which is writing to the spurious vector register, lvt divide, lvt timer and lvt initial count
well
that's not looking good
tf
oh
dumbass
uint8_t
OH
☠️
OH
uint16
apic_mem_writel 0xf0 = 0x00000121
enabled lapic?
apic_mem_writel 0x3e0 = 0x00000003
apic_mem_writel 0x320 = 0x00000022
apic_mem_writel 0x380 = 0x00005000
well um
that's a little better
you can -trace apic_local_deliver*
kk
to figure out if its firing any interrupts
i get a bunch of apic_local_deliver vector 0 delivery mode 0 apic_local_deliver vector 0 delivery mode 0 apic_local_deliver vector 0 delivery mode 0 apic_local_deliver vector 0 delivery mode 0
so yeah the same for you
-d int then
kk
maybe you're not registering an interrupt handler properly?
lol
idk at this point
but it seems to be firing
oh
its one shot
yea its one shot?
maybe it fires before you get a chance to unmask it
but i think if you set cr8 to 0 and there's any pending interrupts they should fire anyway
i do sti and i do set cr8 to 0 before ANYTHING
if they were pending due to the cr8 masking them that is
the last thing i do is set inital count
try a periodic timer
kk
anything when you use -d int?
interesting
yea doing -trace apic_local_deliver*
shows
its sending interrupts
spamming my stdio
oh
oh?
oh rip
well the idt shouldn't have anything to do with the interrupts not arriving
yea
are you messing with the PIC/PIT/IOAPIC?
ioapic yes?
no wait no im not doing anything with the ioapic
hm ok then
so like wtf
confused
will i post my code onto github or smth
cause idk
why the interrupts
arent arriving
its sending interrupts
the lapic looks configured correctly
whats going on

i am not able to help even
qemu trace clearly tells you that the apic is trying to deliver interrupts
my kernel is cursed
but something is preventing them from reaching the cpu
yea 😭
is it a limine thing idk
about
can you try using 0xff as the spurious interrupt vector?
or smthin
no its not
or it shouldn't be
does nothing
hm ok well it was worth a try
one more difference is that your lvt0 is configured as edge triggered and for me it's configured as level triggered
idk how it all works, but i can see that it's a difference
yea but this shouldnt rlly do anything
i should still be getting an interrupt
at the very least
😭
idk what to do
im banging my head againist the wall with this issue 
like bro
why wont bro just
receive the heckin interrupt

😭
kk
9th bit is off
001001000110 is the binary of 0x246
@finite summit
triggering the timer irq interrupt i have setup in my idt manually works fine
meaning that idt is configured correctly
yea
okay
if that fixes it, someone forgets to send an EOI
how fast does current_count go up? (down?)
quite fast
sent one
void send_lapic_eoi()
{
write_lapic_register(lapic_addr, 0xb0, 1);
}
before enabling the lapic
nothing happened
to the point it spams my terminal when tracing each interrupt the apic sends in qemu
do you have the vector set up as an interrupt or trap gate? you could be getting so many interrupts it never gets to print anything. You could also up the interval so you get fewer interrupts
interrupt gate
are you using kvm?
no
welp
-accel tcg
just making sure
anything !tcg would make it so -d int doesnt print anything
or at least kvm, cant say for sure for other
this makes zero sense
in why the cpu
isnt getting any interrupts at all
from the apic
@sudo qemu-system-x86_64 $(IMAGE_NAME).iso -M q35 -bios /usr/share/edk2-ovmf/OVMF_CODE.fd -m 3G -accel tcg -serial stdio
my qemu command
https://pastebin.com/kgaDRuTf my whole apic.c
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
irr = 34 seems curious
That means the LAPIC has that irq in it's queue
but something is blocking it from getting sent
you can see clearly i do sti
so i can get interrupts
what other thing could possibly block it???
is it something with limine?
TPR in the LAPIC
tpr?
Task Priority Register
also if the LAPIC is waiting for an EOI
he's not getting an interrupt to begin with
^^^
i mean i can try reading the tpr and see the value
what?
it is definitely broken, but if he compiles in debug it's probably moving 0 to cr8 anyway
you are moving from reg to cr8
but you are telling gcc you are reading to the register
asm("mov %%cr8, %0" : "=r"(i));
this is how you read out of cr8 to i
since he initializes it to 0 beforehand
oh nvm if it's debug then it's probably on the stack and the register will contain garbage
yea he adopted the same garbage values i use in zigux
i even have a big ass troll face in the source code right above it
you want 0xB not 0x3, because the value is _X__ not ___
i used 0x3 with initial count of 5000 because it gave me roughly what i was looking for, apparently setting lvt divide to 0x3 gives you a divisor of 16
professional lapic timer calibration
uhhh weird results
oh yeah cause we end at _start and disable interrupts and just hlt
BUT IT WORKS!!!!
i like how i spotted the broken inline assembly 3 hours ago but i didn't care about it because i miscompiled the code in my head
life could've been easier
also you're supposed to write 0 to the eoi register
not 1
what
i think so at least, i remember reading about this somewhere
and yet the comment says divide by 1
oh yeah
make up your mind
i changed it
lol

well now this epic gamer timer is working
do i hook it up to my scheduler for funny shanngains or what 
wait ill need to like "calibrate" the timer
lol
uhhhh
how do i make the timer "calibrated" so the timer ticks at like
a proper value
that is quantifiable and not just random number 1000 divide by 1
you compare how fast it ticks against a different timer :^)
bruh
☠️

i remember someone talking about the hpet
uhhh
i guess ill try and use that?
(i have absolutely no idea how im gonna "calibrate")
hpet tells you how fast it ticks
you can measure how many lapic ticks elapse in a certain amount of time by polling the hpet
you pick that amount of time, the longer the better (more accuracy)
but you also dont want it to be too long for obvious reasons
okay so do i set the lapic timer to be one shot, messure the hpet, wait for the lapic timer to fire an interrupt, once its interrupted i messure the hpet and thats the timer calibrated?
no, you mask the lapic timer and read it's counter value
oh
kk
what should i set the divider to?
you set the lapic timer up as one shot, mask it, mark starting hpet tick count, set lapic timer ticks very high (0xffffffff or something, idk) wait for a certain amount of time to pass, mark current lapic counter, check how many ticks elapsed (0xffffffff - current) and save that somewhere so you can accurately configure it in the future
probably 1 is the best
okay
it's your choice
// set vector to 34 , ONE SHOT, MASK IT
write_lapic_register(lapic_addr, 0x320, 34 | (1 << 15));
okay
ill set inital count to somthin like
uhhh
0xffffffff
okay ill use trusty handy dandy uacpi to scan for the hpet table
btw i love u copyobject abuser for making uacpi
its SO much better then lai
The APIC timer frequency will be the processor’s bus clock or core crystal clock frequency (when TSC/core crystal
clock ratio is enumerated in CPUID leaf 0x15) divided by the value specified in the divide configuration register
you might want to set the divide to 2/4, depending on how fast the clock actually is 
wha
I noticed that divide by 1 can be very inconsistent on QEMU
yeah you probably want to use a higher divisor then
dunno what this means or why I have to use a higher divisor but I’ll do that cause u said so !!

the apic timer ticks at the speed of the bus clock divided by what you configure
oh that’s makes more sense lmao
right
yeah
is it like a register thing with hpet as well