Commit d300b016 authored by Oliver Upton's avatar Oliver Upton
Browse files

Merge branch 'kvm-arm64/pv-cpuid' into kvmarm/next



* kvm-arm64/pv-cpuid:
  : Paravirtualized implementation ID, courtesy of Shameer Kolothum
  :
  : Big-little has historically been a pain in the ass to virtualize. The
  : implementation ID (MIDR, REVIDR, AIDR) of a vCPU can change at the whim
  : of vCPU scheduling. This can be particularly annoying when the guest
  : needs to know the underlying implementation to mitigate errata.
  :
  : "Hyperscalers" face a similar scheduling problem, where VMs may freely
  : migrate between hosts in a pool of heterogenous hardware. And yes, our
  : server-class friends are equally riddled with errata too.
  :
  : In absence of an architected solution to this wart on the ecosystem,
  : introduce support for paravirtualizing the implementation exposed
  : to a VM, allowing the VMM to describe the pool of implementations that a
  : VM may be exposed to due to scheduling/migration.
  :
  : Userspace is expected to intercept and handle these hypercalls using the
  : SMCCC filter UAPI, should it choose to do so.
  smccc: kvm_guest: Fix kernel builds for 32 bit arm
  KVM: selftests: Add test for KVM_REG_ARM_VENDOR_HYP_BMAP_2
  smccc/kvm_guest: Enable errata based on implementation CPUs
  arm64: Make  _midr_in_range_list() an exported function
  KVM: arm64: Introduce KVM_REG_ARM_VENDOR_HYP_BMAP_2
  KVM: arm64: Specify hypercall ABI for retrieving target implementations
  arm64: Modify _midr_range() functions to read MIDR/REVIDR internally

Signed-off-by: default avatarOliver Upton <oliver.upton@linux.dev>
parents 13f64f6d 44ff44ca
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -116,7 +116,7 @@ The pseudo-firmware bitmap register are as follows:
      ARM DEN0057A.

* KVM_REG_ARM_VENDOR_HYP_BMAP:
    Controls the bitmap of the Vendor specific Hypervisor Service Calls.
    Controls the bitmap of the Vendor specific Hypervisor Service Calls[0-63].

  The following bits are accepted:

@@ -127,6 +127,19 @@ The pseudo-firmware bitmap register are as follows:
    Bit-1: KVM_REG_ARM_VENDOR_HYP_BIT_PTP:
      The bit represents the Precision Time Protocol KVM service.

* KVM_REG_ARM_VENDOR_HYP_BMAP_2:
    Controls the bitmap of the Vendor specific Hypervisor Service Calls[64-127].

  The following bits are accepted:

    Bit-0: KVM_REG_ARM_VENDOR_HYP_BIT_DISCOVER_IMPL_VER
      This represents the ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID
      function-id. This is reset to 0.

    Bit-1: KVM_REG_ARM_VENDOR_HYP_BIT_DISCOVER_IMPL_CPUS
      This represents the ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID
      function-id. This is reset to 0.

Errors:

    =======  =============================================================
+59 −0
Original line number Diff line number Diff line
@@ -142,3 +142,62 @@ region is equal to the memory protection granule advertised by
|                     |          |    +---------------------------------------------+
|                     |          |    | ``INVALID_PARAMETER (-3)``                  |
+---------------------+----------+----+---------------------------------------------+

``ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID``
-------------------------------------------------------
Request the target CPU implementation version information and the number of target
implementations for the Guest VM.

+---------------------+-------------------------------------------------------------+
| Presence:           | Optional;  KVM/ARM64 Guests only                            |
+---------------------+-------------------------------------------------------------+
| Calling convention: | HVC64                                                       |
+---------------------+----------+--------------------------------------------------+
| Function ID:        | (uint32) | 0xC6000040                                       |
+---------------------+----------+--------------------------------------------------+
| Arguments:          | None                                                        |
+---------------------+----------+----+---------------------------------------------+
| Return Values:      | (int64)  | R0 | ``SUCCESS (0)``                             |
|                     |          |    +---------------------------------------------+
|                     |          |    | ``NOT_SUPPORTED (-1)``                      |
|                     +----------+----+---------------------------------------------+
|                     | (uint64) | R1 | Bits [63:32] Reserved/Must be zero          |
|                     |          |    +---------------------------------------------+
|                     |          |    | Bits [31:16] Major version                  |
|                     |          |    +---------------------------------------------+
|                     |          |    | Bits [15:0] Minor version                   |
|                     +----------+----+---------------------------------------------+
|                     | (uint64) | R2 | Number of target implementations            |
|                     +----------+----+---------------------------------------------+
|                     | (uint64) | R3 | Reserved / Must be zero                     |
+---------------------+----------+----+---------------------------------------------+

``ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID``
-------------------------------------------------------

Request the target CPU implementation information for the Guest VM. The Guest kernel
will use this information to enable the associated errata.

+---------------------+-------------------------------------------------------------+
| Presence:           | Optional;  KVM/ARM64 Guests only                            |
+---------------------+-------------------------------------------------------------+
| Calling convention: | HVC64                                                       |
+---------------------+----------+--------------------------------------------------+
| Function ID:        | (uint32) | 0xC6000041                                       |
+---------------------+----------+----+---------------------------------------------+
| Arguments:          | (uint64) | R1 | selected implementation index               |
|                     +----------+----+---------------------------------------------+
|                     | (uint64) | R2 | Reserved / Must be zero                     |
|                     +----------+----+---------------------------------------------+
|                     | (uint64) | R3 | Reserved / Must be zero                     |
+---------------------+----------+----+---------------------------------------------+
| Return Values:      | (int64)  | R0 | ``SUCCESS (0)``                             |
|                     |          |    +---------------------------------------------+
|                     |          |    | ``INVALID_PARAMETER (-3)``                  |
|                     +----------+----+---------------------------------------------+
|                     | (uint64) | R1 | MIDR_EL1 of the selected implementation     |
|                     +----------+----+---------------------------------------------+
|                     | (uint64) | R2 | REVIDR_EL1 of the selected implementation   |
|                     +----------+----+---------------------------------------------+
|                     | (uint64) | R3 | AIDR_EL1  of the selected implementation    |
+---------------------+----------+----+---------------------------------------------+
+17 −23
Original line number Diff line number Diff line
@@ -231,6 +231,16 @@

#define read_cpuid(reg)			read_sysreg_s(SYS_ ## reg)

/*
 * The CPU ID never changes at run time, so we might as well tell the
 * compiler that it's constant.  Use this function to read the CPU ID
 * rather than directly reading processor_id or read_cpuid() directly.
 */
static inline u32 __attribute_const__ read_cpuid_id(void)
{
	return read_cpuid(MIDR_EL1);
}

/*
 * Represent a range of MIDR values for a given CPU model and a
 * range of variant/revision values.
@@ -266,30 +276,14 @@ static inline bool midr_is_cpu_model_range(u32 midr, u32 model, u32 rv_min,
	return _model == model && rv >= rv_min && rv <= rv_max;
}

static inline bool is_midr_in_range(u32 midr, struct midr_range const *range)
{
	return midr_is_cpu_model_range(midr, range->model,
				       range->rv_min, range->rv_max);
}

static inline bool
is_midr_in_range_list(u32 midr, struct midr_range const *ranges)
{
	while (ranges->model)
		if (is_midr_in_range(midr, ranges++))
			return true;
	return false;
}
struct target_impl_cpu {
	u64 midr;
	u64 revidr;
	u64 aidr;
};

/*
 * The CPU ID never changes at run time, so we might as well tell the
 * compiler that it's constant.  Use this function to read the CPU ID
 * rather than directly reading processor_id or read_cpuid() directly.
 */
static inline u32 __attribute_const__ read_cpuid_id(void)
{
	return read_cpuid(MIDR_EL1);
}
bool cpu_errata_set_target_impl(u64 num, void *impl_cpus);
bool is_midr_in_range_list(struct midr_range const *ranges);

static inline u64 __attribute_const__ read_cpuid_mpidr(void)
{
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@

void kvm_init_hyp_services(void);
bool kvm_arm_hyp_service_available(u32 func_id);
void kvm_arm_target_impl_cpu_init(void);

#ifdef CONFIG_ARM_PKVM_GUEST
void pkvm_init_hyp_services(void);
+2 −1
Original line number Diff line number Diff line
@@ -238,7 +238,8 @@ struct kvm_arch_memory_slot {
struct kvm_smccc_features {
	unsigned long std_bmap;
	unsigned long std_hyp_bmap;
	unsigned long vendor_hyp_bmap;
	unsigned long vendor_hyp_bmap; /* Function numbers 0-63 */
	unsigned long vendor_hyp_bmap_2; /* Function numbers 64-127 */
};

typedef unsigned int pkvm_handle_t;
Loading