-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The delta is now minimal. Merge them Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
- Loading branch information
Thomas Gleixner
authored and
Ingo Molnar
committed
Jan 30, 2008
1 parent
0b9c99b
commit d291cf8
Showing
3 changed files
with
155 additions
and
290 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,158 @@ | ||
#ifndef _ASM_X86_TLBFLUSH_H | ||
#define _ASM_X86_TLBFLUSH_H | ||
|
||
#include <linux/mm.h> | ||
#include <linux/sched.h> | ||
|
||
#include <asm/processor.h> | ||
#include <asm/system.h> | ||
|
||
#ifdef CONFIG_PARAVIRT | ||
#include <asm/paravirt.h> | ||
#else | ||
#define __flush_tlb() __native_flush_tlb() | ||
#define __flush_tlb_global() __native_flush_tlb_global() | ||
#define __flush_tlb_single(addr) __native_flush_tlb_single(addr) | ||
#endif | ||
|
||
static inline void __native_flush_tlb(void) | ||
{ | ||
write_cr3(read_cr3()); | ||
} | ||
|
||
static inline void __native_flush_tlb_global(void) | ||
{ | ||
unsigned long cr4 = read_cr4(); | ||
|
||
/* clear PGE */ | ||
write_cr4(cr4 & ~X86_CR4_PGE); | ||
/* write old PGE again and flush TLBs */ | ||
write_cr4(cr4); | ||
} | ||
|
||
static inline void __native_flush_tlb_single(unsigned long addr) | ||
{ | ||
__asm__ __volatile__("invlpg (%0)" ::"r" (addr) : "memory"); | ||
} | ||
|
||
static inline void __flush_tlb_all(void) | ||
{ | ||
if (cpu_has_pge) | ||
__flush_tlb_global(); | ||
else | ||
__flush_tlb(); | ||
} | ||
|
||
static inline void __flush_tlb_one(unsigned long addr) | ||
{ | ||
if (cpu_has_invlpg) | ||
__flush_tlb_single(addr); | ||
else | ||
__flush_tlb(); | ||
} | ||
|
||
#ifdef CONFIG_X86_32 | ||
# include "tlbflush_32.h" | ||
# define TLB_FLUSH_ALL 0xffffffff | ||
#else | ||
# include "tlbflush_64.h" | ||
# define TLB_FLUSH_ALL -1ULL | ||
#endif | ||
|
||
/* | ||
* TLB flushing: | ||
* | ||
* - flush_tlb() flushes the current mm struct TLBs | ||
* - flush_tlb_all() flushes all processes TLBs | ||
* - flush_tlb_mm(mm) flushes the specified mm context TLB's | ||
* - flush_tlb_page(vma, vmaddr) flushes one page | ||
* - flush_tlb_range(vma, start, end) flushes a range of pages | ||
* - flush_tlb_kernel_range(start, end) flushes a range of kernel pages | ||
* - flush_tlb_others(cpumask, mm, va) flushes TLBs on other cpus | ||
* | ||
* ..but the i386 has somewhat limited tlb flushing capabilities, | ||
* and page-granular flushes are available only on i486 and up. | ||
* | ||
* x86-64 can only flush individual pages or full VMs. For a range flush | ||
* we always do the full VM. Might be worth trying if for a small | ||
* range a few INVLPGs in a row are a win. | ||
*/ | ||
|
||
#ifndef CONFIG_SMP | ||
|
||
#define flush_tlb() __flush_tlb() | ||
#define flush_tlb_all() __flush_tlb_all() | ||
#define local_flush_tlb() __flush_tlb() | ||
|
||
static inline void flush_tlb_mm(struct mm_struct *mm) | ||
{ | ||
if (mm == current->active_mm) | ||
__flush_tlb(); | ||
} | ||
|
||
static inline void flush_tlb_page(struct vm_area_struct *vma, | ||
unsigned long addr) | ||
{ | ||
if (vma->vm_mm == current->active_mm) | ||
__flush_tlb_one(addr); | ||
} | ||
|
||
static inline void flush_tlb_range(struct vm_area_struct *vma, | ||
unsigned long start, unsigned long end) | ||
{ | ||
if (vma->vm_mm == current->active_mm) | ||
__flush_tlb(); | ||
} | ||
|
||
static inline void native_flush_tlb_others(const cpumask_t *cpumask, | ||
struct mm_struct *mm, | ||
unsigned long va) | ||
{ | ||
} | ||
|
||
#else /* SMP */ | ||
|
||
#include <asm/smp.h> | ||
|
||
#define local_flush_tlb() __flush_tlb() | ||
|
||
extern void flush_tlb_all(void); | ||
extern void flush_tlb_current_task(void); | ||
extern void flush_tlb_mm(struct mm_struct *); | ||
extern void flush_tlb_page(struct vm_area_struct *, unsigned long); | ||
|
||
#define flush_tlb() flush_tlb_current_task() | ||
|
||
static inline void flush_tlb_range(struct vm_area_struct *vma, | ||
unsigned long start, unsigned long end) | ||
{ | ||
flush_tlb_mm(vma->vm_mm); | ||
} | ||
|
||
void native_flush_tlb_others(const cpumask_t *cpumask, struct mm_struct *mm, | ||
unsigned long va); | ||
|
||
#define TLBSTATE_OK 1 | ||
#define TLBSTATE_LAZY 2 | ||
|
||
#ifdef CONFIG_X86_32 | ||
struct tlb_state | ||
{ | ||
struct mm_struct *active_mm; | ||
int state; | ||
char __cacheline_padding[L1_CACHE_BYTES-8]; | ||
}; | ||
DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate); | ||
#endif | ||
|
||
#endif /* SMP */ | ||
|
||
#ifndef CONFIG_PARAVIRT | ||
#define flush_tlb_others(mask, mm, va) native_flush_tlb_others(&mask, mm, va) | ||
#endif | ||
|
||
static inline void flush_tlb_kernel_range(unsigned long start, | ||
unsigned long end) | ||
{ | ||
flush_tlb_all(); | ||
} | ||
|
||
#endif /* _ASM_X86_TLBFLUSH_H */ |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.