Revert "ANDROID: KVM: arm64: s2mpu: Add driver initializer"

This reverts commit b5877cf5f5.

Bug: 233587962
Signed-off-by: Will Deacon <willdeacon@google.com>
Change-Id: Icb38c5eab21bc0c00d69ff26b778d1b8903509bb
This commit is contained in:
Will Deacon
2022-07-07 15:49:02 +01:00
parent 494fb078fe
commit a2d0c06025
6 changed files with 31 additions and 139 deletions

View File

@@ -380,7 +380,6 @@ enum kvm_iommu_driver {
};
enum pkvm_iommu_driver_id {
PKVM_IOMMU_DRIVER_S2MPU,
PKVM_IOMMU_NR_DRIVERS,
};
@@ -395,8 +394,6 @@ int pkvm_iommu_register(struct device *dev, enum pkvm_iommu_driver_id drv_id,
int pkvm_iommu_suspend(struct device *dev);
int pkvm_iommu_resume(struct device *dev);
int pkvm_iommu_s2mpu_register(struct device *dev, phys_addr_t pa);
struct vcpu_reset_state {
unsigned long pc;
unsigned long r0;

View File

@@ -123,9 +123,8 @@ static_assert(SMPT_GRAN <= PAGE_SIZE);
#define SMPT_ELEMS_PER_WORD (SMPT_WORD_SIZE * SMPT_ELEMS_PER_BYTE)
#define SMPT_WORD_BYTE_RANGE (SMPT_GRAN * SMPT_ELEMS_PER_WORD)
#define SMPT_NUM_ELEMS (SZ_1G / SMPT_GRAN)
#define SMPT_SIZE (SMPT_NUM_ELEMS / SMPT_ELEMS_PER_BYTE)
#define SMPT_NUM_WORDS (SMPT_SIZE / SMPT_WORD_SIZE)
#define SMPT_NUM_PAGES (SMPT_SIZE / PAGE_SIZE)
#define SMPT_SIZE (SMPT_NUM_ELEMS / SMPT_ELEMS_PER_BYTE)
#define SMPT_ORDER get_order(SMPT_SIZE)
/*

View File

@@ -80,8 +80,6 @@ bool pkvm_iommu_host_dabt_handler(struct kvm_cpu_context *host_ctxt, u32 esr,
void pkvm_iommu_host_stage2_idmap(phys_addr_t start, phys_addr_t end,
enum kvm_pgtable_prot prot);
extern const struct pkvm_iommu_ops pkvm_s2mpu_ops;
struct kvm_iommu_ops {
int (*init)(void);
bool (*host_smc_handler)(struct kvm_cpu_context *host_ctxt);

View File

@@ -63,8 +63,6 @@ static inline struct pkvm_iommu_driver *get_driver(enum pkvm_iommu_driver_id id)
static const struct pkvm_iommu_ops *get_driver_ops(enum pkvm_iommu_driver_id id)
{
switch (id) {
case PKVM_IOMMU_DRIVER_S2MPU:
return IS_ENABLED(CONFIG_KVM_S2MPU) ? &pkvm_s2mpu_ops : NULL;
default:
return NULL;
}

View File

@@ -472,72 +472,50 @@ static bool s2mpu_host_mmio_dabt_handler(struct kvm_cpu_context *host_ctxt,
return true;
}
static int s2mpu_init(void *data, size_t size)
static int s2mpu_init(void)
{
struct mpt in_mpt;
u32 *smpt;
phys_addr_t pa;
struct pkvm_iommu *dev;
unsigned int gb;
int ret = 0;
int ret;
if (size != sizeof(in_mpt))
return -EINVAL;
/* Map data structures in EL2 stage-1. */
ret = pkvm_create_mappings(s2mpus,
s2mpus + nr_s2mpus,
PAGE_HYP);
if (ret)
return ret;
/* The host can concurrently modify 'data'. Copy it to avoid TOCTOU. */
memcpy(&in_mpt, data, sizeof(in_mpt));
/* Take ownership of all SMPT buffers. This will also map them in. */
for_each_gb(gb) {
smpt = kern_hyp_va(in_mpt.fmpt[gb].smpt);
pa = __hyp_pa(smpt);
if (!IS_ALIGNED(pa, SMPT_SIZE)) {
ret = -EINVAL;
break;
}
ret = __pkvm_host_donate_hyp(pa >> PAGE_SHIFT, SMPT_NUM_PAGES);
ret = pkvm_create_mappings(
host_mpt.fmpt[gb].smpt,
host_mpt.fmpt[gb].smpt + SMPT_NUM_WORDS,
PAGE_HYP);
if (ret)
break;
host_mpt.fmpt[gb] = (struct fmpt){
.smpt = smpt,
.gran_1g = true,
.prot = MPT_PROT_NONE,
};
return ret;
}
/* Try to return memory back if there was an error. */
if (ret) {
for_each_gb(gb) {
smpt = host_mpt.fmpt[gb].smpt;
if (!smpt)
break;
WARN_ON(__pkvm_hyp_donate_host(__hyp_pa(smpt) >> PAGE_SHIFT,
SMPT_NUM_PAGES));
}
memset(&host_mpt, 0, sizeof(host_mpt));
/* Map S2MPU MMIO regions in EL2 stage-1. */
for_each_s2mpu(dev) {
dev->va = (void __iomem *)__pkvm_create_private_mapping(
dev->pa, S2MPU_MMIO_SIZE, PAGE_HYP_DEVICE);
if (IS_ERR_OR_NULL(dev->va))
return PTR_ERR(dev->va);
}
return ret;
}
static int s2mpu_validate(phys_addr_t pa, size_t size)
{
if (size != S2MPU_MMIO_SIZE)
return -EINVAL;
/*
* Program all S2MPUs powered on at boot. Note that they may not be in
* the blocking reset state as the bootloader may have programmed them.
*/
for_each_powered_s2mpu(dev) {
ret = initialize_with_mpt(dev, &host_mpt);
if (ret)
return ret;
}
return 0;
}
const struct pkvm_iommu_ops pkvm_s2mpu_ops = (struct pkvm_iommu_ops){
.init = s2mpu_init,
.validate = s2mpu_validate,
.data_size = sizeof(struct s2mpu_drv_data),
};
const struct kvm_iommu_ops kvm_s2mpu_ops = (struct kvm_iommu_ops){
.init = s2mpu_init,
.host_smc_handler = s2mpu_host_smc_handler,
.host_mmio_dabt_handler = s2mpu_host_mmio_dabt_handler,
.host_stage2_set_owner = s2mpu_host_stage2_set_owner,

View File

@@ -6,81 +6,3 @@
#include <linux/kvm_host.h>
#include <asm/kvm_s2mpu.h>
static int init_s2mpu_driver(void)
{
static DEFINE_MUTEX(lock);
static bool init_done;
struct mpt *mpt;
unsigned int gb;
unsigned long addr;
u64 pfn;
int ret = 0;
mutex_lock(&lock);
if (init_done)
goto out;
/* Allocate a page for driver data. Must fit MPT descriptor. */
BUILD_BUG_ON(sizeof(*mpt) > PAGE_SIZE);
addr = __get_free_page(GFP_KERNEL);
if (!addr) {
ret = -ENOMEM;
goto out;
}
mpt = (struct mpt *)addr;
/* Allocate SMPT buffers. */
for_each_gb(gb) {
addr = __get_free_pages(GFP_KERNEL, SMPT_ORDER);
if (!addr) {
ret = -ENOMEM;
goto out_free;
}
mpt->fmpt[gb].smpt = (u32 *)addr;
}
/* Share MPT descriptor with hyp. */
pfn = __pa(mpt) >> PAGE_SHIFT;
ret = kvm_call_hyp_nvhe(__pkvm_host_share_hyp, pfn);
if (ret)
goto out_free;
/* Hypercall to initialize EL2 driver. */
ret = pkvm_iommu_driver_init(PKVM_IOMMU_DRIVER_S2MPU, mpt, sizeof(*mpt));
if (ret)
goto out_unshare;
init_done = true;
out_unshare:
WARN_ON(kvm_call_hyp_nvhe(__pkvm_host_unshare_hyp, pfn));
out_free:
/* TODO - will driver return the memory? */
if (ret) {
for_each_gb(gb)
free_pages((unsigned long)mpt->fmpt[gb].smpt, SMPT_ORDER);
free_page((unsigned long)mpt);
}
out:
mutex_unlock(&lock);
return ret;
}
int pkvm_iommu_s2mpu_register(struct device *dev, phys_addr_t addr)
{
int ret;
if (!is_protected_kvm_enabled())
return -ENODEV;
ret = init_s2mpu_driver();
if (ret)
return ret;
return pkvm_iommu_register(dev, PKVM_IOMMU_DRIVER_S2MPU,
addr, S2MPU_MMIO_SIZE);
}
EXPORT_SYMBOL_GPL(pkvm_iommu_s2mpu_register);