简体   繁体   English

如何使用 cpuid.h 将 ac 程序交叉编译为 aarch64?

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

I'm trying to cross-compile a simple C program to aarch64 (arm64) from a 64bit Ubuntu Linux.我正在尝试将一个简单的 C 程序从 64 位 Ubuntu Linux 交叉编译为 aarch64(arm64)。 Can someone please help me why i'm getting this error.有人可以帮助我为什么会收到此错误。

It says 'cpuid.h' is not found.它说找不到'cpuid.h'。 I've tried compiling it on the 64bit linux, it works fine.我已经尝试在 64 位 linux 上编译它,它工作正常。 But when using aarch64-linux-gnu-gcc it is giving errors.但是在使用aarch64-linux-gnu-gcc时会出错。

I'm getting the following error.我收到以下错误。

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.

The contents of test.c : 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] = '\0';
    
    int correct = (strcmp(buff, argv[1]) == 0);
    free(buff);

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

As explained in the comments, you need to port this program to the Aarch64 architecture, you cannot just compile the code as is.正如评论中所解释的,您需要将此程序移植到 Aarch64 架构,您不能只按原样编译代码。 The features implemented in your SoC are exposed through the various AArch64 feature system registers or instruction set attribute registers , for example ID_AA64PFR1_EL1 . SoC 中实现的功能通过各种AArch64 功能系统寄存器或指令集属性寄存器公开,例如ID_AA64PFR1_EL1

By convention, registers with names terminating with _EL1 cannot be accessed from a user-mode program running at EL0.按照惯例,名称以 _EL1 结尾的寄存器不能从运行在 EL0 的用户模式程序访问。 Some support in the Operating System (running at EL1) is therefore required for reading those registers from a user-mode program - I used a Linux 5.15.0 kernel for the purpose of this answer.因此,从用户模式程序中读取这些寄存器需要操作系统(在 EL1 上运行)的一些支持——我使用 Linux 5.15.0 内核来回答这个问题。

On a recent Linux kernel, this can be achieved by using the HWCAP_CPUID API available in hwcaps - more details in this article , ARM64 CPU Feature Registers .在最近的 Linux 内核上,这可以通过使用 hwcaps 中提供的HWCAP_CPUID API 来实现 - 更多详细信息请参见本文ARM64 CPU 功能寄存器

We can compile/execute the example code provided in Appendix I:我们可以编译/执行附录 I 中提供的示例代码:

/*
 * 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;
}
 

Execution:执行:

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

You now just need to identify the feature/instructions set register(s) that will provide you with the same kind of information provided by your x86_64 code.您现在只需要识别将为您提供 x86_64 代码提供的相同类型信息的功能/指令集寄存器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM