Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 330312
b: refs/heads/master
c: 7aa0727
h: refs/heads/master
v: v3
  • Loading branch information
Aneesh Kumar K.V authored and Benjamin Herrenschmidt committed Sep 17, 2012
1 parent 49d5bb4 commit 82d4239
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 56 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: 67550080b8288ee9b61e132e8ebc87d563f9c516
refs/heads/master: 7aa0727f3302931e698b3a7979ae5b9a4600da4e
6 changes: 5 additions & 1 deletion trunk/arch/powerpc/include/asm/mmu-hash64.h
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,11 @@ typedef struct {

#ifdef CONFIG_PPC_MM_SLICES
u64 low_slices_psize; /* SLB page size encodings */
u64 high_slices_psize; /* 4 bits per slice for now */
/*
* Right now we support 64TB and 4 bits for each
* 1TB slice we need 32 bytes for 64TB.
*/
unsigned char high_slices_psize[32]; /* 4 bits per slice for now */
#else
u16 sllp; /* SLB page size encoding */
#endif
Expand Down
6 changes: 5 additions & 1 deletion trunk/arch/powerpc/include/asm/page_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ extern u64 ppc64_pft_size;

struct slice_mask {
u16 low_slices;
u16 high_slices;
/*
* This should be derived out of PGTABLE_RANGE. For the current
* max 64TB, u64 should be ok.
*/
u64 high_slices;
};

struct mm_struct;
Expand Down
15 changes: 9 additions & 6 deletions trunk/arch/powerpc/mm/hash_utils_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -803,16 +803,19 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
#ifdef CONFIG_PPC_MM_SLICES
unsigned int get_paca_psize(unsigned long addr)
{
unsigned long index, slices;
u64 lpsizes;
unsigned char *hpsizes;
unsigned long index, mask_index;

if (addr < SLICE_LOW_TOP) {
slices = get_paca()->context.low_slices_psize;
lpsizes = get_paca()->context.low_slices_psize;
index = GET_LOW_SLICE_INDEX(addr);
} else {
slices = get_paca()->context.high_slices_psize;
index = GET_HIGH_SLICE_INDEX(addr);
return (lpsizes >> (index * 4)) & 0xF;
}
return (slices >> (index * 4)) & 0xF;
hpsizes = get_paca()->context.high_slices_psize;
index = GET_HIGH_SLICE_INDEX(addr);
mask_index = index & 0x1;
return (hpsizes[index >> 1] >> (mask_index * 4)) & 0xF;
}

#else
Expand Down
30 changes: 22 additions & 8 deletions trunk/arch/powerpc/mm/slb_low.S
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,31 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
* between 4k and 64k standard page size
*/
#ifdef CONFIG_PPC_MM_SLICES
/* r10 have esid */
cmpldi r10,16

/* Get the slice index * 4 in r11 and matching slice size mask in r9 */
ld r9,PACALOWSLICESPSIZE(r13)
sldi r11,r10,2
/* below SLICE_LOW_TOP */
blt 5f
ld r9,PACAHIGHSLICEPSIZE(r13)
srdi r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT - 2)
andi. r11,r11,0x3c
/*
* Handle hpsizes,
* r9 is get_paca()->context.high_slices_psize[index], r11 is mask_index
*/
srdi r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT + 1) /* index */
addi r9,r11,PACAHIGHSLICEPSIZE
lbzx r9,r13,r9 /* r9 is hpsizes[r11] */
/* r11 = (r10 >> (SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT)) & 0x1 */
rldicl r11,r10,(64 - (SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT)),63
b 6f

5: /* Extract the psize and multiply to get an array offset */
5:
/*
* Handle lpsizes
* r9 is get_paca()->context.low_slices_psize, r11 is index
*/
ld r9,PACALOWSLICESPSIZE(r13)
mr r11,r10
6:
sldi r11,r11,2 /* index * 4 */
/* Extract the psize and multiply to get an array offset */
srd r9,r9,r11
andi. r9,r9,0xf
mulli r9,r9,MMUPSIZEDEFSIZE
Expand Down
107 changes: 68 additions & 39 deletions trunk/arch/powerpc/mm/slice.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ int _slice_debug = 1;

static void slice_print_mask(const char *label, struct slice_mask mask)
{
char *p, buf[16 + 3 + 16 + 1];
char *p, buf[16 + 3 + 64 + 1];
int i;

if (!_slice_debug)
Expand All @@ -54,7 +54,7 @@ static void slice_print_mask(const char *label, struct slice_mask mask)
*(p++) = '-';
*(p++) = ' ';
for (i = 0; i < SLICE_NUM_HIGH; i++)
*(p++) = (mask.high_slices & (1 << i)) ? '1' : '0';
*(p++) = (mask.high_slices & (1ul << i)) ? '1' : '0';
*(p++) = 0;

printk(KERN_DEBUG "%s:%s\n", label, buf);
Expand Down Expand Up @@ -84,8 +84,8 @@ static struct slice_mask slice_range_to_mask(unsigned long start,
}

if ((start + len) > SLICE_LOW_TOP)
ret.high_slices = (1u << (GET_HIGH_SLICE_INDEX(end) + 1))
- (1u << GET_HIGH_SLICE_INDEX(start));
ret.high_slices = (1ul << (GET_HIGH_SLICE_INDEX(end) + 1))
- (1ul << GET_HIGH_SLICE_INDEX(start));

return ret;
}
Expand Down Expand Up @@ -135,26 +135,31 @@ static struct slice_mask slice_mask_for_free(struct mm_struct *mm)

for (i = 0; i < SLICE_NUM_HIGH; i++)
if (!slice_high_has_vma(mm, i))
ret.high_slices |= 1u << i;
ret.high_slices |= 1ul << i;

return ret;
}

static struct slice_mask slice_mask_for_size(struct mm_struct *mm, int psize)
{
unsigned char *hpsizes;
int index, mask_index;
struct slice_mask ret = { 0, 0 };
unsigned long i;
u64 psizes;
u64 lpsizes;

psizes = mm->context.low_slices_psize;
lpsizes = mm->context.low_slices_psize;
for (i = 0; i < SLICE_NUM_LOW; i++)
if (((psizes >> (i * 4)) & 0xf) == psize)
if (((lpsizes >> (i * 4)) & 0xf) == psize)
ret.low_slices |= 1u << i;

psizes = mm->context.high_slices_psize;
for (i = 0; i < SLICE_NUM_HIGH; i++)
if (((psizes >> (i * 4)) & 0xf) == psize)
ret.high_slices |= 1u << i;
hpsizes = mm->context.high_slices_psize;
for (i = 0; i < SLICE_NUM_HIGH; i++) {
mask_index = i & 0x1;
index = i >> 1;
if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize)
ret.high_slices |= 1ul << i;
}

return ret;
}
Expand Down Expand Up @@ -183,8 +188,10 @@ static void slice_flush_segments(void *parm)

static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psize)
{
int index, mask_index;
/* Write the new slice psize bits */
u64 lpsizes, hpsizes;
unsigned char *hpsizes;
u64 lpsizes;
unsigned long i, flags;

slice_dbg("slice_convert(mm=%p, psize=%d)\n", mm, psize);
Expand All @@ -201,14 +208,18 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
lpsizes = (lpsizes & ~(0xful << (i * 4))) |
(((unsigned long)psize) << (i * 4));

hpsizes = mm->context.high_slices_psize;
for (i = 0; i < SLICE_NUM_HIGH; i++)
if (mask.high_slices & (1u << i))
hpsizes = (hpsizes & ~(0xful << (i * 4))) |
(((unsigned long)psize) << (i * 4));

/* Assign the value back */
mm->context.low_slices_psize = lpsizes;
mm->context.high_slices_psize = hpsizes;

hpsizes = mm->context.high_slices_psize;
for (i = 0; i < SLICE_NUM_HIGH; i++) {
mask_index = i & 0x1;
index = i >> 1;
if (mask.high_slices & (1ul << i))
hpsizes[index] = (hpsizes[index] &
~(0xf << (mask_index * 4))) |
(((unsigned long)psize) << (mask_index * 4));
}

slice_dbg(" lsps=%lx, hsps=%lx\n",
mm->context.low_slices_psize,
Expand Down Expand Up @@ -587,18 +598,19 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,

unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr)
{
u64 psizes;
int index;
unsigned char *hpsizes;
int index, mask_index;

if (addr < SLICE_LOW_TOP) {
psizes = mm->context.low_slices_psize;
u64 lpsizes;
lpsizes = mm->context.low_slices_psize;
index = GET_LOW_SLICE_INDEX(addr);
} else {
psizes = mm->context.high_slices_psize;
index = GET_HIGH_SLICE_INDEX(addr);
return (lpsizes >> (index * 4)) & 0xf;
}

return (psizes >> (index * 4)) & 0xf;
hpsizes = mm->context.high_slices_psize;
index = GET_HIGH_SLICE_INDEX(addr);
mask_index = index & 0x1;
return (hpsizes[index >> 1] >> (mask_index * 4)) & 0xf;
}
EXPORT_SYMBOL_GPL(get_slice_psize);

Expand All @@ -618,7 +630,9 @@ EXPORT_SYMBOL_GPL(get_slice_psize);
*/
void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
{
unsigned long flags, lpsizes, hpsizes;
int index, mask_index;
unsigned char *hpsizes;
unsigned long flags, lpsizes;
unsigned int old_psize;
int i;

Expand All @@ -639,15 +653,21 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
if (((lpsizes >> (i * 4)) & 0xf) == old_psize)
lpsizes = (lpsizes & ~(0xful << (i * 4))) |
(((unsigned long)psize) << (i * 4));
/* Assign the value back */
mm->context.low_slices_psize = lpsizes;

hpsizes = mm->context.high_slices_psize;
for (i = 0; i < SLICE_NUM_HIGH; i++)
if (((hpsizes >> (i * 4)) & 0xf) == old_psize)
hpsizes = (hpsizes & ~(0xful << (i * 4))) |
(((unsigned long)psize) << (i * 4));
for (i = 0; i < SLICE_NUM_HIGH; i++) {
mask_index = i & 0x1;
index = i >> 1;
if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == old_psize)
hpsizes[index] = (hpsizes[index] &
~(0xf << (mask_index * 4))) |
(((unsigned long)psize) << (mask_index * 4));
}



mm->context.low_slices_psize = lpsizes;
mm->context.high_slices_psize = hpsizes;

slice_dbg(" lsps=%lx, hsps=%lx\n",
mm->context.low_slices_psize,
Expand All @@ -660,18 +680,27 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
void slice_set_psize(struct mm_struct *mm, unsigned long address,
unsigned int psize)
{
unsigned char *hpsizes;
unsigned long i, flags;
u64 *p;
u64 *lpsizes;

spin_lock_irqsave(&slice_convert_lock, flags);
if (address < SLICE_LOW_TOP) {
i = GET_LOW_SLICE_INDEX(address);
p = &mm->context.low_slices_psize;
lpsizes = &mm->context.low_slices_psize;
*lpsizes = (*lpsizes & ~(0xful << (i * 4))) |
((unsigned long) psize << (i * 4));
} else {
int index, mask_index;
i = GET_HIGH_SLICE_INDEX(address);
p = &mm->context.high_slices_psize;
hpsizes = mm->context.high_slices_psize;
mask_index = i & 0x1;
index = i >> 1;
hpsizes[index] = (hpsizes[index] &
~(0xf << (mask_index * 4))) |
(((unsigned long)psize) << (mask_index * 4));
}
*p = (*p & ~(0xful << (i * 4))) | ((unsigned long) psize << (i * 4));

spin_unlock_irqrestore(&slice_convert_lock, flags);

#ifdef CONFIG_SPU_BASE
Expand Down

0 comments on commit 82d4239

Please sign in to comment.