forked from StevenBaby/onix
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
23235f1
commit e637407
Showing
7 changed files
with
226 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# CPU 功能检测 | ||
|
||
## CPUID | ||
|
||
`CPUID` [^osdev] 指令可以用于获取很多 CPU 的信息,比如供应商(Vendor) 字符串,和模型数,内部缓存大小,以及很多其他有趣的东西。 | ||
|
||
EFLAGS 位图: | ||
|
||
![](../04%20中断和时钟/images/eflags.drawio.svg) | ||
|
||
## 功能检测 | ||
|
||
在执行 `CPUID` 指令之前,首先应该检测处理器是否支持该指令,如果 EFLAGS 的 ID 位可修改,那么表示处理器支持 `CPUID` 指令。 | ||
|
||
## 基础用法 | ||
|
||
执行 `CPUID` 指令前,将参数 `0` 传入 `EAX`,不同的参数将返回不同的信息。 | ||
|
||
### 供应商 ID | ||
|
||
当 `EAX=0` 时,CPUID 将返回供应商 ID 字符串到 `EBX`, `EDX` 和 `ECX`,将它们写入内存将得到长度 12 的字符串。这个字符串表示了供应商的 ID。下面是典型的供应商 ID: | ||
|
||
```c++ | ||
#define CPUID_VENDOR_AMD "AuthenticAMD" | ||
#define CPUID_VENDOR_INTEL "GenuineIntel" | ||
``` | ||
`EAX` 中返回最大的输入数; | ||
### CPU 功能 | ||
使用参数 `EAX` = 1 调用 CPUID,返回一个位图存储在 `EDX` 和 `ECX` 中 [^info]。注意不同品牌的 CPU 可能有不同的含义。 | ||
## 参考 | ||
[^osdev]: https://wiki.osdev.org/CPUID | ||
[^info]: Intel® 64 and IA-32 Architectures Software Developer's Manual |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
#ifndef ONIX_CPU_H | ||
#define ONIX_CPU_H | ||
|
||
#include <onix/types.h> | ||
|
||
// Vendor strings from CPUs. | ||
#define CPUID_VENDOR_AMD "AuthenticAMD" | ||
#define CPUID_VENDOR_INTEL "GenuineIntel" | ||
|
||
bool cpu_check_cpuid(); | ||
|
||
typedef struct cpu_vendor_t | ||
{ | ||
u32 max_value; | ||
char info[13]; | ||
} _packed cpu_vendor_t; | ||
|
||
void cpu_vendor_id(cpu_vendor_t *item); | ||
|
||
typedef struct cpu_version_t | ||
{ | ||
u8 stepping : 4; | ||
u8 model : 4; | ||
u8 family : 4; | ||
u8 type : 2; | ||
u8 RESERVED : 2; | ||
u8 emodel : 4; | ||
u8 efamily0 : 4; | ||
u8 efamily1 : 4; | ||
u8 RESERVED : 4; | ||
|
||
u8 brand_index; | ||
u8 clflush; | ||
u8 max_num; | ||
u8 apic_id; | ||
|
||
// ECX; | ||
u8 SSE3 : 1; // 0 | ||
u8 PCLMULQDQ : 1; // 1 | ||
u8 DTES64 : 1; // 2 | ||
u8 MONITOR : 1; // 3 | ||
u8 DS_CPL : 1; // 4 | ||
u8 VMX : 1; // 5 | ||
u8 SMX : 1; // 6 | ||
u8 EIST : 1; // 7 | ||
u8 TM2 : 1; // 8 | ||
u8 SSSE3 : 1; // 9 | ||
u8 CNXT_ID : 1; // 10 | ||
u8 SDBG : 1; // 11 | ||
u8 FMA : 1; // 12 | ||
u8 CMPXCHG16B : 1; // 13 | ||
u8 xTPR : 1; // 14 | ||
u8 PDCM : 1; // 15 | ||
u8 RESERVED : 1; // 16 | ||
u8 PCID : 1; // 17 | ||
u8 DCA : 1; // 18 | ||
u8 SSE4_1 : 1; // 19 | ||
u8 SSE4_2 : 1; // 20 | ||
u8 x2APIC : 1; // 21 | ||
u8 MOVBE : 1; // 22 | ||
u8 POPCNT : 1; // 23 | ||
u8 TSCD : 1; // 24 | ||
u8 AESNI : 1; // 25 | ||
u8 XSAVE : 1; // 26 | ||
u8 OSXSAVE : 1; // 27 | ||
u8 AVX : 1; // 28 | ||
u8 F16C : 1; // 29 | ||
u8 RDRAND : 1; // 30 | ||
u8 RESERVED : 1; // 31 | ||
|
||
// EDX | ||
u8 FPU : 1; // 0 x87 FPU on Chip | ||
u8 VME : 1; // 1 Virtual-8086 Mode Enhancement | ||
u8 DE : 1; // 2 Debugging Extensions | ||
u8 PSE : 1; // 3 Page Size Extensions | ||
u8 TSC : 1; // 4 Time Stamp Counter | ||
u8 MSR : 1; // 5 RDMSR and WRMSR Support | ||
u8 PAE : 1; // 6 Physical Address Extensions | ||
u8 MCE : 1; // 7 Machine Check Exception | ||
u8 CX8 : 1; // 8 CMPXCHG8B Inst. | ||
u8 APIC : 1; // 9 APIC on Chip | ||
u8 RESERVED : 1; // 10 | ||
u8 SEP : 1; // 11 SYSENTER and SYSEXIT | ||
u8 MTRR : 1; // 12 Memory Type Range Registers | ||
u8 PGE : 1; // 13 PTE Global Bit | ||
u8 MCA : 1; // 14 Machine Check Architecture | ||
u8 CMOV : 1; // 15 Conditional Move/Compare Instruction | ||
u8 PAT : 1; // 16 Page Attribute Table | ||
u8 PSE36 : 1; // 17 Page Size Extension | ||
u8 PSN : 1; // 18 Processor Serial Number | ||
u8 CLFSH : 1; // 19 CLFLUSH instruction | ||
u8 RESERVED : 1; // 20 | ||
u8 DS : 1; // 21 Debug Store | ||
u8 ACPI : 1; // 22 Thermal Monitor and Clock Ctrl | ||
u8 MMX : 1; // 23 MMX Technology | ||
u8 FXSR : 1; // 24 FXSAVE/FXRSTOR | ||
u8 SSE : 1; // 25 SSE Extensions | ||
u8 SSE2 : 1; // 26 SSE2 Extensions | ||
u8 SS : 1; // 27 Self Snoop | ||
u8 HTT : 1; // 28 Multi-threading | ||
u8 TM : 1; // 29 Therm. Monitor | ||
u8 RESERVED : 1; // 30 | ||
u8 PBE : 1; // 31 Pend. Brk. EN. | ||
} _packed cpu_version_t; | ||
|
||
void cpu_version(cpu_version_t *ver); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#include <onix/cpu.h> | ||
|
||
// 检测是否支持 cpuid 指令 | ||
bool cpu_check_cpuid() | ||
{ | ||
bool ret; | ||
asm volatile( | ||
"pushfl \n" // 保存 eflags | ||
|
||
"pushfl \n" // 得到 eflags | ||
"xorl $0x00200000, (%%esp)\n" // 反转 ID 位 | ||
"popfl\n" // 写入 eflags | ||
|
||
"pushfl\n" // 得到 eflags | ||
"popl %%eax\n" // 写入 eax | ||
"xorl (%%esp), %%eax\n" // 将写入的值与原值比较 | ||
"andl $0x00200000, %%eax\n" // 得到 ID 位 | ||
"shrl $21, %%eax\n" // 右移 21 位,得到是否支持 | ||
|
||
"popfl\n" // 恢复 eflags | ||
: "=a"(ret)); | ||
return ret; | ||
} | ||
|
||
// 得到供应商 ID 字符串 | ||
void cpu_vendor_id(cpu_vendor_t *item) | ||
{ | ||
asm volatile( | ||
"cpuid \n" | ||
: "=a"(*((u32 *)item + 0)), | ||
"=b"(*((u32 *)item + 1)), | ||
"=d"(*((u32 *)item + 2)), | ||
"=c"(*((u32 *)item + 3)) | ||
: "a"(0)); | ||
item->info[12] = 0; | ||
} | ||
|
||
void cpu_version(cpu_version_t *item) | ||
{ | ||
asm volatile( | ||
"cpuid \n" | ||
: "=a"(*((u32 *)item + 0)), | ||
"=b"(*((u32 *)item + 1)), | ||
"=c"(*((u32 *)item + 2)), | ||
"=d"(*((u32 *)item + 3)) | ||
: "a"(1)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#include <onix/types.h> | ||
#include <onix/cpu.h> | ||
#include <onix/printk.h> | ||
#include <onix/debug.h> | ||
#include <onix/errno.h> | ||
|
||
#define LOGK(fmt, args...) DEBUGK(fmt, ##args) | ||
|
||
err_t sys_test() | ||
{ | ||
LOGK("test syscall...\n"); | ||
|
||
cpu_vendor_t vendor; | ||
|
||
cpu_vendor_id(&vendor); | ||
printk("CPU vendor id: %s\n", vendor.info); | ||
printk("CPU max value: 0x%X\n", vendor.max_value); | ||
|
||
cpu_version_t ver; | ||
|
||
cpu_version(&ver); | ||
printk("FPU support state: %d\n", ver.FPU); | ||
printk("APIC support state: %d\n", ver.APIC); | ||
return EOK; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters