[RFC v2 23/26] KVM: x86/asi: Introduce KVM address space isolation

From: Alexandre Chartre
Date: Thu Jul 11 2019 - 10:28:14 EST


From: Liran Alon <liran.alon@xxxxxxxxxx>

Create a separate address space for KVM that will be active when
KVM #VMExit handlers run. Up until the point which we architectully
need to access host (or other VM) sensitive data.

This patch just create the address space using address space
isolation (asi) but never makes it active yet. This will be done
by next commits.

Signed-off-by: Liran Alon <liran.alon@xxxxxxxxxx>
Signed-off-by: Alexandre Chartre <alexandre.chartre@xxxxxxxxxx>
---
arch/x86/kvm/vmx/isolation.c | 58 ++++++++++++++++++++++++++++++++++++++++++
arch/x86/kvm/vmx/vmx.c | 7 ++++-
arch/x86/kvm/vmx/vmx.h | 3 ++
include/linux/kvm_host.h | 5 +++
4 files changed, 72 insertions(+), 1 deletions(-)

diff --git a/arch/x86/kvm/vmx/isolation.c b/arch/x86/kvm/vmx/isolation.c
index e25f663..644d8d3 100644
--- a/arch/x86/kvm/vmx/isolation.c
+++ b/arch/x86/kvm/vmx/isolation.c
@@ -7,6 +7,15 @@

#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/printk.h>
+#include <asm/asi.h>
+#include <asm/vmx.h>
+
+#include "vmx.h"
+#include "x86.h"
+
+#define VMX_ASI_MAP_FLAGS \
+ (ASI_MAP_STACK_CANARY | ASI_MAP_CPU_PTR | ASI_MAP_CURRENT_TASK)

/*
* When set to true, KVM #VMExit handlers run in isolated address space
@@ -24,3 +33,52 @@
*/
static bool __read_mostly address_space_isolation;
module_param(address_space_isolation, bool, 0444);
+
+static int vmx_isolation_init_mapping(struct asi *asi, struct vcpu_vmx *vmx)
+{
+ /* TODO: Populate the KVM ASI page-table */
+
+ return 0;
+}
+
+int vmx_isolation_init(struct vcpu_vmx *vmx)
+{
+ struct kvm_vcpu *vcpu = &vmx->vcpu;
+ struct asi *asi;
+ int err;
+
+ if (!address_space_isolation) {
+ vcpu->asi = NULL;
+ return 0;
+ }
+
+ asi = asi_create(VMX_ASI_MAP_FLAGS);
+ if (!asi) {
+ pr_debug("KVM: x86: Failed to create address space isolation\n");
+ return -ENXIO;
+ }
+
+ err = vmx_isolation_init_mapping(asi, vmx);
+ if (err) {
+ vcpu->asi = NULL;
+ return err;
+ }
+
+ vcpu->asi = asi;
+
+ pr_info("KVM: x86: Running with isolated address space\n");
+
+ return 0;
+}
+
+void vmx_isolation_uninit(struct vcpu_vmx *vmx)
+{
+ struct kvm_vcpu *vcpu = &vmx->vcpu;
+
+ if (!address_space_isolation || !vcpu->asi)
+ return;
+
+ asi_destroy(vcpu->asi);
+ vcpu->asi = NULL;
+ pr_info("KVM: x86: End of isolated address space\n");
+}
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index d98eac3..9b92467 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -202,7 +202,7 @@
};

#define L1D_CACHE_ORDER 4
-static void *vmx_l1d_flush_pages;
+void *vmx_l1d_flush_pages;

static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf)
{
@@ -6561,6 +6561,7 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);

+ vmx_isolation_uninit(vmx);
if (enable_pml)
vmx_destroy_pml_buffer(vmx);
free_vpid(vmx->vpid);
@@ -6672,6 +6673,10 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)

vmx->ept_pointer = INVALID_PAGE;

+ err = vmx_isolation_init(vmx);
+ if (err)
+ goto free_vmcs;
+
return &vmx->vcpu;

free_vmcs:
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
index 61128b4..09c1593 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
@@ -525,4 +525,7 @@ static inline void decache_tsc_multiplier(struct vcpu_vmx *vmx)

void dump_vmcs(void);

+int vmx_isolation_init(struct vcpu_vmx *vmx);
+void vmx_isolation_uninit(struct vcpu_vmx *vmx);
+
#endif /* __KVM_X86_VMX_H */
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index d1ad38a..2a9d073 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -34,6 +34,7 @@
#include <linux/kvm_types.h>

#include <asm/kvm_host.h>
+#include <asm/asi.h>

#ifndef KVM_MAX_VCPU_ID
#define KVM_MAX_VCPU_ID KVM_MAX_VCPUS
@@ -320,6 +321,10 @@ struct kvm_vcpu {
bool preempted;
struct kvm_vcpu_arch arch;
struct dentry *debugfs_dentry;
+
+#ifdef CONFIG_ADDRESS_SPACE_ISOLATION
+ struct asi *asi;
+#endif
};

static inline int kvm_vcpu_exiting_guest_mode(struct kvm_vcpu *vcpu)
--
1.7.1