Skip to content

Commit

Permalink
[PATCH] ppc64: Store virtual address in TLB flush batches
Browse files Browse the repository at this point in the history
This patch slightly change the TLB flush batch mecanism so that we
store the full vaddr (including vsid) when adding an entry to the
batch so that the flush part doesn't have to get to the context.

This cleans it a bit, and paves the way to future updates like
dynamic vsids.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
  • Loading branch information
Benjamin Herrenschmidt authored and Paul Mackerras committed Sep 21, 2005
1 parent 637a6ff commit 61b1a94
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 48 deletions.
5 changes: 2 additions & 3 deletions arch/ppc64/kernel/pSeries_lpar.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,8 +486,7 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
* Take a spinlock around flushes to avoid bouncing the hypervisor tlbie
* lock.
*/
void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number,
int local)
void pSeries_lpar_flush_hash_range(unsigned long number, int local)
{
int i;
unsigned long flags = 0;
Expand All @@ -498,7 +497,7 @@ void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number,
spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);

for (i = 0; i < number; i++)
flush_hash_page(context, batch->addr[i], batch->pte[i], local);
flush_hash_page(batch->vaddr[i], batch->pte[i], local);

if (lock_tlbie)
spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
Expand Down
13 changes: 3 additions & 10 deletions arch/ppc64/mm/hash_native.c
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,9 @@ static void native_hpte_clear(void)
local_irq_restore(flags);
}

static void native_flush_hash_range(unsigned long context,
unsigned long number, int local)
static void native_flush_hash_range(unsigned long number, int local)
{
unsigned long vsid, vpn, va, hash, secondary, slot, flags, avpn;
unsigned long va, vpn, hash, secondary, slot, flags, avpn;
int i, j;
hpte_t *hptep;
unsigned long hpte_v;
Expand All @@ -351,13 +350,7 @@ static void native_flush_hash_range(unsigned long context,

j = 0;
for (i = 0; i < number; i++) {
if (batch->addr[i] < KERNELBASE)
vsid = get_vsid(context, batch->addr[i]);
else
vsid = get_kernel_vsid(batch->addr[i]);

va = (vsid << 28) | (batch->addr[i] & 0x0fffffff);
batch->vaddr[j] = va;
va = batch->vaddr[j];
if (large)
vpn = va >> HPAGE_SHIFT;
else
Expand Down
21 changes: 7 additions & 14 deletions arch/ppc64/mm/hash_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,18 +355,11 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
return ret;
}

void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte,
int local)
void flush_hash_page(unsigned long va, pte_t pte, int local)
{
unsigned long vsid, vpn, va, hash, secondary, slot;
unsigned long vpn, hash, secondary, slot;
unsigned long huge = pte_huge(pte);

if (ea < KERNELBASE)
vsid = get_vsid(context, ea);
else
vsid = get_kernel_vsid(ea);

va = (vsid << 28) | (ea & 0x0fffffff);
if (huge)
vpn = va >> HPAGE_SHIFT;
else
Expand All @@ -381,17 +374,17 @@ void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte,
ppc_md.hpte_invalidate(slot, va, huge, local);
}

void flush_hash_range(unsigned long context, unsigned long number, int local)
void flush_hash_range(unsigned long number, int local)
{
if (ppc_md.flush_hash_range) {
ppc_md.flush_hash_range(context, number, local);
ppc_md.flush_hash_range(number, local);
} else {
int i;
struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
struct ppc64_tlb_batch *batch =
&__get_cpu_var(ppc64_tlb_batch);

for (i = 0; i < number; i++)
flush_hash_page(context, batch->addr[i], batch->pte[i],
local);
flush_hash_page(batch->vaddr[i], batch->pte[i], local);
}
}

Expand Down
25 changes: 12 additions & 13 deletions arch/ppc64/mm/tlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,10 @@ void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf)
void hpte_update(struct mm_struct *mm, unsigned long addr,
unsigned long pte, int wrprot)
{
int i;
unsigned long context = 0;
struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
unsigned long vsid;
int i;

if (REGION_ID(addr) == USER_REGION_ID)
context = mm->context.id;
i = batch->index;

/*
Expand All @@ -143,17 +141,19 @@ void hpte_update(struct mm_struct *mm, unsigned long addr,
* up scanning and resetting referenced bits then our batch context
* will change mid stream.
*/
if (unlikely(i != 0 && context != batch->context)) {
if (unlikely(i != 0 && mm != batch->mm)) {
flush_tlb_pending();
i = 0;
}

if (i == 0) {
batch->context = context;
if (i == 0)
batch->mm = mm;
}
if (addr < KERNELBASE) {
vsid = get_vsid(mm->context.id, addr);
WARN_ON(vsid == 0);
} else
vsid = get_kernel_vsid(addr);
batch->vaddr[i] = (vsid << 28 ) | (addr & 0x0fffffff);
batch->pte[i] = __pte(pte);
batch->addr[i] = addr;
batch->index = ++i;
if (i >= PPC64_TLB_BATCH_NR)
flush_tlb_pending();
Expand All @@ -175,10 +175,9 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
local = 1;

if (i == 1)
flush_hash_page(batch->context, batch->addr[0], batch->pte[0],
local);
flush_hash_page(batch->vaddr[0], batch->pte[0], local);
else
flush_hash_range(batch->context, i, local);
flush_hash_range(i, local);
batch->index = 0;
put_cpu();
}
Expand Down
5 changes: 2 additions & 3 deletions include/asm-ppc64/machdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ struct machdep_calls {
unsigned long vflags,
unsigned long rflags);
long (*hpte_remove)(unsigned long hpte_group);
void (*flush_hash_range)(unsigned long context,
unsigned long number,
int local);
void (*flush_hash_range)(unsigned long number, int local);

/* special for kexec, to be called in real mode, linar mapping is
* destroyed as well */
void (*hpte_clear_all)(void);
Expand Down
7 changes: 2 additions & 5 deletions include/asm-ppc64/tlbflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@
struct mm_struct;
struct ppc64_tlb_batch {
unsigned long index;
unsigned long context;
struct mm_struct *mm;
pte_t pte[PPC64_TLB_BATCH_NR];
unsigned long addr[PPC64_TLB_BATCH_NR];
unsigned long vaddr[PPC64_TLB_BATCH_NR];
};
DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
Expand All @@ -47,8 +45,7 @@ static inline void flush_tlb_pending(void)
#define flush_tlb_kernel_range(start, end) flush_tlb_pending()
#define flush_tlb_pgtables(mm, start, end) do { } while (0)

extern void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte,
int local);
void flush_hash_range(unsigned long context, unsigned long number, int local);
extern void flush_hash_page(unsigned long va, pte_t pte, int local);
void flush_hash_range(unsigned long number, int local);

#endif /* _PPC64_TLBFLUSH_H */

0 comments on commit 61b1a94

Please sign in to comment.