Skip to content

Commit

Permalink
powerpc/mm: Convert virtual address to vpn
Browse files Browse the repository at this point in the history
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: Paul Mackerras <paulus@samba.org>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
  • Loading branch information
Aneesh Kumar K.V authored and Benjamin Herrenschmidt committed Sep 17, 2012
1 parent dcda287 commit 5524a27
Show file tree
Hide file tree
Showing 16 changed files with 324 additions and 240 deletions.
2 changes: 1 addition & 1 deletion arch/powerpc/include/asm/kvm_book3s.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions arch/powerpc/include/asm/machdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
78 changes: 61 additions & 17 deletions arch/powerpc/include/asm/mmu-hash64.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand All @@ -179,19 +195,40 @@ extern unsigned long tce_alloc_start, tce_alloc_end;
*/
extern int mmu_ci_restrictions;

/*
* 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_avpn(unsigned long vpn, int psize,
int ssize)
{
unsigned long v;
/*
* 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 va, int psize,
int ssize)
static inline unsigned long hpte_encode_v(unsigned long vpn,
int psize, int ssize)
{
unsigned long v;
v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
v <<= HPTE_V_AVPN_SHIFT;
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;
}

Expand All @@ -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;
}
Expand Down
18 changes: 10 additions & 8 deletions arch/powerpc/include/asm/pte-hash64-64k.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
do { \
unsigned long __end = va + PAGE_SIZE; \
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 { \
#define pte_iterate_hashed_subpages(rpte, psize, vpn, index, shift) \
do { \
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; 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)

Expand Down
4 changes: 2 additions & 2 deletions arch/powerpc/include/asm/tlbflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down Expand Up @@ -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);

Expand Down
8 changes: 4 additions & 4 deletions arch/powerpc/kvm/book3s_32_mmu_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ extern char etext[];
int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
{
pfn_t hpaddr;
u64 va;
u64 vpn;
u64 vsid;
struct kvmppc_sid_map *map;
volatile u32 *pteg;
Expand Down Expand Up @@ -173,7 +173,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
BUG_ON(!map);

vsid = map->host_vsid;
va = (vsid << SID_SHIFT) | (eaddr & ~ESID_MASK);
vpn = (vsid << (SID_SHIFT - VPN_SHIFT)) | ((eaddr & ~ESID_MASK) >> VPN_SHIFT)

next_pteg:
if (rr == 16) {
Expand Down Expand Up @@ -244,11 +244,11 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
dprintk_mmu("KVM: %c%c Map 0x%llx: [%lx] 0x%llx (0x%llx) -> %lx\n",
orig_pte->may_write ? 'w' : '-',
orig_pte->may_execute ? 'x' : '-',
orig_pte->eaddr, (ulong)pteg, va,
orig_pte->eaddr, (ulong)pteg, vpn,
orig_pte->vpage, hpaddr);

pte->slot = (ulong)&pteg[rr];
pte->host_va = va;
pte->host_vpn = vpn;
pte->pte = *orig_pte;
pte->pfn = hpaddr >> PAGE_SHIFT;

Expand Down
17 changes: 10 additions & 7 deletions arch/powerpc/kvm/book3s_64_mmu_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
{
ppc_md.hpte_invalidate(pte->slot, pte->host_va,
ppc_md.hpte_invalidate(pte->slot, pte->host_vpn,
MMU_PAGE_4K, MMU_SEGSIZE_256M,
false);
}
Expand Down Expand Up @@ -80,8 +80,9 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)

int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
{
unsigned long vpn;
pfn_t hpaddr;
ulong hash, hpteg, va;
ulong hash, hpteg;
u64 vsid;
int ret;
int rflags = 0x192;
Expand Down Expand Up @@ -117,7 +118,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
}

vsid = map->host_vsid;
va = hpt_va(orig_pte->eaddr, vsid, MMU_SEGSIZE_256M);
vpn = hpt_vpn(orig_pte->eaddr, vsid, MMU_SEGSIZE_256M);

if (!orig_pte->may_write)
rflags |= HPTE_R_PP;
Expand All @@ -129,7 +130,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
else
kvmppc_mmu_flush_icache(hpaddr >> PAGE_SHIFT);

hash = hpt_hash(va, PTE_SIZE, MMU_SEGSIZE_256M);
hash = hpt_hash(vpn, PTE_SIZE, MMU_SEGSIZE_256M);

map_again:
hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
Expand All @@ -141,7 +142,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
goto out;
}

ret = ppc_md.hpte_insert(hpteg, va, hpaddr, rflags, vflags, MMU_PAGE_4K, MMU_SEGSIZE_256M);
ret = ppc_md.hpte_insert(hpteg, vpn, hpaddr, rflags, vflags,
MMU_PAGE_4K, MMU_SEGSIZE_256M);

if (ret < 0) {
/* If we couldn't map a primary PTE, try a secondary */
Expand All @@ -152,7 +154,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
} else {
struct hpte_cache *pte = kvmppc_mmu_hpte_cache_next(vcpu);

trace_kvm_book3s_64_mmu_map(rflags, hpteg, va, hpaddr, orig_pte);
trace_kvm_book3s_64_mmu_map(rflags, hpteg,
vpn, hpaddr, orig_pte);

/* The ppc_md code may give us a secondary entry even though we
asked for a primary. Fix up. */
Expand All @@ -162,7 +165,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
}

pte->slot = hpteg + (ret & 7);
pte->host_va = va;
pte->host_vpn = vpn;
pte->pte = *orig_pte;
pte->pfn = hpaddr >> PAGE_SHIFT;

Expand Down
14 changes: 7 additions & 7 deletions arch/powerpc/kvm/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ TRACE_EVENT(kvm_book3s_mmu_map,
TP_ARGS(pte),

TP_STRUCT__entry(
__field( u64, host_va )
__field( u64, host_vpn )
__field( u64, pfn )
__field( ulong, eaddr )
__field( u64, vpage )
Expand All @@ -198,7 +198,7 @@ TRACE_EVENT(kvm_book3s_mmu_map,
),

TP_fast_assign(
__entry->host_va = pte->host_va;
__entry->host_vpn = pte->host_vpn;
__entry->pfn = pte->pfn;
__entry->eaddr = pte->pte.eaddr;
__entry->vpage = pte->pte.vpage;
Expand All @@ -208,8 +208,8 @@ TRACE_EVENT(kvm_book3s_mmu_map,
(pte->pte.may_execute ? 0x1 : 0);
),

TP_printk("Map: hva=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]",
__entry->host_va, __entry->pfn, __entry->eaddr,
TP_printk("Map: hvpn=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]",
__entry->host_vpn, __entry->pfn, __entry->eaddr,
__entry->vpage, __entry->raddr, __entry->flags)
);

Expand All @@ -218,7 +218,7 @@ TRACE_EVENT(kvm_book3s_mmu_invalidate,
TP_ARGS(pte),

TP_STRUCT__entry(
__field( u64, host_va )
__field( u64, host_vpn )
__field( u64, pfn )
__field( ulong, eaddr )
__field( u64, vpage )
Expand All @@ -227,7 +227,7 @@ TRACE_EVENT(kvm_book3s_mmu_invalidate,
),

TP_fast_assign(
__entry->host_va = pte->host_va;
__entry->host_vpn = pte->host_vpn;
__entry->pfn = pte->pfn;
__entry->eaddr = pte->pte.eaddr;
__entry->vpage = pte->pte.vpage;
Expand All @@ -238,7 +238,7 @@ TRACE_EVENT(kvm_book3s_mmu_invalidate,
),

TP_printk("Flush: hva=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]",
__entry->host_va, __entry->pfn, __entry->eaddr,
__entry->host_vpn, __entry->pfn, __entry->eaddr,
__entry->vpage, __entry->raddr, __entry->flags)
);

Expand Down
Loading

0 comments on commit 5524a27

Please sign in to comment.