x86/guest: Introduce {get,set}_reg() infrastructure

Various registers have per-guest-type or per-vendor locations or access
requirements.  To support their use from common code, provide accessors which
allow for per-guest-type behaviour.

For now, just infrastructure handling default cases and expectations.
Subsequent patches will start handling registers using this infrastructure.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: 88d3ff7ab1
master date: 2022-01-20 16:32:11 +0000
This commit is contained in:
Andrew Cooper authored and Jan Beulich committed 2022-01-25 13:52:07 +01:00
1 parent 0f88870898
commit c45c2c2e09
6 files changed
+133

No files matched your search

+22
View File
@@ -3724,6 +3724,28 @@ gp_fault:
return X86EMUL_EXCEPTION;
}
uint64_t hvm_get_reg(struct vcpu *v, unsigned int reg)
{
ASSERT(v == current || !vcpu_runnable(v));
switch ( reg )
{
default:
return alternative_call(hvm_funcs.get_reg, v, reg);
}
}
void hvm_set_reg(struct vcpu *v, unsigned int reg, uint64_t val)
{
ASSERT(v == current || !vcpu_runnable(v));
switch ( reg )
{
default:
return alternative_vcall(hvm_funcs.set_reg, v, reg, val);
}
}
static bool is_sysdesc_access(const struct x86_emulate_state *state,
const struct x86_emulate_ctxt *ctxt)
{
+30
View File
@@ -2415,6 +2415,33 @@ static bool svm_get_pending_event(struct vcpu *v, struct x86_event *info)
return true;
}
static uint64_t svm_get_reg(struct vcpu *v, unsigned int reg)
{
struct domain *d = v->domain;
switch ( reg )
{
default:
printk(XENLOG_G_ERR "%s(%pv, 0x%08x) Bad register\n",
__func__, v, reg);
domain_crash(d);
return 0;
}
}
static void svm_set_reg(struct vcpu *v, unsigned int reg, uint64_t val)
{
struct domain *d = v->domain;
switch ( reg )
{
default:
printk(XENLOG_G_ERR "%s(%pv, 0x%08x, 0x%016"PRIx64") Bad register\n",
__func__, v, reg, val);
domain_crash(d);
}
}
static struct hvm_function_table __initdata svm_function_table = {
.name = "SVM",
.cpu_up_prepare = svm_cpu_up_prepare,
@@ -2464,6 +2491,9 @@ static struct hvm_function_table __initdata svm_function_table = {
.nhvm_intr_blocked = nsvm_intr_blocked,
.nhvm_hap_walk_L1_p2m = nsvm_hap_walk_L1_p2m,
.get_reg = svm_get_reg,
.set_reg = svm_set_reg,
.tsc_scaling = {
.max_ratio = ~TSC_RATIO_RSVD_BITS,
},
+31
View File
@@ -2240,6 +2240,33 @@ static bool vmx_get_pending_event(struct vcpu *v, struct x86_event *info)
return true;
}
static uint64_t vmx_get_reg(struct vcpu *v, unsigned int reg)
{
struct domain *d = v->domain;
switch ( reg )
{
default:
printk(XENLOG_G_ERR "%s(%pv, 0x%08x) Bad register\n",
__func__, v, reg);
domain_crash(d);
return 0;
}
}
static void vmx_set_reg(struct vcpu *v, unsigned int reg, uint64_t val)
{
struct domain *d = v->domain;
switch ( reg )
{
default:
printk(XENLOG_G_ERR "%s(%pv, 0x%08x, 0x%016"PRIx64") Bad register\n",
__func__, v, reg, val);
domain_crash(d);
}
}
static struct hvm_function_table __initdata vmx_function_table = {
.name = "VMX",
.cpu_up_prepare = vmx_cpu_up_prepare,
@@ -2295,6 +2322,10 @@ static struct hvm_function_table __initdata vmx_function_table = {
.altp2m_vcpu_update_vmfunc_ve = vmx_vcpu_update_vmfunc_ve,
.altp2m_vcpu_emulate_ve = vmx_vcpu_emulate_ve,
.altp2m_vcpu_emulate_vmfunc = vmx_vcpu_emulate_vmfunc,
.get_reg = vmx_get_reg,
.set_reg = vmx_set_reg,
.tsc_scaling = {
.max_ratio = VMX_TSC_MULTIPLIER_MAX,
},
+31
View File
@@ -90,6 +90,37 @@ void pv_emul_instruction_done(struct cpu_user_regs *regs, unsigned long rip)
}
}
uint64_t pv_get_reg(struct vcpu *v, unsigned int reg)
{
struct domain *d = v->domain;
ASSERT(v == current || !vcpu_runnable(v));
switch ( reg )
{
default:
printk(XENLOG_G_ERR "%s(%pv, 0x%08x) Bad register\n",
__func__, v, reg);
domain_crash(d);
return 0;
}
}
void pv_set_reg(struct vcpu *v, unsigned int reg, uint64_t val)
{
struct domain *d = v->domain;
ASSERT(v == current || !vcpu_runnable(v));
switch ( reg )
{
default:
printk(XENLOG_G_ERR "%s(%pv, 0x%08x, 0x%016"PRIx64") Bad register\n",
__func__, v, reg, val);
domain_crash(d);
}
}
/*
* Local variables:
* mode: C
+15
View File
@@ -214,6 +214,9 @@ struct hvm_function_table {
bool_t (*altp2m_vcpu_emulate_ve)(struct vcpu *v);
int (*altp2m_vcpu_emulate_vmfunc)(const struct cpu_user_regs *regs);
uint64_t (*get_reg)(struct vcpu *v, unsigned int reg);
void (*set_reg)(struct vcpu *v, unsigned int reg, uint64_t val);
/*
* Parameters and callbacks for hardware-assisted TSC scaling,
* which are valid only when the hardware feature is available.
@@ -655,6 +658,18 @@ static inline bool altp2m_vcpu_emulate_ve(struct vcpu *v)
return false;
}
/*
* Accessors for registers which have per-guest-type or per-vendor locations
* (e.g. VMCS, msr load/save lists, VMCB, VMLOAD lazy, etc).
*
* The caller is responsible for all auditing - these accessors do not fail,
* but do use domain_crash() for usage errors.
*
* Must cope with being called in non-current context.
*/
uint64_t hvm_get_reg(struct vcpu *v, unsigned int reg);
void hvm_set_reg(struct vcpu *v, unsigned int reg, uint64_t val);
/*
* This must be defined as a macro instead of an inline function,
* because it uses 'struct vcpu' and 'struct domain' which have
+4
View File
@@ -65,6 +65,10 @@ static inline unsigned long get_pcid_bits(const struct vcpu *v, bool is_xpti)
#endif
}
/* See hvm_{get,set}_reg() for description. */
uint64_t pv_get_reg(struct vcpu *v, unsigned int reg);
void pv_set_reg(struct vcpu *v, unsigned int reg, uint64_t val);
#ifdef CONFIG_PV
void pv_vcpu_destroy(struct vcpu *v);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.