From owner-svn-src-all@FreeBSD.ORG Wed Jul 2 13:09:27 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id D1017197; Wed, 2 Jul 2014 13:09:27 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id B186A2337; Wed, 2 Jul 2014 13:09:27 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s62D9RuC056281; Wed, 2 Jul 2014 13:09:27 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s62D9QnG056273; Wed, 2 Jul 2014 13:09:26 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201407021309.s62D9QnG056273@svn.freebsd.org> From: Konstantin Belousov Date: Wed, 2 Jul 2014 13:09:26 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268157 - in stable/10: share/man/man4 sys/dev/cpuctl sys/sys usr.sbin/cpucontrol X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Jul 2014 13:09:27 -0000 Author: kib Date: Wed Jul 2 13:09:26 2014 New Revision: 268157 URL: http://svnweb.freebsd.org/changeset/base/268157 Log: MFC r267651 (by attilio): Add the possibility to specify ecx when performing cpuid calls. MFC r267673: Restore the ABI of the cpuctl(4) ioctl request CPUCTL_CPUID. MFC r267814: Make cpuctl_do_cpuid() and cpuctl_do_cpuid_count() return void. Modified: stable/10/share/man/man4/cpuctl.4 stable/10/sys/dev/cpuctl/cpuctl.c stable/10/sys/sys/cpuctl.h stable/10/usr.sbin/cpucontrol/cpucontrol.8 stable/10/usr.sbin/cpucontrol/cpucontrol.c Directory Properties: stable/10/ (props changed) Modified: stable/10/share/man/man4/cpuctl.4 ============================================================================== --- stable/10/share/man/man4/cpuctl.4 Wed Jul 2 12:13:11 2014 (r268156) +++ stable/10/share/man/man4/cpuctl.4 Wed Jul 2 13:09:26 2014 (r268157) @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 30, 2009 +.Dd June 20, 2014 .Dt CPUCTL 4 .Os .Sh NAME @@ -65,7 +65,7 @@ All of the supported operations are invo .Xr ioctl 2 system call. Currently, the following ioctls are defined: -.Bl -tag -width CPUCTL_UPDATE +.Bl -tag -width CPUCTL_CPUID_COUNT .It Dv CPUCTL_RDMSR Fa cpuctl_msr_args_t *args .It Dv CPUCTL_WRMSR Fa cpuctl_msr_args_t *args Read/write CPU machine specific register. @@ -87,20 +87,59 @@ Set/clear MSR bits according to the mask field. .It Dv CPUCTL_CPUID Fa cpuctl_cpuid_args_t *args Retrieve CPUID information. -Arguments are supplied in -the following struct: +Arguments are supplied in the following structure: .Bd -literal typedef struct { - int level; /* CPUID level */ + int level; /* CPUID level */ uint32_t data[4]; } cpuctl_cpuid_args_t; .Ed -.Pp +It is equivalent to the +.Dv CPUCTL_CPUID_COUNT +request with +.Va level_type +set to 0. +.It Dv CPUCTL_CPUID_COUNT Fa cpuctl_cpuid_count_args_t *args +Retrieve CPUID information. +Arguments are supplied in the following structure: +.Bd -literal +typedef struct { + int level; /* CPUID level */ + int level_type; /* CPUID level type */ + uint32_t data[4]; +} cpuctl_cpuid_count_args_t; +.Ed The .Va level -field indicates the CPUID level to retrieve information for, while the +field indicates the CPUID level to retrieve, +it is loaded into the +.Va %eax +register before the CPUID instruction is executed, +The +.Va level_type +field indicates the CPUID level type to retrieve, +it is loaded into the +.Va %ecx +register. +.Pp +The .Va data field is used to store the received CPUID data. +That is, +.Va data[0] +contains the value of +.Va %eax +register after the CPUID instruction is executed, +.Va data[1] +is for +.Va %ebx , +.Va data[2] +for +.Va %ecx , +and +.Va data[3] +for +.Va %edx . .It Dv CPUCTL_UPDATE cpuctl_update_args_t *args Update CPU firmware (microcode). The structure is defined in Modified: stable/10/sys/dev/cpuctl/cpuctl.c ============================================================================== --- stable/10/sys/dev/cpuctl/cpuctl.c Wed Jul 2 12:13:11 2014 (r268156) +++ stable/10/sys/dev/cpuctl/cpuctl.c Wed Jul 2 13:09:26 2014 (r268157) @@ -67,7 +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 int cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_t *data, +static void 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, struct thread *td); static int cpuctl_do_update(int cpu, cpuctl_update_args_t *data, struct thread *td); @@ -169,7 +171,8 @@ cpuctl_ioctl(struct cdev *dev, u_long cm ret = cpuctl_do_msr(cpu, (cpuctl_msr_args_t *)data, cmd, td); break; case CPUCTL_CPUID: - ret = cpuctl_do_cpuid(cpu, (cpuctl_cpuid_args_t *)data, td); + cpuctl_do_cpuid(cpu, (cpuctl_cpuid_args_t *)data, td); + ret = 0; break; case CPUCTL_UPDATE: ret = priv_check(td, PRIV_CPUCTL_UPDATE); @@ -177,6 +180,11 @@ cpuctl_ioctl(struct cdev *dev, u_long cm goto fail; 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; + break; default: ret = EINVAL; break; @@ -188,8 +196,9 @@ fail: /* * Actually perform cpuid operation. */ -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, + struct thread *td) { int is_bound = 0; int oldcpu; @@ -199,14 +208,25 @@ cpuctl_do_cpuid(int cpu, cpuctl_cpuid_ar /* Explicitly clear cpuid data to avoid returning stale info. */ bzero(data->data, sizeof(data->data)); - DPRINTF("[cpuctl,%d]: retriving cpuid level %#0x for %d cpu\n", - __LINE__, data->level, cpu); + DPRINTF("[cpuctl,%d]: retrieving cpuid lev %#0x type %#0x for %d cpu\n", + __LINE__, data->level, data->level_type, cpu); oldcpu = td->td_oncpu; is_bound = cpu_sched_is_bound(td); set_cpu(cpu, td); - cpuid_count(data->level, 0, data->data); + cpuid_count(data->level, data->level_type, data->data); restore_cpu(oldcpu, is_bound, td); - return (0); +} + +static void +cpuctl_do_cpuid(int cpu, cpuctl_cpuid_args_t *data, struct thread *td) +{ + cpuctl_cpuid_count_args_t cdata; + + cdata.level = data->level; + /* Override the level type. */ + cdata.level_type = 0; + cpuctl_do_cpuid_count(cpu, &cdata, td); + bcopy(cdata.data, data->data, sizeof(data->data)); /* Ignore error */ } /* @@ -271,12 +291,7 @@ cpuctl_do_update(int cpu, cpuctl_update_ ("[cpuctl,%d]: bad cpu number %d", __LINE__, cpu)); DPRINTF("[cpuctl,%d]: XXX %d", __LINE__, cpu); - ret = cpuctl_do_cpuid(cpu, &args, td); - if (ret != 0) { - DPRINTF("[cpuctl,%d]: cannot retrive cpuid info for cpu %d", - __LINE__, cpu); - return (ENXIO); - } + cpuctl_do_cpuid(cpu, &args, td); ((uint32_t *)vendor)[0] = args.data[1]; ((uint32_t *)vendor)[1] = args.data[3]; ((uint32_t *)vendor)[2] = args.data[2]; Modified: stable/10/sys/sys/cpuctl.h ============================================================================== --- stable/10/sys/sys/cpuctl.h Wed Jul 2 12:13:11 2014 (r268156) +++ stable/10/sys/sys/cpuctl.h Wed Jul 2 13:09:26 2014 (r268157) @@ -35,11 +35,17 @@ typedef struct { } cpuctl_msr_args_t; typedef struct { - int level; /* CPUID level */ + int level; /* CPUID level */ uint32_t data[4]; } cpuctl_cpuid_args_t; typedef struct { + int level; /* CPUID level */ + int level_type; /* CPUID level type */ + uint32_t data[4]; +} cpuctl_cpuid_count_args_t; + +typedef struct { void *data; size_t size; } cpuctl_update_args_t; @@ -50,5 +56,6 @@ typedef struct { #define CPUCTL_UPDATE _IOWR('c', 4, cpuctl_update_args_t) #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) #endif /* _CPUCTL_H_ */ Modified: stable/10/usr.sbin/cpucontrol/cpucontrol.8 ============================================================================== --- stable/10/usr.sbin/cpucontrol/cpucontrol.8 Wed Jul 2 12:13:11 2014 (r268156) +++ stable/10/usr.sbin/cpucontrol/cpucontrol.8 Wed Jul 2 13:09:26 2014 (r268157) @@ -65,6 +65,12 @@ device .Ek .Nm .Op Fl vh +.Fl i Ar level,level_type +.Bk +.Ar device +.Ek +.Nm +.Op Fl vh .Op Fl d Ar datadir .Fl u .Bk @@ -114,6 +120,9 @@ In this case the inverted value of mask .It Fl i Ar level Retrieve CPUID info. Level should be given as a hex number. +.It Fl i Ar level,level_type +Retrieve CPUID info. +Level and level_type should be given as hex numbers. .It Fl u Apply CPU firmware updates. The Modified: stable/10/usr.sbin/cpucontrol/cpucontrol.c ============================================================================== --- stable/10/usr.sbin/cpucontrol/cpucontrol.c Wed Jul 2 12:13:11 2014 (r268156) +++ stable/10/usr.sbin/cpucontrol/cpucontrol.c Wed Jul 2 13:09:26 2014 (r268157) @@ -99,6 +99,7 @@ static struct ucode_handler { static void usage(void); static int isdir(const char *path); static int do_cpuid(const char *cmdarg, const char *dev); +static int do_cpuid_count(const char *cmdarg, const char *dev); static int do_msr(const char *cmdarg, const char *dev); static int do_update(const char *dev); static void datadir_add(const char *path); @@ -112,7 +113,7 @@ usage(void) if (name == NULL) name = "cpuctl"; fprintf(stderr, "Usage: %s [-vh] [-d datadir] [-m msr[=value] | " - "-i level | -u] device\n", name); + "-i level | -i level,level_type | -u] device\n", name); exit(EX_USAGE); } @@ -170,6 +171,57 @@ do_cpuid(const char *cmdarg, const char } static int +do_cpuid_count(const char *cmdarg, const char *dev) +{ + char *cmdarg1, *endptr, *endptr1; + unsigned int level, level_type; + cpuctl_cpuid_count_args_t args; + int fd, error; + + assert(cmdarg != NULL); + assert(dev != NULL); + + level = strtoul(cmdarg, &endptr, 16); + if (*cmdarg == '\0' || *endptr == '\0') { + WARNX(0, "incorrect or missing operand: %s", cmdarg); + usage(); + /* NOTREACHED */ + } + /* Locate the comma... */ + cmdarg1 = strstr(endptr, ","); + /* ... and skip past it */ + cmdarg1 += 1; + level_type = strtoul(cmdarg1, &endptr1, 16); + if (*cmdarg1 == '\0' || *endptr1 != '\0') { + WARNX(0, "incorrect or missing operand: %s", cmdarg); + usage(); + /* NOTREACHED */ + } + + /* + * Fill ioctl argument structure. + */ + args.level = level; + args.level_type = level_type; + fd = open(dev, O_RDONLY); + if (fd < 0) { + WARN(0, "error opening %s for reading", dev); + return (1); + } + error = ioctl(fd, CPUCTL_CPUID_COUNT, &args); + if (error < 0) { + WARN(0, "ioctl(%s, CPUCTL_CPUID_COUNT)", dev); + close(fd); + return (error); + } + fprintf(stdout, "cpuid level 0x%x, level_type 0x%x: 0x%.8x 0x%.8x " + "0x%.8x 0x%.8x\n", level, level_type, args.data[0], args.data[1], + args.data[2], args.data[3]); + close(fd); + return (0); +} + +static int do_msr(const char *cmdarg, const char *dev) { unsigned int msr; @@ -414,7 +466,10 @@ main(int argc, char *argv[]) c = flags & (FLAG_I | FLAG_M | FLAG_U); switch (c) { case FLAG_I: - error = do_cpuid(cmdarg, dev); + 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);