首页 > 系统相关 >多核内存访问问题整理

多核内存访问问题整理

时间:2024-06-04 17:23:39浏览次数:30  
标签:初始化 cache Cache 访问 多核 内存 L2 Core1 cpu

问题:linux 和 裸板通信 不采用ocm的时候 ,各自对内存访问不体现在另一个核的内存上。

zynq 的两级缓存 和ddr访问问题

 

linux + 裸核,linux那边的缓存行为还不确定

 

裸核的两级数据缓存 由 Xil_DCache 决定;

cache几个操作:clean、invalidate与flush的含义

cache line

cache line是cache的基本访问单元。

cache line一般都会包含valid和dirty两个状态位,如下图的v和d。

valid位表示当前cache line的内容是否有效。dirty位表示当前cache line的内容是否比内存上的要更新(即是否修改过)。

 

 清除(flush) cache的意思是清除cache中存储的全部数据。对处理器而言,清除操作只要清零相应cache行的有效位即可。当存储器配置上有变化时,整体或部分cache可能需要进行清除(flush)操作。有时也用术语作废(invalidate)来代替术语“清除(flush)”。然而,对于采用写回策略的D-cache,就需要使用清理(clean)操作(注:dcache也有flush(清除)操作,见flush_dcache_range函数)。
    清理(clean) cache的意思是把脏的(即被改写过的)cache行强制写到主存,并把cache行中的脏位清零。清理(clean)cache可以重建cache与主存之间的一致性,它只用在使用写回策略的D-cache上。

 

arm a9系列 v7架构 的cache设置功能

 

 

 

 

 

linux 启动CPU过程:

https://www.cnblogs.com/linhaostudy/p/16384935.html

一般主处理器启动从处理器有以下三种:

(1).ACPI

(2).spin-table

(3).PSCI

第一种ACPI是高级配置与电源接口(Advanced Configuration and Power Interface)一般在x86平台用的比较多,而后两种spin-table(自旋表)和PSCI(电源状态协调协议 Power State Coordination)会在arm平台上使用,本系列主要讲解后两种。主要内容分为上下两篇如下:

 

soc启动流程:soc启动的一般会从片内的rom, 也叫bootrom开始执行第一条指令,这个地址是系统默认的启动地址,会在bootrom中由芯片厂家固化一段启动代码来加载启动bootloader到片内的sram,启动完成后的bootloader除了做一些硬件初始化之外做的最重要的事情是初始化ddr,因为sram的空间比较小所以需要初始化拥有大内存 ddr,最后会从网络/usb下载 或从存储设备分区上加载内核到ddr某个地址,为内核传递参数之后,然后bootloader就完成了它的使命,跳转到内核,就进入了操作系统内核的世界。

4)linux内核启动流程:bootloader将系统的控制权交给内核之后,他首先会进行处理器架构相关初始化部分,如设置异常向量表,初始化mmu(之后内核就从物理地址空间进入了虚拟地址空间的世界,一切是那么的虚无缥缈,又是那么的恰到好处)等等,然后会清bss段,设置sp之后跳转到C语言部分进行更加复杂通用的初始化,其中会进行内存方面的初始化,调度器初始化,文件系统等内核基础组件 初始化工作,随后会进行关键的从处理器的引导过程,然后是各种实质性的设备驱动的初始化,最后 创建系统的第一个用户进程init后进入用户空间执行用户进程宣誓内核初始化完成,可以进程正常的调度执行。

5)系统初始化阶段大多数都是主处理器做初始化工作,所有不用考虑处理器并发情况,一旦从处理器被bingup起来,调度器和各自的运行队列准备就绪,多个任务就会均衡到各个处理器,开始了并发的世界,一切是那么的神奇

 

在spin_table_secondary_jump中:首先会执行wfe指令,使得从处理器睡眠等待。如果被唤醒,则从处理器会判断spin_table_cpu_release_addr这个地址是否为0,为0则继续跳转到wfe处继续睡眠,否则跳转到spin_table_cpu_release_addr指定的地址处执行。

那么这个地址什么时候会被设置呢?答案是:主处理器在uboot中读取设备树的相关节点属性获得,我们来看下如何获得。执行路径为:

do_bootm_linux
->boot_prep_linux
 ->image_setup_linux
  ->image_setup_libfdt
  ->arch_fixup_fdt
   ->spin_table_update_dt

 

那么什么时候释放地址spin_table_cpu_release_addr 的内容不是0呢?

那么我们得回到主处理器流程上来:主处理器设置好了设备树,传递给内核设备树地址之后就要启动内核,启动内核之后,执行初始化工作,执行如下路径:

setup_arch   //arch/arm64/kernel/setup.c:
->smp_init_cpus  //arch/arm64/kernel/smp.c
 ->**smp_cpu_setup**
  ->cpu_ops[cpu]->cpu_init(cpu)
   ->smp_spin_table_ops->cpu_init  //arch/arm64/kernel/cpu_ops.c
    ->**smp_spin_table_cpu_init**//arch/arm64/kernel/smp_spin_table.c

 

但是事与愿违,在这个函数中又有了一层关卡:689行到701行 判断是否secondary_holding_pen_release被设置为了从处理器的编号,如果设置的不是我的编号,则我再次进入705行执行wfe睡眠等待,行吧,那就等待啥时候主处理器来将secondary_holding_pen_release设置为我的处理器编号吧。那么何时会设置呢?答案是最终要启动从处理器的时候。

我们再次回到主处理器的处理流程,上面主处理器执行到了smp_prepare_cpus之后,继续往下执行,代码路径如下:

start_kernel
->arch_call_rest_init
  ->rest_init
    ->kernel_init,
  ->kernel_init_freeable
   ->smp_prepare_cpus //arch/arm64/kernel/smp.c
    ->smp_init  //kernel/smp.c  (这是从处理器启动的函数)
    ->cpu_up
     ->do_cpu_up
      ->_cpu_up
       ->cpuhp_up_callbacks
        ->cpuhp_invoke_callback
         ->cpuhp_hp_states[CPUHP_BRINGUP_CPU]
          ->**bringup_cpu**
           ->__cpu_up  //arch/arm64/kernel/smp.c
            ->boot_secondary
             ->cpu_ops[cpu]->cpu_boot(cpu)
              ->smp_spin_table_ops.cpu_boot  //arch/arm64/kernel/cpu_ops.c
               ->smp_spin_table_cpu_boot //arch/arm64/kernel/smp_spin_table.c

https://pic1.zhimg.com/80/v2-5152c326e8ce7e2ddde144b908102ec0_720w.jpg




zynq
Xil_DCacheInvalidateRange
发送前Xil_DCacheFlushRange,接收数据Xil_DCacheInvalidateRange
但感觉没有直接disable 效果好,核1 FLUSH,修改的数据,核0 关了cache还是没收到。





zynq相关
SCU: Snoop Control Unit,用来保持双核之间的数据Cache的一致性。也就是说,第一个A9 处理器写存储时,只是写在了缓存里,没有进主存,如果第二个A9读操作,涉及到第一个写脏了的数据段,SCU要保证第二个A9的缓存里是最新的数据。如果第二个A9写同样数据段的数据,需要在第一个中体现出写的内容。SCU的存在,才使得两个核成互相联系的 “双核”,才能成为MPsoc。
4、赛灵思 7 系列器件包含 32 个全局时钟缓冲器 (BUFG)。其中 16 个全局时钟缓冲器位于 FPGA 器件水平方向中心的上半部分,而另外 16 个则位于水平方向中心的下半部分。芯片上半部的 PLL MMCM只能连接到水平方向中心以上的 16 个 BUFG 上。而芯片下半部的PLL 和 MMCM 只能连接到水平方向中心以下的 16 个 BUFG 上。选择 PLL 或 MMCM 时,请尽量使用 PLL,因为其具有更严格的抖动控制。在如下情况下也可以使用 MMCM :(1) PLL 已用尽 ; (2)MMCM 可提供所需的高级功能,但 PLL 则不能。


Zynq的AMP开发注意事项之禁用L2 cache

2.原理说明

首先,在AMP模式中,core 0与core 1共用512K L2 Cache,这势必会引起两个核的Cache竞争问题。
通常情况下,L2 Cache被core 0,core 1共享。那么会出现以下情况:
core 0的内存访问操作可能会清除core 1所使用的L2缓存内容,从而使core 1的软件性能有不确定性。
有时,我们需要为core 0 或core 1提供更多的确定性行为,尤其是架构为AMP时。


3.L2 Cache的锁定

通过寄存器的控制可以将L2 Cache锁定在不同core上,这让用户可以将L2 Cache的功能保留在特定的core上。

(1)相关说明

第一:Cache way是分区的宽度,Zynq的L2 Cache有8 Cache ways。

第二:L2 Cache控制器只能被锁定8个不同的方式。

如图 3.1所示,在Zynq 7000中,Cortex-A9 MP核的64个AXI被分为8个可以锁定的组。



问题验证步骤:
1.Core0-Linux初始化L2-cache,Core1-FreeRTOS BSP不对L2-cache初始化,Core1-FreeRTOS DMA搬运数据
core0的memtester 100M 1 操作影响core1的响应速度

2.Core0-Linux不初始化L2-cache,Core1-FreeRTOS BSP对L2-cache初始化,Core1-FreeRTOS DMA搬运数据
core0的memtester 100M 1 操作影响core1的响应速度

3.Core0-Linux不初始化L2-cache,Core1-FreeRTOS BSP对L2-cache初始化,lockdown by master方法,将L2-Cache空间一半用于Core0-Linux,一半用于缓存Core1-FreeRTOS的数据,Core1-FreeRTOS DMA搬运数据
网口不通,core0的memtester 100M 1 操作影响core1的响应速度

4.Core0-Linux不初始化L2-cache,Core1-FreeRTOS BSP对L2-cache初始化,lockdown by master方法,将L2-Cache空间全部用于缓存Core1-FreeRTOS的数据,Core1-FreeRTOS DMA搬运数据
core0网口OK,core0启动速度变慢,core0的memtester 100M 1操作影响core1的响应速度

5.Core0-Linux不初始化L2-cache,Core1-FreeRTOS BSP对L2-cache初始化,lockdown by master方法,将L2-Cache空间全部用于缓存Core1-FreeRTOS的数据,Core1-FreeRTOS CPU搬运数据
网口OK,core0启动速度变慢,core0的memtester 100M 1 对core1没有明显的影响

6.Core0-Linux初始化L2-cache,Core1-FreeRTOS BSP不对L2-cache初始化,Core1-FreeRTOS CPU搬运数据
网口OK,core0启动速度不受影响,memtester 100M 1操作影响core1的响应速度

7.Core0-Linux初始化L2-cache,Core1-FreeRTOS BSP不对L2-cache初始化,Core1-FreeRTOS BSP配置lockdown相关寄存器 将L2-Cache空间一半用于Core0-Linux,一半用于缓存Core1-FreeRTOS的数据,CPU搬运数据
网口OK,core0启动速度不受影响,core0的memtester 100M 1 对core1没有明显的影响
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/Doriswang84/article/details/97272500

lockdown by master的相关寄存器:

/i/ll/?i=20190725165118762.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0Rvcmlzd2FuZzg0,size_16,color_FFFFFF,t_70

ldr r0, =L2CCDLockdown0 /* Load L2CC base address base + reg9_d_lockdown0 register*/
ldr r1, =0x0f
str r1, [r0] /* lockdown by cpu0 */

ldr r0, =L2CCILockdown0 /* Load L2CC base address base + way register*/
ldr r1, =0x0f
str r1, [r0] /* lockdown by cpu0 */

ldr r0, =L2CCDLockdown1 /* Load L2CC base address base + reg9_d_lockdown1 register */
ldr r1, =0xf0
str r1, [r0] /* lockdown by cpu1 */

ldr r0, =L2CCILockdown1 /* Load L2CC base address base + reg9_i_lockdown1 register */
ldr r1, =0xf0
str r1, [r0] /* lockdown by cpu1 */
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/Doriswang84/article/details/97272500

 

 

 

 

如何初始化L2 cache

mrc  p15,1,r0,c9,c0,2

orr   r0,r0,#0x1

mcr p15,1,r0,c9,c0,2

 

失效:

mov ro,#0

mcr p15,0,r0,c7,c14,2

 

 

缓存读写策略

CACHE 写透式与回写式

 

 

use_amp 以及进制初始化CPU1的l2缓存,但还有l1缓存。

那么总结一下就是,“-DUSE_AMP=1”编译选项将影响到工程代码里的USE_AMP预编译指令,使得Cache操作函数、全局时钟以及中断控制器SCUGIC的初始化函数不被编译进CPU1的应用程序中,避免可能会出现的CPU0和CPU1Cache一致性维护异常和中断异常等问题。

 

两个核心各自拥有独立的L1 DCache,并且共享同一个L2 DCache,在ZYNQ中存在一个Snoop Control Unit (SCU)用于维护CORE0和CORE1的L1 DCache与L2 DCache之间的一致性

但好像没更新是为啥(linux smp那边设置的?)

DCache一致性维护的原理为:在多级存储器结构中,CPU通过1级或多级Cache与DDR产生连接,CPU本身不直接访问DDR,而是通过Cache访问DDR。Cache中始终会暂存一小部分(通常是KB~几MB量级)CPU最近访问的DDR某些地址区域中的数据。因此,在应用程序中对DDR进行读或写操作,实际上都是CPU对Cache进行读或写操作。当DDR中某个地址范围内的数据突然被除CPU以外的Master(如DMA)改变时,若此时Cache中保存了这些区域的数据,且这些数据在Cache中状态为有效时,当CPU需要再次读取DDR这片区域的数据时,就不会让Cache去读取DDR中此区域内最新的数据来更新Cache,再从Cache里读取最新的数据,而是直接从Cache中读取原来的旧数据,显然这不是我们所期望的结果。这时,便引入了所谓的Cache一致性问题。

 

    ZYNQ中维护DCache一致性的方法为:写入方将数据写入DDR对应地址区域后,需将残留在DCache中相应地址范围内的数据全部刷入DDR3中。读取方在从DDR相应地址读取数据之前,需将DCache中DDR相应地址范围内的数据全部设置为invalid,然后CPU会再次通过DCache从DDR3中读取该地址范围内最新的数据。

 在get_data_from_region函数中,在将CORE0传递的数据复制到本地缓存区域之前,调用Xil_DCacheInvalidateRange函数将DCache中该数据指针所指向内存区域的数据设置为invalid,进行DCache一致性维护

  CORE0通过shared_mem.c中的put_data_to_region()函数将所需传递的数据长度及指针存入shared region结构体中。在put_data_to_region函数中调用Xil_DCacheFlushRange函数将DCache中该数据指针所指向内存区域的数据刷入DDR中,进行DCache一致性维护。

 

五、清理和清除cache
ARM使用 清理和 清除表示对cache的两种基本操作。

清理就是把脏的(即被改写过的)cache行强制写到主存,并把cache行中的脏位清零。清理cache可以重建cache和主存之间的一致性,它只是用在回写策略的D-cache上。
清除就是指清除cache中存储的全部数据,其实就是将cache使无效,将cache行中的有效位清零,让所有访问这个cache行的操作都不命中。

对cache进项清理和清除的操作是通过协处理器CP15中的寄存器C7实现的,具体操作指令看CP15协处理器寄存器详解。

————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/gameit/article/details/13169445

 

标签:初始化,cache,Cache,访问,多核,内存,L2,Core1,cpu
From: https://www.cnblogs.com/ycjstudy/p/18228075

相关文章

  • 学习笔记482—手把手教你如何用mac访问win10共享文件
    这个方法巨简单,只需要两台电脑都用同一个网络,我的两台电脑都是连接wifi使用的,跟着图文一步步来操作哦操作步骤:......
  • 轻松拿捏C语言——【内存函数】
    ......
  • Influxdb内存泄漏
    项目类型:WindowsService.netVersion: .netFramework 4.8开发语言:C#influxDBAPI:  InfluxDB.Clientv4.15.0 InfluxDB.Client.Core v4.15.0重现代码:创建一个Timer周期性地调用写入函数:_timerWriteDB=newTimer((o)=>WriteData(),null,timeMinute*1000......
  • C++访问限定符private、public、protected的使用场景
    众所周知,C++中有3种访问符,分别是private、public、protected。其中private和public比较好理解。private:只能由该类中的函数、其友元函数访问,不能被任何其他访问,更不能由该类的对象在类外进行访问,类成员变量一般修饰为private,防止类使用者不受约束地直接修改数据。public:......
  • 解锁 Java I/O 力量,一站式掌握文件操作、内存映射等黑科技
    大家好,今天我们来聊一聊Java中的I/O操作这个重要话题。作为一名资深Java开发者,深入掌握JavaI/O体系不仅可以让我们对文件、网络等资源操作游刃有余,更可以在一些场景下发挥其独特的性能优势。接下来,就让我为您一一拨开JavaI/O的神秘面纱!一、JavaI/O家族简......
  • 数据在内存中的存储<C语言>
    导言       在计算机中不同类型的数据在计算机内部存储形式各不相同,弄懂各种数据在计算机内部存储形式是有必要的,C语言的学习不能浮于表面,更要锻炼我们的“内功”,将来在写程序的时候遇见各种稀奇古怪的bug时,也便能迎刃而解,所以本文将着重介绍,整数在内存中的存储、大小......
  • 如何利用CXL技术突破内存墙?-1
    CXL诞生的基础是为了解决CPU内存和附加设备内存的互联,实现资源共享,得到最大的性能提升。随着数据大规模超算、AI、5G、云技术、边缘计算、自动驾驶等蓬勃发展,未来的数据存在指数级的增长且要求实时计算。从2019年的CXL1.0,CXL协议目前已经发展了CXL3.1。服务器目前正面临着......
  • 如何利用CXL技术突破内存墙?-2
    为了解决这些问题,业界正积极寻求新的技术和标准,比如ComputeExpressLink(CXL),它旨在通过提供标准化的高速互连来提高内存带宽、降低延迟,并简化内存扩展的软件集成,从而有效地打破内存墙的限制。通过使用CXL(ComputeExpressLink)技术来突破内存墙,可以实现以下几项关键改进,比如......
  • 通过精准的内容分发和优化的路由策略,确保企业客户能够以高速稳定的方式接入互联网,访问
    为了满足企业对于高质量、高效率互联网接入的需求,中国联通国际推出了ChinaDIA及GlobalDIA产品,旨在为企业客户提供专属IP地址和独享带宽,保证企业客户能够以更加稳定、高速的方式访问全球互联网内容。产品优势带宽独享:中国联通国际拥有丰富的全球网络资源,凭借行业领先的技术和......
  • c语言中,结构体变量交换改写为堆空间申请内存
            在这里我实现的功能为:输入三个人的信息,每个人的信息分别为姓名和三个成绩,我分别计算三个人的成绩和,并通过经典的三杯水案例完成对三个人的成绩从小到大的排列打印。重点:     我这里使用的为堆空间申请内存的形式 第一步:        定义一个......