2005-11-03 15:33:31 +11:00
# ifndef _PSERIES_PLPAR_WRAPPERS_H
# define _PSERIES_PLPAR_WRAPPERS_H
2011-07-22 18:04:33 -04:00
# include <linux/string.h>
2012-10-17 21:30:13 +00:00
# include <linux/irqflags.h>
2011-07-22 18:04:33 -04:00
2005-11-03 15:33:31 +11:00
# include <asm/hvcall.h>
2011-07-22 18:04:33 -04:00
# include <asm/paca.h>
2008-08-16 05:09:33 +10:00
# include <asm/page.h>
2005-11-03 15:33:31 +11:00
2010-04-28 13:39:41 +00:00
/* Get state of physical CPU from query_cpu_stopped */
int smp_query_cpu_stopped ( unsigned int pcpu ) ;
# define QCSS_STOPPED 0
# define QCSS_STOPPING 1
# define QCSS_NOT_STOPPED 2
# define QCSS_HARDWARE_ERROR -1
# define QCSS_HARDWARE_BUSY -2
2005-11-03 15:33:31 +11:00
static inline long poll_pending ( void )
{
2006-07-19 08:01:28 +10:00
return plpar_hcall_norets ( H_POLL_PENDING ) ;
2005-11-03 15:33:31 +11:00
}
2009-10-29 19:22:48 +00:00
static inline u8 get_cede_latency_hint ( void )
{
2012-04-10 16:20:54 +00:00
return get_lppaca ( ) - > cede_latency_hint ;
2009-10-29 19:22:48 +00:00
}
static inline void set_cede_latency_hint ( u8 latency_hint )
{
2012-04-10 16:20:54 +00:00
get_lppaca ( ) - > cede_latency_hint = latency_hint ;
2009-10-29 19:22:48 +00:00
}
2005-11-03 15:33:31 +11:00
static inline long cede_processor ( void )
{
2006-07-19 08:01:28 +10:00
return plpar_hcall_norets ( H_CEDE ) ;
2005-11-03 15:33:31 +11:00
}
2009-10-29 19:22:48 +00:00
static inline long extended_cede_processor ( unsigned long latency_hint )
{
long rc ;
u8 old_latency_hint = get_cede_latency_hint ( ) ;
set_cede_latency_hint ( latency_hint ) ;
2012-10-17 21:30:13 +00:00
2009-10-29 19:22:48 +00:00
rc = cede_processor ( ) ;
2012-10-17 21:30:13 +00:00
# ifdef CONFIG_TRACE_IRQFLAGS
/* Ensure that H_CEDE returns with IRQs on */
if ( WARN_ON ( ! ( mfmsr ( ) & MSR_EE ) ) )
__hard_irq_enable ( ) ;
# endif
2009-10-29 19:22:48 +00:00
set_cede_latency_hint ( old_latency_hint ) ;
return rc ;
}
2005-11-03 19:34:38 +11:00
static inline long vpa_call ( unsigned long flags , unsigned long cpu ,
2005-11-03 15:33:31 +11:00
unsigned long vpa )
{
2005-11-03 19:34:38 +11:00
/* flags are in bits 16-18 (counting from most significant bit) */
flags = flags < < ( 63 - 18 ) ;
return plpar_hcall_norets ( H_REGISTER_VPA , flags , cpu , vpa ) ;
}
2011-07-25 01:46:34 +00:00
static inline long unregister_vpa ( unsigned long cpu )
2005-11-03 19:34:38 +11:00
{
2011-07-25 01:46:34 +00:00
return vpa_call ( 0x5 , cpu , 0 ) ;
2005-11-03 19:34:38 +11:00
}
static inline long register_vpa ( unsigned long cpu , unsigned long vpa )
{
return vpa_call ( 0x1 , cpu , vpa ) ;
2005-11-03 15:33:31 +11:00
}
2011-07-25 01:46:34 +00:00
static inline long unregister_slb_shadow ( unsigned long cpu )
2006-08-07 16:19:19 +10:00
{
2011-07-25 01:46:34 +00:00
return vpa_call ( 0x7 , cpu , 0 ) ;
2006-08-07 16:19:19 +10:00
}
static inline long register_slb_shadow ( unsigned long cpu , unsigned long vpa )
{
return vpa_call ( 0x3 , cpu , vpa ) ;
}
2011-07-25 01:46:32 +00:00
static inline long unregister_dtl ( unsigned long cpu )
2009-03-11 17:55:52 +00:00
{
2011-07-25 01:46:32 +00:00
return vpa_call ( 0x6 , cpu , 0 ) ;
2009-03-11 17:55:52 +00:00
}
static inline long register_dtl ( unsigned long cpu , unsigned long vpa )
{
return vpa_call ( 0x2 , cpu , vpa ) ;
}
2008-07-24 04:29:16 +10:00
static inline long plpar_page_set_loaned ( unsigned long vpa )
{
2008-08-16 05:09:33 +10:00
unsigned long cmo_page_sz = cmo_get_page_size ( ) ;
long rc = 0 ;
int i ;
for ( i = 0 ; ! rc & & i < PAGE_SIZE ; i + = cmo_page_sz )
rc = plpar_hcall_norets ( H_PAGE_INIT , H_PAGE_SET_LOANED , vpa + i , 0 ) ;
for ( i - = cmo_page_sz ; rc & & i ! = 0 ; i - = cmo_page_sz )
plpar_hcall_norets ( H_PAGE_INIT , H_PAGE_SET_ACTIVE ,
vpa + i - cmo_page_sz , 0 ) ;
return rc ;
2008-07-24 04:29:16 +10:00
}
static inline long plpar_page_set_active ( unsigned long vpa )
{
2008-08-16 05:09:33 +10:00
unsigned long cmo_page_sz = cmo_get_page_size ( ) ;
long rc = 0 ;
int i ;
for ( i = 0 ; ! rc & & i < PAGE_SIZE ; i + = cmo_page_sz )
rc = plpar_hcall_norets ( H_PAGE_INIT , H_PAGE_SET_ACTIVE , vpa + i , 0 ) ;
for ( i - = cmo_page_sz ; rc & & i ! = 0 ; i - = cmo_page_sz )
plpar_hcall_norets ( H_PAGE_INIT , H_PAGE_SET_LOANED ,
vpa + i - cmo_page_sz , 0 ) ;
return rc ;
2008-07-24 04:29:16 +10:00
}
2005-11-03 19:34:38 +11:00
extern void vpa_init ( int cpu ) ;
2005-11-03 15:33:31 +11:00
2006-07-19 08:01:28 +10:00
static inline long plpar_pte_enter ( unsigned long flags ,
unsigned long hpte_group , unsigned long hpte_v ,
unsigned long hpte_r , unsigned long * slot )
{
long rc ;
unsigned long retbuf [ PLPAR_HCALL_BUFSIZE ] ;
rc = plpar_hcall ( H_ENTER , retbuf , flags , hpte_group , hpte_v , hpte_r ) ;
* slot = retbuf [ 0 ] ;
return rc ;
}
2005-11-03 15:33:31 +11:00
static inline long plpar_pte_remove ( unsigned long flags , unsigned long ptex ,
unsigned long avpn , unsigned long * old_pteh_ret ,
unsigned long * old_ptel_ret )
{
2006-07-19 08:01:28 +10:00
long rc ;
unsigned long retbuf [ PLPAR_HCALL_BUFSIZE ] ;
rc = plpar_hcall ( H_REMOVE , retbuf , flags , ptex , avpn ) ;
* old_pteh_ret = retbuf [ 0 ] ;
* old_ptel_ret = retbuf [ 1 ] ;
return rc ;
2005-11-03 15:33:31 +11:00
}
2007-03-21 11:21:32 +05:30
/* plpar_pte_remove_raw can be called in real mode. It calls plpar_hcall_raw */
static inline long plpar_pte_remove_raw ( unsigned long flags , unsigned long ptex ,
unsigned long avpn , unsigned long * old_pteh_ret ,
unsigned long * old_ptel_ret )
{
long rc ;
unsigned long retbuf [ PLPAR_HCALL_BUFSIZE ] ;
rc = plpar_hcall_raw ( H_REMOVE , retbuf , flags , ptex , avpn ) ;
* old_pteh_ret = retbuf [ 0 ] ;
* old_ptel_ret = retbuf [ 1 ] ;
return rc ;
}
2005-11-03 15:33:31 +11:00
static inline long plpar_pte_read ( unsigned long flags , unsigned long ptex ,
unsigned long * old_pteh_ret , unsigned long * old_ptel_ret )
{
2006-07-19 08:01:28 +10:00
long rc ;
unsigned long retbuf [ PLPAR_HCALL_BUFSIZE ] ;
rc = plpar_hcall ( H_READ , retbuf , flags , ptex ) ;
* old_pteh_ret = retbuf [ 0 ] ;
* old_ptel_ret = retbuf [ 1 ] ;
return rc ;
2005-11-03 15:33:31 +11:00
}
2007-06-14 15:31:34 +10:00
/* plpar_pte_read_raw can be called in real mode. It calls plpar_hcall_raw */
static inline long plpar_pte_read_raw ( unsigned long flags , unsigned long ptex ,
unsigned long * old_pteh_ret , unsigned long * old_ptel_ret )
{
long rc ;
unsigned long retbuf [ PLPAR_HCALL_BUFSIZE ] ;
rc = plpar_hcall_raw ( H_READ , retbuf , flags , ptex ) ;
* old_pteh_ret = retbuf [ 0 ] ;
* old_ptel_ret = retbuf [ 1 ] ;
return rc ;
}
2010-05-10 20:28:26 +00:00
/*
* plpar_pte_read_4_raw can be called in real mode .
* ptes must be 8 * sizeof ( unsigned long )
*/
static inline long plpar_pte_read_4_raw ( unsigned long flags , unsigned long ptex ,
unsigned long * ptes )
{
long rc ;
unsigned long retbuf [ PLPAR_HCALL9_BUFSIZE ] ;
rc = plpar_hcall9_raw ( H_READ , retbuf , flags | H_READ_4 , ptex ) ;
memcpy ( ptes , retbuf , 8 * sizeof ( unsigned long ) ) ;
return rc ;
}
2005-11-03 15:33:31 +11:00
static inline long plpar_pte_protect ( unsigned long flags , unsigned long ptex ,
unsigned long avpn )
{
return plpar_hcall_norets ( H_PROTECT , flags , ptex , avpn ) ;
}
static inline long plpar_tce_get ( unsigned long liobn , unsigned long ioba ,
unsigned long * tce_ret )
{
2006-07-19 08:01:28 +10:00
long rc ;
unsigned long retbuf [ PLPAR_HCALL_BUFSIZE ] ;
rc = plpar_hcall ( H_GET_TCE , retbuf , liobn , ioba ) ;
* tce_ret = retbuf [ 0 ] ;
return rc ;
2005-11-03 15:33:31 +11:00
}
static inline long plpar_tce_put ( unsigned long liobn , unsigned long ioba ,
unsigned long tceval )
{
return plpar_hcall_norets ( H_PUT_TCE , liobn , ioba , tceval ) ;
}
static inline long plpar_tce_put_indirect ( unsigned long liobn ,
unsigned long ioba , unsigned long page , unsigned long count )
{
return plpar_hcall_norets ( H_PUT_TCE_INDIRECT , liobn , ioba , page , count ) ;
}
static inline long plpar_tce_stuff ( unsigned long liobn , unsigned long ioba ,
unsigned long tceval , unsigned long count )
{
return plpar_hcall_norets ( H_STUFF_TCE , liobn , ioba , tceval , count ) ;
}
static inline long plpar_get_term_char ( unsigned long termno ,
unsigned long * len_ret , char * buf_ret )
{
2006-07-19 08:01:28 +10:00
long rc ;
unsigned long retbuf [ PLPAR_HCALL_BUFSIZE ] ;
2005-11-03 15:33:31 +11:00
unsigned long * lbuf = ( unsigned long * ) buf_ret ; /* TODO: alignment? */
2006-07-19 08:01:28 +10:00
rc = plpar_hcall ( H_GET_TERM_CHAR , retbuf , termno ) ;
* len_ret = retbuf [ 0 ] ;
lbuf [ 0 ] = retbuf [ 1 ] ;
lbuf [ 1 ] = retbuf [ 2 ] ;
return rc ;
2005-11-03 15:33:31 +11:00
}
static inline long plpar_put_term_char ( unsigned long termno , unsigned long len ,
const char * buffer )
{
unsigned long * lbuf = ( unsigned long * ) buffer ; /* TODO: alignment? */
return plpar_hcall_norets ( H_PUT_TERM_CHAR , termno , len , lbuf [ 0 ] ,
lbuf [ 1 ] ) ;
}
2012-11-06 16:15:17 +11:00
/* Set various resource mode parameters */
static inline long plpar_set_mode ( unsigned long mflags , unsigned long resource ,
unsigned long value1 , unsigned long value2 )
{
return plpar_hcall_norets ( H_SET_MODE , mflags , resource , value1 , value2 ) ;
}
2012-11-08 15:57:04 +11:00
/*
* Enable relocation on exceptions on this partition
*
* Note : this call has a partition wide scope and can take a while to complete .
* If it returns H_LONG_BUSY_ * it should be retried periodically until it
* returns H_SUCCESS .
*/
static inline long enable_reloc_on_exceptions ( void )
{
/* mflags = 3: Exceptions at 0xC000000000004000 */
return plpar_set_mode ( 3 , 3 , 0 , 0 ) ;
}
/*
* Disable relocation on exceptions on this partition
*
* Note : this call has a partition wide scope and can take a while to complete .
* If it returns H_LONG_BUSY_ * it should be retried periodically until it
* returns H_SUCCESS .
*/
static inline long disable_reloc_on_exceptions ( void ) {
return plpar_set_mode ( 0 , 3 , 0 , 0 ) ;
}
2005-11-03 15:33:31 +11:00
# endif /* _PSERIES_PLPAR_WRAPPERS_H */