riscv64 SCS support.

Bug: https://github.com/google/android-riscv64/issues/55
Test: treehugger
Change-Id: I05d48a07a302305126942d38529ffa280640c7b7
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 7222b62..083c2ed 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -105,9 +105,13 @@
 
   void* alternate_signal_stack;
 
-  // The start address of the shadow call stack's guard region (arm64 only).
+  // The start address of the shadow call stack's guard region (arm64/riscv64).
+  // This region is SCS_GUARD_REGION_SIZE bytes large, but only SCS_SIZE bytes
+  // are actually used.
+  //
   // This address is only used to deallocate the shadow call stack on thread
   // exit; the address of the stack itself is stored only in the x18 register.
+  //
   // Because the protection offered by SCS relies on the secrecy of the stack
   // address, storing the address here weakens the protection, but only
   // slightly, because it is relatively easy for an attacker to discover the
@@ -115,13 +119,22 @@
   // to other allocations), but not the stack itself, which is <0.1% of the size
   // of the guard region.
   //
+  // longjmp()/setjmp() don't store all the bits of x18, only the bottom bits
+  // covered by SCS_MASK. Since longjmp()/setjmp() between different threads is
+  // undefined behavior (and unsupported on Android), we can retrieve the high
+  // bits of x18 from the current value in x18 --- all the jmp_buf needs to store
+  // is where exactly the shadow stack pointer is in the thread's shadow stack:
+  // the bottom bits of x18.
+  //
   // There are at least two other options for discovering the start address of
   // the guard region on thread exit, but they are not as simple as storing in
   // TLS.
+  //
   // 1) Derive it from the value of the x18 register. This is only possible in
   //    processes that do not contain legacy code that might clobber x18,
   //    therefore each process must declare early during process startup whether
   //    it might load legacy code.
+  //    TODO: riscv64 has no legacy code, so we can actually go this route there!
   // 2) Mark the guard region as such using prctl(PR_SET_VMA_ANON_NAME) and
   //    discover its address by reading /proc/self/maps. One issue with this is
   //    that reading /proc/self/maps can race with allocations, so we may need