Page 1 of 1

Attempting to create a wait function with PIT

Posted: Mon Mar 28, 2022 6:27 pm
by austanss
I am attempting to create a wait function using the PIT, in order to calibrate the local APIC timer.

Originally, I had a few oversights that prevented the PIT from functioning at all.
Now, when I try to implement the wait function, it's... horrible. The QEMU instance hangs and shits itself.
I assume this is some inefficiency that loads the virtual CPU too much for the instance to properly function, but that's just a hypothesis.

Code: Select all

// glass/src/dev/timer/pit/pit.c

void pit_deadline_wait(uint64_t delay_ticks) {
    ticks = 0;
    watching = true;
    
    while (ticks < delay_ticks)
        asm ("hlt");

    watching = false;
    return;
}
You can find the repository in my signature.

Re: Attempting to create a wait function with PIT

Posted: Mon Mar 28, 2022 6:45 pm
by Octocontrabass

Re: Attempting to create a wait function with PIT

Posted: Tue Mar 29, 2022 1:06 pm
by austanss
I did.

Check the bottom entry, my code was indexed on 5/30/21. All the other entries were indexed thereafter.

As for the macro, I don't quite understand the issue, or how it pertains to my problem. My PIT handler is completely separated from that code.

Re: Attempting to create a wait function with PIT

Posted: Tue Mar 29, 2022 1:32 pm
by Octocontrabass
austanss wrote:As for the macro, I don't quite understand what's wrong with it.
You forgot to save and restore R8, R9, R10, R11, R12, R13, R14, and R15. You shouldn't save or restore CR0, CR2, CR3, or CR4.

You need assembly stubs for IRQs too. Otherwise, you won't be able to switch tasks in response to a hardware IRQ unblocking a thread (because you won't be able to access the saved register state).

You're accessing the same variables both inside and outside an interrupt handler. Your compiler assumes interrupts will not change any variables, so it can turn your HLT loop into an infinite loop. Ideally you would use C++11 atomics to access those variables, but the volatile keyword is a lot easier and should work well enough.

And finally, timing in a virtual machine is pretty difficult. You may see delays that are much longer or shorter than you intended just because you're using QEMU instead of bare metal.

Re: Attempting to create a wait function with PIT

Posted: Tue Mar 29, 2022 1:40 pm
by austanss
Octocontrabass wrote:
austanss wrote:As for the macro, I don't quite understand what's wrong with it.
You forgot to save and restore R8, R9, R10, R11, R12, R13, R14, and R15. You shouldn't save or restore CR0, CR2, CR3, or CR4.

You need assembly stubs for IRQs too. Otherwise, you won't be able to switch tasks in response to a hardware IRQ unblocking a thread (because you won't be able to access the saved register state).

You're accessing the same variables both inside and outside an interrupt handler. Your compiler assumes interrupts will not change any variables, so it can turn your HLT loop into an infinite loop. Ideally you would use C++11 atomics to access those variables, but the volatile keyword is a lot easier and should work well enough.

And finally, timing in a virtual machine is pretty difficult. You may see delays that are much longer or shorter than you intended just because you're using QEMU instead of bare metal.
a. Compiler optimization flags are unaltered in my Makefile.
b. I beg to differ:

Code: Select all

ffffffff80204ce0 <pit_deadline_wait>:
ffffffff80204ce0:       55                      push   rbp
ffffffff80204ce1:       48 89 e5                mov    rbp,rsp
ffffffff80204ce4:       50                      push   rax
ffffffff80204ce5:       48 89 7d f8             mov    QWORD PTR [rbp-0x8],rdi
ffffffff80204ce9:       48 c7 05 94 94 01 00    mov    QWORD PTR [rip+0x19494],0x0        # ffffffff8021e188 <ticks>
ffffffff80204cf0:       00 00 00 00 
ffffffff80204cf4:       c6 05 89 94 01 00 01    mov    BYTE PTR [rip+0x19489],0x1        # ffffffff8021e184 <watching>
ffffffff80204cfb:       48 8b 05 86 94 01 00    mov    rax,QWORD PTR [rip+0x19486]        # ffffffff8021e188 <ticks>
ffffffff80204d02:       48 3b 45 f8             cmp    rax,QWORD PTR [rbp-0x8]
ffffffff80204d06:       0f 83 06 00 00 00       jae    ffffffff80204d12 <pit_deadline_wait+0x32>
ffffffff80204d0c:       f4                      hlt    
ffffffff80204d0d:       e9 e9 ff ff ff          jmp    ffffffff80204cfb <pit_deadline_wait+0x1b>
ffffffff80204d12:       c6 05 6b 94 01 00 00    mov    BYTE PTR [rip+0x1946b],0x0        # ffffffff8021e184 <watching>
ffffffff80204d19:       48 83 c4 08             add    rsp,0x8
ffffffff80204d1d:       5d                      pop    rbp
ffffffff80204d1e:       c3                      ret    

Re: Attempting to create a wait function with PIT

Posted: Tue Mar 29, 2022 3:09 pm
by austanss
Upon further examination, it seems as if the PIT never fires, at all. I have checked the IOAPIC state using info pic in QEMU and validated that the entry for IRQ 0 is proper and valid. I have also validated that the interrupt flag is set.

Re: Attempting to create a wait function with PIT

Posted: Tue Mar 29, 2022 4:11 pm
by Octocontrabass
austanss wrote:IRQ 0
Are you looking at ISA IRQ 0 or GSI 0? Most PCs (and emulators like QEMU) will route ISA IRQ 0 to GSI 2. Your OS can find these routes in the MADT.

It looks like there are a few places where your code uses the ISA IRQ number without translating it to a GSI number.

Re: Attempting to create a wait function with PIT

Posted: Tue Mar 29, 2022 5:08 pm
by austanss
Octocontrabass wrote:
austanss wrote:IRQ 0
Are you looking at ISA IRQ 0 or GSI 0? Most PCs (and emulators like QEMU) will route ISA IRQ 0 to GSI 2. Your OS can find these routes in the MADT.

It looks like there are a few places where your code uses the ISA IRQ number without translating it to a GSI number.
I just want to clear up some confusion I have with the IRQ-GSI relationship.

If I want to modify the redirection entry for IRQ 0, and the MADT specifies that IRQ 0 maps to GSI 2, do I access redirection entry 0 or redirection entry 2?

Re: Attempting to create a wait function with PIT

Posted: Tue Mar 29, 2022 5:11 pm
by Octocontrabass
Entry 2.

Re: Attempting to create a wait function with PIT

Posted: Tue Mar 29, 2022 5:37 pm
by austanss
Now I'm getting a Segment Not Present exception when the PIT interrupt does fire.

Code: Select all

   215: v=21 e=0000 i=0 cpl=0 IP=0008:ffffffff80204d40 pc=ffffffff80204d40 SP=0010:ffffffff8022efc8 env->regs[R_EAX]=ffff8000fec00010
RAX=ffff8000fec00010 RBX=ffff800000343000 RCX=0000000000000021 RDX=0000000000000021
RSI=0000000000000014 RDI=00000000000004a9 RBP=ffffffff8022efe0 RSP=ffffffff8022efc8
R8 =0000000000000000 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000000
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
RIP=ffffffff80204d40 RFL=00000286 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 0000000000000000 00000fff 00a09300 DPL=0 DS   [-WA]
CS =0008 0000000000000000 00000fff 00a09a00 DPL=0 CS64 [-R-]
SS =0010 0000000000000000 00000fff 00a09300 DPL=0 DS   [-WA]
DS =0010 0000000000000000 00000fff 00a09300 DPL=0 DS   [-WA]
FS =0000 0000000000000000 00000000 00000000
GS =0000 0000000000000000 00000000 00000000
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0030 ffffffff8021c020 00000070 00008900 DPL=0 TSS64-avl
GDT=     ffffffff8020c000 0000ffff
IDT=     ffffffff8021d000 00000fff
CR0=80000033 CR2=0000000000000000 CR3=0000000000104000 CR4=00000620
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000084 CCD=ffffffff8022efc0 CCO=EFLAGS  
EFER=0000000000000501
check_exception old: 0xffffffff new 0xb
   216: v=0b e=0212 i=0 cpl=0 IP=0008:ffffffff80204d40 pc=ffffffff80204d40 SP=0010:ffffffff8022efc8 env->regs[R_EAX]=ffff8000fec00010
RAX=ffff8000fec00010 RBX=ffff800000343000 RCX=0000000000000021 RDX=0000000000000021
RSI=0000000000000014 RDI=00000000000004a9 RBP=ffffffff8022efe0 RSP=ffffffff8022efc8
R8 =0000000000000000 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000000
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
RIP=ffffffff80204d40 RFL=00000286 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 0000000000000000 00000fff 00a09300 DPL=0 DS   [-WA]
CS =0008 0000000000000000 00000fff 00a09a00 DPL=0 CS64 [-R-]
SS =0010 0000000000000000 00000fff 00a09300 DPL=0 DS   [-WA]
DS =0010 0000000000000000 00000fff 00a09300 DPL=0 DS   [-WA]
FS =0000 0000000000000000 00000000 00000000
GS =0000 0000000000000000 00000000 00000000
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0030 ffffffff8021c020 00000070 00008900 DPL=0 TSS64-avl
GDT=     ffffffff8020c000 0000ffff
IDT=     ffffffff8021d000 00000fff
CR0=80000033 CR2=0000000000000000 CR3=0000000000104000 CR4=00000620
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000084 CCD=ffffffff8022efc0 CCO=EFLAGS  
EFER=0000000000000501


error: cpu exception 0xb @ 0xffffffff80204d40
error code: 0x212⏎ 
Instruction pointer is irrelevant.
Error code is 0x212 (1000010010).

1000010 01 0: exception originated internally, missing segment in IDT, at entry... 66??

Re: Attempting to create a wait function with PIT

Posted: Tue Mar 29, 2022 5:55 pm
by Octocontrabass
austanss wrote:1000010 01 0: exception originated internally, missing segment in IDT, at entry... 66??
Entry 33 (0x21). Gate descriptors are 8 bytes, and each entry in the IDT uses two descriptors instead of one.

The segment is indeed not present.

Re: Attempting to create a wait function with PIT

Posted: Tue Mar 29, 2022 6:34 pm
by austanss
Octocontrabass wrote:
austanss wrote:1000010 01 0: exception originated internally, missing segment in IDT, at entry... 66??
Entry 33 (0x21). Gate descriptors are 8 bytes, and each entry in the IDT uses two descriptors instead of one.

The segment is indeed not present.
haha i forgot to use my own macros :lol: