Re: [patch] entry.S asm improvement (removed some ugly jmp)

Linus Torvalds (torvalds@transmeta.com)
29 Nov 1998 19:05:19 GMT


In article <Pine.LNX.3.96.981128145704.607B-100000@dragon.bogus>,
Andrea Arcangeli <andrea@e-mind.com> wrote:
>On Fri, 27 Nov 1998, Linus Torvalds wrote:
>
>>When you actually end up doing a context switch, the return predictor is
>>hosed anyway - there's no way it can know what is going on, as the stack
>
>I guess that also when we return in user mode (return_all) we lose the
>return predictor...

No, the return predictor is certainly able to work past a user/kernel
switch: it probably won't even notice. I doubt any x86 chip actually
predicts far calls/jumps - they take too much time doing other things
that the prediction is fairly useless.

So as far as the predictor is concerned, a system call is either just a
no-op or just another call/return sequence.

What flushes a return predictor is
- context switches: in theory you could have process ID's for return
prediction the same way most modern chips have them for TLB entries,
but in practice it makes no sense at all, and the return predictor is
just screwed.

Note that this doesn't have to be "kernel" context switches at all:
it happens in user mode thread packages too, where the stack is
switched from under the thread so that the call/returns are no longer
nicely nested around the context switch.

- unpredictable call/return sequences. Sometimes people have "returns"
that return not to the caller, but somewhere else (error cases,
exceptions, etc).

Your patch falls into the second category, where you made a call/return
sequence unpredictable by removing the call and doing the return push it by
hand. Another case that used to be common is when a call expects the
called function to return to different places depending on whether an
error happened or not, so people had code like this:

call function
jmp ok
jmp error
jmp overflow

and then the function did something like this:

if (error) {
*return_value += 3;
return;
}

I know this used to be fairly common for BIOS/OS kind of interfaces not
all that long ago. Other uses that screw up return prediction tends to
be stuff like

call printoutfn
.asciiz "Hello world"
hlt /* "printoutfn" will return to after the string */

which was used at least for certain game machines where it was an easy
way to set up the arguments (hide them directly after the call, and have
the function increment the return point to after the arguments).

Few people seem to do stuff like this any more. And most modern CPU's
seem to have some kind of return predictor, usually 4 or 8 entries
(that's apparently enough to get 99% of all calls).

Linus

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/