如何使用 cpuid.h 交叉编译一个 c 程序到 aarch64?

How to cross compile a c program to aarch64 with cpuid.h?

我正在尝试将一个简单的 C 程序从 64 位 Ubuntu Linux 交叉编译为 aarch64 (arm64)。有人可以帮助我为什么会收到此错误。

它说 'cpuid.h' 没有找到。我试过在 64 位 linux 上编译它,它工作正常。但是当使用 aarch64-linux-gnu-gcc 时会出错。

我收到以下错误。

aarch64-linux-gnu-gcc -O1 -fno-stack-protector  -march=armv8-a  test.c -o test
test.c:4:10: fatal error: cpuid.h: No such file or directory
    4 | #include <cpuid.h>
      |          ^~~~~~~~~
compilation terminated.

test.c的内容:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <cpuid.h>

// Requires that the user input the CPUID,
// plus the bytes "3" and "Q";

void succeed(char* string) {
    printf("Yes, %s is correct!\n", string);
    exit(0);
}

void fail(char* string) {
    printf("No, %s is not correct.\n", string);
    exit(1);
}

void shift_int_to_char(int i, char* buff) {
    buff[0] = (i) & 0xFF;
    buff[1] = (i >> 8) & 0xFF;
    buff[2] = (i >> 16) & 0xFF;
    buff[3] = (i >> 24) & 0xFF;
}

int main(int argc, char** argv) {

    if (argc != 2) {
        printf("Need exactly one argument.\n");
        return -1;
    }

    unsigned int eax, ebx, ecx, edx;
    char* buff = malloc(sizeof(char) * 15);
    __get_cpuid(0, &eax, &ebx, &ecx, &edx);
    shift_int_to_char(ebx, buff);
    shift_int_to_char(edx, buff + 4);
    shift_int_to_char(ecx, buff + 8);
    buff[12] = '3';
    buff[13] = 'Q';
    buff[14] = '[=12=]';
    
    int correct = (strcmp(buff, argv[1]) == 0);
    free(buff);

    if (correct) {
        succeed(argv[1]);
    } else {
        fail(argv[1]);
    }
}

如评论中所述,您需要将此程序移植到Aarch64架构,不能直接编译代码。您的 SoC 中实现的功能通过各种 AArch64 feature system registers or instruction set attribute registers, for example ID_AA64PFR1_EL1.

公开。

按照惯例,名称以 _EL1 结尾的寄存器不能从 EL0 的 user-mode 程序 运行 访问。因此,从 user-mode 程序读取这些寄存器需要操作系统(运行 在 EL1)中的一些支持——为了这个答案,我使用了 Linux 5.15.0 内核。

在最近的 Linux 内核上,这可以通过使用 hwcaps - more details in this article , ARM64 CPU Feature Registers.

中可用的 HWCAP_CPUID API 来实现

我们可以compile/execute附录一中提供的示例代码:

/*
 * Sample program to demonstrate the MRS emulation ABI.
 *
 * Copyright (C) 2015-2016, ARM Ltd
 *
 * Author: Suzuki K Poulose <suzuki.poulose@arm.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <asm/hwcap.h>
#include <stdio.h>
#include <sys/auxv.h>

#define get_cpu_ftr(id) ({                                    \
              unsigned long __val;                            \
              asm("mrs %0, "#id : "=r" (__val));              \
              printf("%-20s: 0x%016lx\n", #id, __val);        \
      })

int main(void)
{

      if (!(getauxval(AT_HWCAP) & HWCAP_CPUID)) {
              fputs("CPUID registers unavailable\n", stderr);
              return 1;
      }

      get_cpu_ftr(ID_AA64ISAR0_EL1);
      get_cpu_ftr(ID_AA64ISAR1_EL1);
      get_cpu_ftr(ID_AA64MMFR0_EL1);
      get_cpu_ftr(ID_AA64MMFR1_EL1);
      get_cpu_ftr(ID_AA64PFR0_EL1);
      get_cpu_ftr(ID_AA64PFR1_EL1);
      get_cpu_ftr(ID_AA64DFR0_EL1);
      get_cpu_ftr(ID_AA64DFR1_EL1);

      get_cpu_ftr(MIDR_EL1);
      get_cpu_ftr(MPIDR_EL1);
      get_cpu_ftr(REVIDR_EL1);

#if 0
      /* Unexposed register access causes SIGILL */
      get_cpu_ftr(ID_MMFR0_EL1);
#endif

      return 0;
}
 

执行:

gcc -o cpu-feature-registers  cpu-feature-registers.c
./cpu-feature-registers
ID_AA64ISAR0_EL1    : 0x0000000000010000
ID_AA64ISAR1_EL1    : 0x0000000000000000
ID_AA64MMFR0_EL1    : 0x00000111ff000000
ID_AA64MMFR1_EL1    : 0x0000000000000000
ID_AA64PFR0_EL1     : 0x0000000000000011
ID_AA64PFR1_EL1     : 0x0000000000000000
ID_AA64DFR0_EL1     : 0x0000000000000006
ID_AA64DFR1_EL1     : 0x0000000000000000
MIDR_EL1            : 0x00000000410fd034
MPIDR_EL1           : 0x0000000080000000
REVIDR_EL1          : 0x0000000000000000

您现在只需要确定 feature/instructions 设置寄存器,它将为您提供与您的 x86_64 代码提供的相同类型的信息。