2007-02-16 12:48:11 +03:00
# include <linux/module.h>
# include <linux/preempt.h>
# include <asm/msr.h>
2009-12-11 20:14:40 +03:00
struct msr * msrs_alloc ( void )
{
struct msr * msrs = NULL ;
msrs = alloc_percpu ( struct msr ) ;
if ( ! msrs ) {
2014-03-09 21:05:23 +04:00
pr_warn ( " %s: error allocating msrs \n " , __func__ ) ;
2009-12-11 20:14:40 +03:00
return NULL ;
}
return msrs ;
}
EXPORT_SYMBOL ( msrs_alloc ) ;
void msrs_free ( struct msr * msrs )
{
free_percpu ( msrs ) ;
}
EXPORT_SYMBOL ( msrs_free ) ;
2014-03-09 21:05:23 +04:00
/**
* Read an MSR with error handling
*
* @ msr : MSR to read
* @ m : value to read into
*
* It returns read data only on success , otherwise it doesn ' t change the output
* argument @ m .
*
*/
int msr_read ( u32 msr , struct msr * m )
{
int err ;
u64 val ;
err = rdmsrl_safe ( msr , & val ) ;
if ( ! err )
m - > q = val ;
return err ;
}
/**
* Write an MSR with error handling
*
* @ msr : MSR to write
* @ m : value to write
*/
int msr_write ( u32 msr , struct msr * m )
{
return wrmsrl_safe ( msr , m - > q ) ;
}
static inline int __flip_bit ( u32 msr , u8 bit , bool set )
{
struct msr m , m1 ;
int err = - EINVAL ;
if ( bit > 63 )
return err ;
err = msr_read ( msr , & m ) ;
if ( err )
return err ;
m1 = m ;
if ( set )
m1 . q | = BIT_64 ( bit ) ;
else
m1 . q & = ~ BIT_64 ( bit ) ;
if ( m1 . q = = m . q )
return 0 ;
2014-05-09 05:29:16 +04:00
err = msr_write ( msr , & m1 ) ;
2014-03-09 21:05:23 +04:00
if ( err )
return err ;
return 1 ;
}
/**
* Set @ bit in a MSR @ msr .
*
* Retval :
* < 0 : An error was encountered .
* = 0 : Bit was already set .
* > 0 : Hardware accepted the MSR write .
*/
int msr_set_bit ( u32 msr , u8 bit )
{
return __flip_bit ( msr , bit , true ) ;
}
/**
* Clear @ bit in a MSR @ msr .
*
* Retval :
* < 0 : An error was encountered .
* = 0 : Bit was already cleared .
* > 0 : Hardware accepted the MSR write .
*/
int msr_clear_bit ( u32 msr , u8 bit )
{
return __flip_bit ( msr , bit , false ) ;
}