Skip to content

Commit 2e51e0a

Browse files
committed
Merge tag 'loongarch-fixes-6.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
Pull LoongArch fixes from Huacai Chen: "Fix bugs in kernel build, hibernation, memory management and KVM" * tag 'loongarch-fixes-6.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson: LoongArch: KVM: Fix GPA size issue about VM LoongArch: KVM: Reload guest CSR registers after sleep LoongArch: KVM: Add interrupt checking for AVEC LoongArch: Set hugetlb mmap base address aligned with pmd size LoongArch: Set max_pfn with the PFN of the last page LoongArch: Use polling play_dead() when resuming from hibernation LoongArch: Eliminate superfluous get_numa_distances_cnt() LoongArch: Convert unreachable() to BUG()
2 parents 2a52007 + 6bdbb73 commit 2e51e0a

File tree

9 files changed

+75
-18
lines changed

9 files changed

+75
-18
lines changed

arch/loongarch/kernel/acpi.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -249,18 +249,6 @@ static __init int setup_node(int pxm)
249249
return acpi_map_pxm_to_node(pxm);
250250
}
251251

252-
/*
253-
* Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for
254-
* I/O localities since SRAT does not list them. I/O localities are
255-
* not supported at this point.
256-
*/
257-
unsigned int numa_distance_cnt;
258-
259-
static inline unsigned int get_numa_distances_cnt(struct acpi_table_slit *slit)
260-
{
261-
return slit->locality_count;
262-
}
263-
264252
void __init numa_set_distance(int from, int to, int distance)
265253
{
266254
if ((u8)distance != distance || (from == to && distance != LOCAL_DISTANCE)) {

arch/loongarch/kernel/machine_kexec.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,14 @@ void kexec_reboot(void)
126126
/* All secondary cpus go to kexec_smp_wait */
127127
if (smp_processor_id() > 0) {
128128
relocated_kexec_smp_wait(NULL);
129-
unreachable();
129+
BUG();
130130
}
131131
#endif
132132

133133
do_kexec = (void *)reboot_code_buffer;
134134
do_kexec(efi_boot, cmdline_ptr, systable_ptr, start_addr, first_ind_entry);
135135

136-
unreachable();
136+
BUG();
137137
}
138138

139139

arch/loongarch/kernel/setup.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,9 @@ static void __init check_kernel_sections_mem(void)
387387
*/
388388
static void __init arch_mem_init(char **cmdline_p)
389389
{
390+
/* Recalculate max_low_pfn for "mem=xxx" */
391+
max_pfn = max_low_pfn = PHYS_PFN(memblock_end_of_DRAM());
392+
390393
if (usermem)
391394
pr_info("User-defined physical RAM map overwrite\n");
392395

arch/loongarch/kernel/smp.c

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/smp.h>
2020
#include <linux/threads.h>
2121
#include <linux/export.h>
22+
#include <linux/suspend.h>
2223
#include <linux/syscore_ops.h>
2324
#include <linux/time.h>
2425
#include <linux/tracepoint.h>
@@ -423,7 +424,7 @@ void loongson_cpu_die(unsigned int cpu)
423424
mb();
424425
}
425426

426-
void __noreturn arch_cpu_idle_dead(void)
427+
static void __noreturn idle_play_dead(void)
427428
{
428429
register uint64_t addr;
429430
register void (*init_fn)(void);
@@ -447,6 +448,50 @@ void __noreturn arch_cpu_idle_dead(void)
447448
BUG();
448449
}
449450

451+
#ifdef CONFIG_HIBERNATION
452+
static void __noreturn poll_play_dead(void)
453+
{
454+
register uint64_t addr;
455+
register void (*init_fn)(void);
456+
457+
idle_task_exit();
458+
__this_cpu_write(cpu_state, CPU_DEAD);
459+
460+
__smp_mb();
461+
do {
462+
__asm__ __volatile__("nop\n\t");
463+
addr = iocsr_read64(LOONGARCH_IOCSR_MBUF0);
464+
} while (addr == 0);
465+
466+
init_fn = (void *)TO_CACHE(addr);
467+
iocsr_write32(0xffffffff, LOONGARCH_IOCSR_IPI_CLEAR);
468+
469+
init_fn();
470+
BUG();
471+
}
472+
#endif
473+
474+
static void (*play_dead)(void) = idle_play_dead;
475+
476+
void __noreturn arch_cpu_idle_dead(void)
477+
{
478+
play_dead();
479+
BUG(); /* play_dead() doesn't return */
480+
}
481+
482+
#ifdef CONFIG_HIBERNATION
483+
int hibernate_resume_nonboot_cpu_disable(void)
484+
{
485+
int ret;
486+
487+
play_dead = poll_play_dead;
488+
ret = suspend_disable_secondary_cpus();
489+
play_dead = idle_play_dead;
490+
491+
return ret;
492+
}
493+
#endif
494+
450495
#endif
451496

452497
/*

arch/loongarch/kvm/exit.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,12 @@ static int kvm_handle_rdwr_fault(struct kvm_vcpu *vcpu, bool write)
669669
struct kvm_run *run = vcpu->run;
670670
unsigned long badv = vcpu->arch.badv;
671671

672+
/* Inject ADE exception if exceed max GPA size */
673+
if (unlikely(badv >= vcpu->kvm->arch.gpa_size)) {
674+
kvm_queue_exception(vcpu, EXCCODE_ADE, EXSUBCODE_ADEM);
675+
return RESUME_GUEST;
676+
}
677+
672678
ret = kvm_handle_mm_fault(vcpu, badv, write);
673679
if (ret) {
674680
/* Treat as MMIO */

arch/loongarch/kvm/main.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,13 @@ int kvm_arch_enable_virtualization_cpu(void)
317317
kvm_debug("GCFG:%lx GSTAT:%lx GINTC:%lx GTLBC:%lx",
318318
read_csr_gcfg(), read_csr_gstat(), read_csr_gintc(), read_csr_gtlbc());
319319

320+
/*
321+
* HW Guest CSR registers are lost after CPU suspend and resume.
322+
* Clear last_vcpu so that Guest CSR registers forced to reload
323+
* from vCPU SW state.
324+
*/
325+
this_cpu_ptr(vmcs)->last_vcpu = NULL;
326+
320327
return 0;
321328
}
322329

arch/loongarch/kvm/vcpu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ static int kvm_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
311311
{
312312
int ret = RESUME_GUEST;
313313
unsigned long estat = vcpu->arch.host_estat;
314-
u32 intr = estat & 0x1fff; /* Ignore NMI */
314+
u32 intr = estat & CSR_ESTAT_IS;
315315
u32 ecode = (estat & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT;
316316

317317
vcpu->mode = OUTSIDE_GUEST_MODE;

arch/loongarch/kvm/vm.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
4848
if (kvm_pvtime_supported())
4949
kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME);
5050

51-
kvm->arch.gpa_size = BIT(cpu_vabits - 1);
51+
/*
52+
* cpu_vabits means user address space only (a half of total).
53+
* GPA size of VM is the same with the size of user address space.
54+
*/
55+
kvm->arch.gpa_size = BIT(cpu_vabits);
5256
kvm->arch.root_level = CONFIG_PGTABLE_LEVELS - 1;
5357
kvm->arch.invalid_ptes[0] = 0;
5458
kvm->arch.invalid_ptes[1] = (unsigned long)invalid_pte_table;

arch/loongarch/mm/mmap.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
44
*/
55
#include <linux/export.h>
6+
#include <linux/hugetlb.h>
67
#include <linux/io.h>
78
#include <linux/kfence.h>
89
#include <linux/memblock.h>
@@ -63,8 +64,11 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
6364
}
6465

6566
info.length = len;
66-
info.align_mask = do_color_align ? (PAGE_MASK & SHM_ALIGN_MASK) : 0;
6767
info.align_offset = pgoff << PAGE_SHIFT;
68+
if (filp && is_file_hugepages(filp))
69+
info.align_mask = huge_page_mask_align(filp);
70+
else
71+
info.align_mask = do_color_align ? (PAGE_MASK & SHM_ALIGN_MASK) : 0;
6872

6973
if (dir == DOWN) {
7074
info.flags = VM_UNMAPPED_AREA_TOPDOWN;

0 commit comments

Comments
 (0)