2019-06-03 07:44:50 +02:00
/* SPDX-License-Identifier: GPL-2.0-only */
2012-12-10 16:15:34 +00:00
/*
* Copyright ( C ) 2012 , 2013 - ARM Ltd
* Author : Marc Zyngier < marc . zyngier @ arm . com >
*
* Derived from arch / arm / kvm / coproc . h
* Copyright ( C ) 2012 - Virtual Open Systems and Columbia University
* Authors : Christoffer Dall < c . dall @ virtualopensystems . com >
*/
# ifndef __ARM64_KVM_SYS_REGS_LOCAL_H__
# define __ARM64_KVM_SYS_REGS_LOCAL_H__
struct sys_reg_params {
u8 Op0 ;
u8 Op1 ;
u8 CRn ;
u8 CRm ;
u8 Op2 ;
2015-12-04 15:03:13 +03:00
u64 regval ;
2012-12-10 16:15:34 +00:00
bool is_write ;
} ;
struct sys_reg_desc {
2018-12-04 10:44:22 +00:00
/* Sysreg string for debug */
const char * name ;
2020-10-29 17:09:12 +00:00
enum {
AA32_ZEROHIGH ,
AA32_LO ,
AA32_HI ,
} aarch32_map ;
2012-12-10 16:15:34 +00:00
/* MRS/MSR instruction which accesses it. */
u8 Op0 ;
u8 Op1 ;
u8 CRn ;
u8 CRm ;
u8 Op2 ;
/* Trapped access from guest, if non-NULL. */
bool ( * access ) ( struct kvm_vcpu * ,
2015-12-04 15:03:12 +03:00
struct sys_reg_params * ,
2012-12-10 16:15:34 +00:00
const struct sys_reg_desc * ) ;
/* Initialization for vcpu. */
void ( * reset ) ( struct kvm_vcpu * , const struct sys_reg_desc * ) ;
/* Index into sys_reg[], or 0 if we don't need to save it. */
int reg ;
/* Value (usually reset value) */
u64 val ;
2015-07-07 17:30:00 +01:00
/* Custom get/set_user functions, fallback to generic if NULL */
int ( * get_user ) ( struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
const struct kvm_one_reg * reg , void __user * uaddr ) ;
int ( * set_user ) ( struct kvm_vcpu * vcpu , const struct sys_reg_desc * rd ,
const struct kvm_one_reg * reg , void __user * uaddr ) ;
2018-09-28 14:39:15 +01:00
/* Return mask of REG_* runtime visibility overrides */
unsigned int ( * visibility ) ( const struct kvm_vcpu * vcpu ,
const struct sys_reg_desc * rd ) ;
2012-12-10 16:15:34 +00:00
} ;
2020-11-05 10:10:20 +01:00
# define REG_HIDDEN (1 << 0) /* hidden from userspace and guest */
2020-11-05 10:10:21 +01:00
# define REG_RAZ (1 << 1) /* RAZ from userspace and guest */
2018-09-28 14:39:15 +01:00
2019-12-05 18:06:51 +00:00
static __printf ( 2 , 3 )
inline void print_sys_reg_msg ( const struct sys_reg_params * p ,
char * fmt , . . . )
2012-12-10 16:15:34 +00:00
{
2019-12-05 18:06:51 +00:00
va_list va ;
va_start ( va , fmt ) ;
2012-12-10 16:15:34 +00:00
/* Look, we even formatted it for you to paste into the table! */
2019-12-05 18:06:51 +00:00
kvm_pr_unimpl ( " %pV { Op0(%2u), Op1(%2u), CRn(%2u), CRm(%2u), Op2(%2u), func_%s }, \n " ,
& ( struct va_format ) { fmt , & va } ,
2012-12-10 16:15:34 +00:00
p - > Op0 , p - > Op1 , p - > CRn , p - > CRm , p - > Op2 , p - > is_write ? " write " : " read " ) ;
2019-12-05 18:06:51 +00:00
va_end ( va ) ;
}
static inline void print_sys_reg_instr ( const struct sys_reg_params * p )
{
/* GCC warns on an empty format string */
print_sys_reg_msg ( p , " %s " , " " ) ;
2012-12-10 16:15:34 +00:00
}
static inline bool ignore_write ( struct kvm_vcpu * vcpu ,
const struct sys_reg_params * p )
{
return true ;
}
static inline bool read_zero ( struct kvm_vcpu * vcpu ,
2015-12-04 15:03:12 +03:00
struct sys_reg_params * p )
2012-12-10 16:15:34 +00:00
{
2015-12-04 15:03:13 +03:00
p - > regval = 0 ;
2012-12-10 16:15:34 +00:00
return true ;
}
/* Reset functions */
static inline void reset_unknown ( struct kvm_vcpu * vcpu ,
const struct sys_reg_desc * r )
{
BUG_ON ( ! r - > reg ) ;
BUG_ON ( r - > reg > = NR_SYS_REGS ) ;
2016-03-16 15:38:53 +01:00
__vcpu_sys_reg ( vcpu , r - > reg ) = 0x1de7ec7edbadc0deULL ;
2012-12-10 16:15:34 +00:00
}
static inline void reset_val ( struct kvm_vcpu * vcpu , const struct sys_reg_desc * r )
{
BUG_ON ( ! r - > reg ) ;
BUG_ON ( r - > reg > = NR_SYS_REGS ) ;
2016-03-16 15:38:53 +01:00
__vcpu_sys_reg ( vcpu , r - > reg ) = r - > val ;
2012-12-10 16:15:34 +00:00
}
2020-11-05 10:10:20 +01:00
static inline bool sysreg_hidden ( const struct kvm_vcpu * vcpu ,
const struct sys_reg_desc * r )
2018-09-28 14:39:15 +01:00
{
if ( likely ( ! r - > visibility ) )
return false ;
2020-11-05 10:10:20 +01:00
return r - > visibility ( vcpu , r ) & REG_HIDDEN ;
2018-09-28 14:39:15 +01:00
}
2020-11-05 10:10:21 +01:00
static inline bool sysreg_visible_as_raz ( const struct kvm_vcpu * vcpu ,
const struct sys_reg_desc * r )
{
if ( likely ( ! r - > visibility ) )
return false ;
return r - > visibility ( vcpu , r ) & REG_RAZ ;
}
2012-12-10 16:15:34 +00:00
static inline int cmp_sys_reg ( const struct sys_reg_desc * i1 ,
const struct sys_reg_desc * i2 )
{
BUG_ON ( i1 = = i2 ) ;
if ( ! i1 )
return 1 ;
else if ( ! i2 )
return - 1 ;
if ( i1 - > Op0 ! = i2 - > Op0 )
return i1 - > Op0 - i2 - > Op0 ;
if ( i1 - > Op1 ! = i2 - > Op1 )
return i1 - > Op1 - i2 - > Op1 ;
if ( i1 - > CRn ! = i2 - > CRn )
return i1 - > CRn - i2 - > CRn ;
if ( i1 - > CRm ! = i2 - > CRm )
return i1 - > CRm - i2 - > CRm ;
return i1 - > Op2 - i2 - > Op2 ;
}
2017-01-26 19:50:48 +05:30
const struct sys_reg_desc * find_reg_by_id ( u64 id ,
struct sys_reg_params * params ,
const struct sys_reg_desc table [ ] ,
unsigned int num ) ;
2012-12-10 16:15:34 +00:00
2020-10-29 17:09:12 +00:00
# define AA32(_x) .aarch32_map = AA32_##_x
2012-12-10 16:15:34 +00:00
# define Op0(_x) .Op0 = _x
# define Op1(_x) .Op1 = _x
# define CRn(_x) .CRn = _x
# define CRm(_x) .CRm = _x
# define Op2(_x) .Op2 = _x
2017-01-13 17:25:11 +00:00
# define SYS_DESC(reg) \
2018-12-04 10:44:22 +00:00
. name = # reg , \
2017-01-13 17:25:11 +00:00
Op0 ( sys_reg_Op0 ( reg ) ) , Op1 ( sys_reg_Op1 ( reg ) ) , \
CRn ( sys_reg_CRn ( reg ) ) , CRm ( sys_reg_CRm ( reg ) ) , \
Op2 ( sys_reg_Op2 ( reg ) )
2012-12-10 16:15:34 +00:00
# endif /* __ARM64_KVM_SYS_REGS_LOCAL_H__ */