Hello,
The following hunk of the 2.6.14 patch:
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index e3f362e..7a14fdf 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -313,16 +311,12 @@ void show_regs(struct pt_regs * regs)
printk(" DS: %04x ES: %04x\n",
0xffff & regs->xds,0xffff & regs->xes);
- __asm__("movl %%cr0, %0": "=r" (cr0));
- __asm__("movl %%cr2, %0": "=r" (cr2));
- __asm__("movl %%cr3, %0": "=r" (cr3));
- /* This could fault if %cr4 does not exist */
- __asm__("1: movl %%cr4, %0 \n"
- "2: \n"
- ".section __ex_table,\"a\" \n"
- ".long 1b,2b \n"
- ".previous \n"
- : "=r" (cr4): "0" (0));
+ cr0 = read_cr0();
+ cr2 = read_cr2();
+ cr3 = read_cr3();
+ if (current_cpu_data.x86 > 4) {
+ cr4 = read_cr4();
+ }
printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
show_trace(NULL, ®s->esp);
}
disables code to retrieve the actual value of CR4 on 486-class systems
(which may or may not implement the register, depending on the exact CPU
type and stepping). This seems suspicious to me, but I have to admit I
haven't followed the discussion on the issue if there was any.
Zachary, I think the change originates from you -- have you done it
deliberately (why?) or has it just been a mistake?
Maciej
Maciej W. Rozycki wrote:
>Hello,
>
> The following hunk of the 2.6.14 patch:
>
>diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
>index e3f362e..7a14fdf 100644
>--- a/arch/i386/kernel/process.c
>+++ b/arch/i386/kernel/process.c
>@@ -313,16 +311,12 @@ void show_regs(struct pt_regs * regs)
> printk(" DS: %04x ES: %04x\n",
> 0xffff & regs->xds,0xffff & regs->xes);
>
>- __asm__("movl %%cr0, %0": "=r" (cr0));
>- __asm__("movl %%cr2, %0": "=r" (cr2));
>- __asm__("movl %%cr3, %0": "=r" (cr3));
>- /* This could fault if %cr4 does not exist */
>- __asm__("1: movl %%cr4, %0 \n"
>- "2: \n"
>- ".section __ex_table,\"a\" \n"
>- ".long 1b,2b \n"
>- ".previous \n"
>- : "=r" (cr4): "0" (0));
>+ cr0 = read_cr0();
>+ cr2 = read_cr2();
>+ cr3 = read_cr3();
>+ if (current_cpu_data.x86 > 4) {
>+ cr4 = read_cr4();
>+ }
> printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
> show_trace(NULL, ®s->esp);
> }
>
>disables code to retrieve the actual value of CR4 on 486-class systems
>(which may or may not implement the register, depending on the exact CPU
>type and stepping). This seems suspicious to me, but I have to admit I
>haven't followed the discussion on the issue if there was any.
>
>
This was deliberate. CR4 doesn't exist on standard 486 class systems,
and I'm not sure how you could make use of it anyway, since the features
used by Linux - machine check, page size extensions, time stamp counter,
global pages, are only available in Pentium and later class systems, and
identified by CPUID, which also doesn't exist on 486.
There may be some funky Cyrix or even Intel CPUs that have CR4
registers, but showing the output in a register dump seems very
useless. I would also not recommend using undocumented features in CR4
even if you have such a freaky processor - there were bugs and/or
missing functionality with the early large page and global page
extensions that were not ironed out until the features became
documented, IIRC. YMMV - please let me know if anyone has found ways to
make this useful.
If I am wrong, I am happy to correct this, but I would like to do so
properly by adding safe_read_cr4() or equivalent rather than using raw
inlines assembler to catch the fault.
Thanks,
Zach
On Thu, 3 Nov 2005, Zachary Amsden wrote:
> >disables code to retrieve the actual value of CR4 on 486-class systems
> >(which may or may not implement the register, depending on the exact CPU
> >type and stepping). This seems suspicious to me, but I have to admit I
> >haven't followed the discussion on the issue if there was any.
> >
> >
>
> This was deliberate. CR4 doesn't exist on standard 486 class systems,
> and I'm not sure how you could make use of it anyway, since the features
> used by Linux - machine check, page size extensions, time stamp counter,
> global pages, are only available in Pentium and later class systems, and
> identified by CPUID, which also doesn't exist on 486.
Later Intel i486DX2 and i486DX4 processors (the so called "write-back
enhanced" ones) did support page size extensions (4MB pages) and as far as
I know we do use them on such chips. They did implement the CPUID
instruction, too (as well as late i486SX and i486SX2 chips that did not
support PSE). That's a counter-example that proves the actual value of
CR4 is going to be useful on these systems. These chips also implemented
the VME feature (the PVI and VME bits of CR4), but they may not be
terribly useful for us.
I used quite a few of such chips myself in mid 90s -- you may search
archives of various mailing lists for examples of "cpuinfo" dumps for such
processors.
> There may be some funky Cyrix or even Intel CPUs that have CR4
> registers, but showing the output in a register dump seems very
> useless. I would also not recommend using undocumented features in CR4
> even if you have such a freaky processor - there were bugs and/or
> missing functionality with the early large page and global page
> extensions that were not ironed out until the features became
> documented, IIRC. YMMV - please let me know if anyone has found ways to
> make this useful.
Please do always check the relevant datasheets before making such
assumptions -- these features of late Intel i486 processors were
documented to the expected extent, i.e. at least mentioned; though
depending on the exact document referred to, the exact details may have
been hidden behind these dreadful NDA-covered appendices.
The implementation you have removed (using a fault trapper) has been
originally written using the KISS approach -- instead of trying to
determine which bits of the CPUID status imply presence of CR4, the
register is accessed unconditionally as the opcode of the instruction used
is guarateed not to clash with any post-286 vendor-specific proprietary
CPU extension. As a result it may not be immediately obvious 486-class
chips are involved too. Search LKML archives for the original discussion
several years ago.
> If I am wrong, I am happy to correct this, but I would like to do so
> properly by adding safe_read_cr4() or equivalent rather than using raw
> inlines assembler to catch the fault.
Obviously -- I am not questioning the syntax, only the semantics.
Maciej
Maciej W. Rozycki wrote:
>On Thu, 3 Nov 2005, Zachary Amsden wrote:
>
>
>
>>>disables code to retrieve the actual value of CR4 on 486-class systems
>>>(which may or may not implement the register, depending on the exact CPU
>>>type and stepping). This seems suspicious to me, but I have to admit I
>>>haven't followed the discussion on the issue if there was any.
>>>
>>>
>>>
>>>
>>This was deliberate. CR4 doesn't exist on standard 486 class systems,
>>and I'm not sure how you could make use of it anyway, since the features
>>used by Linux - machine check, page size extensions, time stamp counter,
>>global pages, are only available in Pentium and later class systems, and
>>identified by CPUID, which also doesn't exist on 486.
>>
>>
>
> Later Intel i486DX2 and i486DX4 processors (the so called "write-back
>enhanced" ones) did support page size extensions (4MB pages) and as far as
>I know we do use them on such chips. They did implement the CPUID
>instruction, too (as well as late i486SX and i486SX2 chips that did not
>support PSE). That's a counter-example that proves the actual value of
>CR4 is going to be useful on these systems. These chips also implemented
>the VME feature (the PVI and VME bits of CR4), but they may not be
>terribly useful for us.
>
> I used quite a few of such chips myself in mid 90s -- you may search
>archives of various mailing lists for examples of "cpuinfo" dumps for such
>processors.
>
Finally got the relevant information from Intel. The embedded i486DX-2/4
series does support CPUID, and PSE, and thus CR4. Ugh. Also just found
this guy:
$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 4
model : 7
model name : 486 DX/2-WB
stepping : 0
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 1
wp : yes
flags : fpu vme pse
bogomips : 32.25
He won't like me too much. I'll write up a proper patch for this, a la
mode de rdmsr_safe / wrmsr_safe. At least it's not a bug, just missing
information.
Zach
Zachary Amsden <[email protected]> writes:
>
> He won't like me too much. I'll write up a proper patch for this, a la
> mode de rdmsr_safe / wrmsr_safe. At least it's not a bug, just missing
> information.
I don't think it's a good idea. Relying on nested faults in oops
is a bit unsafe because it could lead to recursive faults in the worst case.
Yes it does it already with __get_user, but that
is only last resort. You would make it default on these systems.
Better keep the if
-Andi
On Sat, 5 Nov 2005, Andi Kleen wrote:
> I don't think it's a good idea. Relying on nested faults in oops
> is a bit unsafe because it could lead to recursive faults in the worst case.
Good point.
> Better keep the if
Except the condition is wrong. Presence of CR4 could be tested elsewhere
though, with the result being the condition here.
Maciej
So some 486 processors do have CR4 register. Allow them to present it in
register dumps by using the old fault technique rather than testing processor
family.
Thanks to Maciej for noticing this.
Signed-off-by: Zachary Amsden <[email protected]>
Index: linux-2.6.14-zach-work/arch/i386/kernel/process.c
===================================================================
--- linux-2.6.14-zach-work.orig/arch/i386/kernel/process.c 2005-11-05 01:19:21.000000000 -0800
+++ linux-2.6.14-zach-work/arch/i386/kernel/process.c 2005-11-05 03:02:21.000000000 -0800
@@ -314,9 +314,7 @@ void show_regs(struct pt_regs * regs)
cr0 = read_cr0();
cr2 = read_cr2();
cr3 = read_cr3();
- if (current_cpu_data.x86 > 4) {
- cr4 = read_cr4();
- }
+ cr4 = read_cr4_safe();
printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
show_trace(NULL, ®s->esp);
}
Index: linux-2.6.14-zach-work/include/asm-i386/system.h
===================================================================
--- linux-2.6.14-zach-work.orig/include/asm-i386/system.h 2005-11-05 01:11:32.000000000 -0800
+++ linux-2.6.14-zach-work/include/asm-i386/system.h 2005-11-05 03:06:57.000000000 -0800
@@ -97,6 +97,19 @@ extern struct task_struct * FASTCALL(__s
:"=r" (__dummy)); \
__dummy; \
})
+
+#define read_cr4_safe() ({ \
+ unsigned int __dummy; \
+ /* This could fault if %cr4 does not exist */ \
+ __asm__("1: movl %%cr4, %0 \n" \
+ "2: \n" \
+ ".section __ex_table,\"a\" \n" \
+ ".long 1b,2b \n" \
+ ".previous \n" \
+ : "=r" (__dummy): "0" (0)); \
+ __dummy; \
+})
+
#define write_cr4(x) \
__asm__ __volatile__("movl %0,%%cr4": :"r" (x));
#define stts() write_cr0(8 | read_cr0())
On Mon, 7 Nov 2005, Zachary Amsden wrote:
> While this is at least no worse in the nested fault case than earlier
> kernels, I really wish I had one of those weird 486s so I could test the
> faulting mechanism. It seems the trap handling code has gotten quite
What's so weird about 486s? Besides, for testing it doesn't have to be
one -- you will get away with a 386, too. I have neither anymore, but
there are people around still using them.
Maciej
Maciej W. Rozycki wrote:
>On Mon, 7 Nov 2005, Zachary Amsden wrote:
>
>
>
>>While this is at least no worse in the nested fault case than earlier
>>kernels, I really wish I had one of those weird 486s so I could test the
>>faulting mechanism. It seems the trap handling code has gotten quite
>>
>>
>
> What's so weird about 486s? Besides, for testing it doesn't have to be
>one -- you will get away with a 386, too. I have neither anymore, but
>there are people around still using them.
>
>
Because I hold in my hand "i486 Microprocessor Programmer's Reference
Manual, c 1990", and it has no mention whatsoever of CR4, and all
documentation I had until Friday had either no mention of CR4, or
something to the effect of "new on Pentium, the CR4 register ..." So
I've had to re-adjust my definition of 486, which was weird.
Zach
On Mon, 7 Nov 2005, Zachary Amsden wrote:
> Maciej W. Rozycki wrote:
>
>> On Mon, 7 Nov 2005, Zachary Amsden wrote:
>>
>>
>>
>>> While this is at least no worse in the nested fault case than earlier
>>> kernels, I really wish I had one of those weird 486s so I could test the
>>> faulting mechanism. It seems the trap handling code has gotten quite
>>>
>>>
>>
>> What's so weird about 486s? Besides, for testing it doesn't have to be
>> one -- you will get away with a 386, too. I have neither anymore, but
>> there are people around still using them.
>>
>>
>
> Because I hold in my hand "i486 Microprocessor Programmer's Reference
> Manual, c 1990", and it has no mention whatsoever of CR4, and all
> documentation I had until Friday had either no mention of CR4, or
> something to the effect of "new on Pentium, the CR4 register ..." So
> I've had to re-adjust my definition of 486, which was weird.
>
> Zach
> -
Yes, and undocumented opcodes might not fault. They might do nothing
or something strange. It's not a good idea to use an undocumented
opcode in kernel space. The read-from-CR4 in kernel space, hoping
that an immoral-opcode trap will save you is not good practice.
You might reset the processor.
Cheers,
Dick Johnson
Penguin : Linux version 2.6.13.4 on an i686 machine (5589.55 BogoMips).
Warning : 98.36% of all statistics are fiction.
.
****************************************************************
The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to [email protected] - and destroy all copies of this information, including any attachments, without reading or disclosing them.
Thank you.
On Mon, 7 Nov 2005, Zachary Amsden wrote:
> Because I hold in my hand "i486 Microprocessor Programmer's Reference
> Manual, c 1990", and it has no mention whatsoever of CR4, and all
Ah, that's too old. Severely. By definition it can only cover the
original i486, perhaps even only before the i486SX has been released (and
the original renamed to the i486DX).
> documentation I had until Friday had either no mention of CR4, or
You've had to have the right bits of documentation -- Intel has been
quite precise about presence or absence of these bits in given members of
the i486 family, but you've had to check specifically each datasheet and
yes, there was a separate one for each member up till the grand merge in
1995 or so, when model specifics became chapters of the combined spec
("Intel486 Processor Family Developer's Manual" or something like that).
I still own the pile of printed books, including the latter, but not
easily accessible anymore.
> something to the effect of "new on Pentium, the CR4 register ..." So
> I've had to re-adjust my definition of 486, which was weird.
Note that the workstation version of the i486 continued to evolve up to
around 1995, IIRC, and unsurprisingly got some updates "from upstream".
;-)
Maciej
linux-os (Dick Johnson) wrote:
>On Mon, 7 Nov 2005, Zachary Amsden wrote:
>
>
>
>>Maciej W. Rozycki wrote:
>>
>>
>>
>>>On Mon, 7 Nov 2005, Zachary Amsden wrote:
>>>
>>>
>>>
>>>
>>>
>>>>While this is at least no worse in the nested fault case than earlier
>>>>kernels, I really wish I had one of those weird 486s so I could test the
>>>>faulting mechanism. It seems the trap handling code has gotten quite
>>>>
>>>>
>>>>
>>>>
>>>What's so weird about 486s? Besides, for testing it doesn't have to be
>>>one -- you will get away with a 386, too. I have neither anymore, but
>>>there are people around still using them.
>>>
>>>
>>>
>>>
>>Because I hold in my hand "i486 Microprocessor Programmer's Reference
>>Manual, c 1990", and it has no mention whatsoever of CR4, and all
>>documentation I had until Friday had either no mention of CR4, or
>>something to the effect of "new on Pentium, the CR4 register ..." So
>>I've had to re-adjust my definition of 486, which was weird.
>>
>>Zach
>>-
>>
>>
>
>Yes, and undocumented opcodes might not fault. They might do nothing
>or something strange. It's not a good idea to use an undocumented
>opcode in kernel space. The read-from-CR4 in kernel space, hoping
>that an immoral-opcode trap will save you is not good practice.
>
>You might reset the processor.
>
>
No, you won't. #UD and #GP will not (I hesitate to say never, but other
than a processor bug, I believe that is correct) reset the processor.
And CR4 is not "undocumented", even on 486.
What is immoral about opcode trapping?
Zach
On Mon, 7 Nov 2005, Zachary Amsden wrote:
> linux-os (Dick Johnson) wrote:
>
>> On Mon, 7 Nov 2005, Zachary Amsden wrote:
>>
>>
>>
>>> Maciej W. Rozycki wrote:
>>>
>>>> On Mon, 7 Nov 2005, Zachary Amsden wrote:
>>>>
>>>>
>>>>> While this is at least no worse in the nested fault case than earlier
>>>>> kernels, I really wish I had one of those weird 486s so I could test the
>>>>> faulting mechanism. It seems the trap handling code has gotten quite
>>>>>
>>>> What's so weird about 486s? Besides, for testing it doesn't have to be
>>>> one -- you will get away with a 386, too. I have neither anymore, but
>>>> there are people around still using them.
>>>>
>>>>
>>> Because I hold in my hand "i486 Microprocessor Programmer's Reference
>>> Manual, c 1990", and it has no mention whatsoever of CR4, and all
>>> documentation I had until Friday had either no mention of CR4, or
>>> something to the effect of "new on Pentium, the CR4 register ..." So
>>> I've had to re-adjust my definition of 486, which was weird.
>>>
>>> Zach
>>> -
>> Yes, and undocumented opcodes might not fault. They might do nothing
>> or something strange. It's not a good idea to use an undocumented
>> opcode in kernel space. The read-from-CR4 in kernel space, hoping
>> that an immoral-opcode trap will save you is not good practice.
>>
>> You might reset the processor.
>>
>>
>
> No, you won't. #UD and #GP will not (I hesitate to say never, but other
> than a processor bug, I believe that is correct) reset the processor.
> And CR4 is not "undocumented", even on 486.
>
Yes it is. The i486 Programmer's reference manual documents only
to CR3.
> What is immoral about opcode trapping?
>
> Zach
>
Unfortunately Intel and others call bad opcodes "illegal opcodes".
They are not, because as powerful as they are, Intel doesn't make
law. Instead, they are "invalid opcodes" (or just immoral) as I
stated as a play on words.
Cheers,
Dick Johnson
Penguin : Linux version 2.6.13.4 on an i686 machine (5589.55 BogoMips).
Warning : 98.36% of all statistics are fiction.
.
****************************************************************
The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to [email protected] - and destroy all copies of this information, including any attachments, without reading or disclosing them.
Thank you.
linux-os (Dick Johnson) wrote:
>>No, you won't. #UD and #GP will not (I hesitate to say never, but other
>>than a processor bug, I believe that is correct) reset the processor.
>>And CR4 is not "undocumented", even on 486.
>>
>
>
> Yes it is. The i486 Programmer's reference manual documents only
> to CR3.
The manual might be older than the newer 486 CPUs.
And don't forget that not every 486 is Intel. There are at least Cyrix,
AMD and UMC with interesting Am5x86-P75 and Cx5x86 too.
--
Ondrej Zary