2001-04-06 07:31:39

by alad

[permalink] [raw]
Subject: __switch_to macro



Hi,
The note above __switch_to macro in i386/kernel/process.c says that we no
more use hardware context switching as some problems in recovering from
saved state that is no longer valid. (I am peeking into 2.2 kernel). Now I have
following questions

1) What exactly is meant by ' stale segment register values' in the note.
2) In the above macro, I think we recover gracefully from error condition while
recovering fs and gs segment registers . The loadsegment(fs,next->tss.fs) and
loadsegment(gs,next->tss.gs) does it. I am not able to understand loadsegment
macro. The macro is as under

/** Load a segment. Fall back on loading a zero segment if something goes wrong
**/
#define loadsegment(seg,value) \
asm volatile("\n" \
"1:\t" \
"movl %0,%%" #seg "\n" \
"2:\n" \
"3:\t" \
"pushl $0\n\t" \
"jmp 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n\t \
"/align 4\n\t" \
".long 1b,3b\n" \
".previous" \
: :"m" (*(unsigned int *)&(value)))

I also want to know what is 'something' in the comment above the macro

Thanks in advance
Amol







2001-04-06 08:49:30

by Jamie Lokier

[permalink] [raw]
Subject: Re: __switch_to macro

[email protected] wrote:
> 1) What exactly is meant by ' stale segment register values' in the note.
> 2) In the above macro, I think we recover gracefully from error
> condition while recovering fs and gs segment registers . The
> loadsegment(fs,next->tss.fs) and loadsegment(gs,next->tss.gs) does
> it. I am not able to understand loadsegment macro. The macro is as under
>
> /** Load a segment. Fall back on loading a zero segment if something goes wrong
> **/
> #define loadsegment(seg,value) \
> asm volatile("\n" \
> "1:\t" \
> "movl %0,%%" #seg "\n" \
> "2:\n" \
> "3:\t" \
> "pushl $0\n\t" \
> "jmp 2b\n" \
> ".previous\n" \
> ".section __ex_table,\"a\"\n\t \
> "/align 4\n\t" \
> ".long 1b,3b\n" \
> ".previous" \
> : :"m" (*(unsigned int *)&(value)))
>
> I also want to know what is 'something' in the comment above the macro

The answers to 1. and 'something' are the same: stale segment values.
You can't load any value into %ss, %ds, %es, %fs or %gs. They must be
valid references into the GDT or LDT, with the appropriote protection
level, or 0.

Usually the values stored in tss are ok, as they were valid values when
they were stored. However for programs that use modify_ldt, it's
possible for a valid LDT entry to be made invalid while some tss still
refers to that segment.

At the next attempt to load the segment value into a segment register,
you get a fault. The code in loadsegment traps this fault and loads
zero into the segment register instead when this happens. Zero is
always allowed. If the user program then tries to access data
referenced by that segment register, user space will get a
general_protection fault. As it's only user space that calls modify_ldt
to invalidate an LDT entry, that's reasonable.

There's one thing that confuses me: don't you get a segment_not_present
fault? If so, traps.c's do_segment_not_present doesn't appear to search
the exception table, and the code in loadsegment would not work.

-- Jamie

2001-04-06 09:21:36

by alad

[permalink] [raw]
Subject: Re: __switch_to macro








Jamie Lokier <[email protected]> on 04/06/2001 03:18:13 PM

To: Amol Lad/HSS@HSS
cc: [email protected]

Subject: Re: __switch_to macro




[email protected] wrote:
> 1) What exactly is meant by ' stale segment register values' in the note.
> 2) In the above macro, I think we recover gracefully from error
> condition while recovering fs and gs segment registers . The
> loadsegment(fs,next->tss.fs) and loadsegment(gs,next->tss.gs) does
> it. I am not able to understand loadsegment macro. The macro is as under
>
> /** Load a segment. Fall back on loading a zero segment if something goes
wrong
> **/
> #define loadsegment(seg,value) \
> asm volatile("\n" \
> "1:\t" \
> "movl %0,%%" #seg "\n" \
> "2:\n" \
> "3:\t" \
> "pushl $0\n\t" \
> "jmp 2b\n" \
> ".previous\n" \
> ".section __ex_table,\"a\"\n\t \
> "/align 4\n\t" \
> ".long 1b,3b\n" \
> ".previous" \
> : :"m" (*(unsigned int *)&(value)))
>
> I also want to know what is 'something' in the comment above the macro

The answers to 1. and 'something' are the same: stale segment values.
You can't load any value into %ss, %ds, %es, %fs or %gs. They must be
valid references into the GDT or LDT, with the appropriote protection
level, or 0.

Usually the values stored in tss are ok, as they were valid values when
they were stored. However for programs that use modify_ldt, it's
possible for a valid LDT entry to be made invalid while some tss still
refers to that segment.

>>> Thanks a lot.. good explanation..

At the next attempt to load the segment value into a segment register,
you get a fault. The code in loadsegment traps this fault and loads
zero into the segment register instead when this happens. Zero is
always allowed. If the user program then tries to access data
referenced by that segment register, user space will get a
general_protection fault. As it's only user space that calls modify_ldt
to invalidate an LDT entry, that's reasonable.

There's one thing that confuses me: don't you get a segment_not_present
fault? If so, traps.c's do_segment_not_present doesn't appear to search
the exception table, and the code in loadsegment would not work.

>>> well.. I peeked into traps.c.. I do seem a call to die_if_no_fixup
in this function. And I think loadsegment is already making an entry in
exception table.

Amol


-- Jamie




2001-04-06 11:40:25

by Jamie Lokier

[permalink] [raw]
Subject: Re: __switch_to macro

[email protected] wrote:
> There's one thing that confuses me: don't you get a segment_not_present
> fault? If so, traps.c's do_segment_not_present doesn't appear to search
> the exception table, and the code in loadsegment would not work.
>
> >>> well.. I peeked into traps.c.. I do seem a call to die_if_no_fixup
> in this function. And I think loadsegment is already making an entry in
> exception table.

Ah, you're right. I didn't follow DO_ERROR all the way to do_trap and
hency search_exception_table.

-- Jamie