Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

LoongArch: Add cpuhotplug hooks to fix high cpu usage of vCPU threads

When the CPU is offline, the timer of LoongArch is not correctly closed.
This is harmless for real machines, but resulting in an excessively high
cpu usage rate of the offline vCPU thread in the virtual machines.

To correctly close the timer, we have made the following modifications:

Register the cpu hotplug event (CPUHP_AP_LOONGARCH_ARCH_TIMER_STARTING)
for LoongArch. This event's hooks will be called to close the timer when
the CPU is offline.

Clear the timer interrupt when the timer is turned off. Since before the
timer is turned off, there may be a timer interrupt that has already been
in the pending state due to the interruption of the disabled, which also
affects the halt state of the offline vCPU.

Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>

authored by

Xianglai Li and committed by
Huacai Chen
8ef7f313 f7794a4d

+23
+22
arch/loongarch/kernel/time.c
··· 5 5 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 6 6 */ 7 7 #include <linux/clockchips.h> 8 + #include <linux/cpuhotplug.h> 8 9 #include <linux/delay.h> 9 10 #include <linux/export.h> 10 11 #include <linux/init.h> ··· 103 102 return 0; 104 103 } 105 104 105 + static int arch_timer_starting(unsigned int cpu) 106 + { 107 + set_csr_ecfg(ECFGF_TIMER); 108 + 109 + return 0; 110 + } 111 + 112 + static int arch_timer_dying(unsigned int cpu) 113 + { 114 + constant_set_state_shutdown(this_cpu_ptr(&constant_clockevent_device)); 115 + 116 + /* Clear Timer Interrupt */ 117 + write_csr_tintclear(CSR_TINTCLR_TI); 118 + 119 + return 0; 120 + } 121 + 106 122 static unsigned long get_loops_per_jiffy(void) 107 123 { 108 124 unsigned long lpj = (unsigned long)const_clock_freq; ··· 189 171 190 172 lpj_fine = get_loops_per_jiffy(); 191 173 pr_info("Constant clock event device register\n"); 174 + 175 + cpuhp_setup_state(CPUHP_AP_LOONGARCH_ARCH_TIMER_STARTING, 176 + "clockevents/loongarch/timer:starting", 177 + arch_timer_starting, arch_timer_dying); 192 178 193 179 return 0; 194 180 }
+1
include/linux/cpuhotplug.h
··· 168 168 CPUHP_AP_QCOM_TIMER_STARTING, 169 169 CPUHP_AP_TEGRA_TIMER_STARTING, 170 170 CPUHP_AP_ARMADA_TIMER_STARTING, 171 + CPUHP_AP_LOONGARCH_ARCH_TIMER_STARTING, 171 172 CPUHP_AP_MIPS_GIC_TIMER_STARTING, 172 173 CPUHP_AP_ARC_TIMER_STARTING, 173 174 CPUHP_AP_REALTEK_TIMER_STARTING,