Fork me on GitHub

root/kernel/cpu.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. detect_cpuspeed
  2. show_cache
  3. check_cache
  4. get_cpu_flags
  5. cpu_init

   1 /*
   2  * fiwix/kernel/cpu.c
   3  *
   4  * Copyright 2018-2022, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/asm.h>
   9 #include <fiwix/kernel.h>
  10 #include <fiwix/utsname.h>
  11 #include <fiwix/pic.h>
  12 #include <fiwix/pit.h>
  13 #include <fiwix/cpu.h>
  14 #include <fiwix/timer.h>
  15 #include <fiwix/stdio.h>
  16 #include <fiwix/string.h>
  17 
  18 char UTS_MACHINE[_UTSNAME_LENGTH + 1];
  19 
  20 static struct cpu_type intel[] = {
  21         { 4,
  22            { "i486 DX", "i486 DX", "i486 SX", "i486 DX/2",
  23              "i486 SL", "i486 SX/2", NULL, "i486 DX/2 WBE",
  24              "i486 DX/4", NULL, NULL, NULL, NULL, NULL, NULL, NULL }
  25         },
  26         { 5,
  27            { NULL, "Pentium 60/66", "Pentium 75-200", "Pentium ODfor486",
  28              "PentiumMMX", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  29              NULL, NULL, NULL }
  30         },
  31         { 6,
  32            { NULL, "Pentium Pro", NULL, "Pentium II", NULL, "Pentium II",
  33              "Intel Celeron", "Pentium III", "Pentium III", NULL,
  34              "Pentium III Xeon", "Pentium III", NULL, NULL, NULL, NULL }
  35         }
  36 };
  37 
  38 static const char *cpu_flags[] = {
  39         "FPU", "VME", "DE", "PSE", "TSC", "MSR", "PAE", "MCE", "CX8", "APIC",
  40         "10", "SEP", "MTRR", "PGE", "MCA", "CMOV", "PAT", "PSE-36", "PSN",
  41         "CLFSH", "20", "DS", "ACPI", "MMX", "FXSR", "SSE", "SSE2", "SS",
  42         "HTT", "TM", "30", "PBE"
  43 };
  44 
  45 static unsigned long int detect_cpuspeed(void)
  46 {
  47         unsigned long long int tsc1, tsc2;
  48 
  49         outport_b(MODEREG, SEL_CHAN2 | LSB_MSB | TERM_COUNT | BINARY_CTR);
  50         outport_b(CHANNEL2, (OSCIL / HZ) & 0xFF);
  51         outport_b(CHANNEL2, (OSCIL / HZ) >> 8);
  52         outport_b(PS2_SYSCTRL_B, inport_b(PS2_SYSCTRL_B) | ENABLE_SDATA | ENABLE_TMR2G);
  53 
  54         tsc1 = 0;
  55         tsc1 = get_rdtsc();
  56 
  57         while(!(inport_b(PS2_SYSCTRL_B) & 0x20));
  58 
  59         tsc2 = 0;
  60         tsc2 = get_rdtsc();
  61 
  62         outport_b(PS2_SYSCTRL_B, inport_b(PS2_SYSCTRL_B) & ~(ENABLE_SDATA | ENABLE_TMR2G));
  63 
  64         return (tsc2 - tsc1) * HZ;
  65 }
  66 
  67 /*
  68  * These are the 2nd and 3rd level cache values according to Intel Processor
  69  * Identification and the CPUID Instruction.
  70  * Application Note 485. Document Number: 241618-031. September 2006.
  71  */
  72 static void show_cache(int value)
  73 {
  74         switch(value) {
  75                 /* 2nd level cache */
  76                 case 0x39:
  77                 case 0x3B:
  78                 case 0x41:
  79                 case 0x79:
  80                         cpu_table.cache = "128KB L2";
  81                         break;
  82                 case 0x3A:
  83                         cpu_table.cache = "192KB L2";
  84                         break;
  85                 case 0x3C:
  86                 case 0x42:
  87                 case 0x7A:
  88                 case 0x82:
  89                         cpu_table.cache = "256KB L2";
  90                         break;
  91                 case 0x3D:
  92                         cpu_table.cache = "384KB L2";
  93                         break;
  94                 case 0x3E:
  95                 case 0x43:
  96                 case 0x7B:
  97                 case 0x7F:
  98                 case 0x83:
  99                 case 0x86:
 100                         cpu_table.cache = "512KB L2";
 101                         break;
 102                 case 0x44:
 103                 case 0x78:
 104                 case 0x7C:
 105                 case 0x84:
 106                 case 0x87:
 107                         cpu_table.cache = "1MB L2";
 108                         break;
 109                 case 0x45:
 110                 case 0x7D:
 111                 case 0x85:
 112                         cpu_table.cache = "2MB L2";
 113                         break;
 114 
 115                 /* 3rd level cache */
 116                 case 0x22:
 117                         cpu_table.cache = "512KB L3";
 118                         break;
 119                 case 0x23:
 120                         cpu_table.cache = "1MB L3";
 121                         break;
 122                 case 0x25:
 123                         cpu_table.cache = "2MB L3";
 124                         break;
 125                 case 0x29:
 126                 case 0x46:
 127                         cpu_table.cache = "4MB L3";
 128                         break;
 129                 case 0x49:
 130                         cpu_table.cache = "4MB L3 & L2";
 131                         break;
 132                 case 0x4A:
 133                         cpu_table.cache = "6MB L3";
 134                         break;
 135                 case 0x47:
 136                 case 0x4B:
 137                         cpu_table.cache = "8MB L3";
 138                         break;
 139                 case 0x4C:
 140                         cpu_table.cache = "12MB L3";
 141                         break;
 142                 case 0x4D:
 143                         cpu_table.cache = "16MB L3";
 144                         break;
 145                 default:
 146                         break;
 147         }
 148 }
 149 
 150 static void check_cache(int maxcpuid)
 151 {
 152         int n, maxcpuids;
 153 
 154         maxcpuids = 1;
 155         if(maxcpuid >= 2) {
 156                 for(n = 0; n < maxcpuids; n++) {
 157                         tlbinfo();
 158                         maxcpuids = _tlbinfo_eax & 0xFF;
 159                         show_cache((_tlbinfo_eax >> 8) & 0xFF);
 160                         show_cache((_tlbinfo_eax >> 16) & 0xFF);
 161                         show_cache((_tlbinfo_eax >> 24) & 0xFF);
 162                         if(!(_tlbinfo_ebx & RESERVED_DESC)) {
 163                                 show_cache(_tlbinfo_ebx & 0xFF);
 164                                 show_cache((_tlbinfo_ebx >> 8) & 0xFF);
 165                                 show_cache((_tlbinfo_ebx >> 16) & 0xFF);
 166                                 show_cache((_tlbinfo_ebx >> 24) & 0xFF);
 167                         }
 168                         if(!(_tlbinfo_ecx & RESERVED_DESC)) {
 169                                 show_cache(_tlbinfo_ecx & 0xFF);
 170                                 show_cache((_tlbinfo_ecx >> 8) & 0xFF);
 171                                 show_cache((_tlbinfo_ecx >> 16) & 0xFF);
 172                                 show_cache((_tlbinfo_ecx >> 24) & 0xFF);
 173                         }
 174                         if(!(_tlbinfo_edx & RESERVED_DESC)) {
 175                                 show_cache(_tlbinfo_edx & 0xFF);
 176                                 show_cache((_tlbinfo_edx >> 8) & 0xFF);
 177                                 show_cache((_tlbinfo_edx >> 16) & 0xFF);
 178                                 show_cache((_tlbinfo_edx >> 24) & 0xFF);
 179                         }
 180                 }
 181         }
 182 }
 183 
 184 int get_cpu_flags(char *buffer, int offset)
 185 {
 186         int n, size;
 187         unsigned int mask;
 188 
 189         size = sprintk(buffer + offset, "flags           :");
 190         for(n = 0, mask = 1; n < 32; n++, mask <<= 1) {
 191                 if(_cpuflags & mask) {
 192                         size += sprintk(buffer + offset + size, " %s", cpu_flags[n]);
 193                 }
 194         }
 195         size += sprintk(buffer + offset + size, "\n");
 196         return size;
 197 }
 198 
 199 void cpu_init(void)
 200 {
 201         unsigned int n;
 202         int maxcpuid;
 203 
 204         memset_b(&cpu_table, 0, sizeof(cpu_table));
 205         cpu_table.model = -1;
 206         cpu_table.stepping = -1;
 207 
 208         printk("cpu       -                 -\t");
 209         cpu_table.family = cpuid();
 210         if(!cpu_table.family) {
 211                 cpu_table.has_cpuid = 1;
 212                 maxcpuid = get_cpu_vendor_id();
 213                 cpu_table.vendor_id = _vendorid;
 214                 if(maxcpuid >= 1) {
 215                         signature_flags();
 216                         cpu_table.family = _cputype;
 217                         cpu_table.flags = _cpuflags;
 218                         if(!strcmp((char *)_vendorid, "GenuineIntel")) {
 219                                 printk("Intel ");
 220                                 for(n = 0; n < sizeof(intel) / sizeof(struct cpu_type); n++) {
 221                                         if(intel[n].cpu == _cputype) {
 222                                                 cpu_table.model_name = !intel[n].name[(((int)_cpusignature >> 4) & 0xF)] ? NULL : intel[n].name[(((int)_cpusignature >> 4) & 0xF)];
 223                                                 break;
 224                                         }
 225                                 }
 226                                 if(cpu_table.model_name) {
 227                                         printk("%s", cpu_table.model_name);
 228                                 } else {
 229                                         printk("processor");
 230                                 }
 231                         } else if(!strcmp((char *)_vendorid, "AuthenticAMD")) {
 232                                         printk("AMD processor");
 233                         } else {
 234                                 printk("x86");
 235                         }
 236                         if(_cpuflags & CPU_TSC) {
 237                                 cpu_table.hz = detect_cpuspeed();
 238                                 printk(" at %d.%d Mhz", (cpu_table.hz / 1000000), ((cpu_table.hz % 1000000) / 100000));
 239                                 check_cache(maxcpuid);
 240                                 if(cpu_table.cache) {
 241                                         printk(" (%s)", cpu_table.cache);
 242                                 }
 243                         }
 244                         printk("\n");
 245                         printk("\t\t\t\tvendorid=%s ", _vendorid);
 246                         cpu_table.model = (_cpusignature >> 4) & 0xF;
 247                         cpu_table.stepping = _cpusignature & 0xF;
 248                         printk("model=%d stepping=%d\n", cpu_table.model, cpu_table.stepping);
 249                 }
 250                 if(!brand_str()) {
 251                         cpu_table.model_name = _brandstr;
 252                         if(cpu_table.model_name[0]) {
 253                                 printk("\t\t\t\t%s\n", cpu_table.model_name);
 254                         }
 255                 }
 256         } else {
 257                 printk("80%d86\n", cpu_table.family);
 258                 cpu_table.has_cpuid = 0;
 259         }
 260         strcpy(UTS_MACHINE, "i386");
 261         strncpy(sys_utsname.machine, UTS_MACHINE, _UTSNAME_LENGTH);
 262         cpu_table.has_fpu = getfpu();
 263 }

/* [previous][next][first][last][top][bottom][index][help] */