国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【ARM v8】如何在ARM上實(shí)現(xiàn)x86的rdtsc()函數(shù)

這篇具有很好參考價(jià)值的文章主要介紹了【ARM v8】如何在ARM上實(shí)現(xiàn)x86的rdtsc()函數(shù)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

博主未授權(quán)任何人或組織機(jī)構(gòu)轉(zhuǎn)載博主任何原創(chuàng)文章,感謝各位對(duì)原創(chuàng)的支持!
博主鏈接

本人就職于國(guó)際知名終端廠商,負(fù)責(zé)modem芯片研發(fā)。
在5G早期負(fù)責(zé)終端數(shù)據(jù)業(yè)務(wù)層、核心網(wǎng)相關(guān)的開(kāi)發(fā)工作,目前牽頭6G算力網(wǎng)絡(luò)技術(shù)標(biāo)準(zhǔn)研究。


博客內(nèi)容主要圍繞:
???????5G/6G協(xié)議講解
???????算力網(wǎng)絡(luò)講解(云計(jì)算,邊緣計(jì)算,端計(jì)算)
???????高級(jí)C語(yǔ)言講解
???????Rust語(yǔ)言講解



如何在ARM上實(shí)現(xiàn)x86的rdtsc()函數(shù)


【ARM v8】如何在ARM上實(shí)現(xiàn)x86的rdtsc()函數(shù),ARMv8,arm開(kāi)發(fā)

一、使用ARMv8提供的獨(dú)立定時(shí)器CNTVCT_EL0

???????System counter是Arm64下獨(dú)立于CPU core的計(jì)數(shù)器,在系統(tǒng)上電時(shí),會(huì)給此計(jì)數(shù)器設(shè)置固定的頻率。一個(gè)映射System counter計(jì)數(shù)器內(nèi)容的寄存器為CNTVCT_EL0,可在用戶(hù)態(tài)下讀取此寄存器獲取counter值。而CNTFRQ_EL0保存的是counter的頻率值(詳細(xì)內(nèi)容參考《【ARMv8】通用定時(shí)器總結(jié)》)。通過(guò)下面的函數(shù)實(shí)現(xiàn)獲取counter值及頻率值:

static inline uint64_t 
arm64_cntvct(void) 
{   
	uint64_t tsc;   
    asm volatile("mrs %0, cntvct_el0" : "=r" (tsc));   
    return tsc; 
} 

static inline uint64_t 
arm64_cntfrq(void)
{   
	uint64_t freq;   
	asm volatile("mrs %0, cntfrq_el0" : "=r" (freq));   
    return freq; 
} 

static inline uint64_t 
rdtsc(void) 
{
	return arm64_cntvct();
}

但是System counter的精度從Armv8.0到Armv8.5,范圍通常在1-50MHz;從Armv8.6開(kāi)始,以1GHz的固定頻率遞增。雖然1GHz的頻率已經(jīng)足夠高了,但是還是達(dá)不到CPU cycle級(jí)別的精度。


二、使用ARMv8的PMU計(jì)數(shù)器PMCCNTR_EL0

???????在ARMv8中,有Performance Monitors Control Register系列寄存器,其中PMCCNTR_EL0就類(lèi)似于x86的TSC寄存器。但是如果想在用戶(hù)態(tài)訪問(wèn)這些寄存器,需要在內(nèi)核代碼中開(kāi)啟PMU用戶(hù)態(tài)訪問(wèn)開(kāi)關(guān)。

2.1 關(guān)鍵寄存器介紹

PMCCNTR_EL0(Performance Monitors Cycle Count Register)

保存了處理器周期計(jì)數(shù)器的值,其結(jié)構(gòu)如下:
【ARM v8】如何在ARM上實(shí)現(xiàn)x86的rdtsc()函數(shù),ARMv8,arm開(kāi)發(fā)

PMCR_EL0(Performance Monitors Control Register)

PMU配置寄存器,其結(jié)果如下:

【ARM v8】如何在ARM上實(shí)現(xiàn)x86的rdtsc()函數(shù),ARMv8,arm開(kāi)發(fā)
其中和我們關(guān)系密切的幾個(gè)參數(shù)含義:

  • LC:設(shè)置為1,表示開(kāi)啟64bit的周期計(jì)數(shù)器;否則,使用32bit的計(jì)數(shù)器(32bit的已經(jīng)摒棄);
  • D:設(shè)置為1,表示每64個(gè)時(shí)鐘周期,計(jì)時(shí)器累加一次(已經(jīng)摒棄);否則,每個(gè)時(shí)鐘周期計(jì)數(shù)器累加一次;
  • C:設(shè)置為1,表示重置計(jì)數(shù)器;
  • E:設(shè)置為1,表示開(kāi)啟計(jì)數(shù)器PMCCNTR_EL0;

PMUSERENR_EL0(Performance Monitors User Enable Register)

用于開(kāi)啟或關(guān)閉用戶(hù)態(tài)下是否可以訪問(wèn)PMU寄存器,相關(guān)結(jié)構(gòu)如下:

【ARM v8】如何在ARM上實(shí)現(xiàn)x86的rdtsc()函數(shù),ARMv8,arm開(kāi)發(fā)
其中和我們關(guān)系密切的幾個(gè)參數(shù)含義:

  • ER:設(shè)置為1,表示用戶(hù)態(tài)下可以讀寫(xiě)PMU寄存器;否則不可以讀寫(xiě);
  • EN:設(shè)置為1,表示用戶(hù)態(tài)軟件可以訪問(wèn)所有PMU特定的寄存器;

PMCNTENCLR_EL0(Performance Monitors Count Enable Clear register)

設(shè)置啟用的計(jì)數(shù)器和事件計(jì)數(shù)器,相關(guān)結(jié)構(gòu)如下:

【ARM v8】如何在ARM上實(shí)現(xiàn)x86的rdtsc()函數(shù),ARMv8,arm開(kāi)發(fā)
其中和我們關(guān)系密切的幾個(gè)參數(shù)含義:

  • C:設(shè)置為1,表示啟用PMCCNTR_EL0計(jì)數(shù)器;

2.2 內(nèi)核使能代碼

/*                                                                             
 * Enable user-mode ARM performance counter access.                            
 */                                                                           
#include <linux/kernel.h>                                                      
#include <linux/module.h>                                                      
#include <linux/smp.h>                                                         
                                                                                                                                                       
#define ARMV8_PMCR_MASK         0x3f                                                                    
#define ARMV8_PMCR_E            (1 << 0) /* Enable all counters */                                      
#define ARMV8_PMCR_P            (1 << 1) /* Reset all counters */                                       
#define ARMV8_PMCR_C            (1 << 2) /* Cycle counter reset */                                      
#define ARMV8_PMCR_D            (1 << 3) /* CCNT counts every 64th cpu cycle */                         
#define ARMV8_PMCR_X            (1 << 4) /* Export to ETM */                                            
#define ARMV8_PMCR_DP           (1 << 5) /* Disable CCNT if non-invasive debug*/                        
#define ARMV8_PMCR_LC           (1 << 6) /* Cycle Counter 64bit overflow*/
#define ARMV8_PMCR_N_SHIFT      11       /* Number of counters supported */                             
#define ARMV8_PMCR_N_MASK       0x1f                                                                    
                                                                                                         
#define ARMV8_PMUSERENR_EN_EL0  (1 << 0) /* EL0 access enable */                                        
#define ARMV8_PMUSERENR_CR      (1 << 2) /* Cycle counter read enable */                                
#define ARMV8_PMUSERENR_ER      (1 << 3) /* Event counter read enable */                                
                                                                                                         
static inline u32 armv8pmu_pmcr_read(void)                                                              
{                                                                                                       
        u64 val=0;                                                                                      
        asm volatile("mrs %0, pmcr_el0" : "=r" (val));                                                  
        return (u32)val;                                                                                
}                                                                                                       
static inline void armv8pmu_pmcr_write(u32 val)                                                         
{                                                                                                       
        val &= ARMV8_PMCR_MASK;                                                                         
        isb();                                                                                          
        asm volatile("msr pmcr_el0, %0" : : "r" ((u64)val));                                            
}       
                                                                                                         
static void                                                                                            
enable_cpu_counters(void* data)                                                                         
{                                                                                                       
    u32 val=0;                                                         
    asm volatile("msr pmuserenr_el0, %0" : : "r"(0xf));                                                   
    asm volatile("msr PMCNTENSET_EL0, %0" :: "r" ((u32)(1<<31)));
    armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ARMV8_PMCR_E|ARMV8_PMCR_LC);   
    printk("\nCPU:%d ", smp_processor_id());
}                                                                                                       
                                                                                                         
static void                                                                                            
disable_cpu_counters(void* data)                                                                        
{                                                                                                                                                                                                   
    printk(KERN_INFO "\ndisabling user-mode PMU access on CPU #%d",                       
    smp_processor_id());                                                                                   
                                                                                                         
    /* Program PMU and disable all counters */                                                            
    armv8pmu_pmcr_write(armv8pmu_pmcr_read() |~ARMV8_PMCR_E);                                              
    asm volatile("msr pmuserenr_el0, %0" : : "r"((u64)0));                                                                                                                                                
}                                                                                                       
                                                                                                         
static int __init                                                                                       
init(void)                                                                                              
{                                                                       
	isb();
	on_each_cpu(enable_cpu_counters, NULL, 1);                                                             
    printk(KERN_INFO "Enable Access PMU Initialized");                                                       
    return 0;                                                                                              
}                                                                                                       
                                                                                                         
static void __exit                                                                                      
fini(void)                                                                                              
{                                                                                                       
    on_each_cpu(disable_cpu_counters, NULL, 1);                                                            
    printk(KERN_INFO "Access PMU Disabled");                                                          
}                                                                                                       
                                                                                                         
module_init(init);                                                                                      
module_exit(fini);
module_license("GPL");

2.3 用戶(hù)態(tài)代碼

#include <stdio.h>

#define u64 unsigned long long
#define isb()       asm volatile("isb" : : : "memory")
 
static inline u64 arch_counter_get_cntpct(void)
{
    u64 cval;
    isb();
    asm volatile("mrs %0, PMCCNTR_EL0" : "+r"(cval));
    return cval;
}

2.4 測(cè)試時(shí)遇到的問(wèn)題

可能有同學(xué)會(huì)用下面的代碼測(cè)試定時(shí)精度,

int main()
{
	u64 begin,end;
	
	begin = arch_counter_get_cntpct();
	sleep(1);
	end= arch_counter_get_cntpct();
	
	printf("The count is %llu.\n",end-begin);

	return 0;
}

但是會(huì)發(fā)現(xiàn)使用統(tǒng)計(jì)的計(jì)數(shù)值與CPU當(dāng)前的始終頻率計(jì)算后,時(shí)間不是1s。這是因?yàn)長(zhǎng)inux的省電功能導(dǎo)致的,sleep會(huì)使當(dāng)前進(jìn)程讓出CPU,如果此時(shí)CPU任務(wù)隊(duì)列中沒(méi)有任務(wù),就會(huì)進(jìn)入低功耗(例如,WFI)甚至offline,如果進(jìn)入上述狀態(tài)PMU計(jì)數(shù)器就會(huì)停止計(jì)數(shù),導(dǎo)致計(jì)數(shù)值不準(zhǔn)確。

畢竟PMU是為調(diào)式使用的,如果此時(shí)CPU沒(méi)有任務(wù),也確實(shí)沒(méi)有必要繼續(xù)統(tǒng)計(jì)了。所以使用PMU寄存器計(jì)數(shù)是,不應(yīng)該有主動(dòng)讓出CPU的行為,可能會(huì)導(dǎo)致計(jì)數(shù)不準(zhǔn)確。

可以嘗試關(guān)閉省電模式:

echo 1 > /sys/devices/system/cpu/cpu<X>/cpuidle/state<Y>/disable


【ARM v8】如何在ARM上實(shí)現(xiàn)x86的rdtsc()函數(shù),ARMv8,arm開(kāi)發(fā)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-744228.html

到了這里,關(guān)于【ARM v8】如何在ARM上實(shí)現(xiàn)x86的rdtsc()函數(shù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • RISC-V是如何與X86、ARM三分天下

    RISC-V是如何與X86、ARM三分天下

    目錄 1.行業(yè)CPU指令集格局 2.汽車(chē)中的RISC-V進(jìn)展 2.1 國(guó)際進(jìn)展 2.2 國(guó)內(nèi)進(jìn)展 3.小結(jié) 2023年3月2日,在平頭哥牽頭舉辦的玄鐵RISC-V生態(tài)大會(huì)上,工程院院士倪光南表示,基于RISC-V模塊化、可擴(kuò)展、容易定制、不受壟斷制約等優(yōu)勢(shì),成為了中國(guó)CPU領(lǐng)域最受歡迎的架構(gòu)。 那么RISC-V到底是

    2024年01月15日
    瀏覽(31)
  • 帶wiringPi庫(kù)的交叉編譯 ---宿主機(jī)x86Ubuntu,目標(biāo)機(jī)ARMv8 aarch64(香橙派)

    帶wiringPi庫(kù)的交叉編譯 ---宿主機(jī)x86Ubuntu,目標(biāo)機(jī)ARMv8 aarch64(香橙派)

    帶wiringPi庫(kù)的交叉編譯如何進(jìn)行 先交叉編譯wiringPi庫(kù),編譯出的庫(kù)適合香橙派,這時(shí)候交叉編譯可執(zhí)行程序的平臺(tái)和鏈接庫(kù)的格式也是正確的 ,然后通過(guò)-I和-L來(lái)指定鏈接的wiringPi庫(kù)的頭文件和庫(kù)的位置,但是現(xiàn)在還沒(méi)有學(xué)習(xí)過(guò),后面學(xué)了補(bǔ)上 此時(shí)如果把wiringPi庫(kù)拿到Ubuntu上進(jìn)

    2024年02月15日
    瀏覽(23)
  • X86和arm的區(qū)別

    硬件上的區(qū)別 x86 系統(tǒng)中的硬件組件(如聲卡、顯卡、內(nèi)存、存儲(chǔ)器和 CPU)都是相互獨(dú)立的。大多數(shù)組件都有單獨(dú)的芯片,稱(chēng)為控制器。我們可以對(duì)這些組件進(jìn)行更改或擴(kuò)展,而不會(huì)影響連接性或整個(gè)硬件平臺(tái)。 ARM 處理器沒(méi)有單獨(dú)的 CPU。相反,處理單元與其他硬件控制器位

    2024年02月03日
    瀏覽(19)
  • 【ARM架構(gòu)】ARMv8-A 系統(tǒng)中的安全架構(gòu)概述

    【ARM架構(gòu)】ARMv8-A 系統(tǒng)中的安全架構(gòu)概述

    一個(gè)安全或可信的操作系統(tǒng)保護(hù)著系統(tǒng)中敏感的信息,例如,可以保護(hù)用戶(hù)存儲(chǔ)的密碼,信用卡等認(rèn)證信息免受攻擊。 安全由以下原則定義: 保密性:保護(hù)設(shè)備上的敏感信息,防止未經(jīng)授權(quán)的訪問(wèn)。有以下幾種方法可以做到,比如密碼和加密密鑰。 完整性:使用公鑰來(lái)保護(hù)

    2024年02月21日
    瀏覽(21)
  • X86、X64和ARM

    X86架構(gòu)和X64架構(gòu)(也稱(chēng)為x86-64、AMD64或Intel 64)都是計(jì)算機(jī)處理器架構(gòu)的名稱(chēng),它們都屬于x86家族的一部分。 這些架構(gòu)主要用于描述計(jì)算機(jī)中處理器的指令集和尋址能力。 ? X86指的是支持32位的指令集架構(gòu)處理器, 最初由英特爾在1978年發(fā)布的 intel 8086,這個(gè)系統(tǒng)主要為X86結(jié)尾

    2024年02月15日
    瀏覽(42)
  • x86 平臺(tái)運(yùn)行 arm 的方法

    參考: https://github.com/multiarch/qemu-user-static 核心是使用 binfmt_misc 設(shè)定運(yùn)行 arm 的默認(rèn)程序?yàn)?qemu-aarch64-static 1.先下載 arm64 即 aarch64 的運(yùn)行文件 2.設(shè)置默認(rèn)打開(kāi)方式, 即設(shè)置 binfmt_misc 以支持 arm64 程序的運(yùn)行 # --reset 會(huì)刪除同名條目后重新設(shè)置 3.測(cè)試 4.不用映射qemu-*-static也可以使用

    2024年02月12日
    瀏覽(24)
  • x86 和 x64 arm的區(qū)別

    x86和x64是基于英特爾x86架構(gòu)的復(fù)雜指令集架構(gòu)(ISA),而ARM是一種精簡(jiǎn)指令集架構(gòu)。 假設(shè)我們現(xiàn)在要開(kāi)發(fā)一個(gè)cpu,就好比說(shuō)我們?nèi)バ藿ㄒ粭潣牵_(kāi)發(fā)商會(huì)先將圖紙?jiān)O(shè)計(jì)好。設(shè)計(jì)好之后由施工單位按照設(shè)計(jì)圖去建造。在建造的這個(gè)過(guò)程中,施工方是要按照國(guó)家一定的規(guī)范來(lái)設(shè)計(jì)

    2024年01月19日
    瀏覽(28)
  • CPU 架構(gòu):ARM 和 x86 架構(gòu)區(qū)別

    計(jì)算機(jī)有兩種主要的 CPU 架構(gòu)可供選擇。Windows PC 通常建立在 Intel 和 AMD 使用的 x86 平臺(tái)上,而 Apple 的計(jì)算機(jī)則使用該公司自己的基于 ARM 架構(gòu)的?M1 和 M2 處理器。 這些方法之間存在差異,并且對(duì)性能的意義具有重大影響。 x86 和 ARM 處理器平臺(tái)做相同的事情,但它們以完全不

    2024年04月27日
    瀏覽(23)
  • 『ARM』和『x86』處理器架構(gòu)解析指南

    『ARM』和『x86』處理器架構(gòu)解析指南

    如果問(wèn)大家是否知道 CPU,我相信不會(huì)得到否定的答案,但是如果繼續(xù)問(wèn)大家是否了解 ARM 和 X86 架構(gòu) ,他們的區(qū)別又是什么,相信 可能部分人就會(huì)啞口無(wú)言 了 目前隨著深度學(xué)習(xí)、高性能計(jì)算、NLP、AIGC、GLM、AGI 的技術(shù)迭代,助力大模型快速發(fā)展,對(duì)于 多元算力結(jié)合(CPU+GP

    2024年02月08日
    瀏覽(123)
  • ARM和X86架構(gòu)對(duì)比分析-2023-4-27

    架構(gòu) 項(xiàng)目 ARM X86 性能 CPU:幾百兆,最近才出現(xiàn)1G左右。制程使用不到65nm制程的工藝。 CPU: 1G以上;雙核、四核。常用45nm(甚至更高級(jí))制程工藝生產(chǎn)。 擴(kuò)展能力 ARM結(jié)構(gòu)的電腦是通過(guò)專(zhuān)用的數(shù)據(jù)接口使CPU與數(shù)據(jù)存儲(chǔ)設(shè)備進(jìn)行連接,所以ARM的存儲(chǔ)、內(nèi)存等性能擴(kuò)展難以進(jìn)行

    2024年02月01日
    瀏覽(54)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包