[haiku-commits] haiku: hrev44025 - src/system/kernel/arch/x86 headers/private/kernel/arch/x86

  • From: fredrik.holmqvist@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 14 Apr 2012 18:23:20 +0200 (CEST)

hrev44025 adds 1 changeset to branch 'master'
old head: eaa5e0936d94e7d0bb2e6066a87d485e7613414c
new head: cc586f1655b94c248be58ba1752b42bc39fbaf03

----------------------------------------------------------------------------

cc586f1: x86: AMD C1E with no ARAT(Always Running APIC Timer) idle support
  
  AMD C1E is a BIOS controlled C3 state. Certain processors families
  may cut off TSC and the lapic timer when it is in a deep C state,
  including C1E state, thus the cpu can't be waken up and system will hang.
  
  This patch firstly adds the support of idle selection during boot. Then
  it implements amdc1e_noarat_idle() routine which checks the MSR which
  contains the C1eOnCmpHalt (bit 28) and SmiOnCmpHalt (bit 27)  before
  executing the halt instruction, then clear them once set.
  
  However intel C1E doesn't has such problem. AMD C1E is a BIOS controlled
  C3 state. The difference between C1E and C3 is that transition into C1E
  is not initiated by the operating system. System will enter C1E state
  automatically when both cores enters C1 state. As for intel C1E, it
  means "reduce CPU voltage before entering corresponding Cx-state".
  
  This patch may fix #8111, #3999, #7562, #7940 and #8060
  
  Copied from the description of #3999:
  >but for some reason I hit the power button instead of the reset one. And
  >the boot continued!!
  The reason is CPUs are waken up once power button is hit.
  
  Signed-off-by: Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>

                                     [ Yongcong Du <ycdu.vmcore@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev44025
Commit:      cc586f1655b94c248be58ba1752b42bc39fbaf03
URL:         http://cgit.haiku-os.org/haiku/commit/?id=cc586f1
Author:      Yongcong Du <ycdu.vmcore@xxxxxxxxx>
Date:        Sat Apr  7 08:07:29 2012 UTC
Committer:   Fredrik Holmqvist <fredrik.holmqvist@xxxxxxxxx>
Commit-Date: Sat Apr 14 16:18:29 2012 UTC

Ticket:      https://dev.haiku-os.org/ticket/3999
Ticket:      https://dev.haiku-os.org/ticket/7562
Ticket:      https://dev.haiku-os.org/ticket/7940
Ticket:      https://dev.haiku-os.org/ticket/8060
Ticket:      https://dev.haiku-os.org/ticket/8111

----------------------------------------------------------------------------

2 files changed, 52 insertions(+), 1 deletions(-)
headers/private/kernel/arch/x86/arch_cpu.h |    3 +
src/system/kernel/arch/x86/arch_cpu.cpp    |   50 +++++++++++++++++++++++-

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/arch/x86/arch_cpu.h 
b/headers/private/kernel/arch/x86/arch_cpu.h
index 67ebe5e..ff5523b 100644
--- a/headers/private/kernel/arch/x86/arch_cpu.h
+++ b/headers/private/kernel/arch/x86/arch_cpu.h
@@ -33,6 +33,9 @@
 #define IA32_MSR_MTRR_PHYSICAL_BASE_0  0x200
 #define IA32_MSR_MTRR_PHYSICAL_MASK_0  0x201
 
+// K8 MSR registers
+#define K8_MSR_IPM                                             0xc0010055
+
 // x86 features from cpuid eax 1, edx register
 // reference http://www.intel.com/assets/pdf/appnote/241618.pdf (Table 5-5)
 #define IA32_FEATURE_FPU       (1 << 0) // x87 fpu
diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp 
b/src/system/kernel/arch/x86/arch_cpu.cpp
index c199afc..81daaf8 100644
--- a/src/system/kernel/arch/x86/arch_cpu.cpp
+++ b/src/system/kernel/arch/x86/arch_cpu.cpp
@@ -64,6 +64,11 @@ static const struct cpu_vendor_info vendor_info[VENDOR_NUM] 
= {
 #define CR4_OS_FXSR                            (1UL << 9)
 #define CR4_OS_XMM_EXCEPTION   (1UL << 10)
 
+#define K8_SMIONCMPHALT                        (1ULL << 27)
+#define K8_C1EONCMPHALT                        (1ULL << 28)
+
+#define K8_CMPHALT                             (K8_SMIONCMPHALT | 
K8_C1EONCMPHALT)
+
 struct set_mtrr_parameter {
        int32   index;
        uint64  base;
@@ -82,6 +87,7 @@ extern "C" void reboot(void);
        // from arch_x86.S
 
 void (*gX86SwapFPUFunc)(void *oldState, const void *newState);
+void (*gCpuIdleFunc)(void);
 bool gHasSSE = false;
 
 static uint32 sCpuRendezvous;
@@ -699,6 +705,40 @@ arch_cpu_preboot_init_percpu(kernel_args *args, int cpu)
 }
 
 
+static void
+halt_idle(void)
+{
+       asm("hlt");
+}
+
+
+static void
+amdc1e_noarat_idle(void)
+{
+       uint64 msr = x86_read_msr(K8_MSR_IPM);
+       if (msr & K8_CMPHALT)
+               x86_write_msr(K8_MSR_IPM, msr & ~K8_CMPHALT);
+       halt_idle();
+}
+
+
+static bool
+detect_amdc1e_noarat()
+{
+       cpu_ent *cpu = get_cpu_struct();
+
+       if (cpu->arch.vendor != VENDOR_AMD)
+               return false;
+
+       // Family 0x12 and higher processors support ARAT
+       // Family lower than 0xf processors doesn't support C1E
+       // Family 0xf with model <= 0x40 procssors doesn't support C1E
+       uint32 family = cpu->arch.family + cpu->arch.extended_family;
+       uint32 model = (cpu->arch.extended_model << 4) | cpu->arch.model;
+       return (family < 0x12 && family > 0xf) || (family == 0xf && model > 
0x40);
+}
+
+
 status_t
 arch_cpu_init_percpu(kernel_args *args, int cpu)
 {
@@ -721,9 +761,16 @@ arch_cpu_init_percpu(kernel_args *args, int cpu)
                asm volatile("lidt      %0" : : "m"(descriptor));
        }
 
+       if (!gCpuIdleFunc) {
+               if (detect_amdc1e_noarat())
+                       gCpuIdleFunc = amdc1e_noarat_idle;
+               else
+                       gCpuIdleFunc = halt_idle;
+       }
        return 0;
 }
 
+
 status_t
 arch_cpu_init(kernel_args *args)
 {
@@ -882,6 +929,7 @@ i386_set_tss_and_kstack(addr_t kstack)
        get_cpu_struct()->arch.tss.sp0 = kstack;
 }
 
+
 void
 arch_cpu_global_TLB_invalidate(void)
 {
@@ -1008,7 +1056,7 @@ arch_cpu_shutdown(bool rebootSystem)
 void
 arch_cpu_idle(void)
 {
-       asm("hlt");
+       gCpuIdleFunc();
 }
 
 


Other related posts:

  • » [haiku-commits] haiku: hrev44025 - src/system/kernel/arch/x86 headers/private/kernel/arch/x86 - fredrik . holmqvist