From owner-svn-src-head@freebsd.org Thu Nov 30 01:40:08 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 45A0FDF05ED; Thu, 30 Nov 2017 01:40:08 +0000 (UTC) (envelope-from jkim@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1FAF46DD43; Thu, 30 Nov 2017 01:40:08 +0000 (UTC) (envelope-from jkim@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id vAU1e7ec001293; Thu, 30 Nov 2017 01:40:07 GMT (envelope-from jkim@FreeBSD.org) Received: (from jkim@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id vAU1e7dC001292; Thu, 30 Nov 2017 01:40:07 GMT (envelope-from jkim@FreeBSD.org) Message-Id: <201711300140.vAU1e7dC001292@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jkim set sender to jkim@FreeBSD.org using -f From: Jung-uk Kim Date: Thu, 30 Nov 2017 01:40:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r326383 - head/sys/x86/cpufreq X-SVN-Group: head X-SVN-Commit-Author: jkim X-SVN-Commit-Paths: head/sys/x86/cpufreq X-SVN-Commit-Revision: 326383 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 30 Nov 2017 01:40:08 -0000 Author: jkim Date: Thu Nov 30 01:40:07 2017 New Revision: 326383 URL: https://svnweb.freebsd.org/changeset/base/326383 Log: Add a tunable "debug.hwpstate_verify" to check P-state after changing it and turn it off by default. It is very inefficient to verify current P-state of each core, especially for CPUs with many cores. When multiple commands are requested to the same power domain before completion of pending transitions, the last command is executed according to the manual. Because requests are serialized by the caller, all cores will receive the same command for each call. Do not call sched_bind() and sched_unbind(). It is redundant because the caller does it anyway. Modified: head/sys/x86/cpufreq/hwpstate.c Modified: head/sys/x86/cpufreq/hwpstate.c ============================================================================== --- head/sys/x86/cpufreq/hwpstate.c Thu Nov 30 00:27:49 2017 (r326382) +++ head/sys/x86/cpufreq/hwpstate.c Thu Nov 30 01:40:07 2017 (r326383) @@ -123,10 +123,14 @@ static int hwpstate_get_info_from_acpi_perf(device_t d static int hwpstate_get_info_from_msr(device_t dev); static int hwpstate_goto_pstate(device_t dev, int pstate_id); -static int hwpstate_verbose = 0; +static int hwpstate_verbose; SYSCTL_INT(_debug, OID_AUTO, hwpstate_verbose, CTLFLAG_RWTUN, &hwpstate_verbose, 0, "Debug hwpstate"); +static int hwpstate_verify; +SYSCTL_INT(_debug, OID_AUTO, hwpstate_verify, CTLFLAG_RWTUN, + &hwpstate_verify, 0, "Verify P-state after setting"); + static device_method_t hwpstate_methods[] = { /* Device interface */ DEVMETHOD(device_identify, hwpstate_identify), @@ -160,15 +164,13 @@ DRIVER_MODULE(hwpstate, cpu, hwpstate_driver, hwpstate * Go to Px-state on all cpus considering the limit. */ static int -hwpstate_goto_pstate(device_t dev, int pstate) +hwpstate_goto_pstate(device_t dev, int id) { sbintime_t sbt; int i; uint64_t msr; int j; int limit; - int id = pstate; - int error; /* get the current pstate limit */ msr = rdmsr(MSR_AMD_10H_11H_LIMIT); @@ -176,47 +178,57 @@ hwpstate_goto_pstate(device_t dev, int pstate) if (limit > id) id = limit; + HWPSTATE_DEBUG(dev, "setting P%d-state on cpu%d\n", id, + PCPU_GET(cpuid)); + /* Go To Px-state */ + wrmsr(MSR_AMD_10H_11H_CONTROL, id); + /* * We are going to the same Px-state on all cpus. * Probably should take _PSD into account. */ - error = 0; CPU_FOREACH(i) { + if (i == PCPU_GET(cpuid)) + continue; + /* Bind to each cpu. */ thread_lock(curthread); sched_bind(curthread, i); thread_unlock(curthread); - HWPSTATE_DEBUG(dev, "setting P%d-state on cpu%d\n", - id, PCPU_GET(cpuid)); + HWPSTATE_DEBUG(dev, "setting P%d-state on cpu%d\n", id, i); /* Go To Px-state */ wrmsr(MSR_AMD_10H_11H_CONTROL, id); } - CPU_FOREACH(i) { - /* Bind to each cpu. */ - thread_lock(curthread); - sched_bind(curthread, i); - thread_unlock(curthread); - /* wait loop (100*100 usec is enough ?) */ - for (j = 0; j < 100; j++) { - /* get the result. not assure msr=id */ - msr = rdmsr(MSR_AMD_10H_11H_STATUS); - if (msr == id) - break; - sbt = SBT_1MS / 10; - tsleep_sbt(dev, PZERO, "pstate_goto", sbt, - sbt >> tc_precexp, 0); + + /* + * Verify whether each core is in the requested P-state. + */ + if (hwpstate_verify) { + CPU_FOREACH(i) { + thread_lock(curthread); + sched_bind(curthread, i); + thread_unlock(curthread); + /* wait loop (100*100 usec is enough ?) */ + for (j = 0; j < 100; j++) { + /* get the result. not assure msr=id */ + msr = rdmsr(MSR_AMD_10H_11H_STATUS); + if (msr == id) + break; + sbt = SBT_1MS / 10; + tsleep_sbt(dev, PZERO, "pstate_goto", sbt, + sbt >> tc_precexp, 0); + } + HWPSTATE_DEBUG(dev, "result: P%d-state on cpu%d\n", + (int)msr, i); + if (msr != id) { + HWPSTATE_DEBUG(dev, + "error: loop is not enough.\n"); + return (ENXIO); + } } - HWPSTATE_DEBUG(dev, "result: P%d-state on cpu%d\n", - (int)msr, PCPU_GET(cpuid)); - if (msr != id) { - HWPSTATE_DEBUG(dev, "error: loop is not enough.\n"); - error = ENXIO; - } } - thread_lock(curthread); - sched_unbind(curthread); - thread_unlock(curthread); - return (error); + + return (0); } static int