Bochs: LTR: doesn't point to an available TSS descriptor!

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
User avatar
AlfaOmega08
Member
Member
Posts: 226
Joined: Wed Nov 07, 2007 12:15 pm
Location: Italy

Bochs: LTR: doesn't point to an available TSS descriptor!

Post by AlfaOmega08 »

When loading my Task Register, bochs exit with:

LTR: doesn't point to an available TSS descriptor!

I've read the Bochs Source Code:

Code: Select all

if (descriptor.valid==0 || descriptor.segment ||
       (descriptor.type!=BX_SYS_SEGMENT_AVAIL_286_TSS && 
        descriptor.type!=BX_SYS_SEGMENT_AVAIL_386_TSS)) 
{
  BX_ERROR(("LTR: doesn't point to an available TSS descriptor!"));
  exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
}
my descriptor.type is equal to 0x9 in the GDT
I've tried to see where is defined descriptor.segment and .valid.

In the function parse_descriptor in cpu/segment_ctrl_pro.cc is checked if the descriptor is a segment (if the bit4 in the access byte is set). If not it starts to see wath the descriptor is. In this checks is included also the 386 TSS descriptor, and descriptor.valid is set to 1. So why does bochs give me this error?[/code]
alkot
Posts: 13
Joined: Tue Nov 06, 2007 5:10 am

Post by alkot »

You can set breakpoint (int 3 maybe) in Bochs and see real descriptors loaded into gdt with command "info gdt" to check that Bochs realy loaded what you assume to load.

You need a Bochs compiled with --enable-debugger
User avatar
AlfaOmega08
Member
Member
Posts: 226
Joined: Wed Nov 07, 2007 12:15 pm
Location: Italy

Post by AlfaOmega08 »

I need not the INT 3. When bochs give me that message, a General Protection Fault is fired, and my kernel enter in an infinite loop. So I press CTRL+C to enter the debugger and my gdt contains:

Code: Select all

Global Descriptor Table (base=0x00016c80, limit=39):
GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x01]=Code segment, linearaddr=00000000, limit=fffff * 4Kbytes, Execute/Read, 32-bit
GDT[0x02]=Data segment, linearaddr=00000000, limit=fffff * 4Kbytes, Read/Write, Accessed
GDT[0x03]=32-Bit TSS (Busy) at 0x000274c0, length 0x00068
GDT[0x04]=32-Bit TSS (Available) at 0x00027528, length 0x00068
alkot
Posts: 13
Joined: Tue Nov 06, 2007 5:10 am

Post by alkot »

What selector do you pass to the LTR command? What is the error code of GP exception in bochs log?
Can you show a part of your code?
User avatar
AlfaOmega08
Member
Member
Posts: 226
Joined: Wed Nov 07, 2007 12:15 pm
Location: Italy

Post by AlfaOmega08 »

Sure I can. I've a gdt::setDesc function:

Code: Select all

int gdt::setDesc(int index, unsigned long base, unsigned long limit, unsigned char dpl, types type, char update) {
	if (index == 0) {
		gdtDescs[0].lowBase = 0;
		gdtDescs[0].middleBase = 0;
		gdtDescs[0].highBase = 0;
		gdtDescs[0].lowLimit = 0;
		gdtDescs[0].granularity = 0;
		gdtDescs[0].access = 0;
		return 0;
	}

	gdtDescs[index].lowBase = (base & 0xFFFF);
	gdtDescs[index].middleBase = (base >> 16) & 0xFF;
	gdtDescs[index].highBase = (base >> 24) & 0xFF;

	gdtDescs[index].lowLimit = (limit & 0xFFFF);
	
	gdtDescs[index].granularity = (0xC << 4) ^ ((limit >> 16) & 0x0F);

	switch (type) {
		case DataUp: //0x0
		case DataUpWriteable: //0x2
		case CodeUp: //0x8
		case CodeUpReadable: //0xA
			gdtDescs[index].access = (1 << 7) ^ ((dpl & 0x3) << 5) ^ (1 << 4) ^ (type & 0x0F);
			break;
		default:
			gdtDescs[index].access = (1 << 7) ^ ((dpl & 0x3) << 5) ^ (0 << 4) ^ (type & 0x0F);
			break;
	}

//	printf("Dword1: %X\nDword2: %X\n", ((limit & 0xFFFF) << 16) ^ (base & 0xFFFF), (base & 0xFF) ^ (gdtDescs[index].access << 16) ^ (gdtDescs[index].granularity << 8) ^ ((base >> 24) & 0xFF));

	GDTr.limit = (sizeof(struct GDTentry) * getNumberOfDescs()) - 1;

	if (update)
		updGDT();

	return index * 8;
}
where gdtDescs is an array of 8192 elements defined as gdt::GDTEntry that is a structure like this:

Code: Select all

struct GDTentry {
	unsigned short lowLimit;
	unsigned short lowBase;
	unsigned char middleBase;
	unsigned char access;
	unsigned char granularity;
	unsigned char highBase;
}
The Handler of my GP Faults report an Error Code = 24 (3 * 8 ), so it should be right
alkot
Posts: 13
Joined: Tue Nov 06, 2007 5:10 am

Post by alkot »

According to GP error code (raw_selector & 0xfffc) you are trying to switch to BUSY TSS (index 3) --
/* #GP(selector) if object is not a TSS or is already busy */
User avatar
AlfaOmega08
Member
Member
Posts: 226
Joined: Wed Nov 07, 2007 12:15 pm
Location: Italy

Post by AlfaOmega08 »

I've tryed to load the 4th segment with the tr = 32. Now info gdt tells that the 4th segment is Busy. So them became busy when I load the TR
alkot
Posts: 13
Joined: Tue Nov 06, 2007 5:10 am

Post by alkot »

TSS marks busy when it successfully loaded.
the end of BX_CPU_C::LTR_Ew

Code: Select all

  /* mark as busy */
  if (!(dword2 & 0x0200)) {
    dword2 |= 0x0200; /* set busy bit */
    access_linear(BX_CPU_THIS_PTR gdtr.base + selector.index*8 + 4, 4, 0,
        BX_WRITE, &dword2);
  }
Maybe you are trying to switch to it twice?
User avatar
AlfaOmega08
Member
Member
Posts: 226
Joined: Wed Nov 07, 2007 12:15 pm
Location: Italy

Post by AlfaOmega08 »

Yes!!! :shock:
I've two TSSs. When the PIT fires, I've to load the new TR. If I make an infinite loop after the first LTR is loaded... there isn't any GP fault!!! Now the problem is to understand why it tryes to loads the same TR again... :lol:

Thanks a lot
Post Reply