arm64: paravirt: Initialize steal time when cpu is online

Steal time initialization requires mapping a memory region which
invokes a memory allocation. Doing this at CPU starting time results
in the following trace when CONFIG_DEBUG_ATOMIC_SLEEP is enabled:

BUG: sleeping function called from invalid context at mm/slab.h:498
in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 0, name: swapper/1
CPU: 1 PID: 0 Comm: swapper/1 Not tainted 5.9.0-rc5+ #1
Call trace:
dump_backtrace+0x0/0x208
show_stack+0x1c/0x28
dump_stack+0xc4/0x11c
___might_sleep+0xf8/0x130
__might_sleep+0x58/0x90
slab_pre_alloc_hook.constprop.101+0xd0/0x118
kmem_cache_alloc_node_trace+0x84/0x270
__get_vm_area_node+0x88/0x210
get_vm_area_caller+0x38/0x40
__ioremap_caller+0x70/0xf8
ioremap_cache+0x78/0xb0
memremap+0x9c/0x1a8
init_stolen_time_cpu+0x54/0xf0
cpuhp_invoke_callback+0xa8/0x720
notify_cpu_starting+0xc8/0xd8
secondary_start_kernel+0x114/0x180
CPU1: Booted secondary processor 0x0000000001 [0x431f0a11]

However we don't need to initialize steal time at CPU starting time.
We can simply wait until CPU online time, just sacrificing a bit of
accuracy by returning zero for steal time until we know better.

While at it, add __init to the functions that are only called by
pv_time_init() which is __init.

Signed-off-by: Andrew Jones <drjones@redhat.com>
Fixes: e0685fa228fd ("arm64: Retrieve stolen time as paravirtualized guest")
Cc: stable@vger.kernel.org
Reviewed-by: Steven Price <steven.price@arm.com>
Link: https://lore.kernel.org/r/20200916154530.40809-1-drjones@redhat.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by Andrew Jones and committed by Catalin Marinas 75df529b 32f6865c

Changed files
+15 -12
arch
arm64
kernel
include
linux
+15 -11
arch/arm64/kernel/paravirt.c
··· 50 50 struct pv_time_stolen_time_region *reg; 51 51 52 52 reg = per_cpu_ptr(&stolen_time_region, cpu); 53 - if (!reg->kaddr) { 54 - pr_warn_once("stolen time enabled but not configured for cpu %d\n", 55 - cpu); 53 + 54 + /* 55 + * paravirt_steal_clock() may be called before the CPU 56 + * online notification callback runs. Until the callback 57 + * has run we just return zero. 58 + */ 59 + if (!reg->kaddr) 56 60 return 0; 57 - } 58 61 59 62 return le64_to_cpu(READ_ONCE(reg->kaddr->stolen_time)); 60 63 } 61 64 62 - static int stolen_time_dying_cpu(unsigned int cpu) 65 + static int stolen_time_cpu_down_prepare(unsigned int cpu) 63 66 { 64 67 struct pv_time_stolen_time_region *reg; 65 68 ··· 76 73 return 0; 77 74 } 78 75 79 - static int init_stolen_time_cpu(unsigned int cpu) 76 + static int stolen_time_cpu_online(unsigned int cpu) 80 77 { 81 78 struct pv_time_stolen_time_region *reg; 82 79 struct arm_smccc_res res; ··· 106 103 return 0; 107 104 } 108 105 109 - static int pv_time_init_stolen_time(void) 106 + static int __init pv_time_init_stolen_time(void) 110 107 { 111 108 int ret; 112 109 113 - ret = cpuhp_setup_state(CPUHP_AP_ARM_KVMPV_STARTING, 114 - "hypervisor/arm/pvtime:starting", 115 - init_stolen_time_cpu, stolen_time_dying_cpu); 110 + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, 111 + "hypervisor/arm/pvtime:online", 112 + stolen_time_cpu_online, 113 + stolen_time_cpu_down_prepare); 116 114 if (ret < 0) 117 115 return ret; 118 116 return 0; 119 117 } 120 118 121 - static bool has_pv_steal_clock(void) 119 + static bool __init has_pv_steal_clock(void) 122 120 { 123 121 struct arm_smccc_res res; 124 122
-1
include/linux/cpuhotplug.h
··· 142 142 /* Must be the last timer callback */ 143 143 CPUHP_AP_DUMMY_TIMER_STARTING, 144 144 CPUHP_AP_ARM_XEN_STARTING, 145 - CPUHP_AP_ARM_KVMPV_STARTING, 146 145 CPUHP_AP_ARM_CORESIGHT_STARTING, 147 146 CPUHP_AP_ARM_CORESIGHT_CTI_STARTING, 148 147 CPUHP_AP_ARM64_ISNDEP_STARTING,