Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 28efc35f authored by Scott Wood's avatar Scott Wood
Browse files

powerpc/e6500: TLB miss handler with hardware tablewalk support



There are a few things that make the existing hw tablewalk handlers
unsuitable for e6500:

 - Indirect entries go in TLB1 (though the resulting direct entries go in
   TLB0).

 - It has threads, but no "tlbsrx." -- so we need a spinlock and
   a normal "tlbsx".  Because we need this lock, hardware tablewalk
   is mandatory on e6500 unless we want to add spinlock+tlbsx to
   the normal bolted TLB miss handler.

 - TLB1 has no HES (nor next-victim hint) so we need software round robin
   (TODO: integrate this round robin data with hugetlb/KVM)

 - The existing tablewalk handlers map half of a page table at a time,
   because IBM hardware has a fixed 1MiB indirect page size.  e6500
   has variable size indirect entries, with a minimum of 2MiB.
   So we can't do the half-page indirect mapping, and even if we
   could it would be less efficient than mapping the full page.

 - Like on e5500, the linear mapping is bolted, so we don't need the
   overhead of supporting nested tlb misses.

Note that hardware tablewalk does not work in rev1 of e6500.
We do not expect to support e6500 rev1 in mainline Linux.

Signed-off-by: default avatarScott Wood <scottwood@freescale.com>
Cc: Mihai Caraman <mihai.caraman@freescale.com>
parent 47ce8af4
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -286,8 +286,21 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
extern int mmu_linear_psize;
extern int mmu_vmemmap_psize;

struct tlb_core_data {
	/* For software way selection, as on Freescale TLB1 */
	u8 esel_next, esel_max, esel_first;

	/* Per-core spinlock for e6500 TLB handlers (no tlbsrx.) */
	u8 lock;
};

#ifdef CONFIG_PPC64
extern unsigned long linear_map_top;
extern int book3e_htw_mode;

#define PPC_HTW_NONE	0
#define PPC_HTW_IBM	1
#define PPC_HTW_E6500	2

/*
 * 64-bit booke platforms don't load the tlb in the tlb miss handler code.
+11 −10
Original line number Diff line number Diff line
@@ -180,16 +180,17 @@ static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
#define MMU_PAGE_64K_AP	3	/* "Admixed pages" (hash64 only) */
#define MMU_PAGE_256K	4
#define MMU_PAGE_1M	5
#define MMU_PAGE_4M	6
#define MMU_PAGE_8M	7
#define MMU_PAGE_16M	8
#define MMU_PAGE_64M	9
#define MMU_PAGE_256M	10
#define MMU_PAGE_1G	11
#define MMU_PAGE_16G	12
#define MMU_PAGE_64G	13

#define MMU_PAGE_COUNT	14
#define MMU_PAGE_2M	6
#define MMU_PAGE_4M	7
#define MMU_PAGE_8M	8
#define MMU_PAGE_16M	9
#define MMU_PAGE_64M	10
#define MMU_PAGE_256M	11
#define MMU_PAGE_1G	12
#define MMU_PAGE_16G	13
#define MMU_PAGE_64G	14

#define MMU_PAGE_COUNT	15

#if defined(CONFIG_PPC_STD_MMU_64)
/* 64-bit classic hash table MMU */
+6 −0
Original line number Diff line number Diff line
@@ -113,6 +113,10 @@ struct paca_struct {
	/* Keep pgd in the same cacheline as the start of extlb */
	pgd_t *pgd __attribute__((aligned(0x80))); /* Current PGD */
	pgd_t *kernel_pgd;		/* Kernel PGD */

	/* Shared by all threads of a core -- points to tcd of first thread */
	struct tlb_core_data *tcd_ptr;

	/* We can have up to 3 levels of reentrancy in the TLB miss handler */
	u64 extlb[3][EX_TLB_SIZE / sizeof(u64)];
	u64 exmc[8];		/* used for machine checks */
@@ -123,6 +127,8 @@ struct paca_struct {
	void *mc_kstack;
	void *crit_kstack;
	void *dbg_kstack;

	struct tlb_core_data tcd;
#endif /* CONFIG_PPC_BOOK3E */

	mm_context_t context;
+9 −0
Original line number Diff line number Diff line
@@ -203,6 +203,15 @@ int main(void)
	DEFINE(PACA_MC_STACK, offsetof(struct paca_struct, mc_kstack));
	DEFINE(PACA_CRIT_STACK, offsetof(struct paca_struct, crit_kstack));
	DEFINE(PACA_DBG_STACK, offsetof(struct paca_struct, dbg_kstack));
	DEFINE(PACA_TCD_PTR, offsetof(struct paca_struct, tcd_ptr));

	DEFINE(TCD_ESEL_NEXT,
		offsetof(struct tlb_core_data, esel_next));
	DEFINE(TCD_ESEL_MAX,
		offsetof(struct tlb_core_data, esel_max));
	DEFINE(TCD_ESEL_FIRST,
		offsetof(struct tlb_core_data, esel_first));
	DEFINE(TCD_LOCK, offsetof(struct tlb_core_data, lock));
#endif /* CONFIG_PPC_BOOK3E */

#ifdef CONFIG_PPC_STD_MMU_64
+5 −0
Original line number Diff line number Diff line
@@ -160,6 +160,11 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
#ifdef CONFIG_PPC_STD_MMU_64
	new_paca->slb_shadow_ptr = init_slb_shadow(cpu);
#endif /* CONFIG_PPC_STD_MMU_64 */

#ifdef CONFIG_PPC_BOOK3E
	/* For now -- if we have threads this will be adjusted later */
	new_paca->tcd_ptr = &new_paca->tcd;
#endif
}

/* Put the paca pointer into r13 and SPRG_PACA */
Loading