LoongArch fixes for v6.17-rc3

-----BEGIN PGP SIGNATURE-----
 
 iQJKBAABCAA0FiEEzOlt8mkP+tbeiYy5AoYrw/LiJnoFAminBwoWHGNoZW5odWFj
 YWlAa2VybmVsLm9yZwAKCRAChivD8uImemVYD/44F6KMPz2nUnS+5kIDs6Dpe4VI
 Lqz+QinoA4ZT/poY0Ui78UEz/XqHxKmcSnIg20wHVMtZ7XuWWuqj4VHzroa83okB
 YOyYdKg8oiRJR3LSi28uPIqJjQ/UPGLtKsjuO+UJS6fgKwRYVFShGgg6V7LIXSYe
 gbkeOFcom+VMCV2PE4xxhmvfCYvG3CbisUk7YqTYFbUe8Iic0xNTDZIRT+IImL0Z
 sRq2PMGOmKNV4HU4FfixXkCyppRxX/QLLYPFap1koWk0lwreB8gVXcSNTt4HhI/R
 9hzySdJmTdn9HlWBvBn1LD24HBFs6zqliRftw8SwTZovw1garUFbpMqc8S7hE58L
 QMpV5h8BanUvoJo2X2iLvEsDycdvVPIE7voU+9JCMXyPrLy3KTbVehMY2lHY5YXu
 CMPL4nGvq1SXunrfUlxttgmVvuKKqeJ0Wp9NQ2hjOvVz2hmObRe5nugK0yBREV7b
 0GeZ1M2N8hdmMNQ39BC7P53s3XzpV258BrXbUOSzct6nITeIHzzNj69O0+jKFN7d
 RKh6Qi0XxDuocNckmrmLPk5Wh0u/OPB3D1WHyndMmPgfVCGTxF7XLqmDTJnpdDiL
 JO0IUdBB59SbecjFLZs4QXVrNIocw8TzK0HNCAFjaeEeJABCDVFoo98CrJ+wT3pG
 dAcwd9Gpal6hb+l0Bg==
 =dUol
 -----END PGP SIGNATURE-----

Merge tag 'loongarch-fixes-6.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson

Pull LoongArch fixes from Huacai Chen:
 "Fix a lot of build warnings for LTO-enabled objtool check, increase
  COMMAND_LINE_SIZE up to 4096, rename a missing GCC_PLUGIN_STACKLEAK to
  KSTACK_ERASE, and fix some bugs about arch timer, module loading, LBT
  and KVM"

* tag 'loongarch-fixes-6.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson:
  LoongArch: KVM: Add address alignment check in pch_pic register access
  LoongArch: KVM: Use kvm_get_vcpu_by_id() instead of kvm_get_vcpu()
  LoongArch: KVM: Fix stack protector issue in send_ipi_data()
  LoongArch: KVM: Make function kvm_own_lbt() robust
  LoongArch: Rename GCC_PLUGIN_STACKLEAK to KSTACK_ERASE
  LoongArch: Save LBT before FPU in setup_sigcontext()
  LoongArch: Optimize module load time by optimizing PLT/GOT counting
  LoongArch: Add cpuhotplug hooks to fix high cpu usage of vCPU threads
  LoongArch: Increase COMMAND_LINE_SIZE up to 4096
  LoongArch: Pass annotate-tablejump option if LTO is enabled
  objtool/LoongArch: Get table size correctly if LTO is enabled
This commit is contained in:
Linus Torvalds 2025-08-21 10:37:33 -04:00
commit 1c656b1efd
12 changed files with 110 additions and 33 deletions

View File

@ -102,7 +102,13 @@ KBUILD_CFLAGS += $(call cc-option,-mthin-add-sub) $(call cc-option,-Wa$(comma)
ifdef CONFIG_OBJTOOL
ifdef CONFIG_CC_HAS_ANNOTATE_TABLEJUMP
# The annotate-tablejump option can not be passed to LLVM backend when LTO is enabled.
# Ensure it is aware of linker with LTO, '--loongarch-annotate-tablejump' also needs to
# be passed via '-mllvm' to ld.lld.
KBUILD_CFLAGS += -mannotate-tablejump
ifdef CONFIG_LTO_CLANG
KBUILD_LDFLAGS += -mllvm --loongarch-annotate-tablejump
endif
else
KBUILD_CFLAGS += -fno-jump-tables # keep compatibility with older compilers
endif

View File

@ -58,7 +58,7 @@
.endm
.macro STACKLEAK_ERASE
#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
#ifdef CONFIG_KSTACK_ERASE
bl stackleak_erase_on_task_stack
#endif
.endm

View File

@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI_ASM_LOONGARCH_SETUP_H
#define _UAPI_ASM_LOONGARCH_SETUP_H
#define COMMAND_LINE_SIZE 4096
#endif /* _UAPI_ASM_LOONGARCH_SETUP_H */

View File

@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/moduleloader.h>
#include <linux/ftrace.h>
#include <linux/sort.h>
Elf_Addr module_emit_got_entry(struct module *mod, Elf_Shdr *sechdrs, Elf_Addr val)
{
@ -61,39 +62,38 @@ Elf_Addr module_emit_plt_entry(struct module *mod, Elf_Shdr *sechdrs, Elf_Addr v
return (Elf_Addr)&plt[nr];
}
static int is_rela_equal(const Elf_Rela *x, const Elf_Rela *y)
#define cmp_3way(a, b) ((a) < (b) ? -1 : (a) > (b))
static int compare_rela(const void *x, const void *y)
{
return x->r_info == y->r_info && x->r_addend == y->r_addend;
}
int ret;
const Elf_Rela *rela_x = x, *rela_y = y;
static bool duplicate_rela(const Elf_Rela *rela, int idx)
{
int i;
ret = cmp_3way(rela_x->r_info, rela_y->r_info);
if (ret == 0)
ret = cmp_3way(rela_x->r_addend, rela_y->r_addend);
for (i = 0; i < idx; i++) {
if (is_rela_equal(&rela[i], &rela[idx]))
return true;
}
return false;
return ret;
}
static void count_max_entries(Elf_Rela *relas, int num,
unsigned int *plts, unsigned int *gots)
{
unsigned int i, type;
unsigned int i;
sort(relas, num, sizeof(Elf_Rela), compare_rela, NULL);
for (i = 0; i < num; i++) {
type = ELF_R_TYPE(relas[i].r_info);
switch (type) {
if (i && !compare_rela(&relas[i-1], &relas[i]))
continue;
switch (ELF_R_TYPE(relas[i].r_info)) {
case R_LARCH_SOP_PUSH_PLT_PCREL:
case R_LARCH_B26:
if (!duplicate_rela(relas, i))
(*plts)++;
(*plts)++;
break;
case R_LARCH_GOT_PC_HI20:
if (!duplicate_rela(relas, i))
(*gots)++;
(*gots)++;
break;
default:
break; /* Do nothing. */

View File

@ -677,6 +677,11 @@ static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
for (i = 1; i < 32; i++)
err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
#ifdef CONFIG_CPU_HAS_LBT
if (extctx->lbt.addr)
err |= protected_save_lbt_context(extctx);
#endif
if (extctx->lasx.addr)
err |= protected_save_lasx_context(extctx);
else if (extctx->lsx.addr)
@ -684,11 +689,6 @@ static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
else if (extctx->fpu.addr)
err |= protected_save_fpu_context(extctx);
#ifdef CONFIG_CPU_HAS_LBT
if (extctx->lbt.addr)
err |= protected_save_lbt_context(extctx);
#endif
/* Set the "end" magic */
info = (struct sctx_info *)extctx->end.addr;
err |= __put_user(0, &info->magic);

View File

@ -5,6 +5,7 @@
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
*/
#include <linux/clockchips.h>
#include <linux/cpuhotplug.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/init.h>
@ -102,6 +103,23 @@ static int constant_timer_next_event(unsigned long delta, struct clock_event_dev
return 0;
}
static int arch_timer_starting(unsigned int cpu)
{
set_csr_ecfg(ECFGF_TIMER);
return 0;
}
static int arch_timer_dying(unsigned int cpu)
{
constant_set_state_shutdown(this_cpu_ptr(&constant_clockevent_device));
/* Clear Timer Interrupt */
write_csr_tintclear(CSR_TINTCLR_TI);
return 0;
}
static unsigned long get_loops_per_jiffy(void)
{
unsigned long lpj = (unsigned long)const_clock_freq;
@ -172,6 +190,10 @@ int constant_clockevent_init(void)
lpj_fine = get_loops_per_jiffy();
pr_info("Constant clock event device register\n");
cpuhp_setup_state(CPUHP_AP_LOONGARCH_ARCH_TIMER_STARTING,
"clockevents/loongarch/timer:starting",
arch_timer_starting, arch_timer_dying);
return 0;
}

View File

@ -45,7 +45,12 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level)
}
cpu = s->sw_coremap[irq];
vcpu = kvm_get_vcpu(s->kvm, cpu);
vcpu = kvm_get_vcpu_by_id(s->kvm, cpu);
if (unlikely(vcpu == NULL)) {
kvm_err("%s: invalid target cpu: %d\n", __func__, cpu);
return;
}
if (level) {
/* if not enable return false */
if (!test_bit(irq, (unsigned long *)s->enable.reg_u32))

View File

@ -99,7 +99,7 @@ static void write_mailbox(struct kvm_vcpu *vcpu, int offset, uint64_t data, int
static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data)
{
int i, idx, ret;
uint32_t val = 0, mask = 0;
uint64_t val = 0, mask = 0;
/*
* Bit 27-30 is mask for byte writing.
@ -108,7 +108,7 @@ static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data)
if ((data >> 27) & 0xf) {
/* Read the old val */
idx = srcu_read_lock(&vcpu->kvm->srcu);
ret = kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, sizeof(val), &val);
ret = kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, 4, &val);
srcu_read_unlock(&vcpu->kvm->srcu, idx);
if (unlikely(ret)) {
kvm_err("%s: : read data from addr %llx failed\n", __func__, addr);
@ -124,7 +124,7 @@ static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data)
}
val |= ((uint32_t)(data >> 32) & ~mask);
idx = srcu_read_lock(&vcpu->kvm->srcu);
ret = kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, sizeof(val), &val);
ret = kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, 4, &val);
srcu_read_unlock(&vcpu->kvm->srcu, idx);
if (unlikely(ret))
kvm_err("%s: : write data to addr %llx failed\n", __func__, addr);
@ -298,7 +298,7 @@ static int kvm_ipi_regs_access(struct kvm_device *dev,
cpu = (attr->attr >> 16) & 0x3ff;
addr = attr->attr & 0xff;
vcpu = kvm_get_vcpu(dev->kvm, cpu);
vcpu = kvm_get_vcpu_by_id(dev->kvm, cpu);
if (unlikely(vcpu == NULL)) {
kvm_err("%s: invalid target cpu: %d\n", __func__, cpu);
return -EINVAL;

View File

@ -195,6 +195,11 @@ static int kvm_pch_pic_read(struct kvm_vcpu *vcpu,
return -EINVAL;
}
if (addr & (len - 1)) {
kvm_err("%s: pch pic not aligned addr %llx len %d\n", __func__, addr, len);
return -EINVAL;
}
/* statistics of pch pic reading */
vcpu->stat.pch_pic_read_exits++;
ret = loongarch_pch_pic_read(s, addr, len, val);
@ -302,6 +307,11 @@ static int kvm_pch_pic_write(struct kvm_vcpu *vcpu,
return -EINVAL;
}
if (addr & (len - 1)) {
kvm_err("%s: pch pic not aligned addr %llx len %d\n", __func__, addr, len);
return -EINVAL;
}
/* statistics of pch pic writing */
vcpu->stat.pch_pic_write_exits++;
ret = loongarch_pch_pic_write(s, addr, len, val);

View File

@ -1283,9 +1283,11 @@ int kvm_own_lbt(struct kvm_vcpu *vcpu)
return -EINVAL;
preempt_disable();
set_csr_euen(CSR_EUEN_LBTEN);
_restore_lbt(&vcpu->arch.lbt);
vcpu->arch.aux_inuse |= KVM_LARCH_LBT;
if (!(vcpu->arch.aux_inuse & KVM_LARCH_LBT)) {
set_csr_euen(CSR_EUEN_LBTEN);
_restore_lbt(&vcpu->arch.lbt);
vcpu->arch.aux_inuse |= KVM_LARCH_LBT;
}
preempt_enable();
return 0;

View File

@ -168,6 +168,7 @@ enum cpuhp_state {
CPUHP_AP_QCOM_TIMER_STARTING,
CPUHP_AP_TEGRA_TIMER_STARTING,
CPUHP_AP_ARMADA_TIMER_STARTING,
CPUHP_AP_LOONGARCH_ARCH_TIMER_STARTING,
CPUHP_AP_MIPS_GIC_TIMER_STARTING,
CPUHP_AP_ARC_TIMER_STARTING,
CPUHP_AP_REALTEK_TIMER_STARTING,

View File

@ -27,6 +27,7 @@ static void get_rodata_table_size_by_table_annotate(struct objtool_file *file,
struct table_info *next_table;
unsigned long tmp_insn_offset;
unsigned long tmp_rodata_offset;
bool is_valid_list = false;
rsec = find_section_by_name(file->elf, ".rela.discard.tablejump_annotate");
if (!rsec)
@ -35,6 +36,12 @@ static void get_rodata_table_size_by_table_annotate(struct objtool_file *file,
INIT_LIST_HEAD(&table_list);
for_each_reloc(rsec, reloc) {
if (reloc->sym->sec->rodata)
continue;
if (strcmp(insn->sec->name, reloc->sym->sec->name))
continue;
orig_table = malloc(sizeof(struct table_info));
if (!orig_table) {
WARN("malloc failed");
@ -49,6 +56,22 @@ static void get_rodata_table_size_by_table_annotate(struct objtool_file *file,
if (reloc_idx(reloc) + 1 == sec_num_entries(rsec))
break;
if (strcmp(insn->sec->name, (reloc + 1)->sym->sec->name)) {
list_for_each_entry(orig_table, &table_list, jump_info) {
if (orig_table->insn_offset == insn->offset) {
is_valid_list = true;
break;
}
}
if (!is_valid_list) {
list_del_init(&table_list);
continue;
}
break;
}
}
list_for_each_entry(orig_table, &table_list, jump_info) {