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