From 6514e2d8fd67c6b15f1306f76fd4286a6a4b1e06 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 4 Mar 2016 23:57:15 +0100 Subject: [PATCH] use HALT state to shutdown the system, otherwise PAUSE, check EST & P-states --- hermit/arch/x86/include/asm/processor.h | 31 ++++++++ hermit/arch/x86/kernel/apic.c | 6 +- hermit/arch/x86/kernel/processor.c | 96 ++++++++++++++++++++++++- hermit/arch/x86/kernel/tasks.c | 4 +- hermit/arch/x86/kernel/timer.c | 2 +- hermit/kernel/main.c | 6 +- hermit/kernel/syscall.c | 2 + 7 files changed, 137 insertions(+), 10 deletions(-) diff --git a/hermit/arch/x86/include/asm/processor.h b/hermit/arch/x86/include/asm/processor.h index 2e38d43ab..ef9f45665 100644 --- a/hermit/arch/x86/include/asm/processor.h +++ b/hermit/arch/x86/include/asm/processor.h @@ -64,6 +64,7 @@ extern "C" { // feature list 0x00000001 (ecx) #define CPU_FEATURE_MWAIT (1 << 3) #define CPU_FEATURE_VMX (1 << 5) +#define CPU_FEATURE_EST (1 << 7) #define CPU_FEATURE_SSE3 (1 << 9) #define CPU_FEATURE_FMA (1 << 12) #define CPU_FEATURE_DCA (1 << 18) @@ -87,6 +88,9 @@ extern "C" { #define CPU_FEATURE_FSGSBASE (1 << 0) #define CPU_FEATURE_AVX2 (1 << 5) +// feature list 0x00000006 +#define CPU_FEATURE_IDA (1 << 0) +#define CPU_FEATURE_HWP (1 << 10) /* * EFLAGS bits @@ -197,13 +201,31 @@ extern "C" { #define MSR_XAPIC_ENABLE (1UL << 11) #define MSR_X2APIC_ENABLE (1UL << 10) +#define MSR_PLATFORM_INFO 0x000000ce + +#define MSR_IA32_MPERF 0x000000e7 +#define MSR_IA32_APERF 0x000000e8 #define MSR_IA32_MISC_ENABLE 0x000001a0 #define MSR_IA32_FEATURE_CONTROL 0x0000003a #define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0 #define MSR_IA32_PERF_STATUS 0x00000198 +#define MSR_IA32_PERF_CTL 0x00000199 #define MSR_IA32_CR_PAT 0x00000277 #define MSR_MTRRdefType 0x000002ff +#define MSR_PPERF 0x0000064e +#define MSR_PERF_LIMIT_REASONS 0x0000064f +#define MSR_PM_ENABLE 0x00000770 +#define MSR_HWP_CAPABILITIES 0x00000771 +#define MSR_HWP_REQUEST_PKG 0x00000772 +#define MSR_HWP_INTERRUPT 0x00000773 +#define MSR_HWP_REQUEST 0x00000774 +#define MSR_HWP_STATUS 0x00000777 + +#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP (1ULL << 16) +#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK (1ULL << 20) +#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE (1ULL << 38) + #define MSR_MTRRfix64K_00000 0x00000250 #define MSR_MTRRfix16K_80000 0x00000258 #define MSR_MTRRfix16K_A0000 0x00000259 @@ -290,6 +312,11 @@ inline static uint32_t has_vmx(void) { return (cpu_info.feature2 & CPU_FEATURE_VMX); } +inline static uint32_t has_est(void) +{ + return (cpu_info.feature2 & CPU_FEATURE_EST); +} + inline static uint32_t has_sse3(void) { return (cpu_info.feature2 & CPU_FEATURE_SSE3); } @@ -679,6 +706,10 @@ static inline size_t lsb(size_t i) return ret; } +/** @brief: print current pstate + */ +void dump_pstate(void); + /// A one-instruction-do-nothing #define NOP asm volatile ("nop") /// The PAUSE instruction provides a hint to the processor that the code sequence is a spin-wait loop. diff --git a/hermit/arch/x86/kernel/apic.c b/hermit/arch/x86/kernel/apic.c index df40eadf3..4826db8ed 100644 --- a/hermit/arch/x86/kernel/apic.c +++ b/hermit/arch/x86/kernel/apic.c @@ -421,7 +421,7 @@ int apic_calibration(void) /* wait for the next time slice */ while ((ticks = get_clock_tick()) - old == 0) - HALT; + PAUSE; flags = irq_nested_disable(); lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments @@ -431,7 +431,7 @@ int apic_calibration(void) /* wait 3 time slices to determine a ICR */ while (get_clock_tick() - ticks < 3) - HALT; + PAUSE; icr = (0xFFFFFFFFUL - lapic_read(APIC_CCR)) / 3; @@ -802,6 +802,8 @@ void shutdown_system(void) if (if_bootprocessor) { kprintf("Try to shutdown HermitCore\n"); + dump_pstate(); + while(atomic_int32_read(&cpu_online) != 1) PAUSE; diff --git a/hermit/arch/x86/kernel/processor.c b/hermit/arch/x86/kernel/processor.c index 6e95b422b..32bfeff3a 100644 --- a/hermit/arch/x86/kernel/processor.c +++ b/hermit/arch/x86/kernel/processor.c @@ -190,13 +190,13 @@ uint32_t detect_cpu_frequency(void) /* wait for the next time slice */ while((ticks = get_clock_tick()) - old == 0) - HALT; + PAUSE; rmb(); start = rdtsc(); /* wait a second to determine the frequency */ while(get_clock_tick() - ticks < TIMER_FREQ) - HALT; + PAUSE; rmb(); end = rdtsc(); @@ -206,6 +206,93 @@ uint32_t detect_cpu_frequency(void) return cpu_freq; } +static int get_min_pstate(void) +{ + uint64_t value; + + value = rdmsr(MSR_PLATFORM_INFO); + + return (value >> 40) & 0xFF; +} + +static int get_max_pstate(void) +{ + uint64_t value; + + value = rdmsr(MSR_PLATFORM_INFO); + + return (value >> 8) & 0xFF; +} + +static uint8_t is_turbo = 0; +static int max_pstate, min_pstate; + +static void set_max_pstate(void) +{ + uint64_t v = max_pstate << 8; + if (is_turbo) + v |= (1ULL << 32); + wrmsr(MSR_IA32_PERF_CTL, v); +} + +void dump_pstate(void) +{ + kprintf("P-State 0x%x - 0x%x\n", min_pstate, max_pstate); + kprintf("PERF CTL 0x%llx\n", rdmsr(MSR_IA32_PERF_CTL)); + kprintf("PERF STATUS 0x%llx\n", rdmsr(MSR_IA32_PERF_STATUS)); +} + +static void check_est(uint8_t out) +{ + uint32_t a=0, b=0, c=0, d=0; + uint64_t v; + + if (!has_est()) + return; + + if (out) + kputs("System supports Enhanced SpeedStep Technology\n"); + + // enable Enhanced SpeedStep Technology + v = rdmsr(MSR_IA32_MISC_ENABLE); + if (!(v & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) { + if (out) + kputs("Linux doesn't enable Enhanced SpeedStep Technology\n"); + return; + } + + if (v & MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK) { + if (out) + kputs("Enhanced SpeedStep Technology is locked\n"); + return; + } + + if (v & MSR_IA32_MISC_ENABLE_TURBO_DISABLE) { + if (out) + kputs("Turbo Mode is disabled\n"); + } else is_turbo=1; + + cpuid(6, &a, &b, &c, &d); + if (c & CPU_FEATURE_IDA) { + if (out) + kprintf("Found P-State hardware coordination feedback capability bit\n"); + } + + if (c & CPU_FEATURE_HWP) { + if (out) + kprintf("P-State HWP enabled\n"); + } + + max_pstate = get_max_pstate(); + min_pstate = get_min_pstate(); + set_max_pstate(); + + if (out) + dump_pstate(); + + return; +} + int cpu_detection(void) { uint64_t xcr0; uint32_t a=0, b=0, c=0, d=0, level = 0; @@ -403,6 +490,9 @@ int cpu_detection(void) { fpu_init = fpu_init_fxsr; } + // initialize Enhanced SpeedStep Technology + check_est(first_time); + if (first_time && on_hypervisor()) { uint32_t c, d; char vendor_id[13]; @@ -426,7 +516,7 @@ int cpu_detection(void) { uint64_t msr; kprintf("IA32_MISC_ENABLE 0x%llx\n", rdmsr(MSR_IA32_MISC_ENABLE)); - kprintf("IA32_FEATURE_CONTROL 0x%llx\n", rdmsr(MSR_IA32_FEATURE_CONTROL)); + //kprintf("IA32_FEATURE_CONTROL 0x%llx\n", rdmsr(MSR_IA32_FEATURE_CONTROL)); //kprintf("IA32_ENERGY_PERF_BIAS 0x%llx\n", rdmsr(MSR_IA32_ENERGY_PERF_BIAS)); //kprintf("IA32_PERF_STATUS 0x%llx\n", rdmsr(MSR_IA32_PERF_STATUS)); if (has_pat()) { diff --git a/hermit/arch/x86/kernel/tasks.c b/hermit/arch/x86/kernel/tasks.c index b10bbdabe..976a7093f 100644 --- a/hermit/arch/x86/kernel/tasks.c +++ b/hermit/arch/x86/kernel/tasks.c @@ -117,7 +117,7 @@ size_t* get_current_stack(void) if (curr_task->status == TASK_IDLE) stptr += KERNEL_STACK_SIZE - 0x10; else - stptr += DEFAULT_STACK_SIZE - 0x10; + stptr = (stptr + DEFAULT_STACK_SIZE - 1) & ~0x1F; set_per_core(kernel_stack, stptr); tss_set_rsp0(stptr); @@ -151,7 +151,7 @@ int create_default_frame(task_t* task, entry_point_t ep, void* arg, uint32_t cor * and not for HW-task-switching is setting up a stack and not a TSS. * This is the stack which will be activated and popped off for iret later. */ - stack = (size_t*) (((size_t) task->stack + DEFAULT_STACK_SIZE - 0x10) & ~0xF); // => stack is 16byte aligned + stack = (size_t*) (((size_t) task->stack + DEFAULT_STACK_SIZE - 1) & ~0x1F); // => stack is 16byte aligned /* Only marker for debugging purposes, ... */ *stack-- = 0xDEADBEEF; diff --git a/hermit/arch/x86/kernel/timer.c b/hermit/arch/x86/kernel/timer.c index 5f6536173..7cabf2c66 100644 --- a/hermit/arch/x86/kernel/timer.c +++ b/hermit/arch/x86/kernel/timer.c @@ -121,7 +121,7 @@ int timer_wait(unsigned int ticks) if (per_core(timer_ticks) >= eticks) break; - HALT; + PAUSE; } } else if (per_core(timer_ticks) < eticks) { check_workqueues(); diff --git a/hermit/kernel/main.c b/hermit/kernel/main.c index d0cc85417..372d2ad73 100644 --- a/hermit/kernel/main.c +++ b/hermit/kernel/main.c @@ -87,6 +87,8 @@ extern int32_t possible_isles; extern uint32_t boot_processor; extern int libc_sd; +uint32_t idle_poll = 1; + islelock_t* rcce_lock = NULL; rcce_mpb_t* rcce_mpb = NULL; @@ -227,7 +229,7 @@ int smp_main(void) while(1) { check_workqueues(); - if (libc_sd >= 0) + if (idle_poll) PAUSE; else HALT; @@ -478,7 +480,7 @@ int hermit_main(void) while(1) { check_workqueues(); - if (libc_sd >= 0) + if (idle_poll) PAUSE; else HALT; diff --git a/hermit/kernel/syscall.c b/hermit/kernel/syscall.c index bba7e77cd..d9fb88604 100644 --- a/hermit/kernel/syscall.c +++ b/hermit/kernel/syscall.c @@ -48,6 +48,7 @@ static spinlock_t lwip_lock = SPINLOCK_INIT; extern int32_t isle; extern int32_t possible_isles; extern int libc_sd; +extern uint32_t idle_poll; tid_t sys_getpid(void) { @@ -90,6 +91,7 @@ void NORETURN sys_exit(int arg) lwip_close(libc_sd); libc_sd = -1; + idle_poll = 0; } do_exit(arg);