? compile/GENERIC.MP.PROF ? compile/PROFILED.MP ? compile/WITNESS.MP ? conf/PROFILED.MP ? conf/WITNESS.MP Index: amd64/mainbus.c =================================================================== RCS file: /cvs/src/sys/arch/amd64/amd64/mainbus.c,v retrieving revision 1.51 diff -u -p -r1.51 mainbus.c --- amd64/mainbus.c 31 Aug 2021 15:52:59 -0000 1.51 +++ amd64/mainbus.c 22 Apr 2022 04:44:55 -0000 @@ -49,6 +49,7 @@ #include "bios.h" #include "mpbios.h" #include "vmm.h" +#include "msrs.h" #include "pvbus.h" #include "efifb.h" @@ -253,6 +254,13 @@ mainbus_attach(struct device *parent, st if (isa_has_been_seen == 0) config_found(self, &mba_iba, mainbus_print); #endif + +#if NMSRS > 0 + { + mba.mba_busname = "msrs"; + config_found(self, &mba.mba_busname, mainbus_print); + } +#endif /* NMSRS > 0 */ #if NVMM > 0 if (vmm_enabled()) { Index: amd64/msrs.c =================================================================== RCS file: amd64/msrs.c diff -N amd64/msrs.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ amd64/msrs.c 22 Apr 2022 04:44:55 -0000 @@ -0,0 +1,350 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2022 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "kstat.h" + +#if NKSTAT == 0 +#error msrs(4) requires kstat(4) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct msrs_kstats_thread { + struct kstat_kv mt_tsc; + struct kstat_kv mt_mperf; + struct kstat_kv mt_aperf; + struct kstat_kv mt_irperf; +}; + +struct msrs_kstats_core { + struct kstat_kv mc_energy; +}; + +struct msrs_kstats_pkg { + struct kstat_kv mp_energy; +}; + + +struct msrs_softc; + +struct msrs_link { + struct msrs_softc *l_sc; + struct cpu_info *l_ci; + struct kstat *l_ks; + TAILQ_ENTRY(msrs_link) l_entry; +}; + +TAILQ_HEAD(msrs_links, msrs_link); + +struct msrs_softc { + struct device sc_dev; + + struct msrs_links sc_threads; + struct msrs_links sc_cores; + struct msrs_links sc_pkgs; +}; + +static int msrs_match(struct device *, void *, void *); +static void msrs_attach(struct device *, struct device *, void *); + +struct cfdriver msrs_cd = { + NULL, "msrs", DV_DULL, CD_SKIPHIBERNATE +}; + +const struct cfattach msrs_ca = { + sizeof(struct msrs_softc), msrs_match, msrs_attach, NULL, NULL +}; + +static int msrs_link_cmp(struct msrs_links *, struct cpu_info *ci, + int (*)(struct cpu_info *, struct cpu_info *)); +static int msrs_link_cmp_core(struct cpu_info *, struct cpu_info *); +static int msrs_link_cmp_pkg(struct cpu_info *, struct cpu_info *); + +static struct kstat * + msrs_attach_thread(struct cpu_info *); +static struct kstat * + msrs_attach_core(struct cpu_info *); +static struct kstat * + msrs_attach_pkg(struct cpu_info *); + +#define msrs_core_exists(_sc, _ci) \ + msrs_link_cmp(&(_sc)->sc_cores, (_ci), msrs_link_cmp_core) + +#define msrs_pkg_exists(_sc, _ci) \ + msrs_link_cmp(&(_sc)->sc_pkgs, (_ci), msrs_link_cmp_pkg) + +static int +msrs_match(struct device *parent, void *match, void *aux) +{ + const char **busname = (const char **)aux; + + if (strcmp(*busname, msrs_cd.cd_name) != 0) + return (0); + + return (1); +} + +static void +msrs_attach(struct device *parent, struct device *self, void *aux) +{ + struct msrs_softc *sc = (struct msrs_softc *)self; + struct msrs_link *l; + struct cpu_info *ci; + CPU_INFO_ITERATOR cii; + + TAILQ_INIT(&sc->sc_threads); + TAILQ_INIT(&sc->sc_cores); + TAILQ_INIT(&sc->sc_pkgs); + + CPU_INFO_FOREACH(cii, ci) { + l = malloc(sizeof(*l), M_DEVBUF, M_WAITOK); + + l->l_sc = sc; + l->l_ci = ci; + l->l_ks = msrs_attach_thread(ci); + + TAILQ_INSERT_TAIL(&sc->sc_threads, l, l_entry); + + if (!msrs_core_exists(sc, ci)) { + l = malloc(sizeof(*l), M_DEVBUF, M_WAITOK); + + l->l_sc = sc; + l->l_ci = ci; + l->l_ks = msrs_attach_core(ci); + + TAILQ_INSERT_TAIL(&sc->sc_cores, l, l_entry); + } + + if (!msrs_pkg_exists(sc, ci)) { + l = malloc(sizeof(*l), M_DEVBUF, M_WAITOK); + + l->l_sc = sc; + l->l_ci = ci; + l->l_ks = msrs_attach_pkg(ci); + + TAILQ_INSERT_TAIL(&sc->sc_pkgs, l, l_entry); + } + } + + printf(": tsc, effperf, irperf, rapl\n"); +} + +static int +msrs_read_thread(struct kstat *ks) +{ + struct msrs_kstats_thread *mt = ks->ks_data; + unsigned long s; + + s = intr_disable(); + kstat_kv_u64(&mt->mt_tsc) = rdtsc_lfence(); + kstat_kv_u64(&mt->mt_mperf) = rdmsr(0xe7); + kstat_kv_u64(&mt->mt_aperf) = rdmsr(0xe8); + //kstat_kv_u64(&mt->mt_irperf) = rdmsr(0xe9); + intr_restore(s); + + nanouptime(&ks->ks_updated); + + return (0); +} + +static struct kstat * +msrs_attach_thread(struct cpu_info *ci) +{ + struct kstat *ks; + struct msrs_kstats_thread *mt; +#if 0 + uint32_t eax, ebx, ecx, edx; + + /* be conservative */ + if (strcmp(cpu_vendor, "GenuineIntel") != 0 && + strcmp(cpu_vendor, "AuthenticAMD") != 0) + return; + + CPUID(0x06, eax, ebx, ecx, edx); + if (!ISSET(ecx, 1U << 0)) + return; +#endif + + ks = kstat_create(msrs_cd.cd_name, 0, + "msrs-thread", ci->ci_dev->dv_unit, + KSTAT_T_KV, 0); + if (ks == NULL) { + /* XXX printf */ + return (NULL); + } + + kstat_set_cpu(ks, ci); + + mt = malloc(sizeof(*mt), M_DEVBUF, M_WAITOK|M_ZERO); + + kstat_kv_unit_init(&mt->mt_tsc, "tsc", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_CYCLES); + kstat_kv_unit_init(&mt->mt_mperf, "mperf", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_CYCLES); + kstat_kv_unit_init(&mt->mt_aperf, "aperf", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_CYCLES); + kstat_kv_unit_init(&mt->mt_irperf, "irperf", + KSTAT_KV_T_COUNTER64, KSTAT_KV_U_NONE); + + ks->ks_data = mt; + ks->ks_datalen = sizeof(*mt); + ks->ks_read = msrs_read_thread; + + kstat_install(ks); + + return (ks); +} + +static int +msrs_read_core(struct kstat *ks) +{ + struct msrs_kstats_core *mc = ks->ks_data; + kstat_kv_u64(&mc->mc_energy) = rdmsr(0xc001029a); + nanouptime(&ks->ks_updated); + return (0); +} + +static struct kstat * +msrs_attach_core(struct cpu_info *ci) +{ + struct kstat *ks; + struct msrs_kstats_core *mc; +#if 0 + uint32_t eax, ebx, ecx, edx; + + /* be conservative */ + if (strcmp(cpu_vendor, "GenuineIntel") != 0 && + strcmp(cpu_vendor, "AuthenticAMD") != 0) + return; + + CPUID(0x06, eax, ebx, ecx, edx); + if (!ISSET(ecx, 1U << 0)) + return; +#endif + + ks = kstat_create(msrs_cd.cd_name, 0, + "msrs-core", ci->ci_dev->dv_unit, + KSTAT_T_KV, 0); + if (ks == NULL) { + /* XXX printf */ + return (NULL); + } + + kstat_set_cpu(ks, ci); + + mc = malloc(sizeof(*mc), M_DEVBUF, M_WAITOK|M_ZERO); + + kstat_kv_init(&mc->mc_energy, "energy", KSTAT_KV_T_COUNTER32); + + ks->ks_data = mc; + ks->ks_datalen = sizeof(*mc); + ks->ks_read = msrs_read_core; + + kstat_install(ks); + + return (ks); +} + +int +msrs_read_pkg(struct kstat *ks) +{ + struct msrs_kstats_pkg *mp = ks->ks_data; + kstat_kv_u32(&mp->mp_energy) = rdmsr(0xc001029b); + nanouptime(&ks->ks_updated); + return (0); +} + +static struct kstat * +msrs_attach_pkg(struct cpu_info *ci) +{ + struct kstat *ks; + struct msrs_kstats_pkg *mp; +#if 0 + uint32_t eax, ebx, ecx, edx; + + /* be conservative */ + if (strcmp(cpu_vendor, "GenuineIntel") != 0 && + strcmp(cpu_vendor, "AuthenticAMD") != 0) + return; + + CPUID(0x06, eax, ebx, ecx, edx); + if (!ISSET(ecx, 1U << 0)) + return; +#endif + + ks = kstat_create(msrs_cd.cd_name, 0, + "msrs-pkg", ci->ci_dev->dv_unit, + KSTAT_T_KV, 0); + if (ks == NULL) { + /* XXX printf */ + return (NULL); + } + + kstat_set_cpu(ks, ci); + + mp = malloc(sizeof(*mp), M_DEVBUF, M_WAITOK|M_ZERO); + + kstat_kv_init(&mp->mp_energy, "energy", KSTAT_KV_T_COUNTER32); + + ks->ks_data = mp; + ks->ks_datalen = sizeof(*mp); + ks->ks_read = msrs_read_pkg; + + kstat_install(ks); + + return (ks); +} + +static int +msrs_link_cmp_core(struct cpu_info *a, struct cpu_info *b) +{ + return (a->ci_pkg_id == b->ci_pkg_id) && + (a->ci_core_id == b->ci_core_id); +} + +static int +msrs_link_cmp_pkg(struct cpu_info *a, struct cpu_info *b) +{ + return (a->ci_pkg_id == b->ci_pkg_id); +} + +static int +msrs_link_cmp(struct msrs_links *ls, struct cpu_info *ci, + int (*cmp)(struct cpu_info *, struct cpu_info *)) +{ + struct msrs_link *l; + + TAILQ_FOREACH(l, ls, l_entry) { + if ((*cmp)(l->l_ci, ci)) + return (1); + } + + return (0); +} Index: conf/GENERIC =================================================================== RCS file: /cvs/src/sys/arch/amd64/conf/GENERIC,v retrieving revision 1.510 diff -u -p -r1.510 GENERIC --- conf/GENERIC 4 Jan 2022 05:50:43 -0000 1.510 +++ conf/GENERIC 22 Apr 2022 04:44:56 -0000 @@ -34,6 +34,7 @@ isa0 at amdpcib? isa0 at tcpcib? pci* at mainbus0 vmm0 at mainbus0 +msrs0 at mainbus0 pvbus0 at mainbus0 acpi0 at bios0 Index: conf/files.amd64 =================================================================== RCS file: /cvs/src/sys/arch/amd64/conf/files.amd64,v retrieving revision 1.104 diff -u -p -r1.104 files.amd64 --- conf/files.amd64 7 Sep 2019 13:46:19 -0000 1.104 +++ conf/files.amd64 22 Apr 2022 04:44:56 -0000 @@ -250,6 +250,13 @@ file arch/amd64/amd64/vmm.c vmm needs file arch/amd64/amd64/vmm_support.S vmm # +# MSR kstats +# +device msrs {} +attach msrs at mainbus +file arch/amd64/amd64/msrs.c msrs needs-flag + +# # Machine-independent SD/MMC drivers # include "dev/sdmmc/files.sdmmc"