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

_______________________________________________
[EMAIL PROTECTED] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to