在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            ARM Linux 大小核切換

            作者: 時間:2016-11-09 來源:網(wǎng)絡(luò) 收藏
            8核CPU或者是更多核的處理器,這些CPU有可能不完全對稱。有的是4個A15和4個A7,或者是4個A57和4個A53,甚至像海思麒麟935處理器(4核A53 2.2 GHz + 4核A53 1.5 GHz),這8個核的頻率可能不一樣,則使用過程中需要大小核切換(頻率高的是大核,頻率低的是小核)。本文以ARM cortex-A7為例,分析大小核切換的代碼,著重于分析實現(xiàn)切換的代碼,對于為什么要這樣切換、以及什么時候切換,不做過多探討。

            本文引用地址:http://www.biyoush.com/article/201611/317988.htm

            主要代碼分布:

            arch/arm/common/bL_switcher.c

            arch/arm/include/asm/bL_switcher.h

            drivers/cpufreq/Arm_big_little.c

            編譯后形成的兩個驅(qū)動模塊:

            __initcall_bL_switcher_init6

            __initcall_bL_cpufreq_register7

            執(zhí)行流程圖如下所示。

            上圖的左邊是bL_switcher_init執(zhí)行流程。

            右邊是切換線程bL_switcher_thread執(zhí)行流程,這個線程是核心代碼。代碼的上半部分是一個CPU在運行,然后這個CPU完成下電后。下半部分藍(lán)色所示,是起來的那個CPU在運行,這樣就完成了大小核的切換操作。

            1 bL_switcher_init

            bL_switcher_init執(zhí)行流程如下:

            如果最大CPU組數(shù)(簇)不為2,則報錯,然后返回

            bL_running_cluster賦值1,默認(rèn)設(shè)為是第一簇在運行

            no_bL_switcher初值為FALSE

            bL_switcher_enable

            bL_switcher_halve_cpus 關(guān)閉不必要的CPU

            為每個online的CPU創(chuàng)建切換線程bL_switcher_thread

            bL_switcher_active賦值1

            bL_switcher_sysfs_init 創(chuàng)建sys/kernel/bL_switcher

            bL_switcher_restore_unpaired_cpus 恢復(fù)不成對的CPU,給它們上電

            創(chuàng)建完sys/kernel/bL_switcher,則可以通過下面的命令,手動查看/設(shè)置能否切換、查看/設(shè)置切換那個簇的CPU。

            cat /sys/kernel/bL_switcher/active

            echo 0/1 > /sys/kernel/ bL_switcher/active

            cat /sys/kernel/bL_switcher/do_switch

            echo0/1> /sys/kernel/ bL_switcher/ do_switch

            2 切換請求bL_switch_request

            這是個內(nèi)聯(lián)函數(shù),需要兩個參數(shù),第一個是CPU的ID,第二個是簇號,內(nèi)核調(diào)到的有三處。

            一是在Arm_big_little.c:bL_cpufreq_set_rate:需要不同的簇切換時;

            二、三是在執(zhí)行echo 0/1 > /sys/kernel/ bL_switcher/ do_switch ,調(diào)用到bL_do_switch_store函數(shù),這里面判斷是否需要切換

            這個內(nèi)聯(lián)函數(shù),直接執(zhí)行bL_switch_request_cb,參數(shù)是前面的2個,再加上兩個NULL。

            bL_switch_request_cb:

            判斷第一個參數(shù)CPU的ID是否超出范圍;

            獲取當(dāng)前CPU的線程函數(shù)指針

            賦值wanted_cluster

            喚醒當(dāng)前線程函數(shù)的工作隊列

            3 切換線程bL_switcher_thread

            bL_switcher_thread執(zhí)行流程:

            等待事件。滿足事件的兩個可能條件:

            一是上面的bL_switch_request_cb函數(shù),喚醒線程,且切換到的CPU簇數(shù)不為-1;

            二是bL_switcher_disable函數(shù)調(diào)用kthread_stop,喚醒線程

            bL_switch_to

            找到成對的CPU ID ,簇號

            mcpm_cpu_power_up 給CPU上電,跳轉(zhuǎn)到 mcpm_entry_point

            gic_send_sgi 給其發(fā)送0號軟中斷

            wait_for_completion_timeout(&inbound_alive 等待它給我發(fā)送軟中斷 IPI_COMPLETION

            關(guān)閉IRQ、FIQ

            遷移中斷到對應(yīng)的CPU上

            關(guān)閉時鐘Tick

            cpu_pm_enter gic_cpu_save 保存中斷設(shè)置

            cpu_suspend這個跟睡眠的流程很相似

            bL_switchpoint

            call_with_stack arch/arm/lib/call_with_stack.S 若失敗了,是可以返回的

            bL_do_switch

            讓剛起來的CPU跳轉(zhuǎn)到cpu_resume,給其發(fā)送sev

            若handshake變量為0,則進(jìn)入wfe

            等待不為0后,mcpm_cpu_power_down對自身斷電

            call_with_stack:攜帶的三個參數(shù),第一個是函數(shù),第二個是函數(shù)調(diào)用時用到的參數(shù),第三個是棧地址

            將SP、LR依次放入棧的頂部

            SP賦值讓開兩個寄存器后的地址

            R0賦給R2

            R1賦給R0

            LR賦值下面的標(biāo)號1處

            R2賦給PC,即跳轉(zhuǎn)到R2

            若失敗了,則跳轉(zhuǎn)到LR處,就是標(biāo)號1處

            彈出LR

            彈出SP

            LR賦給PC,跳轉(zhuǎn)到了bL_switchpoint,調(diào)用call_with_stack函數(shù)的地方。

            此處設(shè)置真是巧妙,不同簇對應(yīng)的CPU ID都是0,則剛起來的CPU正好能通過下面的步驟

            mcpm_entry_point-> cpu_resume-> cpu_do_resume=cpu_v7_do_resume -> cpu_resume_mmu -> 再次跳轉(zhuǎn)到上面調(diào)用__cpu_suspend處繼續(xù)運行了。

            即要下電的CPU剛保存后堆棧,又被剛上電的CPU恢復(fù)了。

            接下來就是上電的CPU再運行了。

            cpu_pm_exit gic_cpu_restore 恢復(fù)中斷設(shè)置

            時鐘接著運行 Tick,兩個CPU用到的節(jié)拍Timer是同一個。

            開啟IRQ、FIQ

            *handshake_ptr = 1;

            dsb_sev 給那個CPU發(fā)送事件

            這樣就完成了CPU的切換,這個函數(shù)的前一半是一個CPU在執(zhí)行,后一半變成了另一個CPU在執(zhí)行。

            4 bL_cpufreq_register

            獲取bL_switcher_active的值,將這個值(真或者假)設(shè)置給bL_switching_enabled變量;

            初始化互斥鎖cluster_lock;

            注冊cpufreq_driver驅(qū)動bL_cpufreq_driver。

            如果上面的驅(qū)動注冊成功,則將bL_switcher_notifier 掛在bL_activation_notifier鏈表上;

            若掛載失敗,則卸載驅(qū)動bL_cpufreq_driver

            bL_cpufreq_driver定義如下:

            static struct cpufreq_driver bL_cpufreq_driver = {

            .name = "arm-big-little",

            .flags = CPUFREQ_STICKY,

            .verify = bL_cpufreq_verify_policy,

            .target = bL_cpufreq_set_target,

            .get = bL_cpufreq_get_rate,

            .init = bL_cpufreq_init,

            .have_governor_per_policy = true,

            .attr = bL_cpufreq_attr,

            };

            若bL_cpufreq_driver注冊成功,執(zhí)行下面的命令,就可以看到有個驅(qū)動是arm-big-little。

            cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors

            conservative ondemand userspace powersaveinteractiveperformance

            cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governors

            interactive

            cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver

            arm-big-little

            用bL_cpufreq_driver這種調(diào)頻策略時,就會執(zhí)行到bL_cpufreq_set_target,然后執(zhí)行bL_cpufreq_set_rate,則有可能調(diào)用到bL_switch_request。



            關(guān)鍵詞: ARMLinux大小核切

            評論


            技術(shù)專區(qū)

            關(guān)閉