OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 3:10 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 294 posts ]  Go to page Previous  1 ... 13, 14, 15, 16, 17, 18, 19, 20  Next
Author Message
 Post subject: Re: How to make a GDT?
PostPosted: Tue Nov 01, 2022 12:10 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
zap8600 wrote:
I believe that it is pointing to the 16-bit segment. It should instead point to 0x30, which I believe is the 64-bit segment.
Without the GDT, nobody will be able to tell you. However, segment 0x10 refers to index 2, and 0x30 refers to index 6 (you just have to divide by eight).
zap8600 wrote:
If this is the case though, I believe the problem should be fixed by replacing the 5 with 7.
You are loading the TR with 0x2B, which refers to index 5. Your problem is that segment 5 is not initialized correctly, You set the limit (one byte too high, because the limit for some reason is one less than the size of the segment, but that is immaterial here) and the base, but never the segment type. This is why you should read the CPU manuals which detail the structure of the thing.

In 64-bit mode, the TSS is a long segment, i.e. it uses two consecutive GDT entries for the whole base pointer. I have the GDT declared as just an array of 64-bit numbers, and therefore I can just do this initialization:
Code:
static void init_gdt(uint64_t *gdt, const struct tss* tss)
{
    uint64_t tssp = (uint64_t)tss;
    gdt[KCODE_DESC] = 0x00af9a000000ffff;
    gdt[KDATA_DESC] = 0x00af92000000ffff;
    gdt[UDATA_DESC] = 0x00aff2000000ffff;
    gdt[UCODE_DESC] = 0x00affa000000ffff;
    gdt[TSS_DESC] = (tssp << 16) & 0xffffff0000 | (tssp << 32) & 0xff00000000000000 | sizeof (struct tss) - 1 | (uint64_t)0x89 << 40;
    gdt[TSSU_DESC] = tssp >> 32;
}
There. Done. That is all you need. You don't need anything more. Never understood why people love to complicate this stuff with tons of structures.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: How to make a GDT?
PostPosted: Tue Nov 01, 2022 12:29 pm 
Offline
Member
Member

Joined: Tue Nov 02, 2021 11:26 am
Posts: 195
nullplan wrote:
You are loading the TR with 0x2B, which refers to index 5. Your problem is that segment 5 is not initialized correctly, You set the limit (one byte too high, because the limit for some reason is one less than the size of the segment, but that is immaterial here) and the base, but never the segment type. This is why you should read the CPU manuals which detail the structure of the thing.

In 64-bit mode, the TSS is a long segment, i.e. it uses two consecutive GDT entries for the whole base pointer. I have the GDT declared as just an array of 64-bit numbers, and therefore I can just do this initialization:
Code:
static void init_gdt(uint64_t *gdt, const struct tss* tss)
{
    uint64_t tssp = (uint64_t)tss;
    gdt[KCODE_DESC] = 0x00af9a000000ffff;
    gdt[KDATA_DESC] = 0x00af92000000ffff;
    gdt[UDATA_DESC] = 0x00aff2000000ffff;
    gdt[UCODE_DESC] = 0x00affa000000ffff;
    gdt[TSS_DESC] = (tssp << 16) & 0xffffff0000 | (tssp << 32) & 0xff00000000000000 | sizeof (struct tss) - 1 | (uint64_t)0x89 << 40;
    gdt[TSSU_DESC] = tssp >> 32;
}
There. Done. That is all you need. You don't need anything more. Never understood why people love to complicate this stuff with tons of structures.

So what does the TR need to be in order to refer to segment 7?


Top
 Profile  
 
 Post subject: Re: How to make a GDT?
PostPosted: Tue Nov 01, 2022 12:49 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
zap8600 wrote:
So what does the TR need to be in order to refer to segment 7?
Go the other way around and multiply by eight. Seven times eight is fifty-six, or 0x38 in hexadecimal. You can add another three to retain the original code's RPL of three, but it really doesn't matter unless you were using hardware task switching. Which you are not, seeing as you are in 64-bit mode, which has no support for such.

_________________
Carpe diem!


Top
 Profile  
 
 Post subject: Re: How to make a GDT?
PostPosted: Tue Nov 01, 2022 2:35 pm 
Offline
Member
Member

Joined: Tue Nov 02, 2021 11:26 am
Posts: 195
nullplan wrote:
Go the other way around and multiply by eight. Seven times eight is fifty-six, or 0x38 in hexadecimal. You can add another three to retain the original code's RPL of three, but it really doesn't matter unless you were using hardware task switching. Which you are not, seeing as you are in 64-bit mode, which has no support for such.

Thank you. Finally, my GDT works, and Limine's terminal function works as well. I also got interrupts working. Although, the interrupts aren't working properly (I think). When running asm volatile ("int $0x3"); in the kernel, it prints the interrupt message three times. I believe that it may have to do with my ISR handler (which is very simple). Here is my ISR handler.
Code:
void isr_handler()
{
    terminal_write("Received ISR!\n");
}


Top
 Profile  
 
 Post subject: Re: How to make a GDT?
PostPosted: Tue Nov 01, 2022 4:40 pm 
Offline
Member
Member

Joined: Tue Nov 02, 2021 11:26 am
Posts: 195
I have updated my ISR handler, and now I know that something is going wrong. When running asm volatile ("int $0x3");, it prints Received ISR: Breakpoint, which is what it is supposed to do, but then it prints Received ISR: General Protection Fault, which it shouldn't do. It tries to print Received ISR: General Protection Fault again, but it replaces characters in the string with random junk data. Nothing is printed to the screen after that, and I'm not sure if my ISR handler returns or not. Here is my ISR handler.
Code:
void isr_handler(registers_t r)
{
    terminal_writestring("Received ISR: ");
    terminal_writestring(exception_messages[r.int_no]);
    terminal_writestring("\n");
}

What is going wrong?


Top
 Profile  
 
 Post subject: Re: How to make a GDT?
PostPosted: Tue Nov 01, 2022 5:05 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5100
zap8600 wrote:
Code:
void isr_handler(registers_t r)

Are you sure that's the correct type for the argument to this function?

zap8600 wrote:
What is going wrong?

What is the address of the instruction causing the exception? What is the exception error code? What are the contents of the CPU registers when it happens?

You can get all of this information by printing the contents of your registers struct or by checking the QEMU "-d int" log.


Top
 Profile  
 
 Post subject: Re: How to make a GDT?
PostPosted: Tue Nov 01, 2022 5:45 pm 
Offline
Member
Member

Joined: Tue Nov 02, 2021 11:26 am
Posts: 195
Octocontrabass wrote:
Are you sure that's the correct type for the argument to this function?

I believe so. If not, what would it be? Here is registers_t.
Code:
typedef struct {
   uintptr_t r15, r14, r13, r12;
   uintptr_t r11, r10, r9, r8;
   uintptr_t rbp, rdi, rsi, rdx, rcx, rbx, rax;

   uintptr_t int_no, err_code;

   uintptr_t rip, cs, rflags, rsp, ss;
} registers_t;


Octocontrabass wrote:
What is the address of the instruction causing the exception? What is the exception error code? What are the contents of the CPU registers when it happens?

You can get all of this information by printing the contents of your registers struct or by checking the QEMU "-d int" log.

Well, it appears to repeat the same thing over and over. It repeats it so fast that I can't get the entire log. Here it is.
Code:
check_exception old: 0xffffffff new 0xd
   546: v=0d e=e190 i=0 cpl=0 IP=0028:ffffffff800002a9 pc=ffffffff800002a9 SP=0030:0000000007f80088 env->regs[R_EAX]=0000000007f80088
RAX=0000000007f80088 RBX=0000000000000006 RCX=0000000000000028 RDX=ffffffff800002a9
RSI=000000000000e190 RDI=000000000000000d RBP=0000000007f80088 RSP=0000000007f80088
R8 =0000000000000006 R9 =0000000000000028 R10=ffffffff800002a9 R11=000000000000e190
R12=000000000000000e R13=0000000007f80088 R14=0000000000000000 R15=0000000000000028
RIP=ffffffff800002a9 RFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS   [-WA]
CS =0028 0000000000000000 ffffffff 00af9a00 DPL=0 CS64 [-R-]
SS =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS   [-WA]
DS =0030 0000000000000000 ffffffff 00af9300 DPL=0 DS   [-WA]
FS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
GS =0030 0000000000000000 00000000 00009300 DPL=0 DS   [-WA]
LDT=0000 0000000000000000 00000000 00008200 DPL=0 LDT
TR =0038 ffffffff80400e92 00000068 0000e900 DPL=3 TSS64-avl
GDT=     ffffffff80400e40 00000047
IDT=     ffffffff80406740 00001000
CR0=80010011 CR2=0000000000000000 CR3=0000000007617000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000010 CCD=0000000007f80088 CCO=ADDQ
EFER=0000000000000d00
check_exception old: 0xffffffff new 0xd


Top
 Profile  
 
 Post subject: Re: How to make a GDT?
PostPosted: Tue Nov 01, 2022 9:27 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5100
zap8600 wrote:
If not, what would it be?

Usually it would be "registers_t *" instead of "registers_t". Otherwise, you can't modify the stack frame before returning, and the compiler may clobber your stack frame.

zap8600 wrote:
Code:
RIP=ffffffff800002a9

What is the instruction at this address? Which function contains that instruction?


Top
 Profile  
 
 Post subject: Re: How to make a GDT?
PostPosted: Wed Nov 02, 2022 9:26 am 
Offline
Member
Member

Joined: Tue Nov 02, 2021 11:26 am
Posts: 195
Octocontrabass wrote:
Usually it would be "registers_t *" instead of "registers_t". Otherwise, you can't modify the stack frame before returning, and the compiler may clobber your stack frame.

I fixed this, but it had no effect.

Octocontrabass wrote:
What is the instruction at this address? Which function contains that instruction?

I'm not sure. How do I check what function is at that address?


Top
 Profile  
 
 Post subject: Re: How to make a GDT?
PostPosted: Wed Nov 02, 2022 10:14 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5100
zap8600 wrote:
How do I check what function is at that address?

You can use addr2line or objdump. I prefer objdump since I usually want to examine the nearby code to get a better idea of what's wrong.


Top
 Profile  
 
 Post subject: Re: How to make a GDT?
PostPosted: Wed Nov 02, 2022 10:48 am 
Offline
Member
Member

Joined: Tue Nov 02, 2021 11:26 am
Posts: 195
Octocontrabass wrote:
You can use addr2line or objdump. I prefer objdump since I usually want to examine the nearby code to get a better idea of what's wrong.

I believe I might do this by running objdump -d myos.elf. I'm not exactly familiar with objdump. I plan on integrating a mini debugger, so that may help.


Top
 Profile  
 
 Post subject: Re: How to make a GDT?
PostPosted: Wed Nov 02, 2022 11:01 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
You should consider running your OS under a full debugger. Gdb works very well in conjunction with qemu and has a host of useful features.


Top
 Profile  
 
 Post subject: Re: How to make a GDT?
PostPosted: Wed Nov 02, 2022 1:42 pm 
Offline
Member
Member

Joined: Tue Nov 02, 2021 11:26 am
Posts: 195
What command(s) do I need to run to find the function I'm looking for? I think it is objdump -d myos.elf, but I'm probably wrong.


Top
 Profile  
 
 Post subject: Re: How to make a GDT?
PostPosted: Wed Nov 02, 2022 3:07 pm 
Offline
Member
Member

Joined: Tue Nov 02, 2021 11:26 am
Posts: 195
I added this mini debugger to my OS, but I wasn't able to get it to work, so I'll worry about it later. Anyways, I found the instruction at ffffffff80000209 (it changed from ffffffff800002a9 to ffffffff80000209). It's in the isr_common function, near the bottom.
Code:
ffffffff800001cb <isr_common>:
ffffffff800001cb:       50                      push   %rax
ffffffff800001cc:       53                      push   %rbx
ffffffff800001cd:       51                      push   %rcx
ffffffff800001ce:       52                      push   %rdx
ffffffff800001cf:       56                      push   %rsi
ffffffff800001d0:       57                      push   %rdi
ffffffff800001d1:       55                      push   %rbp
ffffffff800001d2:       41 50                   push   %r8
ffffffff800001d4:       41 51                   push   %r9
ffffffff800001d6:       41 52                   push   %r10
ffffffff800001d8:       41 53                   push   %r11
ffffffff800001da:       41 54                   push   %r12
ffffffff800001dc:       41 55                   push   %r13
ffffffff800001de:       41 56                   push   %r14
ffffffff800001e0:       41 57                   push   %r15
ffffffff800001e2:       fc                      cld
ffffffff800001e3:       48 89 e7                mov    %rsp,%rdi
ffffffff800001e6:       e8 25 00 00 00          call   ffffffff80000210 <isr_handler>
ffffffff800001eb:       48 89 c4                mov    %rax,%rsp
ffffffff800001ee:       41 5f                   pop    %r15
ffffffff800001f0:       41 5e                   pop    %r14
ffffffff800001f2:       41 5d                   pop    %r13
ffffffff800001f4:       41 5c                   pop    %r12
ffffffff800001f6:       41 5b                   pop    %r11
ffffffff800001f8:       41 5a                   pop    %r10
ffffffff800001fa:       41 59                   pop    %r9
ffffffff800001fc:       41 58                   pop    %r8
ffffffff800001fe:       5d                      pop    %rbp
ffffffff800001ff:       5f                      pop    %rdi
ffffffff80000200:       5e                      pop    %rsi
ffffffff80000201:       5a                      pop    %rdx
ffffffff80000202:       59                      pop    %rcx
ffffffff80000203:       5b                      pop    %rbx
ffffffff80000204:       58                      pop    %rax
ffffffff80000205:       48 83 c4 10             add    $0x10,%rsp
ffffffff80000209:       48 cf                   iretq
ffffffff8000020b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

Is iretq causing problems?


Top
 Profile  
 
 Post subject: Re: How to make a GDT?
PostPosted: Wed Nov 02, 2022 3:10 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5100
The exception is happening at the IRETQ instruction, but usually that means there's a problem somewhere else that causes stack corruption.

For example, the instruction at ffffffff800001eb might be corrupting the stack pointer.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 294 posts ]  Go to page Previous  1 ... 13, 14, 15, 16, 17, 18, 19, 20  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], Google [Bot], Majestic-12 [Bot] and 54 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group