Message ID | 20211203144642.3460447-6-pgonda@google.com |
---|---|
State | Superseded |
Headers | show |
Series | Add SEV_INIT_EX support | expand |
Hi Peter, I love your patch! Perhaps something to improve: [auto build test WARNING on herbert-cryptodev-2.6/master] [also build test WARNING on herbert-crypto-2.6/master kvm/queue linus/master v5.16-rc3 next-20211203] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Peter-Gonda/Add-SEV_INIT_EX-support/20211203-224846 base: https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master config: x86_64-randconfig-c007-20211203 (https://download.01.org/0day-ci/archive/20211204/202112040513.JRZWd1LU-lkp@intel.com/config) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project d30fcadf07ee552f20156ea90be2fdb54cb9cb08) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/32a279c228e30c47be88442fe20f890203854d9c git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Peter-Gonda/Add-SEV_INIT_EX-support/20211203-224846 git checkout 32a279c228e30c47be88442fe20f890203854d9c # save the config file to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/crypto/ccp/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): drivers/crypto/ccp/sev-dev.c:179:2: error: member reference type 'struct mutex' is not a pointer; did you mean to use '.'? lockdep_assert_held(sev_cmd_mutex); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:316:17: note: expanded from macro 'lockdep_assert_held' lockdep_assert(lockdep_is_held(l) != LOCK_STATE_NOT_HELD) ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:286:52: note: expanded from macro 'lockdep_is_held' #define lockdep_is_held(lock) lock_is_held(&(lock)->dep_map) ^ include/linux/lockdep.h:310:32: note: expanded from macro 'lockdep_assert' do { WARN_ON(debug_locks && !(cond)); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ include/asm-generic/bug.h:121:25: note: expanded from macro 'WARN_ON' int __ret_warn_on = !!(condition); \ ^~~~~~~~~ drivers/crypto/ccp/sev-dev.c:179:2: error: cannot take the address of an rvalue of type 'struct lockdep_map' lockdep_assert_held(sev_cmd_mutex); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:316:17: note: expanded from macro 'lockdep_assert_held' lockdep_assert(lockdep_is_held(l) != LOCK_STATE_NOT_HELD) ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:286:45: note: expanded from macro 'lockdep_is_held' #define lockdep_is_held(lock) lock_is_held(&(lock)->dep_map) ^ include/linux/lockdep.h:310:32: note: expanded from macro 'lockdep_assert' do { WARN_ON(debug_locks && !(cond)); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ include/asm-generic/bug.h:121:25: note: expanded from macro 'WARN_ON' int __ret_warn_on = !!(condition); \ ^~~~~~~~~ drivers/crypto/ccp/sev-dev.c:215:2: error: member reference type 'struct mutex' is not a pointer; did you mean to use '.'? lockdep_assert_held(sev_cmd_mutex); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:316:17: note: expanded from macro 'lockdep_assert_held' lockdep_assert(lockdep_is_held(l) != LOCK_STATE_NOT_HELD) ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:286:52: note: expanded from macro 'lockdep_is_held' #define lockdep_is_held(lock) lock_is_held(&(lock)->dep_map) ^ include/linux/lockdep.h:310:32: note: expanded from macro 'lockdep_assert' do { WARN_ON(debug_locks && !(cond)); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ include/asm-generic/bug.h:121:25: note: expanded from macro 'WARN_ON' int __ret_warn_on = !!(condition); \ ^~~~~~~~~ drivers/crypto/ccp/sev-dev.c:215:2: error: cannot take the address of an rvalue of type 'struct lockdep_map' lockdep_assert_held(sev_cmd_mutex); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:316:17: note: expanded from macro 'lockdep_assert_held' lockdep_assert(lockdep_is_held(l) != LOCK_STATE_NOT_HELD) ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:286:45: note: expanded from macro 'lockdep_is_held' #define lockdep_is_held(lock) lock_is_held(&(lock)->dep_map) ^ include/linux/lockdep.h:310:32: note: expanded from macro 'lockdep_assert' do { WARN_ON(debug_locks && !(cond)); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ include/asm-generic/bug.h:121:25: note: expanded from macro 'WARN_ON' int __ret_warn_on = !!(condition); \ ^~~~~~~~~ >> drivers/crypto/ccp/sev-dev.c:224:4: warning: format specifies type 'int' but the argument has type 'long' [-Wformat] PTR_ERR(fp)); ^~~~~~~~~~~ include/linux/dev_printk.h:144:65: note: expanded from macro 'dev_err' dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__) ~~~ ^~~~~~~~~~~ include/linux/dev_printk.h:110:23: note: expanded from macro 'dev_printk_index_wrap' _p_func(dev, fmt, ##__VA_ARGS__); \ ~~~ ^~~~~~~~~~~ drivers/crypto/ccp/sev-dev.c:244:2: error: member reference type 'struct mutex' is not a pointer; did you mean to use '.'? lockdep_assert_held(sev_cmd_mutex); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:316:17: note: expanded from macro 'lockdep_assert_held' lockdep_assert(lockdep_is_held(l) != LOCK_STATE_NOT_HELD) ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:286:52: note: expanded from macro 'lockdep_is_held' #define lockdep_is_held(lock) lock_is_held(&(lock)->dep_map) ^ include/linux/lockdep.h:310:32: note: expanded from macro 'lockdep_assert' do { WARN_ON(debug_locks && !(cond)); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ include/asm-generic/bug.h:121:25: note: expanded from macro 'WARN_ON' int __ret_warn_on = !!(condition); \ ^~~~~~~~~ drivers/crypto/ccp/sev-dev.c:244:2: error: cannot take the address of an rvalue of type 'struct lockdep_map' lockdep_assert_held(sev_cmd_mutex); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:316:17: note: expanded from macro 'lockdep_assert_held' lockdep_assert(lockdep_is_held(l) != LOCK_STATE_NOT_HELD) ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:286:45: note: expanded from macro 'lockdep_is_held' #define lockdep_is_held(lock) lock_is_held(&(lock)->dep_map) ^ include/linux/lockdep.h:310:32: note: expanded from macro 'lockdep_assert' do { WARN_ON(debug_locks && !(cond)); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ include/asm-generic/bug.h:121:25: note: expanded from macro 'WARN_ON' int __ret_warn_on = !!(condition); \ ^~~~~~~~~ drivers/crypto/ccp/sev-dev.c:1250:15: warning: unused variable 'tmr_page' [-Wunused-variable] struct page *tmr_page; ^ 2 warnings and 6 errors generated. vim +224 drivers/crypto/ccp/sev-dev.c 207 208 static void sev_write_init_ex_file(void) 209 { 210 struct sev_device *sev = psp_master->sev_data; 211 struct file *fp; 212 loff_t offset = 0; 213 ssize_t nwrite; 214 215 lockdep_assert_held(sev_cmd_mutex); 216 217 if (!sev_init_ex_buffer) 218 return; 219 220 fp = filp_open(init_ex_path, O_CREAT | O_WRONLY, 0600); 221 if (IS_ERR(fp)) { 222 dev_err(sev->dev, 223 "SEV: could not open file for write, error %d\n", > 224 PTR_ERR(fp)); 225 return; 226 } 227 228 nwrite = kernel_write(fp, sev_init_ex_buffer, NV_LENGTH, &offset); 229 vfs_fsync(fp, 0); 230 filp_close(fp, NULL); 231 232 if (nwrite != NV_LENGTH) { 233 dev_err(sev->dev, 234 "SEV: failed to write %u bytes to non volatile memory area, ret %ld\n", 235 NV_LENGTH, nwrite); 236 return; 237 } 238 239 dev_dbg(sev->dev, "SEV: write successful to NV file\n"); 240 } 241 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Hi Peter, I love your patch! Yet something to improve: [auto build test ERROR on herbert-cryptodev-2.6/master] [also build test ERROR on herbert-crypto-2.6/master kvm/queue linus/master v5.16-rc3 next-20211203] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Peter-Gonda/Add-SEV_INIT_EX-support/20211203-224846 base: https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master config: x86_64-randconfig-c007-20211203 (https://download.01.org/0day-ci/archive/20211204/202112041112.wJCjLloK-lkp@intel.com/config) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project d30fcadf07ee552f20156ea90be2fdb54cb9cb08) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/32a279c228e30c47be88442fe20f890203854d9c git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Peter-Gonda/Add-SEV_INIT_EX-support/20211203-224846 git checkout 32a279c228e30c47be88442fe20f890203854d9c # save the config file to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): >> drivers/crypto/ccp/sev-dev.c:179:2: error: member reference type 'struct mutex' is not a pointer; did you mean to use '.'? lockdep_assert_held(sev_cmd_mutex); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:316:17: note: expanded from macro 'lockdep_assert_held' lockdep_assert(lockdep_is_held(l) != LOCK_STATE_NOT_HELD) ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:286:52: note: expanded from macro 'lockdep_is_held' #define lockdep_is_held(lock) lock_is_held(&(lock)->dep_map) ^ include/linux/lockdep.h:310:32: note: expanded from macro 'lockdep_assert' do { WARN_ON(debug_locks && !(cond)); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ include/asm-generic/bug.h:121:25: note: expanded from macro 'WARN_ON' int __ret_warn_on = !!(condition); \ ^~~~~~~~~ >> drivers/crypto/ccp/sev-dev.c:179:2: error: cannot take the address of an rvalue of type 'struct lockdep_map' lockdep_assert_held(sev_cmd_mutex); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:316:17: note: expanded from macro 'lockdep_assert_held' lockdep_assert(lockdep_is_held(l) != LOCK_STATE_NOT_HELD) ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:286:45: note: expanded from macro 'lockdep_is_held' #define lockdep_is_held(lock) lock_is_held(&(lock)->dep_map) ^ include/linux/lockdep.h:310:32: note: expanded from macro 'lockdep_assert' do { WARN_ON(debug_locks && !(cond)); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ include/asm-generic/bug.h:121:25: note: expanded from macro 'WARN_ON' int __ret_warn_on = !!(condition); \ ^~~~~~~~~ drivers/crypto/ccp/sev-dev.c:215:2: error: member reference type 'struct mutex' is not a pointer; did you mean to use '.'? lockdep_assert_held(sev_cmd_mutex); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:316:17: note: expanded from macro 'lockdep_assert_held' lockdep_assert(lockdep_is_held(l) != LOCK_STATE_NOT_HELD) ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:286:52: note: expanded from macro 'lockdep_is_held' #define lockdep_is_held(lock) lock_is_held(&(lock)->dep_map) ^ include/linux/lockdep.h:310:32: note: expanded from macro 'lockdep_assert' do { WARN_ON(debug_locks && !(cond)); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ include/asm-generic/bug.h:121:25: note: expanded from macro 'WARN_ON' int __ret_warn_on = !!(condition); \ ^~~~~~~~~ drivers/crypto/ccp/sev-dev.c:215:2: error: cannot take the address of an rvalue of type 'struct lockdep_map' lockdep_assert_held(sev_cmd_mutex); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:316:17: note: expanded from macro 'lockdep_assert_held' lockdep_assert(lockdep_is_held(l) != LOCK_STATE_NOT_HELD) ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:286:45: note: expanded from macro 'lockdep_is_held' #define lockdep_is_held(lock) lock_is_held(&(lock)->dep_map) ^ include/linux/lockdep.h:310:32: note: expanded from macro 'lockdep_assert' do { WARN_ON(debug_locks && !(cond)); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ include/asm-generic/bug.h:121:25: note: expanded from macro 'WARN_ON' int __ret_warn_on = !!(condition); \ ^~~~~~~~~ drivers/crypto/ccp/sev-dev.c:224:4: warning: format specifies type 'int' but the argument has type 'long' [-Wformat] PTR_ERR(fp)); ^~~~~~~~~~~ include/linux/dev_printk.h:144:65: note: expanded from macro 'dev_err' dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__) ~~~ ^~~~~~~~~~~ include/linux/dev_printk.h:110:23: note: expanded from macro 'dev_printk_index_wrap' _p_func(dev, fmt, ##__VA_ARGS__); \ ~~~ ^~~~~~~~~~~ drivers/crypto/ccp/sev-dev.c:244:2: error: member reference type 'struct mutex' is not a pointer; did you mean to use '.'? lockdep_assert_held(sev_cmd_mutex); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:316:17: note: expanded from macro 'lockdep_assert_held' lockdep_assert(lockdep_is_held(l) != LOCK_STATE_NOT_HELD) ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:286:52: note: expanded from macro 'lockdep_is_held' #define lockdep_is_held(lock) lock_is_held(&(lock)->dep_map) ^ include/linux/lockdep.h:310:32: note: expanded from macro 'lockdep_assert' do { WARN_ON(debug_locks && !(cond)); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ include/asm-generic/bug.h:121:25: note: expanded from macro 'WARN_ON' int __ret_warn_on = !!(condition); \ ^~~~~~~~~ drivers/crypto/ccp/sev-dev.c:244:2: error: cannot take the address of an rvalue of type 'struct lockdep_map' lockdep_assert_held(sev_cmd_mutex); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:316:17: note: expanded from macro 'lockdep_assert_held' lockdep_assert(lockdep_is_held(l) != LOCK_STATE_NOT_HELD) ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/lockdep.h:286:45: note: expanded from macro 'lockdep_is_held' #define lockdep_is_held(lock) lock_is_held(&(lock)->dep_map) ^ include/linux/lockdep.h:310:32: note: expanded from macro 'lockdep_assert' do { WARN_ON(debug_locks && !(cond)); } while (0) ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ include/asm-generic/bug.h:121:25: note: expanded from macro 'WARN_ON' int __ret_warn_on = !!(condition); \ ^~~~~~~~~ drivers/crypto/ccp/sev-dev.c:1250:15: warning: unused variable 'tmr_page' [-Wunused-variable] struct page *tmr_page; ^ 2 warnings and 6 errors generated. vim +179 drivers/crypto/ccp/sev-dev.c 172 173 static int sev_read_init_ex_file(void) 174 { 175 struct sev_device *sev = psp_master->sev_data; 176 struct file *fp; 177 ssize_t nread; 178 > 179 lockdep_assert_held(sev_cmd_mutex); 180 181 if (!sev_init_ex_buffer) 182 return -EOPNOTSUPP; 183 184 fp = filp_open(init_ex_path, O_RDONLY, 0); 185 if (IS_ERR(fp)) { 186 int ret = PTR_ERR(fp); 187 188 dev_err(sev->dev, 189 "SEV: could not open %s for read, error %d\n", 190 init_ex_path, ret); 191 return ret; 192 } 193 194 nread = kernel_read(fp, sev_init_ex_buffer, NV_LENGTH, NULL); 195 if (nread != NV_LENGTH) { 196 dev_err(sev->dev, 197 "SEV: failed to read %u bytes to non volatile memory area, ret %ld\n", 198 NV_LENGTH, nread); 199 return -EIO; 200 } 201 202 dev_dbg(sev->dev, "SEV: read %ld bytes from NV file\n", nread); 203 filp_close(fp, NULL); 204 205 return 0; 206 } 207 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
On Sat, Dec 04, 2021 at 05:25:25AM +0800, kernel test robot wrote: > Hi Peter, > > I love your patch! Yet something to improve: > > [auto build test ERROR on herbert-cryptodev-2.6/master] > [also build test ERROR on herbert-crypto-2.6/master kvm/queue linus/master v5.16-rc3 next-20211203] > [If your patch is applied to the wrong git tree, kindly drop us a note. > And when submitting patch, we suggest to use '--base' as documented in > https://git-scm.com/docs/git-format-patch] So this still seems to be broken. Cheers,
diff --git a/Documentation/virt/kvm/amd-memory-encryption.rst b/Documentation/virt/kvm/amd-memory-encryption.rst index 5c081c8c7164..1c6847fff304 100644 --- a/Documentation/virt/kvm/amd-memory-encryption.rst +++ b/Documentation/virt/kvm/amd-memory-encryption.rst @@ -85,6 +85,12 @@ guests, such as launching, running, snapshotting, migrating and decommissioning. The KVM_SEV_INIT command is used by the hypervisor to initialize the SEV platform context. In a typical workflow, this command should be the first command issued. +The firmware can be initialized either by using its own non-volatile storage or +the OS can manage the NV storage for the firmware using the module parameter +``init_ex_path``. The file specified by ``init_ex_path`` must exist. To create +a new NV storage file allocate the file with 32KB bytes of 0xFF as required by +the SEV spec. + Returns: 0 on success, -negative on error 2. KVM_SEV_LAUNCH_START diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index ab3752799011..d0d5962fa6aa 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -22,6 +22,7 @@ #include <linux/firmware.h> #include <linux/gfp.h> #include <linux/cpufeature.h> +#include <linux/fs.h> #include <asm/smp.h> @@ -43,6 +44,10 @@ static int psp_probe_timeout = 5; module_param(psp_probe_timeout, int, 0644); MODULE_PARM_DESC(psp_probe_timeout, " default timeout value, in seconds, during PSP device probe"); +static char *init_ex_path; +module_param(init_ex_path, charp, 0444); +MODULE_PARM_DESC(init_ex_path, " Path for INIT_EX data; if set try INIT_EX"); + static bool psp_init_on_probe = true; module_param(psp_init_on_probe, bool, 0444); MODULE_PARM_DESC(psp_init_on_probe, " if true, the PSP will be initialized on module init. Else the PSP will be initialized on the first command requiring it"); @@ -62,6 +67,14 @@ static int psp_timeout; #define SEV_ES_TMR_SIZE (1024 * 1024) static void *sev_es_tmr; +/* 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 (32 * 1024) +static void *sev_init_ex_buffer; + static inline bool sev_version_greater_or_equal(u8 maj, u8 min) { struct sev_device *sev = psp_master->sev_data; @@ -111,6 +124,7 @@ static int sev_cmd_buffer_len(int cmd) { switch (cmd) { case SEV_CMD_INIT: return sizeof(struct sev_data_init); + case SEV_CMD_INIT_EX: return sizeof(struct sev_data_init_ex); case SEV_CMD_PLATFORM_STATUS: return sizeof(struct sev_user_data_status); case SEV_CMD_PEK_CSR: return sizeof(struct sev_data_pek_csr); case SEV_CMD_PEK_CERT_IMPORT: return sizeof(struct sev_data_pek_cert_import); @@ -156,6 +170,101 @@ static void *sev_fw_alloc(unsigned long len) return page_address(page); } +static int sev_read_init_ex_file(void) +{ + struct sev_device *sev = psp_master->sev_data; + struct file *fp; + ssize_t nread; + + lockdep_assert_held(sev_cmd_mutex); + + if (!sev_init_ex_buffer) + return -EOPNOTSUPP; + + fp = filp_open(init_ex_path, O_RDONLY, 0); + if (IS_ERR(fp)) { + int ret = PTR_ERR(fp); + + dev_err(sev->dev, + "SEV: could not open %s for read, error %d\n", + init_ex_path, ret); + return ret; + } + + nread = kernel_read(fp, sev_init_ex_buffer, NV_LENGTH, NULL); + if (nread != NV_LENGTH) { + dev_err(sev->dev, + "SEV: failed to read %u bytes to non volatile memory area, ret %ld\n", + NV_LENGTH, nread); + return -EIO; + } + + dev_dbg(sev->dev, "SEV: read %ld bytes from NV file\n", nread); + filp_close(fp, NULL); + + return 0; +} + +static void sev_write_init_ex_file(void) +{ + struct sev_device *sev = psp_master->sev_data; + struct file *fp; + loff_t offset = 0; + ssize_t nwrite; + + lockdep_assert_held(sev_cmd_mutex); + + if (!sev_init_ex_buffer) + return; + + fp = filp_open(init_ex_path, O_CREAT | O_WRONLY, 0600); + if (IS_ERR(fp)) { + dev_err(sev->dev, + "SEV: could not open file for write, error %d\n", + PTR_ERR(fp)); + return; + } + + nwrite = kernel_write(fp, sev_init_ex_buffer, NV_LENGTH, &offset); + vfs_fsync(fp, 0); + filp_close(fp, NULL); + + if (nwrite != NV_LENGTH) { + dev_err(sev->dev, + "SEV: failed to write %u bytes to non volatile memory area, ret %ld\n", + NV_LENGTH, nwrite); + return; + } + + dev_dbg(sev->dev, "SEV: write successful to NV file\n"); +} + +static void sev_write_init_ex_file_if_required(int cmd_id) +{ + lockdep_assert_held(sev_cmd_mutex); + + if (!sev_init_ex_buffer) + return; + + /* + * Only a few platform commands modify the SPI/NV area, but none of the + * non-platform commands do. Only INIT(_EX), PLATFORM_RESET, PEK_GEN, + * PEK_CERT_IMPORT, and PDH_GEN do. + */ + switch (cmd_id) { + case SEV_CMD_FACTORY_RESET: + case SEV_CMD_INIT_EX: + case SEV_CMD_PDH_GEN: + case SEV_CMD_PEK_CERT_IMPORT: + case SEV_CMD_PEK_GEN: + break; + default: + return; + }; + + sev_write_init_ex_file(); +} + static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret) { struct psp_device *psp = psp_master; @@ -225,6 +334,8 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret) dev_dbg(sev->dev, "sev command %#x failed (%#010x)\n", cmd, reg & PSP_CMDRESP_ERR_MASK); ret = -EIO; + } else { + sev_write_init_ex_file_if_required(cmd); } print_hex_dump_debug("(out): ", DUMP_PREFIX_OFFSET, 16, 2, data, @@ -251,37 +362,71 @@ static int sev_do_cmd(int cmd, void *data, int *psp_ret) return rc; } -static int __sev_platform_init_locked(int *error) +static int __sev_init_locked(int *error) { - struct psp_device *psp = psp_master; struct sev_data_init data; - struct sev_device *sev; - int psp_ret, rc = 0; - if (!psp || !psp->sev_data) - return -ENODEV; + memset(&data, 0, sizeof(data)); + if (sev_es_tmr) { + /* + * Do not include the encryption mask on the physical + * address of the TMR (firmware should clear it anyway). + */ + data.tmr_address = __pa(sev_es_tmr); - sev = psp->sev_data; + data.flags |= SEV_INIT_FLAGS_SEV_ES; + data.tmr_len = SEV_ES_TMR_SIZE; + } - if (sev->state == SEV_STATE_INIT) - return 0; + return __sev_do_cmd_locked(SEV_CMD_INIT, &data, error); +} + +static int __sev_init_ex_locked(int *error) +{ + struct sev_data_init_ex data; + int ret; memset(&data, 0, sizeof(data)); - if (sev_es_tmr) { - u64 tmr_pa; + data.length = sizeof(data); + data.nv_address = __psp_pa(sev_init_ex_buffer); + data.nv_len = NV_LENGTH; + + ret = sev_read_init_ex_file(); + if (ret) + return ret; + if (sev_es_tmr) { /* * Do not include the encryption mask on the physical * address of the TMR (firmware should clear it anyway). */ - tmr_pa = __pa(sev_es_tmr); + data.tmr_address = __pa(sev_es_tmr); data.flags |= SEV_INIT_FLAGS_SEV_ES; - data.tmr_address = tmr_pa; data.tmr_len = SEV_ES_TMR_SIZE; } - rc = __sev_do_cmd_locked(SEV_CMD_INIT, &data, &psp_ret); + return __sev_do_cmd_locked(SEV_CMD_INIT_EX, &data, error); +} + +static int __sev_platform_init_locked(int *error) +{ + struct psp_device *psp = psp_master; + struct sev_device *sev; + int rc, psp_ret; + int (*init_function)(int *error); + + if (!psp || !psp->sev_data) + return -ENODEV; + + sev = psp->sev_data; + + if (sev->state == SEV_STATE_INIT) + return 0; + + init_function = sev_init_ex_buffer ? __sev_init_ex_locked : + __sev_init_locked; + rc = init_function(&psp_ret); if (rc && psp_ret == SEV_RET_SECURE_DATA_INVALID) { /* * Initialization command returned an integrity check failure @@ -291,7 +436,7 @@ static int __sev_platform_init_locked(int *error) * with a reset state. */ dev_dbg(sev->dev, "SEV: retrying INIT command"); - rc = __sev_do_cmd_locked(SEV_CMD_INIT, &data, &psp_ret); + rc = init_function(&psp_ret); } if (error) *error = psp_ret; @@ -1066,6 +1211,12 @@ static void sev_firmware_shutdown(struct sev_device *sev) get_order(SEV_ES_TMR_SIZE)); sev_es_tmr = NULL; } + + if (sev_init_ex_buffer) { + free_pages((unsigned long)sev_init_ex_buffer, + get_order(NV_LENGTH)); + sev_init_ex_buffer = NULL; + } } void sev_dev_destroy(struct psp_device *psp) @@ -1111,6 +1262,18 @@ void sev_pci_init(void) sev_update_firmware(sev->dev) == 0) sev_get_api_version(); + /* If an init_ex_path is provided rely on INIT_EX for PSP initialization + * instead of INIT. + */ + if (init_ex_path) { + sev_init_ex_buffer = sev_fw_alloc(NV_LENGTH); + if (!sev_init_ex_buffer) { + dev_err(sev->dev, + "SEV: INIT_EX NV memory allocation failed\n"); + goto err; + } + } + /* Obtain the TMR memory area for SEV-ES use */ sev_es_tmr = sev_fw_alloc(SEV_ES_TMR_SIZE); if (!sev_es_tmr) diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h index d48a7192e881..1595088c428b 100644 --- a/include/linux/psp-sev.h +++ b/include/linux/psp-sev.h @@ -52,6 +52,7 @@ enum sev_cmd { SEV_CMD_DF_FLUSH = 0x00A, SEV_CMD_DOWNLOAD_FIRMWARE = 0x00B, SEV_CMD_GET_ID = 0x00C, + SEV_CMD_INIT_EX = 0x00D, /* Guest commands */ SEV_CMD_DECOMMISSION = 0x020, @@ -102,6 +103,26 @@ struct sev_data_init { u32 tmr_len; /* In */ } __packed; +/** + * struct sev_data_init_ex - INIT_EX command parameters + * + * @length: len of the command buffer read by the PSP + * @flags: processing flags + * @tmr_address: system physical address used for SEV-ES + * @tmr_len: len of tmr_address + * @nv_address: system physical address used for PSP NV storage + * @nv_len: len of nv_address + */ +struct sev_data_init_ex { + u32 length; /* In */ + u32 flags; /* In */ + u64 tmr_address; /* In */ + u32 tmr_len; /* In */ + u32 reserved; /* In */ + u64 nv_address; /* In/Out */ + u32 nv_len; /* In */ +} __packed; + #define SEV_INIT_FLAGS_SEV_ES 0x01 /**