LoongArch fixes for v7.1-rc5

-----BEGIN PGP SIGNATURE-----
 
 iQJKBAABCAA0FiEEzOlt8mkP+tbeiYy5AoYrw/LiJnoFAmoQFmAWHGNoZW5odWFj
 YWlAa2VybmVsLm9yZwAKCRAChivD8uImevFED/9pCspo7HFPyYlEBeEoPfKvkLRr
 XyJzaVpCyqfbnfnsLyUGnu+rtQfX1hLxRqeMUjPGx0AE8M59KD9KkQ0H2ZdTVz80
 3ytI0oVBVCzmm1QdbtxRHPGd1kvJcUH/Z2hQFQhSPDoq8wiLbjj36kpGy3YQEdjb
 o7880THpa47OemgHwAKqCUOyXnsfjPj5nISimuIZg3XfFn9svsvuk3nsktYWdcJ3
 UiH9BDSVbIqHj7xzSCrvgil8fcaBHYbXNBjWezubmc0V21PKWf063XNqO9xKzkGQ
 uzcb0l0B9qImm0brxczIlDfoLc3wzOj67jrvUF5xhU4DZiNBci039RNfW8+7l1pQ
 GhrWBxf+sWuhW/vqiv65bHys4Af5P1FX2848i4ZxW+m2gfuxw5T43Mf6R1v05Acy
 0NZ3Y0zZt+rw8VpTF0I7egjshLFix5fq4mdfECKBB24fCsr8svNFuNYT8JPtqw3S
 Hk6wN5RVHy5cbc4wnq3zUQna7iWO+bE+rngnyv29BS/1nIfAhbOUqIrNrB0lvs5S
 UK6IQVmW84Zx18KvWie4tzyAXWJglCOM1V8f1QejOrNGPPZI9+RDtYw8TONFrFdz
 SFfL6fulS6X5tSCo9e8V7NzeWLIvIGEjxVP2bVeVBrY4fVvmjromm/msVqrYhj3Z
 8UYQqCuduiGQErmH3g==
 =cYtz
 -----END PGP SIGNATURE-----

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

Pull LoongArch fixes from Huacai Chen:
 "Rework KASLR to avoid initrd overlap, remove some unused code to avoid
  a build warning, fix some bugs in kprobes and KVM"

* tag 'loongarch-fixes-7.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson:
  LoongArch: KVM: Move some variable declarations to paravirt.h
  LoongArch: kprobes: Fix handling of fatal unrecoverable recursions
  LoongArch: kprobes: Use larch_insn_text_copy() to patch instructions
  LoongArch: Remove unused code to avoid build warning
  LoongArch: Avoid initrd overlap during kernel relocation
  LoongArch: Skip relocation-time KASLR if already applied
  efi/loongarch: Randomize kernel preferred address for KASLR
This commit is contained in:
Linus Torvalds 2026-05-23 09:13:00 -07:00
commit 95e6d3ba05
8 changed files with 88 additions and 15 deletions

View File

@ -30,6 +30,8 @@ static inline unsigned long efi_get_kimg_min_align(void)
return SZ_2M;
}
#define EFI_KIMG_PREFERRED_ADDRESS PHYSADDR(VMLINUX_LOAD_ADDRESS)
unsigned long efi_get_kimg_kaslr_address(void);
#define EFI_KIMG_PREFERRED_ADDRESS efi_get_kimg_kaslr_address()
#endif /* _ASM_LOONGARCH_EFI_H */

View File

@ -4,6 +4,12 @@
#ifdef CONFIG_PARAVIRT
#include <linux/jump_label.h>
DECLARE_STATIC_KEY_FALSE(virt_preempt_key);
DECLARE_STATIC_KEY_FALSE(virt_spin_lock_key);
DECLARE_PER_CPU(struct kvm_steal_time, steal_time);
int __init pv_ipi_init(void);
int __init pv_time_init(void);
int __init pv_spinlock_init(void);

View File

@ -3,12 +3,9 @@
#define _ASM_LOONGARCH_QSPINLOCK_H
#include <asm/kvm_para.h>
#include <linux/jump_label.h>
#include <asm/paravirt.h>
#ifdef CONFIG_PARAVIRT
DECLARE_STATIC_KEY_FALSE(virt_preempt_key);
DECLARE_STATIC_KEY_FALSE(virt_spin_lock_key);
DECLARE_PER_CPU(struct kvm_steal_time, steal_time);
#define virt_spin_lock virt_spin_lock

View File

@ -60,16 +60,18 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe);
/* Install breakpoint in text */
void arch_arm_kprobe(struct kprobe *p)
{
*p->addr = KPROBE_BP_INSN;
flush_insn_slot(p);
u32 insn = KPROBE_BP_INSN;
larch_insn_text_copy(p->addr, &insn, LOONGARCH_INSN_SIZE);
}
NOKPROBE_SYMBOL(arch_arm_kprobe);
/* Remove breakpoint from text */
void arch_disarm_kprobe(struct kprobe *p)
{
*p->addr = p->opcode;
flush_insn_slot(p);
u32 insn = p->opcode;
larch_insn_text_copy(p->addr, &insn, LOONGARCH_INSN_SIZE);
}
NOKPROBE_SYMBOL(arch_disarm_kprobe);
@ -184,16 +186,16 @@ static bool reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
struct kprobe_ctlblk *kcb)
{
switch (kcb->kprobe_status) {
case KPROBE_HIT_SS:
case KPROBE_HIT_SSDONE:
case KPROBE_HIT_ACTIVE:
kprobes_inc_nmissed_count(p);
setup_singlestep(p, regs, kcb, 1);
break;
case KPROBE_HIT_SS:
case KPROBE_REENTER:
pr_warn("Failed to recover from reentered kprobes.\n");
dump_kprobe(p);
WARN_ON_ONCE(1);
BUG();
break;
default:
WARN_ON(1);

View File

@ -134,11 +134,23 @@ early_param("nokaslr", nokaslr);
#define KASLR_DISABLED_MESSAGE "KASLR is disabled by %s in %s cmdline.\n"
/*
* Note: strictly-defined KASLR means the kernel's final runtime address
* has a random offset from the kernel's load address, which is implemented
* in relocate.c; broadly-defined KALSR means the kernel's final runtime
* address has a random offset from the kernel's link address (a.k.a.
* VMLINUX_LOAD_ADDRESS), which also include the efistlub implementation,
* kexec_file implementation and QEMU direct kernel boot. kaslr_disabled()
* return true only means strictly-defined KASLR is disabled.
*/
static inline __init bool kaslr_disabled(void)
{
char *str;
const char *builtin_cmdline = CONFIG_CMDLINE;
if (kaslr_offset())
return true; /* KASLR is performed during early boot. */
str = strstr(builtin_cmdline, "nokaslr");
if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) {
pr_info(KASLR_DISABLED_MESSAGE, "\'nokaslr\'", "built-in");
@ -210,14 +222,52 @@ static inline void __init *determine_relocation_address(void)
return RELOCATED_KASLR(destination);
}
static unsigned long __init determine_initrd_address(unsigned long *size)
{
unsigned long start = 0;
unsigned long key_length;
char *p, *endp, *key = "initrd=";
key_length = strlen(key);
p = strstr(boot_command_line, key);
if (!p) {
key = "initrdmem=";
key_length = strlen(key);
p = strstr(boot_command_line, key);
}
if (p == boot_command_line || (p > boot_command_line && *(p - 1) == ' ')) {
p += key_length;
start = memparse(p, &endp);
if (*endp == ',')
*size = memparse(endp + 1, NULL);
}
return start;
}
static inline int __init relocation_addr_valid(void *location_new)
{
unsigned long kernel_start, kernel_size;
unsigned long initrd_start, initrd_size = 0;
if ((unsigned long)location_new & 0x00000ffff)
return 0; /* Inappropriately aligned new location */
if ((unsigned long)location_new < (unsigned long)_end)
return 0; /* New location overlaps original kernel */
initrd_start = determine_initrd_address(&initrd_size);
if (initrd_start && initrd_size) {
kernel_start = PHYSADDR(location_new);
kernel_size = (unsigned long)_end - (unsigned long)_text;
if (kernel_start < (initrd_start + initrd_size) &&
initrd_start < (kernel_start + kernel_size))
return 0; /* initrd/initramfs overlaps kernel */
}
return 1;
}
#endif

View File

@ -123,11 +123,7 @@ void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
{
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;
struct page *page = pfn_to_page(start_pfn);
/* With altmap the first mapped page is offset from @start */
if (altmap)
page += vmem_altmap_offset(altmap);
__remove_pages(start_pfn, nr_pages, altmap);
}
#endif

View File

@ -79,6 +79,10 @@ efi_status_t efi_parse_options(char const *cmdline)
efi_noinitrd = true;
} else if (IS_ENABLED(CONFIG_X86_64) && !strcmp(param, "no5lvl")) {
efi_no5lvl = true;
} else if (IS_ENABLED(CONFIG_LOONGARCH) &&
IS_ENABLED(CONFIG_HIBERNATION) &&
!strcmp(param, "resume") && val) {
efi_nokaslr = true; /* LoongArch can't KASLR for hibernation */
} else if (IS_ENABLED(CONFIG_ARCH_HAS_MEM_ENCRYPT) &&
!strcmp(param, "mem_encrypt") && val) {
if (parse_option_str(val, "on"))

View File

@ -23,6 +23,22 @@ void efi_cache_sync_image(unsigned long image_base, unsigned long alloc_size)
asm volatile ("ibar 0" ::: "memory");
}
unsigned long efi_get_kimg_kaslr_address(void)
{
unsigned int random_offset = 0;
#ifdef CONFIG_RANDOMIZE_BASE
if (!efi_nokaslr) {
efi_get_random_bytes(sizeof(random_offset), (u8 *)&random_offset);
random_offset ^= (random_get_entropy() << 16);
random_offset &= (CONFIG_RANDOMIZE_BASE_MAX_OFFSET - 1);
random_offset = ALIGN(random_offset + SZ_64K, SZ_64K);
}
#endif
return PHYSADDR(VMLINUX_LOAD_ADDRESS) + random_offset;
}
struct exit_boot_struct {
efi_memory_desc_t *runtime_map;
int runtime_entry_count;