Add SSE4 optimized SHA256 #10821

pull sipa wants to merge 5 commits into bitcoin:master from sipa:20170713_shasse changing 8 files +1681 −88
  1. sipa commented at 6:46 am on July 14, 2017: member

    This adds an SSE4 assembly version of the SHA256 transform by Intel, and uses it at run time if SSE4 instructions are available, and use a fallback C++ implementation otherwise. Nearly every x86_64 CPU supports SSE4. The feature is only enabled when compiled with --enable-experimental-asm.

    In order to avoid build dependencies and other complications, the original Intel YASM code was translated to GCC extended asm syntax.

    This gives around a 50% speedup on the SHA256 benchmark for me.

    It is based on an earlier patch by @laanwj, though only includes a single assembly version (for now), and removes the YASM dependency.

  2. in src/crypto/sha256.cpp:181 in e486f5774d outdated
    237+{
    238+    TransformType fn = sha256::Transform;
    239+
    240+#if defined(__x86_64__) || defined(__amd64__)
    241+    uint32_t eax, ebx, ecx, edx;
    242+    if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx >> 20) & 1) {
    


    laanwj commented at 6:57 am on July 14, 2017:
    I’d prefer to do this setup explicitly during initialization; this also avoids having to use an atomic pointer, which seems overkill (why would it ever change during runtime?) and may be inefficient on some platforms. (also the detection might be more involved on some platforms, so it’s better for clarity to drive it from an init function instead of magically at first call).

    theuni commented at 1:07 pm on July 14, 2017:

    We also have the option of using the ifunc attribute, supported on recent binutils with at least gcc and clang.

    Though it’s non-standard and afaik elf-specific, it’s worth considering where possible.


    gmaxwell commented at 2:50 am on July 16, 2017:
    do we have constructors with hashing in them?

    sipa commented at 7:54 am on July 16, 2017:
    @laanwj Fixed.
  3. luke-jr commented at 7:15 am on July 14, 2017: member
    Even with inline assembly, there are build complications unfortunately. The compile will fail if the target doesn’t support it..
  4. laanwj added the label Validation on Jul 14, 2017
  5. laanwj added the label Utils and libraries on Jul 14, 2017
  6. sipa force-pushed on Jul 14, 2017
  7. sipa commented at 8:36 am on July 14, 2017: member
    @luke-jr There are system macros to test whether you’re compiling for x86_64 or not.
  8. luke-jr commented at 9:34 am on July 14, 2017: member
    You said almost every x86_64 CPU. Are we going to drop support for the outliers then?
  9. meshcollider commented at 10:13 am on July 14, 2017: contributor
    One of the travis builds obviously has an issue with it too: crypto/sha256_sse42.cpp:42:9: error: inline assembly requires more registers than available
  10. theuni commented at 4:11 pm on July 14, 2017: member
    The clang/osx build succeeds when -fomit-frame-pointer is used. I don’t speak enough asm to know if a register can be freed up.
  11. gmaxwell commented at 4:20 pm on July 14, 2017: contributor

    Even with inline assembly, there are build complications unfortunately. The compile will fail if the target doesn’t support it..

    No it won’t– these files are compiled without -msse4.2 already. The only thing required is that its x86_64, which the build tests for.

  12. sipa commented at 6:24 pm on July 14, 2017: member
    @luke-jr There is runtime detection to see if the CPU supports the extension. The only requirement is that the target is x86_64.
  13. jonasschnelli commented at 7:11 pm on July 14, 2017: contributor

    Gitian OSX build is broken (https://bitcoin.jonasschnelli.ch/build/216):

    0Generated test/data/base58_keys_invalid.json.h
    1crypto/sha256_sse42.cpp:42:9: error: inline assembly requires more registers than available
    2        "shl    $0x6,%2;"
    3        ^
    41 error generated.
    

    No problem on Win/ OSX Linux

  14. sipa commented at 7:41 pm on July 14, 2017: member
    @jonasschnelli @theuni figured it out - clang isn’t compiling with -fomit-frame-pointer, and thus there is one fewer register available. Unfortunately, omitting the frame pointer still makes this code not work…
  15. sipa force-pushed on Jul 14, 2017
  16. sipa commented at 10:11 pm on July 14, 2017: member
    Updated the code to use one fewer register. The original YASM code used the dx register for two purposes, which I had separated out into two separate registers. They’re merged now.
  17. sipa force-pushed on Jul 14, 2017
  18. sipa force-pushed on Jul 14, 2017
  19. in src/crypto/sha256_sse42.cpp:975 in dc1fa8410c outdated
    970+; * Redistributions in binary form must reproduce the above copyright
    971+;   notice, this list of conditions and the following disclaimer in the
    972+;   documentation and/or other materials provided with the
    973+;   distribution. 
    974+; 
    975+; * Neither the name of the Intel Corporation nor the names of its
    


    TheBlueMatt commented at 11:28 pm on July 14, 2017:
    We’re gonna have to do something to meet this condition, though it doesnt appear we’d have to do much.

    gmaxwell commented at 11:33 pm on July 14, 2017:
    This is the standard three clause BSD license, it is GPL and whatnot compatible. The source code to Bitcoin, which contains this notice, is part of the “documentation and/or other materials” we provide.

    TheBlueMatt commented at 11:37 pm on July 14, 2017:
    We ship sans-source all the time? I figured we’d just put a “contains softare copyright Intel” in the –help output or a README somewhere.
  20. sipa force-pushed on Jul 15, 2017
  21. sipa renamed this:
    Add SSE 4.2 optimized SHA256
    [WIP] Add SSE 4.2 optimized SHA256
    on Jul 15, 2017
  22. sipa commented at 1:05 am on July 15, 2017: member
    Marking as WIP, as this does not seem to produce correct hashes on OSX (cc @theuni).
  23. sipa force-pushed on Jul 15, 2017
  24. theuni commented at 5:46 am on July 15, 2017: member
    I poked at this for hours and came up empty-handed. I’ll wait for someone else to confirm my osx breakage isn’t just local.
  25. theuni commented at 6:51 am on July 15, 2017: member

    two more data points:

    1. @fanquake verified that this crashes on osx for him as well.

    2. I managed to reproduce a crash on Linux with an old clang (3.2), and it’s even uglier, crashing gdb as well:

    Starting program: /home/cory/dev/bitcoin2/src/bitcoind [Thread debugging using libthread_db enabled] Using host libthread_db library “/lib/x86_64-linux-gnu/libthread_db.so.1”.

    Program received signal SIGSEGV, Segmentation fault. /build/buildd/gdb-7.6~20130417/gdb/dwarf2read.c:10350: internal-error: dwarf2_record_block_ranges: Assertion dwarf2_per_objfile->ranges.readin' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Quit this debugging session? (y or n) n /build/buildd/gdb-7.6~20130417/gdb/dwarf2read.c:10350: internal-error: dwarf2_record_block_ranges: Assertion dwarf2_per_objfile->ranges.readin’ failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Create a core file of GDB? (y or n) n 0x000000000074c910 in sha256_sse42::Transform ( /build/buildd/gdb-7.6~20130417/gdb/dwarf2read.c:10350: internal-error: dwarf2_record_block_ranges: Assertion dwarf2_per_objfile->ranges.readin' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Quit this debugging session? (y or n) n /build/buildd/gdb-7.6~20130417/gdb/dwarf2read.c:10350: internal-error: dwarf2_record_block_ranges: Assertion dwarf2_per_objfile->ranges.readin’ failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Create a core file of GDB? (y or n) n Segmentation fault (core dumped)

  26. sipa force-pushed on Jul 15, 2017
  27. sipa force-pushed on Jul 16, 2017
  28. sipa force-pushed on Jul 16, 2017
  29. theuni commented at 6:41 am on July 16, 2017: member

    Tested ACK 08b7438f73236fc738fb655f766e77a81e6b7311. Good on OSX now!

    Edit: Though I’d prefer to have the cpu check done separately.

  30. sipa renamed this:
    [WIP] Add SSE 4.2 optimized SHA256
    Add SSE 4.2 optimized SHA256
    on Jul 16, 2017
  31. sipa commented at 6:43 am on July 16, 2017: member
    Removing WIP tag, I believe we solved the OSX problem.
  32. sipa force-pushed on Jul 16, 2017
  33. fanquake commented at 10:20 am on July 16, 2017: member

    Confirmed that this now runs on OSX.

    Running src/bench/bench_bitcoin master (https://github.com/bitcoin/bitcoin/commit/5cfdda2503c995cdd563b1a2a29162ac298d173d)

    0SHA256,30,0.034190416336060,0.035426974296570,0.034737364451090,115983933,120179929,117843926
    1SHA256,30,0.033560991287231,0.037778496742249,0.035649696985881,113846584,128155476,120938933
    2SHA256,30,0.033833026885986,0.035175085067749,0.034680000940959,114771438,119322675,117649641
    3SHA256_32b,2,2.333264589309692,2.333264589309692,2.333264589309692,7915485729,7915485729,7915485729
    4SHA256_32b,2,2.289189100265503,2.289189100265503,2.289189100265503,7765884738,7765884738,7765884738
    5SHA256_32b,2,2.370669960975647,2.370669960975647,2.370669960975647,8042288399,8042288399,8042288399
    

    master (https://github.com/bitcoin/bitcoin/commit/5cfdda2503c995cdd563b1a2a29162ac298d173d) + this PR

    0SHA256,320,0.003191620111465,0.003264248371124,0.003223562240601,10826857,11073394,10935724
    1SHA256,352,0.003048248589039,0.003163591027260,0.003104761242867,10340442,10731709,10532673
    2SHA256,352,0.003055907785892,0.003142252564430,0.003093159334226,10366424,10659420,10493303
    3SHA256_32b,4,0.324660062789917,0.329437971115112,0.327049016952515,1101416645,1117628996,1109522820
    4SHA256_32b,4,0.327362537384033,0.329176425933838,0.328269481658936,1110585003,1116655624,1113620313
    5SHA256_32b,4,0.325733423233032,0.331611037254333,0.328672230243683,1105059350,1124999710,1115029530
    
  34. gmaxwell commented at 2:06 pm on July 16, 2017: contributor
    This should do something to print what implementation its using to help spot runtime auto-detection bugs.
  35. sipa commented at 5:28 pm on July 16, 2017: member
    @gmaxwell Already done
  36. sipa commented at 6:31 pm on July 16, 2017: member
    Added an extra commit that performs a self-test before selecting an optimized transform function.
  37. sipa commented at 6:44 pm on July 16, 2017: member
    @fanquake Are you compiling with -O0 or something similar? This shouldn’t give a 10x speedup for the SHA256 benchmark. More like a factor 1.5x.
  38. jonasschnelli commented at 7:26 pm on July 16, 2017: contributor

    Tested ACK on my OSX box as well as on a Debian with Skylake

    CPU OSX: Intel(R) Core(TM) i7-6920HQ CPU @ 2.90GHz CPU Debian: Intel(R) Xeon(R) CPU E3-1275 v5 @ 3.60GHz

    Perf.-improvements: factor ~1.6.

    —- DETAILS:

    Exts OSX:

    0SMEP ERMS RDWRFSGS TSC_THREAD_OFFSET BMI1 HLE AVX2 BMI2 INVPCID RTM SMAP RDSEED ADX IPT SGX FPU_CSDS MPX CLFSOPT
    1FPU VME DE PSE TSC MSR PAE MCE CX8 APIC SEP MTRR PGE MCA CMOV PAT PSE36 CLFSH DS ACPI MMX FXSR SSE SSE2 SS HTT TM PBE SSE3 PCLMULQDQ DTES64 MON DSCPL VMX SMX EST TM2 SSSE3 FMA CX16 TPR PDCM SSE4.1 SSE4.2 x2APIC MOVBE POPCNT AES PCID XSAVE OSXSAVE SEGLIM64 TSCTMR AVX1.0 RDRAND F16C
    

    Exts Debian:

    0flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch ida arat epb xsaveopt pln pts dtherm tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt
    

    OSX Master

    0SHA1,576,0.001819185912609,0.002340316772461,0.001918800589111,5282892,6796157,5572193
    1SHA256,208,0.004609435796738,0.005578860640526,0.004965331691962,13385764,16201094,14419137
    2SHA256_32b,4,0.332423448562622,0.333897590637207,0.333160519599915,965338619,969639015,967488817
    3SHA512,352,0.002628467977047,0.003746151924133,0.002973860637708,7633100,10878782,8636088
    

    OSX This PR

    0SHA1,576,0.001871295273304,0.002110570669174,0.001951401018434,5434265,6129157,5666867
    1SHA256,352,0.002895936369896,0.003193676471710,0.002999408678575,8409812,9274468,8710180
    2SHA256_32b,6,0.216736078262329,0.222404479980469,0.219772179921468,629402126,645863039,638218484
    3SHA512,352,0.002783536911011,0.003117501735687,0.002889553931626,8083365,9053381,8391166
    

    Debian Master

    0SHA1,704,0.001483812928200,0.001535888761282,0.001513123512268,5341692,5529187,5447247
    1SHA256,256,0.003961175680161,0.004363536834717,0.004079484380782,14260373,15708338,14686141
    2SHA256_32b,4,0.281208992004395,0.283093929290771,0.282151460647583,1012352610,1019139204,1015745907
    3SHA512,416,0.002545125782490,0.002609595656395,0.002585454629018,9162493,9394502,9307633
    

    Debian This PR

    0SHA1,704,0.001500129699707,0.001563936471939,0.001528463241729,5400623,5630186,5502462
    1SHA256,384,0.002633377909660,0.002746812999249,0.002677822485566,9480191,9888481,9640152
    2SHA256_32b,6,0.190533041954041,0.193126082420349,0.191900690396627,685917852,695253649,690841909
    3SHA512,384,0.002558782696724,0.002740010619164,0.002604349205891,9211619,9863917,9375649
    

    (non 256 SHA’s are for comp. reference).

  39. sipa force-pushed on Jul 16, 2017
  40. sipa commented at 7:42 pm on July 16, 2017: member
    Rebased, and moved the autodetection to an explicit SHA256AutoDetect() function that is called during initialization.
  41. sipa force-pushed on Jul 16, 2017
  42. sipa commented at 11:50 pm on July 16, 2017: member
    Improved the self test (it now tests 0, 1, and 2-block transforms), and made it assert when the selftest fails rather than failing over to the standard implementation. This way, it won’t hide problems.
  43. gmaxwell approved
  44. gmaxwell commented at 0:39 am on July 17, 2017: contributor
    ACK
  45. sipa force-pushed on Jul 17, 2017
  46. sipa renamed this:
    Add SSE 4.2 optimized SHA256
    Add SSE4 optimized SHA256
    on Jul 17, 2017
  47. sipa force-pushed on Jul 17, 2017
  48. gmaxwell approved
  49. gmaxwell commented at 6:28 am on July 17, 2017: contributor
    re-ACK
  50. in src/crypto/sha256_sse4.cpp:60 in 7308332e70 outdated
    55+        "mov    0x1c(%0),%9;"
    56+        "movdqa %18,%%xmm12;"
    57+        "movdqa %19,%%xmm10;"
    58+        "movdqa %20,%%xmm11;"
    59+
    60+        "Lloop0_%=:"
    


    theuni commented at 1:36 pm on July 17, 2017:
    It’d be helpful to add a little note about the ‘L’ prefix and what problem it solves. If nothing else, it may turn up as a another useful google hit for someone in the future.
  51. in src/crypto/sha256.cpp:175 in 7308332e70 outdated
    249+    tr(buf, in2 + 1, 2);
    250+    if (memcmp(buf, out2, sizeof(buf))) return false;
    251+    return true;
    252+}
    253+
    254+TransformType Transform = sha256::Transform;
    


    theuni commented at 2:06 pm on July 17, 2017:
    Like with the rand init, I think we’d save ourselves from future oopses by setting this to nullptr initially, and letting SHA256AutoDetect() set the fallback to sha256::Transform if necessary.

    laanwj commented at 2:16 pm on July 17, 2017:
    I don’t think that will work - there is some SHA256 work before main (IIRC to set up the chain parameteters). Better if that uses the ‘canonical’ SHA256.

    theuni commented at 3:16 pm on July 17, 2017:
    Right, nevermind.

    sipa commented at 6:01 pm on July 17, 2017:
    Indeed, that is the reason.
  52. laanwj commented at 6:42 am on July 18, 2017: member
    utACK, looks good to me now, but I still think it’s too late for 0.15. At least to enable it by default, I’m ok with an --enable-experimental-asm option, then enabling it by default after the 0.15 branch-off.
  53. sipa commented at 8:07 am on July 18, 2017: member
    @laanwj Added a --enable-experimental-asm configure option, disabled by default.
  54. laanwj added this to the milestone 0.15.0 on Jul 18, 2017
  55. in configure.ac:183 in e0aa4ab6fe outdated
    176@@ -177,6 +177,16 @@ AC_ARG_ENABLE([glibc-back-compat],
    177   [use_glibc_compat=$enableval],
    178   [use_glibc_compat=no])
    179 
    180+AC_ARG_ENABLE([experimental-asm],
    181+  [AS_HELP_STRING([--enable-experimental-asm],
    182+  [Enable experimental assembly routines (default is no)])],
    183+  [experimental_asm=$withval],
    


    laanwj commented at 11:57 am on July 18, 2017:
    This should be $enableval, not $withval

    sipa commented at 4:22 pm on July 18, 2017:
    Strange, I tested this.

    laanwj commented at 4:34 pm on July 18, 2017:
    Me too, and it didn’t work for me unless I changed it. Using $withval here most llikelys pick up the last –with check result (for qrencode, which wasn’t installed in my case, so it always had no)

    sipa commented at 5:20 pm on July 18, 2017:
    Fixed.
  56. in configure.ac:1175 in e0aa4ab6fe outdated
    1171@@ -1162,6 +1172,7 @@ AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes])
    1172 AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes])
    1173 AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes])
    1174 AM_CONDITIONAL([ENABLE_HWCRC32],[test x$enable_hwcrc32 = xyes])
    1175+AM_CONDITIONAL([EXPERIMENTAL_ASM],[test x$experimental_asm = xyes])
    


    theuni commented at 4:56 pm on July 18, 2017:
    This is only needed if you intended to avoid compiling the _sse4.o variant altogether. AM_CONDITIONAL sets Makefile variables.

    theuni commented at 5:03 pm on July 18, 2017:

    On second thought, I’d actually prefer doing it that way in order to keep sha256_sse4.cpp completely generic. It was very helpful for me while testing to just throw together a quick test app using the .cpp directly.

    The makefile change would become:

    0if EXPERIMENTAL_ASM
    1crypto_libbitcoin_crypto_a_SOURCES += crypto/sha256_sse4.cpp
    2endif
    

    Then obviously the guard isn’t needed in the .cpp.


    sipa commented at 5:20 pm on July 18, 2017:
    Fixed.
  57. sipa force-pushed on Jul 18, 2017
  58. sipa commented at 5:20 pm on July 18, 2017: member
    Addressed comments, and tested.
  59. sipa force-pushed on Jul 18, 2017
  60. sipa force-pushed on Jul 18, 2017
  61. in src/crypto/sha256.cpp:13 in 66043d3682 outdated
    10@@ -11,11 +11,13 @@
    11 
    12 #if defined(__x86_64__) || defined(__amd64__)
    13 #include <cpuid.h>
    


    theuni commented at 5:33 pm on July 18, 2017:
    Nit: no need to risk including the not-guaranteed-to-exist header. Move the #if up a bit?

    sipa commented at 5:36 pm on July 18, 2017:
    Fixed.
  62. in src/crypto/sha256_sse4.cpp:9 in 66043d3682 outdated
    4@@ -5,6 +5,8 @@
    5 // This is a translation to GCC extended asm syntax from YASM code by Intel
    6 // (available at the bottom of this file).
    7 
    8+#include "config/bitcoin-config.h"
    9+
    


    theuni commented at 5:34 pm on July 18, 2017:
    Not needed anymore :)

    sipa commented at 5:36 pm on July 18, 2017:
    Fixed.
  63. theuni commented at 5:35 pm on July 18, 2017: member
    utACK modulo the small nits.
  64. sipa force-pushed on Jul 18, 2017
  65. gmaxwell approved
  66. gmaxwell commented at 1:07 am on July 20, 2017: contributor
    reACK
  67. Support multi-block SHA256 transforms
    Extracted from a patch by Wladimir van der Laan.
    4d50f38fe0
  68. Add SHA256 dispatcher 2991c91d88
  69. Add SSE4 based SHA256 c1ccb15b0e
  70. Add selftest for SHA256 transform fa9be909c9
  71. Protect SSE4 code behind a compile-time flag 6b8d872e5e
  72. in src/init.cpp:1164 in 03a0e554ba outdated
    1160@@ -1161,6 +1161,7 @@ bool AppInitSanityChecks()
    1161     // ********************************************************* Step 4: sanity checks
    1162 
    1163     // Initialize elliptic curve code
    1164+    LogPrintf("Using the '%s' SHA256 implementation\n", SHA256AutoDetect());
    


    laanwj commented at 7:32 am on July 20, 2017:
    Nit: Seems this is a log message with the side-effect of detecting the SHA256 implementation. I’d prefer to assign the result explicitly, so that if someone happens to comment this out, or moves it to debug category, it won’t just be skipped.

    sipa commented at 4:41 pm on July 20, 2017:
    Fixed.
  73. sipa force-pushed on Jul 20, 2017
  74. theuni commented at 4:39 pm on July 20, 2017: member
    utACK 6b8d872e5e2dd68a5229ec55f5261dae34ff9bdb, though I extensively tested earlier revisions.
  75. laanwj merged this on Jul 20, 2017
  76. laanwj closed this on Jul 20, 2017

  77. laanwj referenced this in commit 16240f43a5 on Jul 20, 2017
  78. sickpig referenced this in commit 01ccd3fba0 on Sep 13, 2017
  79. gandrewstone referenced this in commit f14b9740ed on Sep 13, 2017
  80. sickpig referenced this in commit 62ae4270f6 on Sep 17, 2017
  81. sickpig referenced this in commit 8352d1b0b0 on Oct 13, 2017
  82. gandrewstone referenced this in commit 115f739d1d on Oct 19, 2017
  83. Sjors commented at 7:16 am on October 20, 2017: member
    For future reference, as of #11176 this is now enabled by default.
  84. laanwj referenced this in commit 3a3eabef40 on Jul 9, 2018
  85. PastaPastaPasta referenced this in commit 2b6237dbc6 on Jul 17, 2019
  86. PastaPastaPasta referenced this in commit 3d48aee847 on Jul 17, 2019
  87. PastaPastaPasta referenced this in commit fec98b2168 on Jul 23, 2019
  88. PastaPastaPasta referenced this in commit c7dcf79f02 on Jul 24, 2019
  89. PastaPastaPasta referenced this in commit f38ed3c71b on Jul 24, 2019
  90. codablock referenced this in commit dda04a300e on Oct 1, 2019
  91. codablock referenced this in commit 1b2252c28c on Oct 1, 2019
  92. wqking referenced this in commit 59a2f87672 on Jan 22, 2020
  93. barrystyle referenced this in commit ad1246535f on Jan 22, 2020
  94. barrystyle referenced this in commit cf4ae925ef on Jan 22, 2020
  95. barrystyle referenced this in commit 9be0431b4c on Jan 22, 2020
  96. MarcoFalke locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-07-03 13:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me