+#define COPYINWORD 5 /* from user virtual to kernel virtual */
+
+#if ENABLE_SMAPLOG
+typedef struct {
+ uint64_t timestamp;
+ thread_t thread;
+ uintptr_t cr4;
+ uint8_t cpuid;
+ uint8_t smap_state;
+ uint8_t copyio_active;
+} smaplog_entry_t;
+
+#define SMAPLOG_BUFFER_SIZE (50)
+static smaplog_entry_t smaplog_cbuf[SMAPLOG_BUFFER_SIZE];
+static uint32_t smaplog_head = 0;
+
+static void
+smaplog_add_entry(boolean_t enabling)
+{
+ uint32_t index = 0;
+ thread_t thread = current_thread();
+
+ do {
+ index = smaplog_head;
+ } while (!OSCompareAndSwap(index, (index + 1) % SMAPLOG_BUFFER_SIZE, &smaplog_head));
+
+ assert(index < SMAPLOG_BUFFER_SIZE);
+ assert(smaplog_head < SMAPLOG_BUFFER_SIZE);
+ assert(thread);
+
+ smaplog_cbuf[index].timestamp = mach_absolute_time();
+ smaplog_cbuf[index].thread = thread;
+ smaplog_cbuf[index].cpuid = cpu_number();
+ smaplog_cbuf[index].cr4 = get_cr4();
+ smaplog_cbuf[index].smap_state = enabling;
+ smaplog_cbuf[index].copyio_active = (thread->machine.specFlags & CopyIOActive) ? 1 : 0;
+}
+#endif /* ENABLE_SMAPLOG */
+
+extern boolean_t pmap_smap_enabled;
+static inline void user_access_enable(void) {
+ if (pmap_smap_enabled) {
+ stac();
+#if ENABLE_SMAPLOG
+ smaplog_add_entry(TRUE);
+#endif
+ }
+}
+static inline void user_access_disable(void) {
+ if (pmap_smap_enabled) {
+ clac();
+#if ENABLE_SMAPLOG
+ smaplog_add_entry(FALSE);
+#endif
+ }
+}