9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] some x86 Segment descriptor experiments
@ 2008-05-13 22:10 cinap_lenrek
  2008-05-13 23:26 ` ron minnich
  0 siblings, 1 reply; 3+ messages in thread
From: cinap_lenrek @ 2008-05-13 22:10 UTC (permalink / raw)
  To: 9fans

Hi,

I'm trying to implement TLS support for linuxemu. TLS on
linux works as following:

here is a syscall called set_thread_area() where a struct is
passed containing something like a segment descriptor that
is stored for the process and is switched in the gdt when
the process gets resumed for execution.

the linux thread library allocates some memory, makes an descriptor
with the base address on that memory using set_thread_area, build
segment selector for it and stores that on GS segment register.
that memory is then accessed with the GS segment prefixed so that
every thread ends up with its own TLS block.

For testing, i reserved 2 slots in the Plan9 gdt and wrote a
driver to read/write the slots from userspace. I also needed to comment
out a check that disallows changing the segment register GS and
FS to something other than UDSEG.

This worked fine so far... i could get bash running with libthread and
TLS initialization. (They crash with null-pointer exception when
here is no valid segment descriptor installed)

Things got interesting when i tried to make the descriptors
local for every process. (Thats the whole idea of TLS)

I put a Segdesc tlsdescr[2]; array on the PMMU struct in pc/dat.h
and added code in port/devproc.c to read/write that array from
userspace.

To switch the gdt entries in when the program gets resumed,
added something like this in pc/main.c:

void procrestore(Proc *p){
...
+	m->gdt[UTLSSEG0] =  p->tlsdescr[0];
+	m->gdt[UTLSSRG1] = p->tlsdescr[1];
...
}


and
void procsetup(Proc *p){
...
+	p->tlsdescr[0] = (Segdesc){0, 0};
+	p->tlsdescr[1] = (Segdesc){0, 0};
...
}

assuming the segment registers get reloaded when the kernel
restores to userspace in pc/l.s:

TEXT _strayintr(SB), $0
	/* ... segment registers get saved ... */
	PUSHL	SP			/* Ureg* argument to trap */
	CALL	trap(SB)

TEXT forkret(SB), $0
	POPL	AX
	POPAL
	POPL	GS	/* <- here we reload the segment registers right? */
	POPL	FS
	POPL	ES
	POPL	DS
	ADDL	$8, SP			/* pop error code and trap type */
	IRETL

or are here other paths out of the kernel too?

the reloading is required because as i read from thr processor
documentation, the processor caches the effective contents of a
GDT/LDR descriptor in shadow segment registers and only updates
them on LOAD.

OK... after all... doent work and i have no idea why. Program just crashed
as if here was no segment at all. I added a sleep(1) after i wrote
the p->tlsdescr[x] and then it worked for a short time... and then crashed
the whole kernel...

I have never done any kernelhacking so far and never fiddled with
GDT stuff... So some stupid newbie questions :-)

Does the kernel use any other segment selectors other than CS and DS? If
it doent use GS/FS... this should not have any side effects...
also... a process could change the segment descriptor to some invalid
range... paging would protect the process from doing any harm right?

Can the Mach *m->gdt[] be accessed on restoreproc() without problems?
Do i need to disable interrupts or something?
Are all the segment registers reloaded when the kernel switches back
to userspace? (as the thing above)

Any other idea why this doent work?

cinap




^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [9fans] some x86 Segment descriptor experiments
  2008-05-13 22:10 [9fans] some x86 Segment descriptor experiments cinap_lenrek
@ 2008-05-13 23:26 ` ron minnich
  2008-05-14  0:12   ` cinap_lenrek
  0 siblings, 1 reply; 3+ messages in thread
From: ron minnich @ 2008-05-13 23:26 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

it seems reasonable on first glance. What's the stack barf look like?

ron



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [9fans] some x86 Segment descriptor experiments
  2008-05-13 23:26 ` ron minnich
@ 2008-05-14  0:12   ` cinap_lenrek
  0 siblings, 0 replies; 3+ messages in thread
From: cinap_lenrek @ 2008-05-14  0:12 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 444 bytes --]

arrrg... i found the problem... of course! Plan9 *does* restore/reload the
segment registers! It does it still in kernel mode. So if a segment
register is set (from usermode) with a selector pointing to my TLS
descriptor, and that descriptor gets changed to {0, 0} again, forkret()
restores/reloads the segment register and *kernel* gets a GP fault.

Now the selector checking in trap() makes sense... arrg >_<

sorry for the noise...

[-- Attachment #2: Type: message/rfc822, Size: 2482 bytes --]

From: "ron minnich" <rminnich@gmail.com>
To: "Fans of the OS Plan 9 from Bell Labs" <9fans@9fans.net>
Subject: Re: [9fans] some x86 Segment descriptor experiments
Date: Tue, 13 May 2008 16:26:31 -0700
Message-ID: <13426df10805131626q1c3775b2hc7957c7e77ed724@mail.gmail.com>

it seems reasonable on first glance. What's the stack barf look like?

ron

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2008-05-14  0:12 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-05-13 22:10 [9fans] some x86 Segment descriptor experiments cinap_lenrek
2008-05-13 23:26 ` ron minnich
2008-05-14  0:12   ` cinap_lenrek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).