Skip to content
  1. Jan 14, 2021
  2. Jan 05, 2021
  3. Dec 31, 2020
  4. Dec 30, 2020
  5. Dec 27, 2020
  6. Dec 24, 2020
    • Alexandru Elisei's avatar
      KVM: arm64: Move double-checked lock to kvm_vgic_map_resources() · 1c91f06d
      Alexandru Elisei authored
      
      
      kvm_vgic_map_resources() is called when a VCPU if first run and it maps all
      the VGIC MMIO regions. To prevent double-initialization, the VGIC uses the
      ready variable to keep track of the state of resources and the global KVM
      mutex to protect against concurrent accesses. After the lock is taken, the
      variable is checked again in case another VCPU took the lock between the
      current VCPU reading ready equals false and taking the lock.
      
      The double-checked lock pattern is spread across four different functions:
      in kvm_vcpu_first_run_init(), in kvm_vgic_map_resource() and in
      vgic_{v2,v3}_map_resources(), which makes it hard to reason about and
      introduces minor code duplication. Consolidate the checks in
      kvm_vgic_map_resources(), where the lock is taken.
      
      No functional change intended.
      
      Signed-off-by: default avatarAlexandru Elisei <alexandru.elisei@arm.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201201150157.223625-4-alexandru.elisei@arm.com
      1c91f06d
    • Alexandru Elisei's avatar
      KVM: arm64: arch_timer: Remove VGIC initialization check · f16570ba
      Alexandru Elisei authored
      
      
      kvm_timer_enable() is called in kvm_vcpu_first_run_init() after
      kvm_vgic_map_resources() if the VGIC wasn't ready. kvm_vgic_map_resources()
      is the only place where kvm->arch.vgic.ready is set to true.
      
      For a v2 VGIC, kvm_vgic_map_resources() will attempt to initialize the VGIC
      and set the initialized flag.
      
      For a v3 VGIC, kvm_vgic_map_resources() will return an error code if the
      VGIC isn't already initialized.
      
      The end result is that if we've reached kvm_timer_enable(), the VGIC is
      initialzed and ready and vgic_initialized() will always be true, so remove
      this check.
      
      Signed-off-by: default avatarAlexandru Elisei <alexandru.elisei@arm.com>
      Reviewed-by: default avatarEric Auger <eric.auger@redhat.com>
      [maz: added comment about vgic initialisation, as suggested by Eric]
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201201150157.223625-3-alexandru.elisei@arm.com
      f16570ba
    • Alexandru Elisei's avatar
      KVM: Documentation: Add arm64 KVM_RUN error codes · 3557ae18
      Alexandru Elisei authored
      
      
      The API documentation states that general error codes are not detailed, but
      errors with specific meanings are. On arm64, KVM_RUN can return error
      numbers with a different meaning than what is described by POSIX or the C99
      standard (as taken from man 3 errno).
      
      Absent from the newly documented error codes is ERANGE which can be
      returned when making a change to the EL2 stage 1 tables if the address is
      larger than the largest supported input address. Assuming no bugs in the
      implementation, that is not possible because the input addresses which are
      mapped are the result of applying the macro kern_hyp_va() on kernel virtual
      addresses.
      
      CC: Paolo Bonzini <pbonzini@redhat.com>
      Signed-off-by: default avatarAlexandru Elisei <alexandru.elisei@arm.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201201150157.223625-2-alexandru.elisei@arm.com
      3557ae18
  7. Dec 22, 2020
  8. Dec 09, 2020
  9. Dec 04, 2020
    • Marc Zyngier's avatar
    • David Brazdil's avatar
      KVM: arm64: Fix EL2 mode availability checks · f19f6644
      David Brazdil authored
      
      
      With protected nVHE hyp code interception host's PSCI SMCs, the host
      starts seeing new CPUs boot in EL1 instead of EL2. The kernel logic
      that keeps track of the boot mode needs to be adjusted.
      
      Add a static key enabled if KVM protected mode initialization is
      successful.
      
      When the key is enabled, is_hyp_mode_available continues to report
      `true` because its users either treat it as a check whether KVM will be
      / was initialized, or whether stub HVCs can be made (eg. hibernate).
      
      is_hyp_mode_mismatched is changed to report `false` when the key is
      enabled. That's because all cores' modes matched at the point of KVM
      init and KVM will not allow cores not present at init to boot. That
      said, the function is never used after KVM is initialized.
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-27-dbrazdil@google.com
      f19f6644
    • David Brazdil's avatar
      KVM: arm64: Trap host SMCs in protected mode · b93c17c4
      David Brazdil authored
      
      
      While protected KVM is installed, start trapping all host SMCs.
      For now these are simply forwarded to EL3, except PSCI
      CPU_ON/CPU_SUSPEND/SYSTEM_SUSPEND which are intercepted and the
      hypervisor installed on newly booted cores.
      
      Create new constant HCR_HOST_NVHE_PROTECTED_FLAGS with the new set of HCR
      flags to use while the nVHE vector is installed when the kernel was
      booted with the protected flag enabled. Switch back to the default HCR
      flags when switching back to the stub vector.
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-26-dbrazdil@google.com
      b93c17c4
    • David Brazdil's avatar
      KVM: arm64: Keep nVHE EL2 vector installed · fa8c3d65
      David Brazdil authored
      
      
      KVM by default keeps the stub vector installed and installs the nVHE
      vector only briefly for init and later on demand. Change this policy
      to install the vector at init and then never uninstall it if the kernel
      was given the protected KVM command line parameter.
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-25-dbrazdil@google.com
      fa8c3d65
    • David Brazdil's avatar
      KVM: arm64: Intercept host's SYSTEM_SUSPEND PSCI SMCs · d945f8d9
      David Brazdil authored
      
      
      Add a handler of SYSTEM_SUSPEND host PSCI SMCs. The semantics are
      equivalent to CPU_SUSPEND, typically called on the last online CPU.
      Reuse the same entry point and boot args struct as CPU_SUSPEND.
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-24-dbrazdil@google.com
      d945f8d9
    • David Brazdil's avatar
      KVM: arm64: Intercept host's CPU_SUSPEND PSCI SMCs · abf16336
      David Brazdil authored
      
      
      Add a handler of CPU_SUSPEND host PSCI SMCs. The SMC can either enter
      a sleep state indistinguishable from a WFI or a deeper sleep state that
      behaves like a CPU_OFF+CPU_ON except that the core is still considered
      online while asleep.
      
      The handler saves r0,pc of the host and makes the same call to EL3 with
      the hyp CPU entry point. It either returns back to the handler and then
      back to the host, or wakes up into the entry point and initializes EL2
      state before dropping back to EL1. No EL2 state needs to be
      saved/restored for this purpose.
      
      CPU_ON and CPU_SUSPEND are both implemented using struct psci_boot_args
      to store the state upon powerup, with each CPU having separate structs
      for CPU_ON and CPU_SUSPEND so that CPU_SUSPEND can operate locklessly
      and so that a CPU_ON call targeting a CPU cannot interfere with
      a concurrent CPU_SUSPEND call on that CPU.
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-23-dbrazdil@google.com
      abf16336
    • David Brazdil's avatar
      KVM: arm64: Intercept host's CPU_ON SMCs · cdf36719
      David Brazdil authored
      
      
      Add a handler of the CPU_ON PSCI call from host. When invoked, it looks
      up the logical CPU ID corresponding to the provided MPIDR and populates
      the state struct of the target CPU with the provided x0, pc. It then
      calls CPU_ON itself, with an entry point in hyp that initializes EL2
      state before returning ERET to the provided PC in EL1.
      
      There is a simple atomic lock around the boot args struct. If it is
      already locked, CPU_ON will return PENDING_ON error code.
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-22-dbrazdil@google.com
      cdf36719
    • David Brazdil's avatar
      KVM: arm64: Add function to enter host from KVM nVHE hyp code · 04e05f05
      David Brazdil authored
      
      
      All nVHE hyp code is currently executed as handlers of host's HVCs. This
      will change as nVHE starts intercepting host's PSCI CPU_ON SMCs. The
      newly booted CPU will need to initialize EL2 state and then enter the
      host. Add __host_enter function that branches into the existing
      host state-restoring code after the trap handler would have returned.
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-21-dbrazdil@google.com
      04e05f05
    • David Brazdil's avatar
      KVM: arm64: Extract __do_hyp_init into a helper function · f74e1e21
      David Brazdil authored
      
      
      In preparation for adding a CPU entry point in nVHE hyp code, extract
      most of __do_hyp_init hypervisor initialization code into a common
      helper function. This will be invoked by the entry point to install KVM
      on the newly booted CPU.
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-20-dbrazdil@google.com
      f74e1e21
    • David Brazdil's avatar
      KVM: arm64: Forward safe PSCI SMCs coming from host · 1fd12b7e
      David Brazdil authored
      
      
      Forward the following PSCI SMCs issued by host to EL3 as they do not
      require the hypervisor's intervention. This assumes that EL3 correctly
      implements the PSCI specification.
      
      Only function IDs implemented in Linux are included.
      
      Where both 32-bit and 64-bit variants exist, it is assumed that the host
      will always use the 64-bit variant.
      
       * SMCs that only return information about the system
         * PSCI_VERSION        - PSCI version implemented by EL3
         * PSCI_FEATURES       - optional features supported by EL3
         * AFFINITY_INFO       - power state of core/cluster
         * MIGRATE_INFO_TYPE   - whether Trusted OS can be migrated
         * MIGRATE_INFO_UP_CPU - resident core of Trusted OS
       * operations which do not affect the hypervisor
         * MIGRATE             - migrate Trusted OS to a different core
         * SET_SUSPEND_MODE    - toggle OS-initiated mode
       * system shutdown/reset
         * SYSTEM_OFF
         * SYSTEM_RESET
         * SYSTEM_RESET2
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-19-dbrazdil@google.com
      1fd12b7e
    • David Brazdil's avatar
      KVM: arm64: Add offset for hyp VA <-> PA conversion · d084ecc5
      David Brazdil authored
      
      
      Add a host-initialized constant to KVM nVHE hyp code for converting
      between EL2 linear map virtual addresses and physical addresses.
      Also add `__hyp_pa` macro that performs the conversion.
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-18-dbrazdil@google.com
      d084ecc5
    • David Brazdil's avatar
      KVM: arm64: Bootstrap PSCI SMC handler in nVHE EL2 · eeeee719
      David Brazdil authored
      
      
      Add a handler of PSCI SMCs in nVHE hyp code. The handler is initialized
      with the version used by the host's PSCI driver and the function IDs it
      was configured with. If the SMC function ID matches one of the
      configured PSCI calls (for v0.1) or falls into the PSCI function ID
      range (for v0.2+), the SMC is handled by the PSCI handler. For now, all
      SMCs return PSCI_RET_NOT_SUPPORTED.
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-17-dbrazdil@google.com
      eeeee719
    • David Brazdil's avatar
      KVM: arm64: Add SMC handler in nVHE EL2 · a805e1fb
      David Brazdil authored
      
      
      Add handler of host SMCs in KVM nVHE trap handler. Forward all SMCs to
      EL3 and propagate the result back to EL1. This is done in preparation
      for validating host SMCs in KVM protected mode.
      
      The implementation assumes that firmware uses SMCCC v1.2 or older. That
      means x0-x17 can be used both for arguments and results, other GPRs are
      preserved.
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-16-dbrazdil@google.com
      a805e1fb
    • David Brazdil's avatar
      KVM: arm64: Create nVHE copy of cpu_logical_map · 94f5e8a4
      David Brazdil authored
      
      
      When KVM starts validating host's PSCI requests, it will need to map
      MPIDR back to the CPU ID. To this end, copy cpu_logical_map into nVHE
      hyp memory when KVM is initialized.
      
      Only copy the information for CPUs that are online at the point of KVM
      initialization so that KVM rejects CPUs whose features were not checked
      against the finalized capabilities.
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-15-dbrazdil@google.com
      94f5e8a4
    • David Brazdil's avatar
      KVM: arm64: Support per_cpu_ptr in nVHE hyp code · 687413d3
      David Brazdil authored
      
      
      When compiling with __KVM_NVHE_HYPERVISOR__, redefine per_cpu_offset()
      to __hyp_per_cpu_offset() which looks up the base of the nVHE per-CPU
      region of the given cpu and computes its offset from the
      .hyp.data..percpu section.
      
      This enables use of per_cpu_ptr() helpers in nVHE hyp code. Until now
      only this_cpu_ptr() was supported by setting TPIDR_EL2.
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-14-dbrazdil@google.com
      687413d3
    • David Brazdil's avatar
      KVM: arm64: Add .hyp.data..ro_after_init ELF section · 2d7bf218
      David Brazdil authored
      
      
      Add rules for renaming the .data..ro_after_init ELF section in KVM nVHE
      object files to .hyp.data..ro_after_init, linking it into the kernel
      and mapping it in hyp at runtime.
      
      The section is RW to the host, then mapped RO in hyp. The expectation is
      that the host populates the variables in the section and they are never
      changed by hyp afterwards.
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-13-dbrazdil@google.com
      2d7bf218
    • David Brazdil's avatar
      KVM: arm64: Init MAIR/TCR_EL2 from params struct · d3e1086c
      David Brazdil authored
      
      
      MAIR_EL2 and TCR_EL2 are currently initialized from their _EL1 values.
      This will not work once KVM starts intercepting PSCI ON/SUSPEND SMCs
      and initializing EL2 state before EL1 state.
      
      Obtain the EL1 values during KVM init and store them in the init params
      struct. The struct will stay in memory and can be used when booting new
      cores.
      
      Take the opportunity to move copying the T0SZ value from idmap_t0sz in
      KVM init rather than in .hyp.idmap.text. This avoids the need for the
      idmap_t0sz symbol alias.
      
      Signed-off-by: default avatarDavid Brazdil <dbrazdil@google.com>
      Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
      Link: https://lore.kernel.org/r/20201202184122.26046-12-dbrazdil@google.com
      d3e1086c