Commit 3964f82a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'loongarch-fixes-6.12-1' of...

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
parents c2cd8e45 73adbd92
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -26,6 +26,10 @@ struct loongson_board_info {

#define NR_WORDS DIV_ROUND_UP(NR_CPUS, BITS_PER_LONG)

/*
 * The "core" of cores_per_node and cores_per_package stands for a
 * logical core, which means in a SMT system it stands for a thread.
 */
struct loongson_system_configuration {
	int nr_cpus;
	int nr_nodes;
+1 −1
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@
#define XRANGE_SHIFT (48)

/* Valid address length */
#define XRANGE_SHADOW_SHIFT	(PGDIR_SHIFT + PAGE_SHIFT - 3)
#define XRANGE_SHADOW_SHIFT	min(cpu_vabits, VA_BITS)
/* Used for taking out the valid address */
#define XRANGE_SHADOW_MASK	GENMASK_ULL(XRANGE_SHADOW_SHIFT - 1, 0)
/* One segment whole address space size */
+1 −1
Original line number Diff line number Diff line
@@ -250,7 +250,7 @@
#define  CSR_ESTAT_IS_WIDTH		15
#define  CSR_ESTAT_IS			(_ULCAST_(0x7fff) << CSR_ESTAT_IS_SHIFT)

#define LOONGARCH_CSR_ERA		0x6	/* ERA */
#define LOONGARCH_CSR_ERA		0x6	/* Exception return address */

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

+11 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@

#define __HAVE_ARCH_PMD_ALLOC_ONE
#define __HAVE_ARCH_PUD_ALLOC_ONE
#define __HAVE_ARCH_PTE_ALLOC_ONE_KERNEL
#include <asm-generic/pgalloc.h>

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

extern pgd_t *pgd_alloc(struct mm_struct *mm);

static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
{
	pte_t *pte = __pte_alloc_one_kernel(mm);

	if (pte)
		kernel_pte_init(pte);

	return pte;
}

#define __pte_free_tlb(tlb, pte, address)			\
do {								\
	pagetable_pte_dtor(page_ptdesc(pte));			\
+7 −28
Original line number Diff line number Diff line
@@ -269,6 +269,7 @@ extern void set_pmd_at(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, pm
extern void pgd_init(void *addr);
extern void pud_init(void *addr);
extern void pmd_init(void *addr);
extern void kernel_pte_init(void *addr);

/*
 * 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)
{
	WRITE_ONCE(*ptep, pteval);

	if (pte_val(pteval) & _PAGE_GLOBAL) {
		pte_t *buddy = ptep_buddy(ptep);
		/*
		 * Make sure the buddy is global too (if it's !none,
		 * it better already be global)
		 */
		if (pte_none(ptep_get(buddy))) {
#ifdef CONFIG_SMP
			/*
			 * For SMP, multiple CPUs can race, so we need
			 * to do this atomically.
			 */
			__asm__ __volatile__(
			__AMOR "$zero, %[global], %[buddy] \n"
			: [buddy] "+ZB" (buddy->pte)
			: [global] "r" (_PAGE_GLOBAL)
			: "memory");

	if (pte_val(pteval) & _PAGE_GLOBAL)
		DBAR(0b11000); /* o_wrw = 0b11000 */
#else /* !CONFIG_SMP */
			WRITE_ONCE(*buddy, __pte(pte_val(ptep_get(buddy)) | _PAGE_GLOBAL));
#endif /* CONFIG_SMP */
		}
	}
#endif
}

static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
	/* Preserve global status for the pair */
	if (pte_val(ptep_get(ptep_buddy(ptep))) & _PAGE_GLOBAL)
		set_pte(ptep, __pte(_PAGE_GLOBAL));
	else
		set_pte(ptep, __pte(0));
	pte_t pte = ptep_get(ptep);
	pte_val(pte) &= _PAGE_GLOBAL;
	set_pte(ptep, pte);
}

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