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);

Reply via email to