Add CPU feature detection (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 29 Feb 2016 20:45:13 +0000 (15:45 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 29 Feb 2016 21:56:00 +0000 (16:56 -0500)
Userspace, Glibc, and the kernel can now query whether the CPU has certain
features with

bool cpu_has_feat(int feature);

Some CPU features are architecture independent, such as the support for
virtual machines.  Most others will be architecture dependent.  I added a
few feature bits as an example, though they are not used yet.

To use within the kernel:

#include <cpu_feat.h>

To use within glibc:

#include <kernel-features.h>

To use in generic userspace (e.g. user/*, tests/*, etc):

#include <parlib/cpu_feat.h>

Reinstall your kernel headers to use the features.  Rebuild glibc to make
sure I didn't mess anything up.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/riscv/ros/cpu_feat.h [new file with mode: 0644]
kern/arch/x86/ros/cpu_feat.h [new file with mode: 0644]
kern/include/cpu_feat.h [new file with mode: 0644]
kern/include/ros/cpu_feat.h [new file with mode: 0644]
kern/include/ros/procinfo.h
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/kernel-features.h
user/parlib/include/parlib/cpu_feat.h [new file with mode: 0644]

diff --git a/kern/arch/riscv/ros/cpu_feat.h b/kern/arch/riscv/ros/cpu_feat.h
new file mode 100644 (file)
index 0000000..dcfdc6c
--- /dev/null
@@ -0,0 +1,14 @@
+/* Copyright (c) 2016 Google Inc.
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * RISC-V CPU feature detection.
+ *
+ * You can add new items as needed.  Changing __NR_CPU_FEAT will require
+ * a rebuild of the world.  Otherwise, you just need to reinstall kernel
+ * headers. */
+
+#pragma once
+
+#define CPU_FEAT_RISCV_FOO                             (__CPU_FEAT_ARCH_START + 0)
+#define __NR_CPU_FEAT                                  (__CPU_FEAT_ARCH_START + 64)
diff --git a/kern/arch/x86/ros/cpu_feat.h b/kern/arch/x86/ros/cpu_feat.h
new file mode 100644 (file)
index 0000000..cffa14c
--- /dev/null
@@ -0,0 +1,15 @@
+/* Copyright (c) 2016 Google Inc.
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * x86 CPU feature detection.
+ *
+ * You can add new items as needed.  Changing __NR_CPU_FEAT will require
+ * a rebuild of the world.  Otherwise, you just need to reinstall kernel
+ * headers. */
+
+#pragma once
+
+#define CPU_FEAT_X86_XSAVEOPT                  (__CPU_FEAT_ARCH_START + 0)
+#define CPU_FEAT_X86_FSGSBASE                  (__CPU_FEAT_ARCH_START + 1)
+#define __NR_CPU_FEAT                                  (__CPU_FEAT_ARCH_START + 64)
diff --git a/kern/include/cpu_feat.h b/kern/include/cpu_feat.h
new file mode 100644 (file)
index 0000000..dd09f64
--- /dev/null
@@ -0,0 +1,23 @@
+/* Copyright (c) 2016 Google Inc.
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * Set and query the existence of cpu features.
+ *
+ * Note that I didn't provide a "cpu_clr_feat()" yet.  These are intended to be
+ * write-once, read-many. */
+
+#pragma once
+
+#include <ros/procinfo.h>
+#include <bitops.h>
+
+static inline bool cpu_has_feat(int feature)
+{
+       return test_bit(feature, __proc_global_info.cpu_feats);
+}
+
+static inline void cpu_set_feat(int feature)
+{
+       __set_bit(feature, __proc_global_info.cpu_feats);
+}
diff --git a/kern/include/ros/cpu_feat.h b/kern/include/ros/cpu_feat.h
new file mode 100644 (file)
index 0000000..1834699
--- /dev/null
@@ -0,0 +1,21 @@
+/* Copyright (c) 2016 Google Inc.
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * CPU feature detection.
+ *
+ * You can add new items as needed.  Changing __CPU_FEAT_ARCH_START will require
+ * a rebuild of the world.  Otherwise, you just need to reinstall kernel
+ * headers. */
+
+#pragma once
+
+#include <ros/common.h>
+
+#define CPU_FEAT_VMM                                   1
+#define __CPU_FEAT_ARCH_START                  64
+
+#include <ros/arch/cpu_feat.h>
+
+#define __NR_CPU_FEAT_BITS DIV_ROUND_UP(__NR_CPU_FEAT,                         \
+                                        sizeof(unsigned long) * 8)
index 53d5b6f..26a8363 100644 (file)
@@ -7,6 +7,7 @@
 #include <ros/resource.h>
 #include <ros/atomic.h>
 #include <ros/arch/arch.h>
+#include <ros/cpu_feat.h>
 #include <string.h>
 
 /* Process creation flags */
@@ -65,7 +66,7 @@ typedef struct procinfo {
 
 /* We align this so that the kernel can easily allocate it in the BSS */
 struct proc_global_info {
-
+       unsigned long cpu_feats[__NR_CPU_FEAT_BITS];
 } __attribute__((aligned(PGSIZE)));
 #define PROCGINFO_NUM_PAGES  (sizeof(struct proc_global_info) / PGSIZE)
 
index 57541a6..b38c032 100644 (file)
@@ -1 +1,25 @@
-// This file is empty for the time being...
+/* Copyright (c) 2016 Google Inc.
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * Glibc uses this header to set a bunch of #defines to show what is supported
+ * on a particular kernel version.  They set things like __ASSUME_AT_RANDOM.
+ *
+ * On Akaros, we'll eventually set those too.  This is also a good place for
+ * exporting all of the cpu feature detection to glibc.
+ *
+ * Note that this file is only included within glibc itself; it won't appear in
+ * the sysroot.  Use parlib/cpu_feat.h for that. */
+
+#pragma once
+
+#include <ros/procinfo.h>
+
+static inline bool cpu_has_feat(int feature)
+{
+       size_t bits_per_long = sizeof(unsigned long) * 8;
+       unsigned long *cpu_feats = __proc_global_info.cpu_feats;
+
+       return (cpu_feats[feature / bits_per_long] &
+               (1UL << (feature % bits_per_long))) != 0;
+}
diff --git a/user/parlib/include/parlib/cpu_feat.h b/user/parlib/include/parlib/cpu_feat.h
new file mode 100644 (file)
index 0000000..c43ecfd
--- /dev/null
@@ -0,0 +1,18 @@
+/* Copyright (c) 2016 Google Inc.
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * Query the existence of cpu features. */
+
+#pragma once
+
+#include <ros/procinfo.h>
+
+static inline bool cpu_has_feat(int feature)
+{
+       size_t bits_per_long = sizeof(unsigned long) * 8;
+       unsigned long *cpu_feats = __proc_global_info.cpu_feats;
+
+       return (cpu_feats[feature / bits_per_long] &
+               (1UL << (feature % bits_per_long))) != 0;
+}