Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 12 Jan 2018 10:54:00 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r327871 - in stable/11: sys/amd64/amd64 sys/dev/cpuctl sys/sys sys/x86/include sys/x86/x86 usr.sbin/cpucontrol
Message-ID:  <201801121054.w0CAs0oF078233@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Fri Jan 12 10:54:00 2018
New Revision: 327871
URL: https://svnweb.freebsd.org/changeset/base/327871

Log:
  MFC r327597:
  Make it possible to re-evaluate cpu_features.

Modified:
  stable/11/sys/amd64/amd64/machdep.c
  stable/11/sys/dev/cpuctl/cpuctl.c
  stable/11/sys/sys/cpuctl.h
  stable/11/sys/x86/include/x86_var.h
  stable/11/sys/x86/x86/identcpu.c
  stable/11/usr.sbin/cpucontrol/cpucontrol.8
  stable/11/usr.sbin/cpucontrol/cpucontrol.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/amd64/amd64/machdep.c
==============================================================================
--- stable/11/sys/amd64/amd64/machdep.c	Fri Jan 12 10:51:42 2018	(r327870)
+++ stable/11/sys/amd64/amd64/machdep.c	Fri Jan 12 10:54:00 2018	(r327871)
@@ -1544,7 +1544,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
 
 	kmdp = init_ops.parse_preload_data(modulep);
 
-	identify_cpu();
+	identify_cpu1();
 	identify_hypervisor();
 
 	/* Init basic tunables, hz etc */

Modified: stable/11/sys/dev/cpuctl/cpuctl.c
==============================================================================
--- stable/11/sys/dev/cpuctl/cpuctl.c	Fri Jan 12 10:51:42 2018	(r327870)
+++ stable/11/sys/dev/cpuctl/cpuctl.c	Fri Jan 12 10:54:00 2018	(r327871)
@@ -71,6 +71,7 @@ static int cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_
     struct thread *td);
 static int cpuctl_do_cpuid_count(int cpu, cpuctl_cpuid_count_args_t *data,
     struct thread *td);
+static int cpuctl_do_eval_cpu_features(int cpu, struct thread *td);
 static int cpuctl_do_update(int cpu, cpuctl_update_args_t *data,
     struct thread *td);
 static int update_intel(int cpu, cpuctl_update_args_t *args,
@@ -157,7 +158,8 @@ cpuctl_ioctl(struct cdev *dev, u_long cmd, caddr_t dat
 	}
 	/* Require write flag for "write" requests. */
 	if ((cmd == CPUCTL_MSRCBIT || cmd == CPUCTL_MSRSBIT ||
-	    cmd == CPUCTL_UPDATE || cmd == CPUCTL_WRMSR) &&
+	    cmd == CPUCTL_UPDATE || cmd == CPUCTL_WRMSR ||
+	    cmd == CPUCTL_EVAL_CPU_FEATURES) &&
 	    (flags & FWRITE) == 0)
 		return (EPERM);
 	switch (cmd) {
@@ -185,6 +187,9 @@ cpuctl_ioctl(struct cdev *dev, u_long cmd, caddr_t dat
 		ret = cpuctl_do_cpuid_count(cpu,
 		    (cpuctl_cpuid_count_args_t *)data, td);
 		break;
+	case CPUCTL_EVAL_CPU_FEATURES:
+		ret = cpuctl_do_eval_cpu_features(cpu, td);
+		break;
 	default:
 		ret = EINVAL;
 		break;
@@ -501,6 +506,29 @@ fail:
 	free(ptr, M_CPUCTL);
 	return (ret);
 }
+
+static int
+cpuctl_do_eval_cpu_features(int cpu, struct thread *td)
+{
+	int is_bound = 0;
+	int oldcpu;
+
+	KASSERT(cpu >= 0 && cpu <= mp_maxid,
+	    ("[cpuctl,%d]: bad cpu number %d", __LINE__, cpu));
+
+#ifdef __i386__
+	if (cpu_id == 0)
+		return (ENODEV);
+#endif
+	oldcpu = td->td_oncpu;
+	is_bound = cpu_sched_is_bound(td);
+	set_cpu(cpu, td);
+	identify_cpu1();
+	identify_cpu2();
+	restore_cpu(oldcpu, is_bound, td);
+	return (0);
+}
+
 
 int
 cpuctl_open(struct cdev *dev, int flags, int fmt __unused, struct thread *td)

Modified: stable/11/sys/sys/cpuctl.h
==============================================================================
--- stable/11/sys/sys/cpuctl.h	Fri Jan 12 10:51:42 2018	(r327870)
+++ stable/11/sys/sys/cpuctl.h	Fri Jan 12 10:54:00 2018	(r327871)
@@ -57,5 +57,6 @@ typedef struct {
 #define	CPUCTL_MSRSBIT	_IOWR('c', 5, cpuctl_msr_args_t)
 #define	CPUCTL_MSRCBIT	_IOWR('c', 6, cpuctl_msr_args_t)
 #define	CPUCTL_CPUID_COUNT _IOWR('c', 7, cpuctl_cpuid_count_args_t)
+#define	CPUCTL_EVAL_CPU_FEATURES	_IO('c', 8)
 
 #endif /* _CPUCTL_H_ */

Modified: stable/11/sys/x86/include/x86_var.h
==============================================================================
--- stable/11/sys/x86/include/x86_var.h	Fri Jan 12 10:51:42 2018	(r327870)
+++ stable/11/sys/x86/include/x86_var.h	Fri Jan 12 10:54:00 2018	(r327871)
@@ -116,7 +116,8 @@ void	cpu_setregs(void);
 void	dump_add_page(vm_paddr_t);
 void	dump_drop_page(vm_paddr_t);
 void	finishidentcpu(void);
-void	identify_cpu(void);
+void	identify_cpu1(void);
+void	identify_cpu2(void);
 void	identify_hypervisor(void);
 void	initializecpu(void);
 void	initializecpucache(void);

Modified: stable/11/sys/x86/x86/identcpu.c
==============================================================================
--- stable/11/sys/x86/x86/identcpu.c	Fri Jan 12 10:51:42 2018	(r327870)
+++ stable/11/sys/x86/x86/identcpu.c	Fri Jan 12 10:54:00 2018	(r327871)
@@ -1373,9 +1373,8 @@ fix_cpuid(void)
 	return (false);
 }
 
-#ifdef __amd64__
 void
-identify_cpu(void)
+identify_cpu1(void)
 {
 	u_int regs[4];
 
@@ -1392,15 +1391,37 @@ identify_cpu(void)
 	cpu_feature = regs[3];
 	cpu_feature2 = regs[2];
 }
-#endif
 
+void
+identify_cpu2(void)
+{
+	u_int regs[4], cpu_stdext_disable;
+
+	if (cpu_high >= 7) {
+		cpuid_count(7, 0, regs);
+		cpu_stdext_feature = regs[1];
+
+		/*
+		 * Some hypervisors failed to filter out unsupported
+		 * extended features.  Allow to disable the
+		 * extensions, activation of which requires setting a
+		 * bit in CR4, and which VM monitors do not support.
+		 */
+		cpu_stdext_disable = 0;
+		TUNABLE_INT_FETCH("hw.cpu_stdext_disable", &cpu_stdext_disable);
+		cpu_stdext_feature &= ~cpu_stdext_disable;
+
+		cpu_stdext_feature2 = regs[2];
+	}
+}
+
 /*
  * Final stage of CPU identification.
  */
 void
 finishidentcpu(void)
 {
-	u_int regs[4], cpu_stdext_disable;
+	u_int regs[4];
 #ifdef __i386__
 	u_char ccr3;
 #endif
@@ -1419,22 +1440,7 @@ finishidentcpu(void)
 		cpu_mon_max_size = regs[1] &  CPUID5_MON_MAX_SIZE;
 	}
 
-	if (cpu_high >= 7) {
-		cpuid_count(7, 0, regs);
-		cpu_stdext_feature = regs[1];
-
-		/*
-		 * Some hypervisors failed to filter out unsupported
-		 * extended features.  Allow to disable the
-		 * extensions, activation of which requires setting a
-		 * bit in CR4, and which VM monitors do not support.
-		 */
-		cpu_stdext_disable = 0;
-		TUNABLE_INT_FETCH("hw.cpu_stdext_disable", &cpu_stdext_disable);
-		cpu_stdext_feature &= ~cpu_stdext_disable;
-
-		cpu_stdext_feature2 = regs[2];
-	}
+	identify_cpu2();
 
 #ifdef __i386__
 	if (cpu_high > 0 &&

Modified: stable/11/usr.sbin/cpucontrol/cpucontrol.8
==============================================================================
--- stable/11/usr.sbin/cpucontrol/cpucontrol.8	Fri Jan 12 10:51:42 2018	(r327870)
+++ stable/11/usr.sbin/cpucontrol/cpucontrol.8	Fri Jan 12 10:54:00 2018	(r327871)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd September 30, 2017
+.Dd January 5, 2018
 .Dt CPUCONTROL 8
 .Os
 .Sh NAME
@@ -34,46 +34,51 @@
 device
 .Sh SYNOPSIS
 .Nm
+.Bk
 .Op Fl v
 .Fl m Ar msr
-.Bk
 .Ar device
 .Ek
+.Bk
 .Nm
 .Op Fl v
 .Fl m Ar msr Ns = Ns Ar value
-.Bk
 .Ar device
 .Ek
+.Bk
 .Nm
 .Op Fl v
 .Fl m Ar msr Ns &= Ns Ar mask
-.Bk
 .Ar device
 .Ek
+.Bk
 .Nm
 .Op Fl v
 .Fl m Ar msr Ns |= Ns Ar mask
-.Bk
 .Ar device
 .Ek
+.Bk
 .Nm
 .Op Fl v
 .Fl i Ar level
-.Bk
 .Ar device
 .Ek
+.Bk
 .Nm
 .Op Fl v
 .Fl i Ar level,level_type
-.Bk
 .Ar device
 .Ek
+.Bk
 .Nm
 .Op Fl vn
 .Op Fl d Ar datadir
 .Fl u
+.Ar device
+.Ek
 .Bk
+.Nm
+.Fl e
 .Ar device
 .Ek
 .Sh DESCRIPTION
@@ -136,6 +141,20 @@ The
 .Nm
 utility will walk through the configured data directories
 and apply all firmware updates available for this CPU.
+.It Fl e
+Re-evaluate the kernel flags indicating the present CPU features.
+This command is typically executed after a firmware update was applied
+which changes information reported by the
+.Dv CPUID
+instruction.
+.Pp
+.Bf -symbolic
+Only execute the
+.Fl e
+command after the microcode update was applied to all CPUs in the system.
+The kernel does not operate correctly if the features of processors are
+not identical.
+.Ef
 .It Fl v
 Increase the verbosity level.
 .It Fl h

Modified: stable/11/usr.sbin/cpucontrol/cpucontrol.c
==============================================================================
--- stable/11/usr.sbin/cpucontrol/cpucontrol.c	Fri Jan 12 10:51:42 2018	(r327870)
+++ stable/11/usr.sbin/cpucontrol/cpucontrol.c	Fri Jan 12 10:54:00 2018	(r327871)
@@ -61,6 +61,7 @@ int	verbosity_level = 0;
 #define	FLAG_M	0x02
 #define	FLAG_U	0x04
 #define	FLAG_N	0x08
+#define	FLAG_E	0x10
 
 #define	OP_INVAL	0x00
 #define	OP_READ		0x01
@@ -115,7 +116,7 @@ usage(void)
 	if (name == NULL)
 		name = "cpuctl";
 	fprintf(stderr, "Usage: %s [-vh] [-d datadir] [-m msr[=value] | "
-	    "-i level | -i level,level_type | -u] device\n", name);
+	    "-i level | -i level,level_type | -e | -u] device\n", name);
 	exit(EX_USAGE);
 }
 
@@ -339,6 +340,25 @@ do_msr(const char *cmdarg, const char *dev)
 }
 
 static int
+do_eval_cpu_features(const char *dev)
+{
+	int fd, error;
+
+	assert(dev != NULL);
+
+	fd = open(dev, O_RDWR);
+	if (fd < 0) {
+		WARN(0, "error opening %s for writing", dev);
+		return (1);
+	}
+	error = ioctl(fd, CPUCTL_EVAL_CPU_FEATURES, NULL);
+	if (error < 0)
+		WARN(0, "ioctl(%s, CPUCTL_EVAL_CPU_FEATURES)", dev);
+	close(fd);
+	return (error);
+}
+
+static int
 do_update(const char *dev)
 {
 	int fd;
@@ -428,11 +448,14 @@ main(int argc, char *argv[])
 	error = 0;
 	cmdarg = "";	/* To keep gcc3 happy. */
 
-	while ((c = getopt(argc, argv, "d:hi:m:nuv")) != -1) {
+	while ((c = getopt(argc, argv, "d:ehi:m:nuv")) != -1) {
 		switch (c) {
 		case 'd':
 			datadir_add(optarg);
 			break;
+		case 'e':
+			flags |= FLAG_E;
+			break;
 		case 'i':
 			flags |= FLAG_I;
 			cmdarg = optarg;
@@ -466,22 +489,25 @@ main(int argc, char *argv[])
 	if ((flags & FLAG_N) == 0)
 		datadir_add(DEFAULT_DATADIR);
 	dev = argv[0];
-	c = flags & (FLAG_I | FLAG_M | FLAG_U);
+	c = flags & (FLAG_E | FLAG_I | FLAG_M | FLAG_U);
 	switch (c) {
-		case FLAG_I:
-			if (strstr(cmdarg, ",") != NULL)
-				error = do_cpuid_count(cmdarg, dev);
-			else
-				error = do_cpuid(cmdarg, dev);
-			break;
-		case FLAG_M:
-			error = do_msr(cmdarg, dev);
-			break;
-		case FLAG_U:
-			error = do_update(dev);
-			break;
-		default:
-			usage();	/* Only one command can be selected. */
+	case FLAG_I:
+		if (strstr(cmdarg, ",") != NULL)
+			error = do_cpuid_count(cmdarg, dev);
+		else
+			error = do_cpuid(cmdarg, dev);
+		break;
+	case FLAG_M:
+		error = do_msr(cmdarg, dev);
+		break;
+	case FLAG_U:
+		error = do_update(dev);
+		break;
+	case FLAG_E:
+		error = do_eval_cpu_features(dev);
+		break;
+	default:
+		usage();	/* Only one command can be selected. */
 	}
 	SLIST_FREE(&datadirs, next, free);
 	return (error == 0 ? 0 : 1);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201801121054.w0CAs0oF078233>