Modernize Loongson64 Machine

龙芯的主线内核代码快有一年多没动静了。

Modernize Loongson64 Machine 是我这段时间一直在做的一个Patchset,其主要目标是:

  • 清理龙芯的Legacy代码,将2E/F从3A的代码分离出来方便维护。
  • 使用DeviceTree机制,减少platform device类的dirty work的含量,减少其他子系统的维护难度,使用更多通用机制。
  • 在主线内核增加3A+7A和2K方案支持。

核心观念:希望主线内核里龙芯的代码越来越“少”。也就是采用更多通用的机制。

下面是我大量碎碎念式的记录。

设想

本来是想一次提交所有补丁的,v1和v2彻底打脸了,工作量太大。

代码大清理

  • 分离2E/F与3A代码 Update: 已Merge
  • 将各种不用的代码和有通用机制的代码清理(fw args/cmdline, 8250 early printk) Update: 已Merge

重构中断

本来的中分发大致流程是从CPU收到中断开始一把梭,在mach的irq.c里读HT向量,do_IRQ 8259,把HT中断直接路由到一个CPU IP。但是这样显然不能很好的描述硬件表现。所以我决定把中断控制器分为四级:

  1. CPU IRQ 也就是CPU核的中断线,有现成的mti cpu intc驱动。找到个IRQ Domain的问题,这个驱动在CPU_IRQ_BASE > 15的情况下工作不正常,给修了。另外这个驱动缺乏独立向量中断的优化,这个要想办法整一整。

  2. IO INTC 3A的IO中断控制器(长得和2K的I/O中断控制器也很像),UART(LPC)中断和HT中断控制器的上级都挂在这上面。它可以路由到上游,也就是CPU IRQ的IP中断线上。之前的中断设计都是只把他当个路由器用,把UART路由到IP2,HT路由到IP3,现在我觉得应该把这些中断区分开来。这样可以更加“精确”的访问HT中断向量,并且也方便以后启用实现ECC等其他中断来源的中断。

  3. HT INTC 3A的桥片中断走HT控制器。HT控制器的中断实质上是个MSI引擎,PCIe设备的MSI中断也由他处理(桥片需要转发包的时候做处理?按HT的Spec来看HT的中断包和普通的读写包是不一样的)。它可以作为IOINTC的Chained IRQ,根据上游中断线去读中断向量。 Update:可以直接实现成MSI控制器,利用IRQ Domain的Allocate功能轻松的给下游分配中断号。7A的HTMSI号是可以自由分配的,PIC好像是定死的? Update: 4000的EXTIOI好像可以直接取代HTINTC从IP上拿,也就是说不用做I/O中断的Chained了。IRQ绑核也可以这里做了。

  4. PIC/PCH_INTC PIC就是在780E情况下的I8259中断,应该也是HT以类似MSI的形式Poll来的。PIC的中断向量就是HT的0-15,限制死了。考虑直接注册给HT INTC?之前实现了plat-poll机制但没那么好使,如果要用IRQ Domain分配指定的中断号的话显然也有些麻烦。Legacy Interrupt反正编号定死。 7A的话估计得做个Hierarchy domain做级联。

中断号分配

  • 0~15 PIC (7A LPC)
  • 32~40 CPU IP (包括SMP)
  • 64-127 PCH_INT (7A片上设备)

NR_IRQ设256或512?剩下的中断号,比如MSI和HT INTC在这之中动态分配。

重构PCI

Generic PCI + PCI Domain

干掉LEGACY PCI! 只要实现个Map Bus就行了。

Quirks

Fixup包括MRRS(见Keystone),2K/7A要过滤掉的设备(APB confbus), ClassCode(7A的Bridge),780E的vbios。 7A重复发现的问题怎么Quirk?麻烦。

Port Logic

7A的PCIe Bridge BAR里有些Port Logic,可以区分中断来源,操作ltssm做Hotplug等,可以做个Port Logic Driver,不过怎么写还没想好

重构SMP

现在的SMP代码实在是太头大,各种写死的地址etc 每加上一种新的片子就要大规模重构。 Experimental 正在做实验

Mailbox地址

Mailbox地址应该不写死,由DeviceTree表达,不然2K和3A4000地址不一样又要重新写。 有两种方案,一种是每个CPU Node加个属性,和Arm的spin-table一样。 第二种是做个SMP Controller Node。话说这样的话是不是IPI也可以做个带Allocate的Domain?那就可以用通用的IPI实现了,sync-r4k也可以走起了。

Hotplug/Cache

这玩意有够头疼。。每种芯片的Cache结构不一样,play_dead里Cache清不干净一不小心就把芯片玩死了。play_dead应该尽量用run_uncached实现。在开始刷Cache之前整个函数本地变量把Cache Info存了(run_uncached会整sp,本地变量是安全的)。复苏的时候拿Mailbox的地址用个寄存器传进去,不要再写死或者按Ebase.CPUNum算了。 Update: cpu_state可以用Mailbox3,不用在这个变量上折腾Cache了。

CSR IPI

基于CSR的IPI倒是方便。注意,按4000的PMON他用PC的低32bit有没有写入来判断写Mailbox PC有没有完成,内核里也得这么整。跨片。 读其他节点的Mailbox还是要靠MMIO,逃不开咯。CSR只能访问当前Node的Mailbox。

Node Based Bring-up

5000要上16/64核?一个个Bringup得慢死。可以考虑每个Node Bringup零号核之后让零号核整其他核。

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy