aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/ip.h
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-04-11 16:32:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-11 16:32:29 -0400
commit120dd64cacd4fb796bca0acba3665553f1d9ecaa (patch)
tree6df8e6880d4deafb5e5fbe6f6921b17003dd9b0e /include/linux/ip.h
parent14897e35fdc045fff9baabf0354570da22386706 (diff)
Linux 2.6.25-rc9v2.6.25-rc9
Diffstat (limited to 'include/linux/ip.h')
0 files changed, 0 insertions, 0 deletions
tored-gedf'>wip-refactored-gedf The LITMUS^RT kernel.Bjoern Brandenburg
aboutsummaryrefslogblamecommitdiffstats
path: root/arch/powerpc/mm/hugetlbpage.c
blob: 7370f9f33e2943d038025a6d05ba6b4e02755beb (plain) (tree)




























                                                        


                                                          

                                                                
 



                  
 
                                                      
 






                                                  















                                                                              
                                         
                                  
                                 

                 
 
                    

 
                                                               
 



                  
 

                                                      
                           
 

                                     
 


                                             







                                                                               
                                         
                                 
                                  


                 
                    

 


                                                              
                                 





                                                                           

                                    
                                                       

 

                                                                       
 
                                                   
 
                                

                                                                 
 
                          

 




                             
                                          
 
                                         

                        



                                                                
 




                                                                      
 
                                             
                                             
                                                 
                                 

                                                                   
         


                                             

                                           
                                         

                           
 






                                                                      
 



                                                          
                                              
                                                 


                                                                          
                                                                    
                                                                              
         



                                                                              
 

                                                  
                                   
 
                                      





                                             


                 







                                                                               





                                                                      








                                                                   

                        
                                 
 




                                                                              

                                                                     






                                                                  


                                                                      



                                                   





                                                                    
                                 












                                                                   

                                              
                                                






                                                                      



                                                    





                                                                 
                    



                                
                                 
                                                       
                                                                    
                                         






                                                                            


                           
                 

 





























                                                                        





















                                                                            





                                                        










                                                                

                                                                   









                                                                          

                                                                    






                                                       
                                         




















                                                                             
                                                          



















                                                                         



                                           











                                                                               


                                                                          













                                                                     
                                                                      
                                                                          


                                                            
                                                                         
                                                                 
                                                                    






                                                                    











                                                              
                                 









                                                                     
                                    




                                                                      
                                    



                    










                                                                        


























                                                                        
                                                                        
 
                                           


                                          
                                                
                                                                     





                                                                          



                                                          



                                                                     








                                                                               


                               

                               





                                               


                                                          
                                          


                                                                  
                                                               
 







                                                                             
                                                        


                                    
                                                          



                                                                      

                                              
                                                                           
                                             
                                                                                

                                            
                

                                                                










                                                                              



                                                         
                                                          










                                                                                 
         


                                                                      

 


























                                                                            
                                                              

                                                                   

                    

                                       


                    



                                                             







                                                                 


















                                                                              









                                                               
                                                          
                                                          




                                                                              

                                                       
                                                


                                                         

                                                 

                                                                 
                                                      
 

                                                                          
                                                    

         

                                                               

                                         
                                                           




                                                        

                                                                       


                                                          
                                                  
                                         
 


                                                                        


                                                        
                                                  

                                                                 
                                                                             
                                                                   
                                                                  

                                                 

                                                                               








                                                                     
                                                      

         
          
                                          


                                             


                

                   
/*
 * PPC64 (POWER4) Huge TLB Page Support for Kernel.
 *
 * Copyright (C) 2003 David Gibson, IBM Corporation.
 *
 * Based on the IA-32 version:
 * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com>
 */

#include <linux/init.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/pagemap.h>
#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/sysctl.h>
#include <asm/mman.h>
#include <asm/pgalloc.h>
#include <asm/tlb.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
#include <asm/machdep.h>
#include <asm/cputable.h>
#include <asm/tlb.h>

#include <linux/sysctl.h>

#define NUM_LOW_AREAS	(0x100000000UL >> SID_SHIFT)
#define NUM_HIGH_AREAS	(PGTABLE_RANGE >> HTLB_AREA_SHIFT)

/* Modelled after find_linux_pte() */
pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
{
	pgd_t *pg;
	pud_t *pu;
	pmd_t *pm;
	pte_t *pt;

	BUG_ON(! in_hugepage_area(mm->context, addr));

	addr &= HPAGE_MASK;

	pg = pgd_offset(mm, addr);
	if (!pgd_none(*pg)) {
		pu = pud_offset(pg, addr);
		if (!pud_none(*pu)) {
			pm = pmd_offset(pu, addr);
#ifdef CONFIG_PPC_64K_PAGES
			/* Currently, we use the normal PTE offset within full
			 * size PTE pages, thus our huge PTEs are scattered in
			 * the PTE page and we do waste some. We may change
			 * that in the future, but the current mecanism keeps
			 * things much simpler
			 */
			if (!pmd_none(*pm)) {
				/* Note: pte_offset_* are all equivalent on
				 * ppc64 as we don't have HIGHMEM
				 */
				pt = pte_offset_kernel(pm, addr);
				return pt;
			}
#else /* CONFIG_PPC_64K_PAGES */
			/* On 4k pages, we put huge PTEs in the PMD page */
			pt = (pte_t *)pm;
			return pt;
#endif /* CONFIG_PPC_64K_PAGES */
		}
	}

	return NULL;
}

pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
{
	pgd_t *pg;
	pud_t *pu;
	pmd_t *pm;
	pte_t *pt;

	BUG_ON(! in_hugepage_area(mm->context, addr));

	addr &= HPAGE_MASK;

	pg = pgd_offset(mm, addr);
	pu = pud_alloc(mm, pg, addr);

	if (pu) {
		pm = pmd_alloc(mm, pu, addr);
		if (pm) {
#ifdef CONFIG_PPC_64K_PAGES
			/* See comment in huge_pte_offset. Note that if we ever
			 * want to put the page size in the PMD, we would have
			 * to open code our own pte_alloc* function in order
			 * to populate and set the size atomically
			 */
			pt = pte_alloc_map(mm, pm, addr);
#else /* CONFIG_PPC_64K_PAGES */
			pt = (pte_t *)pm;
#endif /* CONFIG_PPC_64K_PAGES */
			return pt;
		}
	}

	return NULL;
}

void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
		     pte_t *ptep, pte_t pte)
{
	if (pte_present(*ptep)) {
		/* We open-code pte_clear because we need to pass the right
		 * argument to hpte_update (huge / !huge)
		 */
		unsigned long old = pte_update(ptep, ~0UL);
		if (old & _PAGE_HASHPTE)
			hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1);
		flush_tlb_pending();
	}
	*ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
}

pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
			      pte_t *ptep)
{
	unsigned long old = pte_update(ptep, ~0UL);

	if (old & _PAGE_HASHPTE)
		hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1);
	*ptep = __pte(0);

	return __pte(old);
}

struct slb_flush_info {
	struct mm_struct *mm;
	u16 newareas;
};

static void flush_low_segments(void *parm)
{
	struct slb_flush_info *fi = parm;
	unsigned long i;

	BUILD_BUG_ON((sizeof(fi->newareas)*8) != NUM_LOW_AREAS);

	if (current->active_mm != fi->mm)
		return;

	/* Only need to do anything if this CPU is working in the same
	 * mm as the one which has changed */

	/* update the paca copy of the context struct */
	get_paca()->context = current->active_mm->context;

	asm volatile("isync" : : : "memory");
	for (i = 0; i < NUM_LOW_AREAS; i++) {
		if (! (fi->newareas & (1U << i)))
			continue;
		asm volatile("slbie %0"
			     : : "r" ((i << SID_SHIFT) | SLBIE_C));
	}
	asm volatile("isync" : : : "memory");
}

static void flush_high_segments(void *parm)
{
	struct slb_flush_info *fi = parm;
	unsigned long i, j;


	BUILD_BUG_ON((sizeof(fi->newareas)*8) != NUM_HIGH_AREAS);

	if (current->active_mm != fi->mm)
		return;

	/* Only need to do anything if this CPU is working in the same
	 * mm as the one which has changed */

	/* update the paca copy of the context struct */
	get_paca()->context = current->active_mm->context;

	asm volatile("isync" : : : "memory");
	for (i = 0; i < NUM_HIGH_AREAS; i++) {
		if (! (fi->newareas & (1U << i)))
			continue;
		for (j = 0; j < (1UL << (HTLB_AREA_SHIFT-SID_SHIFT)); j++)
			asm volatile("slbie %0"
				     :: "r" (((i << HTLB_AREA_SHIFT)
					      + (j << SID_SHIFT)) | SLBIE_C));
	}
	asm volatile("isync" : : : "memory");
}

static int prepare_low_area_for_htlb(struct mm_struct *mm, unsigned long area)
{
	unsigned long start = area << SID_SHIFT;
	unsigned long end = (area+1) << SID_SHIFT;
	struct vm_area_struct *vma;

	BUG_ON(area >= NUM_LOW_AREAS);

	/* Check no VMAs are in the region */
	vma = find_vma(mm, start);
	if (vma && (vma->vm_start < end))
		return -EBUSY;

	return 0;
}

static int prepare_high_area_for_htlb(struct mm_struct *mm, unsigned long area)
{
	unsigned long start = area << HTLB_AREA_SHIFT;
	unsigned long end = (area+1) << HTLB_AREA_SHIFT;
	struct vm_area_struct *vma;

	BUG_ON(area >= NUM_HIGH_AREAS);

	/* Hack, so that each addresses is controlled by exactly one
	 * of the high or low area bitmaps, the first high area starts
	 * at 4GB, not 0 */
	if (start == 0)
		start = 0x100000000UL;

	/* Check no VMAs are in the region */
	vma = find_vma(mm, start);
	if (vma && (vma->vm_start < end))
		return -EBUSY;

	return 0;
}

static int open_low_hpage_areas(struct mm_struct *mm, u16 newareas)
{
	unsigned long i;
	struct slb_flush_info fi;

	BUILD_BUG_ON((sizeof(newareas)*8) != NUM_LOW_AREAS);
	BUILD_BUG_ON((sizeof(mm->context.low_htlb_areas)*8) != NUM_LOW_AREAS);

	newareas &= ~(mm->context.low_htlb_areas);
	if (! newareas)
		return 0; /* The segments we want are already open */

	for (i = 0; i < NUM_LOW_AREAS; i++)
		if ((1 << i) & newareas)
			if (prepare_low_area_for_htlb(mm, i) != 0)
				return -EBUSY;

	mm->context.low_htlb_areas |= newareas;

	/* the context change must make it to memory before the flush,
	 * so that further SLB misses do the right thing. */
	mb();

	fi.mm = mm;
	fi.newareas = newareas;
	on_each_cpu(flush_low_segments, &fi, 0, 1);

	return 0;
}

static int open_high_hpage_areas(struct mm_struct *mm, u16 newareas)
{
	struct slb_flush_info fi;
	unsigned long i;

	BUILD_BUG_ON((sizeof(newareas)*8) != NUM_HIGH_AREAS);
	BUILD_BUG_ON((sizeof(mm->context.high_htlb_areas)*8)
		     != NUM_HIGH_AREAS);

	newareas &= ~(mm->context.high_htlb_areas);
	if (! newareas)
		return 0; /* The areas we want are already open */

	for (i = 0; i < NUM_HIGH_AREAS; i++)
		if ((1 << i) & newareas)
			if (prepare_high_area_for_htlb(mm, i) != 0)
				return -EBUSY;

	mm->context.high_htlb_areas |= newareas;