Support psp virtualization

Signed-off-by: niuyongwen <niuyongwen@hygon.cn>
This commit is contained in:
niuyongwen 2023-08-10 10:53:18 +08:00 committed by xiongmengbiao
parent d94139184b
commit d1a84dd07d
5 changed files with 93 additions and 2 deletions

View File

@ -2149,6 +2149,8 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event);
int kvm_pv_send_ipi(struct kvm *kvm, unsigned long ipi_bitmap_low,
unsigned long ipi_bitmap_high, u32 min,
unsigned long icr, int op_64_bit);
int kvm_pv_psp_op(struct kvm *kvm, int cmd, gpa_t data_gpa,
gpa_t psp_ret_gpa, gpa_t table_gpa);
int kvm_add_user_return_msr(u32 msr);
int kvm_find_user_return_msr(u32 msr);

View File

@ -12,7 +12,7 @@ include $(srctree)/virt/kvm/Makefile.kvm
kvm-y += x86.o emulate.o i8259.o irq.o lapic.o \
i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \
hyperv.o debugfs.o mmu/mmu.o mmu/page_track.o \
mmu/spte.o
mmu/spte.o psp.o
ifdef CONFIG_HYPERV
kvm-y += kvm_onhyperv.o

85
arch/x86/kvm/psp.c Normal file
View File

@ -0,0 +1,85 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* PSP virtualization
*
* Copyright (c) 2023, HYGON CORPORATION. All rights reserved.
* Author: Ge Yang <yangge@hygon.cn>
*
*/
#include <linux/kvm_types.h>
#include <linux/slab.h>
#include <linux/kvm_host.h>
#include <linux/psp-sev.h>
#include <linux/psp-hygon.h>
struct psp_cmdresp_head {
uint32_t buf_size;
uint32_t cmdresp_size;
uint32_t cmdresp_code;
} __packed;
int guest_addr_map_table_op(void *data_hva, gpa_t data_gpa, gpa_t table_gpa,
int op)
{
return 0;
}
int kvm_pv_psp_op(struct kvm *kvm, int cmd, gpa_t data_gpa, gpa_t psp_ret_gpa,
gpa_t table_gpa)
{
void *data;
struct psp_cmdresp_head psp_head;
uint32_t data_size;
int psp_ret = 0;
int ret = 0;
if (unlikely(kvm_read_guest(kvm, data_gpa, &psp_head,
sizeof(struct psp_cmdresp_head))))
return -EFAULT;
data_size = psp_head.buf_size;
data = kzalloc(data_size, GFP_KERNEL);
if (!data)
return -ENOMEM;
if (unlikely(kvm_read_guest(kvm, data_gpa, data, data_size))) {
ret = -EFAULT;
goto e_free;
}
if (guest_addr_map_table_op(data, data_gpa, table_gpa, 0)) {
ret = -EFAULT;
goto e_free;
}
ret = psp_do_cmd(cmd, data, &psp_ret);
if (ret) {
pr_err("%s: psp do cmd error, %d\n", __func__, psp_ret);
ret = -EIO;
goto e_free;
}
if (guest_addr_map_table_op(data, data_gpa, table_gpa, 1)) {
ret = -EFAULT;
goto e_free;
}
if (unlikely(kvm_write_guest(kvm, data_gpa, data, data_size))) {
ret = -EFAULT;
goto e_free;
}
if (unlikely(kvm_write_guest(kvm, psp_ret_gpa, &psp_ret,
sizeof(psp_ret)))) {
ret = -EFAULT;
goto e_free;
}
return ret;
e_free:
kfree(data);
return ret;
}

View File

@ -9891,7 +9891,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
}
if (static_call(kvm_x86_get_cpl)(vcpu) != 0 &&
!(is_x86_vendor_hygon() && nr == KVM_HC_VM_ATTESTATION)) {
!(is_x86_vendor_hygon() && (nr == KVM_HC_VM_ATTESTATION || nr == KVM_HC_PSP_OP))) {
ret = -KVM_EPERM;
goto out;
}
@ -9928,6 +9928,9 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
kvm_sched_yield(vcpu, a0);
ret = 0;
break;
case KVM_HC_PSP_OP:
ret = kvm_pv_psp_op(vcpu->kvm, a0, a1, a2, a3);
break;
case KVM_HC_MAP_GPA_RANGE: {
u64 gpa = a0, npages = a1, attrs = a2;

View File

@ -31,6 +31,7 @@
#define KVM_HC_SCHED_YIELD 11
#define KVM_HC_MAP_GPA_RANGE 12
#define KVM_HC_VM_ATTESTATION 100 /* Specific to Hygon CPU */
#define KVM_HC_PSP_OP 101 /* Specific to Hygon platform */
/*
* hypercalls use architecture specific