linux/drivers/crypto/ccp/sev-dev.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * AMD Secure Encrypted Virtualization (SEV) interface
 *
 * Copyright (C) 2016,2019 Advanced Micro Devices, Inc.
 *
 * Author: Brijesh Singh <[email protected]>
 */

#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/spinlock_types.h>
#include <linux/types.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/hw_random.h>
#include <linux/ccp.h>
#include <linux/firmware.h>
#include <linux/panic_notifier.h>
#include <linux/gfp.h>
#include <linux/cpufeature.h>
#include <linux/fs.h>
#include <linux/fs_struct.h>
#include <linux/psp.h>
#include <linux/amd-iommu.h>

#include <asm/smp.h>
#include <asm/cacheflush.h>
#include <asm/e820/types.h>
#include <asm/sev.h>

#include "psp-dev.h"
#include "sev-dev.h"

#define DEVICE_NAME
#define SEV_FW_FILE
#define SEV_FW_NAME_SIZE

/* Minimum firmware version required for the SEV-SNP support */
#define SNP_MIN_API_MAJOR
#define SNP_MIN_API_MINOR

/*
 * Maximum number of firmware-writable buffers that might be specified
 * in the parameters of a legacy SEV command buffer.
 */
#define CMD_BUF_FW_WRITABLE_MAX

/* Leave room in the descriptor array for an end-of-list indicator. */
#define CMD_BUF_DESC_MAX

static DEFINE_MUTEX(sev_cmd_mutex);
static struct sev_misc_dev *misc_dev;

static int psp_cmd_timeout =;
module_param(psp_cmd_timeout, int, 0644);
MODULE_PARM_DESC();

static int psp_probe_timeout =;
module_param(psp_probe_timeout, int, 0644);
MODULE_PARM_DESC();

static char *init_ex_path;
module_param(init_ex_path, charp, 0444);
MODULE_PARM_DESC();

static bool psp_init_on_probe =;
module_param(psp_init_on_probe, bool, 0444);
MODULE_PARM_DESC();

MODULE_FIRMWARE(); /* 1st gen EPYC */
MODULE_FIRMWARE(); /* 2nd gen EPYC */
MODULE_FIRMWARE(); /* 3rd gen EPYC */
MODULE_FIRMWARE(); /* 4th gen EPYC */

static bool psp_dead;
static int psp_timeout;

/* Trusted Memory Region (TMR):
 *   The TMR is a 1MB area that must be 1MB aligned.  Use the page allocator
 *   to allocate the memory, which will return aligned memory for the specified
 *   allocation order.
 *
 * When SEV-SNP is enabled the TMR needs to be 2MB aligned and 2MB sized.
 */
#define SEV_TMR_SIZE
#define SNP_TMR_SIZE

static void *sev_es_tmr;
static size_t sev_es_tmr_size =;

/* INIT_EX NV Storage:
 *   The NV Storage is a 32Kb area and must be 4Kb page aligned.  Use the page
 *   allocator to allocate the memory, which will return aligned memory for the
 *   specified allocation order.
 */
#define NV_LENGTH
static void *sev_init_ex_buffer;

/*
 * SEV_DATA_RANGE_LIST:
 *   Array containing range of pages that firmware transitions to HV-fixed
 *   page state.
 */
static struct sev_data_range_list *snp_range_list;

static inline bool sev_version_greater_or_equal(u8 maj, u8 min)
{}

static void sev_irq_handler(int irq, void *data, unsigned int status)
{}

static int sev_wait_cmd_ioc(struct sev_device *sev,
			    unsigned int *reg, unsigned int timeout)
{}

static int sev_cmd_buffer_len(int cmd)
{}

static struct file *open_file_as_root(const char *filename, int flags, umode_t mode)
{}

static int sev_read_init_ex_file(void)
{}

static int sev_write_init_ex_file(void)
{}

static int sev_write_init_ex_file_if_required(int cmd_id)
{}

/*
 * snp_reclaim_pages() needs __sev_do_cmd_locked(), and __sev_do_cmd_locked()
 * needs snp_reclaim_pages(), so a forward declaration is needed.
 */
static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret);

static int snp_reclaim_pages(unsigned long paddr, unsigned int npages, bool locked)
{}

static int rmp_mark_pages_firmware(unsigned long paddr, unsigned int npages, bool locked)
{}

static struct page *__snp_alloc_firmware_pages(gfp_t gfp_mask, int order)
{}

void *snp_alloc_firmware_page(gfp_t gfp_mask)
{}
EXPORT_SYMBOL_GPL();

static void __snp_free_firmware_pages(struct page *page, int order, bool locked)
{}

void snp_free_firmware_page(void *addr)
{}
EXPORT_SYMBOL_GPL();

static void *sev_fw_alloc(unsigned long len)
{}

/**
 * struct cmd_buf_desc - descriptors for managing legacy SEV command address
 * parameters corresponding to buffers that may be written to by firmware.
 *
 * @paddr_ptr:  pointer to the address parameter in the command buffer which may
 *              need to be saved/restored depending on whether a bounce buffer
 *              is used. In the case of a bounce buffer, the command buffer
 *              needs to be updated with the address of the new bounce buffer
 *              snp_map_cmd_buf_desc() has allocated specifically for it. Must
 *              be NULL if this descriptor is only an end-of-list indicator.
 *
 * @paddr_orig: storage for the original address parameter, which can be used to
 *              restore the original value in @paddr_ptr in cases where it is
 *              replaced with the address of a bounce buffer.
 *
 * @len: length of buffer located at the address originally stored at @paddr_ptr
 *
 * @guest_owned: true if the address corresponds to guest-owned pages, in which
 *               case bounce buffers are not needed.
 */
struct cmd_buf_desc {};

/*
 * If a legacy SEV command parameter is a memory address, those pages in
 * turn need to be transitioned to/from firmware-owned before/after
 * executing the firmware command.
 *
 * Additionally, in cases where those pages are not guest-owned, a bounce
 * buffer is needed in place of the original memory address parameter.
 *
 * A set of descriptors are used to keep track of this handling, and
 * initialized here based on the specific commands being executed.
 */
static void snp_populate_cmd_buf_desc_list(int cmd, void *cmd_buf,
					   struct cmd_buf_desc *desc_list)
{}

static int snp_map_cmd_buf_desc(struct cmd_buf_desc *desc)
{}

static int snp_unmap_cmd_buf_desc(struct cmd_buf_desc *desc)
{}

static int snp_map_cmd_buf_desc_list(int cmd, void *cmd_buf, struct cmd_buf_desc *desc_list)
{}

static int snp_unmap_cmd_buf_desc_list(struct cmd_buf_desc *desc_list)
{}

static bool sev_cmd_buf_writable(int cmd)
{}

/* After SNP is INIT'ed, the behavior of legacy SEV commands is changed. */
static bool snp_legacy_handling_needed(int cmd)
{}

static int snp_prep_cmd_buf(int cmd, void *cmd_buf, struct cmd_buf_desc *desc_list)
{}

static int snp_reclaim_cmd_buf(int cmd, void *cmd_buf)
{}

static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
{}

int sev_do_cmd(int cmd, void *data, int *psp_ret)
{}
EXPORT_SYMBOL_GPL();

static int __sev_init_locked(int *error)
{}

static int __sev_init_ex_locked(int *error)
{}

static inline int __sev_do_init_locked(int *psp_ret)
{}

static void snp_set_hsave_pa(void *arg)
{}

static int snp_filter_reserved_mem_regions(struct resource *rs, void *arg)
{}

static int __sev_snp_init_locked(int *error)
{}

static void __sev_platform_init_handle_tmr(struct sev_device *sev)
{}

/*
 * If an init_ex_path is provided allocate a buffer for the file and
 * read in the contents. Additionally, if SNP is initialized, convert
 * the buffer pages to firmware pages.
 */
static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev)
{}

static int __sev_platform_init_locked(int *error)
{}

static int _sev_platform_init_locked(struct sev_platform_init_args *args)
{}

int sev_platform_init(struct sev_platform_init_args *args)
{}
EXPORT_SYMBOL_GPL();

static int __sev_platform_shutdown_locked(int *error)
{}

static int sev_get_platform_state(int *state, int *error)
{}

static int sev_ioctl_do_reset(struct sev_issue_cmd *argp, bool writable)
{}

static int sev_ioctl_do_platform_status(struct sev_issue_cmd *argp)
{}

static int sev_ioctl_do_pek_pdh_gen(int cmd, struct sev_issue_cmd *argp, bool writable)
{}

static int sev_ioctl_do_pek_csr(struct sev_issue_cmd *argp, bool writable)
{}

void *psp_copy_user_blob(u64 uaddr, u32 len)
{}
EXPORT_SYMBOL_GPL();

static int sev_get_api_version(void)
{}

static int sev_get_firmware(struct device *dev,
			    const struct firmware **firmware)
{}

/* Don't fail if SEV FW couldn't be updated. Continue with existing SEV FW */
static int sev_update_firmware(struct device *dev)
{}

static int __sev_snp_shutdown_locked(int *error, bool panic)
{}

static int sev_ioctl_do_pek_import(struct sev_issue_cmd *argp, bool writable)
{}

static int sev_ioctl_do_get_id2(struct sev_issue_cmd *argp)
{}

static int sev_ioctl_do_get_id(struct sev_issue_cmd *argp)
{}

static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable)
{}

static int sev_ioctl_do_snp_platform_status(struct sev_issue_cmd *argp)
{}

static int sev_ioctl_do_snp_commit(struct sev_issue_cmd *argp)
{}

static int sev_ioctl_do_snp_set_config(struct sev_issue_cmd *argp, bool writable)
{}

static int sev_ioctl_do_snp_vlek_load(struct sev_issue_cmd *argp, bool writable)
{}

static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
{}

static const struct file_operations sev_fops =;

int sev_platform_status(struct sev_user_data_status *data, int *error)
{}
EXPORT_SYMBOL_GPL();

int sev_guest_deactivate(struct sev_data_deactivate *data, int *error)
{}
EXPORT_SYMBOL_GPL();

int sev_guest_activate(struct sev_data_activate *data, int *error)
{}
EXPORT_SYMBOL_GPL();

int sev_guest_decommission(struct sev_data_decommission *data, int *error)
{}
EXPORT_SYMBOL_GPL();

int sev_guest_df_flush(int *error)
{}
EXPORT_SYMBOL_GPL();

static void sev_exit(struct kref *ref)
{}

static int sev_misc_init(struct sev_device *sev)
{}

int sev_dev_init(struct psp_device *psp)
{}

static void __sev_firmware_shutdown(struct sev_device *sev, bool panic)
{}

static void sev_firmware_shutdown(struct sev_device *sev)
{}

void sev_dev_destroy(struct psp_device *psp)
{}

static int snp_shutdown_on_panic(struct notifier_block *nb,
				 unsigned long reason, void *arg)
{}

static struct notifier_block snp_panic_notifier =;

int sev_issue_cmd_external_user(struct file *filep, unsigned int cmd,
				void *data, int *error)
{}
EXPORT_SYMBOL_GPL();

void sev_pci_init(void)
{}

void sev_pci_exit(void)
{}