Subject: Re: Patches for EST and SMP
To: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
From: Juan RP <juan@xtrarom.org>
List: tech-kern
Date: 03/19/2007 18:54:01
--Boundary-00=_54s/Fyc9mzDyAmX
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
On Monday 19 March 2007, YAMAMOTO Takashi wrote:
> > x86_msr_runcount is 4 because my system has two CPUs and a write
> > operation (msr_cpu_broadcast_write()), issues two operations (write and
> > read):
>
> what's msr_cpu_broadcast_write?
>
> i'd suggest to attach patches to mails. not everyone read your
> mails immediately. posting urls and replacing actual files afterwards
> confused me at least.
I'll do that in the future. msr_cpu_broadcast_{read,write} are now a single
function: msr_cpu_broadcast with the READ or WRITE flag.
The patches attached are the latest versions with suggestions from Michael
Van Elst, using a memory barrier and making the globals volatile, plus
adding the member msr_mask in the msr_cpu_broadcast struct.
All MULTIPROCESSOR conditionals were removed and now there's no
difference, in the driver when we want to write the value we use these
functions.
--
http://plog.xtrarom.org/
Juan RP's blog - NetBSD/pkgsrc news in Spanish
--Boundary-00=_54s/Fyc9mzDyAmX
Content-Type: text/x-diff;
charset="iso-8859-1";
name="msr_ipi_handlers_mask.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="msr_ipi_handlers_mask.diff"
Index: x86/conf/files.x86
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/conf/files.x86,v
retrieving revision 1.26
diff -u -p -b -u -r1.26 files.x86
--- x86/conf/files.x86 15 Mar 2007 00:28:57 -0000 1.26
+++ x86/conf/files.x86 19 Mar 2007 03:58:56 -0000
@@ -13,6 +13,9 @@ defflag opt_pcifixup.h PCI_ADDR_FIXUP PC
# AMD Powernow/Cool`n'Quiet Technology
defflag opt_powernow_k8.h POWERNOW_K8
+# Pentium 4 and later models Thermal Monitor (On Demand Clock Modulation)
+defflag opt_pentium4_odcm.h PENTIUM4_ONDEMAND_CLOCKMOD
+
# VIA PadLock support
defflag opt_viapadlock.h VIA_PADLOCK: opencrypto
file arch/x86/x86/via_padlock.c via_padlock
@@ -31,6 +34,7 @@ file arch/x86/x86/i8259.c
file arch/x86/x86/intr.c
file arch/x86/x86/ipi.c multiprocessor
file arch/x86/x86/lock_machdep.c lockdebug
+file arch/x86/x86/msr_ipifuncs.c
file arch/x86/x86/mtrr_i686.c mtrr
file arch/x86/x86/patch.c
file arch/x86/x86/softintr.c
@@ -63,6 +67,8 @@ file arch/x86/pci/pciide_machdep.c pciid
file arch/x86/x86/powernow_k8.c powernow_k8
file arch/x86/x86/powernow_common.c powernow_k8 | powernow_k7
+file arch/x86/x86/p4tcc.c pentium4_ondemand_clockmod
+
#IPMI device
device ipmi : sysmon_envsys, sysmon_wdog
attach ipmi at ipmibus
Index: x86/include/cpu_msr.h
===================================================================
RCS file: x86/include/cpu_msr.h
diff -N x86/include/cpu_msr.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ x86/include/cpu_msr.h 19 Mar 2007 03:58:56 -0000
@@ -0,0 +1,65 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2007 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andrew Doran and Juan Romero Pardines.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _X86_CPU_MSR_H
+#define _X86_CPU_MSR_H
+
+#include <sys/param.h>
+#include <sys/mutex.h>
+#include <machine/intrdefs.h>
+#include <machine/cpu.h>
+
+#define MSR_CPU_BROADCAST_READ 0x0001
+#define MSR_CPU_BROADCAST_WRITE 0x0002
+
+struct msr_cpu_broadcast {
+ int msr_type;
+ uint64_t msr_value;
+ uint64_t msr_mask;
+};
+
+#ifdef _KERNEL
+void x86_init(void);
+void msr_read_ipi(struct cpu_info *);
+void msr_write_ipi(struct cpu_info *);
+void msr_cpu_broadcast_initmtx(void);
+int msr_cpu_broadcast_main(struct msr_cpu_broadcast *, int);
+int msr_cpu_broadcast(struct msr_cpu_broadcast *, int);
+#endif /* ! _KERNEL */
+
+#endif /* ! _X86_CPU_MSR_H */
Index: x86/include/intrdefs.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/intrdefs.h,v
retrieving revision 1.5
diff -u -p -b -u -r1.5 intrdefs.h
--- x86/include/intrdefs.h 3 Nov 2005 13:06:06 -0000 1.5
+++ x86/include/intrdefs.h 19 Mar 2007 03:58:56 -0000
@@ -81,12 +81,15 @@
#define X86_IPI_TLB 0x00000010
#define X86_IPI_MTRR 0x00000020
#define X86_IPI_GDT 0x00000040
+#define X86_IPI_READ_MSR 0x00000080
+#define X86_IPI_WRITE_MSR 0x00000100
-#define X86_NIPI 7
+#define X86_NIPI 9
#define X86_IPI_NAMES { "halt IPI", "timeset IPI", "FPU flush IPI", \
"FPU synch IPI", "TLB shootdown IPI", \
- "MTRR update IPI", "GDT update IPI" }
+ "MTRR update IPI", "GDT update IPI", \
+ "MSR read IPI", "MSR write IPI" }
#define IREENT_MAGIC 0x18041969
Index: x86/x86/msr_ipifuncs.c
===================================================================
RCS file: x86/x86/msr_ipifuncs.c
diff -N x86/x86/msr_ipifuncs.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ x86/x86/msr_ipifuncs.c 19 Mar 2007 03:58:56 -0000
@@ -0,0 +1,252 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2007 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Juan Romero Pardines.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Generic IPI handlers to handle reads and writes to a MSR on x86.
+ * Thanks to Andrew Doran, Michael Van Elst and Quentin Garnier for
+ * help and information provided.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/mutex.h>
+#include <sys/lock.h>
+
+#include <x86/cpu_msr.h>
+
+#include <machine/cpu.h>
+#include <machine/intrdefs.h>
+
+#define MSR_CPU_BROADCAST_DEBUG
+
+#ifdef MSR_CPU_BROADCAST_DEBUG
+#define DPRINTF(x) do { printf x; } while (/* CONSTCOND */ 0)
+#else
+#define DPRINTF(x)
+#endif
+
+static kmutex_t msr_mtx;
+static volatile uint64_t msr_setvalue;
+static volatile uint64_t msr_setmask;
+static volatile int msr_type;
+static volatile int msr_runcount;
+
+/*
+ * This function will read the value of the MSR defined in msr_type
+ * and will return it in ci_msr_rvalue (per-cpu), increasing the
+ * msr_runcount global counter atomically.
+ */
+void
+msr_read_ipi(struct cpu_info *ci)
+{
+ ci->ci_msr_rvalue = rdmsr(msr_type);
+ __asm volatile ("lock; incl (%0)" :: "r" (&msr_runcount));
+}
+
+/*
+ * This function will write the value of msr_setvalue in
+ * the MSR msr_type and if a mask is provided, the value will be
+ * masked with msr_setmask, also will update ci->ci_msr_rvalue with
+ * the returned value of the MSR (to avoid another run of msr_read_ipi).
+ */
+void
+msr_write_ipi(struct cpu_info *ci)
+{
+ volatile uint64_t msr;
+
+ /* Read the MSR requested and apply the mask if defined. */
+ msr = rdmsr(msr_type);
+ if (msr_setmask)
+ msr &= ~msr_setmask;
+
+ /* Ok, assign value now */
+ msr |= msr_setvalue;
+
+ /* Write it now */
+ wrmsr(msr_type, msr);
+
+ /* Increase counter atomically */
+ __asm volatile ("lock; incl (%0)" :: "r" (&msr_runcount));
+
+ /* Update our per-cpu returned value of the MSR now */
+ ci->ci_msr_rvalue = rdmsr(msr_type);
+}
+
+/*
+ * This function will return 0 on success and 1 in failure (if msr_type
+ * was not set). If mode is 1, it will do a write operation plus a read
+ * operation. If mode is 0, it will do a read operation.
+ * mcb->msr_type needs to be defined. It will pause with x86_pause() until
+ * the operation has been run in the cpu.
+ */
+int
+msr_cpu_broadcast_main(struct msr_cpu_broadcast *mcb, int mode)
+{
+ CPU_INFO_ITERATOR cii;
+ struct cpu_info *ci;
+
+ DPRINTF(("%s: mcb->msr_type=%d\n", __func__, mcb->msr_type));
+
+ /* sanity check */
+ if (!mcb->msr_type) {
+ DPRINTF(("%s: !msr_type\n", __func__));
+ return 1;
+ }
+
+ DPRINTF(("\n%s: ---- START ----\n", __func__));
+
+ /* We only want one CPU at a time sending these IPIs out. */
+ mutex_enter(&msr_mtx);
+
+ /* Initialize counter, the task has not run in any cpu yet */
+ msr_runcount = msr_setmask = msr_setvalue = 0;
+
+ /* Assign requested MSR type, value and mask */
+ msr_type = mcb->msr_type;
+
+ if (mode) {
+ msr_setvalue = mcb->msr_value;
+ msr_setmask = mcb->msr_mask;
+ }
+
+ DPRINTF(("%s: msr_setvalue=%" PRIu64 " msr_setmask=%" PRIu64 "\n",
+ __func__, msr_setvalue, msr_setmask));
+
+ /*
+ * Issue a full memory barrier, to make sure the operations
+ * are done in a serialized way.
+ */
+ mb_memory();
+
+ /* Write mode */
+ if (mode) {
+ DPRINTF(("%s: before write\n", __func__));
+
+ /* Run the IPI write handler in current CPU */
+ msr_write_ipi(curcpu());
+ /*
+ * Only run the IPI write handler in other CPUs
+ * when there are at least two CPUs.
+ */
+ if (ncpu > 1)
+ x86_broadcast_ipi(X86_IPI_WRITE_MSR);
+
+ DPRINTF(("%s: after write\n", __func__));
+ } else {
+ /* Read mode */
+ DPRINTF(("%s: before read\n", __func__));
+
+ /* Run the IPI read handler in all CPUs */
+ msr_read_ipi(curcpu());
+
+ if (ncpu > 1)
+ x86_broadcast_ipi(X86_IPI_READ_MSR);
+
+ DPRINTF(("%s: after read\n", __func__));
+ }
+
+ DPRINTF(("%s: before pause\n", __func__));
+ DPRINTF(("%s: msr_runcount=%d ncpu=%d\n", __func__,
+ msr_runcount, ncpu));
+
+ /* Spin until every CPU has run the handler. */
+ while (msr_runcount < ncpu)
+ x86_pause();
+
+ DPRINTF(("%s: after pause\n", __func__));
+
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ DPRINTF(("%s: ci_msr_rvalue=0x%" PRIu64 "\n",
+ ci->ci_dev->dv_xname, ci->ci_msr_rvalue));
+ }
+
+ /* We're done, so unlock. */
+ mutex_exit(&msr_mtx);
+
+ DPRINTF(("%s: ----- END -----\n\n", __func__));
+
+ return 0;
+}
+
+/* Initializes the mutex very early in the boot process for future access */
+void
+msr_cpu_broadcast_initmtx(void)
+{
+ mutex_init(&msr_mtx, MUTEX_DRIVER, IPL_NONE);
+}
+
+/*
+ * This is the function used to interact with drivers using this framework.
+ * if mode was set as MSR_CPU_BROADCAST_READ, a read operation will be
+ * performed, otherwise (MSR_CPU_BROADCAST_WRITE) will be performed.
+ * Needs mcb->msr_type set.
+ */
+int
+msr_cpu_broadcast(struct msr_cpu_broadcast *mcb, int mode)
+{
+ if (!mcb->msr_type) {
+ DPRINTF(("%s: !msr_type\n", __func__));
+ return 1;
+ }
+
+ DPRINTF(("%s: mcb->msr_value=%" PRIu64 "\n", __func__,
+ mcb->msr_value));
+
+ switch (mode) {
+ case MSR_CPU_BROADCAST_READ:
+ if (msr_cpu_broadcast_main(mcb, false)) {
+ DPRINTF(("%s: msr_cpu_broadcast in read mode failed\n",
+ __func__));
+ return 1;
+ }
+ break;
+ case MSR_CPU_BROADCAST_WRITE:
+ if (msr_cpu_broadcast_main(mcb, true)) {
+ DPRINTF(("%s: msr_cpu_broadcast in write mode failed\n",
+ __func__));
+ return 1;
+ }
+ break;
+ default:
+ return 1;
+ }
+
+ return 0;
+}
Index: x86/x86/x86_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/x86_machdep.c,v
retrieving revision 1.8
diff -u -p -b -u -r1.8 x86_machdep.c
--- x86/x86/x86_machdep.c 1 Mar 2007 11:49:26 -0000 1.8
+++ x86/x86/x86_machdep.c 19 Mar 2007 03:58:56 -0000
@@ -46,6 +46,8 @@ __KERNEL_RCSID(0, "$NetBSD: x86_machdep.
#include <sys/errno.h>
#include <sys/kauth.h>
+#include <x86/cpu_msr.h>
+
#include <machine/bootinfo.h>
#include <machine/vmparam.h>
@@ -125,3 +127,12 @@ x86_pause(void)
{
__asm volatile("pause");
}
+
+/*
+ * This function is to initialize the mutex used by x86/msr_ipifuncs.c.
+ */
+void
+x86_init(void)
+{
+ msr_cpu_broadcast_initmtx();
+}
Index: amd64/amd64/ipifuncs.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/amd64/ipifuncs.c,v
retrieving revision 1.7
diff -u -p -b -u -r1.7 ipifuncs.c
--- amd64/amd64/ipifuncs.c 9 Feb 2007 21:55:01 -0000 1.7
+++ amd64/amd64/ipifuncs.c 19 Mar 2007 03:58:56 -0000
@@ -65,6 +65,8 @@ __KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v
#include <machine/gdt.h>
#include <machine/fpu.h>
+#include <x86/cpu_msr.h>
+
#include <ddb/db_output.h>
void x86_64_ipi_halt(struct cpu_info *);
@@ -87,6 +89,8 @@ void (*ipifunc[X86_NIPI])(struct cpu_inf
pmap_do_tlb_shootdown,
x86_64_reload_mtrr,
gdt_reload_cpu,
+ msr_read_ipi,
+ msr_write_ipi
};
void
Index: amd64/amd64/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/amd64/machdep.c,v
retrieving revision 1.52
diff -u -p -b -u -r1.52 machdep.c
--- amd64/amd64/machdep.c 4 Mar 2007 14:36:11 -0000 1.52
+++ amd64/amd64/machdep.c 19 Mar 2007 03:58:56 -0000
@@ -135,6 +135,7 @@ __KERNEL_RCSID(0, "$NetBSD: machdep.c,v
#include <machine/fpu.h>
#include <machine/mtrr.h>
#include <machine/mpbiosvar.h>
+#include <x86/cpu_msr.h>
#include <x86/x86/tsc.h>
#include <dev/isa/isareg.h>
@@ -1527,6 +1528,8 @@ init_x86_64(paddr_t first_avail)
splraise(IPL_IPI);
enable_intr();
+ x86_init();
+
/* Make sure maxproc is sane */
if (maxproc > cpu_maxproc())
maxproc = cpu_maxproc();
Index: amd64/include/cpu.h
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/include/cpu.h,v
retrieving revision 1.19
diff -u -p -b -u -r1.19 cpu.h
--- amd64/include/cpu.h 16 Mar 2007 18:52:03 -0000 1.19
+++ amd64/include/cpu.h 19 Mar 2007 03:58:56 -0000
@@ -106,6 +106,8 @@ struct cpu_info {
u_int32_t ci_signature;
u_int64_t ci_tsc_freq;
+ uint64_t ci_msr_rvalue; /* per-cpu msr returned value */
+
const struct cpu_functions *ci_func;
void (*cpu_setup)(struct cpu_info *);
void (*ci_info)(struct cpu_info *);
--Boundary-00=_54s/Fyc9mzDyAmX
Content-Type: text/x-diff;
charset="iso-8859-1";
name="est_smp_mask.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="est_smp_mask.diff"
Index: est.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/est.c,v
retrieving revision 1.33
diff -u -p -r1.33 est.c
--- est.c 18 Mar 2007 07:21:41 -0000 1.33
+++ est.c 19 Mar 2007 02:54:13 -0000
@@ -94,6 +94,8 @@ __KERNEL_RCSID(0, "$NetBSD: est.c,v 1.33
#include <sys/sysctl.h>
#include <sys/once.h>
+#include <x86/cpu_msr.h>
+
#include <machine/cpu.h>
#include <machine/specialreg.h>
@@ -852,6 +854,7 @@ static void est_init_main(int);
static int
est_sysctl_helper(SYSCTLFN_ARGS)
{
+ struct msr_cpu_broadcast mcb;
struct sysctlnode node;
int fq, oldfq, error;
@@ -876,16 +879,20 @@ est_sysctl_helper(SYSCTLFN_ARGS)
/* support writing to ...frequency.target */
if (rnode->sysctl_num == est_node_target && fq != oldfq) {
int i;
- uint64_t msr;
for (i = est_fqlist->n - 1; i > 0; i--)
if (MSR2MHZ(est_fqlist->table[i], bus_clock) >= fq)
break;
fq = MSR2MHZ(est_fqlist->table[i], bus_clock);
- msr = rdmsr(MSR_PERF_CTL);
- msr &= ~0xffffULL;
- msr |= est_fqlist->table[i];
- wrmsr(MSR_PERF_CTL, msr);
+ mcb.msr_type = MSR_PERF_CTL;
+ if (msr_cpu_broadcast(&mcb, MSR_CPU_BROADCAST_READ))
+ return EINVAL;
+
+ mcb.msr_mask = 0xffffULL;
+ mcb.msr_value = est_fqlist->table[i];
+
+ if (msr_cpu_broadcast(&mcb, MSR_CPU_BROADCAST_WRITE))
+ return EINVAL;
}
return 0;
--Boundary-00=_54s/Fyc9mzDyAmX
Content-Type: text/x-diff;
charset="iso-8859-1";
name="powernow_k8_smp_mask.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="powernow_k8_smp_mask.diff"
Index: powernow_k8.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/powernow_k8.c,v
retrieving revision 1.13
diff -u -p -r1.13 powernow_k8.c
--- powernow_k8.c 18 Mar 2007 14:30:54 -0000 1.13
+++ powernow_k8.c 19 Mar 2007 04:09:26 -0000
@@ -75,6 +75,7 @@ __KERNEL_RCSID(0, "$NetBSD: powernow_k8.
#include <sys/sysctl.h>
#include <sys/once.h>
+#include <x86/cpu_msr.h>
#include <x86/powernow.h>
#include <dev/isa/isareg.h>
@@ -84,6 +85,20 @@ __KERNEL_RCSID(0, "$NetBSD: powernow_k8.
#include <machine/cpufunc.h>
#include <machine/bus.h>
+/*
+ * Overwrite our previous WRITE_FIDVID macro with the one used by
+ * the msr_cpu_broadcast framework, which will work in UP and SMP.
+ */
+#undef WRITE_FIDVID
+#define WRITE_FIDVID(fid, vid, ctrl) \
+ mcb.msr_mask = ((ctrl) << 32); \
+ mcb.msr_value = ((1ULL << 16) | ((vid) << 8) | (fid)); \
+ mcb.msr_type = MSR_AMDK7_FIDVID_CTL; \
+ if (msr_cpu_broadcast(&mcb, MSR_CPU_BROADCAST_WRITE)) { \
+ DPRINTF(("%s: failed\n", __func__)); \
+ return EINVAL; \
+ }
+
#ifdef _LKM
static struct sysctllog *sysctllog;
#define SYSCTLLOG &sysctllog
@@ -151,6 +166,7 @@ k8_powernow_setperf(unsigned int freq)
int cfid, cvid, fid = 0, vid = 0;
int rvo;
struct powernow_cpu_state *ccstate;
+ struct msr_cpu_broadcast mcb;
/*
* We dont do a k8pnow_read_pending_wait here, need to ensure that the
--Boundary-00=_54s/Fyc9mzDyAmX--