2008-10-22 22:26:29 -07:00
# ifndef _ASM_X86_CACHEFLUSH_H
# define _ASM_X86_CACHEFLUSH_H
2007-10-15 23:28:20 +02:00
/* Caches aren't brain-dead on the intel. */
2011-01-20 20:32:14 +09:00
# include <asm-generic/cacheflush.h>
2007-10-15 23:28:20 +02:00
2009-07-10 09:57:38 -07:00
# ifdef CONFIG_X86_PAT
/*
* X86 PAT uses page flags WC and Uncached together to keep track of
* memory type of pages that have backing page struct . X86 PAT supports 3
* different memory types , _PAGE_CACHE_WB , _PAGE_CACHE_WC and
* _PAGE_CACHE_UC_MINUS and fourth state where page ' s memory type has not
* been changed from its default ( value of - 1 used to denote this ) .
* Note we do not support _PAGE_CACHE_UC here .
*/
2010-04-23 10:36:22 -05:00
# define _PGMT_DEFAULT 0
# define _PGMT_WC (1UL << PG_arch_1)
# define _PGMT_UC_MINUS (1UL << PG_uncached)
# define _PGMT_WB (1UL << PG_uncached | 1UL << PG_arch_1)
# define _PGMT_MASK (1UL << PG_uncached | 1UL << PG_arch_1)
# define _PGMT_CLEAR_MASK (~_PGMT_MASK)
2009-07-10 09:57:38 -07:00
static inline unsigned long get_page_memtype ( struct page * pg )
{
2010-04-23 10:36:22 -05:00
unsigned long pg_flags = pg - > flags & _PGMT_MASK ;
if ( pg_flags = = _PGMT_DEFAULT )
2009-07-10 09:57:38 -07:00
return - 1 ;
2010-04-23 10:36:22 -05:00
else if ( pg_flags = = _PGMT_WC )
2009-07-10 09:57:38 -07:00
return _PAGE_CACHE_WC ;
2010-04-23 10:36:22 -05:00
else if ( pg_flags = = _PGMT_UC_MINUS )
2009-07-10 09:57:38 -07:00
return _PAGE_CACHE_UC_MINUS ;
else
return _PAGE_CACHE_WB ;
}
static inline void set_page_memtype ( struct page * pg , unsigned long memtype )
{
2010-04-23 10:36:22 -05:00
unsigned long memtype_flags = _PGMT_DEFAULT ;
unsigned long old_flags ;
unsigned long new_flags ;
2009-07-10 09:57:38 -07:00
switch ( memtype ) {
case _PAGE_CACHE_WC :
2010-04-23 10:36:22 -05:00
memtype_flags = _PGMT_WC ;
2009-07-10 09:57:38 -07:00
break ;
case _PAGE_CACHE_UC_MINUS :
2010-04-23 10:36:22 -05:00
memtype_flags = _PGMT_UC_MINUS ;
2009-07-10 09:57:38 -07:00
break ;
case _PAGE_CACHE_WB :
2010-04-23 10:36:22 -05:00
memtype_flags = _PGMT_WB ;
2009-07-10 09:57:38 -07:00
break ;
}
2010-04-23 10:36:22 -05:00
do {
old_flags = pg - > flags ;
new_flags = ( old_flags & _PGMT_CLEAR_MASK ) | memtype_flags ;
} while ( cmpxchg ( & pg - > flags , old_flags , new_flags ) ! = old_flags ) ;
2009-07-10 09:57:38 -07:00
}
# else
static inline unsigned long get_page_memtype ( struct page * pg ) { return - 1 ; }
static inline void set_page_memtype ( struct page * pg , unsigned long memtype ) { }
# endif
x86: a new API for drivers/etc to control cache and other page attributes
Right now, if drivers or other code want to change, say, a cache attribute of a
page, the only API they have is change_page_attr(). c-p-a is a really bad API
for this, because it forces the caller to know *ALL* the attributes he wants
for the page, not just the 1 thing he wants to change. So code that wants to
set a page uncachable, needs to be aware of the NX status as well etc etc etc.
This patch introduces a set of new APIs for this, set_pages_<attr> and
set_memory_<attr>, that offer a logical change to the user, and leave all
attributes not implied by the requested logical change alone.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2008-01-30 13:34:06 +01:00
2008-04-17 17:41:31 +02:00
/*
* The set_memory_ * API can be used to change various attributes of a virtual
* address range . The attributes include :
* Cachability : UnCached , WriteCombining , WriteBack
* Executability : eXeutable , NoteXecutable
* Read / Write : ReadOnly , ReadWrite
* Presence : NotPresent
*
2011-03-17 16:24:16 -03:00
* Within a category , the attributes are mutually exclusive .
2008-04-17 17:41:31 +02:00
*
* The implementation of this API will take care of various aspects that
* are associated with changing such attributes , such as :
* - Flushing TLBs
* - Flushing CPU caches
* - Making sure aliases of the memory behind the mapping don ' t violate
* coherency rules as defined by the CPU in the system .
*
* What this API does not do :
* - Provide exclusion between various callers - including callers that
* operation on other mappings of the same physical page
* - Restore default attributes when a page is freed
* - Guarantee that mappings other than the requested one are
* in any state , other than that these do not violate rules for
* the CPU you have . Do not depend on any effects on other mappings ,
* CPUs other than the one you have may have more relaxed rules .
* The caller is required to take care of these .
*/
x86: a new API for drivers/etc to control cache and other page attributes
Right now, if drivers or other code want to change, say, a cache attribute of a
page, the only API they have is change_page_attr(). c-p-a is a really bad API
for this, because it forces the caller to know *ALL* the attributes he wants
for the page, not just the 1 thing he wants to change. So code that wants to
set a page uncachable, needs to be aware of the NX status as well etc etc etc.
This patch introduces a set of new APIs for this, set_pages_<attr> and
set_memory_<attr>, that offer a logical change to the user, and leave all
attributes not implied by the requested logical change alone.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2008-01-30 13:34:06 +01:00
2008-03-18 17:00:18 -07:00
int _set_memory_uc ( unsigned long addr , int numpages ) ;
2008-03-18 17:00:23 -07:00
int _set_memory_wc ( unsigned long addr , int numpages ) ;
2008-03-18 17:00:18 -07:00
int _set_memory_wb ( unsigned long addr , int numpages ) ;
x86: a new API for drivers/etc to control cache and other page attributes
Right now, if drivers or other code want to change, say, a cache attribute of a
page, the only API they have is change_page_attr(). c-p-a is a really bad API
for this, because it forces the caller to know *ALL* the attributes he wants
for the page, not just the 1 thing he wants to change. So code that wants to
set a page uncachable, needs to be aware of the NX status as well etc etc etc.
This patch introduces a set of new APIs for this, set_pages_<attr> and
set_memory_<attr>, that offer a logical change to the user, and leave all
attributes not implied by the requested logical change alone.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2008-01-30 13:34:06 +01:00
int set_memory_uc ( unsigned long addr , int numpages ) ;
2008-03-18 17:00:23 -07:00
int set_memory_wc ( unsigned long addr , int numpages ) ;
x86: a new API for drivers/etc to control cache and other page attributes
Right now, if drivers or other code want to change, say, a cache attribute of a
page, the only API they have is change_page_attr(). c-p-a is a really bad API
for this, because it forces the caller to know *ALL* the attributes he wants
for the page, not just the 1 thing he wants to change. So code that wants to
set a page uncachable, needs to be aware of the NX status as well etc etc etc.
This patch introduces a set of new APIs for this, set_pages_<attr> and
set_memory_<attr>, that offer a logical change to the user, and leave all
attributes not implied by the requested logical change alone.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2008-01-30 13:34:06 +01:00
int set_memory_wb ( unsigned long addr , int numpages ) ;
int set_memory_x ( unsigned long addr , int numpages ) ;
int set_memory_nx ( unsigned long addr , int numpages ) ;
int set_memory_ro ( unsigned long addr , int numpages ) ;
int set_memory_rw ( unsigned long addr , int numpages ) ;
2008-01-30 13:34:07 +01:00
int set_memory_np ( unsigned long addr , int numpages ) ;
2008-03-12 03:53:29 +01:00
int set_memory_4k ( unsigned long addr , int numpages ) ;
x86: a new API for drivers/etc to control cache and other page attributes
Right now, if drivers or other code want to change, say, a cache attribute of a
page, the only API they have is change_page_attr(). c-p-a is a really bad API
for this, because it forces the caller to know *ALL* the attributes he wants
for the page, not just the 1 thing he wants to change. So code that wants to
set a page uncachable, needs to be aware of the NX status as well etc etc etc.
This patch introduces a set of new APIs for this, set_pages_<attr> and
set_memory_<attr>, that offer a logical change to the user, and leave all
attributes not implied by the requested logical change alone.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2008-01-30 13:34:06 +01:00
2008-08-21 10:46:06 +08:00
int set_memory_array_uc ( unsigned long * addr , int addrinarray ) ;
2010-04-01 12:45:01 +00:00
int set_memory_array_wc ( unsigned long * addr , int addrinarray ) ;
2008-08-21 10:46:06 +08:00
int set_memory_array_wb ( unsigned long * addr , int addrinarray ) ;
2009-03-19 14:51:15 -07:00
int set_pages_array_uc ( struct page * * pages , int addrinarray ) ;
2010-04-01 12:45:01 +00:00
int set_pages_array_wc ( struct page * * pages , int addrinarray ) ;
2009-03-19 14:51:15 -07:00
int set_pages_array_wb ( struct page * * pages , int addrinarray ) ;
2008-04-17 17:41:31 +02:00
/*
* For legacy compatibility with the old APIs , a few functions
* are provided that work on a " struct page " .
* These functions operate ONLY on the 1 : 1 kernel mapping of the
* memory that the struct page represents , and internally just
* call the set_memory_ * function . See the description of the
* set_memory_ * function for more details on conventions .
*
* These APIs should be considered * deprecated * and are likely going to
* be removed in the future .
* The reason for this is the implicit operation on the 1 : 1 mapping only ,
* making this not a generally useful API .
*
* Specifically , many users of the old APIs had a virtual address ,
* called virt_to_page ( ) or vmalloc_to_page ( ) on that address to
* get a struct page * that the old API required .
* To convert these cases , use set_memory_ * ( ) on the original
* virtual address , do not use these functions .
*/
int set_pages_uc ( struct page * page , int numpages ) ;
int set_pages_wb ( struct page * page , int numpages ) ;
int set_pages_x ( struct page * page , int numpages ) ;
int set_pages_nx ( struct page * page , int numpages ) ;
int set_pages_ro ( struct page * page , int numpages ) ;
int set_pages_rw ( struct page * page , int numpages ) ;
2008-01-30 13:34:09 +01:00
void clflush_cache_range ( void * addr , unsigned int size ) ;
2007-10-15 23:28:20 +02:00
# ifdef CONFIG_DEBUG_RODATA
void mark_rodata_ro ( void ) ;
2008-02-12 12:12:01 -08:00
extern const int rodata_test_data ;
2009-10-28 18:46:56 -08:00
extern int kernel_set_to_readonly ;
2009-02-17 17:57:30 -05:00
void set_kernel_text_rw ( void ) ;
void set_kernel_text_ro ( void ) ;
# else
static inline void set_kernel_text_rw ( void ) { }
static inline void set_kernel_text_ro ( void ) { }
2007-10-15 23:28:20 +02:00
# endif
2008-02-12 12:12:01 -08:00
2008-01-30 13:34:08 +01:00
# ifdef CONFIG_DEBUG_RODATA_TEST
2008-02-12 12:12:01 -08:00
int rodata_test ( void ) ;
2008-01-30 13:34:08 +01:00
# else
2008-02-12 12:12:01 -08:00
static inline int rodata_test ( void )
2008-01-30 13:34:08 +01:00
{
2008-02-12 12:12:01 -08:00
return 0 ;
2008-01-30 13:34:08 +01:00
}
# endif
2007-10-15 23:28:20 +02:00
2008-10-22 22:26:29 -07:00
# endif /* _ASM_X86_CACHEFLUSH_H */