linux : psci

27
Linux : PSCI 2016/5/7(土)、作成 2016/11/19 ()、追記 @Vengineer

Upload: mr-vengineer

Post on 12-Apr-2017

738 views

Category:

Software


1 download

TRANSCRIPT

Page 1: Linux : PSCI

Linux : PSCI

2016/5/7(土)、作成2016/11/19 (土)、追記

@Vengineer

Page 2: Linux : PSCI

PSCIとは

PSCIは、POWER STATE COORDINATION INTERFACE の略

ARMv8(ARM64)では、多くのSoCがPSCIをサポートしている

参考資料"Power State Coordination Interface System Software on ARM processors"http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/

LinuxのDevice Tree Bindinghttps://www.kernel.org/doc/Documentation/devicetree/bindings/arm/psci.txt

Page 3: Linux : PSCI

cpuノードのenable-methodプロパティ

http://lxr.free-electrons.com/source/Documentation/devicetree/bindings/arm/cpus.txt

- enable-method Value type: <stringlist> Usage and definition depend on ARM architecture version. # On ARM v8 64-bit this property is required and must be one of:

"psci" "spin-table" - cpu-release-addr Usage: required for systems that have an "enable-method" property value of "spin-table". Value type: <prop-encoded-array> Definition: # On ARM v8 64-bit systems must be a two cell property identifying a 64-bit zero-initialised memory location.

Page 6: Linux : PSCI

spin-tableの例 : Raspberry Pi3

h追記)、2016.11.19  Raspberry Pi3は、Linux 4.8でサポートされたが ”spin-table”

arch/arm64/boot/dts/broadcom/bcm2837.dtsi

参考資料)、 2016年11月号、第2章

 なるほどそうやって動くのか!リセット直後から丸はだか!

 完全理解! ラズベリー・パイの32/64ビットLinux起動シーケンス

                          原山 みや

 http://www.kumikomi.net/interface/sample/201611/if11_037.pdf

Page 7: Linux : PSCI

enable-methodプロパティのチェック

http://lxr.free-electrons.com/source/arch/arm64/kernel/cpu_ops.c

static const char *__init cpu_read_enable_method(int cpu) { struct device_node *dn = of_get_cpu_node(cpu, NULL);

enable_method = of_get_property(dn, "enable-method", NULL); if (!enable_method) { /* The boot CPU may not have an enable method (e.g. * when spin-table is used for secondaries). * Don't warn spuriously. */ if (cpu != 0) pr_err("%s: missing enable-method property\n", dn->full_name); }}

Page 8: Linux : PSCI

pscihttp://lxr.free-electrons.com/source/arch/arm64/kernel/psci.c

const struct cpu_operations cpu_psci_ops = { .name = "psci",#ifdef CONFIG_CPU_IDLE .cpu_init_idle = cpu_psci_cpu_init_idle, .cpu_suspend = cpu_psci_cpu_suspend,#endif .cpu_init = cpu_psci_cpu_init, .cpu_prepare = cpu_psci_cpu_prepare, .cpu_boot = cpu_psci_cpu_boot,#ifdef CONFIG_HOTPLUG_CPU .cpu_disable = cpu_psci_cpu_disable, .cpu_die = cpu_psci_cpu_die, .cpu_kill = cpu_psci_cpu_kill,#endif};

サスペンドをサポート

ホットプラグをサポート

Page 9: Linux : PSCI

spin_tablehttp://lxr.free-electrons.com/source/arch/arm64/kernel/smp_spin_table.c

const strucsmp_spin_table.ct cpu_operations smp_spin_table_ops = { .name = "spin-table", .cpu_init = smp_spin_table_cpu_init, .cpu_prepare = smp_spin_table_cpu_prepare, .cpu_boot = smp_spin_table_cpu_boot,};

サスペンドにも、ホットプラグもサポートしていない。

.cpu_init_idle = NULL, .cpu_suspend = NULL, .cpu_disable = NULL, .cpu_die = NULL, .cpu_kill = NULL,

Page 10: Linux : PSCI

drivers/firmware/psci.c (Linux 4.3〜

static u32 psci_get_version(void){

return invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);}

Page 11: Linux : PSCI

drivers/firmware/psci.c (Linux 4.3〜

static int psci_cpu_suspend(u32 state, unsigned long entry_point){ int err; u32 fn;

fn = psci_function_id[PSCI_FN_CPU_SUSPEND];

err = invoke_psci_fn(fn, state, entry_point, 0); return psci_to_linux_errno(err);}

Page 13: Linux : PSCI

drivers/firmware/psci.c (Linux 4.3〜static int psci_system_suspend(unsigned long unused){

return invoke_psci_fn( PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND), virt_to_phys(cpu_resume), 0, 0);}

static int psci_system_suspend_enter(suspend_state_t state){ return cpu_suspend(0, psci_system_suspend);}

Page 14: Linux : PSCI

drivers/firmware/psci.c (Linux 4.3〜static int get_set_conduit_method(struct device_node *np){ if (of_property_read_string(np, "method", &method)) { pr_warn("missing \"method\" property\n"); return -ENXIO; }

if (!strcmp("hvc", method)) {

invoke_psci_fn = __invoke_psci_fn_hvc; } else if (!strcmp("smc", method)) {

invoke_psci_fn = __invoke_psci_fn_smc; }

Page 15: Linux : PSCI

drivers/firmware/psci.c (Linux 4.3〜

static unsigned long __invoke_psci_fn_smc( unsigned long function_id, unsigned long arg0, unsigned long arg1, unsigned long arg2){ struct arm_smccc_res res;

arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res); return res.a0;}

Page 16: Linux : PSCI

arch/arm64/kernel/smccc-call.S

/* * void arm_smccc_smc(unsigned long a0, unsigned long a1,            unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7, struct arm_smccc_res *res)*/

ENTRY(arm_smccc_smc) SMCCC smcENDPROC(arm_smccc_smc)

Page 17: Linux : PSCI

arch/arm64/kernel/smccc-call.S

.macro SMCCC instr .cfi_startproc \instr #0 ldr x4, [sp] stp x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS] stp x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS] ret .cfi_endproc

.endm

Page 18: Linux : PSCI

LinuxからATFへはどのように伝える?

http://lxr.free-electrons.com/source/arch/arm64/kernel/smccc-call.S

・SMC (Secure Monitor Call) を使う http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204ij/Cjaeeged.html

/* * void arm_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2, * unsigned long a3, unsigned long a4, unsigned long a5, * unsigned long a6, unsigned long a7, struct arm_smccc_res *res) */ENTRY(arm_smccc_smc) SMCCC smc /* SMCCC は、このファイル(smccc-call.S内でマクロ定義されてい

る)*/ENDPROC(arm_smccc_smc)

Page 19: Linux : PSCI

EL3 Runtime Service

https://github.com/ARM-software/arm-trusted-firmware/blob/master/docs/rt-svc-writers-guide.md

Software executing in the normal world and in the trusted world at exception levels lower than EL3 will request runtime services using the Secure Monitor Call (SMC) instruction. These requests will follow the convention described in the SMC Calling Convention PDD (SMCCC). The SMCCC assigns function identifiers to each SMC request and describes how arguments are passed and results are returned.

 ・Standard Service calls => 標準サービスの提供 ( PSCI )

 ・SiP Service calls => 各社独自サービス用

Page 20: Linux : PSCI

Standard Service calls

https://github.com/ARM-software/arm-trusted-firmware/blob/master/services/std_svc/std_svc_setup.c

/* Register Standard Service Calls as runtime service */DECLARE_RT_SVC(

std_svc,

OEN_STD_START,OEN_STD_END,SMC_TYPE_FAST,

std_svc_setup,std_svc_smc_handler

);

Page 21: Linux : PSCI

std_svc_smc_handler

https://github.com/ARM-software/arm-trusted-firmware/blob/master/services/std_svc/std_svc_setup.c

/* Top-level Standard Service SMC handler. This handler will in turn dispatch calls to PSCI SMC handler */

uint64_t std_svc_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,

void *cookie, void *handle, uint64_t flags){

/* Dispatch PSCI calls to PSCI SMC handler and return its return value */if (is_psci_fid(smc_fid)) {

return psci_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);}

Page 22: Linux : PSCI

psci_smc_handler

https://github.com/ARM-software/arm-trusted-firmware/blob/master/services/std_svc/psci/psci_main.c

uint64_t psci_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,

void *cookie, void *handle, uint64_t flags)

switch (smc_fid) {case PSCI_CPU_SUSPEND_AARCH64: SMC_RET1(handle, psci_cpu_suspend(x1, x2, x3));case PSCI_CPU_ON_AARCH64: SMC_RET1(handle, psci_cpu_on(x1, x2, x3));case PSCI_AFFINITY_INFO_AARCH64: SMC_RET1(handle, psci_affinity_info(x1, x2));case PSCI_MIG_AARCH64: SMC_RET1(handle, psci_migrate(x1));case PSCI_MIG_INFO_UP_CPU_AARCH64:SMC_RET1(handle, psci_migrate_info_up_cpu());case PSCI_SYSTEM_SUSPEND_AARCH64: SMC_RET1(handle, psci_system_suspend(x1, x2));default:break;

}

Page 23: Linux : PSCI

Power Off / Reboot / System Suspend

User Landから

 ・Power Off ・Reboot ・System Suspend

を実行した場合、どのような関数を経由して、PSCIにアクセスするのか?

Page 24: Linux : PSCI

System Halt (Power Off)

SYSCALL_DEFINE4(reboot, kernel/reboot.ckernel_restart kernel/reboot.cmachine_restart arch/arm64/kernel/process.carm_pm_restart arch/arm64/kernel/process.cpsci_sys_reset drivers/firmware/psci.cinvoke_psci_fn drivers/firmware/psci.c__invoke_psci_fn_smc drivers/firmware/psci.carm_smccc_smc include/linux/arm-smccc.h

Page 25: Linux : PSCI

System Reboot (System Reset)

SYSCALL_DEFINE4(reboot, kernel/reboot.ckernel_power_off kernel/reboot.cmachine_power_off arch/arm64/kernel/process.cpm_power_off arch/arm64/kernel/process.cpsci_sys_poweroff drivers/firmware/psci.cinvoke_psci_fn drivers/firmware/psci.c__invoke_psci_fn_smc drivers/firmware/psci.carm_smccc_smc include/linux/arm-smccc.h

Page 26: Linux : PSCI

System Suspend

pm_suspend kernel/power/suspend.center_state kernel/power/suspend.csuspend_devices_and_enter kernel/power/suspend.csuspend_enter kernel/power/suspend.cpsci_system_suspend_enter drivers/firmware/psci.cpsci_system_suspend drivers/firmware/psci.cinvoke_psci_fn drivers/firmware/psci.c__invoke_psci_fn_smc drivers/firmware/psci.carm_smccc_smc include/linux/arm-smccc.h

Page 27: Linux : PSCI

おしまい