Page 1 of 1

I can't install Task Register(

Posted: Sat Sep 05, 2020 6:20 am
by mrjbom
Hi.
I have previously discussed this issue here, but we have not been able to achieve a solution, so I have to write about it again...

So, here is my code that deals with setting up GDT and trying to load TR.

First it creates 6 entries in gdt_entries array
0. NULL
1. Kernel Code
2. Kernel Data
3. Usermode Code
4. Usermode Data
5. TSS
After that, everything is successfully flush GDT.
Then I take the ESP to use it in the write_tss() function that configures the TSS.
Then I configure the IDT to track exceptions that may occur when trying to execute the LTR statement.
And finally I try to load TR using the function tss_flush(), as a parameter I specify the number offset to the TSS entry in GDT(0x5 * 0x8 = 0x28).

While calling the tss_flush() function, while trying to execute the LTR statement, I encounter an exception #GP, with the error code d440.
Here's what it means:
Exception inside the processor
The Selector Index references a descriptor in the GDT.
index = 6792
However, the problem is that there is no such index in my GDT, I do not know what exactly it does not like.

Re: I can't install Task Register(

Posted: Sat Sep 05, 2020 6:28 am
by nexos
Remove this section in write_tss

Code: Select all

uint32_t base = (uint32_t) &tss;
	uint32_t limit = sizeof(tss)-1;

	tss_descriptor_t* tss_d = (tss_descriptor_t*) &gdt_entries[num];

	tss_d->base_15_0 = base & 0xFFFF;
	tss_d->base_23_16 = (base >> 16) & 0xFF;
	tss_d->base_31_24 = (base >> 24) & 0xFF;

	tss_d->limit_15_0 = limit & 0xFFFF;
	tss_d->limit_19_16 = (limit >> 16) & 0xF;

	tss_d->present = 1;
	tss_d->sys = 0;
	tss_d->DPL = 0;
	tss_d->type = 9;

	tss_d->AVL = 0;
	tss_d->allways_zero = 0;
	tss_d->gran = 0;
And call write_tss before calling lgdt. Call ltr after writing the GDT.
Then, it should work

Re: I can't install Task Register(

Posted: Sat Sep 05, 2020 6:41 am
by mrjbom
nexos wrote:And call write_tss before calling lgdt. Call ltr after writing the GDT.
Then, it should work
Like this?

Code: Select all

write_tss(5, 0x10, stack);
gdt_flush((uint32_t)&gdt_ptr);
tss_flush(0x28);

Re: I can't install Task Register(

Posted: Sat Sep 05, 2020 6:47 am
by nexos
Yes, just like that.

Re: I can't install Task Register(

Posted: Sat Sep 05, 2020 7:20 am
by mrjbom
nexos wrote:Yes, just like that.
Just in case, I will give the code of both changed functions.
However, this does not solve the problem, the error code is still the same.

Code: Select all

void init_gdt(void)
{
  gdt_ptr.limit = (sizeof(gdt_entry_t) * 6) - 1;
  gdt_ptr.base = (uint32_t)&gdt_entries;
  
  gdt_set_gate(0, 0, 0, 0, 0);	/* Null segment */
  gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); /* Code segment */
  gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); /* Data segment */
  gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); /* User mode code segment */
  gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); /* User mode data segment */
  gdt_set_gate(5, (uint32_t)&tss, (uint32_t)&tss + sizeof(tss_entry_t), 0xE9, 0xCF);

  uint32_t stack = 0;
  __asm__ volatile ("mov %%esp, %0" : "=r"(stack));
  write_tss(5, 0x10, stack);
  
  gdt_flush((uint32_t)&gdt_ptr);
  tss_flush(0x28);
  
  init_idt();
}

Code: Select all

void write_tss(int32_t num, uint32_t ss0, uint32_t esp0)
{
	memset(&tss, 0, sizeof(tss_entry_t));

	tss.ss0 = ss0;
	tss.esp0 = esp0;

	tss.cs = 0x08;

	tss.ss = tss.ds = tss.es = tss.fs = tss.gs = 0x10;

	tss.iomap = 0xFF;
	tss.iomap_offset = (uint16_t) ( (uint32_t) &tss.iomap - (uint32_t) &tss );
}

Re: I can't install Task Register(

Posted: Sat Sep 05, 2020 7:41 am
by nexos
Here is what I do

Code: Select all

memset(&tss, 0, sizeof(tss_entry));

    tss.ss0 = kernelSS;

    tss.esp0 = kernelESP;

    tss.cs = 0x0b;

    tss.ss = tss.ds = tss.es = tss.fs = tss.gs = 0x13;

    tss.iomap = sizeof(tss_entry);

    tss_flush();

Re: I can't install Task Register(

Posted: Sat Sep 05, 2020 8:05 am
by mrjbom
nexos wrote:Here is what I do

Code: Select all

memset(&tss, 0, sizeof(tss_entry));

    tss.ss0 = kernelSS;

    tss.esp0 = kernelESP;

    tss.cs = 0x0b;

    tss.ss = tss.ds = tss.es = tss.fs = tss.gs = 0x13;

    tss.iomap = sizeof(tss_entry);

    tss_flush();
I tried using the same values during tss setup and for tss_flush

Code: Select all

tss.cs = 0x0B;
tss.ss = tss.ds = tss.es = tss.fs = tss.gs = 0x13;

Code: Select all

tss_flush(0x2B);
In this case the error code points to such an index in GDT - 2142
It is absolutely unclear why this particular index contains an error.

Re: I can't install Task Register(

Posted: Sat Sep 05, 2020 12:31 pm
by nexos
Try running it in Bochs. Check the Bochs log and post what it says.

Re: I can't install Task Register(

Posted: Sat Sep 05, 2020 12:56 pm
by sj95126
mrjbom wrote:And finally I try to load TR using the function tss_flush(), as a parameter I specify the number offset to the TSS entry in GDT(0x5 * 0x8 = 0x28).
As an aside, I strongly recommend getting away from the concept that a selector is in some way a byte offset into the GDT. It's not - it's an index. It's *coincidental* that the index and offset are the same for system-level selectors in the GDT (that is, the lower three bits are 0), but if you ever go to 64-bit mode, you're going to be incredibly confused why nothing works.

I know some tutorials frame things this way and it doesn't help as a learning tool.

Re: I can't install Task Register(

Posted: Sat Sep 05, 2020 1:02 pm
by kzinti
Isn't the index a byte offset? :)

Re: I can't install Task Register(

Posted: Sat Sep 05, 2020 3:10 pm
by Octocontrabass
mrjbom wrote:In this case the error code points to such an index in GDT - 2142
It is absolutely unclear why this particular index contains an error.
Because you are loading the value in memory at address 0x2B into the task register, instead of the value 0x2B.

Re: I can't install Task Register(

Posted: Sat Sep 05, 2020 5:08 pm
by mrjbom
Octocontrabass wrote:
mrjbom wrote:In this case the error code points to such an index in GDT - 2142
It is absolutely unclear why this particular index contains an error.
Because you are loading the value in memory at address 0x2B into the task register, instead of the value 0x2B.
Ahaha, my God, I spent so much time solving this problem, and the error was so simple, now it's clear why error code pointed to incomprehensible entries in GDT.

Thank you all for your help! ♥