+#if DEVELOPMENT || DEBUG
+do_cacheline_stash:
+ /*
+ * Copy the cache line that includes the user's EIP/RIP into the shadow cpu structure
+ * for later extraction/sanity-checking in user_trap().
+ */
+
+ pushq %rbx
+ pushq %rcx
+L_dispatch_from_user_with_rbx_rcx_pushes:
+ movq 8+8+8+ISF64_RIP(%rsp), %rbx
+ andq $-64, %rbx /* Round address to cacheline boundary */
+ pushf
+ /*
+ * disable SMAP, if it's enabled (note that CLAC is present in BDW and later only, so we're
+ * using generic instructions here without checking whether the CPU supports SMAP first)
+ */
+ orq $(1 << 18), (%rsp)
+ popf
+ /*
+ * Note that we only check for a faulting read on the first read, since if the first read
+ * succeeds, the rest of the cache line should also be readible since we are running with
+ * interrupts disabled here and a TLB invalidation cannot sneak in and pull the rug out.
+ */
+ movq %cr2, %rcx /* stash the original %cr2 in case the first cacheline read triggers a #PF */
+ /* This value of %cr2 is restored in the page fault handler if it detects */
+ /* that the fault occurrent on the next instruction, so the original #PF can */
+ /* continue to be handled without issue. */
+rip_cacheline_read:
+ mov (%rbx), %rcx
+ /* Note that CPU_RTIMES in the shadow cpu struct was just a convenient place to stash the cacheline */
+ mov %rcx, %gs:CPU_RTIMES(%rax)
+ movq %cr2, %rcx
+ mov 8(%rbx), %rcx
+ mov %rcx, %gs:8+CPU_RTIMES(%rax)
+ movq %cr2, %rcx
+ mov 16(%rbx), %rcx
+ mov %rcx, %gs:16+CPU_RTIMES(%rax)
+ movq %cr2, %rcx
+ mov 24(%rbx), %rcx
+ mov %rcx, %gs:24+CPU_RTIMES(%rax)
+ movq %cr2, %rcx
+ mov 32(%rbx), %rcx
+ mov %rcx, %gs:32+CPU_RTIMES(%rax)
+ movq %cr2, %rcx
+ mov 40(%rbx), %rcx
+ mov %rcx, %gs:40+CPU_RTIMES(%rax)
+ movq %cr2, %rcx
+ mov 48(%rbx), %rcx
+ mov %rcx, %gs:48+CPU_RTIMES(%rax)
+ movq %cr2, %rcx
+rip_cacheline_read_end:
+ mov 56(%rbx), %rcx
+ mov %rcx, %gs:56+CPU_RTIMES(%rax)
+
+ pushf
+ andq $~(1 << 18), (%rsp) /* reenable SMAP */
+ popf
+
+ jmp cacheline_read_cleanup_stack
+
+abort_rip_cacheline_read:
+ pushf
+ andq $~(1 << 18), (%rsp) /* reenable SMAP */
+ popf
+abort_rip_cacheline_read_no_smap_reenable:
+ movl $0xdeadc0de, %ecx /* Write a sentinel so higher-level code knows this was aborted */
+ shlq $32, %rcx
+ movl $0xbeefcafe, %ebx
+ orq %rbx, %rcx
+ movq %rcx, %gs:CPU_RTIMES(%rax)
+ movq %rcx, %gs:8+CPU_RTIMES(%rax)
+
+cacheline_read_cleanup_stack:
+ popq %rcx
+ popq %rbx
+ jmp L_dispatch_kgsb
+#endif /* if DEVELOPMENT || DEBUG */
+