Discussion:
i386/x86_64 segment register issuses (Re: PATCH: Fix x86 segment register access)
(too old to reply)
H. J. Lu
2005-03-27 22:29:49 UTC
Permalink
It turns out that 2.4 kernel has

arch/i386/kernel/process.c: asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value)))
arch/i386/kernel/process.c: asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));
arch/i386/kernel/process.c: asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
arch/x86_64/kernel/process.c: asm("movl %%gs,%0" : "=m" (p->thread.gsindex));
arch/x86_64/kernel/process.c: asm("movl %%fs,%0" : "=m" (p->thread.fsindex));
arch/x86_64/kernel/process.c: asm("movl %%es,%0" : "=m" (p->thread.es));
arch/x86_64/kernel/process.c: asm("movl %%ds,%0" : "=m" (p->thread.ds));
arch/x86_64/kernel/process.c: asm volatile("movl %%es,%0" : "=m" (prev->es));
arch/x86_64/kernel/process.c: asm volatile ("movl %%ds,%0" : "=m" (prev->ds));

2.6 kernel has

arch/i386/kernel/process.c: asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));
arch/i386/kernel/process.c: asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
arch/x86_64/kernel/process.c: asm("movl %%gs,%0" : "=m" (p->thread.gsindex));
arch/x86_64/kernel/process.c: asm("movl %%fs,%0" : "=m" (p->thread.fsindex));
arch/x86_64/kernel/process.c: asm("movl %%es,%0" : "=m" (p->thread.es));
arch/x86_64/kernel/process.c: asm("movl %%ds,%0" : "=m" (p->thread.ds));
arch/x86_64/kernel/process.c: asm volatile("movl %%es,%0" : "=m" (prev->es));
arch/x86_64/kernel/process.c: asm volatile ("movl %%ds,%0" : "=m" (prev->ds));
arch/x86_64/kernel/process.c: asm volatile("movl %%fs,%0" : "=g" (fsindex));
arch/x86_64/kernel/process.c: asm volatile("movl %%gs,%0" : "=g" (gsindex));

The new assembler will disallow them since those instructions with
memory operand will only use the first 16bits. If the memory operand
is 16bit, you won't see any problems. But if the memory destinatin
is 32bit, the upper 16bits may have random values. The new assembler
will force people to use

mov (%eax),%ds
movw (%eax),%ds
movw %ds,(%eax)
mov %ds,(%eax)

Will it be a big problem for kernel people?

BTW, I haven't checked glibc yet. It may have similar issues.

H.J.
---
X86 segment register access is a special. We can move between a segment
register and a 16/32/64bit general-purpose register. But we can only
move between a segment register and a 16bit memory address. The current
assembler allows "movl (%eax),%ds", but doesn't allow "movq %rax,%ds".
The disassembler display "movl (%eax),%ds". This patch tries to fix
those.
H.J.
----
gas/testsuite/
* gas/i386/i386.exp: Run segment and inval-seg for i386. Run
x86-64-segment and x86-64-inval-seg for x86-64.
* gas/i386/intel.d: Expect movw for moving between memory and
segment register.
* gas/i386/naked.d: Likewise.
* gas/i386/opcode.d: Likewise.
* gas/i386/x86-64-opcode.d: Likewise.
* gas/i386/opcode.s: Use movw for moving between memory and
segment register.
* gas/i386/x86-64-opcode.s: Likewise.
* : Likewise.
* gas/i386/inval-seg.l: New.
* gas/i386/inval-seg.s: New.
* gas/i386/segment.l: New.
* gas/i386/segment.s: New.
* gas/i386/x86-64-inval-seg.l: New.
* gas/i386/x86-64-inval-seg.s: New.
* gas/i386/x86-64-segment.l: New.
* gas/i386/x86-64-segment.s: New.
include/opcode/
* i386.h (i386_optab): Don't allow the `l' suffix for moving
moving between memory and segment register. Allow movq for
moving between general-purpose register and segment register.
opcodes/
* i386-dis.c (SEG_Fixup): New.
(Sv): New.
(dis386): Use "Sv" for 0x8c and 0x8e.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



-------------------------------------------------------------------------------
Achtung: diese Newsgruppe ist eine unidirektional gegatete Mailingliste.
Antworten nur per Mail an die im Reply-To-Header angegebene Adresse.
Fragen zum Gateway -> ***@inka.de.
-------------------------------------------------------------------------------
Andi Kleen
2005-03-28 15:48:49 UTC
Permalink
Post by H. J. Lu
The new assembler will disallow them since those instructions with
memory operand will only use the first 16bits. If the memory operand
is 16bit, you won't see any problems. But if the memory destinatin
is 32bit, the upper 16bits may have random values. The new assembler
Does it really have random values on existing x86 hardware?

If it is a only a "theoretical" problem that does not happen
in practice I would advise to not do the change.
Post by H. J. Lu
will force people to use
mov (%eax),%ds
movw (%eax),%ds
movw %ds,(%eax)
mov %ds,(%eax)
Will it be a big problem for kernel people?
Well, we re getting used to the tool chain regularly breaking
perfectly good code.

You would not get more than the usual curses and only waste
a couple hundred man hours of testers worlwide scratching their heads
why their kernel does not compile anymore. World economy
will probably survive ite ;-)

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



-------------------------------------------------------------------------------
Achtung: diese Newsgruppe ist eine unidirektional gegatete Mailingliste.
Antworten nur per Mail an die im Reply-To-Header angegebene Adresse.
Fragen zum Gateway -> ***@inka.de.
-------------------------------------------------------------------------------
H. J. Lu
2005-03-28 18:08:45 UTC
Permalink
Post by Andi Kleen
Post by H. J. Lu
The new assembler will disallow them since those instructions with
memory operand will only use the first 16bits. If the memory operand
is 16bit, you won't see any problems. But if the memory destinatin
is 32bit, the upper 16bits may have random values. The new assembler
Does it really have random values on existing x86 hardware?
The x86 hardwares will only change the first 16bits. The rest bits
are unchanged. A simple test program can verify that.
Post by Andi Kleen
If it is a only a "theoretical" problem that does not happen
in practice I would advise to not do the change.
It depends on what the initial value in the upper bits is. The
assembler in CVS generates the same binary code as

movw %ds,(%eax)

for

movl %ds,(%eax)

But the previous assemblers will generate

66 8c 18 movw %ds,(%eax)

for

movw %ds,(%eax)

This bug has been fixed for a while. I guess that may be why Linux
kernel uses

movl %ds,(%eax)

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



-------------------------------------------------------------------------------
Achtung: diese Newsgruppe ist eine unidirektional gegatete Mailingliste.
Antworten nur per Mail an die im Reply-To-Header angegebene Adresse.
Fragen zum Gateway -> ***@inka.de.
-------------------------------------------------------------------------------
H. J. Lu
2005-03-28 18:30:45 UTC
Permalink
Post by H. J. Lu
Post by Andi Kleen
Post by H. J. Lu
The new assembler will disallow them since those instructions with
memory operand will only use the first 16bits. If the memory operand
is 16bit, you won't see any problems. But if the memory destinatin
is 32bit, the upper 16bits may have random values. The new assembler
Does it really have random values on existing x86 hardware?
The x86 hardwares will only change the first 16bits. The rest bits
are unchanged. A simple test program can verify that.
Post by Andi Kleen
If it is a only a "theoretical" problem that does not happen
in practice I would advise to not do the change.
It depends on what the initial value in the upper bits is. The
assembler in CVS generates the same binary code as
movw %ds,(%eax)
for
movl %ds,(%eax)
But the previous assemblers will generate
66 8c 18 movw %ds,(%eax)
for
movw %ds,(%eax)
This bug has been fixed for a while. I guess that may be why Linux
kernel uses
movl %ds,(%eax)
It turns out that both old and new assemblers will generate

0: 8c 18 movw %ds,(%eax)

for
mov %ds,(%eax)

So kernel can use "mov" instead of "movl" and the binary output will
be the same.

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



-------------------------------------------------------------------------------
Achtung: diese Newsgruppe ist eine unidirektional gegatete Mailingliste.
Antworten nur per Mail an die im Reply-To-Header angegebene Adresse.
Fragen zum Gateway -> ***@inka.de.
-------------------------------------------------------------------------------
H. J. Lu
2005-03-29 19:23:50 UTC
Permalink
The new i386/x86_64 assemblers no longer accept instructions for moving
between a segment register and a 32bit memory location, i.e.,

movl (%eax),%ds
movl %ds,(%eax)

To generate instructions for moving between a segment register and a
16bit memory location without the 16bit operand size prefix, 0x66,

mov (%eax),%ds
mov %ds,(%eax)

should be used. It will work with both new and old assemblers. The
assembler starting from 2.16.90.0.1 will also support

movw (%eax),%ds
movw %ds,(%eax)

without the 0x66 prefix. I am enclosing patches for 2.4 and 2.6 kernels
here. The resulting kernel binaries should be unchanged as before, with
old and new assemblers, if gcc never generates memory access for

unsigned gsindex;
asm volatile("movl %%gs,%0" : "=g" (gsindex));

If gcc does generate memory access for the code above, the upper bits
in gsindex are undefined and the new assembler doesn't allow it.

H.J.

Loading...