Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 21359
b: refs/heads/master
c: 517af33
h: refs/heads/master
i:
  21357: 4028773
  21355: f1a65f8
  21351: 6eb16b7
  21343: 0d269c4
v: v3
  • Loading branch information
David S. Miller committed Mar 20, 2006
1 parent 314ec2f commit 76f62c1
Show file tree
Hide file tree
Showing 10 changed files with 235 additions and 54 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b0fd4e49aea8a460afab7bc67cd618e2d19291d4
refs/heads/master: 517af33237ecfc3c8a93b335365fa61e741ceca4
2 changes: 1 addition & 1 deletion trunk/arch/sparc64/kernel/dtlb_miss.S
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
srlx %g6, 48, %g5 ! Get context
brz,pn %g5, kvmap_dtlb ! Context 0 processing
nop ! Delay slot (fill me)
ldda [%g1] ASI_NUCLEUS_QUAD_LDD, %g4 ! Load TSB entry
TSB_LOAD_QUAD(%g1, %g4) ! Load TSB entry
nop ! Push branch to next I$ line
cmp %g4, %g6 ! Compare TAG

Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/sparc64/kernel/itlb_miss.S
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
srlx %g6, 48, %g5 ! Get context
brz,pn %g5, kvmap_itlb ! Context 0 processing
nop ! Delay slot (fill me)
ldda [%g1] ASI_NUCLEUS_QUAD_LDD, %g4 ! Load TSB entry
TSB_LOAD_QUAD(%g1, %g4) ! Load TSB entry
cmp %g4, %g6 ! Compare TAG
sethi %hi(_PAGE_EXEC), %g4 ! Setup exec check

Expand Down
20 changes: 10 additions & 10 deletions trunk/arch/sparc64/kernel/ktlb.S
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ kvmap_itlb_tsb_miss:
kvmap_itlb_vmalloc_addr:
KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_itlb_longpath)

TSB_LOCK_TAG(%g1, %g2, %g4)
KTSB_LOCK_TAG(%g1, %g2, %g4)

/* Load and check PTE. */
ldxa [%g5] ASI_PHYS_USE_EC, %g5
brgez,a,pn %g5, kvmap_itlb_longpath
stx %g0, [%g1]
KTSB_STORE(%g1, %g0)

TSB_WRITE(%g1, %g5, %g6)
KTSB_WRITE(%g1, %g5, %g6)

/* fallthrough to TLB load */

Expand All @@ -69,19 +69,19 @@ kvmap_itlb_longpath:
kvmap_itlb_obp:
OBP_TRANS_LOOKUP(%g4, %g5, %g2, %g3, kvmap_itlb_longpath)

TSB_LOCK_TAG(%g1, %g2, %g4)
KTSB_LOCK_TAG(%g1, %g2, %g4)

TSB_WRITE(%g1, %g5, %g6)
KTSB_WRITE(%g1, %g5, %g6)

ba,pt %xcc, kvmap_itlb_load
nop

kvmap_dtlb_obp:
OBP_TRANS_LOOKUP(%g4, %g5, %g2, %g3, kvmap_dtlb_longpath)

TSB_LOCK_TAG(%g1, %g2, %g4)
KTSB_LOCK_TAG(%g1, %g2, %g4)

TSB_WRITE(%g1, %g5, %g6)
KTSB_WRITE(%g1, %g5, %g6)

ba,pt %xcc, kvmap_dtlb_load
nop
Expand Down Expand Up @@ -114,14 +114,14 @@ kvmap_linear_patch:
kvmap_dtlb_vmalloc_addr:
KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_dtlb_longpath)

TSB_LOCK_TAG(%g1, %g2, %g4)
KTSB_LOCK_TAG(%g1, %g2, %g4)

/* Load and check PTE. */
ldxa [%g5] ASI_PHYS_USE_EC, %g5
brgez,a,pn %g5, kvmap_dtlb_longpath
stx %g0, [%g1]
KTSB_STORE(%g1, %g0)

TSB_WRITE(%g1, %g5, %g6)
KTSB_WRITE(%g1, %g5, %g6)

/* fallthrough to TLB load */

Expand Down
35 changes: 30 additions & 5 deletions trunk/arch/sparc64/kernel/tsb.S
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ tsb_reload:
/* Load and check PTE. */
ldxa [%g5] ASI_PHYS_USE_EC, %g5
brgez,a,pn %g5, tsb_do_fault
stx %g0, [%g1]
TSB_STORE(%g1, %g0)

/* If it is larger than the base page size, don't
* bother putting it into the TSB.
Expand All @@ -64,7 +64,7 @@ tsb_reload:
and %g2, %g4, %g2
cmp %g2, %g7
bne,a,pn %xcc, tsb_tlb_reload
stx %g0, [%g1]
TSB_STORE(%g1, %g0)

TSB_WRITE(%g1, %g5, %g6)

Expand Down Expand Up @@ -131,13 +131,13 @@ winfix_trampoline:

/* Insert an entry into the TSB.
*
* %o0: TSB entry pointer
* %o0: TSB entry pointer (virt or phys address)
* %o1: tag
* %o2: pte
*/
.align 32
.globl tsb_insert
tsb_insert:
.globl __tsb_insert
__tsb_insert:
rdpr %pstate, %o5
wrpr %o5, PSTATE_IE, %pstate
TSB_LOCK_TAG(%o0, %g2, %g3)
Expand All @@ -146,6 +146,31 @@ tsb_insert:
retl
nop

/* Flush the given TSB entry if it has the matching
* tag.
*
* %o0: TSB entry pointer (virt or phys address)
* %o1: tag
*/
.align 32
.globl tsb_flush
tsb_flush:
sethi %hi(TSB_TAG_LOCK_HIGH), %g2
1: TSB_LOAD_TAG(%o0, %g1)
srlx %g1, 32, %o3
andcc %o3, %g2, %g0
bne,pn %icc, 1b
membar #LoadLoad
cmp %g1, %o1
bne,pt %xcc, 2f
clr %o3
TSB_CAS_TAG(%o0, %g1, %o3)
cmp %g1, %o3
bne,pn %xcc, 1b
nop
2: retl
TSB_MEMBAR

/* Reload MMU related context switch state at
* schedule() time.
*
Expand Down
4 changes: 4 additions & 0 deletions trunk/arch/sparc64/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ SECTIONS
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
SECURITY_INIT
. = ALIGN(4);
__tsb_phys_patch = .;
.tsb_phys_patch : { *(.tsb_phys_patch) }
__tsb_phys_patch_end = .;
. = ALIGN(8192);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
Expand Down
32 changes: 32 additions & 0 deletions trunk/arch/sparc64/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <asm/tlb.h>
#include <asm/spitfire.h>
#include <asm/sections.h>
#include <asm/tsb.h>

extern void device_scan(void);

Expand Down Expand Up @@ -244,6 +245,16 @@ static __inline__ void clear_dcache_dirty_cpu(struct page *page, unsigned long c
: "g1", "g7");
}

static inline void tsb_insert(struct tsb *ent, unsigned long tag, unsigned long pte)
{
unsigned long tsb_addr = (unsigned long) ent;

if (tlb_type == cheetah_plus)
tsb_addr = __pa(tsb_addr);

__tsb_insert(tsb_addr, tag, pte);
}

void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
{
struct mm_struct *mm;
Expand Down Expand Up @@ -1040,6 +1051,24 @@ unsigned long __init find_ecache_flush_span(unsigned long size)
return ~0UL;
}

static void __init tsb_phys_patch(void)
{
struct tsb_phys_patch_entry *p;

p = &__tsb_phys_patch;
while (p < &__tsb_phys_patch_end) {
unsigned long addr = p->addr;

*(unsigned int *) addr = p->insn;
wmb();
__asm__ __volatile__("flush %0"
: /* no outputs */
: "r" (addr));

p++;
}
}

/* paging_init() sets up the page tables */

extern void cheetah_ecache_flush_init(void);
Expand All @@ -1052,6 +1081,9 @@ void __init paging_init(void)
unsigned long end_pfn, pages_avail, shift;
unsigned long real_end, i;

if (tlb_type == cheetah_plus)
tsb_phys_patch();

/* Find available physical memory... */
read_obp_memory("available", &pavail[0], &pavail_ents);

Expand Down
95 changes: 65 additions & 30 deletions trunk/arch/sparc64/mm/tsb.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,9 @@ static inline unsigned long tsb_hash(unsigned long vaddr, unsigned long nentries
return vaddr & (nentries - 1);
}

static inline int tag_compare(struct tsb *entry, unsigned long vaddr, unsigned long context)
static inline int tag_compare(unsigned long tag, unsigned long vaddr, unsigned long context)
{
if (context == ~0UL)
return 1;

return (entry->tag == ((vaddr >> 22) | (context << 48)));
return (tag == ((vaddr >> 22) | (context << 48)));
}

/* TSB flushes need only occur on the processor initiating the address
Expand All @@ -41,7 +38,7 @@ void flush_tsb_kernel_range(unsigned long start, unsigned long end)
unsigned long hash = tsb_hash(v, KERNEL_TSB_NENTRIES);
struct tsb *ent = &swapper_tsb[hash];

if (tag_compare(ent, v, 0)) {
if (tag_compare(ent->tag, v, 0)) {
ent->tag = 0UL;
membar_storeload_storestore();
}
Expand All @@ -52,24 +49,31 @@ void flush_tsb_user(struct mmu_gather *mp)
{
struct mm_struct *mm = mp->mm;
struct tsb *tsb = mm->context.tsb;
unsigned long ctx = ~0UL;
unsigned long nentries = mm->context.tsb_nentries;
unsigned long ctx, base;
int i;

if (CTX_VALID(mm->context))
ctx = CTX_HWBITS(mm->context);
if (unlikely(!CTX_VALID(mm->context)))
return;

ctx = CTX_HWBITS(mm->context);

if (tlb_type == cheetah_plus)
base = __pa(tsb);
else
base = (unsigned long) tsb;

for (i = 0; i < mp->tlb_nr; i++) {
unsigned long v = mp->vaddrs[i];
struct tsb *ent;
unsigned long tag, ent, hash;

v &= ~0x1UL;

ent = &tsb[tsb_hash(v, nentries)];
if (tag_compare(ent, v, ctx)) {
ent->tag = 0UL;
membar_storeload_storestore();
}
hash = tsb_hash(v, nentries);
ent = base + (hash * sizeof(struct tsb));
tag = (v >> 22UL) | (ctx << 48UL);

tsb_flush(ent, tag);
}
}

Expand All @@ -84,6 +88,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_bytes)
tte = (_PAGE_VALID | _PAGE_L | _PAGE_CP |
_PAGE_CV | _PAGE_P | _PAGE_W);
tsb_paddr = __pa(mm->context.tsb);
BUG_ON(tsb_paddr & (tsb_bytes - 1UL));

/* Use the smallest page size that can map the whole TSB
* in one TLB entry.
Expand Down Expand Up @@ -144,13 +149,23 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_bytes)
BUG();
};

tsb_reg |= base;
tsb_reg |= (tsb_paddr & (page_sz - 1UL));
tte |= (tsb_paddr & ~(page_sz - 1UL));
if (tlb_type == cheetah_plus) {
/* Physical mapping, no locked TLB entry for TSB. */
tsb_reg |= tsb_paddr;

mm->context.tsb_reg_val = tsb_reg;
mm->context.tsb_map_vaddr = 0;
mm->context.tsb_map_pte = 0;
} else {
tsb_reg |= base;
tsb_reg |= (tsb_paddr & (page_sz - 1UL));
tte |= (tsb_paddr & ~(page_sz - 1UL));

mm->context.tsb_reg_val = tsb_reg;
mm->context.tsb_map_vaddr = base;
mm->context.tsb_map_pte = tte;
}

mm->context.tsb_reg_val = tsb_reg;
mm->context.tsb_map_vaddr = base;
mm->context.tsb_map_pte = tte;
}

/* The page tables are locked against modifications while this
Expand All @@ -168,13 +183,21 @@ static void copy_tsb(struct tsb *old_tsb, unsigned long old_size,
for (i = 0; i < old_nentries; i++) {
register unsigned long tag asm("o4");
register unsigned long pte asm("o5");
unsigned long v;
unsigned int hash;

__asm__ __volatile__(
"ldda [%2] %3, %0"
: "=r" (tag), "=r" (pte)
: "r" (&old_tsb[i]), "i" (ASI_NUCLEUS_QUAD_LDD));
unsigned long v, hash;

if (tlb_type == cheetah_plus) {
__asm__ __volatile__(
"ldda [%2] %3, %0"
: "=r" (tag), "=r" (pte)
: "r" (__pa(&old_tsb[i])),
"i" (ASI_QUAD_LDD_PHYS));
} else {
__asm__ __volatile__(
"ldda [%2] %3, %0"
: "=r" (tag), "=r" (pte)
: "r" (&old_tsb[i]),
"i" (ASI_NUCLEUS_QUAD_LDD));
}

if (!tag || (tag & (1UL << TSB_TAG_LOCK_BIT)))
continue;
Expand All @@ -198,8 +221,20 @@ static void copy_tsb(struct tsb *old_tsb, unsigned long old_size,
v |= (i & (512UL - 1UL)) << 13UL;

hash = tsb_hash(v, new_nentries);
new_tsb[hash].tag = tag;
new_tsb[hash].pte = pte;
if (tlb_type == cheetah_plus) {
__asm__ __volatile__(
"stxa %0, [%1] %2\n\t"
"stxa %3, [%4] %2"
: /* no outputs */
: "r" (tag),
"r" (__pa(&new_tsb[hash].tag)),
"i" (ASI_PHYS_USE_EC),
"r" (pte),
"r" (__pa(&new_tsb[hash].pte)));
} else {
new_tsb[hash].tag = tag;
new_tsb[hash].pte = pte;
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion trunk/include/asm-sparc64/mmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ struct tsb {
unsigned long pte;
} __attribute__((aligned(TSB_ENTRY_ALIGNMENT)));

extern void tsb_insert(struct tsb *ent, unsigned long tag, unsigned long pte);
extern void __tsb_insert(unsigned long ent, unsigned long tag, unsigned long pte);
extern void tsb_flush(unsigned long ent, unsigned long tag);

typedef struct {
unsigned long sparc64_ctx_val;
Expand Down
Loading

0 comments on commit 76f62c1

Please sign in to comment.