hardware multitasking problem

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.
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

hardware multitasking problem

Post by xyjamepa »

Hi...
I'm trying to write hardware multitasking it consists of two tasks,
task() and main(),I really don't know what the problem is but Bochs
gives me this message: "task_switch: CS NULL",so can any one help me
here is the code....

Code: Select all

#define ACS_PRESENT	0X80		/* present segment */
#define ACS_CSEG	0X18		/* code segment */
#define ACS_DSEG	0X10		/* data segment */
#define ACS_CONIFORM	0X04
#define ACS_READ	0X02
#define ACS_WRITE	0X02
#define ACS_TSS_GATE	0X09
#define ACS_TSS		(ACS_PRESENT | ACS_TSS_GATE)

/* ready-made values */

#define ACS_CODE	(ACS_PRESENT | ACS_CSEG | ACS_READ)
#define ACS_DATA	(ACS_PRESENT | ACS_DSEG | ACS_WRITE)

Code: Select all

#define max_gdt_entrys	5

struct gdt_entry
{
    unsigned short limit_low;
    unsigned short base_low;
    unsigned char base_middle;
    unsigned char access;
    unsigned char granularity;
    unsigned char base_high;
} __attribute__((packed));

/* Special pointer which includes the limit: The max bytes
*  taken up by the GDT, minus 1. Again, this NEEDS to be packed */
struct gdt_ptr
{
    unsigned short limit;
    unsigned int base;
} __attribute__((packed));

/* Our GDT, with 5 entries, and finally our special GDT pointer */

struct gdt_entry gdt[max_gdt_entrys];
struct gdt_ptr gp;

extern gdt_flush();

/* Setup a descriptor in the Global Descriptor Table */
void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran)
{
    /* Setup the descriptor base address */
 gdt[num].base_low = (base & 0xFFFF);
 gdt[num].base_middle = (base >> 16) & 0xFF;
 gdt[num].base_high = (base >> 24) & 0xFF;

    /* Setup the descriptor limits */
 gdt[num].limit_low = (limit & 0xFFFF);
 gdt[num].granularity = ((limit >> 16) & 0x0F);

    /* Finally, set up the granularity and access flags */
 gdt[num].granularity |= (gran & 0xF0);
 gdt[num].access = access;
}

void gdt_install()
{
 printf("Installing GDT...");
    /* Setup the GDT pointer and limit */
 
 gp.limit = (sizeof(struct gdt_entry) * max_gdt_entrys) - 1;
 gp.base = &gdt;

    /* Our NULL descriptor 0x00 */
 gdt_set_gate(0, 0, 0, 0, 0);

    /* code descriptor */
  gdt_set_gate(1, 0, 0xFFFF, ACS_CODE , 0xCF);

   /* data descriptor */
  gdt_set_gate(2, 0,0xFFFF, ACS_DATA , 0xCF);
   
  /* -- 0x18 TSS for main() */
   
   gdt_set_gate(3,(word)&tss[0],sizeof(TSS),ACS_TSS,0xCF);
  
  /* -- 0x20 TSS for task() */
   
   gdt_set_gate(4,(word)&tss[1],sizeof(TSS),ACS_TSS,0xCF);
  
  
    /* Flush out the old GDT and install the new changes! */
  gdt_flush();

  printf("[Done]\n");
}

Code: Select all

struct tss_t
{
 dword  link,
	esp0,
	ss0,
	esp1,
	ss1,
	esp2,
	ss2,
	cr3,
	eip,
	eflags,
	eax,
	ecx,
	edx,
	ebx,
	esp,
	ebp,
	esi,
	edi,
	es,
	cs,
	ss,
	ds,
	fs,
	gs,
	ldtr;
 word	trace,
	io_map_addr;
	
};

typedef struct tss_t TSS;

#define max_tasks	2

TSS tss[max_tasks];

#define stack_size 1024

byte task_stack[stack_size];

void init_task()
{
 disable();
 tss[0].trace=tss[1].trace=0;
 tss[0].io_map_addr=tss[1].io_map_addr=sizeof(TSS);
 tss[0].ldtr=tss[1].ldtr=0;
 tss[1].fs=tss[1].gs=0;
 tss[1].ds=tss[1].es=tss[1].ss=0x10;
 tss[1].esp=(word)&task_stack+stack_size; 
 tss[1].cs=0x8;
 tss[1].eip=(word)&task;
 tss[1].eflags=0x202L;
 ltr(0x18);
 enable();
}

void ltr(unsigned short selector)
{
  asm ("ltr %0": :"r" (selector));
}

void task()
{
 printf("Hello form task()\n");
}


void far_jmp(unsigned int selector)
{
  unsigned int sel[2];
  sel[1] = selector;

  asm ("ljmp %0": :"m" (*sel));
}
when i do this far_jmp(0x20)
far jump to "task()" descriptor i get that message.
Thanx
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post by xyjamepa »

Now I loaded the cs register with value "0x08" i got
invalid opcode Exception.system halted
so can any one help me here...
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

Hi,

Code: Select all

void far_jmp(unsigned int selector) 
{ 
  unsigned int sel[2]; 
  sel[1] = selector; 

  asm ("ljmp %0": :"m" (*sel)); 
} 
What is this? You can use this:

Code: Select all

void far_jmp(unsigned int selector) 
{ 
  asm ("ljmp %0": :"m" (selector)); 
} 
Firstly, the code you were using was dereferencing unset memory (it should have been sel[0] = selector;).

Secondly, the code I posted is more efficient and does the same job.

Hope this helps.
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post by xyjamepa »

I tried your code and unfortunately I got general protection fault
when i made a far jmp to 0x20 which is "task()" descriptor in GDT...
I'm starting to pull my hair up....what's wrong???? :( :? :? :(
Thanx.
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

Do you use paging? If you do then there is a little quirk in X86 processors.
Avoid placing a page boundary in the part of the TSS that the processor reads during a task
switch (the first 104 bytes). The processor may not correctly perform address translations
if a boundary occurs in this area. During a task switch, the processor reads and writes into
the first 104 bytes of each TSS (using contiguous physical addresses beginning with the
physical address of the first byte of the TSS). So, after TSS access begins, if part of the 104
bytes is not physically contiguous, the processor will access incorrect information without
generating a page-fault exception.
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post by xyjamepa »

No right now I'm not using paging...
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

Okay then some other things to check
* The length of the GDT. Are the TSS descriptors within the limit?
* The TSS busy bit isn't set.
* Is the limit for the TSS properly set?

Also can you tell us what the error code from the GPF is?
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post by xyjamepa »

humm...
* The length of the GDT. Are the TSS descriptors within the limit?
The GDT limit is equal to (sizeof(struct gdt_entry) * max_gdt_entrys) - 1;
and max_gdt_entrys=5 and I have 5 descriptors: NULL,code,data,descriptor for main() and descriptr for task()
* The TSS busy bit isn't set.
would you please take a look at the TSS struct up there and see if it is correct,but i don't have busy bit in it.

* Is the limit for the TSS properly set?
if you mean the limit of the main() and task() descriptors the limit is equal to sizeof(TSS)
and Boch's gives me general protection fault and the int_no is 0xd
Thanx
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

Everything looks good to me. Could you post a floppy image? Maybe I would have better luck stepping through it with the debugger in bochs.
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post by xyjamepa »

Hi...
first of all I'm so grateful,thank you frank...
I hope you can open .tar files,you wil find a small version of my kernel and also the IMG file inside.
I built my GDT inside file called "pm.c","pm.h",also the TSS struct
at the end of "pm.h",I hope that was clear.
Thanx again.
Attachments
k.tar.gz
(47.19 KiB) Downloaded 42 times
knl.tar.gz
(15.38 KiB) Downloaded 52 times
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

I believe that I may have figured out your problem. In the following code you cast the the parameters to the set gdt function as words.

Code: Select all

/* -- 0x18 TSS for main() */
gdt_set_gate(3,(word)&tss[0],sizeof(TSS),ACS_TSS,0xCF);
  
/* -- 0x20 TSS for task() */ 
gdt_set_gate(4,(word)&tss[1],sizeof(TSS),ACS_TSS,0xCF);
However, both of the TSSs are above the 1mb mark and therefore cannot be represented with a word. If you eliminate all word casts and make them dwords then the code should work.
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post by xyjamepa »

Hi...
unfortunately it didn't work,I got general protection fault
I'm thinking of this stuff:

*should I load the cs,gs,fs,ds,es,ss with specific values ?
if yes would you please write to me a 32bit function in asm to
load values in one of this registers and then I'll write the rest
of the functions becuase really I'm not that good asm programmer.

*Is it necessary to write a stack descriptor in the GDT ?

*How can I use Boch's debugger ?

Thanx
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

The values of cs, es, ds, fs, gs, and ss should be loaded from the TSS. The stack descriptor in most OSs is the same as ds. You should make sure that all of the segment descriptors in the TSS are set to correct values. IIRC the code selector is 0x8 and all of the other descriptors should be 0x10. Are you sure that you changed the casts in my post from word to dword? That was one of the main problems I saw with the code. If that does not work then could you post an updated floppy image.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Post by Brendan »

Hi,

Just a quick note...
pcmattman wrote:

Code: Select all

void far_jmp(unsigned int selector) 
{ 
  asm ("ljmp %0": :"m" (selector)); 
} 
This won't work, because the selector for a far jump comes after the offset (not before). You'd actually need something like:

Code: Select all

    jmp far [address_of_selector_on_stack - 4]
I'm not sure about inline GAS syntax - something like this might work:

Code: Select all

void far_jmp(unsigned int selector) 
{ 
  asm ("ljmp -4(%0)": :"m" (selector)); 
} 

Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
xyjamepa
Member
Member
Posts: 397
Joined: Fri Sep 29, 2006 8:59 am

Post by xyjamepa »

humm...

I think you'r right Brendan but unfortunately gcc gave me an error.
so could any one give me a valid long jump function.
Are you sure that you changed the casts in my post from word to dword?
yes,I'm sure.

here's the updated floppy image,also if you want take a look at the code
I sent the updated pmode file "pm.c"

would you please take a look at this code,is there any wrong with it?

Code: Select all

void init_task()
{
 disable();
 tss[0].trace=tss[1].trace=0;
 tss[0].io_map_addr=tss[1].io_map_addr=sizeof(TSS);
 tss[0].ldtr=tss[1].ldtr=0;
 tss[1].fs=tss[1].gs=0;
 tss[1].ds=tss[1].es=tss[1].ss=0x10;
 tss[1].esp=(dword)&task_stack+stack_size; 
 tss[1].cs=0x8;
 tss[1].eip=(dword)&task;
 tss[1].eflags=0x202L;
 ltr(0x18);		//main() descriptor in GDT
 enable();
}
Thanx.
Attachments
a.tar.gz
(47.19 KiB) Downloaded 101 times
pm.c
(10.38 KiB) Downloaded 82 times
Post Reply