2009-03-15 14:23:40

by Sergio Luis

[permalink] [raw]
Subject: x86: asm doubt

Hi there,

taking a look at arch/x86/power/cpu_(32|64).c, I saw the 32.c one
using the following macros

#define savesegment(seg, value) \
asm("mov %%" #seg ",%0":"=r" (value) : : "memory")


#define loadsegment(seg, value) \
asm volatile("\n" \
"1:\t" \
"movl %k0,%%" #seg "\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"3:\t" \
"movl %k1, %%" #seg "\n\t" \
"jmp 2b\n" \
".previous\n" \
_ASM_EXTABLE(1b,3b) \
: :"r" (value), "r" (0) : "memory")


saving and loading segment registers as in

savesegment(es, ctxt->es);
loadsegment(es, ctxt->es);

the code in cpu_64.c doesn't make use of such macros, doing the following:

saving:
asm volatile ("movw %%es, %0" : "=m" (ctxt->es));

loading:
asm volatile ("movw %0, %%es" :: "r" (ctxt->es));

So, my question is... what's the actual difference between both
versions? Aren't the macros suitable for the 64 version as well?

Thanks,
Sergio.


2009-03-15 16:41:55

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: Re: x86: asm doubt

Sergio Luis wrote:
> Hi there,
>
> taking a look at arch/x86/power/cpu_(32|64).c, I saw the 32.c one
> using the following macros
>
> #define savesegment(seg, value) \
> asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
>
>
> #define loadsegment(seg, value) \
> asm volatile("\n" \
> "1:\t" \
> "movl %k0,%%" #seg "\n" \
> "2:\n" \
> ".section .fixup,\"ax\"\n" \
> "3:\t" \
> "movl %k1, %%" #seg "\n\t" \
> "jmp 2b\n" \
> ".previous\n" \
> _ASM_EXTABLE(1b,3b) \
> : :"r" (value), "r" (0) : "memory")
>
>
> saving and loading segment registers as in
>
> savesegment(es, ctxt->es);
> loadsegment(es, ctxt->es);
>
> the code in cpu_64.c doesn't make use of such macros, doing the following:
>
> saving:
> asm volatile ("movw %%es, %0" : "=m" (ctxt->es));
>
> loading:
> asm volatile ("movw %0, %%es" :: "r" (ctxt->es));
>
> So, my question is... what's the actual difference between both
> versions? Aren't the macros suitable for the 64 version as well?
>

In 32-bit mode, moving to a segment register can fault if the underlying
GDT/LDT entry is invalid. In 64-bit mode, segment registers are mostly
decorative and have no function, and moving arbitrary values into them
doesn't fault, making the exception catching unnecessary.

But it would be good to use the same syntax to load segment registers
for both architectures to help with unification.

J

2009-03-16 13:12:59

by Sergio Luis

[permalink] [raw]
Subject: Re: x86: asm doubt

On Sun, Mar 15, 2009 at 1:41 PM, Jeremy Fitzhardinge <[email protected]> wrote:
> Sergio Luis wrote:
>>
>> Hi there,
>>
>> taking a look at arch/x86/power/cpu_(32|64).c, I saw the 32.c one
>> using the following macros
>>
>> #define savesegment(seg, value) ? ? ? ? ? ? ? ? ? ? ? ? \
>> ? ? ? ?asm("mov %%" #seg ",%0":"=r" (value) : : "memory")
>>
>>
>> #define loadsegment(seg, value) ? ? ? ? ? ? ? ? \
>> ? ? ? ?asm volatile("\n" ? ? ? ? ? ? ? ? ? ? ? \
>> ? ? ? ? ? ? ? ? ? ? "1:\t" ? ? ? ? ? ? ? ? ? ? \
>> ? ? ? ? ? ? ? ? ? ? "movl %k0,%%" #seg "\n" ? ?\
>> ? ? ? ? ? ? ? ? ? ? "2:\n" ? ? ? ? ? ? ? ? ? ? \
>> ? ? ? ? ? ? ? ? ? ? ".section .fixup,\"ax\"\n" \
>> ? ? ? ? ? ? ? ? ? ? "3:\t" ? ? ? ? ? ? ? ? ? ? \
>> ? ? ? ? ? ? ? ? ? ? "movl %k1, %%" #seg "\n\t" \
>> ? ? ? ? ? ? ? ? ? ? "jmp 2b\n" ? ? ? ? ? ? ? ? \
>> ? ? ? ? ? ? ? ? ? ? ".previous\n" ? ? ? ? ? ? ?\
>> ? ? ? ? ? ? ? ? ? ? _ASM_EXTABLE(1b,3b) ? ? ? ?\
>> ? ? ? ? ? ? ? ? ? ? : :"r" (value), "r" (0) : "memory")
>>
>>
>> saving and loading segment registers as in
>>
>> savesegment(es, ctxt->es);
>> loadsegment(es, ctxt->es);
>>
>> the code in cpu_64.c doesn't make use of such macros, doing the following:
>>
>> saving:
>> ?asm volatile ("movw %%es, %0" : "=m" (ctxt->es));
>>
>> loading:
>> asm volatile ("movw %0, %%es" :: "r" (ctxt->es));
>>
>> So, my question is... what's the actual difference between both
>> versions? Aren't the macros suitable for the 64 version as well?
>>
>
> In 32-bit mode, moving to a segment register can fault if the underlying
> GDT/LDT entry is invalid. ?In 64-bit mode, segment registers are mostly
> decorative and have no function, and moving arbitrary values into them
> doesn't fault, making the exception catching unnecessary.
>
> But it would be good to use the same syntax to load segment registers for
> both architectures to help with unification.
>
> ? J
>

Thanks for the explanation, Jeremy. So, maybe we could define those
same macros for X86_64 with something like the following? (sorry, it's
probably whitespace damaged since I am sending through this webmail
thing, but can you at least tell whether it's correct or not?)

diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h
index 8e626ea..259b85e 100644
--- a/arch/x86/include/asm/system.h
+++ b/arch/x86/include/asm/system.h
@@ -262,6 +262,20 @@ static inline void native_write_cr8(unsigned long val)
{
asm volatile("movq %0,%%cr8" :: "r" (val) : "memory");
}
+
+/*
+ * In 64-bit mode, segment registers are mostly decorative
+ * and have no function, and moving arbitrary values into
+ * them doesn't fault, making the exception catching unnecessary.
+ */
+#define loadsegment(seg, value) \
+ asm volatile ("movw %%" #seg ", %0" : "=r" (value) : : "memory");
+
+/*
+ * Save a segment register away
+ */
+#define savesegment(seg, value) \
+ asm volatile ("movw %%" #seg ", %0" : "=m" (value) : : "memory");
#endif

static inline void native_wbinvd(void)

---

and a last unrelated question. why do we have a asm/system_64.h file
which defines only two functions read_cr8/write_cr8 that are exactly
identical to native_read_cr8/native_write_cr8 defined in system.h?

Thank you again,
Sergio.

2009-03-16 14:13:26

by Avi Kivity

[permalink] [raw]
Subject: Re: x86: asm doubt

Jeremy Fitzhardinge wrote:
> In 32-bit mode, moving to a segment register can fault if the
> underlying GDT/LDT entry is invalid. In 64-bit mode, segment
> registers are mostly decorative and have no function, and moving
> arbitrary values into them doesn't fault, making the exception
> catching unnecessary.

64-bit mode will in fact fault if an access is made outside the GDT/LDT,
or of the descriptor is invalid.


--
error compiling committee.c: too many arguments to function

2009-03-16 16:20:59

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: Re: x86: asm doubt

Avi Kivity wrote:
> Jeremy Fitzhardinge wrote:
>> In 32-bit mode, moving to a segment register can fault if the
>> underlying GDT/LDT entry is invalid. In 64-bit mode, segment
>> registers are mostly decorative and have no function, and moving
>> arbitrary values into them doesn't fault, making the exception
>> catching unnecessary.
>
> 64-bit mode will in fact fault if an access is made outside the
> GDT/LDT, or of the descriptor is invalid.

Oh, I didn't think it bothered. I guess I'm conflating that with the
fact that it doesn't apply any of the segment properties to memory
accesses. Anyway, in that case the 64-bit code should definitely be
using the standard segment accessors.

J