TDX guest driver exposes IOCTL interfaces to service TDX guest user-specific requests. Currently, it is only used to allow the user to get the TDREPORT to support TDX attestation. Details about the TDX attestation process are documented in Documentation/x86/tdx.rst, and the IOCTL details are documented in Documentation/virt/coco/tdx-guest.rst. Operations like getting TDREPORT involves sending a blob of data as input and getting another blob of data as output. It was considered to use a sysfs interface for this, but it doesn't fit well into the standard sysfs model for configuring values. It would be possible to do read/write on files, but it would need multiple file descriptors, which would be somewhat messy. IOCTLs seem to be the best fitting and simplest model for this use case. The AMD sev-guest driver also uses the IOCTL interface to support attestation. [Bagas Sanjaya: Ack is for documentation portion] Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Bagas Sanjaya <bagasdotme@gmail.com> Reviewed-by: Tony Luck <tony.luck@intel.com> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com> Acked-by: Kai Huang <kai.huang@intel.com> Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Acked-by: Wander Lairson Costa <wander@redhat.com> Link: https://lore.kernel.org/all/20221116223820.819090-3-sathyanarayanan.kuppuswamy%40linux.intel.com
102 lines
2.1 KiB
C
102 lines
2.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* TDX guest user interface driver
|
|
*
|
|
* Copyright (C) 2022 Intel Corporation
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/miscdevice.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/module.h>
|
|
#include <linux/mod_devicetable.h>
|
|
#include <linux/string.h>
|
|
#include <linux/uaccess.h>
|
|
|
|
#include <uapi/linux/tdx-guest.h>
|
|
|
|
#include <asm/cpu_device_id.h>
|
|
#include <asm/tdx.h>
|
|
|
|
static long tdx_get_report0(struct tdx_report_req __user *req)
|
|
{
|
|
u8 *reportdata, *tdreport;
|
|
long ret;
|
|
|
|
reportdata = kmalloc(TDX_REPORTDATA_LEN, GFP_KERNEL);
|
|
if (!reportdata)
|
|
return -ENOMEM;
|
|
|
|
tdreport = kzalloc(TDX_REPORT_LEN, GFP_KERNEL);
|
|
if (!tdreport) {
|
|
ret = -ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
if (copy_from_user(reportdata, req->reportdata, TDX_REPORTDATA_LEN)) {
|
|
ret = -EFAULT;
|
|
goto out;
|
|
}
|
|
|
|
/* Generate TDREPORT0 using "TDG.MR.REPORT" TDCALL */
|
|
ret = tdx_mcall_get_report0(reportdata, tdreport);
|
|
if (ret)
|
|
goto out;
|
|
|
|
if (copy_to_user(req->tdreport, tdreport, TDX_REPORT_LEN))
|
|
ret = -EFAULT;
|
|
|
|
out:
|
|
kfree(reportdata);
|
|
kfree(tdreport);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static long tdx_guest_ioctl(struct file *file, unsigned int cmd,
|
|
unsigned long arg)
|
|
{
|
|
switch (cmd) {
|
|
case TDX_CMD_GET_REPORT0:
|
|
return tdx_get_report0((struct tdx_report_req __user *)arg);
|
|
default:
|
|
return -ENOTTY;
|
|
}
|
|
}
|
|
|
|
static const struct file_operations tdx_guest_fops = {
|
|
.owner = THIS_MODULE,
|
|
.unlocked_ioctl = tdx_guest_ioctl,
|
|
.llseek = no_llseek,
|
|
};
|
|
|
|
static struct miscdevice tdx_misc_dev = {
|
|
.name = KBUILD_MODNAME,
|
|
.minor = MISC_DYNAMIC_MINOR,
|
|
.fops = &tdx_guest_fops,
|
|
};
|
|
|
|
static const struct x86_cpu_id tdx_guest_ids[] = {
|
|
X86_MATCH_FEATURE(X86_FEATURE_TDX_GUEST, NULL),
|
|
{}
|
|
};
|
|
MODULE_DEVICE_TABLE(x86cpu, tdx_guest_ids);
|
|
|
|
static int __init tdx_guest_init(void)
|
|
{
|
|
if (!x86_match_cpu(tdx_guest_ids))
|
|
return -ENODEV;
|
|
|
|
return misc_register(&tdx_misc_dev);
|
|
}
|
|
module_init(tdx_guest_init);
|
|
|
|
static void __exit tdx_guest_exit(void)
|
|
{
|
|
misc_deregister(&tdx_misc_dev);
|
|
}
|
|
module_exit(tdx_guest_exit);
|
|
|
|
MODULE_AUTHOR("Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>");
|
|
MODULE_DESCRIPTION("TDX Guest Driver");
|
|
MODULE_LICENSE("GPL");
|