while browsing latest modification I see the throttle written function was not used yet so for curiosity I've tried to use it for throttling cpu in C0 state. I've made some test (md5) sweeping the whole throttle range (hw.throttle=1..2^dutywidth) and it seems to work
giovanni diff -ru sys.orig/arch/i386/conf/GENERIC sys/arch/i386/conf/GENERIC --- sys.orig/arch/i386/conf/GENERIC Fri Jun 1 08:53:17 2007 +++ sys/arch/i386/conf/GENERIC Sat Jun 2 21:46:39 2007 @@ -58,19 +58,19 @@ pci* at mainbus0 #option ACPIVERBOSE -#option ACPI_ENABLE +option ACPI_ENABLE -acpi0 at mainbus? disable -#acpitimer* at acpi? +acpi0 at mainbus? +acpitimer* at acpi? #acpihpet* at acpi? -#acpiac* at acpi? -#acpibat* at acpi? -#acpibtn* at acpi? -#acpicpu* at acpi? +acpiac* at acpi? +acpibat* at acpi? +acpibtn* at acpi? +acpicpu* at acpi? #acpidock* at acpi? -acpiec* at acpi? disable +acpiec* at acpi? acpiprt* at acpi? -#acpitz* at acpi? +acpitz* at acpi? option PCIVERBOSE option EISAVERBOSE diff -ru sys.orig/dev/acpi/acpicpu.c sys/dev/acpi/acpicpu.c --- sys.orig/dev/acpi/acpicpu.c Fri Jun 1 08:53:31 2007 +++ sys/dev/acpi/acpicpu.c Sun Jun 3 08:40:38 2007 @@ -56,7 +56,8 @@ #define CPU_THT_EN (1L << 4) #define CPU_MAXSTATE(sc) (1L << (sc)->sc_duty_wid) -#define CPU_STATE(sc,pct) ((pct * CPU_MAXSTATE(sc) / 100) << (sc)->sc_duty_off) +#define CPU_DUTYWIDTH(sc) ((sc)->sc_duty_wid) +#define CPU_STATE(sc,pct) (pct << (sc)->sc_duty_off) #define CPU_STATEMASK(sc) ((CPU_MAXSTATE(sc) - 1) << (sc)->sc_duty_off) #define ACPI_MAX_C2_LATENCY 100 @@ -106,7 +107,7 @@ void (*sc_notify)(struct acpicpu_pss *, int); }; -void acpicpu_set_throttle(struct acpicpu_softc *, int); +void acpicpu_set_throttle(int *); void acpicpu_add_cstatepkg(struct aml_value *, void *); int acpicpu_getpct(struct acpicpu_softc *); int acpicpu_getpss(struct acpicpu_softc *); @@ -122,6 +123,7 @@ }; extern int setperf_prio; +extern int throttle_lv; #ifdef __i386__ struct acpicpu_softc *acpicpu_sc[I386_MAXPROCS]; @@ -130,22 +132,27 @@ #endif void -acpicpu_set_throttle(struct acpicpu_softc *sc, int level) +acpicpu_set_throttle(int* level) { - uint32_t pbval; + uint32_t pbval; + struct acpicpu_softc *sc; + sc = acpicpu_sc[cpu_number()]; + if (sc->sc_flags & FLAGS_NOTHROTTLE) return; /* Disable throttling control */ pbval = inl(sc->sc_pblk_addr); outl(sc->sc_pblk_addr, pbval & ~CPU_THT_EN); - if (level < 100) { - pbval &= ~CPU_STATEMASK(sc); - pbval |= CPU_STATE(sc, level); - outl(sc->sc_pblk_addr, pbval & ~CPU_THT_EN); - outl(sc->sc_pblk_addr, pbval | CPU_THT_EN); - } + + *level = min(((1 << CPU_DUTYWIDTH(sc)) - 1), *level); + *level = max(1, *level); + + pbval &= ~CPU_STATEMASK(sc); + pbval |= CPU_STATE(sc, *level); + outl(sc->sc_pblk_addr, pbval & ~CPU_THT_EN); + outl(sc->sc_pblk_addr, pbval | CPU_THT_EN); } struct acpi_cstate * @@ -259,6 +266,12 @@ sc->sc_duty_wid = sc->sc_acpi->sc_fadt->duty_width; if (!valid_throttle(sc->sc_duty_off, sc->sc_duty_wid, sc->sc_pblk_addr)) sc->sc_flags |= FLAGS_NOTHROTTLE; + else { + if (cpu_throttle == NULL) { + throttle_lv = (1 << CPU_DUTYWIDTH(sc)) - 1; + cpu_throttle = acpicpu_set_throttle; + } + } #ifdef ACPI_DEBUG printf(": %s: ", sc->sc_devnode->name); diff -ru sys.orig/kern/kern_sysctl.c sys/kern/kern_sysctl.c --- sys.orig/kern/kern_sysctl.c Tue May 29 08:39:40 2007 +++ sys/kern/kern_sysctl.c Sat Jun 2 22:13:00 2007 @@ -105,7 +105,9 @@ int (*cpu_cpuspeed)(int *); void (*cpu_setperf)(int); +void (*cpu_throttle)(int *); int perflevel = 100; +int throttle_lv = 0; /* * Lock to avoid too many processes vslocking a large amount of memory @@ -614,6 +616,15 @@ perflevel = 0; if (newp) cpu_setperf(perflevel); + return (0); + case HW_THROTTLE: + if (!cpu_throttle) + return (EOPNOTSUPP); + err = sysctl_int(oldp, oldlenp, newp, newlen, &throttle_lv); + if (err) + return err; + if (newp) + cpu_throttle(&throttle_lv); return (0); case HW_VENDOR: if (hw_vendor) diff -ru sys.orig/sys/sysctl.h sys/sys/sysctl.h --- sys.orig/sys/sysctl.h Fri Apr 27 10:47:11 2007 +++ sys/sys/sysctl.h Sat Jun 2 21:52:39 2007 @@ -552,7 +552,8 @@ #define HW_VERSION 16 /* string: hardware version */ #define HW_SERIALNO 17 /* string: hardware serial number */ #define HW_UUID 18 /* string: universal unique id */ -#define HW_MAXID 19 /* number of valid hw ids */ +#define HW_THROTTLE 19 /* int: set CPU throttle */ +#define HW_MAXID 20 /* number of valid hw ids */ #define CTL_HW_NAMES { \ { 0, 0 }, \ @@ -574,6 +575,7 @@ { "version", CTLTYPE_STRING }, \ { "serialno", CTLTYPE_STRING }, \ { "uuid", CTLTYPE_STRING }, \ + { "throttle", CTLTYPE_INT }, \ } /* @@ -724,6 +726,7 @@ extern int (*cpu_cpuspeed)(int *); extern void (*cpu_setperf)(int); +extern void (*cpu_throttle)(int *); int bpf_sysctl(int *, u_int, void *, size_t *, void *, size_t);