Subversion Repositories HelenOS

Rev

Rev 3022 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2001-2004 Jakub Jermar
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup ia32
  30.  * @{
  31.  */
  32. /** @file
  33.  */
  34.  
  35. #include <arch/cpu.h>
  36. #include <arch/cpuid.h>
  37. #include <arch/pm.h>
  38.  
  39. #include <arch.h>
  40. #include <arch/types.h>
  41. #include <print.h>
  42. #include <fpu_context.h>
  43.  
  44. #include <arch/smp/apic.h>
  45. #include <arch/syscall.h>
  46.  
  47. /*
  48.  * Identification of CPUs.
  49.  * Contains only non-MP-Specification specific SMP code.
  50.  */
  51. #define AMD_CPUID_EBX  0x68747541
  52. #define AMD_CPUID_ECX  0x444d4163
  53. #define AMD_CPUID_EDX  0x69746e65
  54.  
  55. #define INTEL_CPUID_EBX  0x756e6547
  56. #define INTEL_CPUID_ECX  0x6c65746e
  57. #define INTEL_CPUID_EDX  0x49656e69
  58.  
  59.  
  60. enum vendor {
  61.     VendorUnknown = 0,
  62.     VendorAMD,
  63.     VendorIntel
  64. };
  65.  
  66. static char *vendor_str[] = {
  67.     "Unknown Vendor",
  68.     "AMD",
  69.     "Intel"
  70. };
  71.  
  72. void fpu_disable(void)
  73. {
  74.     asm volatile (
  75.         "mov %%cr0, %%eax\n"
  76.         "or $8, %%eax\n"
  77.         "mov %%eax, %%cr0\n"
  78.         ::: "%eax"
  79.     );
  80. }
  81.  
  82. void fpu_enable(void)
  83. {
  84.     asm volatile (
  85.         "mov %%cr0, %%eax\n"
  86.         "and $0xffFFffF7, %%eax\n"
  87.         "mov %%eax,%%cr0\n"
  88.         ::: "%eax"
  89.     );
  90. }
  91.  
  92. void cpu_arch_init(void)
  93. {
  94.     cpuid_feature_info fi;
  95.     cpuid_extended_feature_info efi;
  96.     cpu_info_t info;
  97.     uint32_t help = 0;
  98.    
  99.     CPU->arch.tss = tss_p;
  100.     CPU->arch.tss->iomap_base = &CPU->arch.tss->iomap[0] - ((uint8_t *) CPU->arch.tss);
  101.    
  102.     CPU->fpu_owner = NULL;
  103.    
  104.     cpuid(1, &info);
  105.    
  106.     fi.word = info.cpuid_edx;
  107.     efi.word = info.cpuid_ecx;
  108.    
  109.     if (fi.bits.fxsr)
  110.         fpu_fxsr();
  111.     else
  112.         fpu_fsr();
  113.    
  114.     if (fi.bits.sse) {
  115.         asm volatile (
  116.             "mov %%cr4, %[help]\n"
  117.             "or %[mask], %[help]\n"
  118.             "mov %[help], %%cr4\n"
  119.             : [help] "+r" (help)
  120.             : [mask] "i" (CR4_OSFXSR_MASK | (1 << 10))
  121.         );
  122.     }
  123.    
  124.     /* Setup fast SYSENTER/SYSEXIT syscalls */
  125.     syscall_setup_cpu();
  126. }
  127.  
  128. void cpu_identify(void)
  129. {
  130.     cpu_info_t info;
  131.  
  132.     CPU->arch.vendor = VendorUnknown;
  133.     if (has_cpuid()) {
  134.         cpuid(0, &info);
  135.  
  136.         /*
  137.          * Check for AMD processor.
  138.          */
  139.         if ((info.cpuid_ebx == AMD_CPUID_EBX)
  140.             && (info.cpuid_ecx == AMD_CPUID_ECX)
  141.             && (info.cpuid_edx == AMD_CPUID_EDX))
  142.             CPU->arch.vendor = VendorAMD;
  143.        
  144.         /*
  145.          * Check for Intel processor.
  146.          */    
  147.         if ((info.cpuid_ebx == INTEL_CPUID_EBX)
  148.             && (info.cpuid_ecx == INTEL_CPUID_ECX)
  149.             && (info.cpuid_edx == INTEL_CPUID_EDX))
  150.             CPU->arch.vendor = VendorIntel;
  151.        
  152.         cpuid(1, &info);
  153.         CPU->arch.family = (info.cpuid_eax >> 8) & 0x0f;
  154.         CPU->arch.model = (info.cpuid_eax >> 4) & 0x0f;
  155.         CPU->arch.stepping = (info.cpuid_eax >> 0) & 0x0f;                     
  156.     }
  157. }
  158.  
  159. void cpu_print_report(cpu_t* cpu)
  160. {
  161.     printf("cpu%u: (%s family=%u model=%u stepping=%u) %" PRIu16 " MHz\n",
  162.         cpu->id, vendor_str[cpu->arch.vendor], cpu->arch.family,
  163.         cpu->arch.model, cpu->arch.stepping, cpu->frequency_mhz);
  164. }
  165.  
  166. /** @}
  167.  */
  168.