I'm trying to read Linux source code(2.6.11)
In the exception handler, at entry.s, error_code:
movl $(__USER_DS), %ecx
movl %ecx, %ds
movl %ecx, %es
I don't know why loading user data segment here. Since it is supposed to be entering the exception handler code which runs in the kernel mode, the selector is supposed to be __KERNEL_DS.
I checked other versions of the code, they do the same thing specifically too at this place.
If the exception handler is entered with
ds
andes
already set to the data segment, it makes no difference except for maybe a microsecond of delay. Exception handlers don't usually need to be fast.But what might cause going to the exception handler? Could it have been because a bad value was loaded into a segment register and then referenced? In such cases it is important for the code to establish a safe environment.
cs
is set by the exception invocation. To be bulletproof,ss
andesp
should be set up too.Followup:
Looking at the 2-6.22.18 kernel for i386, I don't see exactly that:
The symbol
__KERNEL_PERCPU
is a macro defined (ininclude/asm-i386/segment.h
) as0
for non-SMP machines and(GDT_ENTRY_PERCPU * 8)
for SMPs. The 8 is for the GDT entry size (I think) and theGDT_ENTRY_PERCPU
relates to the entries in the per-CPU GDT. Its value is<base> + 15
which the comments indicate is "default user DS", so it is, in fact, the same thing.The kernel data segment is accessed through
fs
andss
. Much kernel data access is on the stack. By keeping the user mode descriptors accessed throughds
, very little loading of segment registers is needed.