Date: Wed, 1 Oct 2003 12:41:56 +0100 From: Bruce M Simpson <bms@spc.org> To: Grumble <invalid@kma.eu.org> Cc: freebsd-questions@freebsd.org Subject: Re: Why is PCE not set in CR4? Message-ID: <20031001114155.GA12991@saboteur.dek.spc.org> In-Reply-To: <3F7AA0D8.1080801@kma.eu.org> References: <3F7AA0D8.1080801@kma.eu.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--DocE+STaALJfprDB Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Wed, Oct 01, 2003 at 11:39:36AM +0200, Grumble wrote: > >>However, I am not allowed to use the RDPMC instruction from ring 3 > >>because the PCE (Performance-monitoring Counters Enable) bit is not set. > > > >You can do it with /dev/perfmon. man 4 perfmon. > > I have read the perfmon documentation and source code. For several > reasons, I do not think it is totally adequate in my situation. [snip] Hi, Eat this. Diff attached. Test this and I'll commit it to -CURRENT if you're happy with it. If you can tell me more about what perfmon needs I'll give it love too. This is an extension to the i386_vm86() syscall which will let you turn PCE on and off if you're the superuser. BMS --DocE+STaALJfprDB Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="i386pce.col.diff" Generated by diffcoll on Wed 1 Oct 2003 12:39:07 BST diff -uN src/lib/libc/i386/sys/i386_vm86.2.orig src/lib/libc/i386/sys/i386_vm86.2 --- /usr/src/lib/libc/i386/sys/i386_vm86.2.orig Wed Oct 1 12:13:50 2003 +++ /usr/src/lib/libc/i386/sys/i386_vm86.2 Wed Oct 1 12:36:44 2003 @@ -112,6 +112,26 @@ .Fa state will contain the state of the VME flag on return. .\" .It Dv VM86_SET_VME +.It Dv VM86_GET_PCE +This is used to retrieve the current state of the Pentium(r) processor's +PCE (Performance Counter Enable) flag, which is bit 8 of CR4. +.Bd -literal +struct vm86_pce_args { + int state; /* status */ +}; +.Ed +.Pp +.Fa state +will contain the state of the VME flag on return. +.It Dv VM86_SET_PCE +This is used to set the current state of the PCE flag. +Enabling this bit allows any code to execute the +.Li RDPMC +instruction. +Disabling this bit will allow only code running at protection level 0 to +execute this instruction. +Because this bit has system-wide granularity, it may only be enabled by +the superuser. .El .Pp vm86 mode is entered by calling @@ -133,6 +153,13 @@ .It Bq Er ENOMEM There is not enough memory to initialize the kernel data structures. .El +.Sh BUGS +The +.Dv VM86_SETPCE +and +.Dv VM86_GETPCE +functions are only guaranteed to work for uniprocessor kernels; their +results on SMP systems are undefined. .Sh AUTHORS .An -nosplit This man page was written by diff -uN src/sys/i386/i386/vm86.c.orig src/sys/i386/i386/vm86.c --- /usr/src/sys/i386/i386/vm86.c.orig Wed Oct 1 12:16:23 2003 +++ /usr/src/sys/i386/i386/vm86.c Wed Oct 1 12:39:01 2003 @@ -734,6 +734,29 @@ } break; + case VM86_SET_PCE: { + struct vm86_pce_args sa; + + if ((error = suser(td))) + return (error); + if (!(cpu_feature & CPUID_TSC) || !(cpu_feature & CPUID_MMX)) + return (ENODEV); + if ((error = copyin(ua.sub_args, &sa, sizeof(sa)))) + return (error); + if (sa.state) + load_cr4(rcr4() | CR4_PCE); + else + load_cr4(rcr4() & ~CR4_PCE); + } + break; + + case VM86_GET_PCE: { + struct vm86_pce_args sa; + + sa.state = (rcr4() & CR4_PCE ? 1 : 0); + error = copyout(&sa, ua.sub_args, sizeof(sa)); + } + default: error = EINVAL; } diff -uN src/sys/i386/include/vm86.h.orig src/sys/i386/include/vm86.h --- /usr/src/sys/i386/include/vm86.h.orig Wed Oct 1 12:22:53 2003 +++ /usr/src/sys/i386/include/vm86.h Wed Oct 1 12:37:56 2003 @@ -128,6 +128,8 @@ #define VM86_SET_VME 2 #define VM86_GET_VME 3 #define VM86_INTCALL 4 +#define VM86_SET_PCE 5 +#define VM86_GET_PCE 6 struct vm86_init_args { int debug; /* debug flag */ @@ -136,6 +138,10 @@ }; struct vm86_vme_args { + int state; /* status */ +}; + +struct vm86_pce_args { int state; /* status */ }; --DocE+STaALJfprDB--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20031001114155.GA12991>