Page 14 of 20
Re: How to make a GDT?
Posted: Sat Oct 29, 2022 3:30 pm
by zap8600
Octocontrabass wrote:
Yes. That specific example sets G=1, D/B=0, L=1, and the upper four bits of the limit to 0xF.
I believe this will need to be done for all the segments. So because the lower (four?) bits limit of the 16-bit segments is
0xF, what does the upper four bits of the limit have to be? I have the same question for the 32-bit (and 64-bit) segments.
I'm attempting to future-proof here. When I begin to enter user-mode, I know I will need user-mode code and data segments. When I add those to the GDT, do I only have to add 64-bit segments to the GDT?
Re: How to make a GDT?
Posted: Sat Oct 29, 2022 4:24 pm
by Octocontrabass
zap8600 wrote:So because the lower (four?) bits limit of the 16-bit segments is 0xF, what does the upper four bits of the limit have to be? I have the same question for the 32-bit (and 64-bit) segments.
For 16-bit segments, the limit needs to be 0xFFFF bytes, which is either 0xFFFF with G=0 or 0xF with G=1. The limit is 20 bits, so the upper four bits of the limit are 0.
For 32-bit segments, the limit needs to be 0xFFFFFFFF bytes, which can only be 0xFFFFF with G=1. The limit is 20 bits, so the upper four bits of the limit are 0xF.
For 64-bit segments, the limit shouldn't matter. It's a good idea to use the same values as 32-bit segments.
zap8600 wrote:When I add those to the GDT, do I only have to add 64-bit segments to the GDT?
That depends on what type of user mode programs you want to run. If you only want to run 64-bit programs, you only need 64-bit segments.
Re: How to make a GDT?
Posted: Sat Oct 29, 2022 5:03 pm
by zap8600
Octocontrabass wrote:zap8600 wrote:So because the lower (four?) bits limit of the 16-bit segments is 0xF, what does the upper four bits of the limit have to be? I have the same question for the 32-bit (and 64-bit) segments.
For 16-bit segments, the limit needs to be 0xFFFF bytes, which is either 0xFFFF with G=0 or 0xF with G=1. The limit is 20 bits, so the upper four bits of the limit are 0.
For 32-bit segments, the limit needs to be 0xFFFFFFFF bytes, which can only be 0xFFFFF with G=1. The limit is 20 bits, so the upper four bits of the limit are 0xF.
For 64-bit segments, the limit shouldn't matter. It's a good idea to use the same values as 32-bit segments.
I believe that my GDT below is correct.
Code: Select all
FullGDT gdt[32] __attribute__((used)) = {{
{
{0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00},
{0xF, 0x0000, 0x00, 0x9A, (1 << 5) | 0x00, 0x00},
{0xF, 0x0000, 0x00, 0x92, (1 << 5) | 0x00, 0x00},
{0xFFFFF, 0x0000, 0x00, 0x9A, (1 << 5) | (1 << 6) | 0x0F, 0x00},
{0xFFFFF, 0x0000, 0x00, 0x92, (1 << 5) | (1 << 6) | 0x0F, 0x00},
{0xFFFFF, 0x0000, 0x00, 0x9A, (1 << 5) | (1 << 7) | 0X0F, 0x00},
{0xFFFFF, 0x0000, 0x00, 0x92, (1 << 5) | (1 << 7) | 0X0F, 0x00},
{0x0067, 0x0000, 0x00, 0xE9, 0x00, 0x00},
},
{0x00000000, 0x00000000},
{0x0000, 0x0000000000000000},
{0,{0,0,0},0,{0,0,0,0,0,0,0},0,0,0},
}};
Re: How to make a GDT?
Posted: Sat Oct 29, 2022 5:08 pm
by Octocontrabass
zap8600 wrote:I believe that my GDT below is correct.
It is not. It looks like you've switched the G and L bits, and you're still trying to put more than 16 bits in the space for the lower 16 bits of the limit.
Re: How to make a GDT?
Posted: Sat Oct 29, 2022 5:21 pm
by zap8600
Octocontrabass wrote:
It is not. It looks like you've switched the G and L bits, and you're still trying to put more than 16 bits in the space for the lower 16 bits of the limit.
Then is this right?
Code: Select all
FullGDT gdt[32] __attribute__((used)) = {{
{
{0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00},
{0xF, 0x0000, 0x00, 0x9A, (1 << 7) | 0x00, 0x00},
{0xF, 0x0000, 0x00, 0x92, (1 << 7) | 0x00, 0x00},
{0xFFFF, 0x0000, 0x00, 0x9A, (1 << 6) | (1 << 7) | 0x0F, 0x00},
{0xFFFF, 0x0000, 0x00, 0x92, (1 << 6) | (1 << 7) | 0x0F, 0x00},
{0xFFFF, 0x0000, 0x00, 0x9A, (1 << 5) | (1 << 7) | 0X0F, 0x00},
{0xFFFF, 0x0000, 0x00, 0x92, (1 << 5) | (1 << 7) | 0X0F, 0x00},
{0x0067, 0x0000, 0x00, 0xE9, 0x00, 0x00},
},
{0x00000000, 0x00000000},
{0x0000, 0x0000000000000000},
{0,{0,0,0},0,{0,0,0,0,0,0,0},0,0,0},
}};
Re: How to make a GDT?
Posted: Sat Oct 29, 2022 5:23 pm
by devc1
Here is what you need :
Code: Select all
struct GDT_ENTRY{
uint16_t limit_low;
uint16_t base_low;
uint8_t base_mid;
uint8_t access;
uint8_t limit_high : 4;
uint8_t flags : 4;
uint8_t base_high;
};
struct GDT{
struct GDT_ENTRY null0;
struct GDT_ENTRY kernel_code;
struct GDT_ENTRY kernel_data;
};
CpuGdt->kernel_code = (struct GDT_ENTRY){ 0, 0, 0, 0b10011010, 0, 0b1010, 0};
CpuGdt->kernel_data = (struct GDT_ENTRY){ 0, 0, 0, 0b10010010, 0, 0b1000, 0};
Re: How to make a GDT?
Posted: Sat Oct 29, 2022 6:12 pm
by zap8600
devc1 wrote:Here is what you need :
Code: Select all
struct GDT_ENTRY{
uint16_t limit_low;
uint16_t base_low;
uint8_t base_mid;
uint8_t access;
uint8_t limit_high : 4;
uint8_t flags : 4;
uint8_t base_high;
};
struct GDT{
struct GDT_ENTRY null0;
struct GDT_ENTRY kernel_code;
struct GDT_ENTRY kernel_data;
};
CpuGdt->kernel_code = (struct GDT_ENTRY){ 0, 0, 0, 0b10011010, 0, 0b1010, 0};
CpuGdt->kernel_data = (struct GDT_ENTRY){ 0, 0, 0, 0b10010010, 0, 0b1000, 0};
This would work with my TSS.
Re: How to make a GDT?
Posted: Sat Oct 29, 2022 6:16 pm
by devc1
Are you asking for a 64 bit tss ?
Re: How to make a GDT?
Posted: Sat Oct 29, 2022 6:39 pm
by zap8600
devc1 wrote:Are you asking for a 64 bit tss ?
No, I have one. It is that adding
limit_high to the
gdt_entry_t doesn't work with my TSS and my Null entry. It gives me a warning.
Code: Select all
arch/x86_64/gdt.c:47:17: warning: missing initializer for field 'base_high' of 'gdt_entry_t' [-Wmissing-field-initializers]
47 | {0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00},
| ^
arch/x86_64/gdt.c:25:17: note: 'base_high' declared here
25 | uint8_t base_high;
| ^~~~~~~~~
arch/x86_64/gdt.c:54:17: warning: missing initializer for field 'base_high' of 'gdt_entry_t' [-Wmissing-field-initializers]
54 | {0x0067, 0x0000, 0x00, 0xE9, 0x00, 0x00},
| ^
arch/x86_64/gdt.c:25:17: note: 'base_high' declared here
25 | uint8_t base_high;
| ^~~~~~~~~
Re: How to make a GDT?
Posted: Sat Oct 29, 2022 9:50 pm
by Octocontrabass
zap8600 wrote:Then is this right?
Those code and data segments look correct to me.
devc1 wrote:Here is what you need :
Your GDT does not meet Limine's requirements. It is not possible to use Limine's terminal with this GDT.
zap8600 wrote:It gives me a warning.
The struct layout is different. You need to rewrite the initializer to match the struct layout.
Re: How to make a GDT?
Posted: Sat Oct 29, 2022 10:52 pm
by zap8600
Octocontrabass wrote:
Those code and data segments look correct to me.
Well, something went wrong. Unfortunately, it is pretty late and I can't stay up attempting to debug my OS like I usually do. I'll leave my QEMU log here and I'll get to it when I wake up.
Re: How to make a GDT?
Posted: Sun Oct 30, 2022 3:58 am
by devc1
Well, I didn't know about the limine thing.
However, if you want the gdt in assembly here it is :
NASM Syntax and you can relayout it as you want
Code: Select all
.NULL dq 0
.Code:
dw 0
dw 0
db 0
db 10011010b
db 1010b << 4 ; Limit | Flags << 4
db 0
.Data:
dw 0
dw 0
db 0
db 10010010b
db 1000b << 4 ; Limit | Flags << 4
db 0
Re: How to make a GDT?
Posted: Sun Oct 30, 2022 4:03 am
by devc1
I looked in to limines github repo and It seems that limines GDT 32 bit. And you are trying to run 64 bit code in 32 bit mode ? If yes and the kernel loads perfectly into the startup function, I can help you but you will not be able to use the terminal, otherwise you can just create your own terminal.
When you create a kernel, you are nomore dependent of bootloader stuff, the bootloader passed the initdata, now its your turn to startup the OS (a long trip).
Re: How to make a GDT?
Posted: Sun Oct 30, 2022 8:52 am
by nexos
@devc1: read the protocol spec. It's very clear that it enters the CPU into long mode if you want it to. You haven't looked hard enough
Re: How to make a GDT?
Posted: Sun Oct 30, 2022 8:59 am
by devc1
Yeahhh, I am not a fan of reading btw.