From nobody Mon Feb 9 03:12:42 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=reject dis=none) header.from=citrix.com ARC-Seal: i=1; a=rsa-sha256; t=1642444534; cv=none; d=zohomail.com; s=zohoarc; b=eWqk39wCBsHZSzgEseHnyO3Re/O8JA+krVnEGhFC0jyCWShX/pIN/hDFo+s5q5XnRA4Tr4i85nyU0KCd6nuFj9gW68wpbq6ejVpUA1oodJ/Uaf1z9SLwUkxCcuSUnw7t5hVOrBQ1fWeoq96w2RbdhdXslSMjtI4+rO4cpOp0c4Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1642444534; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=lTU0CHBSbm+x+z2KbVNHBzvljr5mvGY1ry4zA5guRog=; b=ObbjKVecUT+JSzHs/4W05ciOZGtZwPG+SLjv2iZYn6q07Wk2lwpsHLhmM7RS88OuxHKHbfR+w8dvv1fkQpscgJRxTT5XpesufdMlVjGjETi6AwQ4qfXP+vRHsCdt3fkHAC4a82QXMAl8vYDcj1WkD4saKwmM5+5jYCcPUrViSsM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1642444534760495.05881162456205; Mon, 17 Jan 2022 10:35:34 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.258222.444460 (Exim 4.92) (envelope-from ) id 1n9Wq9-0004gb-GH; Mon, 17 Jan 2022 18:34:49 +0000 Received: by outflank-mailman (output) from mailman id 258222.444460; Mon, 17 Jan 2022 18:34:49 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1n9Wq9-0004gU-Cf; Mon, 17 Jan 2022 18:34:49 +0000 Received: by outflank-mailman (input) for mailman id 258222; Mon, 17 Jan 2022 18:34:47 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1n9Wq7-0004g5-D6 for xen-devel@lists.xenproject.org; Mon, 17 Jan 2022 18:34:47 +0000 Received: from esa6.hc3370-68.iphmx.com (esa6.hc3370-68.iphmx.com [216.71.155.175]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 22e155d3-77c4-11ec-a115-11989b9578b4; Mon, 17 Jan 2022 19:34:44 +0100 (CET) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 22e155d3-77c4-11ec-a115-11989b9578b4 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1642444484; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=HJvhAnanEqe+CxbLx0yf9TQAJKilHOHk3YDJCg2zxCg=; b=Hwgxf5jvdJQqp5UDJ/WmQLlr+AZyV1nTr/S1K0Nv4nmKKXdf9ixNNhaH NjKyaHwBcwdwYeP555X9ShyiGtWYLBq8xZUZwRFbn79SlqLQYS2nxWOy+ mcki+/AK/81pZZgArcq4v3Ruf6PxTYK9Zri7vitLU2KmXDMtf1e93V/0f o=; Authentication-Results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none IronPort-SDR: TB2XcwXV2wc3RobzdhHqcIalrDSepoqgFBepUAmWtUovaWdo/iWfmCLvgM4YxjqM1r1wpjFGjP N5VVoPLRuzr7/KXgPlnutWFLCRi/QMPdgh0HFja9X96JD06gy3lqJkBKVcrX5hTgEN5QuCDkld qgZGIsSjUAAG9m26+dQY66lm20cbmZfL3UEZy2jab/oz6Jo3v/ApaKBlObEfgrySTWZUZ51xeC sjHOch7sez0ykeit8OTNl+StdjXBhpI7iiJmZkxcoYI2jNaK2+7Yj+sO6ePnp2a4ZCHM2EdNr+ VuJ5+rgUlHSUBiMOtoaOBHcD X-SBRS: 5.2 X-MesageID: 62085888 X-Ironport-Server: esa6.hc3370-68.iphmx.com X-Remote-IP: 162.221.156.83 X-Policy: $RELAYED IronPort-Data: A9a23:cKW+JK7Wh512NJP8x6kEQwxRtL3AchMFZxGqfqrLsTDasY5as4F+v mJOD2/VO/ffNjb0c9BxaoXg8U1VvpXQyodnSANqrS8xHi5G8cbLO4+Ufxz6V8+wwmwvb67FA +E2MISowBUcFyeEzvuV3zyIQUBUjclkfJKlYAL/En03FV8MpBsJ00o5wbZg29Ew27BVPivW0 T/Mi5yHULOa82Yc3lI8s8pvfzs24ZweEBtB1rAPTagjUG32zhH5P7pGTU2FFFPqQ5E8IwKPb 72rIIdVXI/u10xF5tuNyt4Xe6CRK1LYFVDmZnF+A8BOjvXez8CbP2lS2Pc0MC9qZzu1c99Zk pZTkcSsERoVIYLowtU5UD4CDQZ7MvgTkFPHCSDXXc27ykTHdz3nwul0DVFwNoodkgp1KTgQr 7pCcmlLN03dwbLtqF64YrAEasALBc/nJo4A/FpnyinUF60OSpHfWaTao9Rf2V/cg+gQR66OO ppJOVKDajzue0R0ZgYdFagfp+Clgj7wKCZ1skCa8P9fD2/7k1UqjemF3MDuUt6XQ4NTl0WRp GPD9kz4BA0XMJqUzj/t2nGhmO7J2z/6UYQ6Fbuk+/osi1qWrkQMDDUGWF39puO24mauVtQaJ 0EK9y4Gqakp6FftXtT7Rwe/onOPolgbQdU4O88Q5RyJy6HUyx2EHWVCRTlEAOHKr+dvG2Zsj AXQ2Yq0W3o/69V5VE5x6J/O7i2WYTRNMFMdSgtefC8GxIP9h4Q820enoslYLIa5idj8GDfVy j+MrTQji7h7sfPnx5lX7nic3Wvy+8Ghohodo1yOAzn7tl8RiJuNPtTwsTDmAeB8wJF1p7Vrl FwNgICg4e8HFvlhfwTdEbxWTNlFCxtoWQAwYGKD/bF8rVxBGFb5JOi8BQ2Swm8zaK7onhezM SfuVft5vsM7AZdTRfYfj3iNI8or17P8Mt/uS+rZaNFDCrAoKlPdp3w+Ph7Mgz69+KTJrU3ZE c3GGSpLJSxLYZmLMRLsH7tNuVPV7n1WKZzvqWDTkE38jOv2iI+9QrYZKlqeBt3VH4vfyDg5B +13bpPQoz0GCbWWSnCOreY7cA5WRVBmW8Geg5EHJ4arf1s9cEl8WqC5/F/UU9E/90ijvr2Wr ijVt44x4AeXuEAr3i3ROy8zM+2+DM8vxZ/5VAR1VWuVN7EYSd7HxM8im1EfJ9HLLcRvkqx5S ecrYcKFDqgdQzjL4W1FP5L8sJZjZFKgggfXZ3ipZz02fphBQQ3V+4C7IluzpXdWVifn59Ejp 7CA1x/ARcZRTQpVE8uLOumkyEm8vCZBlbsqDVfIONRaZG7l7JNud37qlvYyLsxVcUfDyzKW2 hy4GxAdoeWR8YY5/MOQ3fKPrpuzEvs4FU1fRjGJ4bGzPCjc32yi3Y4fD7rYIWGDDDv5ofzwa /9UwvfwNOw8sGxL64csQax2ya8e5sf0o+MIxApTA3iWPU+gDaltIyfa0JAX5LFN3LJQpSC/R lmLpotBIbyMNc7oTAwRKQ4iYrjR3P0YgGCPv/E8IUG87y5r5ruXF05VOkDU2iBaKbJ0NqIjw Psg55FKu1Du1EJyP4bUlD1Q+kSNMmcEAvcuuZwtCYP2jhYmlwNZapvGBy6quJyCZr2g6KXxz uN4UEYau4lh+w== IronPort-HdrOrdr: A9a23:Rau5CaNQvUNKXsBcTvmjsMiBIKoaSvp037Eqv3oedfUzSL3gqy nOpoV86faaslYssR0b9exofZPwJE80lqQFhrX5X43SPzUO0VHAROoJgLcKgQeQfxEWntQtrZ uIGJIeNDSfNzdHZL7BkWuFL+o= X-IronPort-AV: E=Sophos;i="5.88,296,1635220800"; d="scan'208";a="62085888" From: Andrew Cooper To: Xen-devel CC: Andrew Cooper , Jan Beulich , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Wei Liu , Jun Nakajima , Kevin Tian Subject: [PATCH v2 1/4] x86/guest: Introduce {get,set}_reg() infrastructure Date: Mon, 17 Jan 2022 18:34:12 +0000 Message-ID: <20220117183415.11150-2-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20220117183415.11150-1-andrew.cooper3@citrix.com> References: <20220117183415.11150-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @citrix.com) X-ZM-MESSAGEID: 1642444536280100004 Various registers have per-guest-type or per-vendor locations or access requirements. To support their use from common code, provide accessors whi= ch 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 Reviewed-by: Jan Beulich --- CC: Jan Beulich CC: Roger Pau Monn=C3=A9 CC: Wei Liu CC: Jun Nakajima CC: Kevin Tian It is deliberately {get,set}_reg() because in the fullness of time, it will handle more than just MSRs. There's loads of space in the MSR index range which we can reuse for non-MSRs. v2: * New --- xen/arch/x86/hvm/hvm.c | 22 ++++++++++++++++++++++ xen/arch/x86/hvm/svm/svm.c | 30 ++++++++++++++++++++++++++++++ xen/arch/x86/hvm/vmx/vmx.c | 31 +++++++++++++++++++++++++++++++ xen/arch/x86/include/asm/hvm/hvm.h | 24 ++++++++++++++++++++++++ xen/arch/x86/include/asm/pv/domain.h | 13 +++++++++++++ xen/arch/x86/pv/emulate.c | 31 +++++++++++++++++++++++++++++++ 6 files changed, 151 insertions(+) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 3b87506ac4b3..b530e986e86c 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -3744,6 +3744,28 @@ int hvm_msr_write_intercept(unsigned int msr, uint64= _t msr_content, return X86EMUL_EXCEPTION; } =20 +uint64_t hvm_get_reg(struct vcpu *v, unsigned int reg) +{ + ASSERT(v =3D=3D 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 =3D=3D 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) { diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index fae39c4b4cbd..bb6b8e560a9f 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -2469,6 +2469,33 @@ static bool svm_get_pending_event(struct vcpu *v, st= ruct x86_event *info) return true; } =20 +static uint64_t svm_get_reg(struct vcpu *v, unsigned int reg) +{ + struct domain *d =3D 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 =3D 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 =3D { .name =3D "SVM", .cpu_up_prepare =3D svm_cpu_up_prepare, @@ -2518,6 +2545,9 @@ static struct hvm_function_table __initdata svm_funct= ion_table =3D { .nhvm_intr_blocked =3D nsvm_intr_blocked, .nhvm_hap_walk_L1_p2m =3D nsvm_hap_walk_L1_p2m, =20 + .get_reg =3D svm_get_reg, + .set_reg =3D svm_set_reg, + .tsc_scaling =3D { .max_ratio =3D ~TSC_RATIO_RSVD_BITS, }, diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index a7a0d662342a..4ff92ab4e94e 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -2404,6 +2404,33 @@ static int vmtrace_reset(struct vcpu *v) return 0; } =20 +static uint64_t vmx_get_reg(struct vcpu *v, unsigned int reg) +{ + struct domain *d =3D 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 =3D 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 =3D { .name =3D "VMX", .cpu_up_prepare =3D vmx_cpu_up_prepare, @@ -2464,6 +2491,10 @@ static struct hvm_function_table __initdata vmx_func= tion_table =3D { .vmtrace_set_option =3D vmtrace_set_option, .vmtrace_get_option =3D vmtrace_get_option, .vmtrace_reset =3D vmtrace_reset, + + .get_reg =3D vmx_get_reg, + .set_reg =3D vmx_set_reg, + .tsc_scaling =3D { .max_ratio =3D VMX_TSC_MULTIPLIER_MAX, }, diff --git a/xen/arch/x86/include/asm/hvm/hvm.h b/xen/arch/x86/include/asm/= hvm/hvm.h index b26302d9e769..c8b62b514b42 100644 --- a/xen/arch/x86/include/asm/hvm/hvm.h +++ b/xen/arch/x86/include/asm/hvm/hvm.h @@ -223,6 +223,9 @@ struct hvm_function_table { int (*vmtrace_get_option)(struct vcpu *v, uint64_t key, uint64_t *valu= e); int (*vmtrace_reset)(struct vcpu *v); =20 + 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. @@ -730,6 +733,18 @@ static inline int hvm_vmtrace_reset(struct vcpu *v) } =20 /* + * Accessors for registers which have per-guest-type or per-vendor locatio= ns + * (e.g. VMCS, msr load/save lists, VMCB, VMLOAD lazy, etc). + * + * The caller is responsible for all auditing - these accessors do not fai= l, + * 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 * not been defined yet. @@ -852,6 +867,15 @@ static inline int hvm_vmtrace_get_option( return -EOPNOTSUPP; } =20 +static inline uint64_t pv_get_reg(struct vcpu *v, unsigned int reg) +{ + ASSERT_UNREACHABLE(); +} +static inline void pv_set_reg(struct vcpu *v, unsigned int reg, uint64_t v= al) +{ + ASSERT_UNREACHABLE(); +} + #define is_viridian_domain(d) ((void)(d), false) #define is_viridian_vcpu(v) ((void)(v), false) #define has_viridian_time_ref_count(d) ((void)(d), false) diff --git a/xen/arch/x86/include/asm/pv/domain.h b/xen/arch/x86/include/as= m/pv/domain.h index df9716ff26a8..5fbf4043e0d9 100644 --- a/xen/arch/x86/include/asm/pv/domain.h +++ b/xen/arch/x86/include/asm/pv/domain.h @@ -72,6 +72,10 @@ int pv_vcpu_initialise(struct vcpu *v); void pv_domain_destroy(struct domain *d); int pv_domain_initialise(struct domain *d); =20 +/* 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); + /* * Bits which a PV guest can toggle in its view of cr4. Some are loaded i= nto * hardware, while some are fully emulated. @@ -100,6 +104,15 @@ static inline int pv_vcpu_initialise(struct vcpu *v) {= return -EOPNOTSUPP; } static inline void pv_domain_destroy(struct domain *d) {} static inline int pv_domain_initialise(struct domain *d) { return -EOPNOTS= UPP; } =20 +static inline uint64_t pv_get_reg(struct vcpu *v, unsigned int reg) +{ + ASSERT_UNREACHABLE(); +} +static inline void pv_set_reg(struct vcpu *v, unsigned int reg, uint64_t v= al) +{ + ASSERT_UNREACHABLE(); +} + static inline unsigned long pv_make_cr4(const struct vcpu *v) { return ~0u= l; } =20 #endif /* CONFIG_PV */ diff --git a/xen/arch/x86/pv/emulate.c b/xen/arch/x86/pv/emulate.c index e8bb326efdfe..ae049b60f2fc 100644 --- a/xen/arch/x86/pv/emulate.c +++ b/xen/arch/x86/pv/emulate.c @@ -90,6 +90,37 @@ void pv_emul_instruction_done(struct cpu_user_regs *regs= , unsigned long rip) } } =20 +uint64_t pv_get_reg(struct vcpu *v, unsigned int reg) +{ + struct domain *d =3D v->domain; + + ASSERT(v =3D=3D 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 =3D v->domain; + + ASSERT(v =3D=3D 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 --=20 2.11.0