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

Commit f384796c authored by Aneesh Kumar K.V's avatar Aneesh Kumar K.V Committed by Michael Ellerman
Browse files

powerpc/mm: Add support for handling > 512TB address in SLB miss



For addresses above 512TB we allocate additional mmu contexts. To make
it all easy, addresses above 512TB are handled with IR/DR=1 and with
stack frame setup.

The mmu_context_t is also updated to track the new extended_ids. To
support upto 4PB we need a total 8 contexts.

Signed-off-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
[mpe: Minor formatting tweaks and comment wording, switch BUG to WARN
      in get_ea_context().]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 0dea04b2
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -11,6 +11,12 @@
#define H_PUD_INDEX_SIZE  9
#define H_PGD_INDEX_SIZE  9

/*
 * Each context is 512TB. But on 4k we restrict our max TASK size to 64TB
 * Hence also limit max EA bits to 64TB.
 */
#define MAX_EA_BITS_PER_CONTEXT		46

#ifndef __ASSEMBLY__
#define H_PTE_TABLE_SIZE	(sizeof(pte_t) << H_PTE_INDEX_SIZE)
#define H_PMD_TABLE_SIZE	(sizeof(pmd_t) << H_PMD_INDEX_SIZE)
+6 −0
Original line number Diff line number Diff line
@@ -7,6 +7,12 @@
#define H_PUD_INDEX_SIZE  7
#define H_PGD_INDEX_SIZE  8

/*
 * Each context is 512TB size. SLB miss for first context/default context
 * is handled in the hotpath.
 */
#define MAX_EA_BITS_PER_CONTEXT		49

/*
 * 64k aligned address free up few of the lower bits of RPN for us
 * We steal that here. For more deatils look at pte_pfn/pfn_pte()
+32 −1
Original line number Diff line number Diff line
@@ -91,7 +91,18 @@ struct slice_mask {
};

typedef struct {
	union {
		/*
		 * We use id as the PIDR content for radix. On hash we can use
		 * more than one id. The extended ids are used when we start
		 * having address above 512TB. We allocate one extended id
		 * for each 512TB. The new id is then used with the 49 bit
		 * EA to build a new VA. We always use ESID_BITS_1T_MASK bits
		 * from EA and new context ids to build the new VAs.
		 */
		mm_context_id_t id;
		mm_context_id_t extended_id[TASK_SIZE_USER64/TASK_CONTEXT_SIZE];
	};
	u16 user_psize;		/* page size index */

	/* Number of bits in the mm_cpumask */
@@ -196,5 +207,25 @@ extern void radix_init_pseries(void);
static inline void radix_init_pseries(void) { };
#endif

static inline int get_ea_context(mm_context_t *ctx, unsigned long ea)
{
	int index = ea >> MAX_EA_BITS_PER_CONTEXT;

	if (likely(index < ARRAY_SIZE(ctx->extended_id)))
		return ctx->extended_id[index];

	/* should never happen */
	WARN_ON(1);
	return 0;
}

static inline unsigned long get_user_vsid(mm_context_t *ctx,
					  unsigned long ea, int ssize)
{
	unsigned long context = get_ea_context(ctx, ea);

	return get_vsid(context, ea, ssize);
}

#endif /* __ASSEMBLY__ */
#endif /* _ASM_POWERPC_BOOK3S_64_MMU_H_ */
+39 −0
Original line number Diff line number Diff line
@@ -60,12 +60,51 @@ extern int hash__alloc_context_id(void);
extern void hash__reserve_context_id(int id);
extern void __destroy_context(int context_id);
static inline void mmu_context_init(void) { }

static inline int alloc_extended_context(struct mm_struct *mm,
					 unsigned long ea)
{
	int context_id;

	int index = ea >> MAX_EA_BITS_PER_CONTEXT;

	context_id = hash__alloc_context_id();
	if (context_id < 0)
		return context_id;

	VM_WARN_ON(mm->context.extended_id[index]);
	mm->context.extended_id[index] = context_id;
	return context_id;
}

static inline bool need_extra_context(struct mm_struct *mm, unsigned long ea)
{
	int context_id;

	context_id = get_ea_context(&mm->context, ea);
	if (!context_id)
		return true;
	return false;
}

#else
extern void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next,
			       struct task_struct *tsk);
extern unsigned long __init_new_context(void);
extern void __destroy_context(unsigned long context_id);
extern void mmu_context_init(void);
static inline int alloc_extended_context(struct mm_struct *mm,
					 unsigned long ea)
{
	/* non book3s_64 should never find this called */
	WARN_ON(1);
	return -ENOMEM;
}

static inline bool need_extra_context(struct mm_struct *mm, unsigned long ea)
{
	return false;
}
#endif

#if defined(CONFIG_KVM_BOOK3S_HV_POSSIBLE) && defined(CONFIG_PPC_RADIX_MMU)
+6 −0
Original line number Diff line number Diff line
@@ -119,9 +119,15 @@ void release_thread(struct task_struct *);
 */
#define TASK_SIZE_USER64		TASK_SIZE_512TB
#define DEFAULT_MAP_WINDOW_USER64	TASK_SIZE_128TB
#define TASK_CONTEXT_SIZE		TASK_SIZE_512TB
#else
#define TASK_SIZE_USER64		TASK_SIZE_64TB
#define DEFAULT_MAP_WINDOW_USER64	TASK_SIZE_64TB
/*
 * We don't need to allocate extended context ids for 4K page size, because
 * we limit the max effective address on this config to 64TB.
 */
#define TASK_CONTEXT_SIZE		TASK_SIZE_64TB
#endif

/*
Loading