[PATCH 4/7] target/arm/hvf: Add KVMID_TO_HVF, HVF_TO_KVMID

Richard Henderson posted 7 patches 2 months, 4 weeks ago
Maintainers: Peter Maydell <peter.maydell@linaro.org>, Alexander Graf <agraf@csgraf.de>, Mads Ynddal <mads@ynddal.dk>, Paolo Bonzini <pbonzini@redhat.com>
[PATCH 4/7] target/arm/hvf: Add KVMID_TO_HVF, HVF_TO_KVMID
Posted by Richard Henderson 2 months, 4 weeks ago
Conversion between KVM system registers ids and the HVF system
register ids is trivial.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/hvf/hvf.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index f0e4b75e6a..2577dc1c0c 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -403,6 +403,26 @@ struct hvf_sreg_match {
     uint32_t cp_idx;
 };
 
+/*
+ * QEMU uses KVM system register ids in the migration format.
+ * Conveniently, HVF uses the same encoding of the op* and cr* parameters
+ * within the low 16 bits of the ids.  Thus conversion between the
+ * formats is trivial.
+ */
+
+#define KVMID_TO_HVF(KVM)  ((KVM) & 0xffff)
+#define HVF_TO_KVMID(HVF)  \
+    (CP_REG_ARM64 | CP_REG_SIZE_U64 | CP_REG_ARM64_SYSREG | (HVF))
+
+/* Verify this at compile-time. */
+
+#define DEF_SYSREG(HVF_ID, ...) \
+  QEMU_BUILD_BUG_ON(HVF_ID != KVMID_TO_HVF(KVMID_AA64_SYS_REG64(__VA_ARGS__)));
+
+#include "sysreg.c.inc"
+
+#undef DEF_SYSREG
+
 #define DEF_SYSREG(HVF_ID, crn, crm, op0, op1, op2) \
     { HVF_ID, HVF_SYSREG(crn, crm, op0, op1, op2) },
 
-- 
2.43.0
Re: [PATCH 4/7] target/arm/hvf: Add KVMID_TO_HVF, HVF_TO_KVMID
Posted by Philippe Mathieu-Daudé 2 months, 4 weeks ago
On 18/8/25 06:13, Richard Henderson wrote:
> Conversion between KVM system registers ids and the HVF system
> register ids is trivial.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   target/arm/hvf/hvf.c | 20 ++++++++++++++++++++
>   1 file changed, 20 insertions(+)
> 
> diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
> index f0e4b75e6a..2577dc1c0c 100644
> --- a/target/arm/hvf/hvf.c
> +++ b/target/arm/hvf/hvf.c
> @@ -403,6 +403,26 @@ struct hvf_sreg_match {
>       uint32_t cp_idx;
>   };
>   
> +/*
> + * QEMU uses KVM system register ids in the migration format.
> + * Conveniently, HVF uses the same encoding of the op* and cr* parameters
> + * within the low 16 bits of the ids.  Thus conversion between the
> + * formats is trivial.
> + */
> +
> +#define KVMID_TO_HVF(KVM)  ((KVM) & 0xffff)
> +#define HVF_TO_KVMID(HVF)  \
> +    (CP_REG_ARM64 | CP_REG_SIZE_U64 | CP_REG_ARM64_SYSREG | (HVF))
> +
> +/* Verify this at compile-time. */
> +
> +#define DEF_SYSREG(HVF_ID, ...) \
> +  QEMU_BUILD_BUG_ON(HVF_ID != KVMID_TO_HVF(KVMID_AA64_SYS_REG64(__VA_ARGS__)));

Rebasing Mohamed's work I'm getting:

In file included from ../../target/arm/hvf/hvf.c:413:
../../target/arm/hvf/sysreg.c.inc:156:1: error: static assertion failed 
due to requirement '!(HV_SYS_REG_MDCR_EL2 != (((((1 << 28) | (19 << 16) 
| ((3) << 14) | ((4) << 11) | ((1) << 7) | ((1) << 3) | ((1) << 0)) | 
13510798882111488ULL)) & 65535))': not expecting: HV_SYS_REG_MDCR_EL2 != 
KVMID_TO_HVF(KVMID_AA64_SYS_REG64(1, 1, 3, 4, 1))
   156 | DEF_SYSREG(HV_SYS_REG_MDCR_EL2, 1, 1, 3, 4, 1)
       | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Having in <Hypervisor.h> -> <Hypervisor/hv_vcpu_types.h>:
     // Exception Level 2 (EL2) registers.
     // These registers are only available if EL2 was enabled in the VM 
configuration.
     HV_SYS_REG_CNTHCTL_EL2 = 0xe708,
     HV_SYS_REG_CNTHP_CTL_EL2 = 0xe711,
     HV_SYS_REG_CNTHP_CVAL_EL2 = 0xe712,
     HV_SYS_REG_CNTHP_TVAL_EL2 = 0xe710,
     HV_SYS_REG_CNTVOFF_EL2 = 0xe703,
     HV_SYS_REG_CPTR_EL2 = 0xe08a,
     HV_SYS_REG_ELR_EL2 = 0xe201,
     HV_SYS_REG_ESR_EL2 = 0xe290,
     HV_SYS_REG_FAR_EL2 = 0xe300,
     HV_SYS_REG_HCR_EL2 = 0xe088,
     HV_SYS_REG_HPFAR_EL2 = 0xe304,
     HV_SYS_REG_MAIR_EL2 = 0xe510,
     HV_SYS_REG_MDCR_EL2 = 0xe019,   <----
     HV_SYS_REG_SCTLR_EL2 = 0xe080,
     HV_SYS_REG_SPSR_EL2 = 0xe200,
     HV_SYS_REG_SP_EL2 = 0xf208,
     HV_SYS_REG_TCR_EL2 = 0xe102,
     HV_SYS_REG_TPIDR_EL2 = 0xe682,
     HV_SYS_REG_TTBR0_EL2 = 0xe100,
     HV_SYS_REG_TTBR1_EL2 = 0xe101,
     HV_SYS_REG_VBAR_EL2 = 0xe600,
     HV_SYS_REG_VMPIDR_EL2 = 0xe005,
     HV_SYS_REG_VPIDR_EL2 = 0xe000,
     HV_SYS_REG_VTCR_EL2 = 0xe10a,
     HV_SYS_REG_VTTBR_EL2 = 0xe108,

> +
> +#include "sysreg.c.inc"
> +
> +#undef DEF_SYSREG
> +
>   #define DEF_SYSREG(HVF_ID, crn, crm, op0, op1, op2) \
>       { HVF_ID, HVF_SYSREG(crn, crm, op0, op1, op2) },
>
Re: [PATCH 4/7] target/arm/hvf: Add KVMID_TO_HVF, HVF_TO_KVMID
Posted by Richard Henderson 2 months, 4 weeks ago
On 8/18/25 22:41, Philippe Mathieu-Daudé wrote:
> Rebasing Mohamed's work I'm getting:
> 
> In file included from ../../target/arm/hvf/hvf.c:413:
> ../../target/arm/hvf/sysreg.c.inc:156:1: error: static assertion failed due to requirement 
> '!(HV_SYS_REG_MDCR_EL2 != (((((1 << 28) | (19 << 16) | ((3) << 14) | ((4) << 11) | ((1) << 
> 7) | ((1) << 3) | ((1) << 0)) | 13510798882111488ULL)) & 65535))': not expecting: 
> HV_SYS_REG_MDCR_EL2 != KVMID_TO_HVF(KVMID_AA64_SYS_REG64(1, 1, 3, 4, 1))
>    156 | DEF_SYSREG(HV_SYS_REG_MDCR_EL2, 1, 1, 3, 4, 1)
>        | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


>      HV_SYS_REG_MDCR_EL2 = 0xe019,   <----

How odd.  It should be e089, if it were encoded like all the others.

I wonder if this is a manual typo that's now baked into the api, or if it's an OS bug.


r~


Re: [PATCH 4/7] target/arm/hvf: Add KVMID_TO_HVF, HVF_TO_KVMID
Posted by Philippe Mathieu-Daudé 2 months, 4 weeks ago
Cc'ing Apple folks hoping they can forward or directly help :)

On 18/8/25 15:21, Richard Henderson wrote:
> On 8/18/25 22:41, Philippe Mathieu-Daudé wrote:
>> Rebasing Mohamed's work I'm getting:
>>
>> In file included from ../../target/arm/hvf/hvf.c:413:
>> ../../target/arm/hvf/sysreg.c.inc:156:1: error: static assertion 
>> failed due to requirement '!(HV_SYS_REG_MDCR_EL2 != (((((1 << 28) | 
>> (19 << 16) | ((3) << 14) | ((4) << 11) | ((1) << 7) | ((1) << 3) | 
>> ((1) << 0)) | 13510798882111488ULL)) & 65535))': not expecting: 
>> HV_SYS_REG_MDCR_EL2 != KVMID_TO_HVF(KVMID_AA64_SYS_REG64(1, 1, 3, 4, 1))
>>    156 | DEF_SYSREG(HV_SYS_REG_MDCR_EL2, 1, 1, 3, 4, 1)
>>        | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 
> 
>>      HV_SYS_REG_MDCR_EL2 = 0xe019,   <----
> 
> How odd.  It should be e089, if it were encoded like all the others.
> 
> I wonder if this is a manual typo that's now baked into the api, or if 
> it's an OS bug.
> 
> 
> r~
> 


Re: [PATCH 4/7] target/arm/hvf: Add KVMID_TO_HVF, HVF_TO_KVMID
Posted by Danny Canter 2 months, 4 weeks ago
Howdy,

On macOS versions/SDKs before 26 you are correct, we had an invalid enum value for HV_SYS_REG_MDCR_EL2 in the API, but the hv_vcpu_get/set_sys_reg APIs work with this value even though the
encoding is incorrect. The enum value has been remedied in 26+ (0xe089 as you pointed out) and has been done in a backwards compatible way internally in the framework.


> On Aug 18, 2025, at 8:46 AM, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
> 
> Cc'ing Apple folks hoping they can forward or directly help :)
> 
> On 18/8/25 15:21, Richard Henderson wrote:
>> On 8/18/25 22:41, Philippe Mathieu-Daudé wrote:
>>> Rebasing Mohamed's work I'm getting:
>>> 
>>> In file included from ../../target/arm/hvf/hvf.c:413:
>>> ../../target/arm/hvf/sysreg.c.inc:156:1: error: static assertion failed due to requirement '!(HV_SYS_REG_MDCR_EL2 != (((((1 << 28) | (19 << 16) | ((3) << 14) | ((4) << 11) | ((1) << 7) | ((1) << 3) | ((1) << 0)) | 13510798882111488ULL)) & 65535))': not expecting: HV_SYS_REG_MDCR_EL2 != KVMID_TO_HVF(KVMID_AA64_SYS_REG64(1, 1, 3, 4, 1))
>>>    156 | DEF_SYSREG(HV_SYS_REG_MDCR_EL2, 1, 1, 3, 4, 1)
>>>        | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>      HV_SYS_REG_MDCR_EL2 = 0xe019,   <----
>> How odd.  It should be e089, if it were encoded like all the others.
>> I wonder if this is a manual typo that's now baked into the api, or if it's an OS bug.
>> r~
> 

Re: [PATCH 4/7] target/arm/hvf: Add KVMID_TO_HVF, HVF_TO_KVMID
Posted by Philippe Mathieu-Daudé 2 months, 2 weeks ago
On 18/8/25 20:37, Danny Canter wrote:
> Howdy,
> 
> On macOS versions/SDKs before 26 you are correct, we had an invalid enum 
> value for HV_SYS_REG_MDCR_EL2 in the API, but the hv_vcpu_get/ 
> set_sys_reg APIs work with this value even though the
> encoding is incorrect. The enum value has been remedied in 26+ (0xe089 
> as you pointed out) and has been done in a backwards compatible way 
> internally in the framework.

Thanks Danny!

Richard, should we guard the QEMU_BUILD_BUG_ON() macro with:

   #if defined(MAC_OS_VERSION_26_0) && \
       MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_26_0

?

> 
>> On Aug 18, 2025, at 8:46 AM, Philippe Mathieu-Daudé 
>> <philmd@linaro.org> wrote:
>>
>> Cc'ing Apple folks hoping they can forward or directly help :)
>>
>> On 18/8/25 15:21, Richard Henderson wrote:
>>> On 8/18/25 22:41, Philippe Mathieu-Daudé wrote:
>>>> Rebasing Mohamed's work I'm getting:
>>>>
>>>> In file included from ../../target/arm/hvf/hvf.c:413:
>>>> ../../target/arm/hvf/sysreg.c.inc:156:1: error: static assertion 
>>>> failed due to requirement '!(HV_SYS_REG_MDCR_EL2 != (((((1 << 28) | 
>>>> (19 << 16) | ((3) << 14) | ((4) << 11) | ((1) << 7) | ((1) << 3) | 
>>>> ((1) << 0)) | 13510798882111488ULL)) & 65535))': not expecting: 
>>>> HV_SYS_REG_MDCR_EL2 != KVMID_TO_HVF(KVMID_AA64_SYS_REG64(1, 1, 3, 4, 1))
>>>>    156 | DEF_SYSREG(HV_SYS_REG_MDCR_EL2, 1, 1, 3, 4, 1)
>>>>        | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>>      HV_SYS_REG_MDCR_EL2 = 0xe019,   <----
>>> How odd.  It should be e089, if it were encoded like all the others.
>>> I wonder if this is a manual typo that's now baked into the api, or 
>>> if it's an OS bug.
>>> r~
>>
> 


Re: [PATCH 4/7] target/arm/hvf: Add KVMID_TO_HVF, HVF_TO_KVMID
Posted by Richard Henderson 2 months, 1 week ago
On 9/1/25 01:02, Philippe Mathieu-Daudé wrote:
> On 18/8/25 20:37, Danny Canter wrote:
>> Howdy,
>>
>> On macOS versions/SDKs before 26 you are correct, we had an invalid enum value for 
>> HV_SYS_REG_MDCR_EL2 in the API, but the hv_vcpu_get/ set_sys_reg APIs work with this 
>> value even though the
>> encoding is incorrect. The enum value has been remedied in 26+ (0xe089 as you pointed 
>> out) and has been done in a backwards compatible way internally in the framework.
> 
> Thanks Danny!
> 
> Richard, should we guard the QEMU_BUILD_BUG_ON() macro with:
> 
>    #if defined(MAC_OS_VERSION_26_0) && \
>        MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_26_0
> 
> ?

That's one possibility.  Another is to remap the one broken enum, since this fix is 
described to be backward compatible.


r~