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)
This commit is contained in:
Konstantin Belousov 2016-06-16 12:07:40 +00:00
parent 5c2cf81845
commit f1143962a5

View File

@ -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 @@ cpuctl_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
/*
* 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,