LCOV - code coverage report
Current view: top level - dev/acpi - acpicpu.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 518 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 20 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* $OpenBSD: acpicpu.c,v 1.82 2018/06/29 17:39:18 kettenis Exp $ */
       2             : /*
       3             :  * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
       4             :  * Copyright (c) 2015 Philip Guenther <guenther@openbsd.org>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : #include <sys/param.h>
      20             : #include <sys/kernel.h>           /* for tick */
      21             : #include <sys/signalvar.h>
      22             : #include <sys/sysctl.h>
      23             : #include <sys/systm.h>
      24             : #include <sys/device.h>
      25             : #include <sys/malloc.h>
      26             : #include <sys/queue.h>
      27             : #include <sys/atomic.h>
      28             : 
      29             : #include <machine/bus.h>
      30             : #include <machine/cpu.h>
      31             : #include <machine/cpufunc.h>
      32             : #include <machine/specialreg.h>
      33             : 
      34             : #include <dev/acpi/acpireg.h>
      35             : #include <dev/acpi/acpivar.h>
      36             : #include <dev/acpi/acpidev.h>
      37             : #include <dev/acpi/amltypes.h>
      38             : #include <dev/acpi/dsdt.h>
      39             : 
      40             : #include <sys/sensors.h>
      41             : 
      42             : int     acpicpu_match(struct device *, void *, void *);
      43             : void    acpicpu_attach(struct device *, struct device *, void *);
      44             : int     acpicpu_notify(struct aml_node *, int, void *);
      45             : void    acpicpu_setperf(int);
      46             : void    acpicpu_setperf_ppc_change(struct acpicpu_pss *, int);
      47             : 
      48             : #define ACPI_STATE_C0           0x00
      49             : #define ACPI_STATE_C1           0x01
      50             : #define ACPI_STATE_C2           0x02
      51             : #define ACPI_STATE_C3           0x03
      52             : 
      53             : #define ACPI_PDC_REVID          0x1
      54             : #define ACPI_PDC_SMP            0xa
      55             : #define ACPI_PDC_MSR            0x1
      56             : 
      57             : /* _PDC/_OSC Intel capabilities flags */
      58             : #define ACPI_PDC_P_FFH          0x0001
      59             : #define ACPI_PDC_C_C1_HALT      0x0002
      60             : #define ACPI_PDC_T_FFH          0x0004
      61             : #define ACPI_PDC_SMP_C1PT       0x0008
      62             : #define ACPI_PDC_SMP_C2C3       0x0010
      63             : #define ACPI_PDC_SMP_P_SWCOORD  0x0020
      64             : #define ACPI_PDC_SMP_C_SWCOORD  0x0040
      65             : #define ACPI_PDC_SMP_T_SWCOORD  0x0080
      66             : #define ACPI_PDC_C_C1_FFH       0x0100
      67             : #define ACPI_PDC_C_C2C3_FFH     0x0200
      68             : /* reserved                     0x0400 */
      69             : #define ACPI_PDC_P_HWCOORD      0x0800
      70             : #define ACPI_PDC_PPC_NOTIFY     0x1000
      71             : 
      72             : #define CST_METH_HALT           0
      73             : #define CST_METH_IO_HALT        1
      74             : #define CST_METH_MWAIT          2
      75             : #define CST_METH_GAS_IO         3
      76             : 
      77             : /* flags on Intel's FFH mwait method */
      78             : #define CST_FLAG_MWAIT_HW_COORD         0x1
      79             : #define CST_FLAG_MWAIT_BM_AVOIDANCE     0x2
      80             : #define CST_FLAG_FALLBACK               0x4000  /* fallback for broken _CST */
      81             : #define CST_FLAG_SKIP                   0x8000  /* state is worse choice */
      82             : 
      83             : #define FLAGS_MWAIT_ONLY        0x02
      84             : #define FLAGS_BMCHECK           0x04
      85             : #define FLAGS_NOTHROTTLE        0x08
      86             : #define FLAGS_NOPSS             0x10
      87             : #define FLAGS_NOPCT             0x20
      88             : 
      89             : #define CPU_THT_EN              (1L << 4)
      90             : #define CPU_MAXSTATE(sc)        (1L << (sc)->sc_duty_wid)
      91             : #define CPU_STATE(sc,pct)       ((pct * CPU_MAXSTATE(sc) / 100) << (sc)->sc_duty_off)
      92             : #define CPU_STATEMASK(sc)       ((CPU_MAXSTATE(sc) - 1) << (sc)->sc_duty_off)
      93             : 
      94             : #define ACPI_MAX_C2_LATENCY     100
      95             : #define ACPI_MAX_C3_LATENCY     1000
      96             : 
      97             : #define CSD_COORD_SW_ALL        0xFC
      98             : #define CSD_COORD_SW_ANY        0xFD
      99             : #define CSD_COORD_HW_ALL        0xFE
     100             : 
     101             : /* Make sure throttling bits are valid,a=addr,o=offset,w=width */
     102             : #define valid_throttle(o,w,a)   (a && w && (o+w)<=31 && (o>4 || (o+w)<=4))
     103             : 
     104             : struct acpi_cstate
     105             : {
     106             :         SLIST_ENTRY(acpi_cstate) link;
     107             : 
     108             :         u_short         state;
     109             :         short           method;         /* CST_METH_* */
     110             :         u_short         flags;          /* CST_FLAG_* */
     111             :         u_short         latency;
     112             :         int             power;
     113             :         uint64_t        address;        /* or mwait hint */
     114             : };
     115             : 
     116             : unsigned long cst_stats[4] = { 0 };
     117             : 
     118             : struct acpicpu_softc {
     119             :         struct device           sc_dev;
     120             :         int                     sc_cpu;
     121             : 
     122             :         int                     sc_duty_wid;
     123             :         int                     sc_duty_off;
     124             :         uint32_t                sc_pblk_addr;
     125             :         int                     sc_pblk_len;
     126             :         int                     sc_flags;
     127             :         unsigned long           sc_prev_sleep;
     128             :         unsigned long           sc_last_itime;
     129             : 
     130             :         struct cpu_info         *sc_ci;
     131             :         SLIST_HEAD(,acpi_cstate) sc_cstates;
     132             : 
     133             :         bus_space_tag_t         sc_iot;
     134             :         bus_space_handle_t      sc_ioh;
     135             : 
     136             :         struct acpi_softc       *sc_acpi;
     137             :         struct aml_node         *sc_devnode;
     138             : 
     139             :         int                     sc_pss_len;     /* XXX */
     140             :         int                     sc_ppc;
     141             :         int                     sc_level;
     142             :         struct acpicpu_pss      *sc_pss;
     143             :         size_t                  sc_pssfulllen;
     144             : 
     145             :         struct acpicpu_pct      sc_pct;
     146             :         /* save compensation for pct access for lying bios' */
     147             :         uint32_t                sc_pct_stat_as;
     148             :         uint32_t                sc_pct_ctrl_as;
     149             :         uint32_t                sc_pct_stat_len;
     150             :         uint32_t                sc_pct_ctrl_len;
     151             :         /*
     152             :          * XXX: _PPC Change listener
     153             :          * PPC changes can occur when for example a machine is disconnected
     154             :          * from AC power and can no loger support the highest frequency or
     155             :          * voltage when driven from the battery.
     156             :          * Should probably be reimplemented as a list for now we assume only
     157             :          * one listener
     158             :          */
     159             :         void                    (*sc_notify)(struct acpicpu_pss *, int);
     160             : };
     161             : 
     162             : void    acpicpu_add_cstatepkg(struct aml_value *, void *);
     163             : void    acpicpu_add_cdeppkg(struct aml_value *, void *);
     164             : int     acpicpu_getppc(struct acpicpu_softc *);
     165             : int     acpicpu_getpct(struct acpicpu_softc *);
     166             : int     acpicpu_getpss(struct acpicpu_softc *);
     167             : int     acpicpu_getcst(struct acpicpu_softc *);
     168             : void    acpicpu_getcst_from_fadt(struct acpicpu_softc *);
     169             : void    acpicpu_print_one_cst(struct acpi_cstate *_cx);
     170             : void    acpicpu_print_cst(struct acpicpu_softc *_sc);
     171             : void    acpicpu_add_cstate(struct acpicpu_softc *_sc, int _state, int _method,
     172             :             int _flags, int _latency, int _power, uint64_t _address);
     173             : void    acpicpu_set_pdc(struct acpicpu_softc *);
     174             : void    acpicpu_idle(void);
     175             : 
     176             : #if 0
     177             : void    acpicpu_set_throttle(struct acpicpu_softc *, int);
     178             : struct acpi_cstate *acpicpu_find_cstate(struct acpicpu_softc *, int);
     179             : #endif
     180             : 
     181             : struct cfattach acpicpu_ca = {
     182             :         sizeof(struct acpicpu_softc), acpicpu_match, acpicpu_attach
     183             : };
     184             : 
     185             : struct cfdriver acpicpu_cd = {
     186             :         NULL, "acpicpu", DV_DULL
     187             : };
     188             : 
     189             : extern int setperf_prio;
     190             : 
     191             : struct acpicpu_softc *acpicpu_sc[MAXCPUS];
     192             : 
     193             : #if 0
     194             : void
     195             : acpicpu_set_throttle(struct acpicpu_softc *sc, int level)
     196             : {
     197             :         uint32_t pbval;
     198             : 
     199             :         if (sc->sc_flags & FLAGS_NOTHROTTLE)
     200             :                 return;
     201             : 
     202             :         /* Disable throttling control */
     203             :         pbval = inl(sc->sc_pblk_addr);
     204             :         outl(sc->sc_pblk_addr, pbval & ~CPU_THT_EN);
     205             :         if (level < 100) {
     206             :                 pbval &= ~CPU_STATEMASK(sc);
     207             :                 pbval |= CPU_STATE(sc, level);
     208             :                 outl(sc->sc_pblk_addr, pbval & ~CPU_THT_EN);
     209             :                 outl(sc->sc_pblk_addr, pbval | CPU_THT_EN);
     210             :         }
     211             : }
     212             : 
     213             : struct acpi_cstate *
     214             : acpicpu_find_cstate(struct acpicpu_softc *sc, int state)
     215             : {
     216             :         struct acpi_cstate      *cx;
     217             : 
     218             :         SLIST_FOREACH(cx, &sc->sc_cstates, link)
     219             :                 if (cx->state == state)
     220             :                         return cx;
     221             :         return (NULL);
     222             : }
     223             : #endif
     224             : 
     225             : 
     226             : void
     227           0 : acpicpu_set_pdc(struct acpicpu_softc *sc)
     228             : {
     229           0 :         struct aml_value cmd, osc_cmd[4];
     230           0 :         struct aml_value res;
     231             :         uint32_t cap;
     232           0 :         uint32_t buf[3];
     233             : 
     234             :         /* 4077A616-290C-47BE-9EBD-D87058713953 */
     235             :         static uint8_t cpu_oscuuid[16] = { 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29,
     236             :                                            0xBE, 0x47, 0x9E, 0xBD, 0xD8, 0x70,
     237             :                                            0x58, 0x71, 0x39, 0x53 };
     238             :         cap = ACPI_PDC_C_C1_HALT | ACPI_PDC_P_FFH | ACPI_PDC_C_C1_FFH
     239             :             | ACPI_PDC_C_C2C3_FFH | ACPI_PDC_SMP_P_SWCOORD | ACPI_PDC_SMP_C2C3
     240             :             | ACPI_PDC_SMP_C1PT;
     241             : 
     242           0 :         if (aml_searchname(sc->sc_devnode, "_OSC")) {
     243             :                 /* Query _OSC */
     244           0 :                 memset(&osc_cmd, 0, sizeof(osc_cmd));
     245           0 :                 osc_cmd[0].type = AML_OBJTYPE_BUFFER;
     246           0 :                 osc_cmd[0].v_buffer = (uint8_t *)&cpu_oscuuid;
     247           0 :                 osc_cmd[0].length = sizeof(cpu_oscuuid);
     248             : 
     249           0 :                 osc_cmd[1].type = AML_OBJTYPE_INTEGER;
     250           0 :                 osc_cmd[1].v_integer = 1;
     251           0 :                 osc_cmd[1].length = 1;
     252             : 
     253           0 :                 osc_cmd[2].type = AML_OBJTYPE_INTEGER;
     254           0 :                 osc_cmd[2].v_integer = 2;
     255           0 :                 osc_cmd[2].length = 1;
     256             : 
     257           0 :                 buf[0] = 1;
     258           0 :                 buf[1] = cap;
     259           0 :                 osc_cmd[3].type = AML_OBJTYPE_BUFFER;
     260           0 :                 osc_cmd[3].v_buffer = (int8_t *)&buf;
     261           0 :                 osc_cmd[3].length = sizeof(buf);
     262             : 
     263           0 :                 aml_evalname(sc->sc_acpi, sc->sc_devnode, "_OSC",
     264           0 :                     4, osc_cmd, &res);
     265             : 
     266           0 :                 if (res.type != AML_OBJTYPE_BUFFER || res.length < 8) {
     267           0 :                         printf(": unable to query capabilities\n");
     268           0 :                         aml_freevalue(&res);
     269           0 :                         return;
     270             :                 }
     271             : 
     272             :                 /* Evaluate _OSC */
     273           0 :                 memset(&osc_cmd, 0, sizeof(osc_cmd));
     274           0 :                 osc_cmd[0].type = AML_OBJTYPE_BUFFER;
     275           0 :                 osc_cmd[0].v_buffer = (uint8_t *)&cpu_oscuuid;
     276           0 :                 osc_cmd[0].length = sizeof(cpu_oscuuid);
     277             : 
     278           0 :                 osc_cmd[1].type = AML_OBJTYPE_INTEGER;
     279           0 :                 osc_cmd[1].v_integer = 1;
     280           0 :                 osc_cmd[1].length = 1;
     281             : 
     282           0 :                 osc_cmd[2].type = AML_OBJTYPE_INTEGER;
     283           0 :                 osc_cmd[2].v_integer = 2;
     284           0 :                 osc_cmd[2].length = 1;
     285             : 
     286           0 :                 buf[0] = 0;
     287           0 :                 buf[1] = (*(uint32_t *)&res.v_buffer[4]) & cap;
     288           0 :                 osc_cmd[3].type = AML_OBJTYPE_BUFFER;
     289           0 :                 osc_cmd[3].v_buffer = (int8_t *)&buf;
     290           0 :                 osc_cmd[3].length = sizeof(buf);
     291             : 
     292           0 :                 aml_freevalue(&res);
     293             : 
     294           0 :                 aml_evalname(sc->sc_acpi, sc->sc_devnode, "_OSC",
     295             :                     4, osc_cmd, NULL);
     296           0 :         } else {
     297             :                 /* Evaluate _PDC */
     298           0 :                 memset(&cmd, 0, sizeof(cmd));
     299           0 :                 cmd.type = AML_OBJTYPE_BUFFER;
     300           0 :                 cmd.v_buffer = (uint8_t *)&buf;
     301           0 :                 cmd.length = sizeof(buf);
     302             : 
     303           0 :                 buf[0] = ACPI_PDC_REVID;
     304           0 :                 buf[1] = 1;
     305           0 :                 buf[2] = cap;
     306             : 
     307           0 :                 aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PDC",
     308             :                     1, &cmd, NULL);
     309             :         }
     310           0 : }
     311             : 
     312             : /*
     313             :  * sanity check mwait hints against what cpuid told us
     314             :  * ...but because intel screwed up, just check whether cpuid says
     315             :  * the given state has _any_ substates.
     316             :  */
     317             : static int
     318           0 : check_mwait_hints(int state, int hints)
     319             : {
     320             :         int cstate;
     321             :         int num_substates;
     322             : 
     323           0 :         if (cpu_mwait_size == 0)
     324           0 :                 return (0);
     325           0 :         cstate = ((hints >> 4) & 0xf) + 1;
     326           0 :         if (cstate == 16)
     327           0 :                 cstate = 0;
     328           0 :         else if (cstate > 7) {
     329             :                 /* out of range of test against CPUID; just trust'em */
     330           0 :                 return (1);
     331             :         }
     332           0 :         num_substates = (cpu_mwait_states >> (4 * cstate)) & 0xf;
     333           0 :         if (num_substates == 0) {
     334           0 :                 printf(": C%d bad (state %d has no substates)", state, cstate);
     335           0 :                 return (0);
     336             :         }
     337           0 :         return (1);
     338           0 : }
     339             : 
     340             : void
     341           0 : acpicpu_add_cstate(struct acpicpu_softc *sc, int state, int method,
     342             :     int flags, int latency, int power, uint64_t address)
     343             : {
     344             :         struct acpi_cstate      *cx;
     345             : 
     346             :         dnprintf(10," C%d: latency:.%4x power:%.4x addr:%.16llx\n",
     347             :             state, latency, power, address);
     348             : 
     349             :         /* add a new state, or overwrite the fallback C1 state? */
     350           0 :         if (state != ACPI_STATE_C1 ||
     351           0 :             (cx = SLIST_FIRST(&sc->sc_cstates)) == NULL ||
     352           0 :             (cx->flags & CST_FLAG_FALLBACK) == 0) {
     353           0 :                 cx = malloc(sizeof(*cx), M_DEVBUF, M_WAITOK);
     354           0 :                 SLIST_INSERT_HEAD(&sc->sc_cstates, cx, link);
     355           0 :         }
     356             : 
     357           0 :         cx->state = state;
     358           0 :         cx->method = method;
     359           0 :         cx->flags = flags;
     360           0 :         cx->latency = latency;
     361           0 :         cx->power = power;
     362           0 :         cx->address = address;
     363           0 : }
     364             : 
     365             : /* Found a _CST object, add new cstate for each entry */
     366             : void
     367           0 : acpicpu_add_cstatepkg(struct aml_value *val, void *arg)
     368             : {
     369           0 :         struct acpicpu_softc    *sc = arg;
     370             :         uint64_t addr;
     371             :         struct acpi_grd *grd;
     372             :         int state, method, flags;
     373             : 
     374             : #if defined(ACPI_DEBUG) && !defined(SMALL_KERNEL)
     375             :         aml_showvalue(val);
     376             : #endif
     377           0 :         if (val->type != AML_OBJTYPE_PACKAGE || val->length != 4)
     378           0 :                 return;
     379             : 
     380             :         /* range and sanity checks */
     381           0 :         state = val->v_package[1]->v_integer;
     382           0 :         if (state < 0 || state > 4)
     383           0 :                 return;
     384           0 :         if (val->v_package[0]->type != AML_OBJTYPE_BUFFER) {
     385           0 :                 printf(": C%d (unexpected ACPI object type %d)",
     386             :                     state, val->v_package[0]->type);
     387           0 :                 return;
     388             :         }
     389           0 :         grd = (struct acpi_grd *)val->v_package[0]->v_buffer;
     390           0 :         if (val->v_package[0]->length != sizeof(*grd) + 2 ||
     391           0 :             grd->grd_descriptor != LR_GENREGISTER ||
     392           0 :             grd->grd_length != sizeof(grd->grd_gas) ||
     393           0 :             val->v_package[0]->v_buffer[sizeof(*grd)] != SRT_ENDTAG) {
     394           0 :                 printf(": C%d (bogo buffer)", state);
     395           0 :                 return;
     396             :         }
     397             : 
     398             :         flags = 0;
     399           0 :         switch (grd->grd_gas.address_space_id) {
     400             :         case GAS_FUNCTIONAL_FIXED:
     401           0 :                 if (grd->grd_gas.register_bit_width == 0) {
     402             :                         method = CST_METH_HALT;
     403             :                         addr = 0;
     404           0 :                 } else if (grd->grd_gas.register_bit_width == 1 ||
     405           0 :                            grd->grd_gas.register_bit_width == 8) {
     406             :                         /*
     407             :                          * vendor 1 == Intel
     408             :                          * vendor 8 == "AML author used the bitwidth"
     409             :                          */
     410           0 :                         switch (grd->grd_gas.register_bit_offset) {
     411             :                         case 0x1:
     412             :                                 method = CST_METH_IO_HALT;
     413           0 :                                 addr = grd->grd_gas.address;
     414             : 
     415             :                                 /* i386 and amd64 I/O space is 16bits */
     416           0 :                                 if (addr > 0xffff) {
     417           0 :                                         printf(": C%d (bogo I/O addr %llx)",
     418             :                                             state, addr);
     419           0 :                                         return;
     420             :                                 }
     421             :                                 break;
     422             :                         case 0x2:
     423           0 :                                 addr = grd->grd_gas.address;
     424           0 :                                 if (!check_mwait_hints(state, addr))
     425           0 :                                         return;
     426             :                                 method = CST_METH_MWAIT;
     427           0 :                                 flags = grd->grd_gas.access_size;
     428           0 :                                 break;
     429             :                         default:
     430           0 :                                 printf(": C%d (unknown FFH class %d)",
     431             :                                     state, grd->grd_gas.register_bit_offset);
     432           0 :                                 return;
     433             :                         }
     434             :                 } else {
     435           0 :                         printf(": C%d (unknown FFH vendor %d)",
     436             :                             state, grd->grd_gas.register_bit_width);
     437           0 :                         return;
     438             :                 }
     439             :                 break;
     440             : 
     441             :         case GAS_SYSTEM_IOSPACE:
     442           0 :                 addr = grd->grd_gas.address;
     443           0 :                 if (grd->grd_gas.register_bit_width != 8 ||
     444           0 :                     grd->grd_gas.register_bit_offset != 0) {
     445           0 :                         printf(": C%d (unhandled %s spec: %d/%d)", state,
     446           0 :                             "I/O", grd->grd_gas.register_bit_width,
     447           0 :                             grd->grd_gas.register_bit_offset);
     448           0 :                         return;
     449             :                 }
     450             :                 method = CST_METH_GAS_IO;
     451           0 :                 break;
     452             : 
     453             :         default:
     454             :                 /* dump the GAS for analysis */
     455             :                 {
     456             :                         int i;
     457           0 :                         printf(": C%d (unhandled GAS:", state);
     458           0 :                         for (i = 0; i < sizeof(grd->grd_gas); i++)
     459           0 :                                 printf(" %#x", ((u_char *)&grd->grd_gas)[i]);
     460           0 :                         printf(")");
     461             : 
     462             :                 }
     463           0 :                 return;
     464             :         }
     465             : 
     466           0 :         acpicpu_add_cstate(sc, state, method, flags,
     467           0 :             val->v_package[2]->v_integer, val->v_package[3]->v_integer, addr);
     468           0 : }
     469             : 
     470             : 
     471             : /* Found a _CSD object, print the dependency  */
     472             : void
     473           0 : acpicpu_add_cdeppkg(struct aml_value *val, void *arg)
     474             : {
     475             :         int64_t num_proc, coord_type, domain, cindex;
     476             : 
     477             :         /*
     478             :          * errors: unexpected object type, bad length, mismatched length,
     479             :          * and bad CSD revision 
     480             :          */
     481           0 :         if (val->type != AML_OBJTYPE_PACKAGE || val->length < 6 ||
     482           0 :             val->length != val->v_package[0]->v_integer ||
     483           0 :             val->v_package[1]->v_integer != 0) {
     484             : #if 1 || defined(ACPI_DEBUG) && !defined(SMALL_KERNEL)
     485           0 :                 aml_showvalue(val);
     486             : #endif
     487           0 :                 printf("bogus CSD\n");
     488           0 :                 return;
     489             :         }
     490             : 
     491             :         /* coordinating 'among' one CPU is trivial, ignore */
     492           0 :         num_proc = val->v_package[4]->v_integer;
     493           0 :         if (num_proc == 1)
     494           0 :                 return;
     495             : 
     496             :         /* we practically assume the hardware will coordinate, so ignore */
     497           0 :         coord_type = val->v_package[3]->v_integer;
     498           0 :         if (coord_type == CSD_COORD_HW_ALL)
     499           0 :                 return;
     500             : 
     501           0 :         domain = val->v_package[2]->v_integer;
     502           0 :         cindex = val->v_package[5]->v_integer;
     503           0 :         printf(": CSD (c=%#llx d=%lld n=%lld i=%lli)",
     504             :             coord_type, domain, num_proc, cindex);
     505           0 : }
     506             : 
     507             : int
     508           0 : acpicpu_getcst(struct acpicpu_softc *sc)
     509             : {
     510           0 :         struct aml_value        res;
     511             :         struct acpi_cstate      *cx, *next_cx;
     512             :         int                     use_nonmwait;
     513             : 
     514             :         /* delete the existing list */
     515           0 :         while ((cx = SLIST_FIRST(&sc->sc_cstates)) != NULL) {
     516           0 :                 SLIST_REMOVE_HEAD(&sc->sc_cstates, link);
     517           0 :                 free(cx, M_DEVBUF, sizeof(*cx));
     518             :         }
     519             : 
     520             :         /* provide a fallback C1-via-halt in case _CST's C1 is bogus */
     521           0 :         acpicpu_add_cstate(sc, ACPI_STATE_C1, CST_METH_HALT,
     522             :             CST_FLAG_FALLBACK, 1, -1, 0);
     523             : 
     524           0 :         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CST", 0, NULL, &res))
     525           0 :                 return (1);
     526             : 
     527           0 :         aml_foreachpkg(&res, 1, acpicpu_add_cstatepkg, sc);
     528           0 :         aml_freevalue(&res);
     529             : 
     530             :         /* only have fallback state?  then no _CST objects were understood */
     531           0 :         cx = SLIST_FIRST(&sc->sc_cstates);
     532           0 :         if (cx->flags & CST_FLAG_FALLBACK)
     533           0 :                 return (1);
     534             : 
     535             :         /*
     536             :          * Skip states >= C2 if the CPU's LAPIC timer stops in deep
     537             :          * states (i.e., it doesn't have the 'ARAT' bit set).
     538             :          * Also keep track if all the states we'll use use mwait.
     539             :          */
     540             :         use_nonmwait = 0;
     541           0 :         while ((next_cx = SLIST_NEXT(cx, link)) != NULL) {
     542           0 :                 if (cx->state > 1 &&
     543           0 :                     (sc->sc_ci->ci_feature_tpmflags & TPM_ARAT) == 0)
     544           0 :                         cx->flags |= CST_FLAG_SKIP;
     545           0 :                 else if (cx->method != CST_METH_MWAIT)
     546           0 :                         use_nonmwait = 1;
     547             :                 cx = next_cx;
     548             :         }
     549           0 :         if (use_nonmwait)
     550           0 :                 sc->sc_flags &= ~FLAGS_MWAIT_ONLY;
     551             :         else
     552           0 :                 sc->sc_flags |= FLAGS_MWAIT_ONLY;
     553             : 
     554           0 :         if (!aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CSD", 0, NULL, &res)) {
     555           0 :                 aml_foreachpkg(&res, 1, acpicpu_add_cdeppkg, sc);
     556           0 :                 aml_freevalue(&res);
     557           0 :         }
     558             : 
     559           0 :         return (0);
     560           0 : }
     561             : 
     562             : /*
     563             :  * old-style fixed C-state info in the FADT.
     564             :  * Note that this has extra restrictions on values and flags.
     565             :  */
     566             : void
     567           0 : acpicpu_getcst_from_fadt(struct acpicpu_softc *sc)
     568             : {
     569           0 :         struct acpi_fadt        *fadt = sc->sc_acpi->sc_fadt;
     570             :         int flags;
     571             : 
     572             :         /* FADT has to set flag to do C2 and higher on MP */
     573           0 :         if ((fadt->flags & FADT_P_LVL2_UP) == 0 && ncpus > 1)
     574           0 :                 return;
     575             : 
     576             :         /* skip these C2 and C3 states if the CPU doesn't have ARAT */
     577           0 :         flags = (sc->sc_ci->ci_feature_tpmflags & TPM_ARAT)
     578             :             ? 0 : CST_FLAG_SKIP;
     579             : 
     580             :         /* Some systems don't export a full PBLK; reduce functionality */
     581           0 :         if (sc->sc_pblk_len >= 5 && fadt->p_lvl2_lat <= ACPI_MAX_C2_LATENCY) {
     582           0 :                 acpicpu_add_cstate(sc, ACPI_STATE_C2, CST_METH_GAS_IO, flags,
     583           0 :                     fadt->p_lvl2_lat, -1, sc->sc_pblk_addr + 4);
     584           0 :         }
     585           0 :         if (sc->sc_pblk_len >= 6 && fadt->p_lvl3_lat <= ACPI_MAX_C3_LATENCY)
     586           0 :                 acpicpu_add_cstate(sc, ACPI_STATE_C3, CST_METH_GAS_IO, flags,
     587           0 :                     fadt->p_lvl3_lat, -1, sc->sc_pblk_addr + 5);
     588           0 : }
     589             : 
     590             : 
     591             : void
     592           0 : acpicpu_print_one_cst(struct acpi_cstate *cx)
     593             : {
     594             :         const char *meth = "";
     595             :         int show_addr = 0;
     596             : 
     597           0 :         switch (cx->method) {
     598             :         case CST_METH_IO_HALT:
     599           0 :                 show_addr = 1;
     600             :                 /* fallthrough */
     601             :         case CST_METH_HALT:
     602             :                 meth = " halt";
     603           0 :                 break;
     604             : 
     605             :         case CST_METH_MWAIT:
     606             :                 meth = " mwait";
     607           0 :                 show_addr = cx->address != 0;
     608           0 :                 break;
     609             : 
     610             :         case CST_METH_GAS_IO:
     611             :                 meth = " io";
     612             :                 show_addr = 1;
     613           0 :                 break;
     614             : 
     615             :         }
     616             : 
     617           0 :         printf(" %sC%d(", (cx->flags & CST_FLAG_SKIP ? "!" : ""), cx->state);
     618           0 :         if (cx->power != -1)
     619           0 :                 printf("%d", cx->power);
     620           0 :         printf("@%d%s", cx->latency, meth);
     621           0 :         if (cx->flags & ~CST_FLAG_SKIP) {
     622           0 :                 if (cx->flags & CST_FLAG_FALLBACK)
     623           0 :                         printf("!");
     624             :                 else
     625           0 :                         printf(".%x", (cx->flags & ~CST_FLAG_SKIP));
     626             :         }
     627           0 :         if (show_addr)
     628           0 :                 printf("@0x%llx", cx->address);
     629           0 :         printf(")");
     630           0 : }
     631             : 
     632             : void
     633           0 : acpicpu_print_cst(struct acpicpu_softc *sc)
     634             : {
     635             :         struct acpi_cstate      *cx;
     636             :         int i;
     637             : 
     638           0 :         if (!SLIST_EMPTY(&sc->sc_cstates)) {
     639           0 :                 printf(":");
     640             : 
     641             :                 i = 0;
     642           0 :                 SLIST_FOREACH(cx, &sc->sc_cstates, link) {
     643           0 :                         if (i++)
     644           0 :                                 printf(",");
     645           0 :                         acpicpu_print_one_cst(cx);
     646             :                 }
     647             :         }
     648           0 : }
     649             : 
     650             : 
     651             : int
     652           0 : acpicpu_match(struct device *parent, void *match, void *aux)
     653             : {
     654           0 :         struct acpi_attach_args *aa = aux;
     655           0 :         struct cfdata           *cf = match;
     656             : 
     657             :         /* sanity */
     658           0 :         if (aa->aaa_name == NULL ||
     659           0 :             strcmp(aa->aaa_name, cf->cf_driver->cd_name) != 0 ||
     660           0 :             aa->aaa_table != NULL)
     661           0 :                 return (0);
     662             : 
     663           0 :         return (1);
     664           0 : }
     665             : 
     666             : void
     667           0 : acpicpu_attach(struct device *parent, struct device *self, void *aux)
     668             : {
     669           0 :         struct acpicpu_softc    *sc = (struct acpicpu_softc *)self;
     670           0 :         struct acpi_attach_args *aa = aux;
     671           0 :         struct aml_value        res;
     672             :         int                     i;
     673           0 :         uint32_t                status = 0;
     674             :         CPU_INFO_ITERATOR       cii;
     675             :         struct cpu_info         *ci;
     676             : 
     677           0 :         sc->sc_acpi = (struct acpi_softc *)parent;
     678           0 :         sc->sc_devnode = aa->aaa_node;
     679           0 :         acpicpu_sc[sc->sc_dev.dv_unit] = sc;
     680             : 
     681           0 :         SLIST_INIT(&sc->sc_cstates);
     682             : 
     683           0 :         if (aml_evalnode(sc->sc_acpi, sc->sc_devnode, 0, NULL, &res) == 0) {
     684           0 :                 if (res.type == AML_OBJTYPE_PROCESSOR) {
     685           0 :                         sc->sc_cpu = res.v_processor.proc_id;
     686           0 :                         sc->sc_pblk_addr = res.v_processor.proc_addr;
     687           0 :                         sc->sc_pblk_len = res.v_processor.proc_len;
     688           0 :                 }
     689           0 :                 aml_freevalue(&res);
     690           0 :         }
     691           0 :         sc->sc_duty_off = sc->sc_acpi->sc_fadt->duty_offset;
     692           0 :         sc->sc_duty_wid = sc->sc_acpi->sc_fadt->duty_width;
     693             : 
     694             :         /* link in the matching cpu_info */
     695           0 :         CPU_INFO_FOREACH(cii, ci)
     696           0 :                 if (ci->ci_acpi_proc_id == sc->sc_cpu) {
     697           0 :                         ci->ci_acpicpudev = self;
     698           0 :                         sc->sc_ci = ci;
     699           0 :                         break;
     700             :                 }
     701           0 :         if (ci == NULL) {
     702           0 :                 printf(": no cpu matching ACPI ID %d\n", sc->sc_cpu);
     703           0 :                 return;
     704             :         }
     705             : 
     706           0 :         sc->sc_prev_sleep = 1000000;
     707             : 
     708           0 :         acpicpu_set_pdc(sc);
     709             : 
     710           0 :         if (!valid_throttle(sc->sc_duty_off, sc->sc_duty_wid, sc->sc_pblk_addr))
     711           0 :                 sc->sc_flags |= FLAGS_NOTHROTTLE;
     712             : #ifdef ACPI_DEBUG
     713             :         printf(": %s: ", sc->sc_devnode->name);
     714             :         printf("\n: hdr:%x pblk:%x,%x duty:%x,%x pstate:%x "
     715             :                "(%ld throttling states)\n", sc->sc_acpi->sc_fadt->hdr_revision,
     716             :                 sc->sc_pblk_addr, sc->sc_pblk_len, sc->sc_duty_off,
     717             :                 sc->sc_duty_wid, sc->sc_acpi->sc_fadt->pstate_cnt,
     718             :                 CPU_MAXSTATE(sc));
     719             : #endif
     720             : 
     721             :         /* Get C-States from _CST or FADT */
     722           0 :         if (acpicpu_getcst(sc) || SLIST_EMPTY(&sc->sc_cstates))
     723           0 :                 acpicpu_getcst_from_fadt(sc);
     724             :         else {
     725             :                 /* Notify BIOS we use _CST objects */
     726           0 :                 if (sc->sc_acpi->sc_fadt->cst_cnt) {
     727           0 :                         acpi_write_pmreg(sc->sc_acpi, ACPIREG_SMICMD, 0,
     728           0 :                             sc->sc_acpi->sc_fadt->cst_cnt);
     729           0 :                 }
     730             :         }
     731           0 :         if (!SLIST_EMPTY(&sc->sc_cstates)) {
     732             :                 extern uint32_t acpi_force_bm;
     733             : 
     734           0 :                 cpu_idle_cycle_fcn = &acpicpu_idle;
     735             : 
     736             :                 /*
     737             :                  * C3 (and maybe C2?) needs BM_RLD to be set to
     738             :                  * wake the system
     739             :                  */
     740           0 :                 if (SLIST_FIRST(&sc->sc_cstates)->state > 1 && acpi_force_bm == 0) {
     741           0 :                         uint16_t en = acpi_read_pmreg(sc->sc_acpi,
     742             :                             ACPIREG_PM1_CNT, 0);
     743           0 :                         if ((en & ACPI_PM1_BM_RLD) == 0) {
     744           0 :                                 acpi_write_pmreg(sc->sc_acpi, ACPIREG_PM1_CNT,
     745           0 :                                     0, en | ACPI_PM1_BM_RLD);
     746           0 :                                 acpi_force_bm = ACPI_PM1_BM_RLD;
     747           0 :                         }
     748           0 :                 }
     749             :         }
     750             : 
     751           0 :         if (acpicpu_getpss(sc)) {
     752           0 :                 sc->sc_flags |= FLAGS_NOPSS;
     753           0 :         } else {
     754             : #ifdef ACPI_DEBUG
     755             :                 for (i = 0; i < sc->sc_pss_len; i++) {
     756             :                         dnprintf(20, "%d %d %d %d %d %d\n",
     757             :                             sc->sc_pss[i].pss_core_freq,
     758             :                             sc->sc_pss[i].pss_power,
     759             :                             sc->sc_pss[i].pss_trans_latency,
     760             :                             sc->sc_pss[i].pss_bus_latency,
     761             :                             sc->sc_pss[i].pss_ctrl,
     762             :                             sc->sc_pss[i].pss_status);
     763             :                 }
     764             :                 dnprintf(20, "\n");
     765             : #endif
     766           0 :                 if (sc->sc_pss_len == 0) {
     767             :                         /* this should never happen */
     768           0 :                         printf("%s: invalid _PSS length\n", DEVNAME(sc));
     769           0 :                         sc->sc_flags |= FLAGS_NOPSS;
     770           0 :                 }
     771             : 
     772           0 :                 acpicpu_getppc(sc);
     773           0 :                 if (acpicpu_getpct(sc))
     774           0 :                         sc->sc_flags |= FLAGS_NOPCT;
     775           0 :                 else if (sc->sc_pss_len > 0) {
     776             :                         /* Notify BIOS we are handling p-states */
     777           0 :                         if (sc->sc_acpi->sc_fadt->pstate_cnt) {
     778           0 :                                 acpi_write_pmreg(sc->sc_acpi, ACPIREG_SMICMD,
     779           0 :                                     0, sc->sc_acpi->sc_fadt->pstate_cnt);
     780           0 :                         }
     781             : 
     782           0 :                         aml_register_notify(sc->sc_devnode, NULL,
     783           0 :                             acpicpu_notify, sc, ACPIDEV_NOPOLL);
     784             : 
     785           0 :                         acpi_gasio(sc->sc_acpi, ACPI_IOREAD,
     786           0 :                             sc->sc_pct.pct_status.grd_gas.address_space_id,
     787           0 :                             sc->sc_pct.pct_status.grd_gas.address,
     788           0 :                             sc->sc_pct_stat_as, sc->sc_pct_stat_as, &status);
     789           0 :                         sc->sc_level = (100 / sc->sc_pss_len) *
     790           0 :                             (sc->sc_pss_len - status);
     791             :                         dnprintf(20, "%s: cpu index %d, percentage %d\n",
     792             :                             DEVNAME(sc), status, sc->sc_level);
     793           0 :                         if (setperf_prio < 30) {
     794           0 :                                 cpu_setperf = acpicpu_setperf;
     795           0 :                                 acpicpu_set_notify(acpicpu_setperf_ppc_change);
     796           0 :                                 setperf_prio = 30;
     797           0 :                                 acpi_hasprocfvs = 1;
     798           0 :                         }
     799             :                 }
     800             :         }
     801             : 
     802             :         /*
     803             :          * Nicely enumerate what power management capabilities
     804             :          * ACPI CPU provides.
     805             :          */
     806           0 :         acpicpu_print_cst(sc);
     807           0 :         if (!(sc->sc_flags & (FLAGS_NOPSS | FLAGS_NOPCT)) ||
     808           0 :             !(sc->sc_flags & FLAGS_NOPSS)) {
     809           0 :                 printf("%c ", SLIST_EMPTY(&sc->sc_cstates) ? ':' : ',');
     810             : 
     811             :                 /*
     812             :                  * If acpicpu is itself providing the capability to transition
     813             :                  * states, enumerate them in the fashion that est and powernow
     814             :                  * would.
     815             :                  */
     816           0 :                 if (!(sc->sc_flags & (FLAGS_NOPSS | FLAGS_NOPCT))) {
     817           0 :                         printf("FVS, ");
     818           0 :                         for (i = 0; i < sc->sc_pss_len - 1; i++)
     819           0 :                                 printf("%d, ", sc->sc_pss[i].pss_core_freq);
     820           0 :                         printf("%d MHz", sc->sc_pss[i].pss_core_freq);
     821           0 :                 } else
     822           0 :                         printf("PSS");
     823             :         }
     824             : 
     825           0 :         printf("\n");
     826           0 : }
     827             : 
     828             : int
     829           0 : acpicpu_getppc(struct acpicpu_softc *sc)
     830             : {
     831           0 :         struct aml_value        res;
     832             : 
     833           0 :         sc->sc_ppc = 0;
     834             : 
     835           0 :         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PPC", 0, NULL, &res)) {
     836             :                 dnprintf(10, "%s: no _PPC\n", DEVNAME(sc));
     837           0 :                 return (1);
     838             :         }
     839             : 
     840           0 :         sc->sc_ppc = aml_val2int(&res);
     841             :         dnprintf(10, "%s: _PPC: %d\n", DEVNAME(sc), sc->sc_ppc);
     842           0 :         aml_freevalue(&res);
     843             : 
     844           0 :         return (0);
     845           0 : }
     846             : 
     847             : int
     848           0 : acpicpu_getpct(struct acpicpu_softc *sc)
     849             : {
     850           0 :         struct aml_value        res;
     851             :         int                     rv = 1;
     852             : 
     853           0 :         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PCT", 0, NULL, &res)) {
     854             :                 dnprintf(20, "%s: no _PCT\n", DEVNAME(sc));
     855           0 :                 return (1);
     856             :         }
     857             : 
     858           0 :         if (res.length != 2) {
     859             :                 dnprintf(20, "%s: %s: invalid _PCT length\n", DEVNAME(sc),
     860             :                     sc->sc_devnode->name);
     861           0 :                 return (1);
     862             :         }
     863             : 
     864           0 :         memcpy(&sc->sc_pct.pct_ctrl, res.v_package[0]->v_buffer,
     865             :             sizeof sc->sc_pct.pct_ctrl);
     866           0 :         if (sc->sc_pct.pct_ctrl.grd_gas.address_space_id ==
     867             :             GAS_FUNCTIONAL_FIXED) {
     868             :                 dnprintf(20, "CTRL GASIO is functional fixed hardware.\n");
     869             :                 goto ffh;
     870             :         }
     871             : 
     872           0 :         memcpy(&sc->sc_pct.pct_status, res.v_package[1]->v_buffer,
     873             :             sizeof sc->sc_pct.pct_status);
     874           0 :         if (sc->sc_pct.pct_status.grd_gas.address_space_id ==
     875             :             GAS_FUNCTIONAL_FIXED) {
     876             :                 dnprintf(20, "CTRL GASIO is functional fixed hardware.\n");
     877             :                 goto ffh;
     878             :         }
     879             : 
     880             :         dnprintf(10, "_PCT(ctrl)  : %02x %04x %02x %02x %02x %02x %016llx\n",
     881             :             sc->sc_pct.pct_ctrl.grd_descriptor,
     882             :             sc->sc_pct.pct_ctrl.grd_length,
     883             :             sc->sc_pct.pct_ctrl.grd_gas.address_space_id,
     884             :             sc->sc_pct.pct_ctrl.grd_gas.register_bit_width,
     885             :             sc->sc_pct.pct_ctrl.grd_gas.register_bit_offset,
     886             :             sc->sc_pct.pct_ctrl.grd_gas.access_size,
     887             :             sc->sc_pct.pct_ctrl.grd_gas.address);
     888             : 
     889             :         dnprintf(10, "_PCT(status): %02x %04x %02x %02x %02x %02x %016llx\n",
     890             :             sc->sc_pct.pct_status.grd_descriptor,
     891             :             sc->sc_pct.pct_status.grd_length,
     892             :             sc->sc_pct.pct_status.grd_gas.address_space_id,
     893             :             sc->sc_pct.pct_status.grd_gas.register_bit_width,
     894             :             sc->sc_pct.pct_status.grd_gas.register_bit_offset,
     895             :             sc->sc_pct.pct_status.grd_gas.access_size,
     896             :             sc->sc_pct.pct_status.grd_gas.address);
     897             : 
     898             :         /* if not set assume single 32 bit access */
     899           0 :         sc->sc_pct_stat_as = sc->sc_pct.pct_status.grd_gas.register_bit_width
     900           0 :             / 8;
     901           0 :         if (sc->sc_pct_stat_as == 0)
     902           0 :                 sc->sc_pct_stat_as = 4;
     903           0 :         sc->sc_pct_ctrl_as = sc->sc_pct.pct_ctrl.grd_gas.register_bit_width / 8;
     904           0 :         if (sc->sc_pct_ctrl_as == 0)
     905           0 :                 sc->sc_pct_ctrl_as = 4;
     906           0 :         sc->sc_pct_stat_len = sc->sc_pct.pct_status.grd_gas.access_size;
     907           0 :         if (sc->sc_pct_stat_len == 0)
     908           0 :                 sc->sc_pct_stat_len = sc->sc_pct_stat_as;
     909           0 :         sc->sc_pct_ctrl_len = sc->sc_pct.pct_ctrl.grd_gas.access_size;
     910           0 :         if (sc->sc_pct_ctrl_len == 0)
     911           0 :                 sc->sc_pct_ctrl_len = sc->sc_pct_ctrl_as;
     912             : 
     913           0 :         rv = 0;
     914             : ffh:
     915           0 :         aml_freevalue(&res);
     916           0 :         return (rv);
     917           0 : }
     918             : 
     919             : int
     920           0 : acpicpu_getpss(struct acpicpu_softc *sc)
     921             : {
     922           0 :         struct aml_value        res;
     923             :         int                     i, c, cf;
     924             : 
     925           0 :         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PSS", 0, NULL, &res)) {
     926             :                 dprintf("%s: no _PSS\n", DEVNAME(sc));
     927           0 :                 return (1);
     928             :         }
     929             : 
     930           0 :         free(sc->sc_pss, M_DEVBUF, sc->sc_pssfulllen);
     931             : 
     932           0 :         sc->sc_pss = mallocarray(res.length, sizeof(*sc->sc_pss), M_DEVBUF,
     933             :             M_WAITOK | M_ZERO);
     934           0 :         sc->sc_pssfulllen = res.length * sizeof(*sc->sc_pss);
     935             : 
     936             :         c = 0;
     937           0 :         for (i = 0; i < res.length; i++) {
     938           0 :                 cf = aml_val2int(res.v_package[i]->v_package[0]);
     939             : 
     940             :                 /* This heuristic comes from FreeBSDs
     941             :                  * dev/acpica/acpi_perf.c to weed out invalid PSS entries.
     942             :                  */
     943           0 :                 if (cf == sc->sc_pss[c].pss_core_freq) {
     944           0 :                         printf("%s: struck PSS entry, core frequency equals "
     945           0 :                             " last\n", sc->sc_dev.dv_xname);
     946           0 :                         continue;
     947             :                 }
     948             : 
     949           0 :                 if (cf == 0xFFFF || cf == 0x9999 || cf == 99999 || cf == 0) {
     950           0 :                         printf("%s: struck PSS entry, inappropriate core "
     951           0 :                             "frequency value\n", sc->sc_dev.dv_xname);
     952           0 :                         continue;
     953             :                 }
     954             : 
     955           0 :                 sc->sc_pss[c].pss_core_freq = cf;
     956           0 :                 sc->sc_pss[c].pss_power = aml_val2int(
     957           0 :                     res.v_package[i]->v_package[1]);
     958           0 :                 sc->sc_pss[c].pss_trans_latency = aml_val2int(
     959           0 :                     res.v_package[i]->v_package[2]);
     960           0 :                 sc->sc_pss[c].pss_bus_latency = aml_val2int(
     961           0 :                     res.v_package[i]->v_package[3]);
     962           0 :                 sc->sc_pss[c].pss_ctrl = aml_val2int(
     963           0 :                     res.v_package[i]->v_package[4]);
     964           0 :                 sc->sc_pss[c].pss_status = aml_val2int(
     965           0 :                     res.v_package[i]->v_package[5]);
     966           0 :                 c++;
     967           0 :         }
     968           0 :         sc->sc_pss_len = c;
     969             : 
     970           0 :         aml_freevalue(&res);
     971             : 
     972           0 :         return (0);
     973           0 : }
     974             : 
     975             : int
     976           0 : acpicpu_fetch_pss(struct acpicpu_pss **pss)
     977             : {
     978             :         struct acpicpu_softc    *sc;
     979             : 
     980             :         /*
     981             :          * XXX: According to the ACPI spec in an SMP system all processors
     982             :          * are supposed to support the same states. For now we pray
     983             :          * the bios ensures this...
     984             :          */
     985             : 
     986           0 :         sc = acpicpu_sc[0];
     987           0 :         if (!sc)
     988           0 :                 return 0;
     989           0 :         *pss = sc->sc_pss;
     990             : 
     991           0 :         return (sc->sc_pss_len);
     992           0 : }
     993             : 
     994             : int
     995           0 : acpicpu_notify(struct aml_node *node, int notify_type, void *arg)
     996             : {
     997           0 :         struct acpicpu_softc    *sc = arg;
     998             : 
     999             :         dnprintf(10, "acpicpu_notify: %.2x %s\n", notify_type,
    1000             :             sc->sc_devnode->name);
    1001             : 
    1002           0 :         switch (notify_type) {
    1003             :         case 0x80:      /* _PPC changed, retrieve new values */
    1004           0 :                 acpicpu_getppc(sc);
    1005           0 :                 acpicpu_getpss(sc);
    1006           0 :                 if (sc->sc_notify)
    1007           0 :                         sc->sc_notify(sc->sc_pss, sc->sc_pss_len);
    1008             :                 break;
    1009             : 
    1010             :         case 0x81:      /* _CST changed, retrieve new values */
    1011           0 :                 acpicpu_getcst(sc);
    1012           0 :                 printf("%s: notify", DEVNAME(sc));
    1013           0 :                 acpicpu_print_cst(sc);
    1014           0 :                 printf("\n");
    1015           0 :                 break;
    1016             : 
    1017             :         default:
    1018           0 :                 printf("%s: unhandled cpu event %x\n", DEVNAME(sc),
    1019             :                     notify_type);
    1020           0 :                 break;
    1021             :         }
    1022             : 
    1023           0 :         return (0);
    1024             : }
    1025             : 
    1026             : void
    1027           0 : acpicpu_set_notify(void (*func)(struct acpicpu_pss *, int))
    1028             : {
    1029             :         struct acpicpu_softc    *sc;
    1030             : 
    1031           0 :         sc = acpicpu_sc[0];
    1032           0 :         if (sc != NULL)
    1033           0 :                 sc->sc_notify = func;
    1034           0 : }
    1035             : 
    1036             : void
    1037           0 : acpicpu_setperf_ppc_change(struct acpicpu_pss *pss, int npss)
    1038             : {
    1039             :         struct acpicpu_softc    *sc;
    1040             : 
    1041           0 :         sc = acpicpu_sc[0];
    1042             : 
    1043           0 :         if (sc != NULL)
    1044           0 :                 cpu_setperf(sc->sc_level);
    1045           0 : }
    1046             : 
    1047             : void
    1048           0 : acpicpu_setperf(int level)
    1049             : {
    1050             :         struct acpicpu_softc    *sc;
    1051             :         struct acpicpu_pss      *pss = NULL;
    1052             :         int                     idx, len;
    1053           0 :         uint32_t                status = 0;
    1054             : 
    1055           0 :         sc = acpicpu_sc[cpu_number()];
    1056             : 
    1057             :         dnprintf(10, "%s: acpicpu setperf level %d\n",
    1058             :             sc->sc_devnode->name, level);
    1059             : 
    1060           0 :         if (level < 0 || level > 100) {
    1061             :                 dnprintf(10, "%s: acpicpu setperf illegal percentage\n",
    1062             :                     sc->sc_devnode->name);
    1063           0 :                 return;
    1064             :         }
    1065             : 
    1066             :         /*
    1067             :          * XXX this should be handled more gracefully and it needs to also do
    1068             :          * the duty cycle method instead of pss exclusively
    1069             :          */
    1070           0 :         if (sc->sc_flags & FLAGS_NOPSS || sc->sc_flags & FLAGS_NOPCT) {
    1071             :                 dnprintf(10, "%s: acpicpu no _PSS or _PCT\n",
    1072             :                     sc->sc_devnode->name);
    1073           0 :                 return;
    1074             :         }
    1075             : 
    1076           0 :         if (sc->sc_ppc)
    1077           0 :                 len = sc->sc_ppc;
    1078             :         else
    1079           0 :                 len = sc->sc_pss_len;
    1080           0 :         idx = (len - 1) - (level / (100 / len));
    1081           0 :         if (idx < 0)
    1082             :                 idx = 0;
    1083             : 
    1084           0 :         if (sc->sc_ppc)
    1085           0 :                 idx += sc->sc_pss_len - sc->sc_ppc;
    1086             : 
    1087           0 :         if (idx > sc->sc_pss_len)
    1088           0 :                 idx = sc->sc_pss_len - 1;
    1089             : 
    1090             :         dnprintf(10, "%s: acpicpu setperf index %d pss_len %d ppc %d\n",
    1091             :             sc->sc_devnode->name, idx, sc->sc_pss_len, sc->sc_ppc);
    1092             : 
    1093           0 :         pss = &sc->sc_pss[idx];
    1094             : 
    1095             : #ifdef ACPI_DEBUG
    1096             :         /* keep this for now since we will need this for debug in the field */
    1097             :         printf("0 status: %x %llx %u %u ctrl: %x %llx %u %u\n",
    1098             :             sc->sc_pct.pct_status.grd_gas.address_space_id,
    1099             :             sc->sc_pct.pct_status.grd_gas.address,
    1100             :             sc->sc_pct_stat_as, sc->sc_pct_stat_len,
    1101             :             sc->sc_pct.pct_ctrl.grd_gas.address_space_id,
    1102             :             sc->sc_pct.pct_ctrl.grd_gas.address,
    1103             :             sc->sc_pct_ctrl_as, sc->sc_pct_ctrl_len);
    1104             : #endif
    1105           0 :         acpi_gasio(sc->sc_acpi, ACPI_IOREAD,
    1106           0 :             sc->sc_pct.pct_status.grd_gas.address_space_id,
    1107           0 :             sc->sc_pct.pct_status.grd_gas.address, sc->sc_pct_stat_as,
    1108           0 :             sc->sc_pct_stat_len, &status);
    1109             :         dnprintf(20, "1 status: %u <- %u\n", status, pss->pss_status);
    1110             : 
    1111             :         /* Are we already at the requested frequency? */
    1112           0 :         if (status == pss->pss_status)
    1113           0 :                 return;
    1114             : 
    1115           0 :         acpi_gasio(sc->sc_acpi, ACPI_IOWRITE,
    1116           0 :             sc->sc_pct.pct_ctrl.grd_gas.address_space_id,
    1117           0 :             sc->sc_pct.pct_ctrl.grd_gas.address, sc->sc_pct_ctrl_as,
    1118           0 :             sc->sc_pct_ctrl_len, &pss->pss_ctrl);
    1119             :         dnprintf(20, "pss_ctrl: %x\n", pss->pss_ctrl);
    1120             : 
    1121           0 :         acpi_gasio(sc->sc_acpi, ACPI_IOREAD,
    1122           0 :             sc->sc_pct.pct_status.grd_gas.address_space_id,
    1123           0 :             sc->sc_pct.pct_status.grd_gas.address, sc->sc_pct_stat_as,
    1124             :             sc->sc_pct_stat_as, &status);
    1125             :         dnprintf(20, "2 status: %d\n", status);
    1126             : 
    1127             :         /* Did the transition succeed? */
    1128           0 :          if (status == pss->pss_status) {
    1129           0 :                 cpuspeed = pss->pss_core_freq;
    1130           0 :                 sc->sc_level = level;
    1131           0 :         } else
    1132           0 :                 printf("%s: acpicpu setperf failed to alter frequency\n",
    1133           0 :                     sc->sc_devnode->name);
    1134           0 : }
    1135             : 
    1136             : void
    1137           0 : acpicpu_idle(void)
    1138             : {
    1139           0 :         struct cpu_info *ci = curcpu();
    1140           0 :         struct acpicpu_softc *sc = (struct acpicpu_softc *)ci->ci_acpicpudev;
    1141             :         struct acpi_cstate *best, *cx;
    1142             :         unsigned long itime;
    1143             : 
    1144           0 :         if (sc == NULL) {
    1145           0 :                 __asm volatile("sti");
    1146           0 :                 panic("null acpicpu");
    1147             :         }
    1148             : 
    1149             :         /* possibly update the MWAIT_ONLY flag in cpu_info */
    1150           0 :         if (sc->sc_flags & FLAGS_MWAIT_ONLY) {
    1151           0 :                 if ((ci->ci_mwait & MWAIT_ONLY) == 0)
    1152           0 :                         atomic_setbits_int(&ci->ci_mwait, MWAIT_ONLY);
    1153           0 :         } else if (ci->ci_mwait & MWAIT_ONLY)
    1154           0 :                 atomic_clearbits_int(&ci->ci_mwait, MWAIT_ONLY);
    1155             : 
    1156             :         /*
    1157             :          * Find the first state with a latency we'll accept, ignoring
    1158             :          * states marked skippable
    1159             :          */
    1160           0 :         best = cx = SLIST_FIRST(&sc->sc_cstates);
    1161           0 :         while ((cx->flags & CST_FLAG_SKIP) ||
    1162           0 :             cx->latency * 3 > sc->sc_prev_sleep) {
    1163           0 :                 if ((cx = SLIST_NEXT(cx, link)) == NULL)
    1164             :                         break;
    1165             :                 best = cx;
    1166             :         }
    1167             : 
    1168           0 :         if (best->state >= 3 &&
    1169           0 :             (best->flags & CST_FLAG_MWAIT_BM_AVOIDANCE) &&
    1170           0 :             acpi_read_pmreg(acpi_softc, ACPIREG_PM1_STS, 0) & ACPI_PM1_BM_STS) {
    1171             :                 /* clear it and back off */
    1172           0 :                 acpi_write_pmreg(acpi_softc, ACPIREG_PM1_STS, 0,
    1173             :                     ACPI_PM1_BM_STS);
    1174           0 :                 while ((cx = SLIST_NEXT(cx, link)) != NULL) {
    1175           0 :                         if (cx->flags & CST_FLAG_SKIP)
    1176           0 :                                 continue;
    1177           0 :                         if (cx->state < 3 ||
    1178           0 :                             (cx->flags & CST_FLAG_MWAIT_BM_AVOIDANCE) == 0)
    1179             :                                 break;
    1180             :                 }
    1181             :                 best = cx;
    1182           0 :         }
    1183             : 
    1184             : 
    1185           0 :         atomic_inc_long(&cst_stats[best->state]);
    1186             : 
    1187           0 :         itime = tick / 2;
    1188           0 :         switch (best->method) {
    1189             :         default:
    1190             :         case CST_METH_HALT:
    1191           0 :                 __asm volatile("sti; hlt");
    1192           0 :                 break;
    1193             : 
    1194             :         case CST_METH_IO_HALT:
    1195           0 :                 inb((u_short)best->address);
    1196           0 :                 __asm volatile("sti; hlt");
    1197           0 :                 break;
    1198             : 
    1199             :         case CST_METH_MWAIT:
    1200             :                 {
    1201           0 :                 struct timeval start, stop;
    1202             :                 unsigned int hints;
    1203             : 
    1204             : #ifdef __LP64__
    1205           0 :                 if ((read_rflags() & PSL_I) == 0)
    1206           0 :                         panic("idle with interrupts blocked!");
    1207             : #else
    1208             :                 if ((read_eflags() & PSL_I) == 0)
    1209             :                         panic("idle with interrupts blocked!");
    1210             : #endif
    1211             : 
    1212             :                 /* something already queued? */
    1213           0 :                 if (!cpu_is_idle(ci))
    1214           0 :                         return;
    1215             : 
    1216             :                 /*
    1217             :                  * About to idle; setting the MWAIT_IN_IDLE bit tells
    1218             :                  * cpu_unidle() that it can't be a no-op and tells cpu_kick()
    1219             :                  * that it doesn't need to use an IPI.  We also set the
    1220             :                  * MWAIT_KEEP_IDLING bit: those routines clear it to stop
    1221             :                  * the mwait.  Once they're set, we do a final check of the
    1222             :                  * queue, in case another cpu called setrunqueue() and added
    1223             :                  * something to the queue and called cpu_unidle() between
    1224             :                  * the check in sched_idle() and here.
    1225             :                  */
    1226           0 :                 hints = (unsigned)best->address;
    1227           0 :                 microuptime(&start);
    1228           0 :                 atomic_setbits_int(&ci->ci_mwait, MWAIT_IDLING);
    1229           0 :                 if (cpu_is_idle(ci)) {
    1230             :                         /* intel errata AAI65: cflush before monitor */
    1231           0 :                         if (ci->ci_cflushsz != 0) {
    1232           0 :                                 membar_sync();
    1233           0 :                                 clflush((unsigned long)&ci->ci_mwait);
    1234           0 :                                 membar_sync();
    1235           0 :                         }
    1236             : 
    1237           0 :                         monitor(&ci->ci_mwait, 0, 0);
    1238           0 :                         if ((ci->ci_mwait & MWAIT_IDLING) == MWAIT_IDLING)
    1239           0 :                                 mwait(0, hints);
    1240             :                 }
    1241             : 
    1242           0 :                 microuptime(&stop);
    1243           0 :                 timersub(&stop, &start, &stop);
    1244           0 :                 itime = stop.tv_sec * 1000000 + stop.tv_usec;
    1245             : 
    1246             :                 /* done idling; let cpu_kick() know that an IPI is required */
    1247           0 :                 atomic_clearbits_int(&ci->ci_mwait, MWAIT_IDLING);
    1248           0 :                 break;
    1249           0 :                 }
    1250             : 
    1251             :         case CST_METH_GAS_IO:
    1252           0 :                 inb((u_short)best->address);
    1253             :                 /* something harmless to give system time to change state */
    1254           0 :                 acpi_read_pmreg(acpi_softc, ACPIREG_PM1_STS, 0);
    1255           0 :                 break;
    1256             : 
    1257             :         }
    1258             : 
    1259           0 :         sc->sc_last_itime = itime;
    1260           0 :         itime >>= 1;
    1261           0 :         sc->sc_prev_sleep = (sc->sc_prev_sleep + (sc->sc_prev_sleep >> 1)
    1262           0 :             + itime) >> 1;
    1263           0 : }

Generated by: LCOV version 1.13