Daemon News Ezine BSD News BSD Mall BSD Support Forum BSD Advocacy BSD Updates

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Why is PCE not set in CR4?



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
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 */
 };