Merge pull request #5174
pull/200/head0de14396
tests: add a CNv4 JIT test (moneromooo-monero)24d281c3
crypto: plug CNv4 JIT into cn_slow_hash (moneromooo-monero)78ab59ea
crypto: clear cache after generating random program (moneromooo-monero)b9a61884
performance_tests: add tests for new Cryptonight variants (moneromooo-monero)fff23bf7
CNv4 JIT compiler for x86-64 and tests (SChernykh)3dde67d8
blockchain: add v10 fork heights (moneromooo-monero)
commit
815c8a48ab
@ -0,0 +1,102 @@
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "int-util.h"
|
||||
#include "hash-ops.h"
|
||||
#include "variant4_random_math.h"
|
||||
#include "CryptonightR_JIT.h"
|
||||
#include "CryptonightR_template.h"
|
||||
|
||||
static const uint8_t prologue[] = {
|
||||
0x4C, 0x8B, 0xD7, // mov r10, rdi
|
||||
0x53, // push rbx
|
||||
0x55, // push rbp
|
||||
0x41, 0x57, // push r15
|
||||
0x4C, 0x8B, 0xDC, // mov r11, rsp
|
||||
0x41, 0x8B, 0x1A, // mov ebx, DWORD PTR [r10]
|
||||
0x41, 0x8B, 0x72, 0x04, // mov esi, DWORD PTR [r10+4]
|
||||
0x41, 0x8B, 0x7A, 0x08, // mov edi, DWORD PTR [r10+8]
|
||||
0x41, 0x8B, 0x6A, 0x0C, // mov ebp, DWORD PTR [r10+12]
|
||||
0x41, 0x8B, 0x62, 0x10, // mov esp, DWORD PTR [r10+16]
|
||||
0x45, 0x8B, 0x7A, 0x14, // mov r15d, DWORD PTR [r10+20]
|
||||
0x41, 0x8B, 0x42, 0x18, // mov eax, DWORD PTR [r10+24]
|
||||
0x41, 0x8B, 0x52, 0x1C, // mov edx, DWORD PTR [r10+28]
|
||||
0x45, 0x8B, 0x4A, 0x20, // mov r9d, DWORD PTR [r10+32]
|
||||
};
|
||||
|
||||
static const uint8_t epilogue[] = {
|
||||
0x49, 0x8B, 0xE3, // mov rsp, r11
|
||||
0x41, 0x89, 0x1A, // mov DWORD PTR [r10], ebx
|
||||
0x41, 0x89, 0x72, 0x04, // mov DWORD PTR [r10+4], esi
|
||||
0x41, 0x89, 0x7A, 0x08, // mov DWORD PTR [r10+8], edi
|
||||
0x41, 0x89, 0x6A, 0x0C, // mov DWORD PTR [r10+12], ebp
|
||||
0x41, 0x5F, // pop r15
|
||||
0x5D, // pop rbp
|
||||
0x5B, // pop rbx
|
||||
0xC3, // ret
|
||||
};
|
||||
|
||||
#define APPEND_CODE(src, size) \
|
||||
do { \
|
||||
if (JIT_code + (size) > JIT_code_end) \
|
||||
return -1; \
|
||||
memcpy(JIT_code, (src), (size)); \
|
||||
JIT_code += (size); \
|
||||
} while (0)
|
||||
|
||||
int v4_generate_JIT_code(const struct V4_Instruction* code, v4_random_math_JIT_func buf, const size_t buf_size)
|
||||
{
|
||||
uint8_t* JIT_code = (uint8_t*) buf;
|
||||
const uint8_t* JIT_code_end = JIT_code + buf_size;
|
||||
|
||||
APPEND_CODE(prologue, sizeof(prologue));
|
||||
|
||||
uint32_t prev_rot_src = 0xFFFFFFFFU;
|
||||
|
||||
for (int i = 0;; ++i)
|
||||
{
|
||||
const struct V4_Instruction inst = code[i];
|
||||
if (inst.opcode == RET)
|
||||
break;
|
||||
|
||||
const uint8_t opcode = (inst.opcode == MUL) ? inst.opcode : (inst.opcode + 2);
|
||||
|
||||
const uint32_t a = inst.dst_index;
|
||||
const uint32_t b = inst.src_index;
|
||||
const uint8_t c = opcode | (inst.dst_index << V4_OPCODE_BITS) | (((inst.src_index == 8) ? inst.dst_index : inst.src_index) << (V4_OPCODE_BITS + V4_DST_INDEX_BITS));
|
||||
|
||||
switch (inst.opcode)
|
||||
{
|
||||
case ROR:
|
||||
case ROL:
|
||||
if (b != prev_rot_src)
|
||||
{
|
||||
prev_rot_src = b;
|
||||
const uint8_t* p1 = (const uint8_t*) instructions_mov[c];
|
||||
const uint8_t* p2 = (const uint8_t*) instructions_mov[c + 1];
|
||||
APPEND_CODE(p1, p2 - p1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (a == prev_rot_src)
|
||||
prev_rot_src = 0xFFFFFFFFU;
|
||||
|
||||
const uint8_t* p1 = (const uint8_t*) instructions[c];
|
||||
const uint8_t* p2 = (const uint8_t*) instructions[c + 1];
|
||||
APPEND_CODE(p1, p2 - p1);
|
||||
|
||||
if (inst.opcode == ADD)
|
||||
*(uint32_t*)(JIT_code - 4) = inst.C;
|
||||
}
|
||||
|
||||
APPEND_CODE(epilogue, sizeof(epilogue));
|
||||
|
||||
__builtin___clear_cache((char*)buf, (char*)JIT_code);
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
#ifndef CRYPTONIGHTR_JIT_H
|
||||
#define CRYPTONIGHTR_JIT_H
|
||||
|
||||
// Minimalistic JIT code generator for random math sequence in CryptonightR
|
||||
//
|
||||
// Usage:
|
||||
// - Allocate writable and executable memory
|
||||
// - Call v4_generate_JIT_code with "buf" pointed to memory allocated on previous step
|
||||
// - Call the generated code instead of "v4_random_math(code, r)", omit the "code" parameter
|
||||
|
||||
typedef void (*v4_random_math_JIT_func)(uint32_t* r) __attribute__((sysv_abi));
|
||||
|
||||
// Given the random math sequence, generates machine code (x86-64) for it
|
||||
// Returns 0 if code was generated successfully
|
||||
// Returns -1 if provided buffer was too small
|
||||
int v4_generate_JIT_code(const struct V4_Instruction* code, v4_random_math_JIT_func buf, const size_t buf_size);
|
||||
|
||||
#endif // CRYPTONIGHTR_JIT_H
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,119 @@
|
||||
// Copyright (c) 2019, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "crypto/hash-ops.h"
|
||||
|
||||
extern volatile int use_v4_jit_flag;
|
||||
|
||||
static int test(const uint8_t *data, size_t len, uint64_t height)
|
||||
{
|
||||
char hash0[32], hash1[32];
|
||||
use_v4_jit_flag = 0;
|
||||
cn_slow_hash(data, len, hash0, 4, 0, height);
|
||||
use_v4_jit_flag = 1;
|
||||
cn_slow_hash(data, len, hash1, 4, 0, height);
|
||||
return memcmp(hash0, hash1, 32);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
uint8_t data[64];
|
||||
uint64_t start_height = 1788000;
|
||||
uint64_t end_height = 1788001;
|
||||
|
||||
if (argc != 1 && argc != 2 && argc != 3)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [<start_height> [<end_height>]]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if (argc > 1)
|
||||
{
|
||||
errno = 0;
|
||||
start_height = strtoull(argv[1], NULL, 10);
|
||||
if ((start_height == 0 && errno) || start_height == ULLONG_MAX)
|
||||
{
|
||||
fprintf(stderr, "invalid start_height\n");
|
||||
return 1;
|
||||
}
|
||||
end_height = start_height;
|
||||
if (argc > 2)
|
||||
{
|
||||
errno = 0;
|
||||
end_height = strtoull(argv[2], NULL, 10);
|
||||
if ((end_height == 0 && errno) || end_height == ULLONG_MAX)
|
||||
{
|
||||
fprintf(stderr, "invalid end_height\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (start_height == end_height)
|
||||
{
|
||||
uint64_t counter = 0;
|
||||
while (1)
|
||||
{
|
||||
printf("\r%llu", (unsigned long long)counter);
|
||||
fflush(stdout);
|
||||
size_t offset = 0;
|
||||
while (offset + 8 < sizeof(data))
|
||||
{
|
||||
memcpy(data + offset, &counter, sizeof(counter));
|
||||
offset += 8;
|
||||
}
|
||||
if (test(data, sizeof(data), start_height))
|
||||
{
|
||||
fprintf(stderr, "\nFailure at height %llu, counter %llu\n", (unsigned long long)start_height, (unsigned long long)counter);
|
||||
return 0;
|
||||
}
|
||||
++counter;
|
||||
}
|
||||
}
|
||||
|
||||
memset(data, 0x42, sizeof(data));
|
||||
for (uint64_t h = start_height; h < end_height; ++h)
|
||||
{
|
||||
printf("\r%llu/%llu", (unsigned long long)(h-start_height), (unsigned long long)(end_height-start_height));
|
||||
fflush(stdout);
|
||||
if (test(data, sizeof(data), h))
|
||||
{
|
||||
fprintf(stderr, "\nFailure at height %llu\n", (unsigned long long)h);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\r");
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in new issue