[GDT] Loading problems in protected mode.

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.
Post Reply
nintyfan
Posts: 23
Joined: Wed Nov 07, 2018 10:15 am

[GDT] Loading problems in protected mode.

Post by nintyfan »

I search for similar topics, but these didn't provide an solution.

I developing kernel for KISSEM operating system. Problem is GRUB2 starts in protected mode and fill gdt table, so I must to reload GDT.

My code is:
1. x86.h

Code: Select all

#pragma pack(push, 0)
struct gdt_entry
{
  short int llimit;           
  short int lbase;            
  unsigned char mbase;         
  unsigned char flags1;              
  unsigned char flags2;
  unsigned char hbase;           
};


struct gdt_header
{    
  short int size;      
  void *ptr;          
};

struct git_header
{
  short int size;
  void *ptr;  
};

struct git_entry {

  short int addr_lower;
  short int sel_number;
  unsigned char mesh;
  unsigned char flags;
  short int addr_higher;
};
#pragma pack(pop)
2. x86,c

Code: Select all

struct gdt_header *info;
    
    ++init;
    info = &gdts_info;
    gdts_info.size = 3*8-1;
    gdts_info.ptr = gdts;
    
    gdts[1].llimit = 0xFFFF;
    gdts[1].lbase = 0;
    gdts[1].mbase = 0;
    gdts[1].hbase = 0;
    gdts[1].flags1= 0b10011110;
    gdts[1].flags2= 0xCF;
    
    gdts[2].llimit = 0xFFFF;
    gdts[2].lbase = 0;
    gdts[2].mbase = 0;
    gdts[2].hbase = 0;
    gdts[2].flags1= 0b10010010;
    gdts[2].flags2= 0xCF;
    
    
    #if 1
    __asm__ __volatile__ (
    //"lol:\n"
    //"hlt\n"
    //"jmp lol\n"
    "lgdt %0\n"
 
    "push next\n"
    "ret\n"
    "ljmp $0x8,$next\n"
    "next:\n"
    "mov $16, %%eax\n"
    "mov %%eax,%%ds\n"
    "mov %%eax,%%es\n"
    "mov %%eax,%%fs\n"
    "mov %%eax,%%gs\n"
    "mov %%eax,%%ss\n"
    ::"m"(*info):"eax","memory");
    #endif
I use QEMU with gdb. SIGQUIT is send, on instructions generated by __asm__ macrodefinition. But.. gdb don't points me, which instruction causes problem. I think I mess up with gdt structure and no matter, which instruction I will put below lgdt, it will cause problems.
MichaelPetch
Member
Member
Posts: 797
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: [GDT] Loading problems in protected mode.

Post by MichaelPetch »

Remove:

Code: Select all

    "push next\n"
    "ret\n"
It looks like you meant to do:

Code: Select all

     "push $next\n"
    "ret\n"
however that makes no sense as this sequence would effectively jump over the FAR jmp and it is unclear why you want to do that. Thus my opinion is these 2 instructions can just be removed.
nintyfan
Posts: 23
Joined: Wed Nov 07, 2018 10:15 am

Re: [GDT] Loading problems in protected mode.

Post by nintyfan »

Yes. I was trying to do far jump, so code segment/selector change it's value. Also I'd read it's necessary to clean some mode of CPU (prefetch?).
MichaelPetch
Member
Member
Posts: 797
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: [GDT] Loading problems in protected mode.

Post by MichaelPetch »

nintyfan wrote:Yes. I was trying to do far jump, so code segment/selector change it's value. Also I'd read it's necessary to clean some mode of CPU (prefetch?).
You are already doing a FAR JMP to set the code selector with the LJMP. The PUSH/RET (with the $ fix) you did was the equivalent of jumping over the LJMP directly to label `next` which I suggest should just be removed. The LJMP is the one that is setting the CS selector and going to the `next` label. Flushing the instruction prefetch queue (IPFQ) isn't needed when you are going from 32-bit protected mode to 32-bit protected mode, but the LJMP like all other unconditional JMPs clears the IPFQ. We aren't changing processor modes (we are just changing selectors and before and after we are still in 32-bit protected mode). You'd need to potentially flush the IPFQ if you were changing between 32-bit protected mode and 16-bit real or 16-bit protected (or vice versa) since the actual instructions may be decoded differently but that isn't happening in this case. Code that should work as expected is:

Code: Select all

    __asm__ __volatile__ (
    "lgdt %0\n"
    "ljmp $0x8,$1f\n"
    "1:\n"
    "mov $16, %%eax\n"
    "mov %%eax,%%ds\n"
    "mov %%eax,%%es\n"
    "mov %%eax,%%fs\n"
    "mov %%eax,%%gs\n"
    "mov %%eax,%%ss\n"
    ::"m"(*info):"eax","memory");
I would have personally made the inline assembly choose the register instead of forcing it to use EAX, but in theory there is nothing wrong/buggy in what you did in that regard. Allowing GCC to choose the register can produce more optimized code but this code isn't going to be called often so it has little impact either way.
Last edited by MichaelPetch on Tue Aug 23, 2022 3:03 am, edited 4 times in total.
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: [GDT] Loading problems in protected mode.

Post by Octocontrabass »

nintyfan wrote:Also I'd read it's necessary to clean some mode of CPU (prefetch?).
The LJMP instruction already clears the prefetch queue.
nintyfan
Posts: 23
Joined: Wed Nov 07, 2018 10:15 am

Re: [GDT] Loading problems in protected mode.

Post by nintyfan »

MichaelPetch wrote:

Code: Select all

    __asm__ __volatile__ (
    "lgdt %0\n"
    "ljmp $0x8,$next\n"
    "next:\n"
    "mov $16, %%eax\n"
    "mov %%eax,%%ds\n"
    "mov %%eax,%%es\n"
    "mov %%eax,%%fs\n"
    "mov %%eax,%%gs\n"
    "mov %%eax,%%ss\n"
    ::"m"(*info):"eax","memory");
Problem must be in other part of code or there's additional error. I copy your code into my kernel (replace older), but it hangs. I add code like:

Code: Select all

*((char*)0xB8000) = x
Where x is character code, such like '0'. Kernel hangs just before invoking assembly code.

I probably forgot to tell I use GCC compiler under GNU/Linux.
nintyfan
Posts: 23
Joined: Wed Nov 07, 2018 10:15 am

Re: [GDT] Loading problems in protected mode.

Post by nintyfan »

Solved!
There was another problem.

Problematic was in #pragma pack(push, 0)

It's quirk that compiler didn't complain! And I must wrote cleaner code. I correctly uses GCC pack pragma, but after that use VC++ pragma, which isn't use in correct way.
Post Reply