Annotation of sys/arch/amd64/amd64/mp_setperf.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: mp_setperf.c,v 1.1 2007/05/06 03:37:08 gwk Exp $ */
! 2: /*
! 3: * Copyright (c) 2007 Gordon Willem Klok <gwk@openbsd.org>
! 4: *
! 5: * Permission to use, copy, modify, and distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 16: */
! 17:
! 18: #include <sys/param.h>
! 19: #include <sys/systm.h>
! 20: #include <sys/sysctl.h>
! 21: #include <sys/mutex.h>
! 22:
! 23: #include <machine/cpu.h>
! 24:
! 25: #include <machine/intr.h>
! 26:
! 27: struct mutex setperf_mp_mutex = MUTEX_INITIALIZER(IPL_HIGH);
! 28:
! 29: /* underlying setperf mechanism e.g. k8_powernow_setperf() */
! 30: void (*ul_setperf)(int);
! 31:
! 32: #define MP_SETPERF_STEADY 0 /* steady state - normal operation */
! 33: #define MP_SETPERF_INTRANSIT 1 /* in transition */
! 34: #define MP_SETPERF_PROCEED 2 /* proceed with transition */
! 35: #define MP_SETPERF_FINISH 3 /* return from IPI */
! 36:
! 37:
! 38: /* protected by setperf_mp_mutex */
! 39: volatile int mp_setperf_state = MP_SETPERF_STEADY;
! 40: volatile int mp_perflevel;
! 41:
! 42: void mp_setperf(int);
! 43:
! 44: void
! 45: mp_setperf(int level)
! 46: {
! 47: CPU_INFO_ITERATOR cii;
! 48: struct cpu_info *ci;
! 49: int notready, s;
! 50:
! 51: if (mp_setperf_state == MP_SETPERF_STEADY) {
! 52: mtx_enter(&setperf_mp_mutex);
! 53: mp_perflevel = level;
! 54:
! 55: curcpu()->ci_setperf_state = CI_SETPERF_INTRANSIT;
! 56: /* ask all other processors to drop what they are doing */
! 57: CPU_INFO_FOREACH(cii, ci) {
! 58: if (ci->ci_setperf_state != CI_SETPERF_INTRANSIT) {
! 59: ci->ci_setperf_state =
! 60: CI_SETPERF_SHOULDSTOP;
! 61: x86_send_ipi(ci, X86_IPI_SETPERF);
! 62: }
! 63: }
! 64:
! 65:
! 66: /* Loop until all processors report ready */
! 67: do {
! 68: CPU_INFO_FOREACH(cii, ci) {
! 69: if ((notready = (ci->ci_setperf_state
! 70: != CI_SETPERF_INTRANSIT)))
! 71: break;
! 72: }
! 73: } while (notready);
! 74:
! 75: mp_setperf_state = MP_SETPERF_PROCEED; /* release the hounds */
! 76:
! 77: s = splipi();
! 78:
! 79: ul_setperf(mp_perflevel);
! 80:
! 81: splx(s);
! 82:
! 83: curcpu()->ci_setperf_state = CI_SETPERF_DONE;
! 84: /* Loop until all processors report done */
! 85: do {
! 86: CPU_INFO_FOREACH(cii, ci) {
! 87: if ((notready = (ci->ci_setperf_state
! 88: != CI_SETPERF_DONE)))
! 89: break;
! 90: }
! 91: } while (notready);
! 92:
! 93: mp_setperf_state = MP_SETPERF_FINISH;
! 94: /* delay a little for potential straglers */
! 95: DELAY(2);
! 96: curcpu()->ci_setperf_state = CI_SETPERF_READY;
! 97: mp_setperf_state = MP_SETPERF_STEADY; /* restore normallity */
! 98: mtx_leave(&setperf_mp_mutex);
! 99: }
! 100:
! 101: }
! 102:
! 103: void
! 104: x86_setperf_ipi(struct cpu_info *ci)
! 105: {
! 106:
! 107: if (ci->ci_setperf_state == CI_SETPERF_SHOULDSTOP)
! 108: ci->ci_setperf_state = CI_SETPERF_INTRANSIT;
! 109:
! 110: while (mp_setperf_state != MP_SETPERF_PROCEED)
! 111: ;
! 112:
! 113: ul_setperf(mp_perflevel);
! 114:
! 115: ci->ci_setperf_state = CI_SETPERF_DONE;
! 116:
! 117: while (mp_setperf_state != MP_SETPERF_FINISH)
! 118: ;
! 119: ci->ci_setperf_state = CI_SETPERF_READY;
! 120: }
! 121:
! 122: void
! 123: mp_setperf_init()
! 124: {
! 125: CPU_INFO_ITERATOR cii;
! 126: struct cpu_info *ci;
! 127:
! 128:
! 129: if (!cpu_setperf)
! 130: return;
! 131: ul_setperf = cpu_setperf;
! 132:
! 133: cpu_setperf = mp_setperf;
! 134:
! 135: CPU_INFO_FOREACH(cii, ci) {
! 136: ci->ci_setperf_state = CI_SETPERF_READY;
! 137: }
! 138: mtx_init(&setperf_mp_mutex, IPL_HIGH);
! 139: }
CVSweb