tree: https://git.kernel.org/pub/scm/virt/kvm/kvm.git queue head: da0fb9f3d73e7ab266d72a9b216ce0f3833c1e83 commit: 24f41fb23a39bc2b6f190dcef35a5813a4bf183a [32/111] KVM: SVM: Add support for SEV DEBUG_DECRYPT command reproduce: # apt-get install sparse git checkout 24f41fb23a39bc2b6f190dcef35a5813a4bf183a make ARCH=x86_64 allmodconfig make C=1 CF=-D__CHECK_ENDIAN__ sparse warnings: (new ones prefixed by >>) arch/x86/kvm/svm.c:6073:22: sparse: incorrect type in argument 1 (different base types) @@ expected void const volatile @@ got unsigned long lonvoid const volatile @@ arch/x86/kvm/svm.c:6073:22: expected void const volatile arch/x86/kvm/svm.c:6073:22: got unsigned long long uaddr arch/x86/include/asm/paravirt.h:149:9: sparse: cast truncates bits from constant value (100000000 becomes 0) arch/x86/include/asm/paravirt.h:149:9: sparse: cast truncates bits from constant value (100000000 becomes 0) >> arch/x86/kvm/svm.c:6231:60: sparse: dereference of noderef expression vim +6231 arch/x86/kvm/svm.c 6044 6045 static int sev_launch_measure(struct kvm *kvm, struct kvm_sev_cmd *argp) 6046 { 6047 struct kvm_sev_info *sev = &kvm->arch.sev_info; 6048 struct sev_data_launch_measure *data; 6049 struct kvm_sev_launch_measure params; 6050 void *blob = NULL; 6051 int ret; 6052 6053 if (!sev_guest(kvm)) 6054 return -ENOTTY; 6055 6056 if (copy_from_user(¶ms, (void __user *)(uintptr_t)argp->data, sizeof(params))) 6057 return -EFAULT; 6058 6059 data = kzalloc(sizeof(*data), GFP_KERNEL); 6060 if (!data) 6061 return -ENOMEM; 6062 6063 /* User wants to query the blob length */ 6064 if (!params.len) 6065 goto cmd; 6066 6067 if (params.uaddr) { 6068 if (params.len > SEV_FW_BLOB_MAX_SIZE) { 6069 ret = -EINVAL; 6070 goto e_free; 6071 } 6072 > 6073 if (!access_ok(VERIFY_WRITE, params.uaddr, params.len)) { 6074 ret = -EFAULT; 6075 goto e_free; 6076 } 6077 6078 ret = -ENOMEM; 6079 blob = kmalloc(params.len, GFP_KERNEL); 6080 if (!blob) 6081 goto e_free; 6082 6083 data->address = __psp_pa(blob); 6084 data->len = params.len; 6085 } 6086 6087 cmd: 6088 data->handle = sev->handle; 6089 ret = sev_issue_cmd(kvm, SEV_CMD_LAUNCH_MEASURE, data, &argp->error); 6090 6091 /* 6092 * If we query the session length, FW responded with expected data. 6093 */ 6094 if (!params.len) 6095 goto done; 6096 6097 if (ret) 6098 goto e_free_blob; 6099 6100 if (blob) { 6101 if (copy_to_user((void __user *)(uintptr_t)params.uaddr, blob, params.len)) 6102 ret = -EFAULT; 6103 } 6104 6105 done: 6106 params.len = data->len; 6107 if (copy_to_user((void __user *)(uintptr_t)argp->data, ¶ms, sizeof(params))) 6108 ret = -EFAULT; 6109 e_free_blob: 6110 kfree(blob); 6111 e_free: 6112 kfree(data); 6113 return ret; 6114 } 6115 6116 static int sev_launch_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) 6117 { 6118 struct kvm_sev_info *sev = &kvm->arch.sev_info; 6119 struct sev_data_launch_finish *data; 6120 int ret; 6121 6122 if (!sev_guest(kvm)) 6123 return -ENOTTY; 6124 6125 data = kzalloc(sizeof(*data), GFP_KERNEL); 6126 if (!data) 6127 return -ENOMEM; 6128 6129 data->handle = sev->handle; 6130 ret = sev_issue_cmd(kvm, SEV_CMD_LAUNCH_FINISH, data, &argp->error); 6131 6132 kfree(data); 6133 return ret; 6134 } 6135 6136 static int sev_guest_status(struct kvm *kvm, struct kvm_sev_cmd *argp) 6137 { 6138 struct kvm_sev_info *sev = &kvm->arch.sev_info; 6139 struct kvm_sev_guest_status params; 6140 struct sev_data_guest_status *data; 6141 int ret; 6142 6143 if (!sev_guest(kvm)) 6144 return -ENOTTY; 6145 6146 data = kzalloc(sizeof(*data), GFP_KERNEL); 6147 if (!data) 6148 return -ENOMEM; 6149 6150 data->handle = sev->handle; 6151 ret = sev_issue_cmd(kvm, SEV_CMD_GUEST_STATUS, data, &argp->error); 6152 if (ret) 6153 goto e_free; 6154 6155 params.policy = data->policy; 6156 params.state = data->state; 6157 params.handle = data->handle; 6158 6159 if (copy_to_user((void __user *)(uintptr_t)argp->data, ¶ms, sizeof(params))) 6160 ret = -EFAULT; 6161 e_free: 6162 kfree(data); 6163 return ret; 6164 } 6165 6166 static int __sev_issue_dbg_cmd(struct kvm *kvm, unsigned long src, 6167 unsigned long dst, int size, 6168 int *error, bool enc) 6169 { 6170 struct kvm_sev_info *sev = &kvm->arch.sev_info; 6171 struct sev_data_dbg *data; 6172 int ret; 6173 6174 data = kzalloc(sizeof(*data), GFP_KERNEL); 6175 if (!data) 6176 return -ENOMEM; 6177 6178 data->handle = sev->handle; 6179 data->dst_addr = dst; 6180 data->src_addr = src; 6181 data->len = size; 6182 6183 ret = sev_issue_cmd(kvm, 6184 enc ? SEV_CMD_DBG_ENCRYPT : SEV_CMD_DBG_DECRYPT, 6185 data, error); 6186 kfree(data); 6187 return ret; 6188 } 6189 6190 static int __sev_dbg_decrypt(struct kvm *kvm, unsigned long src_paddr, 6191 unsigned long dst_paddr, int sz, int *err) 6192 { 6193 int offset; 6194 6195 /* 6196 * Its safe to read more than we are asked, caller should ensure that 6197 * destination has enough space. 6198 */ 6199 src_paddr = round_down(src_paddr, 16); 6200 offset = src_paddr & 15; 6201 sz = round_up(sz + offset, 16); 6202 6203 return __sev_issue_dbg_cmd(kvm, src_paddr, dst_paddr, sz, err, false); 6204 } 6205 6206 static int __sev_dbg_decrypt_user(struct kvm *kvm, unsigned long paddr, 6207 unsigned long __user dst_uaddr, 6208 unsigned long dst_paddr, 6209 int size, int *err) 6210 { 6211 struct page *tpage = NULL; 6212 int ret, offset; 6213 6214 /* if inputs are not 16-byte then use intermediate buffer */ 6215 if (!IS_ALIGNED(dst_paddr, 16) || 6216 !IS_ALIGNED(paddr, 16) || 6217 !IS_ALIGNED(size, 16)) { 6218 tpage = (void *)alloc_page(GFP_KERNEL); 6219 if (!tpage) 6220 return -ENOMEM; 6221 6222 dst_paddr = __sme_page_pa(tpage); 6223 } 6224 6225 ret = __sev_dbg_decrypt(kvm, paddr, dst_paddr, size, err); 6226 if (ret) 6227 goto e_free; 6228 6229 if (tpage) { 6230 offset = paddr & 15; > 6231 if (copy_to_user((void __user *)(uintptr_t)dst_uaddr, 6232 page_address(tpage) + offset, size)) 6233 ret = -EFAULT; 6234 } 6235 6236 e_free: 6237 if (tpage) 6238 __free_page(tpage); 6239 6240 return ret; 6241 } 6242 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation