Page 1 of 1
Weird PIT issues
Posted: Mon Oct 19, 2020 3:06 pm
by abstractmath
I have this code:
Code: Select all
#include "pit.h"
#include "pic.h"
#include "../lib/common/port.h"
#include "../lib/typeout.h"
void timer_interrupt(){
pitd_tick++;
}
uint32 pitd_init(uint32 clock_frequency){
uint32 divisor = 1193182 / clock_frequency;
p_write8(0x43, 0x36);
pitd_tick = 0;
uint8 l = (uint8)(divisor & 0xFF);
uint8 h = (uint8)(divisor >> 8);
p_write8(0x40, l);
p_write8(0x40, h);
picd_register_interrupt_handler(0, timer_interrupt);
}
void pitd_wait(uint32 ticks){
uint32 ticks_now = pitd_tick;
uint32 time_passed = 0;
while (time_passed <= ticks){
time_passed = pitd_tick - ticks_now;
//screen_printf("is\0", time_passed, "\n\0");
}
return;
}
And I'm getting this weird issue where after I call the pitd_wait() function, it seems like the emulator just skips right over the while loop and doesn't wait at all. However, if I print the value of the time_passed variable (by uncommenting the screen_printf() line) it does actually wait the set the amount of time. Any advice here would be much appreciated as I'm at a loss.
Edit: It seems like any function call fixes the issue, so now I'm wondering if this is the compiler doing something funky. Is it possible that for whatever reason the compiler is throwing out my loop?
Re: Weird PIT issues
Posted: Mon Oct 19, 2020 3:36 pm
by MichaelPetch
Can you show how you declared `pitd_tick`? I will gather you didn't mark it as volatile so the compiler probably optimized the entire loop away. If you don't mark it volatile then the compiler will just assume its value never changed.
Re: Weird PIT issues
Posted: Mon Oct 19, 2020 3:39 pm
by abstractmath
I also tried marking it as volatile just now, but the same issues occur.
Re: Weird PIT issues
Posted: Mon Oct 19, 2020 3:50 pm
by MichaelPetch
Can you compile the file with this code using the `-S` option to output the assembly code and post it here? Either that or objdump your kernel and show us the generated instructions for the function `void pitd_wait(uint32 ticks)`. Anything that can show us the generated code for that function will do.
Re: Weird PIT issues
Posted: Mon Oct 19, 2020 3:56 pm
by abstractmath
Certainly, here's the output of doing an objdump -d,
Code: Select all
drivers/pit.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <timer_interrupt>:
0: f3 0f 1e fa endbr64
4: 55 push %rbp
5: 48 89 e5 mov %rsp,%rbp
8: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # e <timer_interrupt+0xe>
e: 83 c0 01 add $0x1,%eax
11: 89 05 00 00 00 00 mov %eax,0x0(%rip) # 17 <timer_interrupt+0x17>
17: 90 nop
18: 5d pop %rbp
19: c3 retq
000000000000001a <pitd_init>:
1a: f3 0f 1e fa endbr64
1e: 55 push %rbp
1f: 48 89 e5 mov %rsp,%rbp
22: 48 83 ec 20 sub $0x20,%rsp
26: 89 7d ec mov %edi,-0x14(%rbp)
29: b8 de 34 12 00 mov $0x1234de,%eax
2e: ba 00 00 00 00 mov $0x0,%edx
33: f7 75 ec divl -0x14(%rbp)
36: 89 45 fc mov %eax,-0x4(%rbp)
39: be 36 00 00 00 mov $0x36,%esi
3e: bf 43 00 00 00 mov $0x43,%edi
43: e8 00 00 00 00 callq 48 <pitd_init+0x2e>
48: c7 05 00 00 00 00 00 movl $0x0,0x0(%rip) # 52 <pitd_init+0x38>
4f: 00 00 00
52: 8b 45 fc mov -0x4(%rbp),%eax
55: 88 45 fb mov %al,-0x5(%rbp)
58: 8b 45 fc mov -0x4(%rbp),%eax
5b: c1 e8 08 shr $0x8,%eax
5e: 88 45 fa mov %al,-0x6(%rbp)
61: 0f b6 45 fb movzbl -0x5(%rbp),%eax
65: 89 c6 mov %eax,%esi
67: bf 40 00 00 00 mov $0x40,%edi
6c: e8 00 00 00 00 callq 71 <pitd_init+0x57>
71: 0f b6 45 fa movzbl -0x6(%rbp),%eax
75: 89 c6 mov %eax,%esi
77: bf 40 00 00 00 mov $0x40,%edi
7c: e8 00 00 00 00 callq 81 <pitd_init+0x67>
81: be 00 00 00 00 mov $0x0,%esi
86: bf 00 00 00 00 mov $0x0,%edi
8b: e8 00 00 00 00 callq 90 <pitd_init+0x76>
90: 90 nop
91: c9 leaveq
92: c3 retq
0000000000000093 <pitd_wait>:
93: f3 0f 1e fa endbr64
97: 55 push %rbp
98: 48 89 e5 mov %rsp,%rbp
9b: 89 7d ec mov %edi,-0x14(%rbp)
9e: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # a4 <pitd_wait+0x11>
a4: 89 45 f8 mov %eax,-0x8(%rbp)
a7: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
ae: eb 0c jmp bc <pitd_wait+0x29>
b0: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # b6 <pitd_wait+0x23>
b6: 2b 45 f8 sub -0x8(%rbp),%eax
b9: 89 45 fc mov %eax,-0x4(%rbp)
bc: 8b 45 fc mov -0x4(%rbp),%eax
bf: 3b 45 ec cmp -0x14(%rbp),%eax
c2: 76 ec jbe b0 <pitd_wait+0x1d>
c4: 90 nop
c5: 5d pop %rbp
c6: c3 retq
Re: Weird PIT issues
Posted: Mon Oct 19, 2020 4:14 pm
by MichaelPetch
When you called `pitd_init` what was the `clock_frequency` value you passed to the function? when you are calling `pitd_wait` what value for `ticks` did you pass into it?
Re: Weird PIT issues
Posted: Mon Oct 19, 2020 4:16 pm
by abstractmath
I'm passing 1000 for clock_frequency.
Re: Weird PIT issues
Posted: Mon Oct 19, 2020 4:35 pm
by MichaelPetch
What kind of wait value are you passing to pitd_wait that doesn't seem to delay?
Re: Weird PIT issues
Posted: Mon Oct 19, 2020 4:37 pm
by abstractmath
No matter what value I pass, it doesn't wait. I've been testing with passing in the time in milliseconds. At the moment, I'm testing with the value of 5000 ticks, which should be around 5 seconds.
Re: Weird PIT issues
Posted: Mon Oct 19, 2020 4:48 pm
by MichaelPetch
For completeness can you show the code for `p_write8`. Thanks. Do you have a Github project I can look at, or some way to build your code here so I can look at it?
Re: Weird PIT issues
Posted: Mon Oct 19, 2020 4:52 pm
by abstractmath
https://github.com/AsherBearce/AbstractOs
Here you go! I just pushed so you're looking at the same version of the project that I have
Re: Weird PIT issues
Posted: Mon Oct 19, 2020 6:07 pm
by MichaelPetch
You don't save and restore the registers. Since you are still doing all this in kernel mode this should get you started although you only really need to save/restore the volatile registers per the AMD64 System V ABI. This doesn't handle `swapgs`; 16 byte stack alignment; or anything but it should avoid your registers being corrupted while sitting in the `pitd_wait` function.
Code: Select all
irq_asm:
push rax
push rbx
push rcx
push rdx
push rbp
push rdi
push rsi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
cld
call master_IRQ
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rsi
pop rdi
pop rbp
pop rdx
pop rcx
pop rbx
pop rax
iretq
The OSDev wiki I believe has more information on doing this properly and other things to consider.
You also take the slow approach to determining which IRQ fired. Your interrupt handler queries the PICs to figure that out. If you created an entry point for each IRQ in irq.asm then pass the interrupt number to `master_irq` as the first parameter it would be a better option.
You should also compile your kernel code with `-mno-red-zone` and consider disabling SIMD instructions with something like `-mno-mmx -mno-sse -mno-sse2`
Re: Weird PIT issues
Posted: Mon Oct 19, 2020 7:02 pm
by abstractmath
Thank you, that fixed the problem. However, I don't plan on disabling the SSE registers, as I will be using floating point instructions in the future. Is there a way to save the SSE registers onto the stack and then restore them?
Re: Weird PIT issues
Posted: Mon Oct 19, 2020 7:21 pm
by Octocontrabass
Yes. Subtract an appropriate amount from RSP to create a buffer where you can save the registers, then use FXSAVE/XSAVE/XSAVEC/XSAVEOPT/XSAVES to store them in that buffer. Afterwards, use FXRSTOR/XRSTOR/XRSTORS to restore them and add an appropriate amount to RSP to free the buffer.
It's also possible to save and restore the SSE registers one at a time, but I don't think there's any benefit to doing things that way.
Don't forget that your kernel's floating-point code will depend on things like the x87 FPU control and status words and MXCSR. It may be a good idea to "restore" a clean FPU state for your kernel code.
Improperly saving/restoring AVX registers can cause a performance penalty.
Re: Weird PIT issues
Posted: Tue Oct 20, 2020 11:02 am
by abstractmath
Got it, thanks for the advice guys! It's very much appreciated!