Fixing PIT and Utilizing CPUID Features And Flags

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: Fixing PIT and Utilizing CPUID Features And Flags

Post by Octocontrabass »

TheGameMaker90 wrote:Imagine I tried to use a feature like hyper threading on a CPU that doesn't even have multithreading
It would still work, and you might not notice anything is wrong. Processor topology is only a performance hint. You can still use all available hardware threads regardless of where they physically exist.

You're right, though, detecting processor topology is manufacturer-specific, so you would need to know the manufacturer. However, a "hyperthreading" flag is not useful. You need to know the physical location of each hardware thread to perform any optimizations.
TheGameMaker90 wrote:Also, about that "halt loop." Do you mean "jmp $"? I already have that at the end.
I did not say "halt loop", I said "HLT loop", as in a loop that runs the HLT instruction. Like this one you were using earlier:

Code: Select all

1:  hlt
     jmp 1b
Also, it's a bad idea to enable interrupts with STI before you've configured the IDT. Move that somewhere after the IDT configuration.
TheGameMaker90
Member
Member
Posts: 83
Joined: Thu Jan 07, 2021 2:01 pm

Re: Fixing PIT and Utilizing CPUID Features And Flags

Post by TheGameMaker90 »

Octocontrabass wrote:
TheGameMaker90 wrote:Imagine I tried to use a feature like hyper threading on a CPU that doesn't even have multithreading
It would still work, and you might not notice anything is wrong. Processor topology is only a performance hint. You can still use all available hardware threads regardless of where they physically exist.

You're right, though, detecting processor topology is manufacturer-specific, so you would need to know the manufacturer. However, a "hyperthreading" flag is not useful. You need to know the physical location of each hardware thread to perform any optimizations.
TheGameMaker90 wrote:Also, about that "halt loop." Do you mean "jmp $"? I already have that at the end.
I did not say "halt loop", I said "HLT loop", as in a loop that runs the HLT instruction. Like this one you were using earlier:

Code: Select all

1:  hlt
     jmp 1b
Also, it's a bad idea to enable interrupts with STI before you've configured the IDT. Move that somewhere after the IDT configuration.
Hmm I didn't know that. I thought the feature would cause issues. And hyperthreading was an example :)

And that's what I had originally and the pit timer wasn't running. "HLT"-ing of any kind seems to prevent the timer from running if not triple faulting when I throw it in there now. Perhaps I'm missing something?

And good point, for all intents and purposes it works right now, but in practice you're right. The IDT tells the system how to handle the interrupts so it makes sense that it should go after.

Edit:
Ohhh! I think I get it. You mentioned somewhere that "CLI" interferes with the pit timer or hlt instruction, I just realized that in my old bootloader I had "CLI" before my HLT loop. I'm about to test the old one without "CLI".

Edit2:
Bingo! How did I miss that? I tyend to overthink the problem way too much. With just that one instruction removed, the system works. Very nice! Off topic, but I'm now working on the keyboard driver (which I've pretty much written myself) and I need to handle multiple keys at once. Ex: <SHIFT> + <A> = "A". How would I go about that?
My current keyboard handler function (processed through IRQ1) looks something like this:

Code: Select all

if (!(key & 0x80) == 1)
     terminal_printf("%s", keys_normal[keys]); // Where keys is from reading data (0x60)
I tried:

Code: Select all

if ((!(key & 0x80) == 1) && (key == <my shift key macro>))
     terminal_printf("%s", keys_caps[keys]); // Where keys is from reading data (0x60)
else
     terminal_printf("%s", keys_normal[keys]);
Edit3:
If you don't want to answer about the keyboard I get it (off topic), but I just realized something: When I press shift, it only fires once rather that treating it like I'm holding the key. That might be one place to start.

On the note of the CPU flags, how would I retrieve them? In cpuid.asm I have the following:

Code: Select all

cpuid_get_property:
    mov eax, [esp + 4]
    cpuid
I call it like this:

Code: Select all

extern uint32_t cpuid_get_property(uint32_t);
Then I used it like this:

Code: Select all

if (!cpu_get_property(CPUID_FEAT_ECX_SSE3))
    terminal_printf("[WARNING]: CPUID_FEAT_ECX_SSE3 is not supported...\n");
Is this correct, or is there a better way to do it?
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: Fixing PIT and Utilizing CPUID Features And Flags

Post by Octocontrabass »

TheGameMaker90 wrote:Off topic, but I'm now working on the keyboard driver (which I've pretty much written myself) and I need to handle multiple keys at once. Ex: <SHIFT> + <A> = "A". How would I go about that?
Each time a key is pressed or released, the keyboard sends a scan code. You receive an interrupt for each byte of the scan code (scan codes may be more than a single byte). To combine the shift key with other keys, you need to keep track of whether shift has been pressed or released. There are a lot of existing threads on the topic, so I suggest searching.
TheGameMaker90 wrote:When I press shift, it only fires once rather that treating it like I'm holding the key. That might be one place to start.
I think you should start by accepting the "key release" scan codes you're currently ignoring. Things should make a bit more sense once you can see those.
TheGameMaker90 wrote:On the note of the CPU flags, how would I retrieve them?
Check that the CPU supports the basic or extended leaf containing the flag you want to retrieve, then retrieve that leaf and extract the flag of interest from the correct register. (Then optimize by retrieving all of the flags in that leaf at the same time.)

Some ancient CPUs don't support CPUID, but you probably aren't worried about those.
TheGameMaker90 wrote:Is this correct, or is there a better way to do it?
That's not correct, and I'd recommend using either __cpuid() from cpuid.h or inline assembly since it's difficult to return four registers worth of data from one function. You already have code to retrieve the brand string, how does that work?

You might also want to read more about the CPUID instruction in Intel's or AMD's manuals.
TheGameMaker90
Member
Member
Posts: 83
Joined: Thu Jan 07, 2021 2:01 pm

Re: Fixing PIT and Utilizing CPUID Features And Flags

Post by TheGameMaker90 »

Octocontrabass wrote:
TheGameMaker90 wrote:Off topic, but I'm now working on the keyboard driver (which I've pretty much written myself) and I need to handle multiple keys at once. Ex: <SHIFT> + <A> = "A". How would I go about that?
Each time a key is pressed or released, the keyboard sends a scan code. You receive an interrupt for each byte of the scan code (scan codes may be more than a single byte). To combine the shift key with other keys, you need to keep track of whether shift has been pressed or released. There are a lot of existing threads on the topic, so I suggest searching.
TheGameMaker90 wrote:When I press shift, it only fires once rather that treating it like I'm holding the key. That might be one place to start.
I think you should start by accepting the "key release" scan codes you're currently ignoring. Things should make a bit more sense once you can see those.
TheGameMaker90 wrote:On the note of the CPU flags, how would I retrieve them?
Check that the CPU supports the basic or extended leaf containing the flag you want to retrieve, then retrieve that leaf and extract the flag of interest from the correct register. (Then optimize by retrieving all of the flags in that leaf at the same time.)

Some ancient CPUs don't support CPUID, but you probably aren't worried about those.
TheGameMaker90 wrote:Is this correct, or is there a better way to do it?
That's not correct, and I'd recommend using either __cpuid() from cpuid.h or inline assembly since it's difficult to return four registers worth of data from one function. You already have code to retrieve the brand string, how does that work?

You might also want to read more about the CPUID instruction in Intel's or AMD's manuals.
Luckily I already have macros in place for key down/key up. I was reading on the wiki about those buffers you mentioned, just trying to see how I can implement them at the moment. Any ideas? As for the CPU, I am not using existing libraries. As such, cpuid.h will not work for me (plus I have my own cpuid.h in place), I will read up on that. To put it simply, I want to start finishing one module at a time, so I'll be back here once I've finished the keyboard driver and possible a shell for interacting with the file system I haven't yet implemented, lol.
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: Fixing PIT and Utilizing CPUID Features And Flags

Post by Octocontrabass »

TheGameMaker90 wrote:As for the CPU, I am not using existing libraries. As such, cpuid.h will not work for me
That's a header, not a library. :P It's fair if you want to avoid using it; I don't use cpuid.h either. However, don't try to write your own versions of the C freestanding headers. They're part of your cross-compiler, so they contain bits of "compiler magic" that you won't be able to replicate.
Post Reply