_cpuid() - full cpuid instruction wrapper

- the prototype changes to 

	_cpuid(u32_t *eax, u32_t *ebx, u32_t *ecx, u32_t *edx)

- this makes possible to use all the features of the cpuid instruction as
  described in the Intel specs
This commit is contained in:
Tomas Hruby 2010-01-15 15:23:57 +00:00
parent 45eabea285
commit 80d671aea7
5 changed files with 50 additions and 45 deletions

View file

@ -18,6 +18,9 @@
#define _CPUF_I386_SSE4_1 11
#define _CPUF_I386_SSE4_2 12
#define _CPUF_I386_HTT 13 /* Supports HTT */
#define _CPUF_I386_HTT_MAX_NUM 14 /* Maximal num of threads */
_PROTOTYPE(int _cpufeature, (int featureno));
#endif

View file

@ -15,7 +15,7 @@ _PROTOTYPE(void std_err, (char *_s));
_PROTOTYPE(void prints, (const char *_s, ...));
_PROTOTYPE(int fsversion, (char *_dev, char *_prog));
_PROTOTYPE(int getprocessor, (void));
_PROTOTYPE(void _cpuid, (u32_t eax_in, u32_t *eax, u32_t *ebx, u32_t *ecx, u32_t *edx));
_PROTOTYPE(void _cpuid, (u32_t *eax, u32_t *ebx, u32_t *ecx, u32_t *edx));
_PROTOTYPE(int load_mtab, (char *_prog_name));
_PROTOTYPE(int rewrite_mtab, (char *_prog_name));
_PROTOTYPE(int get_mtab_entry, (char *_s1, char *_s2, char *_s3, char *_s4));

View file

@ -75,6 +75,7 @@ sys/vm_i386.h
#define CPUID1_EDX_PGE (1L << 13) /* Page Global (bit) Enable */
#define CPUID1_EDX_APIC_ON_CHIP (1L << 9) /* APIC is present on the chip */
#define CPUID1_EDX_TSC (1L << 4) /* Timestamp counter present */
#define CPUID1_EDX_HTT (1L << 28) /* Supports HTT */
#define CPUID1_EDX_FXSR (1L << 24)
#define CPUID1_EDX_SSE (1L << 25)
#define CPUID1_EDX_SSE2 (1L << 26)

View file

@ -6,57 +6,61 @@
int _cpufeature(int cpufeature)
{
u32_t cpuid_feature_edx = 0;
u32_t cpuid_feature_ecx = 0;
u32_t eax, ebx, ecx, edx;
int proc;
eax = ebx = ecx = edx = 0;
proc = getprocessor();
/* If processor supports CPUID and its CPUID supports enough
* parameters, retrieve EDX feature flags to test against.
*/
if(proc >= 586) {
u32_t params, a, b, c, d;
_cpuid(0, &params, &b, &c, &d);
if(params > 0) {
_cpuid(1, &a, &b, &cpuid_feature_ecx,
&cpuid_feature_edx);
eax = 0;
_cpuid(&eax, &ebx, &ecx, &edx);
if(eax > 0) {
eax = 1;
_cpuid(&eax, &ebx, &ecx, &edx);
}
}
switch(cpufeature) {
case _CPUF_I386_PSE:
return cpuid_feature_edx & CPUID1_EDX_PSE;
return edx & CPUID1_EDX_PSE;
case _CPUF_I386_PGE:
return cpuid_feature_edx & CPUID1_EDX_PGE;
return edx & CPUID1_EDX_PGE;
case _CPUF_I386_APIC_ON_CHIP:
return cpuid_feature_edx & CPUID1_EDX_APIC_ON_CHIP;
return edx & CPUID1_EDX_APIC_ON_CHIP;
case _CPUF_I386_TSC:
return cpuid_feature_edx & CPUID1_EDX_TSC;
return edx & CPUID1_EDX_TSC;
case _CPUF_I386_FPU:
return cpuid_feature_edx & CPUID1_EDX_FPU;
return edx & CPUID1_EDX_FPU;
case _CPUF_I386_SSEx:
return (cpuid_feature_edx & (CPUID1_EDX_FXSR |
CPUID1_EDX_SSE |
CPUID1_EDX_SSE2)) &&
(cpuid_feature_ecx & (CPUID1_ECX_SSE3 |
CPUID1_ECX_SSSE3 |
CPUID1_ECX_SSE4_1 |
CPUID1_ECX_SSE4_2));
return (edx & (CPUID1_EDX_FXSR |
CPUID1_EDX_SSE |
CPUID1_EDX_SSE2)) &&
(ecx & (CPUID1_ECX_SSE3 |
CPUID1_ECX_SSSE3 |
CPUID1_ECX_SSE4_1 |
CPUID1_ECX_SSE4_2));
case _CPUF_I386_FXSR:
return cpuid_feature_edx & CPUID1_EDX_FXSR;
return edx & CPUID1_EDX_FXSR;
case _CPUF_I386_SSE:
return cpuid_feature_edx & CPUID1_EDX_SSE;
return edx & CPUID1_EDX_SSE;
case _CPUF_I386_SSE2:
return cpuid_feature_edx & CPUID1_EDX_SSE2;
return edx & CPUID1_EDX_SSE2;
case _CPUF_I386_SSE3:
return cpuid_feature_ecx & CPUID1_ECX_SSE3;
return ecx & CPUID1_ECX_SSE3;
case _CPUF_I386_SSSE3:
return cpuid_feature_ecx & CPUID1_ECX_SSSE3;
return ecx & CPUID1_ECX_SSSE3;
case _CPUF_I386_SSE4_1:
return cpuid_feature_ecx & CPUID1_ECX_SSE4_1;
return ecx & CPUID1_ECX_SSE4_1;
case _CPUF_I386_SSE4_2:
return cpuid_feature_ecx & CPUID1_ECX_SSE4_2;
return ecx & CPUID1_ECX_SSE4_2;
case _CPUF_I386_HTT:
return edx & CPUID1_EDX_HTT;
case _CPUF_I386_HTT_MAX_NUM:
return (ebx >> 16) & 0xff;
}
return 0;

View file

@ -3,41 +3,38 @@
.sect .text; .sect .rom; .sect .data; .sect .bss
.sect .text
! void _cpuid(u32_t eax, u32_t *eax, u32_t *ebx, u32_t *ecx, u32_t *edx);
! void _cpuid(u32_t *eax, u32_t *ebx, u32_t *ecx, u32_t *edx);
.define __cpuid
__cpuid:
! save registers
push ebp
mov ebp, esp
! save work registers
push eax
push ebx
push ecx
push edx
! set eax parameter to cpuid and execute cpuid
mov eax, 24(esp)
! set parameters to cpuid and execute cpuid
mov ebp, 12(esp)
mov eax, (ebp)
mov ebp, 16(esp)
mov ebx, (ebp)
mov ebp, 20(esp)
mov ecx, (ebp)
mov ebp, 24(esp)
mov edx, (ebp)
.data1 0x0F, 0xA2 ! CPUID
! store results in pointer arguments
mov ebp, 28(esp)
mov ebp, 12(esp)
mov (ebp), eax
mov ebp, 32(esp)
mov ebp, 16(esp)
mov (ebp), ebx
mov ebp, 36(esp)
mov ebp, 20(esp)
mov (ebp), ecx
mov ebp, 40(esp)
mov ebp, 24(esp)
mov (ebp), edx
! restore registers
pop edx
pop ecx
pop ebx
pop eax
pop ebp
ret