diff --git a/CMakeLists.txt b/CMakeLists.txt
index be56cd04b3f2bedb0f6232cc84130c090ccaa3f9..8de0da42f31ae52d07483604c4d44ec0796a45a4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -308,7 +308,7 @@ add_dependencies(build_bundled_libs coro)
 
 if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "86" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "amd64")
     add_definitions("-DCORO_ASM")
-elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm")
+elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64")
     add_definitions("-DCORO_ASM")
 else()
     add_definitions("-DCORO_SJLJ")
diff --git a/third_party/coro/coro.c b/third_party/coro/coro.c
index f5b3f99d204a2bbb658682cb2091a5d414a2e0b5..75816fcc2be051d616bc6baab81c158ab5ee0248 100644
--- a/third_party/coro/coro.c
+++ b/third_party/coro/coro.c
@@ -82,7 +82,7 @@
  * saved registers. Alternatively, we can pass parameters via globals at
  * the cost of 2 additional coro_transfer calls in coro_create.
  */
-# if CORO_ASM && __arm__
+# if CORO_ASM && (__arm__ || __aarch64__)
 #  define CORO_STARTUP 1
 # else
 #  define CORO_STARTUP 0
@@ -260,6 +260,35 @@ trampoline (int sig)
          "\tvpop {d8-d15}\n"
          "\tmov r15, lr\n"
 
+       #elif __aarch64__
+
+         #define NUM_SAVED 20
+         "\tsub x2, sp, #8 * 20\n"
+         "\tstp x19, x20, [x2, #16 * 0]\n"
+         "\tstp x21, x22, [x2, #16 * 1]\n"
+         "\tstp x23, x24, [x2, #16 * 2]\n"
+         "\tstp x25, x26, [x2, #16 * 3]\n"
+         "\tstp x27, x28, [x2, #16 * 4]\n"
+         "\tstp x29, x30, [x2, #16 * 5]\n"
+         "\tstp d8,  d9,  [x2, #16 * 6]\n"
+         "\tstp d10, d11, [x2, #16 * 7]\n"
+         "\tstp d12, d13, [x2, #16 * 8]\n"
+         "\tstp d14, d15, [x2, #16 * 9]\n"
+         "\tstr x2, [x0, #0]\n"
+         "\tldr x3, [x1, #0]\n"
+         "\tldp x19, x20, [x3, #16 * 0]\n"
+         "\tldp x21, x22, [x3, #16 * 1]\n"
+         "\tldp x23, x24, [x3, #16 * 2]\n"
+         "\tldp x25, x26, [x3, #16 * 3]\n"
+         "\tldp x27, x28, [x3, #16 * 4]\n"
+         "\tldp x29, x30, [x3, #16 * 5]\n"
+         "\tldp d8,  d9,  [x3, #16 * 6]\n"
+         "\tldp d10, d11, [x3, #16 * 7]\n"
+         "\tldp d12, d13, [x3, #16 * 8]\n"
+         "\tldp d14, d15, [x3, #16 * 9]\n"
+         "\tadd sp, x3, #8 * 20\n"
+         "\tret\n"
+
        #else
          #error unsupported architecture
        #endif
@@ -279,11 +308,24 @@ trampoline (int sig)
          "\tmov lr, #0\n"
          "\tpush {lr}\n"
          "\tsub sp, #12\n"
-         "\tmov r1, r5\n"
+         "\tmov r0, r5\n"
          "\tblx r4\n"
          "\tb abort\n"
          ".fnend\n"
 
+       #elif __aarch64__
+
+         ".cfi_startproc\n"
+         "\tmov x30, #0\n"
+         "\tsub sp, sp, #16\n"
+         "\tstr x30, [sp, #0]\n"
+         ".cfi_def_cfa_offset 16\n"
+         ".cfi_offset 30, -16\n"
+         "\tmov x0, x20\n"
+         "\tblr x19\n"
+         "\tb abort\n"
+         ".cfi_endproc\n"
+
        #else
          #error unsupported architecture
        #endif
@@ -422,7 +464,7 @@ coro_create (coro_context *ctx, coro_func coro, void *arg, void *sptr, size_t ss
 #if __i386 || __x86_64
   *--ctx->sp = (void *)0;
   *--ctx->sp = (void *)coro_init;
-#elif __arm__ && __ARM_ARCH == 7
+#elif (__arm__ && __ARM_ARCH == 7) || __aarch64__
   /* return address stored in lr register, don't push anything */
 #else
   #error unsupported architecture
@@ -443,6 +485,10 @@ coro_create (coro_context *ctx, coro_func coro, void *arg, void *sptr, size_t ss
   ctx->sp[0] = coro; /* r4 */
   ctx->sp[1] = arg;  /* r5 */
   ctx->sp[8] = (void *)coro_startup; /* lr */
+#elif __aarch64__
+  ctx->sp[0] = coro; /* x19 */
+  ctx->sp[1] = arg;  /* x20 */
+  ctx->sp[11] = (void *)coro_startup; /* lr */
 #else
   #error unsupported architecture
 #endif
diff --git a/third_party/coro/coro.h b/third_party/coro/coro.h
index 8ed6181cd7d7a09c012afa31b56849e0535cc9bf..cc277e278640320a69018c6390eca4ff87888cce 100644
--- a/third_party/coro/coro.h
+++ b/third_party/coro/coro.h
@@ -375,7 +375,7 @@ struct coro_context
   void **sp; /* must be at offset 0 */
 };
 
-#if !__arm__
+#if !__arm__ && !__aarch64__
 void __attribute__ ((__noinline__, __regparm__(2)))
 coro_transfer (coro_context *prev, coro_context *next);
 #else