Skip to content

Commit 3964f82

Browse files
committed
Merge tag 'loongarch-fixes-6.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
Pull LoongArch fixes from Huacai Chen: "Get correct cores_per_package for SMT systems, enable IRQ if do_ale() triggered in irq-enabled context, and fix some bugs about vDSO, memory managenent, hrtimer in KVM, etc" * tag 'loongarch-fixes-6.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson: LoongArch: KVM: Mark hrtimer to expire in hard interrupt context LoongArch: Make KASAN usable for variable cpu_vabits LoongArch: Set initial pte entry with PAGE_GLOBAL for kernel space LoongArch: Don't crash in stack_top() for tasks without vDSO LoongArch: Set correct size for vDSO code mapping LoongArch: Enable IRQ if do_ale() triggered in irq-enabled context LoongArch: Get correct cores_per_package for SMT systems LoongArch: Use "Exception return address" to comment ERA
2 parents c2cd8e4 + 73adbd9 commit 3964f82

File tree

16 files changed

+85
-48
lines changed

16 files changed

+85
-48
lines changed

arch/loongarch/include/asm/bootinfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ struct loongson_board_info {
2626

2727
#define NR_WORDS DIV_ROUND_UP(NR_CPUS, BITS_PER_LONG)
2828

29+
/*
30+
* The "core" of cores_per_node and cores_per_package stands for a
31+
* logical core, which means in a SMT system it stands for a thread.
32+
*/
2933
struct loongson_system_configuration {
3034
int nr_cpus;
3135
int nr_nodes;

arch/loongarch/include/asm/kasan.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#define XRANGE_SHIFT (48)
1717

1818
/* Valid address length */
19-
#define XRANGE_SHADOW_SHIFT (PGDIR_SHIFT + PAGE_SHIFT - 3)
19+
#define XRANGE_SHADOW_SHIFT min(cpu_vabits, VA_BITS)
2020
/* Used for taking out the valid address */
2121
#define XRANGE_SHADOW_MASK GENMASK_ULL(XRANGE_SHADOW_SHIFT - 1, 0)
2222
/* One segment whole address space size */

arch/loongarch/include/asm/loongarch.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@
250250
#define CSR_ESTAT_IS_WIDTH 15
251251
#define CSR_ESTAT_IS (_ULCAST_(0x7fff) << CSR_ESTAT_IS_SHIFT)
252252

253-
#define LOONGARCH_CSR_ERA 0x6 /* ERA */
253+
#define LOONGARCH_CSR_ERA 0x6 /* Exception return address */
254254

255255
#define LOONGARCH_CSR_BADV 0x7 /* Bad virtual address */
256256

arch/loongarch/include/asm/pgalloc.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#define __HAVE_ARCH_PMD_ALLOC_ONE
1212
#define __HAVE_ARCH_PUD_ALLOC_ONE
13+
#define __HAVE_ARCH_PTE_ALLOC_ONE_KERNEL
1314
#include <asm-generic/pgalloc.h>
1415

1516
static inline void pmd_populate_kernel(struct mm_struct *mm,
@@ -44,6 +45,16 @@ extern void pagetable_init(void);
4445

4546
extern pgd_t *pgd_alloc(struct mm_struct *mm);
4647

48+
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
49+
{
50+
pte_t *pte = __pte_alloc_one_kernel(mm);
51+
52+
if (pte)
53+
kernel_pte_init(pte);
54+
55+
return pte;
56+
}
57+
4758
#define __pte_free_tlb(tlb, pte, address) \
4859
do { \
4960
pagetable_pte_dtor(page_ptdesc(pte)); \

arch/loongarch/include/asm/pgtable.h

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ extern void set_pmd_at(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, pm
269269
extern void pgd_init(void *addr);
270270
extern void pud_init(void *addr);
271271
extern void pmd_init(void *addr);
272+
extern void kernel_pte_init(void *addr);
272273

273274
/*
274275
* Encode/decode swap entries and swap PTEs. Swap PTEs are all PTEs that
@@ -325,39 +326,17 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
325326
{
326327
WRITE_ONCE(*ptep, pteval);
327328

328-
if (pte_val(pteval) & _PAGE_GLOBAL) {
329-
pte_t *buddy = ptep_buddy(ptep);
330-
/*
331-
* Make sure the buddy is global too (if it's !none,
332-
* it better already be global)
333-
*/
334-
if (pte_none(ptep_get(buddy))) {
335329
#ifdef CONFIG_SMP
336-
/*
337-
* For SMP, multiple CPUs can race, so we need
338-
* to do this atomically.
339-
*/
340-
__asm__ __volatile__(
341-
__AMOR "$zero, %[global], %[buddy] \n"
342-
: [buddy] "+ZB" (buddy->pte)
343-
: [global] "r" (_PAGE_GLOBAL)
344-
: "memory");
345-
346-
DBAR(0b11000); /* o_wrw = 0b11000 */
347-
#else /* !CONFIG_SMP */
348-
WRITE_ONCE(*buddy, __pte(pte_val(ptep_get(buddy)) | _PAGE_GLOBAL));
349-
#endif /* CONFIG_SMP */
350-
}
351-
}
330+
if (pte_val(pteval) & _PAGE_GLOBAL)
331+
DBAR(0b11000); /* o_wrw = 0b11000 */
332+
#endif
352333
}
353334

354335
static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
355336
{
356-
/* Preserve global status for the pair */
357-
if (pte_val(ptep_get(ptep_buddy(ptep))) & _PAGE_GLOBAL)
358-
set_pte(ptep, __pte(_PAGE_GLOBAL));
359-
else
360-
set_pte(ptep, __pte(0));
337+
pte_t pte = ptep_get(ptep);
338+
pte_val(pte) &= _PAGE_GLOBAL;
339+
set_pte(ptep, pte);
361340
}
362341

363342
#define PGD_T_LOG2 (__builtin_ffs(sizeof(pgd_t)) - 1)

arch/loongarch/kernel/process.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -293,13 +293,15 @@ unsigned long stack_top(void)
293293
{
294294
unsigned long top = TASK_SIZE & PAGE_MASK;
295295

296-
/* Space for the VDSO & data page */
297-
top -= PAGE_ALIGN(current->thread.vdso->size);
298-
top -= VVAR_SIZE;
299-
300-
/* Space to randomize the VDSO base */
301-
if (current->flags & PF_RANDOMIZE)
302-
top -= VDSO_RANDOMIZE_SIZE;
296+
if (current->thread.vdso) {
297+
/* Space for the VDSO & data page */
298+
top -= PAGE_ALIGN(current->thread.vdso->size);
299+
top -= VVAR_SIZE;
300+
301+
/* Space to randomize the VDSO base */
302+
if (current->flags & PF_RANDOMIZE)
303+
top -= VDSO_RANDOMIZE_SIZE;
304+
}
303305

304306
return top;
305307
}

arch/loongarch/kernel/setup.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#define SMBIOS_FREQHIGH_OFFSET 0x17
5656
#define SMBIOS_FREQLOW_MASK 0xFF
5757
#define SMBIOS_CORE_PACKAGE_OFFSET 0x23
58+
#define SMBIOS_THREAD_PACKAGE_OFFSET 0x25
5859
#define LOONGSON_EFI_ENABLE (1 << 3)
5960

6061
unsigned long fw_arg0, fw_arg1, fw_arg2;
@@ -125,7 +126,7 @@ static void __init parse_cpu_table(const struct dmi_header *dm)
125126
cpu_clock_freq = freq_temp * 1000000;
126127

127128
loongson_sysconf.cpuname = (void *)dmi_string_parse(dm, dmi_data[16]);
128-
loongson_sysconf.cores_per_package = *(dmi_data + SMBIOS_CORE_PACKAGE_OFFSET);
129+
loongson_sysconf.cores_per_package = *(dmi_data + SMBIOS_THREAD_PACKAGE_OFFSET);
129130

130131
pr_info("CpuClock = %llu\n", cpu_clock_freq);
131132
}

arch/loongarch/kernel/traps.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,9 @@ asmlinkage void noinstr do_ale(struct pt_regs *regs)
555555
#else
556556
unsigned int *pc;
557557

558+
if (regs->csr_prmd & CSR_PRMD_PIE)
559+
local_irq_enable();
560+
558561
perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, regs->csr_badvaddr);
559562

560563
/*
@@ -579,6 +582,8 @@ asmlinkage void noinstr do_ale(struct pt_regs *regs)
579582
die_if_kernel("Kernel ale access", regs);
580583
force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)regs->csr_badvaddr);
581584
out:
585+
if (regs->csr_prmd & CSR_PRMD_PIE)
586+
local_irq_disable();
582587
#endif
583588
irqentry_exit(regs, state);
584589
}

arch/loongarch/kernel/vdso.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ static union {
3434
struct loongarch_vdso_data vdata;
3535
} loongarch_vdso_data __page_aligned_data;
3636

37-
static struct page *vdso_pages[] = { NULL };
3837
struct vdso_data *vdso_data = generic_vdso_data.data;
3938
struct vdso_pcpu_data *vdso_pdata = loongarch_vdso_data.vdata.pdata;
4039
struct vdso_rng_data *vdso_rng_data = &loongarch_vdso_data.vdata.rng_data;
@@ -85,10 +84,8 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
8584

8685
struct loongarch_vdso_info vdso_info = {
8786
.vdso = vdso_start,
88-
.size = PAGE_SIZE,
8987
.code_mapping = {
9088
.name = "[vdso]",
91-
.pages = vdso_pages,
9289
.mremap = vdso_mremap,
9390
},
9491
.data_mapping = {
@@ -103,11 +100,14 @@ static int __init init_vdso(void)
103100
unsigned long i, cpu, pfn;
104101

105102
BUG_ON(!PAGE_ALIGNED(vdso_info.vdso));
106-
BUG_ON(!PAGE_ALIGNED(vdso_info.size));
107103

108104
for_each_possible_cpu(cpu)
109105
vdso_pdata[cpu].node = cpu_to_node(cpu);
110106

107+
vdso_info.size = PAGE_ALIGN(vdso_end - vdso_start);
108+
vdso_info.code_mapping.pages =
109+
kcalloc(vdso_info.size / PAGE_SIZE, sizeof(struct page *), GFP_KERNEL);
110+
111111
pfn = __phys_to_pfn(__pa_symbol(vdso_info.vdso));
112112
for (i = 0; i < vdso_info.size / PAGE_SIZE; i++)
113113
vdso_info.code_mapping.pages[i] = pfn_to_page(pfn + i);

arch/loongarch/kvm/timer.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,11 @@ static void _kvm_save_timer(struct kvm_vcpu *vcpu)
161161
if (kvm_vcpu_is_blocking(vcpu)) {
162162

163163
/*
164-
* HRTIMER_MODE_PINNED is suggested since vcpu may run in
165-
* the same physical cpu in next time
164+
* HRTIMER_MODE_PINNED_HARD is suggested since vcpu may run in
165+
* the same physical cpu in next time, and the timer should run
166+
* in hardirq context even in the PREEMPT_RT case.
166167
*/
167-
hrtimer_start(&vcpu->arch.swtimer, expire, HRTIMER_MODE_ABS_PINNED);
168+
hrtimer_start(&vcpu->arch.swtimer, expire, HRTIMER_MODE_ABS_PINNED_HARD);
168169
}
169170
}
170171

arch/loongarch/kvm/vcpu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1457,7 +1457,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
14571457
vcpu->arch.vpid = 0;
14581458
vcpu->arch.flush_gpa = INVALID_GPA;
14591459

1460-
hrtimer_init(&vcpu->arch.swtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
1460+
hrtimer_init(&vcpu->arch.swtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED_HARD);
14611461
vcpu->arch.swtimer.function = kvm_swtimer_wakeup;
14621462

14631463
vcpu->arch.handle_exit = kvm_handle_exit;

arch/loongarch/mm/init.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,9 @@ pte_t * __init populate_kernel_pte(unsigned long addr)
201201
pte = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
202202
if (!pte)
203203
panic("%s: Failed to allocate memory\n", __func__);
204+
204205
pmd_populate_kernel(&init_mm, pmd, pte);
206+
kernel_pte_init(pte);
205207
}
206208

207209
return pte_offset_kernel(pmd, addr);

arch/loongarch/mm/pgtable.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,26 @@ void pud_init(void *addr)
116116
EXPORT_SYMBOL_GPL(pud_init);
117117
#endif
118118

119+
void kernel_pte_init(void *addr)
120+
{
121+
unsigned long *p, *end;
122+
123+
p = (unsigned long *)addr;
124+
end = p + PTRS_PER_PTE;
125+
126+
do {
127+
p[0] = _PAGE_GLOBAL;
128+
p[1] = _PAGE_GLOBAL;
129+
p[2] = _PAGE_GLOBAL;
130+
p[3] = _PAGE_GLOBAL;
131+
p[4] = _PAGE_GLOBAL;
132+
p += 8;
133+
p[-3] = _PAGE_GLOBAL;
134+
p[-2] = _PAGE_GLOBAL;
135+
p[-1] = _PAGE_GLOBAL;
136+
} while (p != end);
137+
}
138+
119139
pmd_t mk_pmd(struct page *page, pgprot_t prot)
120140
{
121141
pmd_t pmd;

include/linux/mm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3818,8 +3818,9 @@ void *sparse_buffer_alloc(unsigned long size);
38183818
struct page * __populate_section_memmap(unsigned long pfn,
38193819
unsigned long nr_pages, int nid, struct vmem_altmap *altmap,
38203820
struct dev_pagemap *pgmap);
3821-
void pmd_init(void *addr);
38223821
void pud_init(void *addr);
3822+
void pmd_init(void *addr);
3823+
void kernel_pte_init(void *addr);
38233824
pgd_t *vmemmap_pgd_populate(unsigned long addr, int node);
38243825
p4d_t *vmemmap_p4d_populate(pgd_t *pgd, unsigned long addr, int node);
38253826
pud_t *vmemmap_pud_populate(p4d_t *p4d, unsigned long addr, int node);

mm/kasan/init.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ static void __ref zero_pte_populate(pmd_t *pmd, unsigned long addr,
106106
}
107107
}
108108

109+
void __weak __meminit kernel_pte_init(void *addr)
110+
{
111+
}
112+
109113
static int __ref zero_pmd_populate(pud_t *pud, unsigned long addr,
110114
unsigned long end)
111115
{
@@ -126,8 +130,10 @@ static int __ref zero_pmd_populate(pud_t *pud, unsigned long addr,
126130

127131
if (slab_is_available())
128132
p = pte_alloc_one_kernel(&init_mm);
129-
else
133+
else {
130134
p = early_alloc(PAGE_SIZE, NUMA_NO_NODE);
135+
kernel_pte_init(p);
136+
}
131137
if (!p)
132138
return -ENOMEM;
133139

mm/sparse-vmemmap.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,13 +184,18 @@ static void * __meminit vmemmap_alloc_block_zero(unsigned long size, int node)
184184
return p;
185185
}
186186

187+
void __weak __meminit kernel_pte_init(void *addr)
188+
{
189+
}
190+
187191
pmd_t * __meminit vmemmap_pmd_populate(pud_t *pud, unsigned long addr, int node)
188192
{
189193
pmd_t *pmd = pmd_offset(pud, addr);
190194
if (pmd_none(*pmd)) {
191195
void *p = vmemmap_alloc_block_zero(PAGE_SIZE, node);
192196
if (!p)
193197
return NULL;
198+
kernel_pte_init(p);
194199
pmd_populate_kernel(&init_mm, pmd, p);
195200
}
196201
return pmd;

0 commit comments

Comments
 (0)