您的位置 首页 知识

ARM Linux 巨细核切换

8核CPU或者是更多核的处理器,这些CPU有可能不完全对称。有的是4个A15和4个A7,或者是4个A57和4个A53,甚至像海思麒麟935处理器(4核A532…

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为例,剖析巨细核切换的代码,着重于剖析完结切换的代码,关于为什么要这样切换、以及什么时候切换,不做过多讨论。

首要代码散布:

arch/arm/common/bL_switcher.c

arch/arm/include/asm/bL_switcher.h

drivers/cpufreq/Arm_big_little.c

编译后构成的两个驱动模块:

__initcall_bL_switcher_init6

__initcall_bL_cpufreq_register7

履行流程图如下所示。

上图的左面是bL_switcher_init履行流程。

右边是切换线程bL_switcher_thread履行流程,这个线程是中心代码。代码的上半部分是一个CPU在运转,然后这个CPU完结下电后。下半部分蓝色所示,是起来的那个CPU在运转,这样就完结了巨细核的切换操作。

1 bL_switcher_init

bL_switcher_init履行流程如下:

假如最大CPU组数(簇)不为2,则报错,然后回来

bL_running_cluster赋值1,默许设为是榜首簇在运转

no_bL_switcher初值为FALSE

bL_switcher_enable

bL_switcher_halve_cpus 封闭不必要的CPU

为每个online的CPU创立切换线程bL_switcher_thread

bL_switcher_active赋值1

bL_switcher_sysfs_init 创立sys/kernel/bL_switcher

bL_switcher_restore_unpaired_cpus 康复不成对的CPU,给它们上电

创立完sys/kernel/bL_switcher,则能够经过下面的指令,手动检查/设置能否切换、检查/设置切换那个簇的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

这是个内联函数,需求两个参数,榜首个是CPU的ID,第二个是簇号,内核调到的有三处。

一是在Arm_big_little.c:bL_cpufreq_set_rate:需求不同的簇切换时;

二、三是在履行echo 0/1 > /sys/kernel/ bL_switcher/ do_switch ,调用到bL_do_switch_store函数,这里边判别是否需求切换

这个内联函数,直接履行bL_switch_request_cb,参数是前面的2个,再加上两个NULL。

bL_switch_request_cb:

判别榜首个参数CPU的ID是否超出范围;

获取当时CPU的线程函数指针

赋值wanted_cluster

唤醒当时线程函数的作业行列

3 切换线程bL_switcher_thread

bL_switcher_thread履行流程:

等候事情。满意事情的两个或许条件:

一是上面的bL_switch_request_cb函数,唤醒线程,且切换到的CPU簇数不为-1;

二是bL_switcher_disable函数调用kthread_stop,唤醒线程

bL_switch_to

找到成对的CPU ID ,簇号

mcpm_cpu_power_up 给CPU上电,跳转到 mcpm_entry_point

gic_send_sgi 给其发送0号软中止

wait_for_completion_timeout(&inbound_alive 等候它给我发送软中止 IPI_COMPLETION

封闭IRQ、FIQ

搬迁中止到对应的CPU上

封闭时钟Tick

cpu_pm_enter gic_cpu_save 保存中止设置

cpu_suspend这个跟睡觉的流程很类似

bL_switchpoint

call_with_stack arch/arm/lib/call_with_stack.S 若失利了,是能够回来的

bL_do_switch

让刚起来的CPU跳转到cpu_resume,给其发送sev

若handshake变量为0,则进入wfe

等候不为0后,mcpm_cpu_power_down对本身断电

call_with_stack:带着的三个参数,榜首个是函数,第二个是函数调用时用到的参数,第三个是栈地址

将SP、LR顺次放入栈的顶部

SP赋值让开两个寄存器后的地址

R0赋给R2

R1赋给R0

LR赋值下面的标号1处

R2赋给PC,即跳转到R2

若失利了,则跳转到LR处,便是标号1处

弹出LR

弹出SP

LR赋给PC,跳转到了bL_switchpoint,调用call_with_stack函数的当地。

此处设置真是奇妙,不同簇对应的CPU ID都是0,则刚起来的CPU正好能经过下面的过程

mcpm_entry_point-> cpu_resume-> cpu_do_resume=cpu_v7_do_resume -> cpu_resume_mmu -> 再次跳转到上面调用__cpu_suspend处持续运转了。

即要下电的CPU刚保存后仓库,又被刚上电的CPU康复了。

接下来便是上电的CPU再运转了。

cpu_pm_exit gic_cpu_restore 康复中止设置

时钟接着运转 Tick,两个CPU用到的节拍Timer是同一个。

敞开IRQ、FIQ

*handshake_ptr = 1;

dsb_sev 给那个CPU发送事情

这样就完结了CPU的切换,这个函数的前一半是一个CPU在履行,后一半变成了另一个CPU在履行。

4 bL_cpufreq_register

获取bL_switcher_active的值,将这个值(真或许假)设置给bL_switching_enabled变量;

初始化互斥锁cluster_lock;

注册cpufreq_driver驱动bL_cpufreq_driver。

假如上面的驱动注册成功,则将bL_switcher_notifier 挂在bL_activation_notifier链表上;

若挂载失利,则卸载驱动bL_cpufreq_driver

bL_cpufreq_driver界说如下:

static struct cpufreq_driver bL_cpufreq_driver = {

.name = “arm-big-little”,

.flags = CPUFREQ_ST%&&&&&%KY,

.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注册成功,履行下面的指令,就能够看到有个驱动是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这种调频战略时,就会履行到bL_cpufreq_set_target,然后履行bL_cpufreq_set_rate,则有或许调用到bL_switch_request。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/zhishi/277317.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部