Hacking Linux on PowerPC: porting to a new platform

Вот и настало время обновить наше скудное содержание))
А вопрос следующий: тяжело ли добавить поддержку для новой powerpc-based платформы для нашего любимого пингвина :)
Давайте смотреть! )

Директория ядра arch/powerpc/platforms содержит все что на данный момент поддерживается:

40x   52xx  85xx  amigaone  embedded6xx    Kconfig          maple     prep
44x   82xx  86xx  cell      fsl_uli1575.c  Kconfig.cputype  pasemi    ps3
512x  83xx  8xx   chrp      iseries        Makefile         powermac  pseries

Большинство директорий содержит файл /setup.c. Его задача - реализация платфо-зависимого boot-time кода. Его реализация должна начинаться с макро define_machine(). define_machine по сути своей объявляет сруктуру struct machdep_calls - интерфейс к нашей платформе. (arch/powerpc/include/asm/machdep.h)
#define __machine_desc __attribute__ ((__section__ (".machine.desc")))
 
#define define_machine(name)                    \
    extern struct machdep_calls mach_##name;        \
    EXPORT_SYMBOL(mach_##name);             \
    struct machdep_calls mach_##name __machine_desc =

т.е. эта структура будет лежать в секции .machine.desc

Ядро на самом деле знает только о структуре struct machdep_calls ppc_md (powerpc machine description), через которую и вызывает наши конкретные функции (arch/powerpc/kernel/setup-common.c)

Несколько примеров таких структур:
Cell:

define_machine(cell) {
    .name           = "Cell",
    .probe          = cell_probe,
    .setup_arch     = cell_setup_arch,
    .show_cpuinfo       = cell_show_cpuinfo,
    .restart        = rtas_restart,
    .power_off      = rtas_power_off,
    .halt           = rtas_halt,
    .get_boot_time      = rtas_get_boot_time,
    .get_rtc_time       = rtas_get_rtc_time,
    .set_rtc_time       = rtas_set_rtc_time,
    .calibrate_decr     = generic_calibrate_decr,
    .progress       = cell_progress,
    .init_IRQ           = cell_init_irq,
    .pci_setup_phb      = cell_setup_phb,
};

AmigaOne:
define_machine(amigaone) {
    .name           = "AmigaOne",
    .probe          = amigaone_probe,
    .setup_arch     = amigaone_setup_arch,
    .show_cpuinfo       = amigaone_show_cpuinfo,
    .init_IRQ       = amigaone_init_IRQ,
    .restart        = amigaone_restart,
    .calibrate_decr     = generic_calibrate_decr,
    .progress       = udbg_progress,
};

IBM iSeries:
     define_machine(iseries) {
    .name           = "iSeries",
    .setup_arch     = iSeries_setup_arch,
    .show_cpuinfo       = iSeries_show_cpuinfo,
    .init_IRQ       = iSeries_init_IRQ,
    .get_irq        = iSeries_get_irq,
    .init_early     = iSeries_init_early,
    .pcibios_fixup      = iSeries_pci_final_fixup,
    .pcibios_fixup_resources= iSeries_pcibios_fixup_resources,
    .restart        = mf_reboot,
    .power_off      = mf_power_off,
    .halt           = mf_power_off,
    .get_boot_time      = iSeries_get_boot_time,
    .set_rtc_time       = iSeries_set_rtc_time,
    .get_rtc_time       = iSeries_get_rtc_time,
    .calibrate_decr     = generic_calibrate_decr,
    .progress       = iSeries_progress,
    .probe          = iseries_probe,
    .ioremap        = iseries_ioremap,
    .iounmap        = iseries_iounmap,
#ifdef CONFIG_KEXEC
    .machine_kexec_prepare  = iseries_kexec_prepare,
#endif
    /* XXX Implement enable_pmcs for iSeries */
};

Поддержка SMP обычно реализуется в функции .setup_arch, причем SMP тоже реализуется как правило в файле /smp.c
Здесь очень похожая история: ядро знает о struct smp_ops_t *smp_ops, которую мы должны инициализировать:

Пример для Cell:

static struct smp_ops_t bpa_iic_smp_ops = {
    .message_pass   = smp_iic_message_pass,
    .probe      = smp_iic_probe,
    .kick_cpu   = smp_cell_kick_cpu,
    .setup_cpu  = smp_cell_setup_cpu,
    .cpu_bootable   = smp_cell_cpu_bootable,
};
 
/* This is called very early */
void __init smp_init_cell(void)
{
...
smp_ops = &bpa_iic_smp_ops;
...