summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2016-06-16 12:07:40 +0000
committerkib <kib@FreeBSD.org>2016-06-16 12:07:40 +0000
commit3b7087fccea8083cf8a2ef2575fabccde9af31e1 (patch)
treeca082fcecc8a8b29b4af912691dc8c479bfa387a
parent496a3b1f658d32d5ed000ef2ee765245a29a6c67 (diff)
downloadFreeBSD-src-3b7087fccea8083cf8a2ef2575fabccde9af31e1.zip
FreeBSD-src-3b7087fccea8083cf8a2ef2575fabccde9af31e1.tar.gz
Always allow loading of cpuctl(4). When a CPU feature is not
supported, e.g. CPUID or MSR, return ENODEV from the ioctl which needs that feature. Sponsored by: The FreeBSD Foundation MFC after: 1 week Approved by: re (hrs)
-rw-r--r--sys/dev/cpuctl/cpuctl.c38
1 files changed, 22 insertions, 16 deletions
diff --git a/sys/dev/cpuctl/cpuctl.c b/sys/dev/cpuctl/cpuctl.c
index a73595b..6519e1b 100644
--- a/sys/dev/cpuctl/cpuctl.c
+++ b/sys/dev/cpuctl/cpuctl.c
@@ -67,9 +67,9 @@ static d_ioctl_t cpuctl_ioctl;
static int cpuctl_do_msr(int cpu, cpuctl_msr_args_t *data, u_long cmd,
struct thread *td);
-static void cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_t *data,
+static int cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_t *data,
struct thread *td);
-static void cpuctl_do_cpuid_count(int cpu, cpuctl_cpuid_count_args_t *data,
+static int cpuctl_do_cpuid_count(int cpu, cpuctl_cpuid_count_args_t *data,
struct thread *td);
static int cpuctl_do_update(int cpu, cpuctl_update_args_t *data,
struct thread *td);
@@ -171,8 +171,7 @@ cpuctl_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
ret = cpuctl_do_msr(cpu, (cpuctl_msr_args_t *)data, cmd, td);
break;
case CPUCTL_CPUID:
- cpuctl_do_cpuid(cpu, (cpuctl_cpuid_args_t *)data, td);
- ret = 0;
+ ret = cpuctl_do_cpuid(cpu, (cpuctl_cpuid_args_t *)data, td);
break;
case CPUCTL_UPDATE:
ret = priv_check(td, PRIV_CPUCTL_UPDATE);
@@ -181,9 +180,8 @@ cpuctl_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
ret = cpuctl_do_update(cpu, (cpuctl_update_args_t *)data, td);
break;
case CPUCTL_CPUID_COUNT:
- cpuctl_do_cpuid_count(cpu, (cpuctl_cpuid_count_args_t *)data,
- td);
- ret = 0;
+ ret = cpuctl_do_cpuid_count(cpu,
+ (cpuctl_cpuid_count_args_t *)data, td);
break;
default:
ret = EINVAL;
@@ -196,7 +194,7 @@ fail:
/*
* Actually perform cpuid operation.
*/
-static void
+static int
cpuctl_do_cpuid_count(int cpu, cpuctl_cpuid_count_args_t *data,
struct thread *td)
{
@@ -210,23 +208,30 @@ cpuctl_do_cpuid_count(int cpu, cpuctl_cpuid_count_args_t *data,
bzero(data->data, sizeof(data->data));
DPRINTF("[cpuctl,%d]: retrieving cpuid lev %#0x type %#0x for %d cpu\n",
__LINE__, data->level, data->level_type, 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);
cpuid_count(data->level, data->level_type, data->data);
restore_cpu(oldcpu, is_bound, td);
+ return (0);
}
-static void
+static int
cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_t *data, struct thread *td)
{
cpuctl_cpuid_count_args_t cdata;
+ int error;
cdata.level = data->level;
/* Override the level type. */
cdata.level_type = 0;
- cpuctl_do_cpuid_count(cpu, &cdata, td);
+ error = cpuctl_do_cpuid_count(cpu, &cdata, td);
bcopy(cdata.data, data->data, sizeof(data->data)); /* Ignore error */
+ return (error);
}
/*
@@ -249,6 +254,10 @@ cpuctl_do_msr(int cpu, cpuctl_msr_args_t *data, u_long cmd, struct thread *td)
*/
DPRINTF("[cpuctl,%d]: operating on MSR %#0x for %d cpu\n", __LINE__,
data->msr, cpu);
+#ifdef __i386__
+ if ((cpu_feature & CPUID_MSR) == 0)
+ return (ENODEV);
+#endif
oldcpu = td->td_oncpu;
is_bound = cpu_sched_is_bound(td);
set_cpu(cpu, td);
@@ -291,7 +300,9 @@ cpuctl_do_update(int cpu, cpuctl_update_args_t *data, struct thread *td)
("[cpuctl,%d]: bad cpu number %d", __LINE__, cpu));
DPRINTF("[cpuctl,%d]: XXX %d", __LINE__, cpu);
- cpuctl_do_cpuid(cpu, &args, td);
+ ret = cpuctl_do_cpuid(cpu, &args, td);
+ if (ret != 0)
+ return (ret);
((uint32_t *)vendor)[0] = args.data[1];
((uint32_t *)vendor)[1] = args.data[3];
((uint32_t *)vendor)[2] = args.data[2];
@@ -518,11 +529,6 @@ cpuctl_modevent(module_t mod __unused, int type, void *data __unused)
switch(type) {
case MOD_LOAD:
- if ((cpu_feature & CPUID_MSR) == 0) {
- if (bootverbose)
- printf("cpuctl: not available.\n");
- return (ENODEV);
- }
if (bootverbose)
printf("cpuctl: access to MSR registers/cpuid info.\n");
cpuctl_devs = malloc(sizeof(*cpuctl_devs) * mp_ncpus, M_CPUCTL,
OpenPOWER on IntegriCloud