Page 1 of 1

[SOLVED] %fs base not updating (Thread Local Storage)

Posted: Tue Sep 02, 2014 9:03 am
by zhiayang
Hello. I'm starting to implement TLS in my OS, using the traditional %fs:offset as used by GCC's __thread. Problem is, %fs:0x0 == 0, meaning that the base address of %fs is not resolving properly. Here's some info:

- %fs = 0x2B, which is a dummy GDT descriptor that I cloned from my ring3 DS descriptor
- Long mode.

I'm using the MSR method with MSRID = 0xC0000100 to change FS.base (as described in the AMD manual). I'm getting a page fault on address 0xFFFFFFFFFFFFFFFC, which is -4(0). This is the disassembly of the faulting code (in userspace):

Code: Select all

 2000ab9:	64 48 8b 04 25 00 00 	mov    %fs:0x0,%rax
 2000ac0:	00 00 
 2000ac2:	48 8d 80 fc ff ff ff 	lea    -0x4(%rax),%rax
 2000ac9:	c7 00 00 00 00 00    	movl   $0x0,(%rax)
 2000acf:	48 83 c4 08          	add    $0x8,%rsp

Basically, since movl $0x0, (%rax) page faults, then lea -0x4(%rax) must be loading 0xFFFFFFFFFFFFFFFC, therefore %fs:0x0 must be 0.
Here's how I'm changing %fs:

Code: Select all

uint32_t low = tlsptr & 0xFFFFFFFF;
uint32_t high = tlsptr >> 32;
asm volatile(
		"mov $0x2B, %%bx           \n\t"
		"mov %%bx, %%fs            \n\t"

		"movl $0xC0000100, %%ecx	\n\t"
		"movl %[lo], %%eax		   \n\t"
		"movl %[hi], %%edx		   \n\t"
		"wrmsr				         \n\t"

		:: [lo]"g"(low), [hi]"g"(high) : "memory", "rax", "rbx", "rcx", "rdx");

And finally, here's the GDT entry for 0x28:

Code: Select all

	GDTFS:
		.word 0xFFFF		 // Limit (low)
		.word 0			   // Base (low)
		.byte 0			   // Base (middle)
		.byte 0xF2			// Access
		.byte 0xAF			// Granularity (4) / Limit (high) (4)
		.byte 0			   // Base (high)

This has literally been bugging me for more than a few hours now, so any help is appreciated, thanks!

Re: %fs base not updating (Thread Local Storage)

Posted: Tue Sep 02, 2014 9:20 am
by mrvn
Your code does NOT show that %fs.base is 0 but that the memory %fs.base points to contains 0. You are accessing a NULL pointer.

Re: %fs base not updating (Thread Local Storage)

Posted: Tue Sep 02, 2014 9:21 am
by zhiayang
mrvn wrote:Your code does NOT show that %fs.base is 0 but that the memory %fs.base points to contains 0. You are accessing a NULL pointer.
Yea, totally screwed up there. I guess my mind wasn't working too well, I can see you were trying to tell me this on IRC.
Sorry for wasting your time ):

Re: [SOLVED] %fs base not updating (Thread Local Storage)

Posted: Tue Sep 02, 2014 9:29 am
by Icee
You might also want to use a single dedicated WRFSBASE instruction instead of a WRMSR-based sequence.