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

Commit 5524a27d authored by Aneesh Kumar K.V's avatar Aneesh Kumar K.V Committed by Benjamin Herrenschmidt
Browse files

powerpc/mm: Convert virtual address to vpn



This patch convert different functions to take virtual page number
instead of virtual address. Virtual page number is virtual address
shifted right by VPN_SHIFT (12) bits. This enable us to have an
address range of upto 76 bits.

Reviewed-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent dcda287a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ struct hpte_cache {
	struct hlist_node list_vpte;
	struct hlist_node list_vpte_long;
	struct rcu_head rcu_head;
	u64 host_va;
	u64 host_vpn;
	u64 pfn;
	ulong slot;
	struct kvmppc_pte pte;
+3 −3
Original line number Diff line number Diff line
@@ -34,19 +34,19 @@ struct machdep_calls {
	char		*name;
#ifdef CONFIG_PPC64
	void            (*hpte_invalidate)(unsigned long slot,
					   unsigned long va,
					   unsigned long vpn,
					   int psize, int ssize,
					   int local);
	long		(*hpte_updatepp)(unsigned long slot, 
					 unsigned long newpp, 
					 unsigned long va,
					 unsigned long vpn,
					 int psize, int ssize,
					 int local);
	void            (*hpte_updateboltedpp)(unsigned long newpp, 
					       unsigned long ea,
					       int psize, int ssize);
	long		(*hpte_insert)(unsigned long hpte_group,
				       unsigned long va,
				       unsigned long vpn,
				       unsigned long prpn,
				       unsigned long rflags,
				       unsigned long vflags,
+61 −17
Original line number Diff line number Diff line
@@ -154,9 +154,25 @@ struct mmu_psize_def
#define MMU_SEGSIZE_256M	0
#define MMU_SEGSIZE_1T		1

/*
 * encode page number shift.
 * in order to fit the 78 bit va in a 64 bit variable we shift the va by
 * 12 bits. This enable us to address upto 76 bit va.
 * For hpt hash from a va we can ignore the page size bits of va and for
 * hpte encoding we ignore up to 23 bits of va. So ignoring lower 12 bits ensure
 * we work in all cases including 4k page size.
 */
#define VPN_SHIFT	12

#ifndef __ASSEMBLY__

static inline int segment_shift(int ssize)
{
	if (ssize == MMU_SEGSIZE_256M)
		return SID_SHIFT;
	return SID_SHIFT_1T;
}

/*
 * The current system page and segment sizes
 */
@@ -180,18 +196,39 @@ extern unsigned long tce_alloc_start, tce_alloc_end;
extern int mmu_ci_restrictions;

/*
 * This function sets the AVPN and L fields of the HPTE  appropriately
 * for the page size
 * This computes the AVPN and B fields of the first dword of a HPTE,
 * for use when we want to match an existing PTE.  The bottom 7 bits
 * of the returned value are zero.
 */
static inline unsigned long hpte_encode_v(unsigned long va, int psize,
static inline unsigned long hpte_encode_avpn(unsigned long vpn, int psize,
					     int ssize)
{
	unsigned long v;
	v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
	/*
	 * The AVA field omits the low-order 23 bits of the 78 bits VA.
	 * These bits are not needed in the PTE, because the
	 * low-order b of these bits are part of the byte offset
	 * into the virtual page and, if b < 23, the high-order
	 * 23-b of these bits are always used in selecting the
	 * PTEGs to be searched
	 */
	v = (vpn >> (23 - VPN_SHIFT)) & ~(mmu_psize_defs[psize].avpnm);
	v <<= HPTE_V_AVPN_SHIFT;
	v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
	return v;
}

/*
 * This function sets the AVPN and L fields of the HPTE  appropriately
 * for the page size
 */
static inline unsigned long hpte_encode_v(unsigned long vpn,
					  int psize, int ssize)
{
	unsigned long v;
	v = hpte_encode_avpn(vpn, psize, ssize);
	if (psize != MMU_PAGE_4K)
		v |= HPTE_V_LARGE;
	v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
	return v;
}

@@ -216,30 +253,37 @@ static inline unsigned long hpte_encode_r(unsigned long pa, int psize)
}

/*
 * Build a VA given VSID, EA and segment size
 * Build a VPN_SHIFT bit shifted va given VSID, EA and segment size.
 */
static inline unsigned long hpt_va(unsigned long ea, unsigned long vsid,
				   int ssize)
static inline unsigned long hpt_vpn(unsigned long ea,
				    unsigned long vsid, int ssize)
{
	if (ssize == MMU_SEGSIZE_256M)
		return (vsid << 28) | (ea & 0xfffffffUL);
	return (vsid << 40) | (ea & 0xffffffffffUL);
	unsigned long mask;
	int s_shift = segment_shift(ssize);

	mask = (1ul << (s_shift - VPN_SHIFT)) - 1;
	return (vsid << (s_shift - VPN_SHIFT)) | ((ea >> VPN_SHIFT) & mask);
}

/*
 * This hashes a virtual address
 */

static inline unsigned long hpt_hash(unsigned long va, unsigned int shift,
				     int ssize)
static inline unsigned long hpt_hash(unsigned long vpn,
				     unsigned int shift, int ssize)
{
	int mask;
	unsigned long hash, vsid;

	/* VPN_SHIFT can be atmost 12 */
	if (ssize == MMU_SEGSIZE_256M) {
		hash = (va >> 28) ^ ((va & 0x0fffffffUL) >> shift);
		mask = (1ul << (SID_SHIFT - VPN_SHIFT)) - 1;
		hash = (vpn >> (SID_SHIFT - VPN_SHIFT)) ^
			((vpn & mask) >> (shift - VPN_SHIFT));
	} else {
		vsid = va >> 40;
		hash = vsid ^ (vsid << 25) ^ ((va & 0xffffffffffUL) >> shift);
		mask = (1ul << (SID_SHIFT_1T - VPN_SHIFT)) - 1;
		vsid = vpn >> (SID_SHIFT_1T - VPN_SHIFT);
		hash = vsid ^ (vsid << 25) ^
			((vpn & mask) >> (shift - VPN_SHIFT)) ;
	}
	return hash & 0x7fffffffffUL;
}
+10 −8
Original line number Diff line number Diff line
@@ -58,14 +58,16 @@
/* Trick: we set __end to va + 64k, which happens works for
 * a 16M page as well as we want only one iteration
 */
#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift)	    \
#define pte_iterate_hashed_subpages(rpte, psize, vpn, index, shift)	\
	do {								\
                unsigned long __end = va + PAGE_SIZE;                       \
		unsigned long __end = vpn + (1UL << (PAGE_SHIFT - VPN_SHIFT));	\
		unsigned __split = (psize == MMU_PAGE_4K ||		\
				    psize == MMU_PAGE_64K_AP);		\
		shift = mmu_psize_defs[psize].shift;			\
		for (index = 0; va < __end; index++, va += (1L << shift)) { \
		        if (!__split || __rpte_sub_valid(rpte, index)) do { \
		for (index = 0; vpn < __end; index++,			\
			     vpn += (1L << (shift - VPN_SHIFT))) {	\
			if (!__split || __rpte_sub_valid(rpte, index))	\
				do {

#define pte_iterate_hashed_end() } while(0); } } while(0)

+2 −2
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ struct ppc64_tlb_batch {
	unsigned long		index;
	struct mm_struct	*mm;
	real_pte_t		pte[PPC64_TLB_BATCH_NR];
	unsigned long		vaddr[PPC64_TLB_BATCH_NR];
	unsigned long		vpn[PPC64_TLB_BATCH_NR];
	unsigned int		psize;
	int			ssize;
};
@@ -127,7 +127,7 @@ static inline void arch_leave_lazy_mmu_mode(void)
#define arch_flush_lazy_mmu_mode()      do {} while (0)


extern void flush_hash_page(unsigned long va, real_pte_t pte, int psize,
extern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize,
			    int ssize, int local);
extern void flush_hash_range(unsigned long number, int local);

Loading