OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 11:03 am

All times are UTC - 6 hours




Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 
Author Message
 Post subject: TSS problem
PostPosted: Tue Jan 30, 2018 12:34 pm 
Offline

Joined: Sun Jan 28, 2018 9:29 am
Posts: 4
I'm trying to switch to ring 3 and implement a TSS, but after i switched interrupts stop working. Even if I use cli to get a general protection fault, nothing happens. What's wrong with my code? The full source code is on https://github.com/MSathieu/Cernel, but I copied here the most important files.

tss.h:
Code:
#include <stdint.h>

struct tss_table {
   uint32_t prev_tss;
   uint32_t esp0;
   uint32_t ss0;
   uint32_t esp1;
   uint32_t ss1;
   uint32_t esp2;
   uint32_t ss2;
   uint32_t cr3;
   uint32_t eip;
   uint32_t eflags;
   uint32_t eax;
   uint32_t ecx;
   uint32_t edx;
   uint32_t ebx;
   uint32_t esp;
   uint32_t ebp;
   uint32_t esi;
   uint32_t edi;
   uint32_t es;         
   uint32_t cs;       
   uint32_t ss;       
   uint32_t ds;       
   uint32_t fs;       
   uint32_t gs;         
   uint32_t ldt;     
   uint16_t trap;
   uint16_t iomap_base;
} __attribute__ ((packed));
struct tss_table tss;


gdt.c:
Code:
#include <tss.h>
extern void load_gdt(uint32_t);
extern void load_tss(void);

struct gdt_table {
  uint16_t limit;
  uint32_t base;
} __attribute__((packed));
struct gdt_entry {
  uint16_t limit_low;
  uint16_t base_low;
  uint8_t base_middle;
  uint8_t access;
  uint8_t granularity;
  uint8_t base_high;
} __attribute__((packed));
struct gdt_table gdt;
struct gdt_entry gdt_entry[6];

void add_gdt_segment(int i, uint32_t base, uint32_t limit, uint32_t access, uint32_t granularity) {
  gdt_entry[i].base_low = (base & 0xffff);
  gdt_entry[i].base_middle = (base >> 16) & 0xff;
  gdt_entry[i].base_high = (base >> 24) & 0xff;
  gdt_entry[i].limit_low = (limit & 0xffff);
  gdt_entry[i].granularity = (limit >> 16) & 0x0f;
  gdt_entry[i].granularity |= granularity & 0xf0;
  gdt_entry[i].access = access;
}
void setup_tss(void) {
  uint32_t base = (uint32_t) &tss;
  uint32_t limit = sizeof(tss);
  add_gdt_segment(5, base, limit, 0xE9, 0x00);
  tss.ss0 = 0x10;
  tss.esp0 = 0x0;
}
void setup_gdt(void) {
  gdt.limit = sizeof(gdt_entry) * 6 - 1;
  gdt.base = (uint32_t) &gdt_entry;
  add_gdt_segment(0, 0, 0, 0, 0);
  add_gdt_segment(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
  add_gdt_segment(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
  add_gdt_segment(3, 0, 0xFFFFFFFF, 0xFA, 0xCF);
  add_gdt_segment(4, 0, 0xFFFFFFFF, 0xF2, 0xCF);
  setup_tss();
  load_gdt((uint32_t) &gdt);
  load_tss();
}

load_gdt.asm:
Code:
global load_gdt
global load_tss
load_gdt:
  mov eax, [esp+4]
  lgdt [eax]
  mov ax, 0x10
  mov ds, ax
  mov es, ax
  mov fs, ax
  mov gs, ax
  mov ss, ax
  jmp 0x08:flush_gdt
flush_gdt:
  ret
load_tss:
  mov ax, 0x2B
  ltr ax
  ret

usermode.asm:
Code:
global jump_to_usermode
jump_to_usermode:
  mov ax, 0x23
  mov ds, ax
  mov es, ax
  mov fs, ax
  mov gs, ax
  mov eax, esp
  push 0x23
  push eax
  pushf
  push 0x1B
  push start_usermode
  iret
start_usermode:
  jmp $

idt.c:
Code:
#include <ioports.h>
extern void load_idt();
extern void int0();
extern void int1();
extern void int2();
extern void int3();
extern void int4();
extern void int5();
extern void int6();
extern void int7();
extern void int8();
extern void int9();
extern void int10();
extern void int11();
extern void int12();
extern void int13();
extern void int14();
extern void int15();
extern void int16();
extern void int17();
extern void int18();
extern void int19();
extern void int20();
extern void int21();
extern void int22();
extern void int23();
extern void int24();
extern void int25();
extern void int26();
extern void int27();
extern void int28();
extern void int29();
extern void int30();
extern void int31();
extern void int32();
extern void int33();
extern void int34();
extern void int35();
extern void int36();
extern void int37();
extern void int38();
extern void int39();
extern void int40();
extern void int41();
extern void int42();
extern void int43();
extern void int44();
extern void int45();
extern void int46();
extern void int47();

struct idt_table {
  uint16_t limit;
  uint32_t base;
} __attribute__ ((packed));
struct idt_entry {
  uint16_t base_low;
  uint16_t select;
  uint8_t type;
  uint8_t flags;
  uint16_t base_high;
} __attribute__((packed));
struct idt_entry idt_entry[256];
struct idt_table idt;

void add_idt_segment(int i, uint32_t base) {
  idt_entry[i].base_low = (base & 0xFFFF);
  idt_entry[i].base_high = (base >> 16) & 0xFFFF;
  idt_entry[i].select = 0x08;
  idt_entry[i].type = 0;
  idt_entry[i].flags = 0x8E;
}
void setup_idt(void) {
  outb(0x20, 0x11);
  outb(0xA0, 0x11);
  outb(0x21, 0x20);
  outb(0xA1, 0x28);
  outb(0x21, 0x04);
  outb(0xA1, 0x02);
  outb(0x21, 0x01);
  outb(0xA1, 0x01);
  outb(0x21, 0x0);
  outb(0xA1, 0x0);
  idt.limit = (sizeof (struct idt_entry) * 256) - 1;
  idt.base = (int) idt_entry;
  add_idt_segment(0, (uint32_t) int0);
  add_idt_segment(1, (uint32_t) int1);
  add_idt_segment(2, (uint32_t) int2);
  add_idt_segment(3, (uint32_t) int3);
  add_idt_segment(4, (uint32_t) int4);
  add_idt_segment(5, (uint32_t) int5);
  add_idt_segment(6, (uint32_t) int6);
  add_idt_segment(7, (uint32_t) int7);
  add_idt_segment(8, (uint32_t) int8);
  add_idt_segment(9, (uint32_t) int9);
  add_idt_segment(10, (uint32_t) int10);
  add_idt_segment(11, (uint32_t) int11);
  add_idt_segment(12, (uint32_t) int12);
  add_idt_segment(13, (uint32_t) int13);
  add_idt_segment(14, (uint32_t) int14);
  add_idt_segment(15, (uint32_t) int15);
  add_idt_segment(16, (uint32_t) int16);
  add_idt_segment(17, (uint32_t) int17);
  add_idt_segment(18, (uint32_t) int18);
  add_idt_segment(19, (uint32_t) int19);
  add_idt_segment(20, (uint32_t) int20);
  add_idt_segment(21, (uint32_t) int21);
  add_idt_segment(22, (uint32_t) int22);
  add_idt_segment(23, (uint32_t) int23);
  add_idt_segment(24, (uint32_t) int24);
  add_idt_segment(25, (uint32_t) int25);
  add_idt_segment(26, (uint32_t) int26);
  add_idt_segment(27, (uint32_t) int27);
  add_idt_segment(28, (uint32_t) int28);
  add_idt_segment(29, (uint32_t) int29);
  add_idt_segment(30, (uint32_t) int30);
  add_idt_segment(31, (uint32_t) int31);
  add_idt_segment(32, (uint32_t) int32);
  add_idt_segment(33, (uint32_t) int33);
  add_idt_segment(34, (uint32_t) int34);
  add_idt_segment(35, (uint32_t) int35);
  add_idt_segment(36, (uint32_t) int36);
  add_idt_segment(37, (uint32_t) int37);
  add_idt_segment(38, (uint32_t) int38);
  add_idt_segment(39, (uint32_t) int39);
  add_idt_segment(40, (uint32_t) int40);
  add_idt_segment(41, (uint32_t) int41);
  add_idt_segment(42, (uint32_t) int42);
  add_idt_segment(43, (uint32_t) int43);
  add_idt_segment(44, (uint32_t) int44);
  add_idt_segment(45, (uint32_t) int45);
  add_idt_segment(46, (uint32_t) int46);
  add_idt_segment(47, (uint32_t) int47);
  load_idt();
}


Top
 Profile  
 
 Post subject: Re: TSS problem
PostPosted: Tue Jan 30, 2018 3:04 pm 
Offline
Member
Member
User avatar

Joined: Sun Oct 22, 2006 7:01 am
Posts: 2646
Location: Devon, UK
Hi,

In your registers structure, what do you load in to eflags as an initial value? Is IF set?

CLI and STI are protected instructions, so depending on IOPL, #GPF may be the correct response.

Cheers,
Adam


Top
 Profile  
 
 Post subject: Re: TSS problem
PostPosted: Tue Jan 30, 2018 11:34 pm 
Offline

Joined: Sun Jan 28, 2018 9:29 am
Posts: 4
I loaded nothing in it. I don't think its necessary because i've never disabled interrupts before switching. I followed mainly https://wiki.osdev.org/Getting_to_Ring_3 and JamesM tutorial.


Top
 Profile  
 
 Post subject: Re: TSS problem
PostPosted: Wed Jan 31, 2018 9:07 am 
Offline
Member
Member
User avatar

Joined: Sun Oct 22, 2006 7:01 am
Posts: 2646
Location: Devon, UK
Ok - so what is in eflags when you execute PUSHF?


Top
 Profile  
 
 Post subject: Re: TSS problem
PostPosted: Wed Jan 31, 2018 9:36 am 
Offline

Joined: Sun Jan 28, 2018 9:29 am
Posts: 4
I didn't change EFLAGS, so I guess the defaults.


Top
 Profile  
 
 Post subject: Re: TSS problem
PostPosted: Wed Jan 31, 2018 9:45 am 
Offline
Member
Member
User avatar

Joined: Sun Oct 22, 2006 7:01 am
Posts: 2646
Location: Devon, UK
If you run in Bochs, what is in EFLAGS just prior to pushing the flags?


Top
 Profile  
 
 Post subject: Re: TSS problem
PostPosted: Wed Jan 31, 2018 9:53 am 
Offline

Joined: Sun Jan 28, 2018 9:29 am
Posts: 4
Im using QEMU


Top
 Profile  
 
 Post subject: Re: TSS problem
PostPosted: Wed Jan 31, 2018 10:25 am 
Offline
Member
Member
User avatar

Joined: Sun Oct 22, 2006 7:01 am
Posts: 2646
Location: Devon, UK
Hi,

There has to be some debugging effort on your part here. Either use Bochs or perform a Qemu registers dump just before the pushf instruction. If you are unsure how to do this, you need to learn your toolchain, ensure that you understand the code (not just C&P) and then look at the problem again.

Cheers,
Adam


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot], SemrushBot [Bot], Yahoo [Bot] and 68 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