9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
From: cinap_lenrek@gmx.de
To: 9fans@9fans.net
Subject: [9fans] some x86 Segment descriptor experiments
Date: Wed, 14 May 2008 00:10:06 +0200	[thread overview]
Message-ID: <24aec0f0aa0c2eb4bd08246eb12d0730@gmx.de> (raw)

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




             reply	other threads:[~2008-05-13 22:10 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-13 22:10 cinap_lenrek [this message]
2008-05-13 23:26 ` ron minnich
2008-05-14  0:12   ` cinap_lenrek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=24aec0f0aa0c2eb4bd08246eb12d0730@gmx.de \
    --to=cinap_lenrek@gmx.de \
    --cc=9fans@9fans.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).