我在HLS(使用Vivado 2017.2)中编写了一个RSA加密块,我正试图在zedboard(Zynq 7020)的Linux下运行它。我已经验证了硬件的工作原理,并且具有功能齐全的裸机软件接口。请注意,HLS块是AXI4-lite从站。
在为它编写Linux内核模块(设备驱动程序)时,事情开始变得奇怪(注意我故意不通过Xilinx UIO框架,因为原因......创建我自己的内核模块)。 问题在于,每次启动块并保持输入不变时,结果都会发生变化。这不是硬件块的行为方式,我在SDK中的裸机测试中对此进行了验证。所以在我的内核模块中,鉴于这一点,它一定是奇怪的......对吗?
嗯,实际上没有。不想浪费时间在内核上调试,我决定通过绕过内核模块来决定获取一些基础事实数据,而是使用devmem2直接读/写硬件。只是为了确保我不会疯狂,并再次肯定硬件的工作原理。但是,令我沮丧的是,使用devmem2手动写入输入寄存器返回了垃圾(不正确)数据。每次启动块时它都会返回不同的垃圾数据,即使我没有更改输入。
我再次检查了裸机硬件的工作原理。确实如此。我甚至打印出我写入AXI寄存器的EXACT值,以防万一我弄乱了bye-Endianness(因为每个1024位输入有32个输入寄存器,我想也许我正在向后写字?) 。一旦我获得了EXACT值,我正在写入裸机驱动程序中的输入端口,我继续编写一个脚本,使用devmem2手动写入每个寄存器。这绝对是我写的正确值。
加载输入值(基数,指数,模数和工作模式)后,我将0x1写入ap_ctrl寄存器以启动该块。
答案每次都不一样。
我没有IDEA这里发生了什么。再次,当我使用Xilinx裸机驱动程序向其写入数据时硬件工作。但是在Linux下,即使使用devmem2直接写入物理内存,一切都会中断。我知道它很可能不是硬件,因为它每次都会返回一个不同的错误答案。
所以我完全不知道如何进行调试。作为参考,让我将裸机驱动程序与linux devmem2方法进行比较:
裸金属加密功能:
uint8_t privexp_arr[] = {0xA1,0x11,0xAD,0xAD,0x48,0x88,0xF5,0x2D,0x35,0xF5,0x42,0x8E,0x39,0x39,0x68,0x06,0xBE,0x32,0x52,0x5C,0xDA,0x2B,0xF2,0x2A,0x27,0x58,0x1B,0xDE,0xEE,0x18,0x63,0x92,0xD8,0x9F,0x02,0x2C,0xFB,0xDF,0x77,0xE6,0x1F,0xDB,0xDC,0x84,0x6C,0x90,0x38,0xA0,0x8D,0x8A,0xEB,0x5C,0x2A,0xF7,0xCC,0x25,0x9D,0x62,0xBA,0xB5,0xB2,0xB8,0x7B,0xCD,0x66,0xD6,0x77,0xD5,0x32,0x9D,0xF1,0x98,0x9C,0xB1,0xAC,0x50,0x23,0x7C,0xCF,0x28,0x69,0x32,0xD9,0x3A,0x21,0x82,0x9D,0xE0,0xE1,0xBA,0x12,0x3C,0x79,0x95,0x10,0x7A,0x50,0x6E,0xA2,0x91,0x87,0x04,0x2B,0x6F,0xE4,0x8C,0x05,0x51,0x31,0x81,0x50,0xE9,0x52,0x69,0x09,0xCF,0x68,0x1D,0x74,0x88,0x6B,0x17,0x43,0xE8,0xFD,0x9C,0x7B,0x04};
uint32_t publexp_arr [] = {0x10001,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
uint8_t modulus_arr[] = {0x49,0xF5,0xEB,0x73,0x5B,0x82,0x9C,0xEB,0x4B,0xC2,0xAF,0x74,0x64,0x29,0x38,0xA8,0xAF,0x7E,0xA4,0x77,0xBA,0x9C,0x79,0xB6,0x9B,0x5E,0x65,0xBC,0xBA,0x74,0x84,0x3E,0x84,0xBF,0x5C,0xD4,0xD1,0xF4,0xEC,0xD4,0x83,0x3D,0xC6,0x9B,0x7B,0x52,0x5C,0x2F,0x25,0x79,0x6D,0x21,0x79,0xB3,0x31,0x7A,0x0D,0xAD,0xB1,0xB9,0xDC,0x5F,0xE5,0x3D,0x13,0x21,0xF6,0xFB,0x97,0x1A,0xFB,0xB9,0x7F,0x4D,0x26,0x0F,0x10,0x37,0xEA,0xEA,0xEC,0x97,0xA4,0x79,0x37,0xFB,0x62,0x33,0x9E,0xB3,0x28,0xC4,0x30,0x8A,0xA6,0x94,0x9A,0x9F,0x0D,0xDF,0xE2,0xF5,0xB4,0x1F,0x25,0x4F,0xE1,0x6F,0x35,0xBF,0x82,0xBF,0xE6,0xA2,0xA0,0x15,0x80,0xA1,0x69,0x97,0xD8,0x3D,0x85,0x88,0x9E,0x88,0x4D,0xD9};
const uint8_t ciphertext_golden_ans[] = {0xF0,0xCA,0x37,0xC7,0xFA,0x38,0xB3,0xDF,0x00,0xA6,0xFA,0x10,0x14,0xEA,0xD7,0x36,0x83,0x61,0x5F,0x12,0x29,0x6C,0x19,0xC3,0x3A,0xC6,0x03,0xC9,0x74,0xF2,0x9E,0x57,0x68,0x2C,0xA8,0xAD,0xE6,0xAF,0x27,0x35,0xEF,0xD6,0x33,0x34,0xA8,0x0F,0x8E,0x2D,0x84,0xA5,0xA9,0xF3,0xC6,0x9A,0xF7,0xC9,0xB6,0x9B,0x12,0x0E,0xF3,0x40,0x6E,0x8E,0x2A,0x40,0x4B,0x6C,0x63,0x6B,0x42,0xEC,0xE6,0xB5,0x2E,0x1D,0x5A,0x95,0xFF,0x8E,0xAF,0xB3,0x24,0x8D,0x88,0x01,0x61,0x42,0x1D,0xA9,0x80,0x93,0xD2,0xE9,0x04,0x30,0x63,0x43,0x16,0xC1,0xD0,0xCC,0xFD,0xD1,0xA0,0xA8,0xC3,0xD0,0x73,0xF6,0x66,0x38,0x95,0x42,0xA1,0x75,0x77,0xD1,0xE2,0xBB,0xB8,0x49,0x7B,0x78,0x6F,0x66,0x44,0x93};
const uint32_t plaintext_golden_ans[] = {0x726C6421,0x2C20576F,0x656C6C6F,0x00000048,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int32_t wsrsa_encrypt(uint8_t* plaintext, uint8_t* publexp, uint8_t*modulus, uint8_t* ciphertext)
{
// Set Base
XWsrsa1024_Base_v plaintext_st;
memcpy(&plaintext_st, plaintext, sizeof(XWsrsa1024_Base_v));
XWsrsa1024_Set_base_V(&xrsamodexp,plaintext_st);
// Set public exponent
XWsrsa1024_Publexp_v publexp_st;
memcpy(&publexp_st, publexp, sizeof(XWsrsa1024_Publexp_v));
XWsrsa1024_Set_publexp_V(&xrsamodexp, publexp_st);
// Set Modulus
XWsrsa1024_Modulus_v modulus_st;
memcpy(&modulus_st, modulus, sizeof(modulus_st));
XWsrsa1024_Set_modulus_V(&xrsamodexp, modulus_st);
// Create empty result struct and initialize it to zero
XWsrsa1024_Result_v ciphertext_st;
memset(ciphertext_st, 0, sizeof(XWsrsa1024_Result_v));
// Print input data for debugging
xil_printf("BASE DATA = \n"); printBaseData(&xrsamodexp,plaintext_st);
xil_printf("EXPO DATA = \n"); printExpData(&xrsamodexp,publexp_st);
xil_printf("MODU DATA = \n"); printModData(&xrsamodexp,modulus_st);
// Set mode to encrypt
XWsrsa1024_Set_mode(&xrsamodexp,ENCRYPT);
// Start hardare block
XWsrsa1024_Start(&xrsamodexp);
// wait for result
while( !XWsrsa1024_IsDone(&xrsamodexp));
// read back data into local buffer
ciphertext_st = XWsrsa1024_Get_result_V(&xrsamodexp);
// copy local struct data into user buffer
memcpy(ciphertext, &ciphertext_st, sizeof(XWsrsa1024_Result_v));
// compare result against golden truth data, and fail if its wrong
if (memcmp(ciphertext, golden_ans, sizeof(XWsrsa1024_Result_v)) )
{
printf("ERROR, CIPHERTEXT IS INCORRECT\n");
return XST_FAILURE;
}
else
return XST_SUCCESS;
}
int32_t rsa_test(void)
{
uint8_t result[RSA_NUM_BYTES];
// initialize RSA block
uint32_t ret = rsa_init();
if (ret != XST_SUCCESS)
xil_printf("RSA init error!\n");
// Test public encyption on plaintext, comparing against known ciphertext
ret = wsrsa_encrypt(plaintext_golden_ans, publexp_arr, modulus_arr, result);
xil_printf("Enc result = "); printHex(result,RSA_NUM_BYTES);
return ret;
}
使用devmem2手动写入输入寄存器:
#!/bin/sh
# Set mode to 0
devmem2 0x43c00010 b 0
# WRITE BASE WORD-BY-WORD
devmem2 0x43C00018 w 0x726C6421
devmem2 0x43C0001C w 0x2C20576F
devmem2 0x43C00020 w 0x656C6C6F
devmem2 0x43C00024 w 0x00000048
devmem2 0x43C00028 w 0x00000000
devmem2 0x43C0002C w 0x00000000
devmem2 0x43C00084 w 0x00000000
# ....
# zero writes through 0x43C00094 ....
# ....
devmem2 0x43C00094 w 0x00000000
# WRITE EXPONENT WORD-BY-WORD
devmem2 0x43C0009C w 0x00010001
devmem2 0x43C000A0 w 0x00000000
devmem2 0x43C000A4 w 0x00000000
# ....
# zero writes through 0x43C00118 ....
# ....
devmem2 0x43C00118 w 0x00000000
# WRITE MODULUS WORD-BY-WORD
devmem2 0x43C00120 w 0x73EBF549
devmem2 0x43C00124 w 0xEB9C825B
devmem2 0x43C00128 w 0x74AFC24B
devmem2 0x43C0012C w 0xA8382964
devmem2 0x43C00130 w 0x77A47EAF
devmem2 0x43C00134 w 0xB6799CBA
devmem2 0x43C00138 w 0xBC655E9B
devmem2 0x43C0013C w 0x3E8474BA
devmem2 0x43C00140 w 0xD45CBF84
devmem2 0x43C00144 w 0xD4ECF4D1
devmem2 0x43C00148 w 0x9BC63D83
devmem2 0x43C0014C w 0x2F5C527B
devmem2 0x43C00150 w 0x216D7925
devmem2 0x43C00154 w 0x7A31B379
devmem2 0x43C00158 w 0xB9B1AD0D
devmem2 0x43C0015C w 0x3DE55FDC
devmem2 0x43C00160 w 0xFBF62113
devmem2 0x43C00164 w 0xB9FB1A97
devmem2 0x43C00168 w 0x0F264D7F
devmem2 0x43C0016C w 0xEAEA3710
devmem2 0x43C00170 w 0x79A497EC
devmem2 0x43C00174 w 0x3362FB37
devmem2 0x43C00178 w 0xC428B39E
devmem2 0x43C0017C w 0x94A68A30
devmem2 0x43C00180 w 0xDF0D9F9A
devmem2 0x43C00184 w 0x1FB4F5E2
devmem2 0x43C00188 w 0x6FE14F25
devmem2 0x43C0018C w 0xBF82BF35
devmem2 0x43C00190 w 0x15A0A2E6
devmem2 0x43C00194 w 0x9769A180
devmem2 0x43C00198 w 0x88853DD8
devmem2 0x43C0019C w 0xD94D889E
# disable autorestart
devmem2 0x43C00000 b 0
# start block
devmem2 0x43C00000 b 1
# read back the results to the console
devmem2 0x43C001A4 w
devmem2 0x43C001A8 w
devmem2 0x43C001AC w
devmem2 0x43C001B0 w
devmem2 0x43C001B4 w
devmem2 0x43C001B8 w
devmem2 0x43C001BC w
devmem2 0x43C001C0 w
devmem2 0x43C001C4 w
devmem2 0x43C001C8 w
devmem2 0x43C001CC w
devmem2 0x43C001D0 w
devmem2 0x43C001D4 w
devmem2 0x43C001D8 w
devmem2 0x43C001DC w
devmem2 0x43C001E0 w
devmem2 0x43C001E4 w
devmem2 0x43C001E8 w
devmem2 0x43C001EC w
devmem2 0x43C001F0 w
devmem2 0x43C001F4 w
devmem2 0x43C001F8 w
devmem2 0x43C001FC w
devmem2 0x43C00200 w
devmem2 0x43C00204 w
devmem2 0x43C00208 w
devmem2 0x43C0020C w
devmem2 0x43C00210 w
devmem2 0x43C00214 w
devmem2 0x43C00218 w
devmem2 0x43C0021C w
devmem2 0x43C00220 w
每次调用devmem2脚本时,结果都不同。但我可以循环我的裸机测试程序,不断设置ap_start,结果永远不会改变(因为它不应该)。
我完全不知道如何进一步调试,所以任何和所有的帮助,
布雷特